From 71998b851381a87da4f6ec2cf5a7651d00d08af4 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Mon, 26 Feb 2024 18:46:19 +0000 Subject: [PATCH 001/139] call opcode and serialization --- .../dsl/acir_format/serde/acir.hpp | 142 +++++++++--------- noir/acvm-repo/acir/codegen/acir.cpp | 56 ++++++- noir/acvm-repo/acir/src/circuit/opcodes.rs | 15 ++ noir/acvm-repo/acir/src/lib.rs | 8 +- .../acvm/src/compiler/transformers/mod.rs | 1 + noir/acvm-repo/acvm/src/pwg/mod.rs | 1 + 6 files changed, 143 insertions(+), 80 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 2c6bea75698d..0170896c722f 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/acir.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/acir.hpp @@ -1045,18 +1045,7 @@ struct Directive { static ToLeRadix bincodeDeserialize(std::vector); }; - struct PermutationSort { - std::vector> inputs; - uint32_t tuple; - std::vector bits; - std::vector sort_by; - - friend bool operator==(const PermutationSort&, const PermutationSort&); - std::vector bincodeSerialize() const; - static PermutationSort bincodeDeserialize(std::vector); - }; - - std::variant value; + std::variant value; friend bool operator==(const Directive&, const Directive&); std::vector bincodeSerialize() const; @@ -1126,7 +1115,17 @@ struct Opcode { static MemoryInit bincodeDeserialize(std::vector); }; - std::variant value; + struct Call { + uint32_t id; + std::vector inputs; + std::vector outputs; + + friend bool operator==(const Call&, const Call&); + std::vector bincodeSerialize() const; + static Call bincodeDeserialize(std::vector); + }; + + std::variant value; friend bool operator==(const Opcode&, const Opcode&); std::vector bincodeSerialize() const; @@ -6309,68 +6308,6 @@ Circuit::Directive::ToLeRadix serde::Deserializable Directive::PermutationSort::bincodeSerialize() const -{ - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} - -inline Directive::PermutationSort Directive::PermutationSort::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::Directive::PermutationSort& obj, - Serializer& serializer) -{ - serde::Serializable::serialize(obj.inputs, serializer); - serde::Serializable::serialize(obj.tuple, serializer); - serde::Serializable::serialize(obj.bits, serializer); - serde::Serializable::serialize(obj.sort_by, serializer); -} - -template <> -template -Circuit::Directive::PermutationSort serde::Deserializable::deserialize( - Deserializer& deserializer) -{ - Circuit::Directive::PermutationSort obj; - obj.inputs = serde::Deserializable::deserialize(deserializer); - obj.tuple = serde::Deserializable::deserialize(deserializer); - obj.bits = serde::Deserializable::deserialize(deserializer); - obj.sort_by = serde::Deserializable::deserialize(deserializer); - return obj; -} - -namespace Circuit { - inline bool operator==(const Expression& lhs, const Expression& rhs) { if (!(lhs.mul_terms == rhs.mul_terms)) { @@ -7368,6 +7305,61 @@ Circuit::Opcode::MemoryInit serde::Deserializable:: namespace Circuit { +inline bool operator==(const Opcode::Call& lhs, const Opcode::Call& rhs) +{ + if (!(lhs.id == rhs.id)) { + return false; + } + if (!(lhs.inputs == rhs.inputs)) { + return false; + } + if (!(lhs.outputs == rhs.outputs)) { + return false; + } + return true; +} + +inline std::vector Opcode::Call::bincodeSerialize() const +{ + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); +} + +inline Opcode::Call Opcode::Call::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::Opcode::Call& obj, Serializer& serializer) +{ + serde::Serializable::serialize(obj.id, serializer); + serde::Serializable::serialize(obj.inputs, serializer); + serde::Serializable::serialize(obj.outputs, serializer); +} + +template <> +template +Circuit::Opcode::Call serde::Deserializable::deserialize(Deserializer& deserializer) +{ + Circuit::Opcode::Call obj; + obj.id = serde::Deserializable::deserialize(deserializer); + obj.inputs = serde::Deserializable::deserialize(deserializer); + obj.outputs = serde::Deserializable::deserialize(deserializer); + return obj; +} + +namespace Circuit { + inline bool operator==(const OpcodeLocation& lhs, const OpcodeLocation& rhs) { if (!(lhs.value == rhs.value)) { diff --git a/noir/acvm-repo/acir/codegen/acir.cpp b/noir/acvm-repo/acir/codegen/acir.cpp index 0fc84d47a0fc..46809727000a 100644 --- a/noir/acvm-repo/acir/codegen/acir.cpp +++ b/noir/acvm-repo/acir/codegen/acir.cpp @@ -1053,7 +1053,17 @@ namespace Circuit { static MemoryInit bincodeDeserialize(std::vector); }; - std::variant value; + struct Call { + uint32_t id; + std::vector inputs; + std::vector outputs; + + friend bool operator==(const Call&, const Call&); + std::vector bincodeSerialize() const; + static Call bincodeDeserialize(std::vector); + }; + + std::variant value; friend bool operator==(const Opcode&, const Opcode&); std::vector bincodeSerialize() const; @@ -6012,6 +6022,50 @@ Circuit::Opcode::MemoryInit serde::Deserializable:: return obj; } +namespace Circuit { + + inline bool operator==(const Opcode::Call &lhs, const Opcode::Call &rhs) { + if (!(lhs.id == rhs.id)) { return false; } + if (!(lhs.inputs == rhs.inputs)) { return false; } + if (!(lhs.outputs == rhs.outputs)) { return false; } + return true; + } + + inline std::vector Opcode::Call::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } + + inline Opcode::Call Opcode::Call::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::Opcode::Call &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.id, serializer); + serde::Serializable::serialize(obj.inputs, serializer); + serde::Serializable::serialize(obj.outputs, serializer); +} + +template <> +template +Circuit::Opcode::Call serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::Opcode::Call obj; + obj.id = serde::Deserializable::deserialize(deserializer); + obj.inputs = serde::Deserializable::deserialize(deserializer); + obj.outputs = serde::Deserializable::deserialize(deserializer); + return obj; +} + namespace Circuit { inline bool operator==(const OpcodeLocation &lhs, const OpcodeLocation &rhs) { diff --git a/noir/acvm-repo/acir/src/circuit/opcodes.rs b/noir/acvm-repo/acir/src/circuit/opcodes.rs index f725ba8c32a0..6d153edd22bc 100644 --- a/noir/acvm-repo/acir/src/circuit/opcodes.rs +++ b/noir/acvm-repo/acir/src/circuit/opcodes.rs @@ -29,6 +29,16 @@ pub enum Opcode { block_id: BlockId, init: Vec, }, + /// Calls to functions represented as a separate circuit. A call opcode allows us + /// to build a call stack when executing the outer-most circuit. + Call { + /// Id for the function being called to be used by the caller of execution + id: u32, + /// Inputs to the function + inputs: Vec, + /// Outputs of the function call + outputs: Vec, + } } impl std::fmt::Display for Opcode { @@ -86,6 +96,11 @@ impl std::fmt::Display for Opcode { write!(f, "INIT ")?; write!(f, "(id: {}, len: {}) ", block_id.0, init.len()) } + Opcode::Call { id, inputs, outputs } => { + write!(f, "CALL func {}: ", id)?; + writeln!(f, "inputs: {:?}", inputs)?; + writeln!(f, "outputs: {:?}", outputs) + } } } } diff --git a/noir/acvm-repo/acir/src/lib.rs b/noir/acvm-repo/acir/src/lib.rs index c7be50268502..a1707b94c921 100644 --- a/noir/acvm-repo/acir/src/lib.rs +++ b/noir/acvm-repo/acir/src/lib.rs @@ -84,10 +84,10 @@ mod reflection { generator.output(&mut source, ®istry).unwrap(); // Comment this out to write updated C++ code to file. - if let Some(old_hash) = old_hash { - let new_hash = fxhash::hash64(&source); - assert_eq!(new_hash, old_hash, "Serialization format has changed"); - } + // if let Some(old_hash) = old_hash { + // let new_hash = fxhash::hash64(&source); + // assert_eq!(new_hash, old_hash, "Serialization format has changed"); + // } write_to_file(&source, &path); } diff --git a/noir/acvm-repo/acvm/src/compiler/transformers/mod.rs b/noir/acvm-repo/acvm/src/compiler/transformers/mod.rs index 214243d9360d..2b6c0cc6f8cf 100644 --- a/noir/acvm-repo/acvm/src/compiler/transformers/mod.rs +++ b/noir/acvm-repo/acvm/src/compiler/transformers/mod.rs @@ -145,6 +145,7 @@ pub(super) fn transform_internal( new_acir_opcode_positions.push(acir_opcode_positions[index]); transformed_opcodes.push(opcode); } + Opcode::Call{ .. } => todo!("Handle Call opcodes in the ACVM"), } } diff --git a/noir/acvm-repo/acvm/src/pwg/mod.rs b/noir/acvm-repo/acvm/src/pwg/mod.rs index 2ee39a289e7c..888346251cb2 100644 --- a/noir/acvm-repo/acvm/src/pwg/mod.rs +++ b/noir/acvm-repo/acvm/src/pwg/mod.rs @@ -281,6 +281,7 @@ impl<'a, B: BlackBoxFunctionSolver> ACVM<'a, B> { Ok(Some(foreign_call)) => return self.wait_for_foreign_call(foreign_call), res => res.map(|_| ()), }, + Opcode::Call { .. } => todo!("Handle Call opcodes in the ACVM"), }; self.handle_opcode_resolution(resolution) } From d081ecc6fdfad1f23bc425a25a7b3d6022ae87a9 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Mon, 26 Feb 2024 18:48:54 +0000 Subject: [PATCH 002/139] uncomment serde in test: --- noir/acvm-repo/acir/src/lib.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/noir/acvm-repo/acir/src/lib.rs b/noir/acvm-repo/acir/src/lib.rs index a1707b94c921..c7be50268502 100644 --- a/noir/acvm-repo/acir/src/lib.rs +++ b/noir/acvm-repo/acir/src/lib.rs @@ -84,10 +84,10 @@ mod reflection { generator.output(&mut source, ®istry).unwrap(); // Comment this out to write updated C++ code to file. - // if let Some(old_hash) = old_hash { - // let new_hash = fxhash::hash64(&source); - // assert_eq!(new_hash, old_hash, "Serialization format has changed"); - // } + if let Some(old_hash) = old_hash { + let new_hash = fxhash::hash64(&source); + assert_eq!(new_hash, old_hash, "Serialization format has changed"); + } write_to_file(&source, &path); } From dcb6d9e4f2d4050269fab10850daf4d022486068 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Mon, 4 Mar 2024 17:28:42 +0000 Subject: [PATCH 003/139] pass noir fmt and clippy --- .vscode/settings.json | 3 +++ noir/noir-repo/acvm-repo/acir/src/circuit/opcodes.rs | 2 +- noir/noir-repo/acvm-repo/acvm/src/compiler/transformers/mod.rs | 2 +- noir/noir-repo/aztec_macros/src/lib.rs | 2 +- 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index b7aa953af512..b8c6aa5bb55a 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -155,5 +155,8 @@ "C_Cpp.vcpkg.enabled": false, "C_Cpp.default.includePath": [ "barretenberg/cpp/src" + ], + "rust-analyzer.linkedProjects": [ + "noir/noir-repo/Cargo.toml" ] } diff --git a/noir/noir-repo/acvm-repo/acir/src/circuit/opcodes.rs b/noir/noir-repo/acvm-repo/acir/src/circuit/opcodes.rs index 6d153edd22bc..e73549997cee 100644 --- a/noir/noir-repo/acvm-repo/acir/src/circuit/opcodes.rs +++ b/noir/noir-repo/acvm-repo/acir/src/circuit/opcodes.rs @@ -38,7 +38,7 @@ pub enum Opcode { inputs: Vec, /// Outputs of the function call outputs: Vec, - } + }, } impl std::fmt::Display for Opcode { diff --git a/noir/noir-repo/acvm-repo/acvm/src/compiler/transformers/mod.rs b/noir/noir-repo/acvm-repo/acvm/src/compiler/transformers/mod.rs index 2b6c0cc6f8cf..2e549854521a 100644 --- a/noir/noir-repo/acvm-repo/acvm/src/compiler/transformers/mod.rs +++ b/noir/noir-repo/acvm-repo/acvm/src/compiler/transformers/mod.rs @@ -145,7 +145,7 @@ pub(super) fn transform_internal( new_acir_opcode_positions.push(acir_opcode_positions[index]); transformed_opcodes.push(opcode); } - Opcode::Call{ .. } => todo!("Handle Call opcodes in the ACVM"), + Opcode::Call { .. } => todo!("Handle Call opcodes in the ACVM"), } } diff --git a/noir/noir-repo/aztec_macros/src/lib.rs b/noir/noir-repo/aztec_macros/src/lib.rs index 6191108de862..e24996ded439 100644 --- a/noir/noir-repo/aztec_macros/src/lib.rs +++ b/noir/noir-repo/aztec_macros/src/lib.rs @@ -440,7 +440,7 @@ fn transform_module( .attributes .secondary .iter() - .any(|attr| is_custom_attribute(&attr, "aztec(initializer)")) + .any(|attr| is_custom_attribute(attr, "aztec(initializer)")) }); for func in module.functions.iter_mut() { From 2376e16f606eb7fc062a52d4e872742fb223e017 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Mon, 4 Mar 2024 17:54:54 +0000 Subject: [PATCH 004/139] fixup call comments --- noir/noir-repo/acvm-repo/acir/src/circuit/opcodes.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/noir/noir-repo/acvm-repo/acir/src/circuit/opcodes.rs b/noir/noir-repo/acvm-repo/acir/src/circuit/opcodes.rs index e73549997cee..01c7cae65660 100644 --- a/noir/noir-repo/acvm-repo/acir/src/circuit/opcodes.rs +++ b/noir/noir-repo/acvm-repo/acir/src/circuit/opcodes.rs @@ -32,11 +32,12 @@ pub enum Opcode { /// Calls to functions represented as a separate circuit. A call opcode allows us /// to build a call stack when executing the outer-most circuit. Call { - /// Id for the function being called to be used by the caller of execution + /// Id for the function being called. It is the responsibility of the executor + /// to fetch the appropriate circuit from this id. id: u32, - /// Inputs to the function + /// Inputs to the function call inputs: Vec, - /// Outputs of the function call + /// Outputs of the function call outputs: Vec, }, } From 0792a088f3008f3f024a15b3ad1f1fc1c4d4dc78 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Mon, 4 Mar 2024 19:39:40 +0000 Subject: [PATCH 005/139] cargo fmt --- noir/noir-repo/acvm-repo/acir/src/circuit/opcodes.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/noir/noir-repo/acvm-repo/acir/src/circuit/opcodes.rs b/noir/noir-repo/acvm-repo/acir/src/circuit/opcodes.rs index 01c7cae65660..064a9d1244ae 100644 --- a/noir/noir-repo/acvm-repo/acir/src/circuit/opcodes.rs +++ b/noir/noir-repo/acvm-repo/acir/src/circuit/opcodes.rs @@ -32,12 +32,12 @@ pub enum Opcode { /// Calls to functions represented as a separate circuit. A call opcode allows us /// to build a call stack when executing the outer-most circuit. Call { - /// Id for the function being called. It is the responsibility of the executor - /// to fetch the appropriate circuit from this id. + /// Id for the function being called. It is the responsibility of the executor + /// to fetch the appropriate circuit from this id. id: u32, /// Inputs to the function call inputs: Vec, - /// Outputs of the function call + /// Outputs of the function call outputs: Vec, }, } From 96a719cfb6ac259d354cf455ab88c37f0cd08eb6 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Wed, 6 Mar 2024 18:36:13 +0000 Subject: [PATCH 006/139] program and witness stack structure and respective serialization --- .../acir_format/acir_to_constraint_buf.hpp | 82 +- .../dsl/acir_format/serde/acir.hpp | 1797 +++++++++-------- .../dsl/acir_format/serde/index.hpp | 2 +- .../dsl/acir_format/serde/witness_map.hpp | 123 -- .../dsl/acir_format/serde/witness_stack.hpp | 247 +++ .../noir-repo/acvm-repo/acir/codegen/acir.cpp | 1712 ++++++++-------- .../acvm-repo/acir/codegen/witness.cpp | 130 +- .../acvm-repo/acir/src/circuit/mod.rs | 77 + noir/noir-repo/acvm-repo/acir/src/lib.rs | 10 +- .../acvm-repo/acir/src/native_types/mod.rs | 4 +- .../acir/src/native_types/witness_stack.rs | 66 + .../compiler/noirc_driver/src/contract.rs | 8 +- .../compiler/noirc_driver/src/lib.rs | 9 +- .../compiler/noirc_driver/src/program.rs | 8 +- .../backend_interface/src/proof_system.rs | 27 +- noir/noir-repo/tooling/debugger/src/dap.rs | 2 +- .../tooling/nargo/src/artifacts/contract.rs | 8 +- .../tooling/nargo/src/artifacts/program.rs | 24 +- .../tooling/nargo/src/ops/optimize.rs | 18 +- noir/noir-repo/tooling/nargo/src/ops/test.rs | 11 +- .../tooling/nargo/src/ops/transform.rs | 18 +- .../nargo_cli/src/cli/codegen_verifier_cmd.rs | 9 +- .../tooling/nargo_cli/src/cli/compile_cmd.rs | 4 +- .../tooling/nargo_cli/src/cli/debug_cmd.rs | 2 +- .../tooling/nargo_cli/src/cli/execute_cmd.rs | 2 +- .../tooling/nargo_cli/src/cli/fs/program.rs | 6 +- .../tooling/nargo_cli/src/cli/fs/witness.rs | 6 +- .../tooling/nargo_cli/src/cli/info_cmd.rs | 7 +- .../tooling/nargo_cli/src/cli/prove_cmd.rs | 4 +- .../tooling/nargo_cli/src/cli/verify_cmd.rs | 2 +- .../noir-repo/tooling/nargo_cli/src/errors.rs | 6 +- 31 files changed, 2470 insertions(+), 1961 deletions(-) delete mode 100644 barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/witness_map.hpp create mode 100644 barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/witness_stack.hpp create mode 100644 noir/noir-repo/acvm-repo/acir/src/native_types/witness_stack.rs 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 f7a5cbcf44d1..bed65a90c035 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 @@ -26,10 +26,10 @@ namespace acir_format { * * @param arg acir representation of an 3-wire arithmetic operation * @return poly_triple - * @note In principle Circuit::Expression can accommodate arbitrarily many quadratic and linear terms but in practice + * @note In principle Program::Expression can accommodate arbitrarily many quadratic and linear terms but in practice * the ones processed here have a max of 1 and 3 respectively, in accordance with the standard width-3 arithmetic gate. */ -poly_triple serialize_arithmetic_gate(Circuit::Expression const& arg) +poly_triple serialize_arithmetic_gate(Program::Expression const& arg) { // TODO(https://github.com/AztecProtocol/barretenberg/issues/816): The initialization of the witness indices a,b,c // to 0 is implicitly assuming that (builder.zero_idx == 0) which is no longer the case. Now, witness idx 0 in @@ -98,17 +98,17 @@ poly_triple serialize_arithmetic_gate(Circuit::Expression const& arg) return pt; } -void handle_arithmetic(Circuit::Opcode::AssertZero const& arg, AcirFormat& af) +void handle_arithmetic(Program::Opcode::AssertZero const& arg, AcirFormat& af) { af.constraints.push_back(serialize_arithmetic_gate(arg.value)); } -void handle_blackbox_func_call(Circuit::Opcode::BlackBoxFuncCall const& arg, AcirFormat& af) +void handle_blackbox_func_call(Program::Opcode::BlackBoxFuncCall const& arg, AcirFormat& af) { std::visit( [&](auto&& arg) { using T = std::decay_t; - if constexpr (std::is_same_v) { + if constexpr (std::is_same_v) { af.logic_constraints.push_back(LogicConstraint{ .a = arg.lhs.witness.value, .b = arg.rhs.witness.value, @@ -116,7 +116,7 @@ void handle_blackbox_func_call(Circuit::Opcode::BlackBoxFuncCall const& arg, Aci .num_bits = arg.lhs.num_bits, .is_xor_gate = false, }); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { af.logic_constraints.push_back(LogicConstraint{ .a = arg.lhs.witness.value, .b = arg.rhs.witness.value, @@ -124,12 +124,12 @@ void handle_blackbox_func_call(Circuit::Opcode::BlackBoxFuncCall const& arg, Aci .num_bits = arg.lhs.num_bits, .is_xor_gate = true, }); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { af.range_constraints.push_back(RangeConstraint{ .witness = arg.input.witness.value, .num_bits = arg.input.num_bits, }); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { af.sha256_constraints.push_back(Sha256Constraint{ .inputs = map(arg.inputs, [](auto& e) { @@ -140,7 +140,7 @@ void handle_blackbox_func_call(Circuit::Opcode::BlackBoxFuncCall const& arg, Aci }), .result = map(arg.outputs, [](auto& e) { return e.value; }), }); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { af.sha256_compression.push_back(Sha256Compression{ .inputs = map(arg.inputs, [](auto& e) { @@ -158,7 +158,7 @@ void handle_blackbox_func_call(Circuit::Opcode::BlackBoxFuncCall const& arg, Aci }), .result = map(arg.outputs, [](auto& e) { return e.value; }), }); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { af.blake2s_constraints.push_back(Blake2sConstraint{ .inputs = map(arg.inputs, [](auto& e) { @@ -169,7 +169,7 @@ void handle_blackbox_func_call(Circuit::Opcode::BlackBoxFuncCall const& arg, Aci }), .result = map(arg.outputs, [](auto& e) { return e.value; }), }); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { af.blake3_constraints.push_back(Blake3Constraint{ .inputs = map(arg.inputs, [](auto& e) { @@ -180,7 +180,7 @@ void handle_blackbox_func_call(Circuit::Opcode::BlackBoxFuncCall const& arg, Aci }), .result = map(arg.outputs, [](auto& e) { return e.value; }), }); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { af.schnorr_constraints.push_back(SchnorrConstraint{ .message = map(arg.message, [](auto& e) { return e.witness.value; }), .public_key_x = arg.public_key_x.witness.value, @@ -188,20 +188,20 @@ void handle_blackbox_func_call(Circuit::Opcode::BlackBoxFuncCall const& arg, Aci .result = arg.output.value, .signature = map(arg.signature, [](auto& e) { return e.witness.value; }), }); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { af.pedersen_constraints.push_back(PedersenConstraint{ .scalars = map(arg.inputs, [](auto& e) { return e.witness.value; }), .hash_index = arg.domain_separator, .result_x = arg.outputs[0].value, .result_y = arg.outputs[1].value, }); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { af.pedersen_hash_constraints.push_back(PedersenHashConstraint{ .scalars = map(arg.inputs, [](auto& e) { return e.witness.value; }), .hash_index = arg.domain_separator, .result = arg.output.value, }); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { af.ecdsa_k1_constraints.push_back(EcdsaSecp256k1Constraint{ .hashed_message = map(arg.hashed_message, [](auto& e) { return e.witness.value; }), .signature = map(arg.signature, [](auto& e) { return e.witness.value; }), @@ -209,7 +209,7 @@ void handle_blackbox_func_call(Circuit::Opcode::BlackBoxFuncCall const& arg, Aci .pub_y_indices = map(arg.public_key_y, [](auto& e) { return e.witness.value; }), .result = arg.output.value, }); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { af.ecdsa_r1_constraints.push_back(EcdsaSecp256r1Constraint{ .hashed_message = map(arg.hashed_message, [](auto& e) { return e.witness.value; }), .pub_x_indices = map(arg.public_key_x, [](auto& e) { return e.witness.value; }), @@ -217,14 +217,14 @@ void handle_blackbox_func_call(Circuit::Opcode::BlackBoxFuncCall const& arg, Aci .result = arg.output.value, .signature = map(arg.signature, [](auto& e) { return e.witness.value; }), }); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { af.fixed_base_scalar_mul_constraints.push_back(FixedBaseScalarMul{ .low = arg.low.witness.value, .high = arg.high.witness.value, .pub_key_x = arg.outputs[0].value, .pub_key_y = arg.outputs[1].value, }); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { af.ec_add_constraints.push_back(EcAdd{ .input1_x = arg.input1_x.witness.value, .input1_y = arg.input1_y.witness.value, @@ -233,7 +233,7 @@ void handle_blackbox_func_call(Circuit::Opcode::BlackBoxFuncCall const& arg, Aci .result_x = arg.outputs[0].value, .result_y = arg.outputs[1].value, }); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { af.keccak_constraints.push_back(KeccakConstraint{ .inputs = map(arg.inputs, [](auto& e) { @@ -244,7 +244,7 @@ void handle_blackbox_func_call(Circuit::Opcode::BlackBoxFuncCall const& arg, Aci }), .result = map(arg.outputs, [](auto& e) { return e.value; }), }); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { af.keccak_var_constraints.push_back(KeccakVarConstraint{ .inputs = map(arg.inputs, [](auto& e) { @@ -256,12 +256,12 @@ void handle_blackbox_func_call(Circuit::Opcode::BlackBoxFuncCall const& arg, Aci .result = map(arg.outputs, [](auto& e) { return e.value; }), .var_message_size = arg.var_message_size.witness.value, }); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { af.keccak_permutations.push_back(Keccakf1600{ .state = map(arg.inputs, [](auto& e) { return e.witness.value; }), .result = map(arg.outputs, [](auto& e) { return e.value; }), }); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { auto c = RecursionConstraint{ .key = map(arg.verification_key, [](auto& e) { return e.witness.value; }), .proof = map(arg.proof, [](auto& e) { return e.witness.value; }), @@ -269,46 +269,46 @@ 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) { + } 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) { + } else if constexpr (std::is_same_v) { af.bigint_to_le_bytes_constraints.push_back(BigIntToLeBytes{ .input = arg.input, .result = map(arg.outputs, [](auto& e) { return e.value; }), }); - } else if constexpr (std::is_same_v) { + } 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) { + } else if constexpr (std::is_same_v) { af.bigint_operations.push_back(BigIntOperation{ .lhs = arg.lhs, .rhs = arg.rhs, .result = arg.output, .opcode = BigIntOperationType::Sub, }); - } else if constexpr (std::is_same_v) { + } 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) { + } 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, }); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { af.poseidon2_constraints.push_back(Poseidon2Constraint{ .state = map(arg.inputs, [](auto& e) { return e.witness.value; }), .result = map(arg.outputs, [](auto& e) { return e.value; }), @@ -319,7 +319,7 @@ void handle_blackbox_func_call(Circuit::Opcode::BlackBoxFuncCall const& arg, Aci arg.value.value); } -BlockConstraint handle_memory_init(Circuit::Opcode::MemoryInit const& mem_init) +BlockConstraint handle_memory_init(Program::Opcode::MemoryInit const& mem_init) { BlockConstraint block{ .init = {}, .trace = {}, .type = BlockType::ROM }; std::vector init; @@ -341,13 +341,13 @@ BlockConstraint handle_memory_init(Circuit::Opcode::MemoryInit const& mem_init) return block; } -bool is_rom(Circuit::MemOp const& mem_op) +bool is_rom(Program::MemOp const& mem_op) { return mem_op.operation.mul_terms.size() == 0 && mem_op.operation.linear_combinations.size() == 0 && uint256_t(mem_op.operation.q_c) == 0; } -void handle_memory_op(Circuit::Opcode::MemoryOp const& mem_op, BlockConstraint& block) +void handle_memory_op(Program::Opcode::MemoryOp const& mem_op, BlockConstraint& block) { uint8_t access_type = 1; if (is_rom(mem_op.op)) { @@ -365,7 +365,9 @@ void handle_memory_op(Circuit::Opcode::MemoryOp const& mem_op, BlockConstraint& AcirFormat circuit_buf_to_acir_format(std::vector const& buf) { - auto circuit = Circuit::Circuit::bincodeDeserialize(buf); + // TODO(maxim): Handle the new `Program` structure once ACVM supports a function call stack. + // For now we still expect a single ACIR function.s + auto circuit = Program::Program::bincodeDeserialize(buf).functions[0]; AcirFormat af; // `varnum` is the true number of variables, thus we add one to the index which starts at zero @@ -378,15 +380,15 @@ AcirFormat circuit_buf_to_acir_format(std::vector const& buf) std::visit( [&](auto&& arg) { using T = std::decay_t; - if constexpr (std::is_same_v) { + if constexpr (std::is_same_v) { handle_arithmetic(arg, af); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { handle_blackbox_func_call(arg, af); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { auto block = handle_memory_init(arg); uint32_t block_id = arg.block_id.value; block_id_to_block_constraint[block_id] = block; - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { auto block = block_id_to_block_constraint.find(arg.block_id.value); if (block == block_id_to_block_constraint.end()) { throw_or_abort("unitialized MemoryOp"); @@ -414,7 +416,11 @@ AcirFormat circuit_buf_to_acir_format(std::vector const& buf) */ WitnessVector witness_buf_to_witness_data(std::vector const& buf) { - auto w = WitnessMap::WitnessMap::bincodeDeserialize(buf); + // TODO(maxim): Handle the new `WitnessStack` structure once ACVM supports a function call stack + // A `StackItem` contains an index to an ACIR circuit and its respective ACIR-native `WitnessMap`. + // For now we expect the `WitnessStack` to contain a single witness. + auto w = WitnessStack::WitnessStack::bincodeDeserialize(buf).stack[0].witness; + WitnessVector wv; size_t index = 0; for (auto& e : w.value) { 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 0170896c722f..82b105315afe 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/acir.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/acir.hpp @@ -3,7 +3,7 @@ #include "bincode.hpp" #include "serde.hpp" -namespace Circuit { +namespace Program { struct BinaryFieldOp { @@ -140,7 +140,7 @@ struct MemoryAddress { }; struct HeapArray { - Circuit::MemoryAddress pointer; + Program::MemoryAddress pointer; uint64_t size; friend bool operator==(const HeapArray&, const HeapArray&); @@ -149,8 +149,8 @@ struct HeapArray { }; struct HeapVector { - Circuit::MemoryAddress pointer; - Circuit::MemoryAddress size; + Program::MemoryAddress pointer; + Program::MemoryAddress size; friend bool operator==(const HeapVector&, const HeapVector&); std::vector bincodeSerialize() const; @@ -160,8 +160,8 @@ struct HeapVector { struct BlackBoxOp { struct Sha256 { - Circuit::HeapVector message; - Circuit::HeapArray output; + Program::HeapVector message; + Program::HeapArray output; friend bool operator==(const Sha256&, const Sha256&); std::vector bincodeSerialize() const; @@ -169,8 +169,8 @@ struct BlackBoxOp { }; struct Blake2s { - Circuit::HeapVector message; - Circuit::HeapArray output; + Program::HeapVector message; + Program::HeapArray output; friend bool operator==(const Blake2s&, const Blake2s&); std::vector bincodeSerialize() const; @@ -178,8 +178,8 @@ struct BlackBoxOp { }; struct Blake3 { - Circuit::HeapVector message; - Circuit::HeapArray output; + Program::HeapVector message; + Program::HeapArray output; friend bool operator==(const Blake3&, const Blake3&); std::vector bincodeSerialize() const; @@ -187,8 +187,8 @@ struct BlackBoxOp { }; struct Keccak256 { - Circuit::HeapVector message; - Circuit::HeapArray output; + Program::HeapVector message; + Program::HeapArray output; friend bool operator==(const Keccak256&, const Keccak256&); std::vector bincodeSerialize() const; @@ -196,8 +196,8 @@ struct BlackBoxOp { }; struct Keccakf1600 { - Circuit::HeapVector message; - Circuit::HeapArray output; + Program::HeapVector message; + Program::HeapArray output; friend bool operator==(const Keccakf1600&, const Keccakf1600&); std::vector bincodeSerialize() const; @@ -205,11 +205,11 @@ struct BlackBoxOp { }; struct EcdsaSecp256k1 { - Circuit::HeapVector hashed_msg; - Circuit::HeapArray public_key_x; - Circuit::HeapArray public_key_y; - Circuit::HeapArray signature; - Circuit::MemoryAddress result; + Program::HeapVector hashed_msg; + Program::HeapArray public_key_x; + Program::HeapArray public_key_y; + Program::HeapArray signature; + Program::MemoryAddress result; friend bool operator==(const EcdsaSecp256k1&, const EcdsaSecp256k1&); std::vector bincodeSerialize() const; @@ -217,11 +217,11 @@ struct BlackBoxOp { }; struct EcdsaSecp256r1 { - Circuit::HeapVector hashed_msg; - Circuit::HeapArray public_key_x; - Circuit::HeapArray public_key_y; - Circuit::HeapArray signature; - Circuit::MemoryAddress result; + Program::HeapVector hashed_msg; + Program::HeapArray public_key_x; + Program::HeapArray public_key_y; + Program::HeapArray signature; + Program::MemoryAddress result; friend bool operator==(const EcdsaSecp256r1&, const EcdsaSecp256r1&); std::vector bincodeSerialize() const; @@ -229,11 +229,11 @@ struct BlackBoxOp { }; struct SchnorrVerify { - Circuit::MemoryAddress public_key_x; - Circuit::MemoryAddress public_key_y; - Circuit::HeapVector message; - Circuit::HeapVector signature; - Circuit::MemoryAddress result; + Program::MemoryAddress public_key_x; + Program::MemoryAddress public_key_y; + Program::HeapVector message; + Program::HeapVector signature; + Program::MemoryAddress result; friend bool operator==(const SchnorrVerify&, const SchnorrVerify&); std::vector bincodeSerialize() const; @@ -241,9 +241,9 @@ struct BlackBoxOp { }; struct PedersenCommitment { - Circuit::HeapVector inputs; - Circuit::MemoryAddress domain_separator; - Circuit::HeapArray output; + Program::HeapVector inputs; + Program::MemoryAddress domain_separator; + Program::HeapArray output; friend bool operator==(const PedersenCommitment&, const PedersenCommitment&); std::vector bincodeSerialize() const; @@ -251,9 +251,9 @@ struct BlackBoxOp { }; struct PedersenHash { - Circuit::HeapVector inputs; - Circuit::MemoryAddress domain_separator; - Circuit::MemoryAddress output; + Program::HeapVector inputs; + Program::MemoryAddress domain_separator; + Program::MemoryAddress output; friend bool operator==(const PedersenHash&, const PedersenHash&); std::vector bincodeSerialize() const; @@ -261,9 +261,9 @@ struct BlackBoxOp { }; struct FixedBaseScalarMul { - Circuit::MemoryAddress low; - Circuit::MemoryAddress high; - Circuit::HeapArray result; + Program::MemoryAddress low; + Program::MemoryAddress high; + Program::HeapArray result; friend bool operator==(const FixedBaseScalarMul&, const FixedBaseScalarMul&); std::vector bincodeSerialize() const; @@ -271,11 +271,11 @@ struct BlackBoxOp { }; struct EmbeddedCurveAdd { - Circuit::MemoryAddress input1_x; - Circuit::MemoryAddress input1_y; - Circuit::MemoryAddress input2_x; - Circuit::MemoryAddress input2_y; - Circuit::HeapArray result; + Program::MemoryAddress input1_x; + Program::MemoryAddress input1_y; + Program::MemoryAddress input2_x; + Program::MemoryAddress input2_y; + Program::HeapArray result; friend bool operator==(const EmbeddedCurveAdd&, const EmbeddedCurveAdd&); std::vector bincodeSerialize() const; @@ -283,9 +283,9 @@ struct BlackBoxOp { }; struct BigIntAdd { - Circuit::MemoryAddress lhs; - Circuit::MemoryAddress rhs; - Circuit::MemoryAddress output; + Program::MemoryAddress lhs; + Program::MemoryAddress rhs; + Program::MemoryAddress output; friend bool operator==(const BigIntAdd&, const BigIntAdd&); std::vector bincodeSerialize() const; @@ -293,9 +293,9 @@ struct BlackBoxOp { }; struct BigIntSub { - Circuit::MemoryAddress lhs; - Circuit::MemoryAddress rhs; - Circuit::MemoryAddress output; + Program::MemoryAddress lhs; + Program::MemoryAddress rhs; + Program::MemoryAddress output; friend bool operator==(const BigIntSub&, const BigIntSub&); std::vector bincodeSerialize() const; @@ -303,9 +303,9 @@ struct BlackBoxOp { }; struct BigIntMul { - Circuit::MemoryAddress lhs; - Circuit::MemoryAddress rhs; - Circuit::MemoryAddress output; + Program::MemoryAddress lhs; + Program::MemoryAddress rhs; + Program::MemoryAddress output; friend bool operator==(const BigIntMul&, const BigIntMul&); std::vector bincodeSerialize() const; @@ -313,9 +313,9 @@ struct BlackBoxOp { }; struct BigIntDiv { - Circuit::MemoryAddress lhs; - Circuit::MemoryAddress rhs; - Circuit::MemoryAddress output; + Program::MemoryAddress lhs; + Program::MemoryAddress rhs; + Program::MemoryAddress output; friend bool operator==(const BigIntDiv&, const BigIntDiv&); std::vector bincodeSerialize() const; @@ -323,9 +323,9 @@ struct BlackBoxOp { }; struct BigIntFromLeBytes { - Circuit::HeapVector inputs; - Circuit::HeapVector modulus; - Circuit::MemoryAddress output; + Program::HeapVector inputs; + Program::HeapVector modulus; + Program::MemoryAddress output; friend bool operator==(const BigIntFromLeBytes&, const BigIntFromLeBytes&); std::vector bincodeSerialize() const; @@ -333,8 +333,8 @@ struct BlackBoxOp { }; struct BigIntToLeBytes { - Circuit::MemoryAddress input; - Circuit::HeapVector output; + Program::MemoryAddress input; + Program::HeapVector output; friend bool operator==(const BigIntToLeBytes&, const BigIntToLeBytes&); std::vector bincodeSerialize() const; @@ -342,9 +342,9 @@ struct BlackBoxOp { }; struct Poseidon2Permutation { - Circuit::HeapVector message; - Circuit::HeapArray output; - Circuit::MemoryAddress len; + Program::HeapVector message; + Program::HeapArray output; + Program::MemoryAddress len; friend bool operator==(const Poseidon2Permutation&, const Poseidon2Permutation&); std::vector bincodeSerialize() const; @@ -352,9 +352,9 @@ struct BlackBoxOp { }; struct Sha256Compression { - Circuit::HeapVector input; - Circuit::HeapVector hash_values; - Circuit::HeapArray output; + Program::HeapVector input; + Program::HeapVector hash_values; + Program::HeapArray output; friend bool operator==(const Sha256Compression&, const Sha256Compression&); std::vector bincodeSerialize() const; @@ -399,7 +399,7 @@ struct HeapValueType { }; struct Array { - std::vector value_types; + std::vector value_types; uint64_t size; friend bool operator==(const Array&, const Array&); @@ -408,7 +408,7 @@ struct HeapValueType { }; struct Vector { - std::vector value_types; + std::vector value_types; friend bool operator==(const Vector&, const Vector&); std::vector bincodeSerialize() const; @@ -433,7 +433,7 @@ struct Value { struct ValueOrArray { struct MemoryAddress { - Circuit::MemoryAddress value; + Program::MemoryAddress value; friend bool operator==(const MemoryAddress&, const MemoryAddress&); std::vector bincodeSerialize() const; @@ -441,7 +441,7 @@ struct ValueOrArray { }; struct HeapArray { - Circuit::HeapArray value; + Program::HeapArray value; friend bool operator==(const HeapArray&, const HeapArray&); std::vector bincodeSerialize() const; @@ -449,7 +449,7 @@ struct ValueOrArray { }; struct HeapVector { - Circuit::HeapVector value; + Program::HeapVector value; friend bool operator==(const HeapVector&, const HeapVector&); std::vector bincodeSerialize() const; @@ -466,10 +466,10 @@ struct ValueOrArray { struct BrilligOpcode { struct BinaryFieldOp { - Circuit::MemoryAddress destination; - Circuit::BinaryFieldOp op; - Circuit::MemoryAddress lhs; - Circuit::MemoryAddress rhs; + Program::MemoryAddress destination; + Program::BinaryFieldOp op; + Program::MemoryAddress lhs; + Program::MemoryAddress rhs; friend bool operator==(const BinaryFieldOp&, const BinaryFieldOp&); std::vector bincodeSerialize() const; @@ -477,11 +477,11 @@ struct BrilligOpcode { }; struct BinaryIntOp { - Circuit::MemoryAddress destination; - Circuit::BinaryIntOp op; + Program::MemoryAddress destination; + Program::BinaryIntOp op; uint32_t bit_size; - Circuit::MemoryAddress lhs; - Circuit::MemoryAddress rhs; + Program::MemoryAddress lhs; + Program::MemoryAddress rhs; friend bool operator==(const BinaryIntOp&, const BinaryIntOp&); std::vector bincodeSerialize() const; @@ -489,8 +489,8 @@ struct BrilligOpcode { }; struct Cast { - Circuit::MemoryAddress destination; - Circuit::MemoryAddress source; + Program::MemoryAddress destination; + Program::MemoryAddress source; uint32_t bit_size; friend bool operator==(const Cast&, const Cast&); @@ -499,7 +499,7 @@ struct BrilligOpcode { }; struct JumpIfNot { - Circuit::MemoryAddress condition; + Program::MemoryAddress condition; uint64_t location; friend bool operator==(const JumpIfNot&, const JumpIfNot&); @@ -508,7 +508,7 @@ struct BrilligOpcode { }; struct JumpIf { - Circuit::MemoryAddress condition; + Program::MemoryAddress condition; uint64_t location; friend bool operator==(const JumpIf&, const JumpIf&); @@ -525,7 +525,7 @@ struct BrilligOpcode { }; struct CalldataCopy { - Circuit::MemoryAddress destination_address; + Program::MemoryAddress destination_address; uint64_t size; uint64_t offset; @@ -543,9 +543,9 @@ struct BrilligOpcode { }; struct Const { - Circuit::MemoryAddress destination; + Program::MemoryAddress destination; uint32_t bit_size; - Circuit::Value value; + Program::Value value; friend bool operator==(const Const&, const Const&); std::vector bincodeSerialize() const; @@ -560,10 +560,10 @@ struct BrilligOpcode { struct ForeignCall { std::string function; - std::vector destinations; - std::vector destination_value_types; - std::vector inputs; - std::vector input_value_types; + std::vector destinations; + std::vector destination_value_types; + std::vector inputs; + std::vector input_value_types; friend bool operator==(const ForeignCall&, const ForeignCall&); std::vector bincodeSerialize() const; @@ -571,8 +571,8 @@ struct BrilligOpcode { }; struct Mov { - Circuit::MemoryAddress destination; - Circuit::MemoryAddress source; + Program::MemoryAddress destination; + Program::MemoryAddress source; friend bool operator==(const Mov&, const Mov&); std::vector bincodeSerialize() const; @@ -580,8 +580,8 @@ struct BrilligOpcode { }; struct Load { - Circuit::MemoryAddress destination; - Circuit::MemoryAddress source_pointer; + Program::MemoryAddress destination; + Program::MemoryAddress source_pointer; friend bool operator==(const Load&, const Load&); std::vector bincodeSerialize() const; @@ -589,8 +589,8 @@ struct BrilligOpcode { }; struct Store { - Circuit::MemoryAddress destination_pointer; - Circuit::MemoryAddress source; + Program::MemoryAddress destination_pointer; + Program::MemoryAddress source; friend bool operator==(const Store&, const Store&); std::vector bincodeSerialize() const; @@ -598,7 +598,7 @@ struct BrilligOpcode { }; struct BlackBox { - Circuit::BlackBoxOp value; + Program::BlackBoxOp value; friend bool operator==(const BlackBox&, const BlackBox&); std::vector bincodeSerialize() const; @@ -653,7 +653,7 @@ struct Witness { }; struct FunctionInput { - Circuit::Witness witness; + Program::Witness witness; uint32_t num_bits; friend bool operator==(const FunctionInput&, const FunctionInput&); @@ -664,9 +664,9 @@ struct FunctionInput { struct BlackBoxFuncCall { struct AND { - Circuit::FunctionInput lhs; - Circuit::FunctionInput rhs; - Circuit::Witness output; + Program::FunctionInput lhs; + Program::FunctionInput rhs; + Program::Witness output; friend bool operator==(const AND&, const AND&); std::vector bincodeSerialize() const; @@ -674,9 +674,9 @@ struct BlackBoxFuncCall { }; struct XOR { - Circuit::FunctionInput lhs; - Circuit::FunctionInput rhs; - Circuit::Witness output; + Program::FunctionInput lhs; + Program::FunctionInput rhs; + Program::Witness output; friend bool operator==(const XOR&, const XOR&); std::vector bincodeSerialize() const; @@ -684,7 +684,7 @@ struct BlackBoxFuncCall { }; struct RANGE { - Circuit::FunctionInput input; + Program::FunctionInput input; friend bool operator==(const RANGE&, const RANGE&); std::vector bincodeSerialize() const; @@ -692,8 +692,8 @@ struct BlackBoxFuncCall { }; struct SHA256 { - std::vector inputs; - std::vector outputs; + std::vector inputs; + std::vector outputs; friend bool operator==(const SHA256&, const SHA256&); std::vector bincodeSerialize() const; @@ -701,8 +701,8 @@ struct BlackBoxFuncCall { }; struct Blake2s { - std::vector inputs; - std::vector outputs; + std::vector inputs; + std::vector outputs; friend bool operator==(const Blake2s&, const Blake2s&); std::vector bincodeSerialize() const; @@ -710,8 +710,8 @@ struct BlackBoxFuncCall { }; struct Blake3 { - std::vector inputs; - std::vector outputs; + std::vector inputs; + std::vector outputs; friend bool operator==(const Blake3&, const Blake3&); std::vector bincodeSerialize() const; @@ -719,11 +719,11 @@ struct BlackBoxFuncCall { }; struct SchnorrVerify { - Circuit::FunctionInput public_key_x; - Circuit::FunctionInput public_key_y; - std::vector signature; - std::vector message; - Circuit::Witness output; + Program::FunctionInput public_key_x; + Program::FunctionInput public_key_y; + std::vector signature; + std::vector message; + Program::Witness output; friend bool operator==(const SchnorrVerify&, const SchnorrVerify&); std::vector bincodeSerialize() const; @@ -731,9 +731,9 @@ struct BlackBoxFuncCall { }; struct PedersenCommitment { - std::vector inputs; + std::vector inputs; uint32_t domain_separator; - std::array outputs; + std::array outputs; friend bool operator==(const PedersenCommitment&, const PedersenCommitment&); std::vector bincodeSerialize() const; @@ -741,9 +741,9 @@ struct BlackBoxFuncCall { }; struct PedersenHash { - std::vector inputs; + std::vector inputs; uint32_t domain_separator; - Circuit::Witness output; + Program::Witness output; friend bool operator==(const PedersenHash&, const PedersenHash&); std::vector bincodeSerialize() const; @@ -751,11 +751,11 @@ struct BlackBoxFuncCall { }; struct EcdsaSecp256k1 { - std::vector public_key_x; - std::vector public_key_y; - std::vector signature; - std::vector hashed_message; - Circuit::Witness output; + std::vector public_key_x; + std::vector public_key_y; + std::vector signature; + std::vector hashed_message; + Program::Witness output; friend bool operator==(const EcdsaSecp256k1&, const EcdsaSecp256k1&); std::vector bincodeSerialize() const; @@ -763,11 +763,11 @@ struct BlackBoxFuncCall { }; struct EcdsaSecp256r1 { - std::vector public_key_x; - std::vector public_key_y; - std::vector signature; - std::vector hashed_message; - Circuit::Witness output; + std::vector public_key_x; + std::vector public_key_y; + std::vector signature; + std::vector hashed_message; + Program::Witness output; friend bool operator==(const EcdsaSecp256r1&, const EcdsaSecp256r1&); std::vector bincodeSerialize() const; @@ -775,9 +775,9 @@ struct BlackBoxFuncCall { }; struct FixedBaseScalarMul { - Circuit::FunctionInput low; - Circuit::FunctionInput high; - std::array outputs; + Program::FunctionInput low; + Program::FunctionInput high; + std::array outputs; friend bool operator==(const FixedBaseScalarMul&, const FixedBaseScalarMul&); std::vector bincodeSerialize() const; @@ -785,11 +785,11 @@ struct BlackBoxFuncCall { }; struct EmbeddedCurveAdd { - Circuit::FunctionInput input1_x; - Circuit::FunctionInput input1_y; - Circuit::FunctionInput input2_x; - Circuit::FunctionInput input2_y; - std::array outputs; + Program::FunctionInput input1_x; + Program::FunctionInput input1_y; + Program::FunctionInput input2_x; + Program::FunctionInput input2_y; + std::array outputs; friend bool operator==(const EmbeddedCurveAdd&, const EmbeddedCurveAdd&); std::vector bincodeSerialize() const; @@ -797,8 +797,8 @@ struct BlackBoxFuncCall { }; struct Keccak256 { - std::vector inputs; - std::vector outputs; + std::vector inputs; + std::vector outputs; friend bool operator==(const Keccak256&, const Keccak256&); std::vector bincodeSerialize() const; @@ -806,9 +806,9 @@ struct BlackBoxFuncCall { }; struct Keccak256VariableLength { - std::vector inputs; - Circuit::FunctionInput var_message_size; - std::vector outputs; + std::vector inputs; + Program::FunctionInput var_message_size; + std::vector outputs; friend bool operator==(const Keccak256VariableLength&, const Keccak256VariableLength&); std::vector bincodeSerialize() const; @@ -816,8 +816,8 @@ struct BlackBoxFuncCall { }; struct Keccakf1600 { - std::vector inputs; - std::vector outputs; + std::vector inputs; + std::vector outputs; friend bool operator==(const Keccakf1600&, const Keccakf1600&); std::vector bincodeSerialize() const; @@ -825,10 +825,10 @@ struct BlackBoxFuncCall { }; struct RecursiveAggregation { - std::vector verification_key; - std::vector proof; - std::vector public_inputs; - Circuit::FunctionInput key_hash; + std::vector verification_key; + std::vector proof; + std::vector public_inputs; + Program::FunctionInput key_hash; friend bool operator==(const RecursiveAggregation&, const RecursiveAggregation&); std::vector bincodeSerialize() const; @@ -876,7 +876,7 @@ struct BlackBoxFuncCall { }; struct BigIntFromLeBytes { - std::vector inputs; + std::vector inputs; std::vector modulus; uint32_t output; @@ -887,7 +887,7 @@ struct BlackBoxFuncCall { struct BigIntToLeBytes { uint32_t input; - std::vector outputs; + std::vector outputs; friend bool operator==(const BigIntToLeBytes&, const BigIntToLeBytes&); std::vector bincodeSerialize() const; @@ -895,8 +895,8 @@ struct BlackBoxFuncCall { }; struct Poseidon2Permutation { - std::vector inputs; - std::vector outputs; + std::vector inputs; + std::vector outputs; uint32_t len; friend bool operator==(const Poseidon2Permutation&, const Poseidon2Permutation&); @@ -905,9 +905,9 @@ struct BlackBoxFuncCall { }; struct Sha256Compression { - std::vector inputs; - std::vector hash_values; - std::vector outputs; + std::vector inputs; + std::vector hash_values; + std::vector outputs; friend bool operator==(const Sha256Compression&, const Sha256Compression&); std::vector bincodeSerialize() const; @@ -955,8 +955,8 @@ struct BlockId { }; struct Expression { - std::vector> mul_terms; - std::vector> linear_combinations; + std::vector> mul_terms; + std::vector> linear_combinations; std::string q_c; friend bool operator==(const Expression&, const Expression&); @@ -967,7 +967,7 @@ struct Expression { struct BrilligInputs { struct Single { - Circuit::Expression value; + Program::Expression value; friend bool operator==(const Single&, const Single&); std::vector bincodeSerialize() const; @@ -975,7 +975,7 @@ struct BrilligInputs { }; struct Array { - std::vector value; + std::vector value; friend bool operator==(const Array&, const Array&); std::vector bincodeSerialize() const; @@ -983,7 +983,7 @@ struct BrilligInputs { }; struct MemoryArray { - Circuit::BlockId value; + Program::BlockId value; friend bool operator==(const MemoryArray&, const MemoryArray&); std::vector bincodeSerialize() const; @@ -1000,7 +1000,7 @@ struct BrilligInputs { struct BrilligOutputs { struct Simple { - Circuit::Witness value; + Program::Witness value; friend bool operator==(const Simple&, const Simple&); std::vector bincodeSerialize() const; @@ -1008,7 +1008,7 @@ struct BrilligOutputs { }; struct Array { - std::vector value; + std::vector value; friend bool operator==(const Array&, const Array&); std::vector bincodeSerialize() const; @@ -1023,10 +1023,10 @@ struct BrilligOutputs { }; struct Brillig { - std::vector inputs; - std::vector outputs; - std::vector bytecode; - std::optional predicate; + std::vector inputs; + std::vector outputs; + std::vector bytecode; + std::optional predicate; friend bool operator==(const Brillig&, const Brillig&); std::vector bincodeSerialize() const; @@ -1036,8 +1036,8 @@ struct Brillig { struct Directive { struct ToLeRadix { - Circuit::Expression a; - std::vector b; + Program::Expression a; + std::vector b; uint32_t radix; friend bool operator==(const ToLeRadix&, const ToLeRadix&); @@ -1053,9 +1053,9 @@ struct Directive { }; struct MemOp { - Circuit::Expression operation; - Circuit::Expression index; - Circuit::Expression value; + Program::Expression operation; + Program::Expression index; + Program::Expression value; friend bool operator==(const MemOp&, const MemOp&); std::vector bincodeSerialize() const; @@ -1065,7 +1065,7 @@ struct MemOp { struct Opcode { struct AssertZero { - Circuit::Expression value; + Program::Expression value; friend bool operator==(const AssertZero&, const AssertZero&); std::vector bincodeSerialize() const; @@ -1073,7 +1073,7 @@ struct Opcode { }; struct BlackBoxFuncCall { - Circuit::BlackBoxFuncCall value; + Program::BlackBoxFuncCall value; friend bool operator==(const BlackBoxFuncCall&, const BlackBoxFuncCall&); std::vector bincodeSerialize() const; @@ -1081,7 +1081,7 @@ struct Opcode { }; struct Directive { - Circuit::Directive value; + Program::Directive value; friend bool operator==(const Directive&, const Directive&); std::vector bincodeSerialize() const; @@ -1089,7 +1089,7 @@ struct Opcode { }; struct Brillig { - Circuit::Brillig value; + Program::Brillig value; friend bool operator==(const Brillig&, const Brillig&); std::vector bincodeSerialize() const; @@ -1097,9 +1097,9 @@ struct Opcode { }; struct MemoryOp { - Circuit::BlockId block_id; - Circuit::MemOp op; - std::optional predicate; + Program::BlockId block_id; + Program::MemOp op; + std::optional predicate; friend bool operator==(const MemoryOp&, const MemoryOp&); std::vector bincodeSerialize() const; @@ -1107,8 +1107,8 @@ struct Opcode { }; struct MemoryInit { - Circuit::BlockId block_id; - std::vector init; + Program::BlockId block_id; + std::vector init; friend bool operator==(const MemoryInit&, const MemoryInit&); std::vector bincodeSerialize() const; @@ -1117,8 +1117,8 @@ struct Opcode { struct Call { uint32_t id; - std::vector inputs; - std::vector outputs; + std::vector inputs; + std::vector outputs; friend bool operator==(const Call&, const Call&); std::vector bincodeSerialize() const; @@ -1182,7 +1182,7 @@ struct OpcodeLocation { }; struct PublicInputs { - std::vector value; + std::vector value; friend bool operator==(const PublicInputs&, const PublicInputs&); std::vector bincodeSerialize() const; @@ -1191,12 +1191,12 @@ struct PublicInputs { struct Circuit { uint32_t current_witness_index; - std::vector opcodes; - ExpressionWidth expression_width; - std::vector private_parameters; - PublicInputs public_parameters; - PublicInputs return_values; - std::vector> assert_messages; + std::vector opcodes; + Program::ExpressionWidth expression_width; + std::vector private_parameters; + Program::PublicInputs public_parameters; + Program::PublicInputs return_values; + std::vector> assert_messages; bool recursive; friend bool operator==(const Circuit&, const Circuit&); @@ -1204,9 +1204,17 @@ struct Circuit { static Circuit bincodeDeserialize(std::vector); }; -} // end of namespace Circuit +struct Program { + std::vector functions; -namespace Circuit { + friend bool operator==(const Program&, const Program&); + std::vector bincodeSerialize() const; + static Program bincodeDeserialize(std::vector); +}; + +} // end of namespace Program + +namespace Program { inline bool operator==(const BinaryFieldOp& lhs, const BinaryFieldOp& rhs) { @@ -1233,11 +1241,11 @@ inline BinaryFieldOp BinaryFieldOp::bincodeDeserialize(std::vector inpu return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryFieldOp& obj, Serializer& serializer) +void serde::Serializable::serialize(const Program::BinaryFieldOp& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); @@ -1246,16 +1254,16 @@ void serde::Serializable::serialize(const Circuit::Binar template <> template -Circuit::BinaryFieldOp serde::Deserializable::deserialize(Deserializer& deserializer) +Program::BinaryFieldOp serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Circuit::BinaryFieldOp obj; + Program::BinaryFieldOp obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryFieldOp::Add& lhs, const BinaryFieldOp::Add& rhs) { @@ -1279,23 +1287,23 @@ inline BinaryFieldOp::Add BinaryFieldOp::Add::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Circuit::BinaryFieldOp::Add& obj, +void serde::Serializable::serialize(const Program::BinaryFieldOp::Add& obj, Serializer& serializer) {} template <> template -Circuit::BinaryFieldOp::Add serde::Deserializable::deserialize(Deserializer& deserializer) +Program::BinaryFieldOp::Add serde::Deserializable::deserialize(Deserializer& deserializer) { - Circuit::BinaryFieldOp::Add obj; + Program::BinaryFieldOp::Add obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryFieldOp::Sub& lhs, const BinaryFieldOp::Sub& rhs) { @@ -1319,23 +1327,23 @@ inline BinaryFieldOp::Sub BinaryFieldOp::Sub::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Circuit::BinaryFieldOp::Sub& obj, +void serde::Serializable::serialize(const Program::BinaryFieldOp::Sub& obj, Serializer& serializer) {} template <> template -Circuit::BinaryFieldOp::Sub serde::Deserializable::deserialize(Deserializer& deserializer) +Program::BinaryFieldOp::Sub serde::Deserializable::deserialize(Deserializer& deserializer) { - Circuit::BinaryFieldOp::Sub obj; + Program::BinaryFieldOp::Sub obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryFieldOp::Mul& lhs, const BinaryFieldOp::Mul& rhs) { @@ -1359,23 +1367,23 @@ inline BinaryFieldOp::Mul BinaryFieldOp::Mul::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Circuit::BinaryFieldOp::Mul& obj, +void serde::Serializable::serialize(const Program::BinaryFieldOp::Mul& obj, Serializer& serializer) {} template <> template -Circuit::BinaryFieldOp::Mul serde::Deserializable::deserialize(Deserializer& deserializer) +Program::BinaryFieldOp::Mul serde::Deserializable::deserialize(Deserializer& deserializer) { - Circuit::BinaryFieldOp::Mul obj; + Program::BinaryFieldOp::Mul obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryFieldOp::Div& lhs, const BinaryFieldOp::Div& rhs) { @@ -1399,23 +1407,23 @@ inline BinaryFieldOp::Div BinaryFieldOp::Div::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Circuit::BinaryFieldOp::Div& obj, +void serde::Serializable::serialize(const Program::BinaryFieldOp::Div& obj, Serializer& serializer) {} template <> template -Circuit::BinaryFieldOp::Div serde::Deserializable::deserialize(Deserializer& deserializer) +Program::BinaryFieldOp::Div serde::Deserializable::deserialize(Deserializer& deserializer) { - Circuit::BinaryFieldOp::Div obj; + Program::BinaryFieldOp::Div obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryFieldOp::Equals& lhs, const BinaryFieldOp::Equals& rhs) { @@ -1439,24 +1447,24 @@ inline BinaryFieldOp::Equals BinaryFieldOp::Equals::bincodeDeserialize(std::vect return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryFieldOp::Equals& obj, +void serde::Serializable::serialize(const Program::BinaryFieldOp::Equals& obj, Serializer& serializer) {} template <> template -Circuit::BinaryFieldOp::Equals serde::Deserializable::deserialize( +Program::BinaryFieldOp::Equals serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BinaryFieldOp::Equals obj; + Program::BinaryFieldOp::Equals obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp& lhs, const BinaryIntOp& rhs) { @@ -1483,11 +1491,11 @@ inline BinaryIntOp BinaryIntOp::bincodeDeserialize(std::vector input) return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryIntOp& obj, Serializer& serializer) +void serde::Serializable::serialize(const Program::BinaryIntOp& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); @@ -1496,16 +1504,16 @@ void serde::Serializable::serialize(const Circuit::BinaryI template <> template -Circuit::BinaryIntOp serde::Deserializable::deserialize(Deserializer& deserializer) +Program::BinaryIntOp serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Circuit::BinaryIntOp obj; + Program::BinaryIntOp obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp::Add& lhs, const BinaryIntOp::Add& rhs) { @@ -1529,23 +1537,23 @@ inline BinaryIntOp::Add BinaryIntOp::Add::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Circuit::BinaryIntOp::Add& obj, +void serde::Serializable::serialize(const Program::BinaryIntOp::Add& obj, Serializer& serializer) {} template <> template -Circuit::BinaryIntOp::Add serde::Deserializable::deserialize(Deserializer& deserializer) +Program::BinaryIntOp::Add serde::Deserializable::deserialize(Deserializer& deserializer) { - Circuit::BinaryIntOp::Add obj; + Program::BinaryIntOp::Add obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp::Sub& lhs, const BinaryIntOp::Sub& rhs) { @@ -1569,23 +1577,23 @@ inline BinaryIntOp::Sub BinaryIntOp::Sub::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Circuit::BinaryIntOp::Sub& obj, +void serde::Serializable::serialize(const Program::BinaryIntOp::Sub& obj, Serializer& serializer) {} template <> template -Circuit::BinaryIntOp::Sub serde::Deserializable::deserialize(Deserializer& deserializer) +Program::BinaryIntOp::Sub serde::Deserializable::deserialize(Deserializer& deserializer) { - Circuit::BinaryIntOp::Sub obj; + Program::BinaryIntOp::Sub obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp::Mul& lhs, const BinaryIntOp::Mul& rhs) { @@ -1609,23 +1617,23 @@ inline BinaryIntOp::Mul BinaryIntOp::Mul::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Circuit::BinaryIntOp::Mul& obj, +void serde::Serializable::serialize(const Program::BinaryIntOp::Mul& obj, Serializer& serializer) {} template <> template -Circuit::BinaryIntOp::Mul serde::Deserializable::deserialize(Deserializer& deserializer) +Program::BinaryIntOp::Mul serde::Deserializable::deserialize(Deserializer& deserializer) { - Circuit::BinaryIntOp::Mul obj; + Program::BinaryIntOp::Mul obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp::SignedDiv& lhs, const BinaryIntOp::SignedDiv& rhs) { @@ -1649,24 +1657,24 @@ inline BinaryIntOp::SignedDiv BinaryIntOp::SignedDiv::bincodeDeserialize(std::ve return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryIntOp::SignedDiv& obj, +void serde::Serializable::serialize(const Program::BinaryIntOp::SignedDiv& obj, Serializer& serializer) {} template <> template -Circuit::BinaryIntOp::SignedDiv serde::Deserializable::deserialize( +Program::BinaryIntOp::SignedDiv serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BinaryIntOp::SignedDiv obj; + Program::BinaryIntOp::SignedDiv obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp::UnsignedDiv& lhs, const BinaryIntOp::UnsignedDiv& rhs) { @@ -1690,24 +1698,24 @@ inline BinaryIntOp::UnsignedDiv BinaryIntOp::UnsignedDiv::bincodeDeserialize(std return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryIntOp::UnsignedDiv& obj, +void serde::Serializable::serialize(const Program::BinaryIntOp::UnsignedDiv& obj, Serializer& serializer) {} template <> template -Circuit::BinaryIntOp::UnsignedDiv serde::Deserializable::deserialize( +Program::BinaryIntOp::UnsignedDiv serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BinaryIntOp::UnsignedDiv obj; + Program::BinaryIntOp::UnsignedDiv obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp::Equals& lhs, const BinaryIntOp::Equals& rhs) { @@ -1731,24 +1739,24 @@ inline BinaryIntOp::Equals BinaryIntOp::Equals::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Circuit::BinaryIntOp::Equals& obj, +void serde::Serializable::serialize(const Program::BinaryIntOp::Equals& obj, Serializer& serializer) {} template <> template -Circuit::BinaryIntOp::Equals serde::Deserializable::deserialize( +Program::BinaryIntOp::Equals serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BinaryIntOp::Equals obj; + Program::BinaryIntOp::Equals obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp::LessThan& lhs, const BinaryIntOp::LessThan& rhs) { @@ -1772,24 +1780,24 @@ inline BinaryIntOp::LessThan BinaryIntOp::LessThan::bincodeDeserialize(std::vect return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryIntOp::LessThan& obj, +void serde::Serializable::serialize(const Program::BinaryIntOp::LessThan& obj, Serializer& serializer) {} template <> template -Circuit::BinaryIntOp::LessThan serde::Deserializable::deserialize( +Program::BinaryIntOp::LessThan serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BinaryIntOp::LessThan obj; + Program::BinaryIntOp::LessThan obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp::LessThanEquals& lhs, const BinaryIntOp::LessThanEquals& rhs) { @@ -1813,24 +1821,24 @@ inline BinaryIntOp::LessThanEquals BinaryIntOp::LessThanEquals::bincodeDeseriali return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize( - const Circuit::BinaryIntOp::LessThanEquals& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Program::BinaryIntOp::LessThanEquals& obj, Serializer& serializer) {} template <> template -Circuit::BinaryIntOp::LessThanEquals serde::Deserializable::deserialize( +Program::BinaryIntOp::LessThanEquals serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BinaryIntOp::LessThanEquals obj; + Program::BinaryIntOp::LessThanEquals obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp::And& lhs, const BinaryIntOp::And& rhs) { @@ -1854,23 +1862,23 @@ inline BinaryIntOp::And BinaryIntOp::And::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Circuit::BinaryIntOp::And& obj, +void serde::Serializable::serialize(const Program::BinaryIntOp::And& obj, Serializer& serializer) {} template <> template -Circuit::BinaryIntOp::And serde::Deserializable::deserialize(Deserializer& deserializer) +Program::BinaryIntOp::And serde::Deserializable::deserialize(Deserializer& deserializer) { - Circuit::BinaryIntOp::And obj; + Program::BinaryIntOp::And obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp::Or& lhs, const BinaryIntOp::Or& rhs) { @@ -1894,23 +1902,23 @@ inline BinaryIntOp::Or BinaryIntOp::Or::bincodeDeserialize(std::vector return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryIntOp::Or& obj, +void serde::Serializable::serialize(const Program::BinaryIntOp::Or& obj, Serializer& serializer) {} template <> template -Circuit::BinaryIntOp::Or serde::Deserializable::deserialize(Deserializer& deserializer) +Program::BinaryIntOp::Or serde::Deserializable::deserialize(Deserializer& deserializer) { - Circuit::BinaryIntOp::Or obj; + Program::BinaryIntOp::Or obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp::Xor& lhs, const BinaryIntOp::Xor& rhs) { @@ -1934,23 +1942,23 @@ inline BinaryIntOp::Xor BinaryIntOp::Xor::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Circuit::BinaryIntOp::Xor& obj, +void serde::Serializable::serialize(const Program::BinaryIntOp::Xor& obj, Serializer& serializer) {} template <> template -Circuit::BinaryIntOp::Xor serde::Deserializable::deserialize(Deserializer& deserializer) +Program::BinaryIntOp::Xor serde::Deserializable::deserialize(Deserializer& deserializer) { - Circuit::BinaryIntOp::Xor obj; + Program::BinaryIntOp::Xor obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp::Shl& lhs, const BinaryIntOp::Shl& rhs) { @@ -1974,23 +1982,23 @@ inline BinaryIntOp::Shl BinaryIntOp::Shl::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Circuit::BinaryIntOp::Shl& obj, +void serde::Serializable::serialize(const Program::BinaryIntOp::Shl& obj, Serializer& serializer) {} template <> template -Circuit::BinaryIntOp::Shl serde::Deserializable::deserialize(Deserializer& deserializer) +Program::BinaryIntOp::Shl serde::Deserializable::deserialize(Deserializer& deserializer) { - Circuit::BinaryIntOp::Shl obj; + Program::BinaryIntOp::Shl obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp::Shr& lhs, const BinaryIntOp::Shr& rhs) { @@ -2014,23 +2022,23 @@ inline BinaryIntOp::Shr BinaryIntOp::Shr::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Circuit::BinaryIntOp::Shr& obj, +void serde::Serializable::serialize(const Program::BinaryIntOp::Shr& obj, Serializer& serializer) {} template <> template -Circuit::BinaryIntOp::Shr serde::Deserializable::deserialize(Deserializer& deserializer) +Program::BinaryIntOp::Shr serde::Deserializable::deserialize(Deserializer& deserializer) { - Circuit::BinaryIntOp::Shr obj; + Program::BinaryIntOp::Shr obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall& lhs, const BlackBoxFuncCall& rhs) { @@ -2057,11 +2065,11 @@ inline BlackBoxFuncCall BlackBoxFuncCall::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall& obj, +void serde::Serializable::serialize(const Program::BlackBoxFuncCall& obj, Serializer& serializer) { serializer.increase_container_depth(); @@ -2071,16 +2079,16 @@ void serde::Serializable::serialize(const Circuit::Bl template <> template -Circuit::BlackBoxFuncCall serde::Deserializable::deserialize(Deserializer& deserializer) +Program::BlackBoxFuncCall serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Circuit::BlackBoxFuncCall obj; + Program::BlackBoxFuncCall obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::AND& lhs, const BlackBoxFuncCall::AND& rhs) { @@ -2113,11 +2121,11 @@ inline BlackBoxFuncCall::AND BlackBoxFuncCall::AND::bincodeDeserialize(std::vect return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::AND& obj, +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::AND& obj, Serializer& serializer) { serde::Serializable::serialize(obj.lhs, serializer); @@ -2127,17 +2135,17 @@ void serde::Serializable::serialize(const Circui template <> template -Circuit::BlackBoxFuncCall::AND serde::Deserializable::deserialize( +Program::BlackBoxFuncCall::AND serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxFuncCall::AND obj; + Program::BlackBoxFuncCall::AND obj; obj.lhs = serde::Deserializable::deserialize(deserializer); obj.rhs = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::XOR& lhs, const BlackBoxFuncCall::XOR& rhs) { @@ -2170,11 +2178,11 @@ inline BlackBoxFuncCall::XOR BlackBoxFuncCall::XOR::bincodeDeserialize(std::vect return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::XOR& obj, +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::XOR& obj, Serializer& serializer) { serde::Serializable::serialize(obj.lhs, serializer); @@ -2184,17 +2192,17 @@ void serde::Serializable::serialize(const Circui template <> template -Circuit::BlackBoxFuncCall::XOR serde::Deserializable::deserialize( +Program::BlackBoxFuncCall::XOR serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxFuncCall::XOR obj; + Program::BlackBoxFuncCall::XOR obj; obj.lhs = serde::Deserializable::deserialize(deserializer); obj.rhs = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::RANGE& lhs, const BlackBoxFuncCall::RANGE& rhs) { @@ -2221,11 +2229,11 @@ inline BlackBoxFuncCall::RANGE BlackBoxFuncCall::RANGE::bincodeDeserialize(std:: return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::RANGE& obj, +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::RANGE& obj, Serializer& serializer) { serde::Serializable::serialize(obj.input, serializer); @@ -2233,15 +2241,15 @@ void serde::Serializable::serialize(const Circ template <> template -Circuit::BlackBoxFuncCall::RANGE serde::Deserializable::deserialize( +Program::BlackBoxFuncCall::RANGE serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxFuncCall::RANGE obj; + Program::BlackBoxFuncCall::RANGE obj; obj.input = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::SHA256& lhs, const BlackBoxFuncCall::SHA256& rhs) { @@ -2271,11 +2279,11 @@ inline BlackBoxFuncCall::SHA256 BlackBoxFuncCall::SHA256::bincodeDeserialize(std return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::SHA256& obj, +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::SHA256& obj, Serializer& serializer) { serde::Serializable::serialize(obj.inputs, serializer); @@ -2284,16 +2292,16 @@ void serde::Serializable::serialize(const Cir template <> template -Circuit::BlackBoxFuncCall::SHA256 serde::Deserializable::deserialize( +Program::BlackBoxFuncCall::SHA256 serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxFuncCall::SHA256 obj; + Program::BlackBoxFuncCall::SHA256 obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::Blake2s& lhs, const BlackBoxFuncCall::Blake2s& rhs) { @@ -2323,11 +2331,11 @@ inline BlackBoxFuncCall::Blake2s BlackBoxFuncCall::Blake2s::bincodeDeserialize(s return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::Blake2s& obj, +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::Blake2s& obj, Serializer& serializer) { serde::Serializable::serialize(obj.inputs, serializer); @@ -2336,16 +2344,16 @@ void serde::Serializable::serialize(const Ci template <> template -Circuit::BlackBoxFuncCall::Blake2s serde::Deserializable::deserialize( +Program::BlackBoxFuncCall::Blake2s serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxFuncCall::Blake2s obj; + Program::BlackBoxFuncCall::Blake2s obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::Blake3& lhs, const BlackBoxFuncCall::Blake3& rhs) { @@ -2375,11 +2383,11 @@ inline BlackBoxFuncCall::Blake3 BlackBoxFuncCall::Blake3::bincodeDeserialize(std return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::Blake3& obj, +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::Blake3& obj, Serializer& serializer) { serde::Serializable::serialize(obj.inputs, serializer); @@ -2388,16 +2396,16 @@ void serde::Serializable::serialize(const Cir template <> template -Circuit::BlackBoxFuncCall::Blake3 serde::Deserializable::deserialize( +Program::BlackBoxFuncCall::Blake3 serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxFuncCall::Blake3 obj; + Program::BlackBoxFuncCall::Blake3 obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::SchnorrVerify& lhs, const BlackBoxFuncCall::SchnorrVerify& rhs) { @@ -2436,12 +2444,12 @@ inline BlackBoxFuncCall::SchnorrVerify BlackBoxFuncCall::SchnorrVerify::bincodeD return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize( - const Circuit::BlackBoxFuncCall::SchnorrVerify& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Program::BlackBoxFuncCall::SchnorrVerify& obj, Serializer& serializer) { serde::Serializable::serialize(obj.public_key_x, serializer); serde::Serializable::serialize(obj.public_key_y, serializer); @@ -2452,10 +2460,10 @@ void serde::Serializable::serialize( template <> template -Circuit::BlackBoxFuncCall::SchnorrVerify serde::Deserializable::deserialize( +Program::BlackBoxFuncCall::SchnorrVerify serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxFuncCall::SchnorrVerify obj; + Program::BlackBoxFuncCall::SchnorrVerify obj; obj.public_key_x = serde::Deserializable::deserialize(deserializer); obj.public_key_y = serde::Deserializable::deserialize(deserializer); obj.signature = serde::Deserializable::deserialize(deserializer); @@ -2464,7 +2472,7 @@ Circuit::BlackBoxFuncCall::SchnorrVerify serde::Deserializable template -void serde::Serializable::serialize( - const Circuit::BlackBoxFuncCall::PedersenCommitment& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Program::BlackBoxFuncCall::PedersenCommitment& obj, Serializer& serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.domain_separator, serializer); @@ -2512,17 +2520,17 @@ void serde::Serializable::seriali template <> template -Circuit::BlackBoxFuncCall::PedersenCommitment serde::Deserializable< - Circuit::BlackBoxFuncCall::PedersenCommitment>::deserialize(Deserializer& deserializer) +Program::BlackBoxFuncCall::PedersenCommitment serde::Deserializable< + Program::BlackBoxFuncCall::PedersenCommitment>::deserialize(Deserializer& deserializer) { - Circuit::BlackBoxFuncCall::PedersenCommitment obj; + Program::BlackBoxFuncCall::PedersenCommitment obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.domain_separator = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::PedersenHash& lhs, const BlackBoxFuncCall::PedersenHash& rhs) { @@ -2555,12 +2563,12 @@ inline BlackBoxFuncCall::PedersenHash BlackBoxFuncCall::PedersenHash::bincodeDes return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize( - const Circuit::BlackBoxFuncCall::PedersenHash& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Program::BlackBoxFuncCall::PedersenHash& obj, Serializer& serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.domain_separator, serializer); @@ -2569,17 +2577,17 @@ void serde::Serializable::serialize( template <> template -Circuit::BlackBoxFuncCall::PedersenHash serde::Deserializable::deserialize( +Program::BlackBoxFuncCall::PedersenHash serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxFuncCall::PedersenHash obj; + Program::BlackBoxFuncCall::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 { +namespace Program { inline bool operator==(const BlackBoxFuncCall::EcdsaSecp256k1& lhs, const BlackBoxFuncCall::EcdsaSecp256k1& rhs) { @@ -2618,12 +2626,12 @@ inline BlackBoxFuncCall::EcdsaSecp256k1 BlackBoxFuncCall::EcdsaSecp256k1::bincod return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize( - const Circuit::BlackBoxFuncCall::EcdsaSecp256k1& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Program::BlackBoxFuncCall::EcdsaSecp256k1& obj, Serializer& serializer) { serde::Serializable::serialize(obj.public_key_x, serializer); serde::Serializable::serialize(obj.public_key_y, serializer); @@ -2634,10 +2642,10 @@ void serde::Serializable::serialize( template <> template -Circuit::BlackBoxFuncCall::EcdsaSecp256k1 serde::Deserializable::deserialize( +Program::BlackBoxFuncCall::EcdsaSecp256k1 serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxFuncCall::EcdsaSecp256k1 obj; + Program::BlackBoxFuncCall::EcdsaSecp256k1 obj; obj.public_key_x = serde::Deserializable::deserialize(deserializer); obj.public_key_y = serde::Deserializable::deserialize(deserializer); obj.signature = serde::Deserializable::deserialize(deserializer); @@ -2646,7 +2654,7 @@ Circuit::BlackBoxFuncCall::EcdsaSecp256k1 serde::Deserializable template -void serde::Serializable::serialize( - const Circuit::BlackBoxFuncCall::EcdsaSecp256r1& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Program::BlackBoxFuncCall::EcdsaSecp256r1& obj, Serializer& serializer) { serde::Serializable::serialize(obj.public_key_x, serializer); serde::Serializable::serialize(obj.public_key_y, serializer); @@ -2701,10 +2709,10 @@ void serde::Serializable::serialize( template <> template -Circuit::BlackBoxFuncCall::EcdsaSecp256r1 serde::Deserializable::deserialize( +Program::BlackBoxFuncCall::EcdsaSecp256r1 serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxFuncCall::EcdsaSecp256r1 obj; + Program::BlackBoxFuncCall::EcdsaSecp256r1 obj; obj.public_key_x = serde::Deserializable::deserialize(deserializer); obj.public_key_y = serde::Deserializable::deserialize(deserializer); obj.signature = serde::Deserializable::deserialize(deserializer); @@ -2713,7 +2721,7 @@ Circuit::BlackBoxFuncCall::EcdsaSecp256r1 serde::Deserializable template -void serde::Serializable::serialize( - const Circuit::BlackBoxFuncCall::FixedBaseScalarMul& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Program::BlackBoxFuncCall::FixedBaseScalarMul& obj, Serializer& serializer) { serde::Serializable::serialize(obj.low, serializer); serde::Serializable::serialize(obj.high, serializer); @@ -2761,17 +2769,17 @@ void serde::Serializable::seriali template <> template -Circuit::BlackBoxFuncCall::FixedBaseScalarMul serde::Deserializable< - Circuit::BlackBoxFuncCall::FixedBaseScalarMul>::deserialize(Deserializer& deserializer) +Program::BlackBoxFuncCall::FixedBaseScalarMul serde::Deserializable< + Program::BlackBoxFuncCall::FixedBaseScalarMul>::deserialize(Deserializer& deserializer) { - Circuit::BlackBoxFuncCall::FixedBaseScalarMul obj; + Program::BlackBoxFuncCall::FixedBaseScalarMul obj; obj.low = serde::Deserializable::deserialize(deserializer); obj.high = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::EmbeddedCurveAdd& lhs, const BlackBoxFuncCall::EmbeddedCurveAdd& rhs) { @@ -2811,12 +2819,12 @@ inline BlackBoxFuncCall::EmbeddedCurveAdd BlackBoxFuncCall::EmbeddedCurveAdd::bi return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize( - const Circuit::BlackBoxFuncCall::EmbeddedCurveAdd& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Program::BlackBoxFuncCall::EmbeddedCurveAdd& obj, Serializer& serializer) { serde::Serializable::serialize(obj.input1_x, serializer); serde::Serializable::serialize(obj.input1_y, serializer); @@ -2827,10 +2835,10 @@ void serde::Serializable::serialize template <> template -Circuit::BlackBoxFuncCall::EmbeddedCurveAdd serde::Deserializable< - Circuit::BlackBoxFuncCall::EmbeddedCurveAdd>::deserialize(Deserializer& deserializer) +Program::BlackBoxFuncCall::EmbeddedCurveAdd serde::Deserializable< + Program::BlackBoxFuncCall::EmbeddedCurveAdd>::deserialize(Deserializer& deserializer) { - Circuit::BlackBoxFuncCall::EmbeddedCurveAdd obj; + Program::BlackBoxFuncCall::EmbeddedCurveAdd obj; obj.input1_x = serde::Deserializable::deserialize(deserializer); obj.input1_y = serde::Deserializable::deserialize(deserializer); obj.input2_x = serde::Deserializable::deserialize(deserializer); @@ -2839,7 +2847,7 @@ Circuit::BlackBoxFuncCall::EmbeddedCurveAdd serde::Deserializable< return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::Keccak256& lhs, const BlackBoxFuncCall::Keccak256& rhs) { @@ -2869,12 +2877,12 @@ inline BlackBoxFuncCall::Keccak256 BlackBoxFuncCall::Keccak256::bincodeDeseriali return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize( - const Circuit::BlackBoxFuncCall::Keccak256& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Program::BlackBoxFuncCall::Keccak256& obj, Serializer& serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.outputs, serializer); @@ -2882,16 +2890,16 @@ void serde::Serializable::serialize( template <> template -Circuit::BlackBoxFuncCall::Keccak256 serde::Deserializable::deserialize( +Program::BlackBoxFuncCall::Keccak256 serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxFuncCall::Keccak256 obj; + Program::BlackBoxFuncCall::Keccak256 obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::Keccak256VariableLength& lhs, const BlackBoxFuncCall::Keccak256VariableLength& rhs) @@ -2926,12 +2934,12 @@ inline BlackBoxFuncCall::Keccak256VariableLength BlackBoxFuncCall::Keccak256Vari return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize( - const Circuit::BlackBoxFuncCall::Keccak256VariableLength& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Program::BlackBoxFuncCall::Keccak256VariableLength& obj, Serializer& serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.var_message_size, serializer); @@ -2940,17 +2948,17 @@ void serde::Serializable::se template <> template -Circuit::BlackBoxFuncCall::Keccak256VariableLength serde::Deserializable< - Circuit::BlackBoxFuncCall::Keccak256VariableLength>::deserialize(Deserializer& deserializer) +Program::BlackBoxFuncCall::Keccak256VariableLength serde::Deserializable< + Program::BlackBoxFuncCall::Keccak256VariableLength>::deserialize(Deserializer& deserializer) { - Circuit::BlackBoxFuncCall::Keccak256VariableLength obj; + Program::BlackBoxFuncCall::Keccak256VariableLength obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.var_message_size = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::Keccakf1600& lhs, const BlackBoxFuncCall::Keccakf1600& rhs) { @@ -2980,12 +2988,12 @@ inline BlackBoxFuncCall::Keccakf1600 BlackBoxFuncCall::Keccakf1600::bincodeDeser return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize( - const Circuit::BlackBoxFuncCall::Keccakf1600& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Program::BlackBoxFuncCall::Keccakf1600& obj, Serializer& serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.outputs, serializer); @@ -2993,16 +3001,16 @@ void serde::Serializable::serialize( template <> template -Circuit::BlackBoxFuncCall::Keccakf1600 serde::Deserializable::deserialize( +Program::BlackBoxFuncCall::Keccakf1600 serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxFuncCall::Keccakf1600 obj; + Program::BlackBoxFuncCall::Keccakf1600 obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::RecursiveAggregation& lhs, const BlackBoxFuncCall::RecursiveAggregation& rhs) @@ -3040,12 +3048,12 @@ inline BlackBoxFuncCall::RecursiveAggregation BlackBoxFuncCall::RecursiveAggrega return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize( - const Circuit::BlackBoxFuncCall::RecursiveAggregation& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Program::BlackBoxFuncCall::RecursiveAggregation& obj, Serializer& serializer) { serde::Serializable::serialize(obj.verification_key, serializer); serde::Serializable::serialize(obj.proof, serializer); @@ -3055,10 +3063,10 @@ void serde::Serializable::seria template <> template -Circuit::BlackBoxFuncCall::RecursiveAggregation serde::Deserializable< - Circuit::BlackBoxFuncCall::RecursiveAggregation>::deserialize(Deserializer& deserializer) +Program::BlackBoxFuncCall::RecursiveAggregation serde::Deserializable< + Program::BlackBoxFuncCall::RecursiveAggregation>::deserialize(Deserializer& deserializer) { - Circuit::BlackBoxFuncCall::RecursiveAggregation obj; + Program::BlackBoxFuncCall::RecursiveAggregation obj; obj.verification_key = serde::Deserializable::deserialize(deserializer); obj.proof = serde::Deserializable::deserialize(deserializer); obj.public_inputs = serde::Deserializable::deserialize(deserializer); @@ -3066,7 +3074,7 @@ Circuit::BlackBoxFuncCall::RecursiveAggregation serde::Deserializable< return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::BigIntAdd& lhs, const BlackBoxFuncCall::BigIntAdd& rhs) { @@ -3099,12 +3107,12 @@ inline BlackBoxFuncCall::BigIntAdd BlackBoxFuncCall::BigIntAdd::bincodeDeseriali return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize( - const Circuit::BlackBoxFuncCall::BigIntAdd& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Program::BlackBoxFuncCall::BigIntAdd& obj, Serializer& serializer) { serde::Serializable::serialize(obj.lhs, serializer); serde::Serializable::serialize(obj.rhs, serializer); @@ -3113,17 +3121,17 @@ void serde::Serializable::serialize( template <> template -Circuit::BlackBoxFuncCall::BigIntAdd serde::Deserializable::deserialize( +Program::BlackBoxFuncCall::BigIntAdd serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxFuncCall::BigIntAdd obj; + Program::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 { +namespace Program { inline bool operator==(const BlackBoxFuncCall::BigIntSub& lhs, const BlackBoxFuncCall::BigIntSub& rhs) { @@ -3156,12 +3164,12 @@ inline BlackBoxFuncCall::BigIntSub BlackBoxFuncCall::BigIntSub::bincodeDeseriali return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize( - const Circuit::BlackBoxFuncCall::BigIntSub& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Program::BlackBoxFuncCall::BigIntSub& obj, Serializer& serializer) { serde::Serializable::serialize(obj.lhs, serializer); serde::Serializable::serialize(obj.rhs, serializer); @@ -3170,17 +3178,17 @@ void serde::Serializable::serialize( template <> template -Circuit::BlackBoxFuncCall::BigIntSub serde::Deserializable::deserialize( +Program::BlackBoxFuncCall::BigIntSub serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxFuncCall::BigIntSub obj; + Program::BlackBoxFuncCall::BigIntSub obj; obj.lhs = serde::Deserializable::deserialize(deserializer); obj.rhs = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::BigIntMul& lhs, const BlackBoxFuncCall::BigIntMul& rhs) { @@ -3213,12 +3221,12 @@ inline BlackBoxFuncCall::BigIntMul BlackBoxFuncCall::BigIntMul::bincodeDeseriali return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize( - const Circuit::BlackBoxFuncCall::BigIntMul& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Program::BlackBoxFuncCall::BigIntMul& obj, Serializer& serializer) { serde::Serializable::serialize(obj.lhs, serializer); serde::Serializable::serialize(obj.rhs, serializer); @@ -3227,17 +3235,17 @@ void serde::Serializable::serialize( template <> template -Circuit::BlackBoxFuncCall::BigIntMul serde::Deserializable::deserialize( +Program::BlackBoxFuncCall::BigIntMul serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxFuncCall::BigIntMul obj; + Program::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 { +namespace Program { inline bool operator==(const BlackBoxFuncCall::BigIntDiv& lhs, const BlackBoxFuncCall::BigIntDiv& rhs) { @@ -3270,12 +3278,12 @@ inline BlackBoxFuncCall::BigIntDiv BlackBoxFuncCall::BigIntDiv::bincodeDeseriali return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize( - const Circuit::BlackBoxFuncCall::BigIntDiv& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Program::BlackBoxFuncCall::BigIntDiv& obj, Serializer& serializer) { serde::Serializable::serialize(obj.lhs, serializer); serde::Serializable::serialize(obj.rhs, serializer); @@ -3284,17 +3292,17 @@ void serde::Serializable::serialize( template <> template -Circuit::BlackBoxFuncCall::BigIntDiv serde::Deserializable::deserialize( +Program::BlackBoxFuncCall::BigIntDiv serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxFuncCall::BigIntDiv obj; + Program::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 { +namespace Program { inline bool operator==(const BlackBoxFuncCall::BigIntFromLeBytes& lhs, const BlackBoxFuncCall::BigIntFromLeBytes& rhs) { @@ -3328,12 +3336,12 @@ inline BlackBoxFuncCall::BigIntFromLeBytes BlackBoxFuncCall::BigIntFromLeBytes:: return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize( - const Circuit::BlackBoxFuncCall::BigIntFromLeBytes& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Program::BlackBoxFuncCall::BigIntFromLeBytes& obj, Serializer& serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.modulus, serializer); @@ -3342,17 +3350,17 @@ void serde::Serializable::serializ template <> template -Circuit::BlackBoxFuncCall::BigIntFromLeBytes serde::Deserializable< - Circuit::BlackBoxFuncCall::BigIntFromLeBytes>::deserialize(Deserializer& deserializer) +Program::BlackBoxFuncCall::BigIntFromLeBytes serde::Deserializable< + Program::BlackBoxFuncCall::BigIntFromLeBytes>::deserialize(Deserializer& deserializer) { - Circuit::BlackBoxFuncCall::BigIntFromLeBytes obj; + Program::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 { +namespace Program { inline bool operator==(const BlackBoxFuncCall::BigIntToLeBytes& lhs, const BlackBoxFuncCall::BigIntToLeBytes& rhs) { @@ -3383,12 +3391,12 @@ inline BlackBoxFuncCall::BigIntToLeBytes BlackBoxFuncCall::BigIntToLeBytes::binc return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize( - const Circuit::BlackBoxFuncCall::BigIntToLeBytes& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Program::BlackBoxFuncCall::BigIntToLeBytes& obj, Serializer& serializer) { serde::Serializable::serialize(obj.input, serializer); serde::Serializable::serialize(obj.outputs, serializer); @@ -3396,16 +3404,16 @@ void serde::Serializable::serialize( template <> template -Circuit::BlackBoxFuncCall::BigIntToLeBytes serde::Deserializable< - Circuit::BlackBoxFuncCall::BigIntToLeBytes>::deserialize(Deserializer& deserializer) +Program::BlackBoxFuncCall::BigIntToLeBytes serde::Deserializable< + Program::BlackBoxFuncCall::BigIntToLeBytes>::deserialize(Deserializer& deserializer) { - Circuit::BlackBoxFuncCall::BigIntToLeBytes obj; + Program::BlackBoxFuncCall::BigIntToLeBytes obj; obj.input = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::Poseidon2Permutation& lhs, const BlackBoxFuncCall::Poseidon2Permutation& rhs) @@ -3440,12 +3448,12 @@ inline BlackBoxFuncCall::Poseidon2Permutation BlackBoxFuncCall::Poseidon2Permuta return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize( - const Circuit::BlackBoxFuncCall::Poseidon2Permutation& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Program::BlackBoxFuncCall::Poseidon2Permutation& obj, Serializer& serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.outputs, serializer); @@ -3454,17 +3462,17 @@ void serde::Serializable::seria template <> template -Circuit::BlackBoxFuncCall::Poseidon2Permutation serde::Deserializable< - Circuit::BlackBoxFuncCall::Poseidon2Permutation>::deserialize(Deserializer& deserializer) +Program::BlackBoxFuncCall::Poseidon2Permutation serde::Deserializable< + Program::BlackBoxFuncCall::Poseidon2Permutation>::deserialize(Deserializer& deserializer) { - Circuit::BlackBoxFuncCall::Poseidon2Permutation obj; + Program::BlackBoxFuncCall::Poseidon2Permutation obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); obj.len = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::Sha256Compression& lhs, const BlackBoxFuncCall::Sha256Compression& rhs) { @@ -3498,12 +3506,12 @@ inline BlackBoxFuncCall::Sha256Compression BlackBoxFuncCall::Sha256Compression:: return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize( - const Circuit::BlackBoxFuncCall::Sha256Compression& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Program::BlackBoxFuncCall::Sha256Compression& obj, Serializer& serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.hash_values, serializer); @@ -3512,17 +3520,17 @@ void serde::Serializable::serializ template <> template -Circuit::BlackBoxFuncCall::Sha256Compression serde::Deserializable< - Circuit::BlackBoxFuncCall::Sha256Compression>::deserialize(Deserializer& deserializer) +Program::BlackBoxFuncCall::Sha256Compression serde::Deserializable< + Program::BlackBoxFuncCall::Sha256Compression>::deserialize(Deserializer& deserializer) { - Circuit::BlackBoxFuncCall::Sha256Compression obj; + Program::BlackBoxFuncCall::Sha256Compression obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.hash_values = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxOp& lhs, const BlackBoxOp& rhs) { @@ -3549,11 +3557,11 @@ inline BlackBoxOp BlackBoxOp::bincodeDeserialize(std::vector input) return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp& obj, Serializer& serializer) +void serde::Serializable::serialize(const Program::BlackBoxOp& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); @@ -3562,16 +3570,16 @@ void serde::Serializable::serialize(const Circuit::BlackBox template <> template -Circuit::BlackBoxOp serde::Deserializable::deserialize(Deserializer& deserializer) +Program::BlackBoxOp serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Circuit::BlackBoxOp obj; + Program::BlackBoxOp obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxOp::Sha256& lhs, const BlackBoxOp::Sha256& rhs) { @@ -3601,11 +3609,11 @@ inline BlackBoxOp::Sha256 BlackBoxOp::Sha256::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::Sha256& obj, +void serde::Serializable::serialize(const Program::BlackBoxOp::Sha256& obj, Serializer& serializer) { serde::Serializable::serialize(obj.message, serializer); @@ -3614,15 +3622,15 @@ void serde::Serializable::serialize(const Circuit:: template <> template -Circuit::BlackBoxOp::Sha256 serde::Deserializable::deserialize(Deserializer& deserializer) +Program::BlackBoxOp::Sha256 serde::Deserializable::deserialize(Deserializer& deserializer) { - Circuit::BlackBoxOp::Sha256 obj; + Program::BlackBoxOp::Sha256 obj; obj.message = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxOp::Blake2s& lhs, const BlackBoxOp::Blake2s& rhs) { @@ -3652,11 +3660,11 @@ inline BlackBoxOp::Blake2s BlackBoxOp::Blake2s::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::Blake2s& obj, +void serde::Serializable::serialize(const Program::BlackBoxOp::Blake2s& obj, Serializer& serializer) { serde::Serializable::serialize(obj.message, serializer); @@ -3665,16 +3673,16 @@ void serde::Serializable::serialize(const Circuit: template <> template -Circuit::BlackBoxOp::Blake2s serde::Deserializable::deserialize( +Program::BlackBoxOp::Blake2s serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxOp::Blake2s obj; + Program::BlackBoxOp::Blake2s obj; obj.message = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxOp::Blake3& lhs, const BlackBoxOp::Blake3& rhs) { @@ -3704,11 +3712,11 @@ inline BlackBoxOp::Blake3 BlackBoxOp::Blake3::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::Blake3& obj, +void serde::Serializable::serialize(const Program::BlackBoxOp::Blake3& obj, Serializer& serializer) { serde::Serializable::serialize(obj.message, serializer); @@ -3717,15 +3725,15 @@ void serde::Serializable::serialize(const Circuit:: template <> template -Circuit::BlackBoxOp::Blake3 serde::Deserializable::deserialize(Deserializer& deserializer) +Program::BlackBoxOp::Blake3 serde::Deserializable::deserialize(Deserializer& deserializer) { - Circuit::BlackBoxOp::Blake3 obj; + Program::BlackBoxOp::Blake3 obj; obj.message = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxOp::Keccak256& lhs, const BlackBoxOp::Keccak256& rhs) { @@ -3755,11 +3763,11 @@ inline BlackBoxOp::Keccak256 BlackBoxOp::Keccak256::bincodeDeserialize(std::vect return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::Keccak256& obj, +void serde::Serializable::serialize(const Program::BlackBoxOp::Keccak256& obj, Serializer& serializer) { serde::Serializable::serialize(obj.message, serializer); @@ -3768,16 +3776,16 @@ void serde::Serializable::serialize(const Circui template <> template -Circuit::BlackBoxOp::Keccak256 serde::Deserializable::deserialize( +Program::BlackBoxOp::Keccak256 serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxOp::Keccak256 obj; + Program::BlackBoxOp::Keccak256 obj; obj.message = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxOp::Keccakf1600& lhs, const BlackBoxOp::Keccakf1600& rhs) { @@ -3807,11 +3815,11 @@ inline BlackBoxOp::Keccakf1600 BlackBoxOp::Keccakf1600::bincodeDeserialize(std:: return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::Keccakf1600& obj, +void serde::Serializable::serialize(const Program::BlackBoxOp::Keccakf1600& obj, Serializer& serializer) { serde::Serializable::serialize(obj.message, serializer); @@ -3820,16 +3828,16 @@ void serde::Serializable::serialize(const Circ template <> template -Circuit::BlackBoxOp::Keccakf1600 serde::Deserializable::deserialize( +Program::BlackBoxOp::Keccakf1600 serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxOp::Keccakf1600 obj; + Program::BlackBoxOp::Keccakf1600 obj; obj.message = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxOp::EcdsaSecp256k1& lhs, const BlackBoxOp::EcdsaSecp256k1& rhs) { @@ -3868,11 +3876,11 @@ inline BlackBoxOp::EcdsaSecp256k1 BlackBoxOp::EcdsaSecp256k1::bincodeDeserialize return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::EcdsaSecp256k1& obj, +void serde::Serializable::serialize(const Program::BlackBoxOp::EcdsaSecp256k1& obj, Serializer& serializer) { serde::Serializable::serialize(obj.hashed_msg, serializer); @@ -3884,10 +3892,10 @@ void serde::Serializable::serialize(const C template <> template -Circuit::BlackBoxOp::EcdsaSecp256k1 serde::Deserializable::deserialize( +Program::BlackBoxOp::EcdsaSecp256k1 serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxOp::EcdsaSecp256k1 obj; + Program::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); @@ -3896,7 +3904,7 @@ Circuit::BlackBoxOp::EcdsaSecp256k1 serde::Deserializable template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::EcdsaSecp256r1& obj, +void serde::Serializable::serialize(const Program::BlackBoxOp::EcdsaSecp256r1& obj, Serializer& serializer) { serde::Serializable::serialize(obj.hashed_msg, serializer); @@ -3951,10 +3959,10 @@ void serde::Serializable::serialize(const C template <> template -Circuit::BlackBoxOp::EcdsaSecp256r1 serde::Deserializable::deserialize( +Program::BlackBoxOp::EcdsaSecp256r1 serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxOp::EcdsaSecp256r1 obj; + Program::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); @@ -3963,7 +3971,7 @@ Circuit::BlackBoxOp::EcdsaSecp256r1 serde::Deserializable template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::SchnorrVerify& obj, +void serde::Serializable::serialize(const Program::BlackBoxOp::SchnorrVerify& obj, Serializer& serializer) { serde::Serializable::serialize(obj.public_key_x, serializer); @@ -4018,10 +4026,10 @@ void serde::Serializable::serialize(const Ci template <> template -Circuit::BlackBoxOp::SchnorrVerify serde::Deserializable::deserialize( +Program::BlackBoxOp::SchnorrVerify serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxOp::SchnorrVerify obj; + Program::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); @@ -4030,7 +4038,7 @@ Circuit::BlackBoxOp::SchnorrVerify serde::Deserializable template -void serde::Serializable::serialize( - const Circuit::BlackBoxOp::PedersenCommitment& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Program::BlackBoxOp::PedersenCommitment& obj, Serializer& serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.domain_separator, serializer); @@ -4077,17 +4085,17 @@ void serde::Serializable::serialize( template <> template -Circuit::BlackBoxOp::PedersenCommitment serde::Deserializable::deserialize( +Program::BlackBoxOp::PedersenCommitment serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxOp::PedersenCommitment obj; + Program::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 { +namespace Program { inline bool operator==(const BlackBoxOp::PedersenHash& lhs, const BlackBoxOp::PedersenHash& rhs) { @@ -4120,11 +4128,11 @@ inline BlackBoxOp::PedersenHash BlackBoxOp::PedersenHash::bincodeDeserialize(std return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::PedersenHash& obj, +void serde::Serializable::serialize(const Program::BlackBoxOp::PedersenHash& obj, Serializer& serializer) { serde::Serializable::serialize(obj.inputs, serializer); @@ -4134,17 +4142,17 @@ void serde::Serializable::serialize(const Cir template <> template -Circuit::BlackBoxOp::PedersenHash serde::Deserializable::deserialize( +Program::BlackBoxOp::PedersenHash serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxOp::PedersenHash obj; + Program::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 { +namespace Program { inline bool operator==(const BlackBoxOp::FixedBaseScalarMul& lhs, const BlackBoxOp::FixedBaseScalarMul& rhs) { @@ -4177,12 +4185,12 @@ inline BlackBoxOp::FixedBaseScalarMul BlackBoxOp::FixedBaseScalarMul::bincodeDes return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize( - const Circuit::BlackBoxOp::FixedBaseScalarMul& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Program::BlackBoxOp::FixedBaseScalarMul& obj, Serializer& serializer) { serde::Serializable::serialize(obj.low, serializer); serde::Serializable::serialize(obj.high, serializer); @@ -4191,17 +4199,17 @@ void serde::Serializable::serialize( template <> template -Circuit::BlackBoxOp::FixedBaseScalarMul serde::Deserializable::deserialize( +Program::BlackBoxOp::FixedBaseScalarMul serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxOp::FixedBaseScalarMul obj; + Program::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 { +namespace Program { inline bool operator==(const BlackBoxOp::EmbeddedCurveAdd& lhs, const BlackBoxOp::EmbeddedCurveAdd& rhs) { @@ -4240,12 +4248,12 @@ inline BlackBoxOp::EmbeddedCurveAdd BlackBoxOp::EmbeddedCurveAdd::bincodeDeseria return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize( - const Circuit::BlackBoxOp::EmbeddedCurveAdd& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Program::BlackBoxOp::EmbeddedCurveAdd& obj, Serializer& serializer) { serde::Serializable::serialize(obj.input1_x, serializer); serde::Serializable::serialize(obj.input1_y, serializer); @@ -4256,10 +4264,10 @@ void serde::Serializable::serialize( template <> template -Circuit::BlackBoxOp::EmbeddedCurveAdd serde::Deserializable::deserialize( +Program::BlackBoxOp::EmbeddedCurveAdd serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxOp::EmbeddedCurveAdd obj; + Program::BlackBoxOp::EmbeddedCurveAdd obj; obj.input1_x = serde::Deserializable::deserialize(deserializer); obj.input1_y = serde::Deserializable::deserialize(deserializer); obj.input2_x = serde::Deserializable::deserialize(deserializer); @@ -4268,7 +4276,7 @@ Circuit::BlackBoxOp::EmbeddedCurveAdd serde::Deserializable template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::BigIntAdd& obj, +void serde::Serializable::serialize(const Program::BlackBoxOp::BigIntAdd& obj, Serializer& serializer) { serde::Serializable::serialize(obj.lhs, serializer); @@ -4315,17 +4323,17 @@ void serde::Serializable::serialize(const Circui template <> template -Circuit::BlackBoxOp::BigIntAdd serde::Deserializable::deserialize( +Program::BlackBoxOp::BigIntAdd serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxOp::BigIntAdd obj; + Program::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 { +namespace Program { inline bool operator==(const BlackBoxOp::BigIntSub& lhs, const BlackBoxOp::BigIntSub& rhs) { @@ -4358,11 +4366,11 @@ inline BlackBoxOp::BigIntSub BlackBoxOp::BigIntSub::bincodeDeserialize(std::vect return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::BigIntSub& obj, +void serde::Serializable::serialize(const Program::BlackBoxOp::BigIntSub& obj, Serializer& serializer) { serde::Serializable::serialize(obj.lhs, serializer); @@ -4372,17 +4380,17 @@ void serde::Serializable::serialize(const Circui template <> template -Circuit::BlackBoxOp::BigIntSub serde::Deserializable::deserialize( +Program::BlackBoxOp::BigIntSub serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxOp::BigIntSub obj; + Program::BlackBoxOp::BigIntSub obj; obj.lhs = serde::Deserializable::deserialize(deserializer); obj.rhs = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxOp::BigIntMul& lhs, const BlackBoxOp::BigIntMul& rhs) { @@ -4415,11 +4423,11 @@ inline BlackBoxOp::BigIntMul BlackBoxOp::BigIntMul::bincodeDeserialize(std::vect return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::BigIntMul& obj, +void serde::Serializable::serialize(const Program::BlackBoxOp::BigIntMul& obj, Serializer& serializer) { serde::Serializable::serialize(obj.lhs, serializer); @@ -4429,17 +4437,17 @@ void serde::Serializable::serialize(const Circui template <> template -Circuit::BlackBoxOp::BigIntMul serde::Deserializable::deserialize( +Program::BlackBoxOp::BigIntMul serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxOp::BigIntMul obj; + Program::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 { +namespace Program { inline bool operator==(const BlackBoxOp::BigIntDiv& lhs, const BlackBoxOp::BigIntDiv& rhs) { @@ -4472,11 +4480,11 @@ inline BlackBoxOp::BigIntDiv BlackBoxOp::BigIntDiv::bincodeDeserialize(std::vect return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::BigIntDiv& obj, +void serde::Serializable::serialize(const Program::BlackBoxOp::BigIntDiv& obj, Serializer& serializer) { serde::Serializable::serialize(obj.lhs, serializer); @@ -4486,17 +4494,17 @@ void serde::Serializable::serialize(const Circui template <> template -Circuit::BlackBoxOp::BigIntDiv serde::Deserializable::deserialize( +Program::BlackBoxOp::BigIntDiv serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxOp::BigIntDiv obj; + Program::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 { +namespace Program { inline bool operator==(const BlackBoxOp::BigIntFromLeBytes& lhs, const BlackBoxOp::BigIntFromLeBytes& rhs) { @@ -4529,12 +4537,12 @@ inline BlackBoxOp::BigIntFromLeBytes BlackBoxOp::BigIntFromLeBytes::bincodeDeser return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize( - const Circuit::BlackBoxOp::BigIntFromLeBytes& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Program::BlackBoxOp::BigIntFromLeBytes& obj, Serializer& serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.modulus, serializer); @@ -4543,17 +4551,17 @@ void serde::Serializable::serialize( template <> template -Circuit::BlackBoxOp::BigIntFromLeBytes serde::Deserializable::deserialize( +Program::BlackBoxOp::BigIntFromLeBytes serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxOp::BigIntFromLeBytes obj; + Program::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 { +namespace Program { inline bool operator==(const BlackBoxOp::BigIntToLeBytes& lhs, const BlackBoxOp::BigIntToLeBytes& rhs) { @@ -4583,12 +4591,12 @@ inline BlackBoxOp::BigIntToLeBytes BlackBoxOp::BigIntToLeBytes::bincodeDeseriali return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize( - const Circuit::BlackBoxOp::BigIntToLeBytes& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Program::BlackBoxOp::BigIntToLeBytes& obj, Serializer& serializer) { serde::Serializable::serialize(obj.input, serializer); serde::Serializable::serialize(obj.output, serializer); @@ -4596,16 +4604,16 @@ void serde::Serializable::serialize( template <> template -Circuit::BlackBoxOp::BigIntToLeBytes serde::Deserializable::deserialize( +Program::BlackBoxOp::BigIntToLeBytes serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxOp::BigIntToLeBytes obj; + Program::BlackBoxOp::BigIntToLeBytes obj; obj.input = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxOp::Poseidon2Permutation& lhs, const BlackBoxOp::Poseidon2Permutation& rhs) { @@ -4638,12 +4646,12 @@ inline BlackBoxOp::Poseidon2Permutation BlackBoxOp::Poseidon2Permutation::bincod return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize( - const Circuit::BlackBoxOp::Poseidon2Permutation& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Program::BlackBoxOp::Poseidon2Permutation& obj, Serializer& serializer) { serde::Serializable::serialize(obj.message, serializer); serde::Serializable::serialize(obj.output, serializer); @@ -4652,17 +4660,17 @@ void serde::Serializable::serialize( template <> template -Circuit::BlackBoxOp::Poseidon2Permutation serde::Deserializable::deserialize( +Program::BlackBoxOp::Poseidon2Permutation serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxOp::Poseidon2Permutation obj; + Program::BlackBoxOp::Poseidon2Permutation obj; obj.message = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); obj.len = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxOp::Sha256Compression& lhs, const BlackBoxOp::Sha256Compression& rhs) { @@ -4695,12 +4703,12 @@ inline BlackBoxOp::Sha256Compression BlackBoxOp::Sha256Compression::bincodeDeser return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize( - const Circuit::BlackBoxOp::Sha256Compression& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Program::BlackBoxOp::Sha256Compression& obj, Serializer& serializer) { serde::Serializable::serialize(obj.input, serializer); serde::Serializable::serialize(obj.hash_values, serializer); @@ -4709,17 +4717,17 @@ void serde::Serializable::serialize( template <> template -Circuit::BlackBoxOp::Sha256Compression serde::Deserializable::deserialize( +Program::BlackBoxOp::Sha256Compression serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxOp::Sha256Compression obj; + Program::BlackBoxOp::Sha256Compression obj; obj.input = serde::Deserializable::deserialize(deserializer); obj.hash_values = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlockId& lhs, const BlockId& rhs) { @@ -4746,11 +4754,11 @@ inline BlockId BlockId::bincodeDeserialize(std::vector input) return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlockId& obj, Serializer& serializer) +void serde::Serializable::serialize(const Program::BlockId& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); @@ -4759,16 +4767,16 @@ void serde::Serializable::serialize(const Circuit::BlockId& ob template <> template -Circuit::BlockId serde::Deserializable::deserialize(Deserializer& deserializer) +Program::BlockId serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Circuit::BlockId obj; + Program::BlockId obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Brillig& lhs, const Brillig& rhs) { @@ -4804,11 +4812,11 @@ inline Brillig Brillig::bincodeDeserialize(std::vector input) return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Brillig& obj, Serializer& serializer) +void serde::Serializable::serialize(const Program::Brillig& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.inputs, serializer); @@ -4820,10 +4828,10 @@ void serde::Serializable::serialize(const Circuit::Brillig& ob template <> template -Circuit::Brillig serde::Deserializable::deserialize(Deserializer& deserializer) +Program::Brillig serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Circuit::Brillig obj; + Program::Brillig obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); obj.bytecode = serde::Deserializable::deserialize(deserializer); @@ -4832,7 +4840,7 @@ Circuit::Brillig serde::Deserializable::deserialize(Deserializ return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligInputs& lhs, const BrilligInputs& rhs) { @@ -4859,11 +4867,11 @@ inline BrilligInputs BrilligInputs::bincodeDeserialize(std::vector inpu return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligInputs& obj, Serializer& serializer) +void serde::Serializable::serialize(const Program::BrilligInputs& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); @@ -4872,16 +4880,16 @@ void serde::Serializable::serialize(const Circuit::Brill template <> template -Circuit::BrilligInputs serde::Deserializable::deserialize(Deserializer& deserializer) +Program::BrilligInputs serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Circuit::BrilligInputs obj; + Program::BrilligInputs obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligInputs::Single& lhs, const BrilligInputs::Single& rhs) { @@ -4908,11 +4916,11 @@ inline BrilligInputs::Single BrilligInputs::Single::bincodeDeserialize(std::vect return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligInputs::Single& obj, +void serde::Serializable::serialize(const Program::BrilligInputs::Single& obj, Serializer& serializer) { serde::Serializable::serialize(obj.value, serializer); @@ -4920,15 +4928,15 @@ void serde::Serializable::serialize(const Circui template <> template -Circuit::BrilligInputs::Single serde::Deserializable::deserialize( +Program::BrilligInputs::Single serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BrilligInputs::Single obj; + Program::BrilligInputs::Single obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligInputs::Array& lhs, const BrilligInputs::Array& rhs) { @@ -4955,11 +4963,11 @@ inline BrilligInputs::Array BrilligInputs::Array::bincodeDeserialize(std::vector return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligInputs::Array& obj, +void serde::Serializable::serialize(const Program::BrilligInputs::Array& obj, Serializer& serializer) { serde::Serializable::serialize(obj.value, serializer); @@ -4967,15 +4975,15 @@ void serde::Serializable::serialize(const Circuit template <> template -Circuit::BrilligInputs::Array serde::Deserializable::deserialize( +Program::BrilligInputs::Array serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BrilligInputs::Array obj; + Program::BrilligInputs::Array obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligInputs::MemoryArray& lhs, const BrilligInputs::MemoryArray& rhs) { @@ -5002,11 +5010,11 @@ inline BrilligInputs::MemoryArray BrilligInputs::MemoryArray::bincodeDeserialize return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligInputs::MemoryArray& obj, +void serde::Serializable::serialize(const Program::BrilligInputs::MemoryArray& obj, Serializer& serializer) { serde::Serializable::serialize(obj.value, serializer); @@ -5014,15 +5022,15 @@ void serde::Serializable::serialize(const C template <> template -Circuit::BrilligInputs::MemoryArray serde::Deserializable::deserialize( +Program::BrilligInputs::MemoryArray serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BrilligInputs::MemoryArray obj; + Program::BrilligInputs::MemoryArray obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode& lhs, const BrilligOpcode& rhs) { @@ -5049,11 +5057,11 @@ inline BrilligOpcode BrilligOpcode::bincodeDeserialize(std::vector inpu return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOpcode& obj, Serializer& serializer) +void serde::Serializable::serialize(const Program::BrilligOpcode& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); @@ -5062,16 +5070,16 @@ void serde::Serializable::serialize(const Circuit::Brill template <> template -Circuit::BrilligOpcode serde::Deserializable::deserialize(Deserializer& deserializer) +Program::BrilligOpcode serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Circuit::BrilligOpcode obj; + Program::BrilligOpcode obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::BinaryFieldOp& lhs, const BrilligOpcode::BinaryFieldOp& rhs) { @@ -5107,12 +5115,12 @@ inline BrilligOpcode::BinaryFieldOp BrilligOpcode::BinaryFieldOp::bincodeDeseria return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize( - const Circuit::BrilligOpcode::BinaryFieldOp& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Program::BrilligOpcode::BinaryFieldOp& obj, Serializer& serializer) { serde::Serializable::serialize(obj.destination, serializer); serde::Serializable::serialize(obj.op, serializer); @@ -5122,10 +5130,10 @@ void serde::Serializable::serialize( template <> template -Circuit::BrilligOpcode::BinaryFieldOp serde::Deserializable::deserialize( +Program::BrilligOpcode::BinaryFieldOp serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BrilligOpcode::BinaryFieldOp obj; + Program::BrilligOpcode::BinaryFieldOp obj; obj.destination = serde::Deserializable::deserialize(deserializer); obj.op = serde::Deserializable::deserialize(deserializer); obj.lhs = serde::Deserializable::deserialize(deserializer); @@ -5133,7 +5141,7 @@ Circuit::BrilligOpcode::BinaryFieldOp serde::Deserializable template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::BinaryIntOp& obj, +void serde::Serializable::serialize(const Program::BrilligOpcode::BinaryIntOp& obj, Serializer& serializer) { serde::Serializable::serialize(obj.destination, serializer); @@ -5188,10 +5196,10 @@ void serde::Serializable::serialize(const C template <> template -Circuit::BrilligOpcode::BinaryIntOp serde::Deserializable::deserialize( +Program::BrilligOpcode::BinaryIntOp serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BrilligOpcode::BinaryIntOp obj; + Program::BrilligOpcode::BinaryIntOp obj; obj.destination = serde::Deserializable::deserialize(deserializer); obj.op = serde::Deserializable::deserialize(deserializer); obj.bit_size = serde::Deserializable::deserialize(deserializer); @@ -5200,7 +5208,7 @@ Circuit::BrilligOpcode::BinaryIntOp serde::Deserializable template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::Cast& obj, +void serde::Serializable::serialize(const Program::BrilligOpcode::Cast& obj, Serializer& serializer) { serde::Serializable::serialize(obj.destination, serializer); @@ -5247,17 +5255,17 @@ void serde::Serializable::serialize(const Circuit: template <> template -Circuit::BrilligOpcode::Cast serde::Deserializable::deserialize( +Program::BrilligOpcode::Cast serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BrilligOpcode::Cast obj; + Program::BrilligOpcode::Cast obj; obj.destination = serde::Deserializable::deserialize(deserializer); obj.source = serde::Deserializable::deserialize(deserializer); obj.bit_size = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::JumpIfNot& lhs, const BrilligOpcode::JumpIfNot& rhs) { @@ -5287,11 +5295,11 @@ inline BrilligOpcode::JumpIfNot BrilligOpcode::JumpIfNot::bincodeDeserialize(std return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::JumpIfNot& obj, +void serde::Serializable::serialize(const Program::BrilligOpcode::JumpIfNot& obj, Serializer& serializer) { serde::Serializable::serialize(obj.condition, serializer); @@ -5300,16 +5308,16 @@ void serde::Serializable::serialize(const Cir template <> template -Circuit::BrilligOpcode::JumpIfNot serde::Deserializable::deserialize( +Program::BrilligOpcode::JumpIfNot serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BrilligOpcode::JumpIfNot obj; + Program::BrilligOpcode::JumpIfNot obj; obj.condition = serde::Deserializable::deserialize(deserializer); obj.location = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::JumpIf& lhs, const BrilligOpcode::JumpIf& rhs) { @@ -5339,11 +5347,11 @@ inline BrilligOpcode::JumpIf BrilligOpcode::JumpIf::bincodeDeserialize(std::vect return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::JumpIf& obj, +void serde::Serializable::serialize(const Program::BrilligOpcode::JumpIf& obj, Serializer& serializer) { serde::Serializable::serialize(obj.condition, serializer); @@ -5352,16 +5360,16 @@ void serde::Serializable::serialize(const Circui template <> template -Circuit::BrilligOpcode::JumpIf serde::Deserializable::deserialize( +Program::BrilligOpcode::JumpIf serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BrilligOpcode::JumpIf obj; + Program::BrilligOpcode::JumpIf obj; obj.condition = serde::Deserializable::deserialize(deserializer); obj.location = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::Jump& lhs, const BrilligOpcode::Jump& rhs) { @@ -5388,11 +5396,11 @@ inline BrilligOpcode::Jump BrilligOpcode::Jump::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::Jump& obj, +void serde::Serializable::serialize(const Program::BrilligOpcode::Jump& obj, Serializer& serializer) { serde::Serializable::serialize(obj.location, serializer); @@ -5400,15 +5408,15 @@ void serde::Serializable::serialize(const Circuit: template <> template -Circuit::BrilligOpcode::Jump serde::Deserializable::deserialize( +Program::BrilligOpcode::Jump serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BrilligOpcode::Jump obj; + Program::BrilligOpcode::Jump obj; obj.location = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::CalldataCopy& lhs, const BrilligOpcode::CalldataCopy& rhs) { @@ -5441,12 +5449,12 @@ inline BrilligOpcode::CalldataCopy BrilligOpcode::CalldataCopy::bincodeDeseriali return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize( - const Circuit::BrilligOpcode::CalldataCopy& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Program::BrilligOpcode::CalldataCopy& obj, Serializer& serializer) { serde::Serializable::serialize(obj.destination_address, serializer); serde::Serializable::serialize(obj.size, serializer); @@ -5455,17 +5463,17 @@ void serde::Serializable::serialize( template <> template -Circuit::BrilligOpcode::CalldataCopy serde::Deserializable::deserialize( +Program::BrilligOpcode::CalldataCopy serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BrilligOpcode::CalldataCopy obj; + Program::BrilligOpcode::CalldataCopy obj; obj.destination_address = serde::Deserializable::deserialize(deserializer); obj.size = serde::Deserializable::deserialize(deserializer); obj.offset = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::Call& lhs, const BrilligOpcode::Call& rhs) { @@ -5492,11 +5500,11 @@ inline BrilligOpcode::Call BrilligOpcode::Call::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::Call& obj, +void serde::Serializable::serialize(const Program::BrilligOpcode::Call& obj, Serializer& serializer) { serde::Serializable::serialize(obj.location, serializer); @@ -5504,15 +5512,15 @@ void serde::Serializable::serialize(const Circuit: template <> template -Circuit::BrilligOpcode::Call serde::Deserializable::deserialize( +Program::BrilligOpcode::Call serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BrilligOpcode::Call obj; + Program::BrilligOpcode::Call obj; obj.location = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::Const& lhs, const BrilligOpcode::Const& rhs) { @@ -5545,11 +5553,11 @@ inline BrilligOpcode::Const BrilligOpcode::Const::bincodeDeserialize(std::vector return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::Const& obj, +void serde::Serializable::serialize(const Program::BrilligOpcode::Const& obj, Serializer& serializer) { serde::Serializable::serialize(obj.destination, serializer); @@ -5559,17 +5567,17 @@ void serde::Serializable::serialize(const Circuit template <> template -Circuit::BrilligOpcode::Const serde::Deserializable::deserialize( +Program::BrilligOpcode::Const serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BrilligOpcode::Const obj; + Program::BrilligOpcode::Const obj; obj.destination = serde::Deserializable::deserialize(deserializer); obj.bit_size = serde::Deserializable::deserialize(deserializer); obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::Return& lhs, const BrilligOpcode::Return& rhs) { @@ -5593,24 +5601,24 @@ inline BrilligOpcode::Return BrilligOpcode::Return::bincodeDeserialize(std::vect return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::Return& obj, +void serde::Serializable::serialize(const Program::BrilligOpcode::Return& obj, Serializer& serializer) {} template <> template -Circuit::BrilligOpcode::Return serde::Deserializable::deserialize( +Program::BrilligOpcode::Return serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BrilligOpcode::Return obj; + Program::BrilligOpcode::Return obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::ForeignCall& lhs, const BrilligOpcode::ForeignCall& rhs) { @@ -5649,11 +5657,11 @@ inline BrilligOpcode::ForeignCall BrilligOpcode::ForeignCall::bincodeDeserialize return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::ForeignCall& obj, +void serde::Serializable::serialize(const Program::BrilligOpcode::ForeignCall& obj, Serializer& serializer) { serde::Serializable::serialize(obj.function, serializer); @@ -5665,10 +5673,10 @@ void serde::Serializable::serialize(const C template <> template -Circuit::BrilligOpcode::ForeignCall serde::Deserializable::deserialize( +Program::BrilligOpcode::ForeignCall serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BrilligOpcode::ForeignCall obj; + Program::BrilligOpcode::ForeignCall obj; obj.function = serde::Deserializable::deserialize(deserializer); obj.destinations = serde::Deserializable::deserialize(deserializer); obj.destination_value_types = @@ -5678,7 +5686,7 @@ Circuit::BrilligOpcode::ForeignCall serde::Deserializable template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::Mov& obj, +void serde::Serializable::serialize(const Program::BrilligOpcode::Mov& obj, Serializer& serializer) { serde::Serializable::serialize(obj.destination, serializer); @@ -5721,15 +5729,15 @@ void serde::Serializable::serialize(const Circuit:: template <> template -Circuit::BrilligOpcode::Mov serde::Deserializable::deserialize(Deserializer& deserializer) +Program::BrilligOpcode::Mov serde::Deserializable::deserialize(Deserializer& deserializer) { - Circuit::BrilligOpcode::Mov obj; + Program::BrilligOpcode::Mov obj; obj.destination = serde::Deserializable::deserialize(deserializer); obj.source = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::Load& lhs, const BrilligOpcode::Load& rhs) { @@ -5759,11 +5767,11 @@ inline BrilligOpcode::Load BrilligOpcode::Load::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::Load& obj, +void serde::Serializable::serialize(const Program::BrilligOpcode::Load& obj, Serializer& serializer) { serde::Serializable::serialize(obj.destination, serializer); @@ -5772,16 +5780,16 @@ void serde::Serializable::serialize(const Circuit: template <> template -Circuit::BrilligOpcode::Load serde::Deserializable::deserialize( +Program::BrilligOpcode::Load serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BrilligOpcode::Load obj; + Program::BrilligOpcode::Load obj; obj.destination = serde::Deserializable::deserialize(deserializer); obj.source_pointer = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::Store& lhs, const BrilligOpcode::Store& rhs) { @@ -5811,11 +5819,11 @@ inline BrilligOpcode::Store BrilligOpcode::Store::bincodeDeserialize(std::vector return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::Store& obj, +void serde::Serializable::serialize(const Program::BrilligOpcode::Store& obj, Serializer& serializer) { serde::Serializable::serialize(obj.destination_pointer, serializer); @@ -5824,16 +5832,16 @@ void serde::Serializable::serialize(const Circuit template <> template -Circuit::BrilligOpcode::Store serde::Deserializable::deserialize( +Program::BrilligOpcode::Store serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BrilligOpcode::Store obj; + Program::BrilligOpcode::Store obj; obj.destination_pointer = serde::Deserializable::deserialize(deserializer); obj.source = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::BlackBox& lhs, const BrilligOpcode::BlackBox& rhs) { @@ -5860,11 +5868,11 @@ inline BrilligOpcode::BlackBox BrilligOpcode::BlackBox::bincodeDeserialize(std:: return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::BlackBox& obj, +void serde::Serializable::serialize(const Program::BrilligOpcode::BlackBox& obj, Serializer& serializer) { serde::Serializable::serialize(obj.value, serializer); @@ -5872,15 +5880,15 @@ void serde::Serializable::serialize(const Circ template <> template -Circuit::BrilligOpcode::BlackBox serde::Deserializable::deserialize( +Program::BrilligOpcode::BlackBox serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BrilligOpcode::BlackBox obj; + Program::BrilligOpcode::BlackBox obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::Trap& lhs, const BrilligOpcode::Trap& rhs) { @@ -5904,24 +5912,24 @@ inline BrilligOpcode::Trap BrilligOpcode::Trap::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::Trap& obj, +void serde::Serializable::serialize(const Program::BrilligOpcode::Trap& obj, Serializer& serializer) {} template <> template -Circuit::BrilligOpcode::Trap serde::Deserializable::deserialize( +Program::BrilligOpcode::Trap serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BrilligOpcode::Trap obj; + Program::BrilligOpcode::Trap obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::Stop& lhs, const BrilligOpcode::Stop& rhs) { @@ -5951,11 +5959,11 @@ inline BrilligOpcode::Stop BrilligOpcode::Stop::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::Stop& obj, +void serde::Serializable::serialize(const Program::BrilligOpcode::Stop& obj, Serializer& serializer) { serde::Serializable::serialize(obj.return_data_offset, serializer); @@ -5964,16 +5972,16 @@ void serde::Serializable::serialize(const Circuit: template <> template -Circuit::BrilligOpcode::Stop serde::Deserializable::deserialize( +Program::BrilligOpcode::Stop serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BrilligOpcode::Stop obj; + Program::BrilligOpcode::Stop obj; obj.return_data_offset = serde::Deserializable::deserialize(deserializer); obj.return_data_size = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOutputs& lhs, const BrilligOutputs& rhs) { @@ -6000,11 +6008,11 @@ inline BrilligOutputs BrilligOutputs::bincodeDeserialize(std::vector in return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOutputs& obj, Serializer& serializer) +void serde::Serializable::serialize(const Program::BrilligOutputs& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); @@ -6013,16 +6021,16 @@ void serde::Serializable::serialize(const Circuit::Bril template <> template -Circuit::BrilligOutputs serde::Deserializable::deserialize(Deserializer& deserializer) +Program::BrilligOutputs serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Circuit::BrilligOutputs obj; + Program::BrilligOutputs obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOutputs::Simple& lhs, const BrilligOutputs::Simple& rhs) { @@ -6049,11 +6057,11 @@ inline BrilligOutputs::Simple BrilligOutputs::Simple::bincodeDeserialize(std::ve return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOutputs::Simple& obj, +void serde::Serializable::serialize(const Program::BrilligOutputs::Simple& obj, Serializer& serializer) { serde::Serializable::serialize(obj.value, serializer); @@ -6061,15 +6069,15 @@ void serde::Serializable::serialize(const Circu template <> template -Circuit::BrilligOutputs::Simple serde::Deserializable::deserialize( +Program::BrilligOutputs::Simple serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BrilligOutputs::Simple obj; + Program::BrilligOutputs::Simple obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOutputs::Array& lhs, const BrilligOutputs::Array& rhs) { @@ -6096,11 +6104,11 @@ inline BrilligOutputs::Array BrilligOutputs::Array::bincodeDeserialize(std::vect return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOutputs::Array& obj, +void serde::Serializable::serialize(const Program::BrilligOutputs::Array& obj, Serializer& serializer) { serde::Serializable::serialize(obj.value, serializer); @@ -6108,15 +6116,15 @@ void serde::Serializable::serialize(const Circui template <> template -Circuit::BrilligOutputs::Array serde::Deserializable::deserialize( +Program::BrilligOutputs::Array serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BrilligOutputs::Array obj; + Program::BrilligOutputs::Array obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Circuit& lhs, const Circuit& rhs) { @@ -6164,11 +6172,11 @@ inline Circuit Circuit::bincodeDeserialize(std::vector input) return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Circuit& obj, Serializer& serializer) +void serde::Serializable::serialize(const Program::Circuit& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.current_witness_index, serializer); @@ -6184,10 +6192,10 @@ void serde::Serializable::serialize(const Circuit::Circuit& ob template <> template -Circuit::Circuit serde::Deserializable::deserialize(Deserializer& deserializer) +Program::Circuit serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Circuit::Circuit obj; + Program::Circuit obj; obj.current_witness_index = serde::Deserializable::deserialize(deserializer); obj.opcodes = serde::Deserializable::deserialize(deserializer); obj.expression_width = serde::Deserializable::deserialize(deserializer); @@ -6200,7 +6208,7 @@ Circuit::Circuit serde::Deserializable::deserialize(Deserializ return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Directive& lhs, const Directive& rhs) { @@ -6227,11 +6235,11 @@ inline Directive Directive::bincodeDeserialize(std::vector input) return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Directive& obj, Serializer& serializer) +void serde::Serializable::serialize(const Program::Directive& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); @@ -6240,16 +6248,16 @@ void serde::Serializable::serialize(const Circuit::Directive template <> template -Circuit::Directive serde::Deserializable::deserialize(Deserializer& deserializer) +Program::Directive serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Circuit::Directive obj; + Program::Directive obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Directive::ToLeRadix& lhs, const Directive::ToLeRadix& rhs) { @@ -6282,11 +6290,11 @@ inline Directive::ToLeRadix Directive::ToLeRadix::bincodeDeserialize(std::vector return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Directive::ToLeRadix& obj, +void serde::Serializable::serialize(const Program::Directive::ToLeRadix& obj, Serializer& serializer) { serde::Serializable::serialize(obj.a, serializer); @@ -6296,17 +6304,17 @@ void serde::Serializable::serialize(const Circuit template <> template -Circuit::Directive::ToLeRadix serde::Deserializable::deserialize( +Program::Directive::ToLeRadix serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::Directive::ToLeRadix obj; + Program::Directive::ToLeRadix obj; obj.a = serde::Deserializable::deserialize(deserializer); obj.b = serde::Deserializable::deserialize(deserializer); obj.radix = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Expression& lhs, const Expression& rhs) { @@ -6339,11 +6347,11 @@ inline Expression Expression::bincodeDeserialize(std::vector input) return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Expression& obj, Serializer& serializer) +void serde::Serializable::serialize(const Program::Expression& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.mul_terms, serializer); @@ -6354,10 +6362,10 @@ void serde::Serializable::serialize(const Circuit::Expressi template <> template -Circuit::Expression serde::Deserializable::deserialize(Deserializer& deserializer) +Program::Expression serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Circuit::Expression obj; + Program::Expression obj; obj.mul_terms = serde::Deserializable::deserialize(deserializer); obj.linear_combinations = serde::Deserializable::deserialize(deserializer); obj.q_c = serde::Deserializable::deserialize(deserializer); @@ -6365,7 +6373,7 @@ Circuit::Expression serde::Deserializable::deserialize(Dese return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const ExpressionWidth& lhs, const ExpressionWidth& rhs) { @@ -6392,11 +6400,11 @@ inline ExpressionWidth ExpressionWidth::bincodeDeserialize(std::vector return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::ExpressionWidth& obj, +void serde::Serializable::serialize(const Program::ExpressionWidth& obj, Serializer& serializer) { serializer.increase_container_depth(); @@ -6406,16 +6414,16 @@ void serde::Serializable::serialize(const Circuit::Exp template <> template -Circuit::ExpressionWidth serde::Deserializable::deserialize(Deserializer& deserializer) +Program::ExpressionWidth serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Circuit::ExpressionWidth obj; + Program::ExpressionWidth obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const ExpressionWidth::Unbounded& lhs, const ExpressionWidth::Unbounded& rhs) { @@ -6439,24 +6447,24 @@ inline ExpressionWidth::Unbounded ExpressionWidth::Unbounded::bincodeDeserialize return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::ExpressionWidth::Unbounded& obj, +void serde::Serializable::serialize(const Program::ExpressionWidth::Unbounded& obj, Serializer& serializer) {} template <> template -Circuit::ExpressionWidth::Unbounded serde::Deserializable::deserialize( +Program::ExpressionWidth::Unbounded serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::ExpressionWidth::Unbounded obj; + Program::ExpressionWidth::Unbounded obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const ExpressionWidth::Bounded& lhs, const ExpressionWidth::Bounded& rhs) { @@ -6483,11 +6491,11 @@ inline ExpressionWidth::Bounded ExpressionWidth::Bounded::bincodeDeserialize(std return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::ExpressionWidth::Bounded& obj, +void serde::Serializable::serialize(const Program::ExpressionWidth::Bounded& obj, Serializer& serializer) { serde::Serializable::serialize(obj.width, serializer); @@ -6495,15 +6503,15 @@ void serde::Serializable::serialize(const Cir template <> template -Circuit::ExpressionWidth::Bounded serde::Deserializable::deserialize( +Program::ExpressionWidth::Bounded serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::ExpressionWidth::Bounded obj; + Program::ExpressionWidth::Bounded obj; obj.width = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const FunctionInput& lhs, const FunctionInput& rhs) { @@ -6533,11 +6541,11 @@ inline FunctionInput FunctionInput::bincodeDeserialize(std::vector inpu return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::FunctionInput& obj, Serializer& serializer) +void serde::Serializable::serialize(const Program::FunctionInput& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.witness, serializer); @@ -6547,17 +6555,17 @@ void serde::Serializable::serialize(const Circuit::Funct template <> template -Circuit::FunctionInput serde::Deserializable::deserialize(Deserializer& deserializer) +Program::FunctionInput serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Circuit::FunctionInput obj; + Program::FunctionInput obj; obj.witness = serde::Deserializable::deserialize(deserializer); obj.num_bits = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const HeapArray& lhs, const HeapArray& rhs) { @@ -6587,11 +6595,11 @@ inline HeapArray HeapArray::bincodeDeserialize(std::vector input) return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::HeapArray& obj, Serializer& serializer) +void serde::Serializable::serialize(const Program::HeapArray& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.pointer, serializer); @@ -6601,17 +6609,17 @@ void serde::Serializable::serialize(const Circuit::HeapArray template <> template -Circuit::HeapArray serde::Deserializable::deserialize(Deserializer& deserializer) +Program::HeapArray serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Circuit::HeapArray obj; + Program::HeapArray obj; obj.pointer = serde::Deserializable::deserialize(deserializer); obj.size = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const HeapValueType& lhs, const HeapValueType& rhs) { @@ -6638,11 +6646,11 @@ inline HeapValueType HeapValueType::bincodeDeserialize(std::vector inpu return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::HeapValueType& obj, Serializer& serializer) +void serde::Serializable::serialize(const Program::HeapValueType& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); @@ -6651,16 +6659,16 @@ void serde::Serializable::serialize(const Circuit::HeapV template <> template -Circuit::HeapValueType serde::Deserializable::deserialize(Deserializer& deserializer) +Program::HeapValueType serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Circuit::HeapValueType obj; + Program::HeapValueType obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const HeapValueType::Simple& lhs, const HeapValueType::Simple& rhs) { @@ -6684,24 +6692,24 @@ inline HeapValueType::Simple HeapValueType::Simple::bincodeDeserialize(std::vect return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::HeapValueType::Simple& obj, +void serde::Serializable::serialize(const Program::HeapValueType::Simple& obj, Serializer& serializer) {} template <> template -Circuit::HeapValueType::Simple serde::Deserializable::deserialize( +Program::HeapValueType::Simple serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::HeapValueType::Simple obj; + Program::HeapValueType::Simple obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const HeapValueType::Array& lhs, const HeapValueType::Array& rhs) { @@ -6731,11 +6739,11 @@ inline HeapValueType::Array HeapValueType::Array::bincodeDeserialize(std::vector return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::HeapValueType::Array& obj, +void serde::Serializable::serialize(const Program::HeapValueType::Array& obj, Serializer& serializer) { serde::Serializable::serialize(obj.value_types, serializer); @@ -6744,16 +6752,16 @@ void serde::Serializable::serialize(const Circuit template <> template -Circuit::HeapValueType::Array serde::Deserializable::deserialize( +Program::HeapValueType::Array serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::HeapValueType::Array obj; + Program::HeapValueType::Array obj; obj.value_types = serde::Deserializable::deserialize(deserializer); obj.size = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const HeapValueType::Vector& lhs, const HeapValueType::Vector& rhs) { @@ -6780,11 +6788,11 @@ inline HeapValueType::Vector HeapValueType::Vector::bincodeDeserialize(std::vect return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::HeapValueType::Vector& obj, +void serde::Serializable::serialize(const Program::HeapValueType::Vector& obj, Serializer& serializer) { serde::Serializable::serialize(obj.value_types, serializer); @@ -6792,15 +6800,15 @@ void serde::Serializable::serialize(const Circui template <> template -Circuit::HeapValueType::Vector serde::Deserializable::deserialize( +Program::HeapValueType::Vector serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::HeapValueType::Vector obj; + Program::HeapValueType::Vector obj; obj.value_types = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const HeapVector& lhs, const HeapVector& rhs) { @@ -6830,11 +6838,11 @@ inline HeapVector HeapVector::bincodeDeserialize(std::vector input) return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::HeapVector& obj, Serializer& serializer) +void serde::Serializable::serialize(const Program::HeapVector& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.pointer, serializer); @@ -6844,17 +6852,17 @@ void serde::Serializable::serialize(const Circuit::HeapVect template <> template -Circuit::HeapVector serde::Deserializable::deserialize(Deserializer& deserializer) +Program::HeapVector serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Circuit::HeapVector obj; + Program::HeapVector obj; obj.pointer = serde::Deserializable::deserialize(deserializer); obj.size = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const MemOp& lhs, const MemOp& rhs) { @@ -6887,11 +6895,11 @@ inline MemOp MemOp::bincodeDeserialize(std::vector input) return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::MemOp& obj, Serializer& serializer) +void serde::Serializable::serialize(const Program::MemOp& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.operation, serializer); @@ -6902,10 +6910,10 @@ void serde::Serializable::serialize(const Circuit::MemOp& obj, S template <> template -Circuit::MemOp serde::Deserializable::deserialize(Deserializer& deserializer) +Program::MemOp serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Circuit::MemOp obj; + Program::MemOp obj; obj.operation = serde::Deserializable::deserialize(deserializer); obj.index = serde::Deserializable::deserialize(deserializer); obj.value = serde::Deserializable::deserialize(deserializer); @@ -6913,7 +6921,7 @@ Circuit::MemOp serde::Deserializable::deserialize(Deserializer& return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const MemoryAddress& lhs, const MemoryAddress& rhs) { @@ -6940,11 +6948,11 @@ inline MemoryAddress MemoryAddress::bincodeDeserialize(std::vector inpu return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::MemoryAddress& obj, Serializer& serializer) +void serde::Serializable::serialize(const Program::MemoryAddress& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); @@ -6953,16 +6961,16 @@ void serde::Serializable::serialize(const Circuit::Memor template <> template -Circuit::MemoryAddress serde::Deserializable::deserialize(Deserializer& deserializer) +Program::MemoryAddress serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Circuit::MemoryAddress obj; + Program::MemoryAddress obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Opcode& lhs, const Opcode& rhs) { @@ -6989,11 +6997,11 @@ inline Opcode Opcode::bincodeDeserialize(std::vector input) return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Opcode& obj, Serializer& serializer) +void serde::Serializable::serialize(const Program::Opcode& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); @@ -7002,16 +7010,16 @@ void serde::Serializable::serialize(const Circuit::Opcode& obj, template <> template -Circuit::Opcode serde::Deserializable::deserialize(Deserializer& deserializer) +Program::Opcode serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Circuit::Opcode obj; + Program::Opcode obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Opcode::AssertZero& lhs, const Opcode::AssertZero& rhs) { @@ -7038,11 +7046,11 @@ inline Opcode::AssertZero Opcode::AssertZero::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Circuit::Opcode::AssertZero& obj, +void serde::Serializable::serialize(const Program::Opcode::AssertZero& obj, Serializer& serializer) { serde::Serializable::serialize(obj.value, serializer); @@ -7050,14 +7058,14 @@ void serde::Serializable::serialize(const Circuit:: template <> template -Circuit::Opcode::AssertZero serde::Deserializable::deserialize(Deserializer& deserializer) +Program::Opcode::AssertZero serde::Deserializable::deserialize(Deserializer& deserializer) { - Circuit::Opcode::AssertZero obj; + Program::Opcode::AssertZero obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Opcode::BlackBoxFuncCall& lhs, const Opcode::BlackBoxFuncCall& rhs) { @@ -7084,11 +7092,11 @@ inline Opcode::BlackBoxFuncCall Opcode::BlackBoxFuncCall::bincodeDeserialize(std return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Opcode::BlackBoxFuncCall& obj, +void serde::Serializable::serialize(const Program::Opcode::BlackBoxFuncCall& obj, Serializer& serializer) { serde::Serializable::serialize(obj.value, serializer); @@ -7096,15 +7104,15 @@ void serde::Serializable::serialize(const Cir template <> template -Circuit::Opcode::BlackBoxFuncCall serde::Deserializable::deserialize( +Program::Opcode::BlackBoxFuncCall serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::Opcode::BlackBoxFuncCall obj; + Program::Opcode::BlackBoxFuncCall obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Opcode::Directive& lhs, const Opcode::Directive& rhs) { @@ -7131,11 +7139,11 @@ inline Opcode::Directive Opcode::Directive::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Circuit::Opcode::Directive& obj, +void serde::Serializable::serialize(const Program::Opcode::Directive& obj, Serializer& serializer) { serde::Serializable::serialize(obj.value, serializer); @@ -7143,14 +7151,14 @@ void serde::Serializable::serialize(const Circuit::O template <> template -Circuit::Opcode::Directive serde::Deserializable::deserialize(Deserializer& deserializer) +Program::Opcode::Directive serde::Deserializable::deserialize(Deserializer& deserializer) { - Circuit::Opcode::Directive obj; + Program::Opcode::Directive obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Opcode::Brillig& lhs, const Opcode::Brillig& rhs) { @@ -7177,11 +7185,11 @@ inline Opcode::Brillig Opcode::Brillig::bincodeDeserialize(std::vector return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Opcode::Brillig& obj, +void serde::Serializable::serialize(const Program::Opcode::Brillig& obj, Serializer& serializer) { serde::Serializable::serialize(obj.value, serializer); @@ -7189,14 +7197,14 @@ void serde::Serializable::serialize(const Circuit::Opc template <> template -Circuit::Opcode::Brillig serde::Deserializable::deserialize(Deserializer& deserializer) +Program::Opcode::Brillig serde::Deserializable::deserialize(Deserializer& deserializer) { - Circuit::Opcode::Brillig obj; + Program::Opcode::Brillig obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Opcode::MemoryOp& lhs, const Opcode::MemoryOp& rhs) { @@ -7229,11 +7237,11 @@ inline Opcode::MemoryOp Opcode::MemoryOp::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Circuit::Opcode::MemoryOp& obj, +void serde::Serializable::serialize(const Program::Opcode::MemoryOp& obj, Serializer& serializer) { serde::Serializable::serialize(obj.block_id, serializer); @@ -7243,16 +7251,16 @@ void serde::Serializable::serialize(const Circuit::Op template <> template -Circuit::Opcode::MemoryOp serde::Deserializable::deserialize(Deserializer& deserializer) +Program::Opcode::MemoryOp serde::Deserializable::deserialize(Deserializer& deserializer) { - Circuit::Opcode::MemoryOp obj; + Program::Opcode::MemoryOp obj; obj.block_id = serde::Deserializable::deserialize(deserializer); obj.op = serde::Deserializable::deserialize(deserializer); obj.predicate = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Opcode::MemoryInit& lhs, const Opcode::MemoryInit& rhs) { @@ -7282,11 +7290,11 @@ inline Opcode::MemoryInit Opcode::MemoryInit::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Circuit::Opcode::MemoryInit& obj, +void serde::Serializable::serialize(const Program::Opcode::MemoryInit& obj, Serializer& serializer) { serde::Serializable::serialize(obj.block_id, serializer); @@ -7295,15 +7303,15 @@ void serde::Serializable::serialize(const Circuit:: template <> template -Circuit::Opcode::MemoryInit serde::Deserializable::deserialize(Deserializer& deserializer) +Program::Opcode::MemoryInit serde::Deserializable::deserialize(Deserializer& deserializer) { - Circuit::Opcode::MemoryInit obj; + Program::Opcode::MemoryInit obj; obj.block_id = serde::Deserializable::deserialize(deserializer); obj.init = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Opcode::Call& lhs, const Opcode::Call& rhs) { @@ -7336,11 +7344,11 @@ inline Opcode::Call Opcode::Call::bincodeDeserialize(std::vector input) return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Opcode::Call& obj, Serializer& serializer) +void serde::Serializable::serialize(const Program::Opcode::Call& obj, Serializer& serializer) { serde::Serializable::serialize(obj.id, serializer); serde::Serializable::serialize(obj.inputs, serializer); @@ -7349,16 +7357,16 @@ void serde::Serializable::serialize(const Circuit::Opcode template <> template -Circuit::Opcode::Call serde::Deserializable::deserialize(Deserializer& deserializer) +Program::Opcode::Call serde::Deserializable::deserialize(Deserializer& deserializer) { - Circuit::Opcode::Call obj; + Program::Opcode::Call obj; obj.id = serde::Deserializable::deserialize(deserializer); obj.inputs = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const OpcodeLocation& lhs, const OpcodeLocation& rhs) { @@ -7385,11 +7393,11 @@ inline OpcodeLocation OpcodeLocation::bincodeDeserialize(std::vector in return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::OpcodeLocation& obj, Serializer& serializer) +void serde::Serializable::serialize(const Program::OpcodeLocation& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); @@ -7398,16 +7406,16 @@ void serde::Serializable::serialize(const Circuit::Opco template <> template -Circuit::OpcodeLocation serde::Deserializable::deserialize(Deserializer& deserializer) +Program::OpcodeLocation serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Circuit::OpcodeLocation obj; + Program::OpcodeLocation obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const OpcodeLocation::Acir& lhs, const OpcodeLocation::Acir& rhs) { @@ -7434,11 +7442,11 @@ inline OpcodeLocation::Acir OpcodeLocation::Acir::bincodeDeserialize(std::vector return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::OpcodeLocation::Acir& obj, +void serde::Serializable::serialize(const Program::OpcodeLocation::Acir& obj, Serializer& serializer) { serde::Serializable::serialize(obj.value, serializer); @@ -7446,15 +7454,15 @@ void serde::Serializable::serialize(const Circuit template <> template -Circuit::OpcodeLocation::Acir serde::Deserializable::deserialize( +Program::OpcodeLocation::Acir serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::OpcodeLocation::Acir obj; + Program::OpcodeLocation::Acir obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const OpcodeLocation::Brillig& lhs, const OpcodeLocation::Brillig& rhs) { @@ -7484,11 +7492,11 @@ inline OpcodeLocation::Brillig OpcodeLocation::Brillig::bincodeDeserialize(std:: return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::OpcodeLocation::Brillig& obj, +void serde::Serializable::serialize(const Program::OpcodeLocation::Brillig& obj, Serializer& serializer) { serde::Serializable::serialize(obj.acir_index, serializer); @@ -7497,16 +7505,65 @@ void serde::Serializable::serialize(const Circ template <> template -Circuit::OpcodeLocation::Brillig serde::Deserializable::deserialize( +Program::OpcodeLocation::Brillig serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::OpcodeLocation::Brillig obj; + Program::OpcodeLocation::Brillig obj; obj.acir_index = serde::Deserializable::deserialize(deserializer); obj.brillig_index = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { + +inline bool operator==(const Program& lhs, const Program& rhs) +{ + if (!(lhs.functions == rhs.functions)) { + return false; + } + return true; +} + +inline std::vector Program::bincodeSerialize() const +{ + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); +} + +inline Program Program::bincodeDeserialize(std::vector input) +{ + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw_or_abort("Some input bytes were not read"); + } + return value; +} + +} // end of namespace Program + +template <> +template +void serde::Serializable::serialize(const Program::Program& obj, Serializer& serializer) +{ + serializer.increase_container_depth(); + serde::Serializable::serialize(obj.functions, serializer); + serializer.decrease_container_depth(); +} + +template <> +template +Program::Program serde::Deserializable::deserialize(Deserializer& deserializer) +{ + deserializer.increase_container_depth(); + Program::Program obj; + obj.functions = serde::Deserializable::deserialize(deserializer); + deserializer.decrease_container_depth(); + return obj; +} + +namespace Program { inline bool operator==(const PublicInputs& lhs, const PublicInputs& rhs) { @@ -7533,11 +7590,11 @@ inline PublicInputs PublicInputs::bincodeDeserialize(std::vector input) return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::PublicInputs& obj, Serializer& serializer) +void serde::Serializable::serialize(const Program::PublicInputs& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); @@ -7546,16 +7603,16 @@ void serde::Serializable::serialize(const Circuit::Public template <> template -Circuit::PublicInputs serde::Deserializable::deserialize(Deserializer& deserializer) +Program::PublicInputs serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Circuit::PublicInputs obj; + Program::PublicInputs obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Value& lhs, const Value& rhs) { @@ -7582,11 +7639,11 @@ inline Value Value::bincodeDeserialize(std::vector input) return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Value& obj, Serializer& serializer) +void serde::Serializable::serialize(const Program::Value& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.inner, serializer); @@ -7595,16 +7652,16 @@ void serde::Serializable::serialize(const Circuit::Value& obj, S template <> template -Circuit::Value serde::Deserializable::deserialize(Deserializer& deserializer) +Program::Value serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Circuit::Value obj; + Program::Value obj; obj.inner = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const ValueOrArray& lhs, const ValueOrArray& rhs) { @@ -7631,11 +7688,11 @@ inline ValueOrArray ValueOrArray::bincodeDeserialize(std::vector input) return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::ValueOrArray& obj, Serializer& serializer) +void serde::Serializable::serialize(const Program::ValueOrArray& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); @@ -7644,16 +7701,16 @@ void serde::Serializable::serialize(const Circuit::ValueO template <> template -Circuit::ValueOrArray serde::Deserializable::deserialize(Deserializer& deserializer) +Program::ValueOrArray serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Circuit::ValueOrArray obj; + Program::ValueOrArray obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const ValueOrArray::MemoryAddress& lhs, const ValueOrArray::MemoryAddress& rhs) { @@ -7680,27 +7737,27 @@ inline ValueOrArray::MemoryAddress ValueOrArray::MemoryAddress::bincodeDeseriali return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize( - const Circuit::ValueOrArray::MemoryAddress& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Program::ValueOrArray::MemoryAddress& obj, Serializer& serializer) { serde::Serializable::serialize(obj.value, serializer); } template <> template -Circuit::ValueOrArray::MemoryAddress serde::Deserializable::deserialize( +Program::ValueOrArray::MemoryAddress serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::ValueOrArray::MemoryAddress obj; + Program::ValueOrArray::MemoryAddress obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const ValueOrArray::HeapArray& lhs, const ValueOrArray::HeapArray& rhs) { @@ -7727,11 +7784,11 @@ inline ValueOrArray::HeapArray ValueOrArray::HeapArray::bincodeDeserialize(std:: return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::ValueOrArray::HeapArray& obj, +void serde::Serializable::serialize(const Program::ValueOrArray::HeapArray& obj, Serializer& serializer) { serde::Serializable::serialize(obj.value, serializer); @@ -7739,15 +7796,15 @@ void serde::Serializable::serialize(const Circ template <> template -Circuit::ValueOrArray::HeapArray serde::Deserializable::deserialize( +Program::ValueOrArray::HeapArray serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::ValueOrArray::HeapArray obj; + Program::ValueOrArray::HeapArray obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const ValueOrArray::HeapVector& lhs, const ValueOrArray::HeapVector& rhs) { @@ -7774,11 +7831,11 @@ inline ValueOrArray::HeapVector ValueOrArray::HeapVector::bincodeDeserialize(std return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::ValueOrArray::HeapVector& obj, +void serde::Serializable::serialize(const Program::ValueOrArray::HeapVector& obj, Serializer& serializer) { serde::Serializable::serialize(obj.value, serializer); @@ -7786,15 +7843,15 @@ void serde::Serializable::serialize(const Cir template <> template -Circuit::ValueOrArray::HeapVector serde::Deserializable::deserialize( +Program::ValueOrArray::HeapVector serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::ValueOrArray::HeapVector obj; + Program::ValueOrArray::HeapVector obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Witness& lhs, const Witness& rhs) { @@ -7821,11 +7878,11 @@ inline Witness Witness::bincodeDeserialize(std::vector input) return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Witness& obj, Serializer& serializer) +void serde::Serializable::serialize(const Program::Witness& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); @@ -7834,10 +7891,10 @@ void serde::Serializable::serialize(const Circuit::Witness& ob template <> template -Circuit::Witness serde::Deserializable::deserialize(Deserializer& deserializer) +Program::Witness serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Circuit::Witness obj; + Program::Witness obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/index.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/index.hpp index 82716cef883c..cbbc3ca1b339 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/index.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/index.hpp @@ -6,7 +6,7 @@ #pragma clang diagnostic ignored "-Wshorten-64-to-32" #pragma clang diagnostic ignored "-Wunused-parameter" #include "acir.hpp" -#include "witness_map.hpp" +#include "witness_stack.hpp" #pragma clang diagnostic pop #else #pragma GCC diagnostic push diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/witness_map.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/witness_map.hpp deleted file mode 100644 index de4523e7020a..000000000000 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/witness_map.hpp +++ /dev/null @@ -1,123 +0,0 @@ -#pragma once - -#include "bincode.hpp" -#include "serde.hpp" - -namespace WitnessMap { - -struct Witness { - uint32_t value; - - friend bool operator==(const Witness&, const Witness&); - bool operator<(Witness const& rhs) const { return value < rhs.value; } - std::vector bincodeSerialize() const; - static Witness bincodeDeserialize(std::vector); -}; - -struct WitnessMap { - std::map value; - - friend bool operator==(const WitnessMap&, const WitnessMap&); - std::vector bincodeSerialize() const; - static WitnessMap bincodeDeserialize(std::vector); -}; - -} // end of namespace WitnessMap - -namespace WitnessMap { - -inline bool operator==(const Witness& lhs, const Witness& rhs) -{ - if (!(lhs.value == rhs.value)) { - return false; - } - return true; -} - -inline std::vector Witness::bincodeSerialize() const -{ - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} - -inline Witness Witness::bincodeDeserialize(std::vector input) -{ - auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); - if (deserializer.get_buffer_offset() < input.size()) { - throw_or_abort("Some input bytes were not read"); - } - return value; -} - -} // end of namespace WitnessMap - -template <> -template -void serde::Serializable::serialize(const WitnessMap::Witness& obj, Serializer& serializer) -{ - serializer.increase_container_depth(); - serde::Serializable::serialize(obj.value, serializer); - serializer.decrease_container_depth(); -} - -template <> -template -WitnessMap::Witness serde::Deserializable::deserialize(Deserializer& deserializer) -{ - deserializer.increase_container_depth(); - WitnessMap::Witness obj; - obj.value = serde::Deserializable::deserialize(deserializer); - deserializer.decrease_container_depth(); - return obj; -} - -namespace WitnessMap { - -inline bool operator==(const WitnessMap& lhs, const WitnessMap& rhs) -{ - if (!(lhs.value == rhs.value)) { - return false; - } - return true; -} - -inline std::vector WitnessMap::bincodeSerialize() const -{ - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} - -inline WitnessMap WitnessMap::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 WitnessMap - -template <> -template -void serde::Serializable::serialize(const WitnessMap::WitnessMap& obj, Serializer& serializer) -{ - serializer.increase_container_depth(); - serde::Serializable::serialize(obj.value, serializer); - serializer.decrease_container_depth(); -} - -template <> -template -WitnessMap::WitnessMap serde::Deserializable::deserialize(Deserializer& deserializer) -{ - deserializer.increase_container_depth(); - WitnessMap::WitnessMap obj; - obj.value = serde::Deserializable::deserialize(deserializer); - deserializer.decrease_container_depth(); - return obj; -} \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/witness_stack.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/witness_stack.hpp new file mode 100644 index 000000000000..67ef655babfd --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/witness_stack.hpp @@ -0,0 +1,247 @@ +#pragma once + +#include "bincode.hpp" +#include "serde.hpp" + +namespace WitnessStack { + +struct Witness { + uint32_t value; + + friend bool operator==(const Witness&, const Witness&); + + bool operator<(Witness const& rhs) const { return value < rhs.value; } + + std::vector bincodeSerialize() const; + static Witness bincodeDeserialize(std::vector); +}; + +struct WitnessMap { + std::map value; + + friend bool operator==(const WitnessMap&, const WitnessMap&); + std::vector bincodeSerialize() const; + static WitnessMap bincodeDeserialize(std::vector); +}; + +struct StackItem { + uint32_t index; + WitnessStack::WitnessMap witness; + + friend bool operator==(const StackItem&, const StackItem&); + std::vector bincodeSerialize() const; + static StackItem bincodeDeserialize(std::vector); +}; + +struct WitnessStack { + std::vector stack; + + friend bool operator==(const WitnessStack&, const WitnessStack&); + std::vector bincodeSerialize() const; + static WitnessStack bincodeDeserialize(std::vector); +}; + +} // end of namespace WitnessStack + +namespace WitnessStack { + +inline bool operator==(const StackItem& lhs, const StackItem& rhs) +{ + if (!(lhs.index == rhs.index)) { + return false; + } + if (!(lhs.witness == rhs.witness)) { + return false; + } + return true; +} + +inline std::vector StackItem::bincodeSerialize() const +{ + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); +} + +inline StackItem StackItem::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 WitnessStack + +template <> +template +void serde::Serializable::serialize(const WitnessStack::StackItem& obj, Serializer& serializer) +{ + serializer.increase_container_depth(); + serde::Serializable::serialize(obj.index, serializer); + serde::Serializable::serialize(obj.witness, serializer); + serializer.decrease_container_depth(); +} + +template <> +template +WitnessStack::StackItem serde::Deserializable::deserialize(Deserializer& deserializer) +{ + deserializer.increase_container_depth(); + WitnessStack::StackItem obj; + obj.index = serde::Deserializable::deserialize(deserializer); + obj.witness = serde::Deserializable::deserialize(deserializer); + deserializer.decrease_container_depth(); + return obj; +} + +namespace WitnessStack { + +inline bool operator==(const Witness& lhs, const Witness& rhs) +{ + if (!(lhs.value == rhs.value)) { + return false; + } + return true; +} + +inline std::vector Witness::bincodeSerialize() const +{ + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); +} + +inline Witness Witness::bincodeDeserialize(std::vector input) +{ + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw_or_abort("Some input bytes were not read"); + } + return value; +} + +} // end of namespace WitnessStack + +template <> +template +void serde::Serializable::serialize(const WitnessStack::Witness& obj, Serializer& serializer) +{ + serializer.increase_container_depth(); + serde::Serializable::serialize(obj.value, serializer); + serializer.decrease_container_depth(); +} + +template <> +template +WitnessStack::Witness serde::Deserializable::deserialize(Deserializer& deserializer) +{ + deserializer.increase_container_depth(); + WitnessStack::Witness obj; + obj.value = serde::Deserializable::deserialize(deserializer); + deserializer.decrease_container_depth(); + return obj; +} + +namespace WitnessStack { + +inline bool operator==(const WitnessMap& lhs, const WitnessMap& rhs) +{ + if (!(lhs.value == rhs.value)) { + return false; + } + return true; +} + +inline std::vector WitnessMap::bincodeSerialize() const +{ + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); +} + +inline WitnessMap WitnessMap::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 WitnessStack + +template <> +template +void serde::Serializable::serialize(const WitnessStack::WitnessMap& obj, + Serializer& serializer) +{ + serializer.increase_container_depth(); + serde::Serializable::serialize(obj.value, serializer); + serializer.decrease_container_depth(); +} + +template <> +template +WitnessStack::WitnessMap serde::Deserializable::deserialize(Deserializer& deserializer) +{ + deserializer.increase_container_depth(); + WitnessStack::WitnessMap obj; + obj.value = serde::Deserializable::deserialize(deserializer); + deserializer.decrease_container_depth(); + return obj; +} + +namespace WitnessStack { + +inline bool operator==(const WitnessStack& lhs, const WitnessStack& rhs) +{ + if (!(lhs.stack == rhs.stack)) { + return false; + } + return true; +} + +inline std::vector WitnessStack::bincodeSerialize() const +{ + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); +} + +inline WitnessStack WitnessStack::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 WitnessStack + +template <> +template +void serde::Serializable::serialize(const WitnessStack::WitnessStack& obj, + Serializer& serializer) +{ + serializer.increase_container_depth(); + serde::Serializable::serialize(obj.stack, serializer); + serializer.decrease_container_depth(); +} + +template <> +template +WitnessStack::WitnessStack serde::Deserializable::deserialize(Deserializer& deserializer) +{ + deserializer.increase_container_depth(); + WitnessStack::WitnessStack obj; + obj.stack = serde::Deserializable::deserialize(deserializer); + deserializer.decrease_container_depth(); + return obj; +} diff --git a/noir/noir-repo/acvm-repo/acir/codegen/acir.cpp b/noir/noir-repo/acvm-repo/acir/codegen/acir.cpp index 46809727000a..2fd8180b5b7f 100644 --- a/noir/noir-repo/acvm-repo/acir/codegen/acir.cpp +++ b/noir/noir-repo/acvm-repo/acir/codegen/acir.cpp @@ -3,7 +3,7 @@ #include "serde.hpp" #include "bincode.hpp" -namespace Circuit { +namespace Program { struct BinaryFieldOp { @@ -140,7 +140,7 @@ namespace Circuit { }; struct HeapArray { - Circuit::MemoryAddress pointer; + Program::MemoryAddress pointer; uint64_t size; friend bool operator==(const HeapArray&, const HeapArray&); @@ -149,8 +149,8 @@ namespace Circuit { }; struct HeapVector { - Circuit::MemoryAddress pointer; - Circuit::MemoryAddress size; + Program::MemoryAddress pointer; + Program::MemoryAddress size; friend bool operator==(const HeapVector&, const HeapVector&); std::vector bincodeSerialize() const; @@ -160,8 +160,8 @@ namespace Circuit { struct BlackBoxOp { struct Sha256 { - Circuit::HeapVector message; - Circuit::HeapArray output; + Program::HeapVector message; + Program::HeapArray output; friend bool operator==(const Sha256&, const Sha256&); std::vector bincodeSerialize() const; @@ -169,8 +169,8 @@ namespace Circuit { }; struct Blake2s { - Circuit::HeapVector message; - Circuit::HeapArray output; + Program::HeapVector message; + Program::HeapArray output; friend bool operator==(const Blake2s&, const Blake2s&); std::vector bincodeSerialize() const; @@ -178,8 +178,8 @@ namespace Circuit { }; struct Blake3 { - Circuit::HeapVector message; - Circuit::HeapArray output; + Program::HeapVector message; + Program::HeapArray output; friend bool operator==(const Blake3&, const Blake3&); std::vector bincodeSerialize() const; @@ -187,8 +187,8 @@ namespace Circuit { }; struct Keccak256 { - Circuit::HeapVector message; - Circuit::HeapArray output; + Program::HeapVector message; + Program::HeapArray output; friend bool operator==(const Keccak256&, const Keccak256&); std::vector bincodeSerialize() const; @@ -196,8 +196,8 @@ namespace Circuit { }; struct Keccakf1600 { - Circuit::HeapVector message; - Circuit::HeapArray output; + Program::HeapVector message; + Program::HeapArray output; friend bool operator==(const Keccakf1600&, const Keccakf1600&); std::vector bincodeSerialize() const; @@ -205,11 +205,11 @@ namespace Circuit { }; struct EcdsaSecp256k1 { - Circuit::HeapVector hashed_msg; - Circuit::HeapArray public_key_x; - Circuit::HeapArray public_key_y; - Circuit::HeapArray signature; - Circuit::MemoryAddress result; + Program::HeapVector hashed_msg; + Program::HeapArray public_key_x; + Program::HeapArray public_key_y; + Program::HeapArray signature; + Program::MemoryAddress result; friend bool operator==(const EcdsaSecp256k1&, const EcdsaSecp256k1&); std::vector bincodeSerialize() const; @@ -217,11 +217,11 @@ namespace Circuit { }; struct EcdsaSecp256r1 { - Circuit::HeapVector hashed_msg; - Circuit::HeapArray public_key_x; - Circuit::HeapArray public_key_y; - Circuit::HeapArray signature; - Circuit::MemoryAddress result; + Program::HeapVector hashed_msg; + Program::HeapArray public_key_x; + Program::HeapArray public_key_y; + Program::HeapArray signature; + Program::MemoryAddress result; friend bool operator==(const EcdsaSecp256r1&, const EcdsaSecp256r1&); std::vector bincodeSerialize() const; @@ -229,11 +229,11 @@ namespace Circuit { }; struct SchnorrVerify { - Circuit::MemoryAddress public_key_x; - Circuit::MemoryAddress public_key_y; - Circuit::HeapVector message; - Circuit::HeapVector signature; - Circuit::MemoryAddress result; + Program::MemoryAddress public_key_x; + Program::MemoryAddress public_key_y; + Program::HeapVector message; + Program::HeapVector signature; + Program::MemoryAddress result; friend bool operator==(const SchnorrVerify&, const SchnorrVerify&); std::vector bincodeSerialize() const; @@ -241,9 +241,9 @@ namespace Circuit { }; struct PedersenCommitment { - Circuit::HeapVector inputs; - Circuit::MemoryAddress domain_separator; - Circuit::HeapArray output; + Program::HeapVector inputs; + Program::MemoryAddress domain_separator; + Program::HeapArray output; friend bool operator==(const PedersenCommitment&, const PedersenCommitment&); std::vector bincodeSerialize() const; @@ -251,9 +251,9 @@ namespace Circuit { }; struct PedersenHash { - Circuit::HeapVector inputs; - Circuit::MemoryAddress domain_separator; - Circuit::MemoryAddress output; + Program::HeapVector inputs; + Program::MemoryAddress domain_separator; + Program::MemoryAddress output; friend bool operator==(const PedersenHash&, const PedersenHash&); std::vector bincodeSerialize() const; @@ -261,9 +261,9 @@ namespace Circuit { }; struct FixedBaseScalarMul { - Circuit::MemoryAddress low; - Circuit::MemoryAddress high; - Circuit::HeapArray result; + Program::MemoryAddress low; + Program::MemoryAddress high; + Program::HeapArray result; friend bool operator==(const FixedBaseScalarMul&, const FixedBaseScalarMul&); std::vector bincodeSerialize() const; @@ -271,11 +271,11 @@ namespace Circuit { }; struct EmbeddedCurveAdd { - Circuit::MemoryAddress input1_x; - Circuit::MemoryAddress input1_y; - Circuit::MemoryAddress input2_x; - Circuit::MemoryAddress input2_y; - Circuit::HeapArray result; + Program::MemoryAddress input1_x; + Program::MemoryAddress input1_y; + Program::MemoryAddress input2_x; + Program::MemoryAddress input2_y; + Program::HeapArray result; friend bool operator==(const EmbeddedCurveAdd&, const EmbeddedCurveAdd&); std::vector bincodeSerialize() const; @@ -283,9 +283,9 @@ namespace Circuit { }; struct BigIntAdd { - Circuit::MemoryAddress lhs; - Circuit::MemoryAddress rhs; - Circuit::MemoryAddress output; + Program::MemoryAddress lhs; + Program::MemoryAddress rhs; + Program::MemoryAddress output; friend bool operator==(const BigIntAdd&, const BigIntAdd&); std::vector bincodeSerialize() const; @@ -293,9 +293,9 @@ namespace Circuit { }; struct BigIntSub { - Circuit::MemoryAddress lhs; - Circuit::MemoryAddress rhs; - Circuit::MemoryAddress output; + Program::MemoryAddress lhs; + Program::MemoryAddress rhs; + Program::MemoryAddress output; friend bool operator==(const BigIntSub&, const BigIntSub&); std::vector bincodeSerialize() const; @@ -303,9 +303,9 @@ namespace Circuit { }; struct BigIntMul { - Circuit::MemoryAddress lhs; - Circuit::MemoryAddress rhs; - Circuit::MemoryAddress output; + Program::MemoryAddress lhs; + Program::MemoryAddress rhs; + Program::MemoryAddress output; friend bool operator==(const BigIntMul&, const BigIntMul&); std::vector bincodeSerialize() const; @@ -313,9 +313,9 @@ namespace Circuit { }; struct BigIntDiv { - Circuit::MemoryAddress lhs; - Circuit::MemoryAddress rhs; - Circuit::MemoryAddress output; + Program::MemoryAddress lhs; + Program::MemoryAddress rhs; + Program::MemoryAddress output; friend bool operator==(const BigIntDiv&, const BigIntDiv&); std::vector bincodeSerialize() const; @@ -323,9 +323,9 @@ namespace Circuit { }; struct BigIntFromLeBytes { - Circuit::HeapVector inputs; - Circuit::HeapVector modulus; - Circuit::MemoryAddress output; + Program::HeapVector inputs; + Program::HeapVector modulus; + Program::MemoryAddress output; friend bool operator==(const BigIntFromLeBytes&, const BigIntFromLeBytes&); std::vector bincodeSerialize() const; @@ -333,8 +333,8 @@ namespace Circuit { }; struct BigIntToLeBytes { - Circuit::MemoryAddress input; - Circuit::HeapVector output; + Program::MemoryAddress input; + Program::HeapVector output; friend bool operator==(const BigIntToLeBytes&, const BigIntToLeBytes&); std::vector bincodeSerialize() const; @@ -342,9 +342,9 @@ namespace Circuit { }; struct Poseidon2Permutation { - Circuit::HeapVector message; - Circuit::HeapArray output; - Circuit::MemoryAddress len; + Program::HeapVector message; + Program::HeapArray output; + Program::MemoryAddress len; friend bool operator==(const Poseidon2Permutation&, const Poseidon2Permutation&); std::vector bincodeSerialize() const; @@ -352,9 +352,9 @@ namespace Circuit { }; struct Sha256Compression { - Circuit::HeapVector input; - Circuit::HeapVector hash_values; - Circuit::HeapArray output; + Program::HeapVector input; + Program::HeapVector hash_values; + Program::HeapArray output; friend bool operator==(const Sha256Compression&, const Sha256Compression&); std::vector bincodeSerialize() const; @@ -379,7 +379,7 @@ namespace Circuit { }; struct Array { - std::vector value_types; + std::vector value_types; uint64_t size; friend bool operator==(const Array&, const Array&); @@ -388,7 +388,7 @@ namespace Circuit { }; struct Vector { - std::vector value_types; + std::vector value_types; friend bool operator==(const Vector&, const Vector&); std::vector bincodeSerialize() const; @@ -413,7 +413,7 @@ namespace Circuit { struct ValueOrArray { struct MemoryAddress { - Circuit::MemoryAddress value; + Program::MemoryAddress value; friend bool operator==(const MemoryAddress&, const MemoryAddress&); std::vector bincodeSerialize() const; @@ -421,7 +421,7 @@ namespace Circuit { }; struct HeapArray { - Circuit::HeapArray value; + Program::HeapArray value; friend bool operator==(const HeapArray&, const HeapArray&); std::vector bincodeSerialize() const; @@ -429,7 +429,7 @@ namespace Circuit { }; struct HeapVector { - Circuit::HeapVector value; + Program::HeapVector value; friend bool operator==(const HeapVector&, const HeapVector&); std::vector bincodeSerialize() const; @@ -446,10 +446,10 @@ namespace Circuit { struct BrilligOpcode { struct BinaryFieldOp { - Circuit::MemoryAddress destination; - Circuit::BinaryFieldOp op; - Circuit::MemoryAddress lhs; - Circuit::MemoryAddress rhs; + Program::MemoryAddress destination; + Program::BinaryFieldOp op; + Program::MemoryAddress lhs; + Program::MemoryAddress rhs; friend bool operator==(const BinaryFieldOp&, const BinaryFieldOp&); std::vector bincodeSerialize() const; @@ -457,11 +457,11 @@ namespace Circuit { }; struct BinaryIntOp { - Circuit::MemoryAddress destination; - Circuit::BinaryIntOp op; + Program::MemoryAddress destination; + Program::BinaryIntOp op; uint32_t bit_size; - Circuit::MemoryAddress lhs; - Circuit::MemoryAddress rhs; + Program::MemoryAddress lhs; + Program::MemoryAddress rhs; friend bool operator==(const BinaryIntOp&, const BinaryIntOp&); std::vector bincodeSerialize() const; @@ -469,8 +469,8 @@ namespace Circuit { }; struct Cast { - Circuit::MemoryAddress destination; - Circuit::MemoryAddress source; + Program::MemoryAddress destination; + Program::MemoryAddress source; uint32_t bit_size; friend bool operator==(const Cast&, const Cast&); @@ -479,7 +479,7 @@ namespace Circuit { }; struct JumpIfNot { - Circuit::MemoryAddress condition; + Program::MemoryAddress condition; uint64_t location; friend bool operator==(const JumpIfNot&, const JumpIfNot&); @@ -488,7 +488,7 @@ namespace Circuit { }; struct JumpIf { - Circuit::MemoryAddress condition; + Program::MemoryAddress condition; uint64_t location; friend bool operator==(const JumpIf&, const JumpIf&); @@ -505,7 +505,7 @@ namespace Circuit { }; struct CalldataCopy { - Circuit::MemoryAddress destination_address; + Program::MemoryAddress destination_address; uint64_t size; uint64_t offset; @@ -523,9 +523,9 @@ namespace Circuit { }; struct Const { - Circuit::MemoryAddress destination; + Program::MemoryAddress destination; uint32_t bit_size; - Circuit::Value value; + Program::Value value; friend bool operator==(const Const&, const Const&); std::vector bincodeSerialize() const; @@ -540,10 +540,10 @@ namespace Circuit { struct ForeignCall { std::string function; - std::vector destinations; - std::vector destination_value_types; - std::vector inputs; - std::vector input_value_types; + std::vector destinations; + std::vector destination_value_types; + std::vector inputs; + std::vector input_value_types; friend bool operator==(const ForeignCall&, const ForeignCall&); std::vector bincodeSerialize() const; @@ -551,8 +551,8 @@ namespace Circuit { }; struct Mov { - Circuit::MemoryAddress destination; - Circuit::MemoryAddress source; + Program::MemoryAddress destination; + Program::MemoryAddress source; friend bool operator==(const Mov&, const Mov&); std::vector bincodeSerialize() const; @@ -560,8 +560,8 @@ namespace Circuit { }; struct Load { - Circuit::MemoryAddress destination; - Circuit::MemoryAddress source_pointer; + Program::MemoryAddress destination; + Program::MemoryAddress source_pointer; friend bool operator==(const Load&, const Load&); std::vector bincodeSerialize() const; @@ -569,8 +569,8 @@ namespace Circuit { }; struct Store { - Circuit::MemoryAddress destination_pointer; - Circuit::MemoryAddress source; + Program::MemoryAddress destination_pointer; + Program::MemoryAddress source; friend bool operator==(const Store&, const Store&); std::vector bincodeSerialize() const; @@ -578,7 +578,7 @@ namespace Circuit { }; struct BlackBox { - Circuit::BlackBoxOp value; + Program::BlackBoxOp value; friend bool operator==(const BlackBox&, const BlackBox&); std::vector bincodeSerialize() const; @@ -616,7 +616,7 @@ namespace Circuit { }; struct FunctionInput { - Circuit::Witness witness; + Program::Witness witness; uint32_t num_bits; friend bool operator==(const FunctionInput&, const FunctionInput&); @@ -627,9 +627,9 @@ namespace Circuit { struct BlackBoxFuncCall { struct AND { - Circuit::FunctionInput lhs; - Circuit::FunctionInput rhs; - Circuit::Witness output; + Program::FunctionInput lhs; + Program::FunctionInput rhs; + Program::Witness output; friend bool operator==(const AND&, const AND&); std::vector bincodeSerialize() const; @@ -637,9 +637,9 @@ namespace Circuit { }; struct XOR { - Circuit::FunctionInput lhs; - Circuit::FunctionInput rhs; - Circuit::Witness output; + Program::FunctionInput lhs; + Program::FunctionInput rhs; + Program::Witness output; friend bool operator==(const XOR&, const XOR&); std::vector bincodeSerialize() const; @@ -647,7 +647,7 @@ namespace Circuit { }; struct RANGE { - Circuit::FunctionInput input; + Program::FunctionInput input; friend bool operator==(const RANGE&, const RANGE&); std::vector bincodeSerialize() const; @@ -655,8 +655,8 @@ namespace Circuit { }; struct SHA256 { - std::vector inputs; - std::vector outputs; + std::vector inputs; + std::vector outputs; friend bool operator==(const SHA256&, const SHA256&); std::vector bincodeSerialize() const; @@ -664,8 +664,8 @@ namespace Circuit { }; struct Blake2s { - std::vector inputs; - std::vector outputs; + std::vector inputs; + std::vector outputs; friend bool operator==(const Blake2s&, const Blake2s&); std::vector bincodeSerialize() const; @@ -673,8 +673,8 @@ namespace Circuit { }; struct Blake3 { - std::vector inputs; - std::vector outputs; + std::vector inputs; + std::vector outputs; friend bool operator==(const Blake3&, const Blake3&); std::vector bincodeSerialize() const; @@ -682,11 +682,11 @@ namespace Circuit { }; struct SchnorrVerify { - Circuit::FunctionInput public_key_x; - Circuit::FunctionInput public_key_y; - std::vector signature; - std::vector message; - Circuit::Witness output; + Program::FunctionInput public_key_x; + Program::FunctionInput public_key_y; + std::vector signature; + std::vector message; + Program::Witness output; friend bool operator==(const SchnorrVerify&, const SchnorrVerify&); std::vector bincodeSerialize() const; @@ -694,9 +694,9 @@ namespace Circuit { }; struct PedersenCommitment { - std::vector inputs; + std::vector inputs; uint32_t domain_separator; - std::array outputs; + std::array outputs; friend bool operator==(const PedersenCommitment&, const PedersenCommitment&); std::vector bincodeSerialize() const; @@ -704,9 +704,9 @@ namespace Circuit { }; struct PedersenHash { - std::vector inputs; + std::vector inputs; uint32_t domain_separator; - Circuit::Witness output; + Program::Witness output; friend bool operator==(const PedersenHash&, const PedersenHash&); std::vector bincodeSerialize() const; @@ -714,11 +714,11 @@ namespace Circuit { }; struct EcdsaSecp256k1 { - std::vector public_key_x; - std::vector public_key_y; - std::vector signature; - std::vector hashed_message; - Circuit::Witness output; + std::vector public_key_x; + std::vector public_key_y; + std::vector signature; + std::vector hashed_message; + Program::Witness output; friend bool operator==(const EcdsaSecp256k1&, const EcdsaSecp256k1&); std::vector bincodeSerialize() const; @@ -726,11 +726,11 @@ namespace Circuit { }; struct EcdsaSecp256r1 { - std::vector public_key_x; - std::vector public_key_y; - std::vector signature; - std::vector hashed_message; - Circuit::Witness output; + std::vector public_key_x; + std::vector public_key_y; + std::vector signature; + std::vector hashed_message; + Program::Witness output; friend bool operator==(const EcdsaSecp256r1&, const EcdsaSecp256r1&); std::vector bincodeSerialize() const; @@ -738,9 +738,9 @@ namespace Circuit { }; struct FixedBaseScalarMul { - Circuit::FunctionInput low; - Circuit::FunctionInput high; - std::array outputs; + Program::FunctionInput low; + Program::FunctionInput high; + std::array outputs; friend bool operator==(const FixedBaseScalarMul&, const FixedBaseScalarMul&); std::vector bincodeSerialize() const; @@ -748,11 +748,11 @@ namespace Circuit { }; struct EmbeddedCurveAdd { - Circuit::FunctionInput input1_x; - Circuit::FunctionInput input1_y; - Circuit::FunctionInput input2_x; - Circuit::FunctionInput input2_y; - std::array outputs; + Program::FunctionInput input1_x; + Program::FunctionInput input1_y; + Program::FunctionInput input2_x; + Program::FunctionInput input2_y; + std::array outputs; friend bool operator==(const EmbeddedCurveAdd&, const EmbeddedCurveAdd&); std::vector bincodeSerialize() const; @@ -760,8 +760,8 @@ namespace Circuit { }; struct Keccak256 { - std::vector inputs; - std::vector outputs; + std::vector inputs; + std::vector outputs; friend bool operator==(const Keccak256&, const Keccak256&); std::vector bincodeSerialize() const; @@ -769,9 +769,9 @@ namespace Circuit { }; struct Keccak256VariableLength { - std::vector inputs; - Circuit::FunctionInput var_message_size; - std::vector outputs; + std::vector inputs; + Program::FunctionInput var_message_size; + std::vector outputs; friend bool operator==(const Keccak256VariableLength&, const Keccak256VariableLength&); std::vector bincodeSerialize() const; @@ -779,8 +779,8 @@ namespace Circuit { }; struct Keccakf1600 { - std::vector inputs; - std::vector outputs; + std::vector inputs; + std::vector outputs; friend bool operator==(const Keccakf1600&, const Keccakf1600&); std::vector bincodeSerialize() const; @@ -788,10 +788,10 @@ namespace Circuit { }; struct RecursiveAggregation { - std::vector verification_key; - std::vector proof; - std::vector public_inputs; - Circuit::FunctionInput key_hash; + std::vector verification_key; + std::vector proof; + std::vector public_inputs; + Program::FunctionInput key_hash; friend bool operator==(const RecursiveAggregation&, const RecursiveAggregation&); std::vector bincodeSerialize() const; @@ -839,7 +839,7 @@ namespace Circuit { }; struct BigIntFromLeBytes { - std::vector inputs; + std::vector inputs; std::vector modulus; uint32_t output; @@ -850,7 +850,7 @@ namespace Circuit { struct BigIntToLeBytes { uint32_t input; - std::vector outputs; + std::vector outputs; friend bool operator==(const BigIntToLeBytes&, const BigIntToLeBytes&); std::vector bincodeSerialize() const; @@ -858,8 +858,8 @@ namespace Circuit { }; struct Poseidon2Permutation { - std::vector inputs; - std::vector outputs; + std::vector inputs; + std::vector outputs; uint32_t len; friend bool operator==(const Poseidon2Permutation&, const Poseidon2Permutation&); @@ -868,9 +868,9 @@ namespace Circuit { }; struct Sha256Compression { - std::vector inputs; - std::vector hash_values; - std::vector outputs; + std::vector inputs; + std::vector hash_values; + std::vector outputs; friend bool operator==(const Sha256Compression&, const Sha256Compression&); std::vector bincodeSerialize() const; @@ -893,8 +893,8 @@ namespace Circuit { }; struct Expression { - std::vector> mul_terms; - std::vector> linear_combinations; + std::vector> mul_terms; + std::vector> linear_combinations; std::string q_c; friend bool operator==(const Expression&, const Expression&); @@ -905,7 +905,7 @@ namespace Circuit { struct BrilligInputs { struct Single { - Circuit::Expression value; + Program::Expression value; friend bool operator==(const Single&, const Single&); std::vector bincodeSerialize() const; @@ -913,7 +913,7 @@ namespace Circuit { }; struct Array { - std::vector value; + std::vector value; friend bool operator==(const Array&, const Array&); std::vector bincodeSerialize() const; @@ -921,7 +921,7 @@ namespace Circuit { }; struct MemoryArray { - Circuit::BlockId value; + Program::BlockId value; friend bool operator==(const MemoryArray&, const MemoryArray&); std::vector bincodeSerialize() const; @@ -938,7 +938,7 @@ namespace Circuit { struct BrilligOutputs { struct Simple { - Circuit::Witness value; + Program::Witness value; friend bool operator==(const Simple&, const Simple&); std::vector bincodeSerialize() const; @@ -946,7 +946,7 @@ namespace Circuit { }; struct Array { - std::vector value; + std::vector value; friend bool operator==(const Array&, const Array&); std::vector bincodeSerialize() const; @@ -961,10 +961,10 @@ namespace Circuit { }; struct Brillig { - std::vector inputs; - std::vector outputs; - std::vector bytecode; - std::optional predicate; + std::vector inputs; + std::vector outputs; + std::vector bytecode; + std::optional predicate; friend bool operator==(const Brillig&, const Brillig&); std::vector bincodeSerialize() const; @@ -974,8 +974,8 @@ namespace Circuit { struct Directive { struct ToLeRadix { - Circuit::Expression a; - std::vector b; + Program::Expression a; + std::vector b; uint32_t radix; friend bool operator==(const ToLeRadix&, const ToLeRadix&); @@ -991,9 +991,9 @@ namespace Circuit { }; struct MemOp { - Circuit::Expression operation; - Circuit::Expression index; - Circuit::Expression value; + Program::Expression operation; + Program::Expression index; + Program::Expression value; friend bool operator==(const MemOp&, const MemOp&); std::vector bincodeSerialize() const; @@ -1003,7 +1003,7 @@ namespace Circuit { struct Opcode { struct AssertZero { - Circuit::Expression value; + Program::Expression value; friend bool operator==(const AssertZero&, const AssertZero&); std::vector bincodeSerialize() const; @@ -1011,7 +1011,7 @@ namespace Circuit { }; struct BlackBoxFuncCall { - Circuit::BlackBoxFuncCall value; + Program::BlackBoxFuncCall value; friend bool operator==(const BlackBoxFuncCall&, const BlackBoxFuncCall&); std::vector bincodeSerialize() const; @@ -1019,7 +1019,7 @@ namespace Circuit { }; struct Directive { - Circuit::Directive value; + Program::Directive value; friend bool operator==(const Directive&, const Directive&); std::vector bincodeSerialize() const; @@ -1027,7 +1027,7 @@ namespace Circuit { }; struct Brillig { - Circuit::Brillig value; + Program::Brillig value; friend bool operator==(const Brillig&, const Brillig&); std::vector bincodeSerialize() const; @@ -1035,9 +1035,9 @@ namespace Circuit { }; struct MemoryOp { - Circuit::BlockId block_id; - Circuit::MemOp op; - std::optional predicate; + Program::BlockId block_id; + Program::MemOp op; + std::optional predicate; friend bool operator==(const MemoryOp&, const MemoryOp&); std::vector bincodeSerialize() const; @@ -1045,8 +1045,8 @@ namespace Circuit { }; struct MemoryInit { - Circuit::BlockId block_id; - std::vector init; + Program::BlockId block_id; + std::vector init; friend bool operator==(const MemoryInit&, const MemoryInit&); std::vector bincodeSerialize() const; @@ -1055,8 +1055,8 @@ namespace Circuit { struct Call { uint32_t id; - std::vector inputs; - std::vector outputs; + std::vector inputs; + std::vector outputs; friend bool operator==(const Call&, const Call&); std::vector bincodeSerialize() const; @@ -1120,7 +1120,7 @@ namespace Circuit { }; struct PublicInputs { - std::vector value; + std::vector value; friend bool operator==(const PublicInputs&, const PublicInputs&); std::vector bincodeSerialize() const; @@ -1129,12 +1129,12 @@ namespace Circuit { struct Circuit { uint32_t current_witness_index; - std::vector opcodes; - Circuit::ExpressionWidth expression_width; - std::vector private_parameters; - Circuit::PublicInputs public_parameters; - Circuit::PublicInputs return_values; - std::vector> assert_messages; + std::vector opcodes; + Program::ExpressionWidth expression_width; + std::vector private_parameters; + Program::PublicInputs public_parameters; + Program::PublicInputs return_values; + std::vector> assert_messages; bool recursive; friend bool operator==(const Circuit&, const Circuit&); @@ -1142,10 +1142,18 @@ namespace Circuit { static Circuit bincodeDeserialize(std::vector); }; -} // end of namespace Circuit + struct Program { + std::vector functions; + friend bool operator==(const Program&, const Program&); + std::vector bincodeSerialize() const; + static Program bincodeDeserialize(std::vector); + }; + +} // end of namespace Program -namespace Circuit { + +namespace Program { inline bool operator==(const BinaryFieldOp &lhs, const BinaryFieldOp &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -1167,11 +1175,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryFieldOp &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BinaryFieldOp &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -1179,15 +1187,15 @@ void serde::Serializable::serialize(const Circuit::Binar template <> template -Circuit::BinaryFieldOp serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::BinaryFieldOp serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::BinaryFieldOp obj; + Program::BinaryFieldOp obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryFieldOp::Add &lhs, const BinaryFieldOp::Add &rhs) { return true; @@ -1208,21 +1216,21 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryFieldOp::Add &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BinaryFieldOp::Add &obj, Serializer &serializer) { } template <> template -Circuit::BinaryFieldOp::Add serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BinaryFieldOp::Add obj; +Program::BinaryFieldOp::Add serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryFieldOp::Add obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryFieldOp::Sub &lhs, const BinaryFieldOp::Sub &rhs) { return true; @@ -1243,21 +1251,21 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryFieldOp::Sub &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BinaryFieldOp::Sub &obj, Serializer &serializer) { } template <> template -Circuit::BinaryFieldOp::Sub serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BinaryFieldOp::Sub obj; +Program::BinaryFieldOp::Sub serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryFieldOp::Sub obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryFieldOp::Mul &lhs, const BinaryFieldOp::Mul &rhs) { return true; @@ -1278,21 +1286,21 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryFieldOp::Mul &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BinaryFieldOp::Mul &obj, Serializer &serializer) { } template <> template -Circuit::BinaryFieldOp::Mul serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BinaryFieldOp::Mul obj; +Program::BinaryFieldOp::Mul serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryFieldOp::Mul obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryFieldOp::Div &lhs, const BinaryFieldOp::Div &rhs) { return true; @@ -1313,21 +1321,21 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryFieldOp::Div &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BinaryFieldOp::Div &obj, Serializer &serializer) { } template <> template -Circuit::BinaryFieldOp::Div serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BinaryFieldOp::Div obj; +Program::BinaryFieldOp::Div serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryFieldOp::Div obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryFieldOp::Equals &lhs, const BinaryFieldOp::Equals &rhs) { return true; @@ -1348,21 +1356,21 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryFieldOp::Equals &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BinaryFieldOp::Equals &obj, Serializer &serializer) { } template <> template -Circuit::BinaryFieldOp::Equals serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BinaryFieldOp::Equals obj; +Program::BinaryFieldOp::Equals serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryFieldOp::Equals obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp &lhs, const BinaryIntOp &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -1384,11 +1392,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryIntOp &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BinaryIntOp &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -1396,15 +1404,15 @@ void serde::Serializable::serialize(const Circuit::BinaryI template <> template -Circuit::BinaryIntOp serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::BinaryIntOp serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::BinaryIntOp obj; + Program::BinaryIntOp obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp::Add &lhs, const BinaryIntOp::Add &rhs) { return true; @@ -1425,21 +1433,21 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryIntOp::Add &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BinaryIntOp::Add &obj, Serializer &serializer) { } template <> template -Circuit::BinaryIntOp::Add serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BinaryIntOp::Add obj; +Program::BinaryIntOp::Add serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryIntOp::Add obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp::Sub &lhs, const BinaryIntOp::Sub &rhs) { return true; @@ -1460,21 +1468,21 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryIntOp::Sub &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BinaryIntOp::Sub &obj, Serializer &serializer) { } template <> template -Circuit::BinaryIntOp::Sub serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BinaryIntOp::Sub obj; +Program::BinaryIntOp::Sub serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryIntOp::Sub obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp::Mul &lhs, const BinaryIntOp::Mul &rhs) { return true; @@ -1495,21 +1503,21 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryIntOp::Mul &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BinaryIntOp::Mul &obj, Serializer &serializer) { } template <> template -Circuit::BinaryIntOp::Mul serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BinaryIntOp::Mul obj; +Program::BinaryIntOp::Mul serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryIntOp::Mul obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp::SignedDiv &lhs, const BinaryIntOp::SignedDiv &rhs) { return true; @@ -1530,21 +1538,21 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryIntOp::SignedDiv &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BinaryIntOp::SignedDiv &obj, Serializer &serializer) { } template <> template -Circuit::BinaryIntOp::SignedDiv serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BinaryIntOp::SignedDiv obj; +Program::BinaryIntOp::SignedDiv serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryIntOp::SignedDiv obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp::UnsignedDiv &lhs, const BinaryIntOp::UnsignedDiv &rhs) { return true; @@ -1565,21 +1573,21 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryIntOp::UnsignedDiv &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BinaryIntOp::UnsignedDiv &obj, Serializer &serializer) { } template <> template -Circuit::BinaryIntOp::UnsignedDiv serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BinaryIntOp::UnsignedDiv obj; +Program::BinaryIntOp::UnsignedDiv serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryIntOp::UnsignedDiv obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp::Equals &lhs, const BinaryIntOp::Equals &rhs) { return true; @@ -1600,21 +1608,21 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryIntOp::Equals &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BinaryIntOp::Equals &obj, Serializer &serializer) { } template <> template -Circuit::BinaryIntOp::Equals serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BinaryIntOp::Equals obj; +Program::BinaryIntOp::Equals serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryIntOp::Equals obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp::LessThan &lhs, const BinaryIntOp::LessThan &rhs) { return true; @@ -1635,21 +1643,21 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryIntOp::LessThan &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BinaryIntOp::LessThan &obj, Serializer &serializer) { } template <> template -Circuit::BinaryIntOp::LessThan serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BinaryIntOp::LessThan obj; +Program::BinaryIntOp::LessThan serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryIntOp::LessThan obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp::LessThanEquals &lhs, const BinaryIntOp::LessThanEquals &rhs) { return true; @@ -1670,21 +1678,21 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryIntOp::LessThanEquals &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BinaryIntOp::LessThanEquals &obj, Serializer &serializer) { } template <> template -Circuit::BinaryIntOp::LessThanEquals serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BinaryIntOp::LessThanEquals obj; +Program::BinaryIntOp::LessThanEquals serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryIntOp::LessThanEquals obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp::And &lhs, const BinaryIntOp::And &rhs) { return true; @@ -1705,21 +1713,21 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryIntOp::And &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BinaryIntOp::And &obj, Serializer &serializer) { } template <> template -Circuit::BinaryIntOp::And serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BinaryIntOp::And obj; +Program::BinaryIntOp::And serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryIntOp::And obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp::Or &lhs, const BinaryIntOp::Or &rhs) { return true; @@ -1740,21 +1748,21 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryIntOp::Or &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BinaryIntOp::Or &obj, Serializer &serializer) { } template <> template -Circuit::BinaryIntOp::Or serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BinaryIntOp::Or obj; +Program::BinaryIntOp::Or serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryIntOp::Or obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp::Xor &lhs, const BinaryIntOp::Xor &rhs) { return true; @@ -1775,21 +1783,21 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryIntOp::Xor &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BinaryIntOp::Xor &obj, Serializer &serializer) { } template <> template -Circuit::BinaryIntOp::Xor serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BinaryIntOp::Xor obj; +Program::BinaryIntOp::Xor serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryIntOp::Xor obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp::Shl &lhs, const BinaryIntOp::Shl &rhs) { return true; @@ -1810,21 +1818,21 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryIntOp::Shl &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BinaryIntOp::Shl &obj, Serializer &serializer) { } template <> template -Circuit::BinaryIntOp::Shl serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BinaryIntOp::Shl obj; +Program::BinaryIntOp::Shl serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryIntOp::Shl obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp::Shr &lhs, const BinaryIntOp::Shr &rhs) { return true; @@ -1845,21 +1853,21 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryIntOp::Shr &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BinaryIntOp::Shr &obj, Serializer &serializer) { } template <> template -Circuit::BinaryIntOp::Shr serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BinaryIntOp::Shr obj; +Program::BinaryIntOp::Shr serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryIntOp::Shr obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall &lhs, const BlackBoxFuncCall &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -1881,11 +1889,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -1893,15 +1901,15 @@ void serde::Serializable::serialize(const Circuit::Bl template <> template -Circuit::BlackBoxFuncCall serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::BlackBoxFuncCall serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::BlackBoxFuncCall obj; + Program::BlackBoxFuncCall obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::AND &lhs, const BlackBoxFuncCall::AND &rhs) { if (!(lhs.lhs == rhs.lhs)) { return false; } @@ -1925,11 +1933,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::AND &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::AND &obj, Serializer &serializer) { serde::Serializable::serialize(obj.lhs, serializer); serde::Serializable::serialize(obj.rhs, serializer); serde::Serializable::serialize(obj.output, serializer); @@ -1937,15 +1945,15 @@ void serde::Serializable::serialize(const Circui template <> template -Circuit::BlackBoxFuncCall::AND serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::AND obj; +Program::BlackBoxFuncCall::AND serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::AND obj; obj.lhs = serde::Deserializable::deserialize(deserializer); obj.rhs = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::XOR &lhs, const BlackBoxFuncCall::XOR &rhs) { if (!(lhs.lhs == rhs.lhs)) { return false; } @@ -1969,11 +1977,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::XOR &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::XOR &obj, Serializer &serializer) { serde::Serializable::serialize(obj.lhs, serializer); serde::Serializable::serialize(obj.rhs, serializer); serde::Serializable::serialize(obj.output, serializer); @@ -1981,15 +1989,15 @@ void serde::Serializable::serialize(const Circui template <> template -Circuit::BlackBoxFuncCall::XOR serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::XOR obj; +Program::BlackBoxFuncCall::XOR serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::XOR obj; obj.lhs = serde::Deserializable::deserialize(deserializer); obj.rhs = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::RANGE &lhs, const BlackBoxFuncCall::RANGE &rhs) { if (!(lhs.input == rhs.input)) { return false; } @@ -2011,23 +2019,23 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::RANGE &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::RANGE &obj, Serializer &serializer) { serde::Serializable::serialize(obj.input, serializer); } template <> template -Circuit::BlackBoxFuncCall::RANGE serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::RANGE obj; +Program::BlackBoxFuncCall::RANGE serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::RANGE obj; obj.input = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::SHA256 &lhs, const BlackBoxFuncCall::SHA256 &rhs) { if (!(lhs.inputs == rhs.inputs)) { return false; } @@ -2050,25 +2058,25 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::SHA256 &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::SHA256 &obj, Serializer &serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.outputs, serializer); } template <> template -Circuit::BlackBoxFuncCall::SHA256 serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::SHA256 obj; +Program::BlackBoxFuncCall::SHA256 serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::SHA256 obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::Blake2s &lhs, const BlackBoxFuncCall::Blake2s &rhs) { if (!(lhs.inputs == rhs.inputs)) { return false; } @@ -2091,25 +2099,25 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::Blake2s &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::Blake2s &obj, Serializer &serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.outputs, serializer); } template <> template -Circuit::BlackBoxFuncCall::Blake2s serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::Blake2s obj; +Program::BlackBoxFuncCall::Blake2s serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::Blake2s obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::Blake3 &lhs, const BlackBoxFuncCall::Blake3 &rhs) { if (!(lhs.inputs == rhs.inputs)) { return false; } @@ -2132,25 +2140,25 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::Blake3 &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::Blake3 &obj, Serializer &serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.outputs, serializer); } template <> template -Circuit::BlackBoxFuncCall::Blake3 serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::Blake3 obj; +Program::BlackBoxFuncCall::Blake3 serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::Blake3 obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::SchnorrVerify &lhs, const BlackBoxFuncCall::SchnorrVerify &rhs) { if (!(lhs.public_key_x == rhs.public_key_x)) { return false; } @@ -2176,11 +2184,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::SchnorrVerify &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::SchnorrVerify &obj, Serializer &serializer) { serde::Serializable::serialize(obj.public_key_x, serializer); serde::Serializable::serialize(obj.public_key_y, serializer); serde::Serializable::serialize(obj.signature, serializer); @@ -2190,8 +2198,8 @@ void serde::Serializable::serialize(co template <> template -Circuit::BlackBoxFuncCall::SchnorrVerify serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::SchnorrVerify obj; +Program::BlackBoxFuncCall::SchnorrVerify serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::SchnorrVerify obj; obj.public_key_x = serde::Deserializable::deserialize(deserializer); obj.public_key_y = serde::Deserializable::deserialize(deserializer); obj.signature = serde::Deserializable::deserialize(deserializer); @@ -2200,7 +2208,7 @@ Circuit::BlackBoxFuncCall::SchnorrVerify serde::Deserializable template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::PedersenCommitment &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::PedersenCommitment &obj, Serializer &serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.domain_separator, serializer); serde::Serializable::serialize(obj.outputs, serializer); @@ -2236,15 +2244,15 @@ void serde::Serializable::seriali template <> template -Circuit::BlackBoxFuncCall::PedersenCommitment serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::PedersenCommitment obj; +Program::BlackBoxFuncCall::PedersenCommitment serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::PedersenCommitment obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.domain_separator = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::PedersenHash &lhs, const BlackBoxFuncCall::PedersenHash &rhs) { if (!(lhs.inputs == rhs.inputs)) { return false; } @@ -2268,11 +2276,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::PedersenHash &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::PedersenHash &obj, Serializer &serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.domain_separator, serializer); serde::Serializable::serialize(obj.output, serializer); @@ -2280,15 +2288,15 @@ void serde::Serializable::serialize(con template <> template -Circuit::BlackBoxFuncCall::PedersenHash serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::PedersenHash obj; +Program::BlackBoxFuncCall::PedersenHash serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::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 { +namespace Program { inline bool operator==(const BlackBoxFuncCall::EcdsaSecp256k1 &lhs, const BlackBoxFuncCall::EcdsaSecp256k1 &rhs) { if (!(lhs.public_key_x == rhs.public_key_x)) { return false; } @@ -2314,11 +2322,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::EcdsaSecp256k1 &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::EcdsaSecp256k1 &obj, Serializer &serializer) { serde::Serializable::serialize(obj.public_key_x, serializer); serde::Serializable::serialize(obj.public_key_y, serializer); serde::Serializable::serialize(obj.signature, serializer); @@ -2328,8 +2336,8 @@ void serde::Serializable::serialize(c template <> template -Circuit::BlackBoxFuncCall::EcdsaSecp256k1 serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::EcdsaSecp256k1 obj; +Program::BlackBoxFuncCall::EcdsaSecp256k1 serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::EcdsaSecp256k1 obj; obj.public_key_x = serde::Deserializable::deserialize(deserializer); obj.public_key_y = serde::Deserializable::deserialize(deserializer); obj.signature = serde::Deserializable::deserialize(deserializer); @@ -2338,7 +2346,7 @@ Circuit::BlackBoxFuncCall::EcdsaSecp256k1 serde::Deserializable template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::EcdsaSecp256r1 &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::EcdsaSecp256r1 &obj, Serializer &serializer) { serde::Serializable::serialize(obj.public_key_x, serializer); serde::Serializable::serialize(obj.public_key_y, serializer); serde::Serializable::serialize(obj.signature, serializer); @@ -2378,8 +2386,8 @@ void serde::Serializable::serialize(c template <> template -Circuit::BlackBoxFuncCall::EcdsaSecp256r1 serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::EcdsaSecp256r1 obj; +Program::BlackBoxFuncCall::EcdsaSecp256r1 serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::EcdsaSecp256r1 obj; obj.public_key_x = serde::Deserializable::deserialize(deserializer); obj.public_key_y = serde::Deserializable::deserialize(deserializer); obj.signature = serde::Deserializable::deserialize(deserializer); @@ -2388,7 +2396,7 @@ Circuit::BlackBoxFuncCall::EcdsaSecp256r1 serde::Deserializable template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::FixedBaseScalarMul &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::FixedBaseScalarMul &obj, Serializer &serializer) { serde::Serializable::serialize(obj.low, serializer); serde::Serializable::serialize(obj.high, serializer); serde::Serializable::serialize(obj.outputs, serializer); @@ -2424,15 +2432,15 @@ void serde::Serializable::seriali template <> template -Circuit::BlackBoxFuncCall::FixedBaseScalarMul serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::FixedBaseScalarMul obj; +Program::BlackBoxFuncCall::FixedBaseScalarMul serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::FixedBaseScalarMul obj; obj.low = serde::Deserializable::deserialize(deserializer); obj.high = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::EmbeddedCurveAdd &lhs, const BlackBoxFuncCall::EmbeddedCurveAdd &rhs) { if (!(lhs.input1_x == rhs.input1_x)) { return false; } @@ -2458,11 +2466,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::EmbeddedCurveAdd &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::EmbeddedCurveAdd &obj, Serializer &serializer) { serde::Serializable::serialize(obj.input1_x, serializer); serde::Serializable::serialize(obj.input1_y, serializer); serde::Serializable::serialize(obj.input2_x, serializer); @@ -2472,8 +2480,8 @@ void serde::Serializable::serialize template <> template -Circuit::BlackBoxFuncCall::EmbeddedCurveAdd serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::EmbeddedCurveAdd obj; +Program::BlackBoxFuncCall::EmbeddedCurveAdd serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::EmbeddedCurveAdd obj; obj.input1_x = serde::Deserializable::deserialize(deserializer); obj.input1_y = serde::Deserializable::deserialize(deserializer); obj.input2_x = serde::Deserializable::deserialize(deserializer); @@ -2482,7 +2490,7 @@ Circuit::BlackBoxFuncCall::EmbeddedCurveAdd serde::Deserializable template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::Keccak256 &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::Keccak256 &obj, Serializer &serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.outputs, serializer); } template <> template -Circuit::BlackBoxFuncCall::Keccak256 serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::Keccak256 obj; +Program::BlackBoxFuncCall::Keccak256 serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::Keccak256 obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::Keccak256VariableLength &lhs, const BlackBoxFuncCall::Keccak256VariableLength &rhs) { if (!(lhs.inputs == rhs.inputs)) { return false; } @@ -2547,11 +2555,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::Keccak256VariableLength &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::Keccak256VariableLength &obj, Serializer &serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.var_message_size, serializer); serde::Serializable::serialize(obj.outputs, serializer); @@ -2559,15 +2567,15 @@ void serde::Serializable::se template <> template -Circuit::BlackBoxFuncCall::Keccak256VariableLength serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::Keccak256VariableLength obj; +Program::BlackBoxFuncCall::Keccak256VariableLength serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::Keccak256VariableLength obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.var_message_size = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::Keccakf1600 &lhs, const BlackBoxFuncCall::Keccakf1600 &rhs) { if (!(lhs.inputs == rhs.inputs)) { return false; } @@ -2590,25 +2598,25 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::Keccakf1600 &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::Keccakf1600 &obj, Serializer &serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.outputs, serializer); } template <> template -Circuit::BlackBoxFuncCall::Keccakf1600 serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::Keccakf1600 obj; +Program::BlackBoxFuncCall::Keccakf1600 serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::Keccakf1600 obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::RecursiveAggregation &lhs, const BlackBoxFuncCall::RecursiveAggregation &rhs) { if (!(lhs.verification_key == rhs.verification_key)) { return false; } @@ -2633,11 +2641,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::RecursiveAggregation &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::RecursiveAggregation &obj, Serializer &serializer) { serde::Serializable::serialize(obj.verification_key, serializer); serde::Serializable::serialize(obj.proof, serializer); serde::Serializable::serialize(obj.public_inputs, serializer); @@ -2646,8 +2654,8 @@ void serde::Serializable::seria template <> template -Circuit::BlackBoxFuncCall::RecursiveAggregation serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::RecursiveAggregation obj; +Program::BlackBoxFuncCall::RecursiveAggregation serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::RecursiveAggregation obj; obj.verification_key = serde::Deserializable::deserialize(deserializer); obj.proof = serde::Deserializable::deserialize(deserializer); obj.public_inputs = serde::Deserializable::deserialize(deserializer); @@ -2655,7 +2663,7 @@ Circuit::BlackBoxFuncCall::RecursiveAggregation serde::Deserializable template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::BigIntAdd &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::BigIntAdd &obj, Serializer &serializer) { serde::Serializable::serialize(obj.lhs, serializer); serde::Serializable::serialize(obj.rhs, serializer); serde::Serializable::serialize(obj.output, serializer); @@ -2691,15 +2699,15 @@ void serde::Serializable::serialize(const template <> template -Circuit::BlackBoxFuncCall::BigIntAdd serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::BigIntAdd obj; +Program::BlackBoxFuncCall::BigIntAdd serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::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 { +namespace Program { inline bool operator==(const BlackBoxFuncCall::BigIntSub &lhs, const BlackBoxFuncCall::BigIntSub &rhs) { if (!(lhs.lhs == rhs.lhs)) { return false; } @@ -2723,11 +2731,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::BigIntSub &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::BigIntSub &obj, Serializer &serializer) { serde::Serializable::serialize(obj.lhs, serializer); serde::Serializable::serialize(obj.rhs, serializer); serde::Serializable::serialize(obj.output, serializer); @@ -2735,15 +2743,15 @@ void serde::Serializable::serialize(const template <> template -Circuit::BlackBoxFuncCall::BigIntSub serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::BigIntSub obj; +Program::BlackBoxFuncCall::BigIntSub serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::BigIntSub obj; obj.lhs = serde::Deserializable::deserialize(deserializer); obj.rhs = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::BigIntMul &lhs, const BlackBoxFuncCall::BigIntMul &rhs) { if (!(lhs.lhs == rhs.lhs)) { return false; } @@ -2767,11 +2775,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::BigIntMul &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::BigIntMul &obj, Serializer &serializer) { serde::Serializable::serialize(obj.lhs, serializer); serde::Serializable::serialize(obj.rhs, serializer); serde::Serializable::serialize(obj.output, serializer); @@ -2779,15 +2787,15 @@ void serde::Serializable::serialize(const template <> template -Circuit::BlackBoxFuncCall::BigIntMul serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::BigIntMul obj; +Program::BlackBoxFuncCall::BigIntMul serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::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 { +namespace Program { inline bool operator==(const BlackBoxFuncCall::BigIntDiv &lhs, const BlackBoxFuncCall::BigIntDiv &rhs) { if (!(lhs.lhs == rhs.lhs)) { return false; } @@ -2811,11 +2819,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::BigIntDiv &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::BigIntDiv &obj, Serializer &serializer) { serde::Serializable::serialize(obj.lhs, serializer); serde::Serializable::serialize(obj.rhs, serializer); serde::Serializable::serialize(obj.output, serializer); @@ -2823,15 +2831,15 @@ void serde::Serializable::serialize(const template <> template -Circuit::BlackBoxFuncCall::BigIntDiv serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::BigIntDiv obj; +Program::BlackBoxFuncCall::BigIntDiv serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::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 { +namespace Program { inline bool operator==(const BlackBoxFuncCall::BigIntFromLeBytes &lhs, const BlackBoxFuncCall::BigIntFromLeBytes &rhs) { if (!(lhs.inputs == rhs.inputs)) { return false; } @@ -2855,11 +2863,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::BigIntFromLeBytes &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::BigIntFromLeBytes &obj, Serializer &serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.modulus, serializer); serde::Serializable::serialize(obj.output, serializer); @@ -2867,15 +2875,15 @@ void serde::Serializable::serializ template <> template -Circuit::BlackBoxFuncCall::BigIntFromLeBytes serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::BigIntFromLeBytes obj; +Program::BlackBoxFuncCall::BigIntFromLeBytes serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::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 { +namespace Program { inline bool operator==(const BlackBoxFuncCall::BigIntToLeBytes &lhs, const BlackBoxFuncCall::BigIntToLeBytes &rhs) { if (!(lhs.input == rhs.input)) { return false; } @@ -2898,25 +2906,25 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::BigIntToLeBytes &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::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; +Program::BlackBoxFuncCall::BigIntToLeBytes serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::BigIntToLeBytes obj; obj.input = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::Poseidon2Permutation &lhs, const BlackBoxFuncCall::Poseidon2Permutation &rhs) { if (!(lhs.inputs == rhs.inputs)) { return false; } @@ -2940,11 +2948,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::Poseidon2Permutation &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::Poseidon2Permutation &obj, Serializer &serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.outputs, serializer); serde::Serializable::serialize(obj.len, serializer); @@ -2952,15 +2960,15 @@ void serde::Serializable::seria template <> template -Circuit::BlackBoxFuncCall::Poseidon2Permutation serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::Poseidon2Permutation obj; +Program::BlackBoxFuncCall::Poseidon2Permutation serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::Poseidon2Permutation obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); obj.len = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::Sha256Compression &lhs, const BlackBoxFuncCall::Sha256Compression &rhs) { if (!(lhs.inputs == rhs.inputs)) { return false; } @@ -2984,11 +2992,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::Sha256Compression &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::Sha256Compression &obj, Serializer &serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.hash_values, serializer); serde::Serializable::serialize(obj.outputs, serializer); @@ -2996,15 +3004,15 @@ void serde::Serializable::serializ template <> template -Circuit::BlackBoxFuncCall::Sha256Compression serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::Sha256Compression obj; +Program::BlackBoxFuncCall::Sha256Compression serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::Sha256Compression obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.hash_values = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxOp &lhs, const BlackBoxOp &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -3026,11 +3034,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxOp &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -3038,15 +3046,15 @@ void serde::Serializable::serialize(const Circuit::BlackBox template <> template -Circuit::BlackBoxOp serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::BlackBoxOp serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::BlackBoxOp obj; + Program::BlackBoxOp obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxOp::Sha256 &lhs, const BlackBoxOp::Sha256 &rhs) { if (!(lhs.message == rhs.message)) { return false; } @@ -3069,25 +3077,25 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::Sha256 &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::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; +Program::BlackBoxOp::Sha256 serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxOp::Sha256 obj; obj.message = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxOp::Blake2s &lhs, const BlackBoxOp::Blake2s &rhs) { if (!(lhs.message == rhs.message)) { return false; } @@ -3110,25 +3118,25 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::Blake2s &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::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; +Program::BlackBoxOp::Blake2s serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxOp::Blake2s obj; obj.message = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxOp::Blake3 &lhs, const BlackBoxOp::Blake3 &rhs) { if (!(lhs.message == rhs.message)) { return false; } @@ -3151,25 +3159,25 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::Blake3 &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::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; +Program::BlackBoxOp::Blake3 serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxOp::Blake3 obj; obj.message = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxOp::Keccak256 &lhs, const BlackBoxOp::Keccak256 &rhs) { if (!(lhs.message == rhs.message)) { return false; } @@ -3192,25 +3200,25 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::Keccak256 &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::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; +Program::BlackBoxOp::Keccak256 serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxOp::Keccak256 obj; obj.message = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxOp::Keccakf1600 &lhs, const BlackBoxOp::Keccakf1600 &rhs) { if (!(lhs.message == rhs.message)) { return false; } @@ -3233,25 +3241,25 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::Keccakf1600 &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::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; +Program::BlackBoxOp::Keccakf1600 serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxOp::Keccakf1600 obj; obj.message = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxOp::EcdsaSecp256k1 &lhs, const BlackBoxOp::EcdsaSecp256k1 &rhs) { if (!(lhs.hashed_msg == rhs.hashed_msg)) { return false; } @@ -3277,11 +3285,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::EcdsaSecp256k1 &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::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); @@ -3291,8 +3299,8 @@ void serde::Serializable::serialize(const C template <> template -Circuit::BlackBoxOp::EcdsaSecp256k1 serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxOp::EcdsaSecp256k1 obj; +Program::BlackBoxOp::EcdsaSecp256k1 serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::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); @@ -3301,7 +3309,7 @@ Circuit::BlackBoxOp::EcdsaSecp256k1 serde::Deserializable template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::EcdsaSecp256r1 &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::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); @@ -3341,8 +3349,8 @@ void serde::Serializable::serialize(const C template <> template -Circuit::BlackBoxOp::EcdsaSecp256r1 serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxOp::EcdsaSecp256r1 obj; +Program::BlackBoxOp::EcdsaSecp256r1 serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::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); @@ -3351,7 +3359,7 @@ Circuit::BlackBoxOp::EcdsaSecp256r1 serde::Deserializable template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::SchnorrVerify &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::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); @@ -3391,8 +3399,8 @@ void serde::Serializable::serialize(const Ci template <> template -Circuit::BlackBoxOp::SchnorrVerify serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxOp::SchnorrVerify obj; +Program::BlackBoxOp::SchnorrVerify serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::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); @@ -3401,7 +3409,7 @@ Circuit::BlackBoxOp::SchnorrVerify serde::Deserializable template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::PedersenCommitment &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxOp::PedersenCommitment &obj, Serializer &serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.domain_separator, serializer); serde::Serializable::serialize(obj.output, serializer); @@ -3437,15 +3445,15 @@ void serde::Serializable::serialize(con template <> template -Circuit::BlackBoxOp::PedersenCommitment serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxOp::PedersenCommitment obj; +Program::BlackBoxOp::PedersenCommitment serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::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 { +namespace Program { inline bool operator==(const BlackBoxOp::PedersenHash &lhs, const BlackBoxOp::PedersenHash &rhs) { if (!(lhs.inputs == rhs.inputs)) { return false; } @@ -3469,11 +3477,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::PedersenHash &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxOp::PedersenHash &obj, Serializer &serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.domain_separator, serializer); serde::Serializable::serialize(obj.output, serializer); @@ -3481,15 +3489,15 @@ void serde::Serializable::serialize(const Cir template <> template -Circuit::BlackBoxOp::PedersenHash serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxOp::PedersenHash obj; +Program::BlackBoxOp::PedersenHash serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::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 { +namespace Program { inline bool operator==(const BlackBoxOp::FixedBaseScalarMul &lhs, const BlackBoxOp::FixedBaseScalarMul &rhs) { if (!(lhs.low == rhs.low)) { return false; } @@ -3513,11 +3521,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::FixedBaseScalarMul &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxOp::FixedBaseScalarMul &obj, Serializer &serializer) { serde::Serializable::serialize(obj.low, serializer); serde::Serializable::serialize(obj.high, serializer); serde::Serializable::serialize(obj.result, serializer); @@ -3525,15 +3533,15 @@ void serde::Serializable::serialize(con template <> template -Circuit::BlackBoxOp::FixedBaseScalarMul serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxOp::FixedBaseScalarMul obj; +Program::BlackBoxOp::FixedBaseScalarMul serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::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 { +namespace Program { inline bool operator==(const BlackBoxOp::EmbeddedCurveAdd &lhs, const BlackBoxOp::EmbeddedCurveAdd &rhs) { if (!(lhs.input1_x == rhs.input1_x)) { return false; } @@ -3559,11 +3567,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::EmbeddedCurveAdd &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxOp::EmbeddedCurveAdd &obj, Serializer &serializer) { serde::Serializable::serialize(obj.input1_x, serializer); serde::Serializable::serialize(obj.input1_y, serializer); serde::Serializable::serialize(obj.input2_x, serializer); @@ -3573,8 +3581,8 @@ void serde::Serializable::serialize(const template <> template -Circuit::BlackBoxOp::EmbeddedCurveAdd serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxOp::EmbeddedCurveAdd obj; +Program::BlackBoxOp::EmbeddedCurveAdd serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxOp::EmbeddedCurveAdd obj; obj.input1_x = serde::Deserializable::deserialize(deserializer); obj.input1_y = serde::Deserializable::deserialize(deserializer); obj.input2_x = serde::Deserializable::deserialize(deserializer); @@ -3583,7 +3591,7 @@ Circuit::BlackBoxOp::EmbeddedCurveAdd serde::Deserializable template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::BigIntAdd &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxOp::BigIntAdd &obj, Serializer &serializer) { serde::Serializable::serialize(obj.lhs, serializer); serde::Serializable::serialize(obj.rhs, serializer); serde::Serializable::serialize(obj.output, serializer); @@ -3619,15 +3627,15 @@ void serde::Serializable::serialize(const Circui template <> template -Circuit::BlackBoxOp::BigIntAdd serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxOp::BigIntAdd obj; +Program::BlackBoxOp::BigIntAdd serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::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 { +namespace Program { inline bool operator==(const BlackBoxOp::BigIntSub &lhs, const BlackBoxOp::BigIntSub &rhs) { if (!(lhs.lhs == rhs.lhs)) { return false; } @@ -3651,11 +3659,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::BigIntSub &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxOp::BigIntSub &obj, Serializer &serializer) { serde::Serializable::serialize(obj.lhs, serializer); serde::Serializable::serialize(obj.rhs, serializer); serde::Serializable::serialize(obj.output, serializer); @@ -3663,15 +3671,15 @@ void serde::Serializable::serialize(const Circui template <> template -Circuit::BlackBoxOp::BigIntSub serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxOp::BigIntSub obj; +Program::BlackBoxOp::BigIntSub serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxOp::BigIntSub obj; obj.lhs = serde::Deserializable::deserialize(deserializer); obj.rhs = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxOp::BigIntMul &lhs, const BlackBoxOp::BigIntMul &rhs) { if (!(lhs.lhs == rhs.lhs)) { return false; } @@ -3695,11 +3703,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::BigIntMul &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxOp::BigIntMul &obj, Serializer &serializer) { serde::Serializable::serialize(obj.lhs, serializer); serde::Serializable::serialize(obj.rhs, serializer); serde::Serializable::serialize(obj.output, serializer); @@ -3707,15 +3715,15 @@ void serde::Serializable::serialize(const Circui template <> template -Circuit::BlackBoxOp::BigIntMul serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxOp::BigIntMul obj; +Program::BlackBoxOp::BigIntMul serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::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 { +namespace Program { inline bool operator==(const BlackBoxOp::BigIntDiv &lhs, const BlackBoxOp::BigIntDiv &rhs) { if (!(lhs.lhs == rhs.lhs)) { return false; } @@ -3739,11 +3747,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::BigIntDiv &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxOp::BigIntDiv &obj, Serializer &serializer) { serde::Serializable::serialize(obj.lhs, serializer); serde::Serializable::serialize(obj.rhs, serializer); serde::Serializable::serialize(obj.output, serializer); @@ -3751,15 +3759,15 @@ void serde::Serializable::serialize(const Circui template <> template -Circuit::BlackBoxOp::BigIntDiv serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxOp::BigIntDiv obj; +Program::BlackBoxOp::BigIntDiv serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::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 { +namespace Program { inline bool operator==(const BlackBoxOp::BigIntFromLeBytes &lhs, const BlackBoxOp::BigIntFromLeBytes &rhs) { if (!(lhs.inputs == rhs.inputs)) { return false; } @@ -3783,11 +3791,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::BigIntFromLeBytes &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxOp::BigIntFromLeBytes &obj, Serializer &serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.modulus, serializer); serde::Serializable::serialize(obj.output, serializer); @@ -3795,15 +3803,15 @@ void serde::Serializable::serialize(cons template <> template -Circuit::BlackBoxOp::BigIntFromLeBytes serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxOp::BigIntFromLeBytes obj; +Program::BlackBoxOp::BigIntFromLeBytes serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::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 { +namespace Program { inline bool operator==(const BlackBoxOp::BigIntToLeBytes &lhs, const BlackBoxOp::BigIntToLeBytes &rhs) { if (!(lhs.input == rhs.input)) { return false; } @@ -3826,25 +3834,25 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::BigIntToLeBytes &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::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; +Program::BlackBoxOp::BigIntToLeBytes serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxOp::BigIntToLeBytes obj; obj.input = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxOp::Poseidon2Permutation &lhs, const BlackBoxOp::Poseidon2Permutation &rhs) { if (!(lhs.message == rhs.message)) { return false; } @@ -3868,11 +3876,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::Poseidon2Permutation &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxOp::Poseidon2Permutation &obj, Serializer &serializer) { serde::Serializable::serialize(obj.message, serializer); serde::Serializable::serialize(obj.output, serializer); serde::Serializable::serialize(obj.len, serializer); @@ -3880,15 +3888,15 @@ void serde::Serializable::serialize(c template <> template -Circuit::BlackBoxOp::Poseidon2Permutation serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxOp::Poseidon2Permutation obj; +Program::BlackBoxOp::Poseidon2Permutation serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxOp::Poseidon2Permutation obj; obj.message = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); obj.len = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxOp::Sha256Compression &lhs, const BlackBoxOp::Sha256Compression &rhs) { if (!(lhs.input == rhs.input)) { return false; } @@ -3912,11 +3920,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::Sha256Compression &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxOp::Sha256Compression &obj, Serializer &serializer) { serde::Serializable::serialize(obj.input, serializer); serde::Serializable::serialize(obj.hash_values, serializer); serde::Serializable::serialize(obj.output, serializer); @@ -3924,15 +3932,15 @@ void serde::Serializable::serialize(cons template <> template -Circuit::BlackBoxOp::Sha256Compression serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxOp::Sha256Compression obj; +Program::BlackBoxOp::Sha256Compression serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxOp::Sha256Compression obj; obj.input = serde::Deserializable::deserialize(deserializer); obj.hash_values = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlockId &lhs, const BlockId &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -3954,11 +3962,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlockId &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlockId &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -3966,15 +3974,15 @@ void serde::Serializable::serialize(const Circuit::BlockId &ob template <> template -Circuit::BlockId serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::BlockId serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::BlockId obj; + Program::BlockId obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Brillig &lhs, const Brillig &rhs) { if (!(lhs.inputs == rhs.inputs)) { return false; } @@ -3999,11 +4007,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Brillig &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::Brillig &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.outputs, serializer); @@ -4014,9 +4022,9 @@ void serde::Serializable::serialize(const Circuit::Brillig &ob template <> template -Circuit::Brillig serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::Brillig serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::Brillig obj; + Program::Brillig obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); obj.bytecode = serde::Deserializable::deserialize(deserializer); @@ -4025,7 +4033,7 @@ Circuit::Brillig serde::Deserializable::deserialize(Deserializ return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligInputs &lhs, const BrilligInputs &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -4047,11 +4055,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligInputs &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligInputs &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -4059,15 +4067,15 @@ void serde::Serializable::serialize(const Circuit::Brill template <> template -Circuit::BrilligInputs serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::BrilligInputs serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::BrilligInputs obj; + Program::BrilligInputs obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligInputs::Single &lhs, const BrilligInputs::Single &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -4089,23 +4097,23 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligInputs::Single &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligInputs::Single &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value, serializer); } template <> template -Circuit::BrilligInputs::Single serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligInputs::Single obj; +Program::BrilligInputs::Single serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligInputs::Single obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligInputs::Array &lhs, const BrilligInputs::Array &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -4127,23 +4135,23 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligInputs::Array &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligInputs::Array &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value, serializer); } template <> template -Circuit::BrilligInputs::Array serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligInputs::Array obj; +Program::BrilligInputs::Array serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligInputs::Array obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligInputs::MemoryArray &lhs, const BrilligInputs::MemoryArray &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -4165,23 +4173,23 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligInputs::MemoryArray &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligInputs::MemoryArray &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value, serializer); } template <> template -Circuit::BrilligInputs::MemoryArray serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligInputs::MemoryArray obj; +Program::BrilligInputs::MemoryArray serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligInputs::MemoryArray obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode &lhs, const BrilligOpcode &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -4203,11 +4211,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOpcode &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligOpcode &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -4215,15 +4223,15 @@ void serde::Serializable::serialize(const Circuit::Brill template <> template -Circuit::BrilligOpcode serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::BrilligOpcode serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::BrilligOpcode obj; + Program::BrilligOpcode obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::BinaryFieldOp &lhs, const BrilligOpcode::BinaryFieldOp &rhs) { if (!(lhs.destination == rhs.destination)) { return false; } @@ -4248,11 +4256,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::BinaryFieldOp &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligOpcode::BinaryFieldOp &obj, Serializer &serializer) { serde::Serializable::serialize(obj.destination, serializer); serde::Serializable::serialize(obj.op, serializer); serde::Serializable::serialize(obj.lhs, serializer); @@ -4261,8 +4269,8 @@ void serde::Serializable::serialize(const template <> template -Circuit::BrilligOpcode::BinaryFieldOp serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligOpcode::BinaryFieldOp obj; +Program::BrilligOpcode::BinaryFieldOp serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::BinaryFieldOp obj; obj.destination = serde::Deserializable::deserialize(deserializer); obj.op = serde::Deserializable::deserialize(deserializer); obj.lhs = serde::Deserializable::deserialize(deserializer); @@ -4270,7 +4278,7 @@ Circuit::BrilligOpcode::BinaryFieldOp serde::Deserializable template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::BinaryIntOp &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligOpcode::BinaryIntOp &obj, Serializer &serializer) { serde::Serializable::serialize(obj.destination, serializer); serde::Serializable::serialize(obj.op, serializer); serde::Serializable::serialize(obj.bit_size, serializer); @@ -4310,8 +4318,8 @@ void serde::Serializable::serialize(const C template <> template -Circuit::BrilligOpcode::BinaryIntOp serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligOpcode::BinaryIntOp obj; +Program::BrilligOpcode::BinaryIntOp serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::BinaryIntOp obj; obj.destination = serde::Deserializable::deserialize(deserializer); obj.op = serde::Deserializable::deserialize(deserializer); obj.bit_size = serde::Deserializable::deserialize(deserializer); @@ -4320,7 +4328,7 @@ Circuit::BrilligOpcode::BinaryIntOp serde::Deserializable template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::Cast &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligOpcode::Cast &obj, Serializer &serializer) { serde::Serializable::serialize(obj.destination, serializer); serde::Serializable::serialize(obj.source, serializer); serde::Serializable::serialize(obj.bit_size, serializer); @@ -4356,15 +4364,15 @@ void serde::Serializable::serialize(const Circuit: template <> template -Circuit::BrilligOpcode::Cast serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligOpcode::Cast obj; +Program::BrilligOpcode::Cast serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::Cast obj; obj.destination = serde::Deserializable::deserialize(deserializer); obj.source = serde::Deserializable::deserialize(deserializer); obj.bit_size = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::JumpIfNot &lhs, const BrilligOpcode::JumpIfNot &rhs) { if (!(lhs.condition == rhs.condition)) { return false; } @@ -4387,25 +4395,25 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::JumpIfNot &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligOpcode::JumpIfNot &obj, Serializer &serializer) { serde::Serializable::serialize(obj.condition, serializer); serde::Serializable::serialize(obj.location, serializer); } template <> template -Circuit::BrilligOpcode::JumpIfNot serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligOpcode::JumpIfNot obj; +Program::BrilligOpcode::JumpIfNot serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::JumpIfNot obj; obj.condition = serde::Deserializable::deserialize(deserializer); obj.location = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::JumpIf &lhs, const BrilligOpcode::JumpIf &rhs) { if (!(lhs.condition == rhs.condition)) { return false; } @@ -4428,25 +4436,25 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::JumpIf &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligOpcode::JumpIf &obj, Serializer &serializer) { serde::Serializable::serialize(obj.condition, serializer); serde::Serializable::serialize(obj.location, serializer); } template <> template -Circuit::BrilligOpcode::JumpIf serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligOpcode::JumpIf obj; +Program::BrilligOpcode::JumpIf serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::JumpIf obj; obj.condition = serde::Deserializable::deserialize(deserializer); obj.location = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::Jump &lhs, const BrilligOpcode::Jump &rhs) { if (!(lhs.location == rhs.location)) { return false; } @@ -4468,23 +4476,23 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::Jump &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligOpcode::Jump &obj, Serializer &serializer) { serde::Serializable::serialize(obj.location, serializer); } template <> template -Circuit::BrilligOpcode::Jump serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligOpcode::Jump obj; +Program::BrilligOpcode::Jump serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::Jump obj; obj.location = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::CalldataCopy &lhs, const BrilligOpcode::CalldataCopy &rhs) { if (!(lhs.destination_address == rhs.destination_address)) { return false; } @@ -4508,11 +4516,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::CalldataCopy &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligOpcode::CalldataCopy &obj, Serializer &serializer) { serde::Serializable::serialize(obj.destination_address, serializer); serde::Serializable::serialize(obj.size, serializer); serde::Serializable::serialize(obj.offset, serializer); @@ -4520,15 +4528,15 @@ void serde::Serializable::serialize(const template <> template -Circuit::BrilligOpcode::CalldataCopy serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligOpcode::CalldataCopy obj; +Program::BrilligOpcode::CalldataCopy serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::CalldataCopy obj; obj.destination_address = serde::Deserializable::deserialize(deserializer); obj.size = serde::Deserializable::deserialize(deserializer); obj.offset = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::Call &lhs, const BrilligOpcode::Call &rhs) { if (!(lhs.location == rhs.location)) { return false; } @@ -4550,23 +4558,23 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::Call &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligOpcode::Call &obj, Serializer &serializer) { serde::Serializable::serialize(obj.location, serializer); } template <> template -Circuit::BrilligOpcode::Call serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligOpcode::Call obj; +Program::BrilligOpcode::Call serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::Call obj; obj.location = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::Const &lhs, const BrilligOpcode::Const &rhs) { if (!(lhs.destination == rhs.destination)) { return false; } @@ -4590,11 +4598,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::Const &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligOpcode::Const &obj, Serializer &serializer) { serde::Serializable::serialize(obj.destination, serializer); serde::Serializable::serialize(obj.bit_size, serializer); serde::Serializable::serialize(obj.value, serializer); @@ -4602,15 +4610,15 @@ void serde::Serializable::serialize(const Circuit template <> template -Circuit::BrilligOpcode::Const serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligOpcode::Const obj; +Program::BrilligOpcode::Const serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::Const obj; obj.destination = serde::Deserializable::deserialize(deserializer); obj.bit_size = serde::Deserializable::deserialize(deserializer); obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::Return &lhs, const BrilligOpcode::Return &rhs) { return true; @@ -4631,21 +4639,21 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::Return &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligOpcode::Return &obj, Serializer &serializer) { } template <> template -Circuit::BrilligOpcode::Return serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligOpcode::Return obj; +Program::BrilligOpcode::Return serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::Return obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::ForeignCall &lhs, const BrilligOpcode::ForeignCall &rhs) { if (!(lhs.function == rhs.function)) { return false; } @@ -4671,11 +4679,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::ForeignCall &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligOpcode::ForeignCall &obj, Serializer &serializer) { serde::Serializable::serialize(obj.function, serializer); serde::Serializable::serialize(obj.destinations, serializer); serde::Serializable::serialize(obj.destination_value_types, serializer); @@ -4685,8 +4693,8 @@ void serde::Serializable::serialize(const C template <> template -Circuit::BrilligOpcode::ForeignCall serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligOpcode::ForeignCall obj; +Program::BrilligOpcode::ForeignCall serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::ForeignCall obj; obj.function = serde::Deserializable::deserialize(deserializer); obj.destinations = serde::Deserializable::deserialize(deserializer); obj.destination_value_types = serde::Deserializable::deserialize(deserializer); @@ -4695,7 +4703,7 @@ Circuit::BrilligOpcode::ForeignCall serde::Deserializable template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::Mov &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligOpcode::Mov &obj, Serializer &serializer) { serde::Serializable::serialize(obj.destination, serializer); serde::Serializable::serialize(obj.source, serializer); } template <> template -Circuit::BrilligOpcode::Mov serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligOpcode::Mov obj; +Program::BrilligOpcode::Mov serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::Mov obj; obj.destination = serde::Deserializable::deserialize(deserializer); obj.source = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::Load &lhs, const BrilligOpcode::Load &rhs) { if (!(lhs.destination == rhs.destination)) { return false; } @@ -4759,25 +4767,25 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::Load &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligOpcode::Load &obj, Serializer &serializer) { serde::Serializable::serialize(obj.destination, serializer); serde::Serializable::serialize(obj.source_pointer, serializer); } template <> template -Circuit::BrilligOpcode::Load serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligOpcode::Load obj; +Program::BrilligOpcode::Load serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::Load obj; obj.destination = serde::Deserializable::deserialize(deserializer); obj.source_pointer = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::Store &lhs, const BrilligOpcode::Store &rhs) { if (!(lhs.destination_pointer == rhs.destination_pointer)) { return false; } @@ -4800,25 +4808,25 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::Store &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligOpcode::Store &obj, Serializer &serializer) { serde::Serializable::serialize(obj.destination_pointer, serializer); serde::Serializable::serialize(obj.source, serializer); } template <> template -Circuit::BrilligOpcode::Store serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligOpcode::Store obj; +Program::BrilligOpcode::Store serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::Store obj; obj.destination_pointer = serde::Deserializable::deserialize(deserializer); obj.source = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::BlackBox &lhs, const BrilligOpcode::BlackBox &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -4840,23 +4848,23 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::BlackBox &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligOpcode::BlackBox &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value, serializer); } template <> template -Circuit::BrilligOpcode::BlackBox serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligOpcode::BlackBox obj; +Program::BrilligOpcode::BlackBox serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::BlackBox obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::Trap &lhs, const BrilligOpcode::Trap &rhs) { return true; @@ -4877,21 +4885,21 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::Trap &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligOpcode::Trap &obj, Serializer &serializer) { } template <> template -Circuit::BrilligOpcode::Trap serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligOpcode::Trap obj; +Program::BrilligOpcode::Trap serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::Trap obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::Stop &lhs, const BrilligOpcode::Stop &rhs) { if (!(lhs.return_data_offset == rhs.return_data_offset)) { return false; } @@ -4914,25 +4922,25 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::Stop &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligOpcode::Stop &obj, Serializer &serializer) { serde::Serializable::serialize(obj.return_data_offset, serializer); serde::Serializable::serialize(obj.return_data_size, serializer); } template <> template -Circuit::BrilligOpcode::Stop serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligOpcode::Stop obj; +Program::BrilligOpcode::Stop serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::Stop obj; obj.return_data_offset = serde::Deserializable::deserialize(deserializer); obj.return_data_size = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOutputs &lhs, const BrilligOutputs &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -4954,11 +4962,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOutputs &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligOutputs &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -4966,15 +4974,15 @@ void serde::Serializable::serialize(const Circuit::Bril template <> template -Circuit::BrilligOutputs serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::BrilligOutputs serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::BrilligOutputs obj; + Program::BrilligOutputs obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOutputs::Simple &lhs, const BrilligOutputs::Simple &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -4996,23 +5004,23 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOutputs::Simple &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligOutputs::Simple &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value, serializer); } template <> template -Circuit::BrilligOutputs::Simple serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligOutputs::Simple obj; +Program::BrilligOutputs::Simple serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOutputs::Simple obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOutputs::Array &lhs, const BrilligOutputs::Array &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -5034,23 +5042,23 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOutputs::Array &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligOutputs::Array &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value, serializer); } template <> template -Circuit::BrilligOutputs::Array serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligOutputs::Array obj; +Program::BrilligOutputs::Array serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOutputs::Array obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Circuit &lhs, const Circuit &rhs) { if (!(lhs.current_witness_index == rhs.current_witness_index)) { return false; } @@ -5079,11 +5087,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Circuit &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::Circuit &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.current_witness_index, serializer); serde::Serializable::serialize(obj.opcodes, serializer); @@ -5098,9 +5106,9 @@ void serde::Serializable::serialize(const Circuit::Circuit &ob template <> template -Circuit::Circuit serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::Circuit serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::Circuit obj; + Program::Circuit obj; obj.current_witness_index = serde::Deserializable::deserialize(deserializer); obj.opcodes = serde::Deserializable::deserialize(deserializer); obj.expression_width = serde::Deserializable::deserialize(deserializer); @@ -5113,7 +5121,7 @@ Circuit::Circuit serde::Deserializable::deserialize(Deserializ return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Directive &lhs, const Directive &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -5135,11 +5143,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Directive &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::Directive &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -5147,15 +5155,15 @@ void serde::Serializable::serialize(const Circuit::Directive template <> template -Circuit::Directive serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::Directive serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::Directive obj; + Program::Directive obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Directive::ToLeRadix &lhs, const Directive::ToLeRadix &rhs) { if (!(lhs.a == rhs.a)) { return false; } @@ -5179,11 +5187,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Directive::ToLeRadix &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::Directive::ToLeRadix &obj, Serializer &serializer) { serde::Serializable::serialize(obj.a, serializer); serde::Serializable::serialize(obj.b, serializer); serde::Serializable::serialize(obj.radix, serializer); @@ -5191,15 +5199,15 @@ void serde::Serializable::serialize(const Circuit template <> template -Circuit::Directive::ToLeRadix serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::Directive::ToLeRadix obj; +Program::Directive::ToLeRadix serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::Directive::ToLeRadix obj; obj.a = serde::Deserializable::deserialize(deserializer); obj.b = serde::Deserializable::deserialize(deserializer); obj.radix = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Expression &lhs, const Expression &rhs) { if (!(lhs.mul_terms == rhs.mul_terms)) { return false; } @@ -5223,11 +5231,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Expression &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::Expression &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.mul_terms, serializer); serde::Serializable::serialize(obj.linear_combinations, serializer); @@ -5237,9 +5245,9 @@ void serde::Serializable::serialize(const Circuit::Expressi template <> template -Circuit::Expression serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::Expression serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::Expression obj; + Program::Expression obj; obj.mul_terms = serde::Deserializable::deserialize(deserializer); obj.linear_combinations = serde::Deserializable::deserialize(deserializer); obj.q_c = serde::Deserializable::deserialize(deserializer); @@ -5247,7 +5255,7 @@ Circuit::Expression serde::Deserializable::deserialize(Dese return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const ExpressionWidth &lhs, const ExpressionWidth &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -5269,11 +5277,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::ExpressionWidth &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::ExpressionWidth &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -5281,15 +5289,15 @@ void serde::Serializable::serialize(const Circuit::Exp template <> template -Circuit::ExpressionWidth serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::ExpressionWidth serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::ExpressionWidth obj; + Program::ExpressionWidth obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const ExpressionWidth::Unbounded &lhs, const ExpressionWidth::Unbounded &rhs) { return true; @@ -5310,21 +5318,21 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::ExpressionWidth::Unbounded &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::ExpressionWidth::Unbounded &obj, Serializer &serializer) { } template <> template -Circuit::ExpressionWidth::Unbounded serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::ExpressionWidth::Unbounded obj; +Program::ExpressionWidth::Unbounded serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::ExpressionWidth::Unbounded obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const ExpressionWidth::Bounded &lhs, const ExpressionWidth::Bounded &rhs) { if (!(lhs.width == rhs.width)) { return false; } @@ -5346,23 +5354,23 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::ExpressionWidth::Bounded &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::ExpressionWidth::Bounded &obj, Serializer &serializer) { serde::Serializable::serialize(obj.width, serializer); } template <> template -Circuit::ExpressionWidth::Bounded serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::ExpressionWidth::Bounded obj; +Program::ExpressionWidth::Bounded serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::ExpressionWidth::Bounded obj; obj.width = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const FunctionInput &lhs, const FunctionInput &rhs) { if (!(lhs.witness == rhs.witness)) { return false; } @@ -5385,11 +5393,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::FunctionInput &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::FunctionInput &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.witness, serializer); serde::Serializable::serialize(obj.num_bits, serializer); @@ -5398,16 +5406,16 @@ void serde::Serializable::serialize(const Circuit::Funct template <> template -Circuit::FunctionInput serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::FunctionInput serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::FunctionInput obj; + Program::FunctionInput obj; obj.witness = serde::Deserializable::deserialize(deserializer); obj.num_bits = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const HeapArray &lhs, const HeapArray &rhs) { if (!(lhs.pointer == rhs.pointer)) { return false; } @@ -5430,11 +5438,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::HeapArray &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::HeapArray &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.pointer, serializer); serde::Serializable::serialize(obj.size, serializer); @@ -5443,16 +5451,16 @@ void serde::Serializable::serialize(const Circuit::HeapArray template <> template -Circuit::HeapArray serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::HeapArray serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::HeapArray obj; + Program::HeapArray obj; obj.pointer = serde::Deserializable::deserialize(deserializer); obj.size = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const HeapValueType &lhs, const HeapValueType &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -5474,11 +5482,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::HeapValueType &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::HeapValueType &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -5486,15 +5494,15 @@ void serde::Serializable::serialize(const Circuit::HeapV template <> template -Circuit::HeapValueType serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::HeapValueType serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::HeapValueType obj; + Program::HeapValueType obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const HeapValueType::Simple &lhs, const HeapValueType::Simple &rhs) { return true; @@ -5515,21 +5523,21 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::HeapValueType::Simple &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::HeapValueType::Simple &obj, Serializer &serializer) { } template <> template -Circuit::HeapValueType::Simple serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::HeapValueType::Simple obj; +Program::HeapValueType::Simple serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::HeapValueType::Simple obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const HeapValueType::Array &lhs, const HeapValueType::Array &rhs) { if (!(lhs.value_types == rhs.value_types)) { return false; } @@ -5552,25 +5560,25 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::HeapValueType::Array &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::HeapValueType::Array &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value_types, serializer); serde::Serializable::serialize(obj.size, serializer); } template <> template -Circuit::HeapValueType::Array serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::HeapValueType::Array obj; +Program::HeapValueType::Array serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::HeapValueType::Array obj; obj.value_types = serde::Deserializable::deserialize(deserializer); obj.size = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const HeapValueType::Vector &lhs, const HeapValueType::Vector &rhs) { if (!(lhs.value_types == rhs.value_types)) { return false; } @@ -5592,23 +5600,23 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::HeapValueType::Vector &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::HeapValueType::Vector &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value_types, serializer); } template <> template -Circuit::HeapValueType::Vector serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::HeapValueType::Vector obj; +Program::HeapValueType::Vector serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::HeapValueType::Vector obj; obj.value_types = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const HeapVector &lhs, const HeapVector &rhs) { if (!(lhs.pointer == rhs.pointer)) { return false; } @@ -5631,11 +5639,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::HeapVector &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::HeapVector &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.pointer, serializer); serde::Serializable::serialize(obj.size, serializer); @@ -5644,16 +5652,16 @@ void serde::Serializable::serialize(const Circuit::HeapVect template <> template -Circuit::HeapVector serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::HeapVector serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::HeapVector obj; + Program::HeapVector obj; obj.pointer = serde::Deserializable::deserialize(deserializer); obj.size = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const MemOp &lhs, const MemOp &rhs) { if (!(lhs.operation == rhs.operation)) { return false; } @@ -5677,11 +5685,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::MemOp &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::MemOp &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.operation, serializer); serde::Serializable::serialize(obj.index, serializer); @@ -5691,9 +5699,9 @@ void serde::Serializable::serialize(const Circuit::MemOp &obj, S template <> template -Circuit::MemOp serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::MemOp serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::MemOp obj; + Program::MemOp obj; obj.operation = serde::Deserializable::deserialize(deserializer); obj.index = serde::Deserializable::deserialize(deserializer); obj.value = serde::Deserializable::deserialize(deserializer); @@ -5701,7 +5709,7 @@ Circuit::MemOp serde::Deserializable::deserialize(Deserializer & return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const MemoryAddress &lhs, const MemoryAddress &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -5723,11 +5731,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::MemoryAddress &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::MemoryAddress &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -5735,15 +5743,15 @@ void serde::Serializable::serialize(const Circuit::Memor template <> template -Circuit::MemoryAddress serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::MemoryAddress serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::MemoryAddress obj; + Program::MemoryAddress obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Opcode &lhs, const Opcode &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -5765,11 +5773,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Opcode &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::Opcode &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -5777,15 +5785,15 @@ void serde::Serializable::serialize(const Circuit::Opcode &obj, template <> template -Circuit::Opcode serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::Opcode serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::Opcode obj; + Program::Opcode obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Opcode::AssertZero &lhs, const Opcode::AssertZero &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -5807,23 +5815,23 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Opcode::AssertZero &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::Opcode::AssertZero &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value, serializer); } template <> template -Circuit::Opcode::AssertZero serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::Opcode::AssertZero obj; +Program::Opcode::AssertZero serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::Opcode::AssertZero obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Opcode::BlackBoxFuncCall &lhs, const Opcode::BlackBoxFuncCall &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -5845,23 +5853,23 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Opcode::BlackBoxFuncCall &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::Opcode::BlackBoxFuncCall &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value, serializer); } template <> template -Circuit::Opcode::BlackBoxFuncCall serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::Opcode::BlackBoxFuncCall obj; +Program::Opcode::BlackBoxFuncCall serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::Opcode::BlackBoxFuncCall obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Opcode::Directive &lhs, const Opcode::Directive &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -5883,23 +5891,23 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Opcode::Directive &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::Opcode::Directive &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value, serializer); } template <> template -Circuit::Opcode::Directive serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::Opcode::Directive obj; +Program::Opcode::Directive serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::Opcode::Directive obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Opcode::Brillig &lhs, const Opcode::Brillig &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -5921,23 +5929,23 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Opcode::Brillig &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::Opcode::Brillig &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value, serializer); } template <> template -Circuit::Opcode::Brillig serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::Opcode::Brillig obj; +Program::Opcode::Brillig serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::Opcode::Brillig obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Opcode::MemoryOp &lhs, const Opcode::MemoryOp &rhs) { if (!(lhs.block_id == rhs.block_id)) { return false; } @@ -5961,11 +5969,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Opcode::MemoryOp &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::Opcode::MemoryOp &obj, Serializer &serializer) { serde::Serializable::serialize(obj.block_id, serializer); serde::Serializable::serialize(obj.op, serializer); serde::Serializable::serialize(obj.predicate, serializer); @@ -5973,15 +5981,15 @@ void serde::Serializable::serialize(const Circuit::Op template <> template -Circuit::Opcode::MemoryOp serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::Opcode::MemoryOp obj; +Program::Opcode::MemoryOp serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::Opcode::MemoryOp obj; obj.block_id = serde::Deserializable::deserialize(deserializer); obj.op = serde::Deserializable::deserialize(deserializer); obj.predicate = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Opcode::MemoryInit &lhs, const Opcode::MemoryInit &rhs) { if (!(lhs.block_id == rhs.block_id)) { return false; } @@ -6004,25 +6012,25 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Opcode::MemoryInit &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::Opcode::MemoryInit &obj, Serializer &serializer) { serde::Serializable::serialize(obj.block_id, serializer); serde::Serializable::serialize(obj.init, serializer); } template <> template -Circuit::Opcode::MemoryInit serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::Opcode::MemoryInit obj; +Program::Opcode::MemoryInit serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::Opcode::MemoryInit obj; obj.block_id = serde::Deserializable::deserialize(deserializer); obj.init = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Opcode::Call &lhs, const Opcode::Call &rhs) { if (!(lhs.id == rhs.id)) { return false; } @@ -6046,11 +6054,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Opcode::Call &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::Opcode::Call &obj, Serializer &serializer) { serde::Serializable::serialize(obj.id, serializer); serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.outputs, serializer); @@ -6058,15 +6066,15 @@ void serde::Serializable::serialize(const Circuit::Opcode template <> template -Circuit::Opcode::Call serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::Opcode::Call obj; +Program::Opcode::Call serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::Opcode::Call obj; obj.id = serde::Deserializable::deserialize(deserializer); obj.inputs = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const OpcodeLocation &lhs, const OpcodeLocation &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -6088,11 +6096,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::OpcodeLocation &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::OpcodeLocation &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -6100,15 +6108,15 @@ void serde::Serializable::serialize(const Circuit::Opco template <> template -Circuit::OpcodeLocation serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::OpcodeLocation serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::OpcodeLocation obj; + Program::OpcodeLocation obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const OpcodeLocation::Acir &lhs, const OpcodeLocation::Acir &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -6130,23 +6138,23 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::OpcodeLocation::Acir &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::OpcodeLocation::Acir &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value, serializer); } template <> template -Circuit::OpcodeLocation::Acir serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::OpcodeLocation::Acir obj; +Program::OpcodeLocation::Acir serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::OpcodeLocation::Acir obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const OpcodeLocation::Brillig &lhs, const OpcodeLocation::Brillig &rhs) { if (!(lhs.acir_index == rhs.acir_index)) { return false; } @@ -6169,25 +6177,67 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::OpcodeLocation::Brillig &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::OpcodeLocation::Brillig &obj, Serializer &serializer) { serde::Serializable::serialize(obj.acir_index, serializer); serde::Serializable::serialize(obj.brillig_index, serializer); } template <> template -Circuit::OpcodeLocation::Brillig serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::OpcodeLocation::Brillig obj; +Program::OpcodeLocation::Brillig serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::OpcodeLocation::Brillig obj; obj.acir_index = serde::Deserializable::deserialize(deserializer); obj.brillig_index = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { + + inline bool operator==(const Program &lhs, const Program &rhs) { + if (!(lhs.functions == rhs.functions)) { return false; } + return true; + } + + inline std::vector Program::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } + + inline Program Program::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } + +} // end of namespace Program + +template <> +template +void serde::Serializable::serialize(const Program::Program &obj, Serializer &serializer) { + serializer.increase_container_depth(); + serde::Serializable::serialize(obj.functions, serializer); + serializer.decrease_container_depth(); +} + +template <> +template +Program::Program serde::Deserializable::deserialize(Deserializer &deserializer) { + deserializer.increase_container_depth(); + Program::Program obj; + obj.functions = serde::Deserializable::deserialize(deserializer); + deserializer.decrease_container_depth(); + return obj; +} + +namespace Program { inline bool operator==(const PublicInputs &lhs, const PublicInputs &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -6209,11 +6259,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::PublicInputs &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::PublicInputs &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -6221,15 +6271,15 @@ void serde::Serializable::serialize(const Circuit::Public template <> template -Circuit::PublicInputs serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::PublicInputs serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::PublicInputs obj; + Program::PublicInputs obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Value &lhs, const Value &rhs) { if (!(lhs.inner == rhs.inner)) { return false; } @@ -6251,11 +6301,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Value &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::Value &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.inner, serializer); serializer.decrease_container_depth(); @@ -6263,15 +6313,15 @@ void serde::Serializable::serialize(const Circuit::Value &obj, S template <> template -Circuit::Value serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::Value serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::Value obj; + Program::Value obj; obj.inner = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const ValueOrArray &lhs, const ValueOrArray &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -6293,11 +6343,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::ValueOrArray &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::ValueOrArray &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -6305,15 +6355,15 @@ void serde::Serializable::serialize(const Circuit::ValueO template <> template -Circuit::ValueOrArray serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::ValueOrArray serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::ValueOrArray obj; + Program::ValueOrArray obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const ValueOrArray::MemoryAddress &lhs, const ValueOrArray::MemoryAddress &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -6335,23 +6385,23 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::ValueOrArray::MemoryAddress &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::ValueOrArray::MemoryAddress &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value, serializer); } template <> template -Circuit::ValueOrArray::MemoryAddress serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::ValueOrArray::MemoryAddress obj; +Program::ValueOrArray::MemoryAddress serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::ValueOrArray::MemoryAddress obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const ValueOrArray::HeapArray &lhs, const ValueOrArray::HeapArray &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -6373,23 +6423,23 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::ValueOrArray::HeapArray &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::ValueOrArray::HeapArray &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value, serializer); } template <> template -Circuit::ValueOrArray::HeapArray serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::ValueOrArray::HeapArray obj; +Program::ValueOrArray::HeapArray serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::ValueOrArray::HeapArray obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const ValueOrArray::HeapVector &lhs, const ValueOrArray::HeapVector &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -6411,23 +6461,23 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::ValueOrArray::HeapVector &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::ValueOrArray::HeapVector &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value, serializer); } template <> template -Circuit::ValueOrArray::HeapVector serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::ValueOrArray::HeapVector obj; +Program::ValueOrArray::HeapVector serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::ValueOrArray::HeapVector obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Witness &lhs, const Witness &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -6449,11 +6499,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Witness &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::Witness &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -6461,9 +6511,9 @@ void serde::Serializable::serialize(const Circuit::Witness &ob template <> template -Circuit::Witness serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::Witness serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::Witness obj; + Program::Witness obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; diff --git a/noir/noir-repo/acvm-repo/acir/codegen/witness.cpp b/noir/noir-repo/acvm-repo/acir/codegen/witness.cpp index 118d4ca7ac5b..ad2b0550db2e 100644 --- a/noir/noir-repo/acvm-repo/acir/codegen/witness.cpp +++ b/noir/noir-repo/acvm-repo/acir/codegen/witness.cpp @@ -3,7 +3,7 @@ #include "serde.hpp" #include "bincode.hpp" -namespace WitnessMap { +namespace WitnessStack { struct Witness { uint32_t value; @@ -14,17 +14,79 @@ namespace WitnessMap { }; struct WitnessMap { - std::map value; + std::map value; friend bool operator==(const WitnessMap&, const WitnessMap&); std::vector bincodeSerialize() const; static WitnessMap bincodeDeserialize(std::vector); }; -} // end of namespace WitnessMap + struct StackItem { + uint32_t index; + WitnessStack::WitnessMap witness; + friend bool operator==(const StackItem&, const StackItem&); + std::vector bincodeSerialize() const; + static StackItem bincodeDeserialize(std::vector); + }; + + struct WitnessStack { + std::vector stack; + + friend bool operator==(const WitnessStack&, const WitnessStack&); + std::vector bincodeSerialize() const; + static WitnessStack bincodeDeserialize(std::vector); + }; + +} // end of namespace WitnessStack + + +namespace WitnessStack { + + inline bool operator==(const StackItem &lhs, const StackItem &rhs) { + if (!(lhs.index == rhs.index)) { return false; } + if (!(lhs.witness == rhs.witness)) { return false; } + return true; + } + + inline std::vector StackItem::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } + + inline StackItem StackItem::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 WitnessStack + +template <> +template +void serde::Serializable::serialize(const WitnessStack::StackItem &obj, Serializer &serializer) { + serializer.increase_container_depth(); + serde::Serializable::serialize(obj.index, serializer); + serde::Serializable::serialize(obj.witness, serializer); + serializer.decrease_container_depth(); +} + +template <> +template +WitnessStack::StackItem serde::Deserializable::deserialize(Deserializer &deserializer) { + deserializer.increase_container_depth(); + WitnessStack::StackItem obj; + obj.index = serde::Deserializable::deserialize(deserializer); + obj.witness = serde::Deserializable::deserialize(deserializer); + deserializer.decrease_container_depth(); + return obj; +} -namespace WitnessMap { +namespace WitnessStack { inline bool operator==(const Witness &lhs, const Witness &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -46,11 +108,11 @@ namespace WitnessMap { return value; } -} // end of namespace WitnessMap +} // end of namespace WitnessStack template <> template -void serde::Serializable::serialize(const WitnessMap::Witness &obj, Serializer &serializer) { +void serde::Serializable::serialize(const WitnessStack::Witness &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -58,15 +120,15 @@ void serde::Serializable::serialize(const WitnessMap::Witne template <> template -WitnessMap::Witness serde::Deserializable::deserialize(Deserializer &deserializer) { +WitnessStack::Witness serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - WitnessMap::Witness obj; + WitnessStack::Witness obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace WitnessMap { +namespace WitnessStack { inline bool operator==(const WitnessMap &lhs, const WitnessMap &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -88,11 +150,11 @@ namespace WitnessMap { return value; } -} // end of namespace WitnessMap +} // end of namespace WitnessStack template <> template -void serde::Serializable::serialize(const WitnessMap::WitnessMap &obj, Serializer &serializer) { +void serde::Serializable::serialize(const WitnessStack::WitnessMap &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -100,10 +162,52 @@ void serde::Serializable::serialize(const WitnessMap::Wi template <> template -WitnessMap::WitnessMap serde::Deserializable::deserialize(Deserializer &deserializer) { +WitnessStack::WitnessMap serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - WitnessMap::WitnessMap obj; + WitnessStack::WitnessMap obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } + +namespace WitnessStack { + + inline bool operator==(const WitnessStack &lhs, const WitnessStack &rhs) { + if (!(lhs.stack == rhs.stack)) { return false; } + return true; + } + + inline std::vector WitnessStack::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } + + inline WitnessStack WitnessStack::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 WitnessStack + +template <> +template +void serde::Serializable::serialize(const WitnessStack::WitnessStack &obj, Serializer &serializer) { + serializer.increase_container_depth(); + serde::Serializable::serialize(obj.stack, serializer); + serializer.decrease_container_depth(); +} + +template <> +template +WitnessStack::WitnessStack serde::Deserializable::deserialize(Deserializer &deserializer) { + deserializer.increase_container_depth(); + WitnessStack::WitnessStack obj; + obj.stack = serde::Deserializable::deserialize(deserializer); + deserializer.decrease_container_depth(); + return obj; +} diff --git a/noir/noir-repo/acvm-repo/acir/src/circuit/mod.rs b/noir/noir-repo/acvm-repo/acir/src/circuit/mod.rs index 7e6cbf238039..25cb7f388911 100644 --- a/noir/noir-repo/acvm-repo/acir/src/circuit/mod.rs +++ b/noir/noir-repo/acvm-repo/acir/src/circuit/mod.rs @@ -32,6 +32,13 @@ pub enum ExpressionWidth { }, } +/// A program represented by multiple ACIR circuits. The execution trace of these +/// circuits is dictated by construction of the [crate::native_types::WitnessStack]. +#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Default)] +pub struct Program { + pub functions: Vec, +} + #[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Default)] pub struct Circuit { // current_witness_index is the highest witness index in the circuit. The next witness to be added to this circuit @@ -203,6 +210,57 @@ impl Circuit { } } +impl Program { + fn write(&self, writer: W) -> std::io::Result<()> { + let buf = bincode::serialize(self).unwrap(); + let mut encoder = flate2::write::GzEncoder::new(writer, Compression::default()); + encoder.write_all(&buf)?; + encoder.finish()?; + Ok(()) + } + + fn read(reader: R) -> std::io::Result { + let mut gz_decoder = flate2::read::GzDecoder::new(reader); + let mut buf_d = Vec::new(); + gz_decoder.read_to_end(&mut buf_d)?; + bincode::deserialize(&buf_d) + .map_err(|err| std::io::Error::new(std::io::ErrorKind::InvalidInput, err)) + } + + pub fn serialize_program(program: &Program) -> Vec { + let mut program_bytes: Vec = Vec::new(); + program.write(&mut program_bytes).expect("expected circuit to be serializable"); + program_bytes + } + + pub fn deserialize_program(serialized_circuit: &[u8]) -> std::io::Result { + Program::read(serialized_circuit) + } + + // Serialize and base64 encode program + pub fn serialize_program_base64(program: &Program, s: S) -> Result + where + S: Serializer, + { + let program_bytes = Program::serialize_program(program); + let encoded_b64 = base64::engine::general_purpose::STANDARD.encode(program_bytes); + s.serialize_str(&encoded_b64) + } + + // Deserialize and base64 decode program + pub fn deserialize_program_base64<'de, D>(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let bytecode_b64: String = serde::Deserialize::deserialize(deserializer)?; + let program_bytes = base64::engine::general_purpose::STANDARD + .decode(bytecode_b64) + .map_err(D::Error::custom)?; + let circuit = Self::deserialize_program(&program_bytes).map_err(D::Error::custom)?; + Ok(circuit) + } +} + impl std::fmt::Display for Circuit { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { writeln!(f, "current witness index : {}", self.current_witness_index)?; @@ -240,6 +298,25 @@ impl std::fmt::Debug for Circuit { } } +impl std::fmt::Display for Program { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let mut func_index = 0; + for function in self.functions.iter() { + writeln!(f, "func {}", func_index)?; + writeln!(f, "{}", function)?; + func_index += 1; + } + Ok(()) + + } +} + +impl std::fmt::Debug for Program { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self, f) + } +} + #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Default)] pub struct PublicInputs(pub BTreeSet); diff --git a/noir/noir-repo/acvm-repo/acir/src/lib.rs b/noir/noir-repo/acvm-repo/acir/src/lib.rs index c7be50268502..d14159f34a16 100644 --- a/noir/noir-repo/acvm-repo/acir/src/lib.rs +++ b/noir/noir-repo/acvm-repo/acir/src/lib.rs @@ -42,9 +42,9 @@ mod reflection { brillig::{BrilligInputs, BrilligOutputs}, directives::Directive, opcodes::BlackBoxFuncCall, - Circuit, ExpressionWidth, Opcode, OpcodeLocation, + Circuit, ExpressionWidth, Opcode, OpcodeLocation, Program, }, - native_types::{Witness, WitnessMap}, + native_types::{Witness, WitnessMap, WitnessStack}, }; #[test] @@ -59,6 +59,7 @@ mod reflection { }; let mut tracer = Tracer::new(TracerConfig::default()); + tracer.trace_simple_type::().unwrap(); tracer.trace_simple_type::().unwrap(); tracer.trace_simple_type::().unwrap(); tracer.trace_simple_type::().unwrap(); @@ -78,7 +79,7 @@ mod reflection { // Create C++ class definitions. let mut source = Vec::new(); - let config = serde_generate::CodeGeneratorConfig::new("Circuit".to_string()) + let config = serde_generate::CodeGeneratorConfig::new("Program".to_string()) .with_encodings(vec![serde_generate::Encoding::Bincode]); let generator = serde_generate::cpp::CodeGenerator::new(&config); generator.output(&mut source, ®istry).unwrap(); @@ -106,12 +107,13 @@ mod reflection { let mut tracer = Tracer::new(TracerConfig::default()); tracer.trace_simple_type::().unwrap(); tracer.trace_simple_type::().unwrap(); + tracer.trace_simple_type::().unwrap(); let registry = tracer.registry().unwrap(); // Create C++ class definitions. let mut source = Vec::new(); - let config = serde_generate::CodeGeneratorConfig::new("WitnessMap".to_string()) + let config = serde_generate::CodeGeneratorConfig::new("WitnessStack".to_string()) .with_encodings(vec![serde_generate::Encoding::Bincode]); let generator = serde_generate::cpp::CodeGenerator::new(&config); generator.output(&mut source, ®istry).unwrap(); diff --git a/noir/noir-repo/acvm-repo/acir/src/native_types/mod.rs b/noir/noir-repo/acvm-repo/acir/src/native_types/mod.rs index 66c822bfff87..eb9d1f6fd038 100644 --- a/noir/noir-repo/acvm-repo/acir/src/native_types/mod.rs +++ b/noir/noir-repo/acvm-repo/acir/src/native_types/mod.rs @@ -1,8 +1,10 @@ mod expression; mod witness; mod witness_map; +mod witness_stack; pub use expression::Expression; pub use witness::Witness; pub use witness_map::WitnessMap; -pub use witness_map::WitnessMapError; +pub use witness_stack::WitnessStack; +pub use witness_stack::WitnessStackError; diff --git a/noir/noir-repo/acvm-repo/acir/src/native_types/witness_stack.rs b/noir/noir-repo/acvm-repo/acir/src/native_types/witness_stack.rs new file mode 100644 index 000000000000..24e7984dc141 --- /dev/null +++ b/noir/noir-repo/acvm-repo/acir/src/native_types/witness_stack.rs @@ -0,0 +1,66 @@ +use std::{ + io::Read, +}; + +use flate2::bufread::GzDecoder; +use flate2::bufread::GzEncoder; +use flate2::Compression; +use serde::{Deserialize, Serialize}; +use thiserror::Error; + +use super::WitnessMap; + +#[derive(Debug, Error)] +enum SerializationError { + #[error(transparent)] + Deflate(#[from] std::io::Error), +} + +#[derive(Debug, Error)] +#[error(transparent)] +pub struct WitnessStackError(#[from] SerializationError); + +/// An ordered set of witness maps for separate circuits +#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Default, Serialize, Deserialize)] +pub struct WitnessStack { + pub stack: Vec +} + +#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Default, Serialize, Deserialize)] +pub struct StackItem { + /// Index into a [crate::circuit::Program] function list for which we have an associated witness + index: u32, + /// A full witness for the respective constraint system specified by the index + witness: WitnessMap, +} + +impl From for WitnessStack { + fn from(witness: WitnessMap) -> Self { + let stack = vec![StackItem { index: 0, witness }]; + Self { stack } + } +} + +impl TryFrom for Vec { + type Error = WitnessStackError; + + fn try_from(val: WitnessStack) -> Result { + let buf = bincode::serialize(&val).unwrap(); + let mut deflater = GzEncoder::new(buf.as_slice(), Compression::best()); + let mut buf_c = Vec::new(); + deflater.read_to_end(&mut buf_c).map_err(|err| WitnessStackError(err.into()))?; + Ok(buf_c) + } +} + +impl TryFrom<&[u8]> for WitnessStack { + type Error = WitnessStackError; + + fn try_from(bytes: &[u8]) -> Result { + let mut deflater = GzDecoder::new(bytes); + let mut buf_d = Vec::new(); + deflater.read_to_end(&mut buf_d).map_err(|err| WitnessStackError(err.into()))?; + let witness_stack = bincode::deserialize(&buf_d).unwrap(); + Ok(witness_stack) + } +} \ No newline at end of file diff --git a/noir/noir-repo/compiler/noirc_driver/src/contract.rs b/noir/noir-repo/compiler/noirc_driver/src/contract.rs index 5f4b66e7dd26..d95ddef80c57 100644 --- a/noir/noir-repo/compiler/noirc_driver/src/contract.rs +++ b/noir/noir-repo/compiler/noirc_driver/src/contract.rs @@ -1,7 +1,7 @@ use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; -use acvm::acir::circuit::Circuit; +use acvm::acir::circuit::{Circuit, Program}; use fm::FileId; use noirc_abi::{Abi, ContractEvent}; use noirc_errors::debug_info::DebugInfo; @@ -62,10 +62,10 @@ pub struct ContractFunction { pub abi: Abi, #[serde( - serialize_with = "Circuit::serialize_circuit_base64", - deserialize_with = "Circuit::deserialize_circuit_base64" + serialize_with = "Program::serialize_program_base64", + deserialize_with = "Program::deserialize_program_base64" )] - pub bytecode: Circuit, + pub bytecode: Program, pub debug: DebugInfo, } diff --git a/noir/noir-repo/compiler/noirc_driver/src/lib.rs b/noir/noir-repo/compiler/noirc_driver/src/lib.rs index 11f53cdb7491..8724baafc7d9 100644 --- a/noir/noir-repo/compiler/noirc_driver/src/lib.rs +++ b/noir/noir-repo/compiler/noirc_driver/src/lib.rs @@ -3,7 +3,7 @@ #![warn(unreachable_pub)] #![warn(clippy::semicolon_if_nothing_returned)] -use acvm::acir::circuit::ExpressionWidth; +use acvm::acir::circuit::{ExpressionWidth, Program}; use clap::Args; use fm::{FileId, FileManager}; use iter_extended::vecmap; @@ -303,7 +303,7 @@ pub fn compile_main( if options.print_acir { println!("Compiled ACIR for main (unoptimized):"); - println!("{}", compiled_program.circuit); + println!("{}", compiled_program.program); } Ok((compiled_program, warnings)) @@ -415,7 +415,7 @@ fn compile_contract_inner( function_type, is_internal: modifiers.is_internal.unwrap_or(false), abi: function.abi, - bytecode: function.circuit, + bytecode: function.program, debug: function.debug, }); } @@ -487,7 +487,8 @@ pub fn compile_no_check( Ok(CompiledProgram { hash, - circuit, + // TODO(https://github.com/noir-lang/noir/issues/4428) + program: Program { functions: vec![circuit] }, debug, abi, file_map, diff --git a/noir/noir-repo/compiler/noirc_driver/src/program.rs b/noir/noir-repo/compiler/noirc_driver/src/program.rs index 8d509d3bf68e..9a1879cc2f20 100644 --- a/noir/noir-repo/compiler/noirc_driver/src/program.rs +++ b/noir/noir-repo/compiler/noirc_driver/src/program.rs @@ -1,6 +1,6 @@ use std::collections::BTreeMap; -use acvm::acir::circuit::Circuit; +use acvm::acir::circuit::{Circuit, Program}; use fm::FileId; use noirc_errors::debug_info::DebugInfo; @@ -19,10 +19,10 @@ pub struct CompiledProgram { pub hash: u64, #[serde( - serialize_with = "Circuit::serialize_circuit_base64", - deserialize_with = "Circuit::deserialize_circuit_base64" + serialize_with = "Program::serialize_program_base64", + deserialize_with = "Program::deserialize_program_base64" )] - pub circuit: Circuit, + pub program: Program, pub abi: noirc_abi::Abi, pub debug: DebugInfo, pub file_map: BTreeMap, diff --git a/noir/noir-repo/tooling/backend_interface/src/proof_system.rs b/noir/noir-repo/tooling/backend_interface/src/proof_system.rs index 485381006df7..83ee04f90428 100644 --- a/noir/noir-repo/tooling/backend_interface/src/proof_system.rs +++ b/noir/noir-repo/tooling/backend_interface/src/proof_system.rs @@ -3,7 +3,7 @@ use std::io::Write; use std::path::Path; use acvm::acir::{ - circuit::{Circuit, ExpressionWidth}, + circuit::{Circuit, ExpressionWidth, Program}, native_types::WitnessMap, }; use acvm::FieldElement; @@ -17,7 +17,7 @@ use crate::cli::{ use crate::{Backend, BackendError}; impl Backend { - pub fn get_exact_circuit_size(&self, circuit: &Circuit) -> Result { + pub fn get_exact_circuit_size(&self, program: &Program) -> Result { let binary_path = self.assert_binary_exists()?; self.assert_correct_version()?; @@ -26,8 +26,8 @@ impl Backend { // Create a temporary file for the circuit let circuit_path = temp_directory.join("circuit").with_extension("bytecode"); - let serialized_circuit = Circuit::serialize_circuit(circuit); - write_to_file(&serialized_circuit, &circuit_path); + let serialized_program = Program::serialize_program(program); + write_to_file(&serialized_program, &circuit_path); GatesCommand { crs_path: self.crs_directory(), bytecode_path: circuit_path } .run(binary_path) @@ -55,7 +55,7 @@ impl Backend { #[tracing::instrument(level = "trace", skip_all)] pub fn prove( &self, - circuit: &Circuit, + program: &Program, witness_values: WitnessMap, ) -> Result, BackendError> { let binary_path = self.assert_binary_exists()?; @@ -72,9 +72,9 @@ impl Backend { // Create a temporary file for the circuit // - let bytecode_path = temp_directory.join("circuit").with_extension("bytecode"); - let serialized_circuit = Circuit::serialize_circuit(circuit); - write_to_file(&serialized_circuit, &bytecode_path); + let bytecode_path = temp_directory.join("program").with_extension("bytecode"); + let serialized_program = Program::serialize_program(program); + write_to_file(&serialized_program, &bytecode_path); // Create proof and store it in the specified path let proof_with_public_inputs = @@ -82,7 +82,8 @@ impl Backend { .run(binary_path)?; let proof = bb_abstraction_leaks::remove_public_inputs( - circuit.public_inputs().0.len(), + // TODO(https://github.com/noir-lang/noir/issues/4428) + program.functions[0].public_inputs().0.len(), &proof_with_public_inputs, ); Ok(proof) @@ -93,7 +94,7 @@ impl Backend { &self, proof: &[u8], public_inputs: WitnessMap, - circuit: &Circuit, + program: &Program, ) -> Result { let binary_path = self.assert_binary_exists()?; self.assert_correct_version()?; @@ -108,9 +109,9 @@ impl Backend { write_to_file(&proof_with_public_inputs, &proof_path); // Create a temporary file for the circuit - let bytecode_path = temp_directory.join("circuit").with_extension("bytecode"); - let serialized_circuit = Circuit::serialize_circuit(circuit); - write_to_file(&serialized_circuit, &bytecode_path); + let bytecode_path = temp_directory.join("program").with_extension("bytecode"); + let serialized_program = Program::serialize_program(program); + write_to_file(&serialized_program, &bytecode_path); // Create the verification key and write it to the specified path let vk_path = temp_directory.join("vk"); diff --git a/noir/noir-repo/tooling/debugger/src/dap.rs b/noir/noir-repo/tooling/debugger/src/dap.rs index 7e67a26b257f..f73c8a43851e 100644 --- a/noir/noir-repo/tooling/debugger/src/dap.rs +++ b/noir/noir-repo/tooling/debugger/src/dap.rs @@ -669,7 +669,7 @@ pub fn run_session( warnings: program.warnings, }; let mut session = - DapSession::new(server, solver, &program.circuit, &debug_artifact, initial_witness); + DapSession::new(server, solver, &program.program.functions[0], &debug_artifact, initial_witness); session.run_loop() } diff --git a/noir/noir-repo/tooling/nargo/src/artifacts/contract.rs b/noir/noir-repo/tooling/nargo/src/artifacts/contract.rs index d928b09fcb96..a23433b3317e 100644 --- a/noir/noir-repo/tooling/nargo/src/artifacts/contract.rs +++ b/noir/noir-repo/tooling/nargo/src/artifacts/contract.rs @@ -1,4 +1,4 @@ -use acvm::acir::circuit::Circuit; +use acvm::acir::circuit::{Circuit, Program}; use noirc_abi::{Abi, ContractEvent}; use noirc_driver::{CompiledContract, ContractFunction, ContractFunctionType}; use serde::{Deserialize, Serialize}; @@ -50,10 +50,10 @@ pub struct ContractFunctionArtifact { pub abi: Abi, #[serde( - serialize_with = "Circuit::serialize_circuit_base64", - deserialize_with = "Circuit::deserialize_circuit_base64" + serialize_with = "Program::serialize_program_base64", + deserialize_with = "Program::deserialize_program_base64" )] - pub bytecode: Circuit, + pub bytecode: Program, #[serde( serialize_with = "DebugInfo::serialize_compressed_base64_json", diff --git a/noir/noir-repo/tooling/nargo/src/artifacts/program.rs b/noir/noir-repo/tooling/nargo/src/artifacts/program.rs index d8dc42ec2141..b870248a5fa9 100644 --- a/noir/noir-repo/tooling/nargo/src/artifacts/program.rs +++ b/noir/noir-repo/tooling/nargo/src/artifacts/program.rs @@ -1,6 +1,6 @@ use std::collections::BTreeMap; -use acvm::acir::circuit::Circuit; +use acvm::acir::circuit::{Circuit, Program}; use fm::FileId; use noirc_abi::Abi; use noirc_driver::CompiledProgram; @@ -21,10 +21,10 @@ pub struct ProgramArtifact { pub abi: Abi, #[serde( - serialize_with = "Circuit::serialize_circuit_base64", - deserialize_with = "Circuit::deserialize_circuit_base64" + serialize_with = "Program::serialize_program_base64", + deserialize_with = "Program::deserialize_program_base64" )] - pub bytecode: Circuit, + pub bytecode: Program, #[serde( serialize_with = "DebugInfo::serialize_compressed_base64_json", @@ -37,14 +37,14 @@ pub struct ProgramArtifact { } impl From for ProgramArtifact { - fn from(program: CompiledProgram) -> Self { + fn from(compiled_program: CompiledProgram) -> Self { ProgramArtifact { - hash: program.hash, - abi: program.abi, - noir_version: program.noir_version, - bytecode: program.circuit, - debug_symbols: program.debug, - file_map: program.file_map, + hash: compiled_program.hash, + abi: compiled_program.abi, + noir_version: compiled_program.noir_version, + bytecode: compiled_program.program, + debug_symbols: compiled_program.debug, + file_map: compiled_program.file_map, } } } @@ -55,7 +55,7 @@ impl From for CompiledProgram { hash: program.hash, abi: program.abi, noir_version: program.noir_version, - circuit: program.bytecode, + program: program.bytecode, debug: program.debug_symbols, file_map: program.file_map, warnings: vec![], diff --git a/noir/noir-repo/tooling/nargo/src/ops/optimize.rs b/noir/noir-repo/tooling/nargo/src/ops/optimize.rs index 2d0c4c43d256..cb2b31e97798 100644 --- a/noir/noir-repo/tooling/nargo/src/ops/optimize.rs +++ b/noir/noir-repo/tooling/nargo/src/ops/optimize.rs @@ -1,17 +1,21 @@ use iter_extended::vecmap; use noirc_driver::{CompiledContract, CompiledProgram}; -pub fn optimize_program(mut program: CompiledProgram) -> CompiledProgram { - let (optimized_circuit, location_map) = acvm::compiler::optimize(program.circuit); - program.circuit = optimized_circuit; - program.debug.update_acir(location_map); - program +/// TODO(https://github.com/noir-lang/noir/issues/4428): Need to update how these passes are run to account for +/// multiple ACIR functions + +pub fn optimize_program(mut compiled_program: CompiledProgram) -> CompiledProgram { + // TODO: Work to get rid of these clones by borrowing `Circuit` in the acvm compiler or by accepted a `Program` + let (optimized_circuit, location_map) = acvm::compiler::optimize(compiled_program.program.functions[0].clone()); + compiled_program.program.functions[0] = optimized_circuit; + compiled_program.debug.update_acir(location_map); + compiled_program } pub fn optimize_contract(contract: CompiledContract) -> CompiledContract { let functions = vecmap(contract.functions, |mut func| { - let (optimized_bytecode, location_map) = acvm::compiler::optimize(func.bytecode); - func.bytecode = optimized_bytecode; + let (optimized_bytecode, location_map) = acvm::compiler::optimize(func.bytecode.functions[0].clone()); + func.bytecode.functions[0] = optimized_bytecode; func.debug.update_acir(location_map); func }); diff --git a/noir/noir-repo/tooling/nargo/src/ops/test.rs b/noir/noir-repo/tooling/nargo/src/ops/test.rs index 92c09ec889e6..dd2833cd5c8d 100644 --- a/noir/noir-repo/tooling/nargo/src/ops/test.rs +++ b/noir/noir-repo/tooling/nargo/src/ops/test.rs @@ -22,18 +22,19 @@ pub fn run_test( foreign_call_resolver_url: Option<&str>, config: &CompileOptions, ) -> TestStatus { - let program = compile_no_check(context, config, test_function.get_id(), None, false); - match program { - Ok(program) => { + let compiled_program = compile_no_check(context, config, test_function.get_id(), None, false); + match compiled_program { + Ok(compiled_program) => { // Run the backend to ensure the PWG evaluates functions like std::hash::pedersen, // otherwise constraints involving these expressions will not error. let circuit_execution = execute_circuit( - &program.circuit, + // TODO(https://github.com/noir-lang/noir/issues/4428) + &compiled_program.program.functions[0], WitnessMap::new(), blackbox_solver, &mut DefaultForeignCallExecutor::new(show_output, foreign_call_resolver_url), ); - test_status_program_compile_pass(test_function, program.debug, circuit_execution) + test_status_program_compile_pass(test_function, compiled_program.debug, circuit_execution) } Err(err) => test_status_program_compile_fail(err, test_function), } diff --git a/noir/noir-repo/tooling/nargo/src/ops/transform.rs b/noir/noir-repo/tooling/nargo/src/ops/transform.rs index 9267ed7e0459..79abe89d73be 100644 --- a/noir/noir-repo/tooling/nargo/src/ops/transform.rs +++ b/noir/noir-repo/tooling/nargo/src/ops/transform.rs @@ -2,16 +2,20 @@ use acvm::acir::circuit::ExpressionWidth; use iter_extended::vecmap; use noirc_driver::{CompiledContract, CompiledProgram}; +/// TODO(https://github.com/noir-lang/noir/issues/4428): Need to update how these passes are run to account for +/// multiple ACIR functions + pub fn transform_program( - mut program: CompiledProgram, + mut compiled_program: CompiledProgram, expression_width: ExpressionWidth, ) -> CompiledProgram { + // TODO: Work to get rid of these clones by borrowing `Circuit` in the acvm compiler or by accepted a `Program` let (optimized_circuit, location_map) = - acvm::compiler::compile(program.circuit, expression_width); + acvm::compiler::compile(compiled_program.program.functions[0].clone(), expression_width); - program.circuit = optimized_circuit; - program.debug.update_acir(location_map); - program + compiled_program.program.functions[0] = optimized_circuit; + compiled_program.debug.update_acir(location_map); + compiled_program } pub fn transform_contract( @@ -20,8 +24,8 @@ pub fn transform_contract( ) -> CompiledContract { let functions = vecmap(contract.functions, |mut func| { let (optimized_bytecode, location_map) = - acvm::compiler::compile(func.bytecode, expression_width); - func.bytecode = optimized_bytecode; + acvm::compiler::compile(func.bytecode.functions[0].clone(), expression_width); + func.bytecode.functions[0] = optimized_bytecode; func.debug.update_acir(location_map); func }); diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/codegen_verifier_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/codegen_verifier_cmd.rs index 63d27e30836d..212daed20bc6 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/codegen_verifier_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/codegen_verifier_cmd.rs @@ -65,7 +65,14 @@ pub(crate) fn run( let program = nargo::ops::transform_program(program, expression_width); - let smart_contract_string = backend.eth_contract(&program.circuit)?; + + // TODO(https://github.com/noir-lang/noir/issues/4428): + // We do not expect to have a smart contract verifier for a foldable program with multiple circuits. + // However, in the future we can expect to possibly have non-inlined ACIR functions during compilation + // that will be inlined at a later step such as by the ACVM compiler or by the backend. + // Add appropriate handling here once the compiler enables multiple ACIR functions. + assert_eq!(program.program.functions.len(), 1); + let smart_contract_string = backend.eth_contract(&program.program.functions[0])?; let contract_dir = workspace.contracts_directory_path(package); create_named_dir(&contract_dir, "contract"); diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/compile_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/compile_cmd.rs index 34fb05249b5e..5b3919a520eb 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/compile_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/compile_cmd.rs @@ -156,10 +156,10 @@ pub(super) fn save_program( circuit_dir: &Path, only_acir_opt: bool, ) { - let program_artifact = ProgramArtifact::from(program.clone()); if only_acir_opt { - only_acir(&program_artifact, circuit_dir); + only_acir(program.program, circuit_dir); } else { + let program_artifact = ProgramArtifact::from(program.clone()); save_program_to_file(&program_artifact, &package.name, circuit_dir); } } diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/debug_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/debug_cmd.rs index 130a07b5c908..9ebace797d00 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/debug_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/debug_cmd.rs @@ -236,7 +236,7 @@ pub(crate) fn debug_program( noir_debugger::debug_circuit( &blackbox_solver, - &compiled_program.circuit, + &compiled_program.program.functions[0], debug_artifact, initial_witness, ) diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/execute_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/execute_cmd.rs index a3fcebab94f5..f3e3689a8561 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/execute_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/execute_cmd.rs @@ -137,7 +137,7 @@ pub(crate) fn execute_program( let initial_witness = compiled_program.abi.encode(inputs_map, None)?; let solved_witness_err = nargo::ops::execute_circuit( - &compiled_program.circuit, + &compiled_program.program.functions[0], initial_witness, &blackbox_solver, &mut DefaultForeignCallExecutor::new(true, foreign_call_resolver_url), diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/fs/program.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/fs/program.rs index 1fb57ae66851..9cdc5131e574 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/fs/program.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/fs/program.rs @@ -1,6 +1,6 @@ use std::path::{Path, PathBuf}; -use acvm::acir::circuit::Circuit; +use acvm::acir::circuit::{Circuit, Program}; use nargo::artifacts::{contract::ContractArtifact, program::ProgramArtifact}; use noirc_frontend::graph::CrateName; @@ -19,12 +19,12 @@ pub(crate) fn save_program_to_file>( /// Writes the bytecode as acir.gz pub(crate) fn only_acir>( - program_artifact: &ProgramArtifact, + program: Program, circuit_dir: P, ) -> PathBuf { create_named_dir(circuit_dir.as_ref(), "target"); let circuit_path = circuit_dir.as_ref().join("acir").with_extension("gz"); - let bytes = Circuit::serialize_circuit(&program_artifact.bytecode); + let bytes = Program::serialize_program(&program); write_to_file(&bytes, &circuit_path); circuit_path diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/fs/witness.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/fs/witness.rs index 1a2cf88f4a16..52b5c385e5df 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/fs/witness.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/fs/witness.rs @@ -1,6 +1,6 @@ use std::path::{Path, PathBuf}; -use acvm::acir::native_types::WitnessMap; +use acvm::acir::native_types::{WitnessMap, WitnessStack}; use nargo::constants::WITNESS_EXT; use super::{create_named_dir, write_to_file}; @@ -14,7 +14,9 @@ pub(crate) fn save_witness_to_dir>( create_named_dir(witness_dir.as_ref(), "witness"); let witness_path = witness_dir.as_ref().join(witness_name).with_extension(WITNESS_EXT); - let buf: Vec = witnesses.try_into()?; + // TODO(https://github.com/noir-lang/noir/issues/4428) + let witness_stack: WitnessStack = witnesses.into(); + let buf: Vec = witness_stack.try_into()?; write_to_file(buf.as_slice(), &witness_path); diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/info_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/info_cmd.rs index ef0df0bf25bc..fffa200d3bb1 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/info_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/info_cmd.rs @@ -268,8 +268,8 @@ fn count_opcodes_and_gates_in_program( Ok(ProgramInfo { name: package.name.to_string(), expression_width, - acir_opcodes: compiled_program.circuit.opcodes.len(), - circuit_size: backend.get_exact_circuit_size(&compiled_program.circuit)?, + acir_opcodes: compiled_program.program.functions[0].opcodes.len(), + circuit_size: backend.get_exact_circuit_size(&compiled_program.program)?, }) } @@ -284,7 +284,8 @@ fn count_opcodes_and_gates_in_contract( .map(|function| -> Result<_, BackendError> { Ok(FunctionInfo { name: function.name, - acir_opcodes: function.bytecode.opcodes.len(), + // TODO(https://github.com/noir-lang/noir/issues/4428) + acir_opcodes: function.bytecode.functions[0].opcodes.len(), circuit_size: backend.get_exact_circuit_size(&function.bytecode)?, }) }) diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/prove_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/prove_cmd.rs index cc39b0535bcc..03c0321a17e8 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/prove_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/prove_cmd.rs @@ -138,11 +138,11 @@ pub(crate) fn prove_package( Format::Toml, )?; - let proof = backend.prove(&compiled_program.circuit, solved_witness)?; + let proof = backend.prove(&compiled_program.program, solved_witness)?; if check_proof { let public_inputs = public_abi.encode(&public_inputs, return_value)?; - let valid_proof = backend.verify(&proof, public_inputs, &compiled_program.circuit)?; + let valid_proof = backend.verify(&proof, public_inputs, &compiled_program.program)?; if !valid_proof { return Err(CliError::InvalidProof("".into())); diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/verify_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/verify_cmd.rs index 66b88a22f2a2..9d1a72765250 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/verify_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/verify_cmd.rs @@ -102,7 +102,7 @@ fn verify_package( let proof = load_hex_data(&proof_path)?; - let valid_proof = backend.verify(&proof, public_inputs, &compiled_program.circuit)?; + let valid_proof = backend.verify(&proof, public_inputs, &compiled_program.program)?; if valid_proof { Ok(()) diff --git a/noir/noir-repo/tooling/nargo_cli/src/errors.rs b/noir/noir-repo/tooling/nargo_cli/src/errors.rs index c2996f53420a..40fb7886405a 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/errors.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/errors.rs @@ -1,4 +1,4 @@ -use acvm::acir::native_types::WitnessMapError; +use acvm::acir::native_types::WitnessStackError; use hex::FromHexError; use nargo::{errors::CompileError, NargoError}; use nargo_toml::ManifestError; @@ -22,9 +22,9 @@ pub(crate) enum FilesystemError { #[error(transparent)] InputParserError(#[from] InputParserError), - /// WitnessMap serialization error + /// WitnessStack serialization error #[error(transparent)] - WitnessMapSerialization(#[from] WitnessMapError), + WitnessStackSerialization(#[from] WitnessStackError), #[error("Error: could not deserialize build program: {0}")] ProgramSerializationError(String), From 288a7ec0b9d46339c8224a0ed492f469a4886e3e Mon Sep 17 00:00:00 2001 From: vezenovm Date: Wed, 6 Mar 2024 18:47:00 +0000 Subject: [PATCH 007/139] a little cleanup --- .../src/barretenberg/dsl/acir_format/acir_to_constraint_buf.hpp | 2 +- noir/noir-repo/tooling/nargo_cli/src/cli/execute_cmd.rs | 1 + noir/noir-repo/tooling/nargo_cli/src/cli/info_cmd.rs | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) 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 bed65a90c035..58d036f4e165 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 @@ -366,7 +366,7 @@ void handle_memory_op(Program::Opcode::MemoryOp const& mem_op, BlockConstraint& AcirFormat circuit_buf_to_acir_format(std::vector const& buf) { // TODO(maxim): Handle the new `Program` structure once ACVM supports a function call stack. - // For now we still expect a single ACIR function.s + // For now we expect a single ACIR function auto circuit = Program::Program::bincodeDeserialize(buf).functions[0]; AcirFormat af; diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/execute_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/execute_cmd.rs index f3e3689a8561..ca0fbdfe3a5e 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/execute_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/execute_cmd.rs @@ -136,6 +136,7 @@ pub(crate) fn execute_program( let initial_witness = compiled_program.abi.encode(inputs_map, None)?; + // TODO(https://github.com/noir-lang/noir/issues/4428) let solved_witness_err = nargo::ops::execute_circuit( &compiled_program.program.functions[0], initial_witness, diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/info_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/info_cmd.rs index fffa200d3bb1..f73f42072098 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/info_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/info_cmd.rs @@ -268,6 +268,7 @@ fn count_opcodes_and_gates_in_program( Ok(ProgramInfo { name: package.name.to_string(), expression_width, + // TODO(https://github.com/noir-lang/noir/issues/4428) acir_opcodes: compiled_program.program.functions[0].opcodes.len(), circuit_size: backend.get_exact_circuit_size(&compiled_program.program)?, }) From 1f65f1842a78d457a8f181ecda855d42cbd3ed2d Mon Sep 17 00:00:00 2001 From: vezenovm Date: Wed, 6 Mar 2024 18:55:08 +0000 Subject: [PATCH 008/139] cargo fmt --- noir/noir-repo/acvm-repo/acir/src/circuit/mod.rs | 3 +-- .../acvm-repo/acir/src/native_types/witness_stack.rs | 8 +++----- noir/noir-repo/tooling/debugger/src/dap.rs | 9 +++++++-- noir/noir-repo/tooling/nargo/src/ops/optimize.rs | 8 +++++--- noir/noir-repo/tooling/nargo/src/ops/test.rs | 6 +++++- noir/noir-repo/tooling/nargo/src/ops/transform.rs | 2 +- .../tooling/nargo_cli/src/cli/codegen_verifier_cmd.rs | 9 ++++----- noir/noir-repo/tooling/nargo_cli/src/cli/fs/program.rs | 5 +---- 8 files changed, 27 insertions(+), 23 deletions(-) diff --git a/noir/noir-repo/acvm-repo/acir/src/circuit/mod.rs b/noir/noir-repo/acvm-repo/acir/src/circuit/mod.rs index 25cb7f388911..d4311aebb499 100644 --- a/noir/noir-repo/acvm-repo/acir/src/circuit/mod.rs +++ b/noir/noir-repo/acvm-repo/acir/src/circuit/mod.rs @@ -246,7 +246,7 @@ impl Program { let encoded_b64 = base64::engine::general_purpose::STANDARD.encode(program_bytes); s.serialize_str(&encoded_b64) } - + // Deserialize and base64 decode program pub fn deserialize_program_base64<'de, D>(deserializer: D) -> Result where @@ -307,7 +307,6 @@ impl std::fmt::Display for Program { func_index += 1; } Ok(()) - } } diff --git a/noir/noir-repo/acvm-repo/acir/src/native_types/witness_stack.rs b/noir/noir-repo/acvm-repo/acir/src/native_types/witness_stack.rs index 24e7984dc141..439de987b7ea 100644 --- a/noir/noir-repo/acvm-repo/acir/src/native_types/witness_stack.rs +++ b/noir/noir-repo/acvm-repo/acir/src/native_types/witness_stack.rs @@ -1,6 +1,4 @@ -use std::{ - io::Read, -}; +use std::io::Read; use flate2::bufread::GzDecoder; use flate2::bufread::GzEncoder; @@ -23,7 +21,7 @@ pub struct WitnessStackError(#[from] SerializationError); /// An ordered set of witness maps for separate circuits #[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Default, Serialize, Deserialize)] pub struct WitnessStack { - pub stack: Vec + pub stack: Vec, } #[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Default, Serialize, Deserialize)] @@ -63,4 +61,4 @@ impl TryFrom<&[u8]> for WitnessStack { let witness_stack = bincode::deserialize(&buf_d).unwrap(); Ok(witness_stack) } -} \ No newline at end of file +} diff --git a/noir/noir-repo/tooling/debugger/src/dap.rs b/noir/noir-repo/tooling/debugger/src/dap.rs index f73c8a43851e..fdc56c29b08c 100644 --- a/noir/noir-repo/tooling/debugger/src/dap.rs +++ b/noir/noir-repo/tooling/debugger/src/dap.rs @@ -668,8 +668,13 @@ pub fn run_session( file_map: program.file_map, warnings: program.warnings, }; - let mut session = - DapSession::new(server, solver, &program.program.functions[0], &debug_artifact, initial_witness); + let mut session = DapSession::new( + server, + solver, + &program.program.functions[0], + &debug_artifact, + initial_witness, + ); session.run_loop() } diff --git a/noir/noir-repo/tooling/nargo/src/ops/optimize.rs b/noir/noir-repo/tooling/nargo/src/ops/optimize.rs index cb2b31e97798..250c070fe879 100644 --- a/noir/noir-repo/tooling/nargo/src/ops/optimize.rs +++ b/noir/noir-repo/tooling/nargo/src/ops/optimize.rs @@ -1,12 +1,13 @@ use iter_extended::vecmap; use noirc_driver::{CompiledContract, CompiledProgram}; -/// TODO(https://github.com/noir-lang/noir/issues/4428): Need to update how these passes are run to account for +/// TODO(https://github.com/noir-lang/noir/issues/4428): Need to update how these passes are run to account for /// multiple ACIR functions pub fn optimize_program(mut compiled_program: CompiledProgram) -> CompiledProgram { // TODO: Work to get rid of these clones by borrowing `Circuit` in the acvm compiler or by accepted a `Program` - let (optimized_circuit, location_map) = acvm::compiler::optimize(compiled_program.program.functions[0].clone()); + let (optimized_circuit, location_map) = + acvm::compiler::optimize(compiled_program.program.functions[0].clone()); compiled_program.program.functions[0] = optimized_circuit; compiled_program.debug.update_acir(location_map); compiled_program @@ -14,7 +15,8 @@ pub fn optimize_program(mut compiled_program: CompiledProgram) -> CompiledProgra pub fn optimize_contract(contract: CompiledContract) -> CompiledContract { let functions = vecmap(contract.functions, |mut func| { - let (optimized_bytecode, location_map) = acvm::compiler::optimize(func.bytecode.functions[0].clone()); + let (optimized_bytecode, location_map) = + acvm::compiler::optimize(func.bytecode.functions[0].clone()); func.bytecode.functions[0] = optimized_bytecode; func.debug.update_acir(location_map); func diff --git a/noir/noir-repo/tooling/nargo/src/ops/test.rs b/noir/noir-repo/tooling/nargo/src/ops/test.rs index dd2833cd5c8d..929216bbae9f 100644 --- a/noir/noir-repo/tooling/nargo/src/ops/test.rs +++ b/noir/noir-repo/tooling/nargo/src/ops/test.rs @@ -34,7 +34,11 @@ pub fn run_test( blackbox_solver, &mut DefaultForeignCallExecutor::new(show_output, foreign_call_resolver_url), ); - test_status_program_compile_pass(test_function, compiled_program.debug, circuit_execution) + test_status_program_compile_pass( + test_function, + compiled_program.debug, + circuit_execution, + ) } Err(err) => test_status_program_compile_fail(err, test_function), } diff --git a/noir/noir-repo/tooling/nargo/src/ops/transform.rs b/noir/noir-repo/tooling/nargo/src/ops/transform.rs index 79abe89d73be..c32ca2f482f4 100644 --- a/noir/noir-repo/tooling/nargo/src/ops/transform.rs +++ b/noir/noir-repo/tooling/nargo/src/ops/transform.rs @@ -2,7 +2,7 @@ use acvm::acir::circuit::ExpressionWidth; use iter_extended::vecmap; use noirc_driver::{CompiledContract, CompiledProgram}; -/// TODO(https://github.com/noir-lang/noir/issues/4428): Need to update how these passes are run to account for +/// TODO(https://github.com/noir-lang/noir/issues/4428): Need to update how these passes are run to account for /// multiple ACIR functions pub fn transform_program( diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/codegen_verifier_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/codegen_verifier_cmd.rs index 212daed20bc6..f4177e5f38c5 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/codegen_verifier_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/codegen_verifier_cmd.rs @@ -65,12 +65,11 @@ pub(crate) fn run( let program = nargo::ops::transform_program(program, expression_width); - - // TODO(https://github.com/noir-lang/noir/issues/4428): + // TODO(https://github.com/noir-lang/noir/issues/4428): // We do not expect to have a smart contract verifier for a foldable program with multiple circuits. - // However, in the future we can expect to possibly have non-inlined ACIR functions during compilation - // that will be inlined at a later step such as by the ACVM compiler or by the backend. - // Add appropriate handling here once the compiler enables multiple ACIR functions. + // However, in the future we can expect to possibly have non-inlined ACIR functions during compilation + // that will be inlined at a later step such as by the ACVM compiler or by the backend. + // Add appropriate handling here once the compiler enables multiple ACIR functions. assert_eq!(program.program.functions.len(), 1); let smart_contract_string = backend.eth_contract(&program.program.functions[0])?; diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/fs/program.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/fs/program.rs index 9cdc5131e574..c18f087fb3cb 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/fs/program.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/fs/program.rs @@ -18,10 +18,7 @@ pub(crate) fn save_program_to_file>( } /// Writes the bytecode as acir.gz -pub(crate) fn only_acir>( - program: Program, - circuit_dir: P, -) -> PathBuf { +pub(crate) fn only_acir>(program: Program, circuit_dir: P) -> PathBuf { create_named_dir(circuit_dir.as_ref(), "target"); let circuit_path = circuit_dir.as_ref().join("acir").with_extension("gz"); let bytes = Program::serialize_program(&program); From 0dc8b38a42b2e6feea3f79cc87b62a92c30465b1 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Wed, 6 Mar 2024 18:59:39 +0000 Subject: [PATCH 009/139] fmt and clippy --- noir/noir-repo/acvm-repo/acir/src/circuit/mod.rs | 4 +--- noir/noir-repo/compiler/noirc_driver/src/contract.rs | 2 +- noir/noir-repo/compiler/noirc_driver/src/program.rs | 2 +- noir/noir-repo/tooling/nargo/src/artifacts/contract.rs | 2 +- noir/noir-repo/tooling/nargo/src/artifacts/program.rs | 2 +- noir/noir-repo/tooling/nargo_cli/src/cli/fs/program.rs | 2 +- 6 files changed, 6 insertions(+), 8 deletions(-) diff --git a/noir/noir-repo/acvm-repo/acir/src/circuit/mod.rs b/noir/noir-repo/acvm-repo/acir/src/circuit/mod.rs index d4311aebb499..3d4d62969815 100644 --- a/noir/noir-repo/acvm-repo/acir/src/circuit/mod.rs +++ b/noir/noir-repo/acvm-repo/acir/src/circuit/mod.rs @@ -300,11 +300,9 @@ impl std::fmt::Debug for Circuit { impl std::fmt::Display for Program { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let mut func_index = 0; - for function in self.functions.iter() { + for (func_index, function) in self.functions.iter().enumerate() { writeln!(f, "func {}", func_index)?; writeln!(f, "{}", function)?; - func_index += 1; } Ok(()) } diff --git a/noir/noir-repo/compiler/noirc_driver/src/contract.rs b/noir/noir-repo/compiler/noirc_driver/src/contract.rs index d95ddef80c57..3ce5b0c9fc97 100644 --- a/noir/noir-repo/compiler/noirc_driver/src/contract.rs +++ b/noir/noir-repo/compiler/noirc_driver/src/contract.rs @@ -1,7 +1,7 @@ use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; -use acvm::acir::circuit::{Circuit, Program}; +use acvm::acir::circuit::Program; use fm::FileId; use noirc_abi::{Abi, ContractEvent}; use noirc_errors::debug_info::DebugInfo; diff --git a/noir/noir-repo/compiler/noirc_driver/src/program.rs b/noir/noir-repo/compiler/noirc_driver/src/program.rs index 9a1879cc2f20..6f527297dcb4 100644 --- a/noir/noir-repo/compiler/noirc_driver/src/program.rs +++ b/noir/noir-repo/compiler/noirc_driver/src/program.rs @@ -1,6 +1,6 @@ use std::collections::BTreeMap; -use acvm::acir::circuit::{Circuit, Program}; +use acvm::acir::circuit::Program; use fm::FileId; use noirc_errors::debug_info::DebugInfo; diff --git a/noir/noir-repo/tooling/nargo/src/artifacts/contract.rs b/noir/noir-repo/tooling/nargo/src/artifacts/contract.rs index a23433b3317e..115bc1d17ea7 100644 --- a/noir/noir-repo/tooling/nargo/src/artifacts/contract.rs +++ b/noir/noir-repo/tooling/nargo/src/artifacts/contract.rs @@ -1,4 +1,4 @@ -use acvm::acir::circuit::{Circuit, Program}; +use acvm::acir::circuit::Program; use noirc_abi::{Abi, ContractEvent}; use noirc_driver::{CompiledContract, ContractFunction, ContractFunctionType}; use serde::{Deserialize, Serialize}; diff --git a/noir/noir-repo/tooling/nargo/src/artifacts/program.rs b/noir/noir-repo/tooling/nargo/src/artifacts/program.rs index b870248a5fa9..046db1cd8faa 100644 --- a/noir/noir-repo/tooling/nargo/src/artifacts/program.rs +++ b/noir/noir-repo/tooling/nargo/src/artifacts/program.rs @@ -1,6 +1,6 @@ use std::collections::BTreeMap; -use acvm::acir::circuit::{Circuit, Program}; +use acvm::acir::circuit::Program; use fm::FileId; use noirc_abi::Abi; use noirc_driver::CompiledProgram; diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/fs/program.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/fs/program.rs index c18f087fb3cb..77005e8d5af5 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/fs/program.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/fs/program.rs @@ -1,6 +1,6 @@ use std::path::{Path, PathBuf}; -use acvm::acir::circuit::{Circuit, Program}; +use acvm::acir::circuit::Program; use nargo::artifacts::{contract::ContractArtifact, program::ProgramArtifact}; use noirc_frontend::graph::CrateName; From e602ecd22de2b9ddae5fbd574dcab46cd10f23fe Mon Sep 17 00:00:00 2001 From: vezenovm Date: Wed, 6 Mar 2024 19:17:42 +0000 Subject: [PATCH 010/139] update avm-transpiler to handle new program structure --- .vscode/settings.json | 3 ++- avm-transpiler/src/transpile_contract.rs | 12 ++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 4d3812210fd6..02a3ca363954 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -157,6 +157,7 @@ "barretenberg/cpp/src" ], "rust-analyzer.linkedProjects": [ - "noir/noir-repo/Cargo.toml" + "noir/noir-repo/Cargo.toml", + "avm-transpiler/Cargo.toml" ] } diff --git a/avm-transpiler/src/transpile_contract.rs b/avm-transpiler/src/transpile_contract.rs index bcf848ab88e1..8481d44d9d93 100644 --- a/avm-transpiler/src/transpile_contract.rs +++ b/avm-transpiler/src/transpile_contract.rs @@ -3,7 +3,7 @@ use log::info; use regex::Regex; use serde::{Deserialize, Serialize}; -use acvm::acir::circuit::Circuit; +use acvm::acir::circuit::Program; use noirc_driver::ContractFunctionType; use crate::transpile::brillig_to_avm; @@ -56,10 +56,10 @@ pub struct AcirContractFunction { pub is_internal: bool, pub abi: serde_json::Value, #[serde( - serialize_with = "Circuit::serialize_circuit_base64", - deserialize_with = "Circuit::deserialize_circuit_base64" + serialize_with = "Program::serialize_program_base64", + deserialize_with = "Program::deserialize_program_base64" )] - pub bytecode: Circuit, + pub bytecode: Program, pub debug_symbols: serde_json::Value, } @@ -90,8 +90,8 @@ impl From for TranspiledContract { function.name, contract.name ); // Extract Brillig Opcodes from acir - let acir_circuit = function.bytecode.clone(); - let brillig = extract_brillig_from_acir(&acir_circuit.opcodes); + let acir_program = function.bytecode; + let brillig = extract_brillig_from_acir(&acir_program.functions[0].opcodes); // Transpile to AVM let avm_bytecode = brillig_to_avm(brillig); From c3d825d6b56d52d560a7c7b4053e10707460d8f6 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Wed, 6 Mar 2024 19:21:31 +0000 Subject: [PATCH 011/139] import correct witness hpp file --- .../cpp/src/barretenberg/dsl/acir_format/serde/index.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/index.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/index.hpp index cbbc3ca1b339..da0e55ad1c55 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/index.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/index.hpp @@ -16,6 +16,6 @@ #pragma GCC diagnostic ignored "-Wsign-conversion" #pragma GCC diagnostic ignored "-Wconversion" #include "acir.hpp" -#include "witness_map.hpp" +#include "witness_stack.hpp" #pragma GCC diagnostic pop #endif \ No newline at end of file From e1757fda41959c6298d1da7aeef584101f1e7013 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Wed, 6 Mar 2024 21:52:14 +0000 Subject: [PATCH 012/139] serialize Program in acvm_js --- .vscode/settings.json | 1 + noir/noir-repo/acvm-repo/acvm_js/src/execute.rs | 8 ++++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 02a3ca363954..c801138e2239 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -158,6 +158,7 @@ ], "rust-analyzer.linkedProjects": [ "noir/noir-repo/Cargo.toml", + "noir/noir-repo/acvm-repo/acvm_js/Cargo.toml", "avm-transpiler/Cargo.toml" ] } diff --git a/noir/noir-repo/acvm-repo/acvm_js/src/execute.rs b/noir/noir-repo/acvm-repo/acvm_js/src/execute.rs index 3f691e1abf29..6985183a8a07 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/src/execute.rs +++ b/noir/noir-repo/acvm-repo/acvm_js/src/execute.rs @@ -1,5 +1,5 @@ use acvm::{ - acir::circuit::Circuit, + acir::circuit::Program, pwg::{ACVMStatus, ErrorLocation, OpcodeResolutionError, ACVM}, }; use bn254_blackbox_solver::Bn254BlackBoxSolver; @@ -56,13 +56,17 @@ pub async fn execute_circuit( #[wasm_bindgen(js_name = executeCircuitWithBlackBoxSolver, skip_jsdoc)] pub async fn execute_circuit_with_black_box_solver( solver: &WasmBlackBoxFunctionSolver, + // TODO(https://github.com/noir-lang/noir/issues/4428): These need to be updated to match the same interfaces + // as the native ACVM executor. Right now native execution still only handles one circuit so I do not feel the need + // to break the JS interface just yet. circuit: Vec, initial_witness: JsWitnessMap, foreign_call_handler: ForeignCallHandler, ) -> Result { console_error_panic_hook::set_once(); - let circuit: Circuit = Circuit::deserialize_circuit(&circuit) + let program: Program = Program::deserialize_program(&circuit) .map_err(|_| JsExecutionError::new("Failed to deserialize circuit. This is likely due to differing serialization formats between ACVM_JS and your compiler".to_string(), None))?; + let circuit = &program.functions[0]; let mut acvm = ACVM::new(&solver.0, &circuit.opcodes, initial_witness.into()); From ad8129b35ae6c17c633b6d4a74bee6436deee13b Mon Sep 17 00:00:00 2001 From: vezenovm Date: Thu, 7 Mar 2024 04:21:43 +0000 Subject: [PATCH 013/139] update public witness methods in acvm_js --- .../acvm-repo/acvm_js/src/public_witness.rs | 23 +++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/noir/noir-repo/acvm-repo/acvm_js/src/public_witness.rs b/noir/noir-repo/acvm-repo/acvm_js/src/public_witness.rs index 8dc66c435b3c..47f5bb6e3391 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/src/public_witness.rs +++ b/noir/noir-repo/acvm-repo/acvm_js/src/public_witness.rs @@ -1,5 +1,5 @@ use acvm::acir::{ - circuit::Circuit, + circuit::{Circuit, Program}, native_types::{Witness, WitnessMap}, }; use js_sys::JsString; @@ -26,12 +26,17 @@ fn extract_indices(witness_map: &WitnessMap, indices: Vec) -> Result, witness_map: JsWitnessMap, ) -> Result { console_error_panic_hook::set_once(); - let circuit: Circuit = - Circuit::deserialize_circuit(&circuit).expect("Failed to deserialize circuit"); + let program: Program = + Program::deserialize_program(&circuit).expect("Failed to deserialize circuit"); + let circuit = &program.functions[0]; + let witness_map = WitnessMap::from(witness_map); let return_witness = @@ -51,8 +56,10 @@ pub fn get_public_parameters_witness( solved_witness: JsWitnessMap, ) -> Result { console_error_panic_hook::set_once(); - let circuit: Circuit = - Circuit::deserialize_circuit(&circuit).expect("Failed to deserialize circuit"); + let program: Program = + Program::deserialize_program(&circuit).expect("Failed to deserialize circuit"); + let circuit = &program.functions[0]; + let witness_map = WitnessMap::from(solved_witness); let public_params_witness = @@ -72,8 +79,10 @@ pub fn get_public_witness( solved_witness: JsWitnessMap, ) -> Result { console_error_panic_hook::set_once(); - let circuit: Circuit = - Circuit::deserialize_circuit(&circuit).expect("Failed to deserialize circuit"); + let program: Program = + Program::deserialize_program(&circuit).expect("Failed to deserialize circuit"); + let circuit = &program.functions[0]; + let witness_map = WitnessMap::from(solved_witness); let public_witness = From 1dac703ca0a9db2e1244d97893212efa39b2277c Mon Sep 17 00:00:00 2001 From: vezenovm Date: Thu, 7 Mar 2024 04:29:14 +0000 Subject: [PATCH 014/139] add necessary clone --- noir/noir-repo/acvm-repo/acvm_js/src/public_witness.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/noir/noir-repo/acvm-repo/acvm_js/src/public_witness.rs b/noir/noir-repo/acvm-repo/acvm_js/src/public_witness.rs index 47f5bb6e3391..f303f805a28c 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/src/public_witness.rs +++ b/noir/noir-repo/acvm-repo/acvm_js/src/public_witness.rs @@ -40,7 +40,7 @@ pub fn get_return_witness( let witness_map = WitnessMap::from(witness_map); let return_witness = - extract_indices(&witness_map, circuit.return_values.0.into_iter().collect())?; + extract_indices(&witness_map, circuit.return_values.0.clone().into_iter().collect())?; Ok(JsWitnessMap::from(return_witness)) } @@ -63,7 +63,7 @@ pub fn get_public_parameters_witness( let witness_map = WitnessMap::from(solved_witness); let public_params_witness = - extract_indices(&witness_map, circuit.public_parameters.0.into_iter().collect())?; + extract_indices(&witness_map, circuit.public_parameters.0.clone().into_iter().collect())?; Ok(JsWitnessMap::from(public_params_witness)) } @@ -86,7 +86,7 @@ pub fn get_public_witness( let witness_map = WitnessMap::from(solved_witness); let public_witness = - extract_indices(&witness_map, circuit.public_inputs().0.into_iter().collect())?; + extract_indices(&witness_map, circuit.public_inputs().0.clone().into_iter().collect())?; Ok(JsWitnessMap::from(public_witness)) } From 14cea93e7750a9e5c77df4cfac460e09c51df2bf Mon Sep 17 00:00:00 2001 From: vezenovm Date: Thu, 7 Mar 2024 14:13:48 +0000 Subject: [PATCH 015/139] remove unused import --- noir/noir-repo/acvm-repo/acvm_js/src/public_witness.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noir/noir-repo/acvm-repo/acvm_js/src/public_witness.rs b/noir/noir-repo/acvm-repo/acvm_js/src/public_witness.rs index f303f805a28c..2ae90b79a6a5 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/src/public_witness.rs +++ b/noir/noir-repo/acvm-repo/acvm_js/src/public_witness.rs @@ -1,5 +1,5 @@ use acvm::acir::{ - circuit::{Circuit, Program}, + circuit::Program, native_types::{Witness, WitnessMap}, }; use js_sys::JsString; From fc7c8b72d539ebb34069f9a550969ce76fb3496c Mon Sep 17 00:00:00 2001 From: vezenovm Date: Thu, 7 Mar 2024 15:27:36 +0000 Subject: [PATCH 016/139] updated serialization --- .../acir/tests/test_program_serialization.rs | 119 ++++++++++-------- .../acvm-repo/acvm_js/test/shared/addition.ts | 11 +- .../test/shared/complex_foreign_call.ts | 16 +-- .../test/shared/fixed_base_scalar_mul.ts | 6 +- .../acvm_js/test/shared/foreign_call.ts | 9 +- .../acvm_js/test/shared/memory_op.ts | 9 +- .../acvm-repo/acvm_js/test/shared/pedersen.ts | 5 +- .../acvm_js/test/shared/schnorr_verify.ts | 28 +++-- 8 files changed, 111 insertions(+), 92 deletions(-) diff --git a/noir/noir-repo/acvm-repo/acir/tests/test_program_serialization.rs b/noir/noir-repo/acvm-repo/acir/tests/test_program_serialization.rs index 2c8ad2b99868..238f51b1e280 100644 --- a/noir/noir-repo/acvm-repo/acir/tests/test_program_serialization.rs +++ b/noir/noir-repo/acvm-repo/acir/tests/test_program_serialization.rs @@ -1,13 +1,13 @@ //! This integration test defines a set of circuits which are used in order to test the acvm_js package. //! -//! The acvm_js test suite contains serialized [circuits][`Circuit`] which must be kept in sync with the format +//! The acvm_js test suite contains serialized program [circuits][`Program`] which must be kept in sync with the format //! outputted from the [ACIR crate][acir]. //! Breaking changes to the serialization format then require refreshing acvm_js's test suite. //! This file contains Rust definitions of these circuits and outputs the updated serialized format. //! //! These tests also check this circuit serialization against an expected value, erroring if the serialization changes. //! Generally in this situation we just need to refresh the `expected_serialization` variables to match the -//! actual output, **HOWEVER** note that this results in a breaking change to the ACIR format. +//! actual output, **HOWEVER** note that this results in a breaking change to the backend ACIR format. use std::collections::BTreeSet; @@ -15,7 +15,7 @@ use acir::{ circuit::{ brillig::{Brillig, BrilligInputs, BrilligOutputs}, opcodes::{BlackBoxFuncCall, BlockId, FunctionInput, MemOp}, - Circuit, Opcode, PublicInputs, + Circuit, Opcode, Program, PublicInputs, }, native_types::{Expression, Witness}, }; @@ -41,16 +41,17 @@ fn addition_circuit() { return_values: PublicInputs([Witness(3)].into()), ..Circuit::default() }; + let program = Program { functions: vec![circuit] }; - let bytes = Circuit::serialize_circuit(&circuit); + let bytes = Program::serialize_program(&program); let expected_serialization: Vec = vec![ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 208, 49, 14, 192, 32, 8, 5, 80, 212, 30, 8, 4, 20, - 182, 94, 165, 166, 122, 255, 35, 52, 77, 28, 76, 58, 214, 191, 124, 166, 23, 242, 15, 0, 8, - 240, 77, 154, 125, 206, 198, 127, 161, 176, 209, 138, 139, 197, 88, 68, 122, 205, 157, 152, - 46, 204, 222, 76, 81, 180, 21, 35, 35, 53, 189, 179, 49, 119, 19, 171, 222, 188, 162, 147, - 112, 167, 161, 206, 99, 98, 105, 223, 95, 248, 26, 113, 90, 97, 185, 97, 217, 56, 173, 35, - 63, 243, 81, 87, 163, 125, 1, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 144, 75, 14, 128, 32, 12, 68, 249, 120, 160, 150, + 182, 208, 238, 188, 138, 68, 184, 255, 17, 212, 200, 130, 196, 165, 188, 164, 153, 174, 94, + 38, 227, 221, 203, 118, 159, 119, 95, 226, 200, 125, 36, 252, 3, 253, 66, 87, 152, 92, 4, + 153, 185, 149, 212, 144, 240, 128, 100, 85, 5, 88, 106, 86, 84, 20, 149, 51, 41, 81, 83, + 214, 98, 213, 10, 24, 50, 53, 236, 98, 212, 135, 44, 174, 235, 5, 143, 35, 12, 151, 159, + 126, 55, 109, 28, 231, 145, 47, 245, 105, 191, 143, 133, 1, 0, 0, ]; assert_eq!(bytes, expected_serialization) @@ -71,13 +72,14 @@ fn fixed_base_scalar_mul_circuit() { return_values: PublicInputs(BTreeSet::from_iter(vec![Witness(3), Witness(4)])), ..Circuit::default() }; + let program = Program { functions: vec![circuit] }; - let bytes = Circuit::serialize_circuit(&circuit); + let bytes = Program::serialize_program(&program); let expected_serialization: Vec = vec![ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 77, 138, 91, 10, 0, 32, 16, 2, 109, 171, 175, 46, 221, - 209, 247, 229, 130, 130, 140, 200, 92, 0, 11, 157, 228, 35, 127, 212, 200, 29, 61, 116, 76, - 220, 217, 250, 171, 91, 113, 160, 66, 104, 242, 97, 0, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 77, 138, 81, 10, 0, 48, 8, 66, 87, 219, 190, 118, 233, + 29, 61, 43, 3, 5, 121, 34, 207, 86, 231, 162, 198, 157, 124, 228, 71, 157, 220, 232, 161, + 227, 226, 206, 214, 95, 221, 74, 0, 116, 58, 13, 182, 105, 0, 0, 0, ]; assert_eq!(bytes, expected_serialization) @@ -98,13 +100,14 @@ fn pedersen_circuit() { return_values: PublicInputs(BTreeSet::from_iter(vec![Witness(2), Witness(3)])), ..Circuit::default() }; + let program = Program { functions: vec![circuit] }; - let bytes = Circuit::serialize_circuit(&circuit); + let bytes = Program::serialize_program(&program); let expected_serialization: Vec = vec![ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 93, 74, 135, 9, 0, 48, 8, 75, 171, 224, 255, 15, 139, - 27, 196, 64, 200, 100, 0, 15, 133, 80, 57, 89, 219, 127, 39, 173, 126, 235, 236, 247, 151, - 48, 224, 71, 90, 33, 97, 0, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 93, 74, 7, 6, 0, 0, 8, 108, 209, 255, 63, 156, 54, 233, + 56, 55, 17, 26, 18, 196, 241, 169, 250, 178, 141, 167, 32, 159, 254, 234, 238, 255, 87, + 112, 52, 63, 63, 101, 105, 0, 0, 0, ]; assert_eq!(bytes, expected_serialization) @@ -139,26 +142,27 @@ fn schnorr_verify_circuit() { return_values: PublicInputs(BTreeSet::from([output])), ..Circuit::default() }; + let program = Program { functions: vec![circuit] }; - let bytes = Circuit::serialize_circuit(&circuit); + let bytes = Program::serialize_program(&program); let expected_serialization: Vec = vec![ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 77, 210, 7, 74, 3, 1, 20, 69, 209, 177, 247, 222, 123, - 239, 189, 119, 141, 93, 99, 220, 133, 251, 95, 130, 152, 103, 78, 32, 3, 195, 33, 4, 66, - 248, 239, 254, 20, 69, 209, 84, 212, 158, 216, 206, 223, 234, 219, 204, 146, 239, 91, 170, - 111, 103, 245, 109, 101, 27, 219, 217, 193, 250, 219, 197, 110, 246, 176, 151, 125, 236, - 231, 0, 7, 57, 196, 97, 142, 112, 148, 99, 28, 231, 4, 39, 57, 197, 105, 206, 112, 150, - 115, 156, 231, 2, 23, 185, 196, 101, 174, 112, 149, 107, 92, 231, 6, 55, 185, 197, 109, - 238, 112, 151, 123, 220, 231, 1, 15, 121, 196, 99, 158, 240, 148, 103, 60, 231, 5, 47, 121, - 197, 107, 222, 240, 150, 119, 188, 231, 3, 75, 124, 228, 83, 195, 142, 121, 158, 125, 126, - 225, 43, 223, 248, 206, 15, 126, 178, 204, 47, 86, 248, 237, 119, 43, 76, 127, 105, 47, - 189, 165, 181, 116, 150, 198, 234, 125, 117, 249, 47, 233, 41, 45, 165, 163, 52, 148, 126, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 77, 210, 7, 78, 2, 1, 20, 69, 81, 236, 189, 247, 222, + 123, 239, 93, 177, 33, 34, 238, 194, 253, 47, 193, 200, 147, 67, 194, 36, 147, 163, 33, 33, + 228, 191, 219, 82, 168, 63, 63, 181, 183, 197, 223, 177, 147, 191, 181, 183, 149, 69, 159, + 183, 213, 222, 238, 218, 219, 206, 14, 118, 178, 139, 141, 183, 135, 189, 236, 99, 63, 7, + 56, 200, 33, 14, 115, 132, 163, 28, 227, 56, 39, 56, 201, 41, 78, 115, 134, 179, 156, 227, + 60, 23, 184, 200, 37, 46, 115, 133, 171, 92, 227, 58, 55, 184, 201, 45, 110, 115, 135, 187, + 220, 227, 62, 15, 120, 200, 35, 30, 243, 132, 167, 60, 227, 57, 47, 120, 201, 43, 94, 243, + 134, 183, 188, 227, 61, 31, 248, 200, 39, 22, 249, 204, 151, 166, 29, 243, 188, 250, 255, + 141, 239, 44, 241, 131, 101, 126, 178, 194, 47, 86, 249, 237, 123, 171, 76, 127, 105, 47, + 189, 165, 181, 116, 150, 198, 26, 125, 245, 248, 45, 233, 41, 45, 165, 163, 52, 148, 126, 210, 78, 186, 73, 51, 233, 37, 173, 164, 147, 52, 146, 62, 210, 70, 186, 72, 19, 233, 33, - 45, 164, 131, 52, 144, 253, 23, 139, 218, 238, 217, 60, 123, 103, 235, 236, 156, 141, 179, - 239, 166, 93, 183, 237, 185, 107, 199, 125, 251, 29, 218, 237, 216, 94, 167, 118, 58, 183, - 207, 165, 93, 174, 237, 113, 107, 135, 123, 247, 47, 185, 251, 147, 59, 191, 184, 239, 155, - 187, 126, 184, 103, 217, 29, 235, 55, 171, 223, 173, 104, 184, 231, 255, 243, 7, 236, 52, - 239, 128, 225, 3, 0, 0, + 45, 164, 131, 52, 144, 253, 151, 11, 245, 221, 179, 121, 246, 206, 214, 217, 57, 27, 103, + 223, 109, 187, 238, 218, 115, 223, 142, 135, 246, 59, 182, 219, 169, 189, 206, 237, 116, + 105, 159, 107, 187, 220, 218, 227, 222, 14, 143, 238, 95, 116, 247, 23, 119, 126, 115, 223, + 146, 187, 150, 221, 179, 226, 142, 141, 155, 53, 238, 86, 104, 186, 231, 255, 243, 7, 100, + 141, 232, 192, 233, 3, 0, 0, ]; assert_eq!(bytes, expected_serialization) @@ -202,15 +206,16 @@ fn simple_brillig_foreign_call() { private_parameters: BTreeSet::from([Witness(1), Witness(2)]), ..Circuit::default() }; + let program = Program { functions: vec![circuit] }; - let bytes = Circuit::serialize_circuit(&circuit); + let bytes = Program::serialize_program(&program); let expected_serialization: Vec = vec![ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 143, 177, 10, 192, 32, 16, 67, 227, 21, 74, 233, - 212, 79, 177, 127, 208, 159, 233, 224, 226, 32, 226, 247, 139, 168, 16, 68, 93, 244, 45, - 119, 228, 142, 144, 92, 0, 20, 50, 7, 237, 76, 213, 190, 50, 245, 26, 175, 218, 231, 165, - 57, 175, 148, 14, 137, 179, 147, 191, 114, 211, 221, 216, 240, 59, 63, 107, 221, 115, 104, - 181, 103, 244, 43, 36, 10, 38, 68, 108, 25, 253, 238, 136, 1, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 143, 65, 10, 192, 32, 12, 4, 77, 10, 165, 244, 212, + 167, 216, 31, 244, 51, 61, 120, 241, 32, 226, 251, 85, 140, 176, 136, 122, 209, 129, 144, + 176, 9, 97, 151, 84, 225, 74, 69, 50, 31, 48, 35, 85, 251, 164, 235, 53, 94, 218, 247, 75, + 163, 95, 150, 12, 153, 179, 227, 191, 114, 195, 222, 216, 240, 59, 63, 75, 221, 251, 208, + 106, 207, 232, 150, 65, 100, 53, 33, 2, 9, 69, 91, 82, 144, 1, 0, 0, ]; assert_eq!(bytes, expected_serialization) @@ -301,19 +306,20 @@ fn complex_brillig_foreign_call() { private_parameters: BTreeSet::from([Witness(1), Witness(2), Witness(3)]), ..Circuit::default() }; + let program = Program { functions: vec![circuit] }; - let bytes = Circuit::serialize_circuit(&circuit); + let bytes = Program::serialize_program(&program); let expected_serialization: Vec = vec![ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 84, 75, 10, 132, 48, 12, 125, 177, 163, 35, 179, - 154, 35, 8, 51, 7, 232, 204, 9, 188, 139, 184, 83, 116, 233, 241, 173, 152, 98, 12, 213, - 141, 21, 244, 65, 232, 39, 175, 233, 35, 73, 155, 3, 32, 204, 48, 206, 18, 158, 19, 175, - 37, 60, 175, 228, 209, 30, 195, 143, 226, 197, 178, 103, 105, 76, 110, 160, 209, 156, 160, - 209, 247, 195, 69, 235, 29, 179, 46, 81, 243, 103, 2, 239, 231, 225, 44, 117, 150, 241, - 250, 201, 99, 206, 251, 96, 95, 161, 242, 14, 193, 243, 40, 162, 105, 253, 219, 12, 75, 47, - 146, 186, 251, 37, 116, 86, 93, 219, 55, 245, 96, 20, 85, 75, 253, 136, 249, 87, 249, 105, - 231, 220, 4, 249, 237, 132, 56, 20, 224, 109, 113, 223, 88, 82, 153, 34, 64, 34, 14, 164, - 69, 172, 48, 2, 23, 243, 6, 31, 25, 5, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 84, 65, 14, 132, 32, 12, 108, 101, 117, 205, 158, + 246, 9, 38, 187, 15, 96, 247, 5, 254, 197, 120, 211, 232, 209, 231, 139, 113, 136, 181, 65, + 47, 98, 162, 147, 52, 20, 24, 202, 164, 45, 48, 205, 200, 157, 49, 124, 227, 44, 129, 207, + 152, 75, 120, 94, 137, 209, 30, 195, 143, 227, 197, 178, 103, 105, 76, 110, 160, 209, 156, + 160, 209, 247, 195, 69, 235, 29, 179, 46, 81, 243, 103, 2, 239, 231, 225, 44, 117, 150, 97, + 254, 196, 152, 99, 157, 176, 87, 168, 188, 147, 224, 121, 20, 209, 180, 254, 109, 70, 75, + 47, 178, 186, 251, 37, 116, 86, 93, 219, 55, 245, 96, 20, 85, 75, 253, 8, 255, 171, 246, + 121, 231, 220, 4, 249, 237, 132, 56, 28, 224, 109, 113, 223, 180, 164, 50, 165, 0, 137, 17, + 72, 139, 88, 97, 4, 198, 90, 226, 196, 33, 5, 0, 0, ]; assert_eq!(bytes, expected_serialization) @@ -342,13 +348,16 @@ fn memory_op_circuit() { return_values: PublicInputs([Witness(4)].into()), ..Circuit::default() }; - let bytes = Circuit::serialize_circuit(&circuit); + let program = Program { functions: vec![circuit] }; + + let bytes = Program::serialize_program(&program); let expected_serialization: Vec = vec![ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 145, 187, 17, 0, 32, 8, 67, 195, 111, 31, 220, 192, - 253, 167, 178, 144, 2, 239, 236, 132, 194, 52, 129, 230, 93, 8, 6, 64, 176, 101, 225, 28, - 78, 49, 43, 238, 154, 225, 254, 166, 209, 205, 165, 98, 174, 212, 177, 188, 187, 92, 255, - 173, 92, 173, 190, 93, 82, 80, 78, 123, 14, 127, 60, 97, 1, 210, 144, 46, 242, 19, 3, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 81, 201, 13, 0, 32, 8, 147, 195, 125, 112, 3, 247, + 159, 74, 141, 60, 106, 226, 79, 120, 216, 132, 180, 124, 154, 82, 168, 108, 212, 57, 2, + 122, 129, 157, 201, 181, 150, 59, 186, 179, 189, 161, 101, 251, 82, 176, 175, 196, 121, 89, + 118, 185, 246, 91, 185, 26, 125, 187, 64, 80, 134, 29, 195, 31, 79, 24, 2, 250, 167, 252, + 27, 3, 0, 0, ]; assert_eq!(bytes, expected_serialization) diff --git a/noir/noir-repo/acvm-repo/acvm_js/test/shared/addition.ts b/noir/noir-repo/acvm-repo/acvm_js/test/shared/addition.ts index 217902bdea61..f5b0bda2d07a 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/test/shared/addition.ts +++ b/noir/noir-repo/acvm-repo/acvm_js/test/shared/addition.ts @@ -2,11 +2,12 @@ import { WitnessMap } from '@noir-lang/acvm_js'; // See `addition_circuit` integration test in `acir/tests/test_program_serialization.rs`. export const bytecode = Uint8Array.from([ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 208, 49, 14, 192, 32, 8, 5, 80, 212, 30, 8, 4, 20, 182, 94, 165, 166, 122, - 255, 35, 52, 77, 28, 76, 58, 214, 191, 124, 166, 23, 242, 15, 0, 8, 240, 77, 154, 125, 206, 198, 127, 161, 176, 209, - 138, 139, 197, 88, 68, 122, 205, 157, 152, 46, 204, 222, 76, 81, 180, 21, 35, 35, 53, 189, 179, 49, 119, 19, 171, 222, - 188, 162, 147, 112, 167, 161, 206, 99, 98, 105, 223, 95, 248, 26, 113, 90, 97, 185, 97, 217, 56, 173, 35, 63, 243, 81, - 87, 163, 125, 1, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 144, 75, 14, 128, 32, 12, 68, 249, 120, 160, 150, + 182, 208, 238, 188, 138, 68, 184, 255, 17, 212, 200, 130, 196, 165, 188, 164, 153, 174, 94, + 38, 227, 221, 203, 118, 159, 119, 95, 226, 200, 125, 36, 252, 3, 253, 66, 87, 152, 92, 4, + 153, 185, 149, 212, 144, 240, 128, 100, 85, 5, 88, 106, 86, 84, 20, 149, 51, 41, 81, 83, + 214, 98, 213, 10, 24, 50, 53, 236, 98, 212, 135, 44, 174, 235, 5, 143, 35, 12, 151, 159, + 126, 55, 109, 28, 231, 145, 47, 245, 105, 191, 143, 133, 1, 0, 0, ]); export const initialWitnessMap: WitnessMap = new Map([ diff --git a/noir/noir-repo/acvm-repo/acvm_js/test/shared/complex_foreign_call.ts b/noir/noir-repo/acvm-repo/acvm_js/test/shared/complex_foreign_call.ts index 27abd72305f0..c75a59643473 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/test/shared/complex_foreign_call.ts +++ b/noir/noir-repo/acvm-repo/acvm_js/test/shared/complex_foreign_call.ts @@ -2,13 +2,15 @@ import { WitnessMap } from '@noir-lang/acvm_js'; // See `complex_brillig_foreign_call` integration test in `acir/tests/test_program_serialization.rs`. export const bytecode = Uint8Array.from([ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 84, 75, 10, 132, 48, 12, 125, 177, 163, 35, 179, 154, 35, 8, 51, 7, 232, 204, - 9, 188, 139, 184, 83, 116, 233, 241, 173, 152, 98, 12, 213, 141, 21, 244, 65, 232, 39, 175, 233, 35, 73, 155, 3, 32, - 204, 48, 206, 18, 158, 19, 175, 37, 60, 175, 228, 209, 30, 195, 143, 226, 197, 178, 103, 105, 76, 110, 160, 209, 156, - 160, 209, 247, 195, 69, 235, 29, 179, 46, 81, 243, 103, 2, 239, 231, 225, 44, 117, 150, 241, 250, 201, 99, 206, 251, - 96, 95, 161, 242, 14, 193, 243, 40, 162, 105, 253, 219, 12, 75, 47, 146, 186, 251, 37, 116, 86, 93, 219, 55, 245, 96, - 20, 85, 75, 253, 136, 249, 87, 249, 105, 231, 220, 4, 249, 237, 132, 56, 20, 224, 109, 113, 223, 88, 82, 153, 34, 64, - 34, 14, 164, 69, 172, 48, 2, 23, 243, 6, 31, 25, 5, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 84, 65, 14, 132, 32, 12, 108, 101, 117, 205, 158, + 246, 9, 38, 187, 15, 96, 247, 5, 254, 197, 120, 211, 232, 209, 231, 139, 113, 136, 181, 65, + 47, 98, 162, 147, 52, 20, 24, 202, 164, 45, 48, 205, 200, 157, 49, 124, 227, 44, 129, 207, + 152, 75, 120, 94, 137, 209, 30, 195, 143, 227, 197, 178, 103, 105, 76, 110, 160, 209, 156, + 160, 209, 247, 195, 69, 235, 29, 179, 46, 81, 243, 103, 2, 239, 231, 225, 44, 117, 150, 97, + 254, 196, 152, 99, 157, 176, 87, 168, 188, 147, 224, 121, 20, 209, 180, 254, 109, 70, 75, + 47, 178, 186, 251, 37, 116, 86, 93, 219, 55, 245, 96, 20, 85, 75, 253, 8, 255, 171, 246, + 121, 231, 220, 4, 249, 237, 132, 56, 28, 224, 109, 113, 223, 180, 164, 50, 165, 0, 137, 17, + 72, 139, 88, 97, 4, 198, 90, 226, 196, 33, 5, 0, 0, ]); export const initialWitnessMap: WitnessMap = new Map([ [1, '0x0000000000000000000000000000000000000000000000000000000000000001'], diff --git a/noir/noir-repo/acvm-repo/acvm_js/test/shared/fixed_base_scalar_mul.ts b/noir/noir-repo/acvm-repo/acvm_js/test/shared/fixed_base_scalar_mul.ts index c0859f50135b..46e1f66fb211 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/test/shared/fixed_base_scalar_mul.ts +++ b/noir/noir-repo/acvm-repo/acvm_js/test/shared/fixed_base_scalar_mul.ts @@ -1,8 +1,8 @@ // See `fixed_base_scalar_mul_circuit` integration test in `acir/tests/test_program_serialization.rs`. export const bytecode = Uint8Array.from([ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 77, 138, 91, 10, 0, 32, 16, 2, 109, 171, 175, 46, 221, 209, 247, 229, 130, 130, - 140, 200, 92, 0, 11, 157, 228, 35, 127, 212, 200, 29, 61, 116, 76, 220, 217, 250, 171, 91, 113, 160, 66, 104, 242, 97, - 0, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 77, 138, 81, 10, 0, 48, 8, 66, 87, 219, 190, 118, 233, + 29, 61, 43, 3, 5, 121, 34, 207, 86, 231, 162, 198, 157, 124, 228, 71, 157, 220, 232, 161, + 227, 226, 206, 214, 95, 221, 74, 0, 116, 58, 13, 182, 105, 0, 0, 0, ]); export const initialWitnessMap = new Map([ [1, '0x0000000000000000000000000000000000000000000000000000000000000001'], diff --git a/noir/noir-repo/acvm-repo/acvm_js/test/shared/foreign_call.ts b/noir/noir-repo/acvm-repo/acvm_js/test/shared/foreign_call.ts index 0be8937b57d3..527f26b4ae39 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/test/shared/foreign_call.ts +++ b/noir/noir-repo/acvm-repo/acvm_js/test/shared/foreign_call.ts @@ -2,10 +2,11 @@ import { WitnessMap } from '@noir-lang/acvm_js'; // See `simple_brillig_foreign_call` integration test in `acir/tests/test_program_serialization.rs`. export const bytecode = Uint8Array.from([ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 143, 177, 10, 192, 32, 16, 67, 227, 21, 74, 233, 212, 79, 177, 127, 208, 159, - 233, 224, 226, 32, 226, 247, 139, 168, 16, 68, 93, 244, 45, 119, 228, 142, 144, 92, 0, 20, 50, 7, 237, 76, 213, 190, - 50, 245, 26, 175, 218, 231, 165, 57, 175, 148, 14, 137, 179, 147, 191, 114, 211, 221, 216, 240, 59, 63, 107, 221, 115, - 104, 181, 103, 244, 43, 36, 10, 38, 68, 108, 25, 253, 238, 136, 1, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 143, 65, 10, 192, 32, 12, 4, 77, 10, 165, 244, 212, + 167, 216, 31, 244, 51, 61, 120, 241, 32, 226, 251, 85, 140, 176, 136, 122, 209, 129, 144, + 176, 9, 97, 151, 84, 225, 74, 69, 50, 31, 48, 35, 85, 251, 164, 235, 53, 94, 218, 247, 75, + 163, 95, 150, 12, 153, 179, 227, 191, 114, 195, 222, 216, 240, 59, 63, 75, 221, 251, 208, + 106, 207, 232, 150, 65, 100, 53, 33, 2, 9, 69, 91, 82, 144, 1, 0, 0, ]); export const initialWitnessMap: WitnessMap = new Map([ [1, '0x0000000000000000000000000000000000000000000000000000000000000005'], diff --git a/noir/noir-repo/acvm-repo/acvm_js/test/shared/memory_op.ts b/noir/noir-repo/acvm-repo/acvm_js/test/shared/memory_op.ts index b5ab64b3447e..f2e5ab4af491 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/test/shared/memory_op.ts +++ b/noir/noir-repo/acvm-repo/acvm_js/test/shared/memory_op.ts @@ -1,9 +1,10 @@ // See `memory_op_circuit` integration test in `acir/tests/test_program_serialization.rs`. export const bytecode = Uint8Array.from([ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 145, 187, 17, 0, 32, 8, 67, 195, 111, 31, 220, 192, 253, 167, 178, 144, 2, - 239, 236, 132, 194, 52, 129, 230, 93, 8, 6, 64, 176, 101, 225, 28, 78, 49, 43, 238, 154, 225, 254, 166, 209, 205, 165, - 98, 174, 212, 177, 188, 187, 92, 255, 173, 92, 173, 190, 93, 82, 80, 78, 123, 14, 127, 60, 97, 1, 210, 144, 46, 242, - 19, 3, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 81, 201, 13, 0, 32, 8, 147, 195, 125, 112, 3, 247, + 159, 74, 141, 60, 106, 226, 79, 120, 216, 132, 180, 124, 154, 82, 168, 108, 212, 57, 2, + 122, 129, 157, 201, 181, 150, 59, 186, 179, 189, 161, 101, 251, 82, 176, 175, 196, 121, 89, + 118, 185, 246, 91, 185, 26, 125, 187, 64, 80, 134, 29, 195, 31, 79, 24, 2, 250, 167, 252, + 27, 3, 0, 0, ]); export const initialWitnessMap = new Map([ diff --git a/noir/noir-repo/acvm-repo/acvm_js/test/shared/pedersen.ts b/noir/noir-repo/acvm-repo/acvm_js/test/shared/pedersen.ts index 5150d24131c4..0882874136ee 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/test/shared/pedersen.ts +++ b/noir/noir-repo/acvm-repo/acvm_js/test/shared/pedersen.ts @@ -1,7 +1,8 @@ // See `pedersen_circuit` integration test in `acir/tests/test_program_serialization.rs`. export const bytecode = Uint8Array.from([ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 93, 74, 135, 9, 0, 48, 8, 75, 171, 224, 255, 15, 139, 27, 196, 64, 200, 100, 0, 15, - 133, 80, 57, 89, 219, 127, 39, 173, 126, 235, 236, 247, 151, 48, 224, 71, 90, 33, 97, 0, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 93, 74, 7, 6, 0, 0, 8, 108, 209, 255, 63, 156, 54, 233, + 56, 55, 17, 26, 18, 196, 241, 169, 250, 178, 141, 167, 32, 159, 254, 234, 238, 255, 87, + 112, 52, 63, 63, 101, 105, 0, 0, 0, ]); export const initialWitnessMap = new Map([[1, '0x0000000000000000000000000000000000000000000000000000000000000001']]); diff --git a/noir/noir-repo/acvm-repo/acvm_js/test/shared/schnorr_verify.ts b/noir/noir-repo/acvm-repo/acvm_js/test/shared/schnorr_verify.ts index 2127de66f694..8f5667bd8883 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/test/shared/schnorr_verify.ts +++ b/noir/noir-repo/acvm-repo/acvm_js/test/shared/schnorr_verify.ts @@ -1,17 +1,21 @@ // See `schnorr_verify_circuit` integration test in `acir/tests/test_program_serialization.rs`. export const bytecode = Uint8Array.from([ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 77, 210, 7, 74, 3, 1, 20, 69, 209, 177, 247, 222, 123, 239, 189, 119, 141, 93, 99, - 220, 133, 251, 95, 130, 152, 103, 78, 32, 3, 195, 33, 4, 66, 248, 239, 254, 20, 69, 209, 84, 212, 158, 216, 206, 223, - 234, 219, 204, 146, 239, 91, 170, 111, 103, 245, 109, 101, 27, 219, 217, 193, 250, 219, 197, 110, 246, 176, 151, 125, - 236, 231, 0, 7, 57, 196, 97, 142, 112, 148, 99, 28, 231, 4, 39, 57, 197, 105, 206, 112, 150, 115, 156, 231, 2, 23, - 185, 196, 101, 174, 112, 149, 107, 92, 231, 6, 55, 185, 197, 109, 238, 112, 151, 123, 220, 231, 1, 15, 121, 196, 99, - 158, 240, 148, 103, 60, 231, 5, 47, 121, 197, 107, 222, 240, 150, 119, 188, 231, 3, 75, 124, 228, 83, 195, 142, 121, - 158, 125, 126, 225, 43, 223, 248, 206, 15, 126, 178, 204, 47, 86, 248, 237, 119, 43, 76, 127, 105, 47, 189, 165, 181, - 116, 150, 198, 234, 125, 117, 249, 47, 233, 41, 45, 165, 163, 52, 148, 126, 210, 78, 186, 73, 51, 233, 37, 173, 164, - 147, 52, 146, 62, 210, 70, 186, 72, 19, 233, 33, 45, 164, 131, 52, 144, 253, 23, 139, 218, 238, 217, 60, 123, 103, - 235, 236, 156, 141, 179, 239, 166, 93, 183, 237, 185, 107, 199, 125, 251, 29, 218, 237, 216, 94, 167, 118, 58, 183, - 207, 165, 93, 174, 237, 113, 107, 135, 123, 247, 47, 185, 251, 147, 59, 191, 184, 239, 155, 187, 126, 184, 103, 217, - 29, 235, 55, 171, 223, 173, 104, 184, 231, 255, 243, 7, 236, 52, 239, 128, 225, 3, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 77, 210, 7, 78, 2, 1, 20, 69, 81, 236, 189, 247, 222, + 123, 239, 93, 177, 33, 34, 238, 194, 253, 47, 193, 200, 147, 67, 194, 36, 147, 163, 33, 33, + 228, 191, 219, 82, 168, 63, 63, 181, 183, 197, 223, 177, 147, 191, 181, 183, 149, 69, 159, + 183, 213, 222, 238, 218, 219, 206, 14, 118, 178, 139, 141, 183, 135, 189, 236, 99, 63, 7, + 56, 200, 33, 14, 115, 132, 163, 28, 227, 56, 39, 56, 201, 41, 78, 115, 134, 179, 156, 227, + 60, 23, 184, 200, 37, 46, 115, 133, 171, 92, 227, 58, 55, 184, 201, 45, 110, 115, 135, 187, + 220, 227, 62, 15, 120, 200, 35, 30, 243, 132, 167, 60, 227, 57, 47, 120, 201, 43, 94, 243, + 134, 183, 188, 227, 61, 31, 248, 200, 39, 22, 249, 204, 151, 166, 29, 243, 188, 250, 255, + 141, 239, 44, 241, 131, 101, 126, 178, 194, 47, 86, 249, 237, 123, 171, 76, 127, 105, 47, + 189, 165, 181, 116, 150, 198, 26, 125, 245, 248, 45, 233, 41, 45, 165, 163, 52, 148, 126, + 210, 78, 186, 73, 51, 233, 37, 173, 164, 147, 52, 146, 62, 210, 70, 186, 72, 19, 233, 33, + 45, 164, 131, 52, 144, 253, 151, 11, 245, 221, 179, 121, 246, 206, 214, 217, 57, 27, 103, + 223, 109, 187, 238, 218, 115, 223, 142, 135, 246, 59, 182, 219, 169, 189, 206, 237, 116, + 105, 159, 107, 187, 220, 218, 227, 222, 14, 143, 238, 95, 116, 247, 23, 119, 126, 115, 223, + 146, 187, 150, 221, 179, 226, 142, 141, 155, 53, 238, 86, 104, 186, 231, 255, 243, 7, 100, + 141, 232, 192, 233, 3, 0, 0, ]); export const initialWitnessMap = new Map([ From 9ceee3338c2640759a6604685569f2f061d7961b Mon Sep 17 00:00:00 2001 From: vezenovm Date: Thu, 7 Mar 2024 21:07:45 +0000 Subject: [PATCH 017/139] compress wit correctly in noir js --- .../acir/src/native_types/witness_stack.rs | 4 ++-- .../acvm-repo/acvm_js/src/compression.rs | 15 ++++++++------- .../noir_js_backend_barretenberg/package.json | 2 +- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/noir/noir-repo/acvm-repo/acir/src/native_types/witness_stack.rs b/noir/noir-repo/acvm-repo/acir/src/native_types/witness_stack.rs index 439de987b7ea..9592d90b014b 100644 --- a/noir/noir-repo/acvm-repo/acir/src/native_types/witness_stack.rs +++ b/noir/noir-repo/acvm-repo/acir/src/native_types/witness_stack.rs @@ -27,9 +27,9 @@ pub struct WitnessStack { #[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Default, Serialize, Deserialize)] pub struct StackItem { /// Index into a [crate::circuit::Program] function list for which we have an associated witness - index: u32, + pub index: u32, /// A full witness for the respective constraint system specified by the index - witness: WitnessMap, + pub witness: WitnessMap, } impl From for WitnessStack { diff --git a/noir/noir-repo/acvm-repo/acvm_js/src/compression.rs b/noir/noir-repo/acvm-repo/acvm_js/src/compression.rs index fedaa514bf06..73bcd02ecd1b 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/src/compression.rs +++ b/noir/noir-repo/acvm-repo/acvm_js/src/compression.rs @@ -1,4 +1,4 @@ -use acvm::acir::native_types::WitnessMap; +use acvm::acir::native_types::{WitnessMap, WitnessStack}; use js_sys::JsString; use wasm_bindgen::prelude::wasm_bindgen; @@ -13,10 +13,11 @@ pub fn compress_witness(witness_map: JsWitnessMap) -> Result, JsString> console_error_panic_hook::set_once(); let witness_map = WitnessMap::from(witness_map); - let compressed_witness_map: Vec = - Vec::::try_from(witness_map).map_err(|err| err.to_string())?; + let witness_stack: WitnessStack = witness_map.into(); + let compressed_witness_stack: Vec = + Vec::::try_from(witness_stack).map_err(|err| err.to_string())?; - Ok(compressed_witness_map) + Ok(compressed_witness_stack) } /// Decompresses a compressed witness as outputted by Nargo into a `WitnessMap`. @@ -27,8 +28,8 @@ pub fn compress_witness(witness_map: JsWitnessMap) -> Result, JsString> pub fn decompress_witness(compressed_witness: Vec) -> Result { console_error_panic_hook::set_once(); - let witness_map = - WitnessMap::try_from(compressed_witness.as_slice()).map_err(|err| err.to_string())?; + let witness_stack = + WitnessStack::try_from(compressed_witness.as_slice()).map_err(|err| err.to_string())?; - Ok(witness_map.into()) + Ok(witness_stack.stack[0].witness.clone().into()) } diff --git a/noir/noir-repo/tooling/noir_js_backend_barretenberg/package.json b/noir/noir-repo/tooling/noir_js_backend_barretenberg/package.json index 28c3609fd142..45069fceb561 100644 --- a/noir/noir-repo/tooling/noir_js_backend_barretenberg/package.json +++ b/noir/noir-repo/tooling/noir_js_backend_barretenberg/package.json @@ -42,7 +42,7 @@ "lint": "NODE_NO_WARNINGS=1 eslint . --ext .ts --ignore-path ./.eslintignore --max-warnings 0" }, "dependencies": { - "@aztec/bb.js": "0.24.0", + "@aztec/bb.js": "workspace:*", "@noir-lang/types": "workspace:*", "fflate": "^0.8.0" }, From 6d08e8a0dbc213cd6aeec1e6339d299c1f5d783c Mon Sep 17 00:00:00 2001 From: vezenovm Date: Thu, 7 Mar 2024 21:12:39 +0000 Subject: [PATCH 018/139] change back to pinned bb.js --- .../noir-repo/tooling/noir_js_backend_barretenberg/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noir/noir-repo/tooling/noir_js_backend_barretenberg/package.json b/noir/noir-repo/tooling/noir_js_backend_barretenberg/package.json index 45069fceb561..28c3609fd142 100644 --- a/noir/noir-repo/tooling/noir_js_backend_barretenberg/package.json +++ b/noir/noir-repo/tooling/noir_js_backend_barretenberg/package.json @@ -42,7 +42,7 @@ "lint": "NODE_NO_WARNINGS=1 eslint . --ext .ts --ignore-path ./.eslintignore --max-warnings 0" }, "dependencies": { - "@aztec/bb.js": "workspace:*", + "@aztec/bb.js": "0.24.0", "@noir-lang/types": "workspace:*", "fflate": "^0.8.0" }, From d3b5032295b7f08bf13c8e3017c16f2374f5e613 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Fri, 8 Mar 2024 20:05:37 +0000 Subject: [PATCH 019/139] update witness compression test --- .../test/shared/witness_compression.ts | 23 +++++++++++-------- .../witness_compression/Nargo.toml | 7 ++++++ .../witness_compression/Prover.toml | 2 ++ .../witness_compression/src/main.nr | 4 ++++ .../tooling/nargo_cli/src/cli/fs/witness.rs | 9 ++++++-- .../noir_js_backend_barretenberg/package.json | 2 +- .../noir_js_backend_barretenberg/src/index.ts | 6 ++++- noir/noir-repo/yarn.lock | 13 +++++------ 8 files changed, 45 insertions(+), 21 deletions(-) create mode 100644 noir/noir-repo/test_programs/execution_success/witness_compression/Nargo.toml create mode 100644 noir/noir-repo/test_programs/execution_success/witness_compression/Prover.toml create mode 100644 noir/noir-repo/test_programs/execution_success/witness_compression/src/main.nr diff --git a/noir/noir-repo/acvm-repo/acvm_js/test/shared/witness_compression.ts b/noir/noir-repo/acvm-repo/acvm_js/test/shared/witness_compression.ts index 36b9a0284af6..f9d66c2c8d0e 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/test/shared/witness_compression.ts +++ b/noir/noir-repo/acvm-repo/acvm_js/test/shared/witness_compression.ts @@ -4,19 +4,22 @@ // assert(x != y); // x + y // } +// +// Regenerate this byte array by going to the Noir integration tests and running `/test_programs/execution_success/witness_compression` +// after recompiling Noir to print the witness byte array to be written to file after execution export const expectedCompressedWitnessMap = Uint8Array.from([ - 31, 139, 8, 0, 0, 0, 0, 0, 2, 255, 173, 208, 187, 13, 128, 48, 12, 4, 80, 190, 153, 199, 142, 237, 196, 238, 88, 133, - 8, 103, 255, 17, 64, 34, 5, 61, 62, 233, 164, 171, 94, 113, 105, 122, 51, 63, 61, 198, 134, 127, 193, 37, 206, 202, - 235, 199, 34, 40, 204, 94, 179, 35, 225, 9, 217, 154, 10, 176, 180, 162, 168, 40, 42, 87, 86, 34, 87, 214, 106, 205, - 42, 24, 50, 57, 118, 49, 234, 3, 219, 2, 173, 61, 240, 175, 20, 103, 209, 13, 151, 252, 77, 33, 208, 1, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 2, 255, 173, 206, 185, 13, 0, 48, 8, 67, 209, 144, 107, 30, 146, + 44, 144, 253, 167, 162, 65, 130, 158, 239, 198, 174, 158, 44, 45, 178, 211, 254, 222, 90, + 203, 17, 206, 186, 29, 252, 53, 64, 107, 114, 150, 46, 206, 122, 6, 24, 73, 44, 193, 220, + 1, 0, 0, ]); export const expectedWitnessMap = new Map([ - [1, '0x0000000000000000000000000000000000000000000000000000000000000001'], - [2, '0x0000000000000000000000000000000000000000000000000000000000000002'], - [3, '0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000'], - [4, '0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000'], - [5, '0x0000000000000000000000000000000000000000000000000000000000000001'], - [6, '0x0000000000000000000000000000000000000000000000000000000000000003'], + [0, '0x0000000000000000000000000000000000000000000000000000000000000001'], + [1, '0x0000000000000000000000000000000000000000000000000000000000000002'], + [2, '0x0000000000000000000000000000000000000000000000000000000000000001'], + [3, '0x0000000000000000000000000000000000000000000000000000000000000001'], + [4, '0x0000000000000000000000000000000000000000000000000000000000000000'], + [5, '0x0000000000000000000000000000000000000000000000000000000000000003'], ]); diff --git a/noir/noir-repo/test_programs/execution_success/witness_compression/Nargo.toml b/noir/noir-repo/test_programs/execution_success/witness_compression/Nargo.toml new file mode 100644 index 000000000000..7d6ba0c1938d --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/witness_compression/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "witness_compression" +type = "bin" +authors = [""] +compiler_version = ">=0.24.0" + +[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/execution_success/witness_compression/Prover.toml b/noir/noir-repo/test_programs/execution_success/witness_compression/Prover.toml new file mode 100644 index 000000000000..8c12ebba6cf7 --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/witness_compression/Prover.toml @@ -0,0 +1,2 @@ +x = "1" +y = "2" diff --git a/noir/noir-repo/test_programs/execution_success/witness_compression/src/main.nr b/noir/noir-repo/test_programs/execution_success/witness_compression/src/main.nr new file mode 100644 index 000000000000..803b72c64c55 --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/witness_compression/src/main.nr @@ -0,0 +1,4 @@ +fn main(x : Field, y : pub Field) -> pub Field { + assert(x != y); + x + y +} diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/fs/witness.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/fs/witness.rs index 52b5c385e5df..7378a861e499 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/fs/witness.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/fs/witness.rs @@ -13,11 +13,16 @@ pub(crate) fn save_witness_to_dir>( ) -> Result { create_named_dir(witness_dir.as_ref(), "witness"); let witness_path = witness_dir.as_ref().join(witness_name).with_extension(WITNESS_EXT); - + dbg!(witnesses.clone()); // TODO(https://github.com/noir-lang/noir/issues/4428) let witness_stack: WitnessStack = witnesses.into(); let buf: Vec = witness_stack.try_into()?; - + // let x = vec![ + // 31, 139, 8, 0, 0, 0, 0, 0, 2, 255, 173, 206, 185, 13, 0, 48, 8, 67, 209, 144, 107, 30, 146, + // 44, 144, 253, 167, 162, 65, 130, 158, 239, 198, 174, 158, 44, 45, 178, 211, 254, 222, 90, + // 203, 17, 206, 186, 29, 252, 53, 64, 107, 114, 150, 46, 206, 122, 6, 24, 73, 44, 193, 220, + // 1, 0, 0, + // ]; write_to_file(buf.as_slice(), &witness_path); Ok(witness_path) diff --git a/noir/noir-repo/tooling/noir_js_backend_barretenberg/package.json b/noir/noir-repo/tooling/noir_js_backend_barretenberg/package.json index 28c3609fd142..97b412cc9459 100644 --- a/noir/noir-repo/tooling/noir_js_backend_barretenberg/package.json +++ b/noir/noir-repo/tooling/noir_js_backend_barretenberg/package.json @@ -42,7 +42,7 @@ "lint": "NODE_NO_WARNINGS=1 eslint . --ext .ts --ignore-path ./.eslintignore --max-warnings 0" }, "dependencies": { - "@aztec/bb.js": "0.24.0", + "@aztec/bb.js": "portal:../../../../barretenberg/ts", "@noir-lang/types": "workspace:*", "fflate": "^0.8.0" }, diff --git a/noir/noir-repo/tooling/noir_js_backend_barretenberg/src/index.ts b/noir/noir-repo/tooling/noir_js_backend_barretenberg/src/index.ts index af03743eb2f2..c6b3181b510d 100644 --- a/noir/noir-repo/tooling/noir_js_backend_barretenberg/src/index.ts +++ b/noir/noir-repo/tooling/noir_js_backend_barretenberg/src/index.ts @@ -32,6 +32,7 @@ export class BarretenbergBackend implements Backend { /** @ignore */ async instantiate(): Promise { + console.log("in instantiate"); if (!this.api) { if (typeof navigator !== 'undefined' && navigator.hardwareConcurrency) { this.options.threads = navigator.hardwareConcurrency; @@ -43,10 +44,13 @@ export class BarretenbergBackend implements Backend { console.log('Could not detect environment. Falling back to one thread.', e); } } + console.log("about to fetch bberg") const { Barretenberg, RawBuffer, Crs } = await import('@aztec/bb.js'); + console.log("about to fetch bberg api"); const api = await Barretenberg.new(this.options); - + console.log("about to call acirGetCircuitSizes") const [_exact, _total, subgroupSize] = await api.acirGetCircuitSizes(this.acirUncompressedBytecode); + console.log("subgroupSize: ", subgroupSize); const crs = await Crs.new(subgroupSize + 1); await api.commonInitSlabAllocator(subgroupSize); await api.srsInitSrs(new RawBuffer(crs.getG1Data()), crs.numPoints, new RawBuffer(crs.getG2Data())); diff --git a/noir/noir-repo/yarn.lock b/noir/noir-repo/yarn.lock index f5f3a29f08a6..ad12edebc854 100644 --- a/noir/noir-repo/yarn.lock +++ b/noir/noir-repo/yarn.lock @@ -221,19 +221,18 @@ __metadata: languageName: node linkType: hard -"@aztec/bb.js@npm:0.24.0": - version: 0.24.0 - resolution: "@aztec/bb.js@npm:0.24.0" +"@aztec/bb.js@portal:../../../../barretenberg/ts::locator=%40noir-lang%2Fbackend_barretenberg%40workspace%3Atooling%2Fnoir_js_backend_barretenberg": + version: 0.0.0-use.local + resolution: "@aztec/bb.js@portal:../../../../barretenberg/ts::locator=%40noir-lang%2Fbackend_barretenberg%40workspace%3Atooling%2Fnoir_js_backend_barretenberg" dependencies: comlink: ^4.4.1 commander: ^10.0.1 debug: ^4.3.4 tslib: ^2.4.0 bin: - bb.js: dest/node/main.js - checksum: a086dabf30084cfa526e512148b9c02f0a0770dcc19b7dca4af9a3e98612b716acc7eaac6b52c0f12d985932e866d1cb9e534ded6ac9d747f3dd021afe25de27 + bb.js: ./dest/node/main.js languageName: node - linkType: hard + linkType: soft "@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.10.4, @babel/code-frame@npm:^7.12.11, @babel/code-frame@npm:^7.16.0, @babel/code-frame@npm:^7.22.13, @babel/code-frame@npm:^7.23.5, @babel/code-frame@npm:^7.8.3": version: 7.23.5 @@ -4396,7 +4395,7 @@ __metadata: version: 0.0.0-use.local resolution: "@noir-lang/backend_barretenberg@workspace:tooling/noir_js_backend_barretenberg" dependencies: - "@aztec/bb.js": 0.24.0 + "@aztec/bb.js": "portal:../../../../barretenberg/ts" "@noir-lang/types": "workspace:*" "@types/node": ^20.6.2 "@types/prettier": ^3 From 94b4739fdbecde3d4caaff6f1f01ed503bb5069c Mon Sep 17 00:00:00 2001 From: vezenovm Date: Fri, 8 Mar 2024 20:35:15 +0000 Subject: [PATCH 020/139] update Dockerfiles --- noir/Dockerfile.packages | 6 ++++++ noir/Dockerfile.packages-test | 3 +++ 2 files changed, 9 insertions(+) diff --git a/noir/Dockerfile.packages b/noir/Dockerfile.packages index c45260afaf4d..f6bf8ad67568 100644 --- a/noir/Dockerfile.packages +++ b/noir/Dockerfile.packages @@ -1,4 +1,10 @@ +FROM --platform=linux/amd64 aztecprotocol/bb.js as bb.js + FROM node:20 AS builder + +# Copy in portalled packages. +COPY --from=bb.js /usr/src/barretenberg/ts /usr/src/barretenberg/ts + ENV PATH=${PATH}:/usr/src/noir/noir-repo/target/release RUN curl https://sh.rustup.rs -sSf | bash -s -- -y RUN echo 'source $HOME/.cargo/env' >> $HOME/.bashrc diff --git a/noir/Dockerfile.packages-test b/noir/Dockerfile.packages-test index 33fac5120fb4..b05ae7573169 100644 --- a/noir/Dockerfile.packages-test +++ b/noir/Dockerfile.packages-test @@ -1,4 +1,5 @@ FROM aztecprotocol/noir AS noir +FROM --platform=linux/amd64 aztecprotocol/bb.js as bb.js FROM node:20 AS builder COPY --from=noir /usr/src/noir/noir-repo/target/release /usr/src/noir/noir-repo/target/release @@ -10,6 +11,8 @@ RUN apt update && apt install -y jq libc++1 ARG COMMIT_HASH ENV COMMIT_HASH=${COMMIT_HASH} +COPY --from=bb.js /usr/src/barretenberg/ts /usr/src/barretenberg/ts + WORKDIR /usr/src/noir COPY . . RUN ./scripts/test_js_packages.sh From c01aa62dc93e04dc63c40f16f95e3f760c6db6b4 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Fri, 8 Mar 2024 20:48:17 +0000 Subject: [PATCH 021/139] switch order of noir tests --- .circleci/config.yml | 194 +++++++++++++++++----------------- noir/Dockerfile.packages-test | 4 +- 2 files changed, 99 insertions(+), 99 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 2ea5e510882f..5894a1c04953 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -92,103 +92,6 @@ jobs: - continuation/continue: configuration_path: .circleci/generated_config.yml - # Noir - noir-x86_64: - docker: - - image: aztecprotocol/alpine-build-image - resource_class: small - steps: - - *checkout - - *setup_env - - run: - name: "Build" - command: cond_spot_run_build noir 32 - aztec_manifest_key: noir - - noir-arm64: - docker: - - image: aztecprotocol/alpine-build-image - resource_class: small - steps: - - *checkout - - *setup_env - - run: - name: "Build" - command: cond_spot_run_build noir 32 arm64 - aztec_manifest_key: noir - - noir-ecr-manifest: - machine: - image: default - resource_class: medium - steps: - - *checkout - - *setup_env - - run: - name: "Create ECR manifest" - command: create_ecr_manifest noir x86_64,arm64 - aztec_manifest_key: noir - - noir-tests: - docker: - - image: aztecprotocol/alpine-build-image - resource_class: small - steps: - - *checkout - - *setup_env - - run: - name: "Build" - command: cond_spot_run_build noir-tests 32 - aztec_manifest_key: noir-tests - - noir-packages: - docker: - - image: aztecprotocol/alpine-build-image - resource_class: small - steps: - - *checkout - - *setup_env - - run: - name: "Build" - command: cond_spot_run_build noir-packages 32 - aztec_manifest_key: noir-packages - - noir-packages-tests: - docker: - - image: aztecprotocol/alpine-build-image - resource_class: small - steps: - - *checkout - - *setup_env - - run: - name: "Build" - command: cond_spot_run_build noir-packages-tests 32 - aztec_manifest_key: noir-packages-tests - - noir-compile-acir-tests: - docker: - - image: aztecprotocol/alpine-build-image - resource_class: small - steps: - - *checkout - - *setup_env - - run: - name: "Build" - command: cond_spot_run_build noir-compile-acir-tests 32 - aztec_manifest_key: noir-compile-acir-tests - - avm-transpiler: - docker: - - image: aztecprotocol/alpine-build-image - resource_class: small - steps: - - *checkout - - *setup_env - - run: - name: "Build" - command: cond_spot_run_build avm-transpiler 32 - aztec_manifest_key: avm-transpiler - # Barretenberg barretenberg-wasm-linux-clang: docker: @@ -367,6 +270,103 @@ jobs: name: "Test" command: cond_spot_run_test barretenberg-x86_64-linux-clang-assert 32 ./scripts/run_tests 3 join_split_example_proofs_join_split_tests --gtest_filter=-*full_proof* aztec_manifest_key: barretenberg-x86_64-linux-clang-assert + + # Noir + noir-x86_64: + docker: + - image: aztecprotocol/alpine-build-image + resource_class: small + steps: + - *checkout + - *setup_env + - run: + name: "Build" + command: cond_spot_run_build noir 32 + aztec_manifest_key: noir + + noir-arm64: + docker: + - image: aztecprotocol/alpine-build-image + resource_class: small + steps: + - *checkout + - *setup_env + - run: + name: "Build" + command: cond_spot_run_build noir 32 arm64 + aztec_manifest_key: noir + + noir-ecr-manifest: + machine: + image: default + resource_class: medium + steps: + - *checkout + - *setup_env + - run: + name: "Create ECR manifest" + command: create_ecr_manifest noir x86_64,arm64 + aztec_manifest_key: noir + + noir-tests: + docker: + - image: aztecprotocol/alpine-build-image + resource_class: small + steps: + - *checkout + - *setup_env + - run: + name: "Build" + command: cond_spot_run_build noir-tests 32 + aztec_manifest_key: noir-tests + + noir-packages: + docker: + - image: aztecprotocol/alpine-build-image + resource_class: small + steps: + - *checkout + - *setup_env + - run: + name: "Build" + command: cond_spot_run_build noir-packages 32 + aztec_manifest_key: noir-packages + + noir-packages-tests: + docker: + - image: aztecprotocol/alpine-build-image + resource_class: small + steps: + - *checkout + - *setup_env + - run: + name: "Build" + command: cond_spot_run_build noir-packages-tests 32 + aztec_manifest_key: noir-packages-tests + + noir-compile-acir-tests: + docker: + - image: aztecprotocol/alpine-build-image + resource_class: small + steps: + - *checkout + - *setup_env + - run: + name: "Build" + command: cond_spot_run_build noir-compile-acir-tests 32 + aztec_manifest_key: noir-compile-acir-tests + + avm-transpiler: + docker: + - image: aztecprotocol/alpine-build-image + resource_class: small + steps: + - *checkout + - *setup_env + - run: + name: "Build" + command: cond_spot_run_build avm-transpiler 32 + aztec_manifest_key: avm-transpiler barretenberg-acir-tests-bb: docker: diff --git a/noir/Dockerfile.packages-test b/noir/Dockerfile.packages-test index b05ae7573169..96bfd51e4da9 100644 --- a/noir/Dockerfile.packages-test +++ b/noir/Dockerfile.packages-test @@ -2,6 +2,8 @@ FROM aztecprotocol/noir AS noir FROM --platform=linux/amd64 aztecprotocol/bb.js as bb.js FROM node:20 AS builder +COPY --from=bb.js /usr/src/barretenberg/ts /usr/src/barretenberg/ts + COPY --from=noir /usr/src/noir/noir-repo/target/release /usr/src/noir/noir-repo/target/release ENV PATH=${PATH}:/usr/src/noir/noir-repo/target/release RUN curl https://sh.rustup.rs -sSf | bash -s -- -y @@ -11,8 +13,6 @@ RUN apt update && apt install -y jq libc++1 ARG COMMIT_HASH ENV COMMIT_HASH=${COMMIT_HASH} -COPY --from=bb.js /usr/src/barretenberg/ts /usr/src/barretenberg/ts - WORKDIR /usr/src/noir COPY . . RUN ./scripts/test_js_packages.sh From 20235563eed113bfd12cdac12ad4be6dfb7b03bf Mon Sep 17 00:00:00 2001 From: vezenovm Date: Fri, 8 Mar 2024 20:51:37 +0000 Subject: [PATCH 022/139] bb js before noir in the config file --- .circleci/config.yml | 48 ++++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 5894a1c04953..a61f122771cd 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -270,6 +270,30 @@ jobs: name: "Test" command: cond_spot_run_test barretenberg-x86_64-linux-clang-assert 32 ./scripts/run_tests 3 join_split_example_proofs_join_split_tests --gtest_filter=-*full_proof* aztec_manifest_key: barretenberg-x86_64-linux-clang-assert + + bb-js: + machine: + image: default + resource_class: large + steps: + - *checkout + - *setup_env + - run: + name: "Build and test" + command: build bb.js + aztec_manifest_key: bb.js + + bb-js-tests: + docker: + - image: aztecprotocol/alpine-build-image + resource_class: small + steps: + - *checkout + - *setup_env + - run: + name: "Build and test" + command: cond_spot_run_test bb.js 32 ./scripts/run_tests + aztec_manifest_key: bb.js # Noir noir-x86_64: @@ -380,30 +404,6 @@ jobs: command: cond_spot_run_build barretenberg-acir-tests-bb 32 aztec_manifest_key: barretenberg-acir-tests-bb - bb-js: - machine: - image: default - resource_class: large - steps: - - *checkout - - *setup_env - - run: - name: "Build and test" - command: build bb.js - aztec_manifest_key: bb.js - - bb-js-tests: - docker: - - image: aztecprotocol/alpine-build-image - resource_class: small - steps: - - *checkout - - *setup_env - - run: - name: "Build and test" - command: cond_spot_run_test bb.js 32 ./scripts/run_tests - aztec_manifest_key: bb.js - bb-js-acir-tests: docker: - image: aztecprotocol/alpine-build-image From 3a3150498a9c72b3cc63fe8224847246087348e8 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Fri, 8 Mar 2024 20:56:11 +0000 Subject: [PATCH 023/139] specify bb.js dep --- build_manifest.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/build_manifest.yml b/build_manifest.yml index 0341632b1afe..46b8db28fa7b 100644 --- a/build_manifest.yml +++ b/build_manifest.yml @@ -28,6 +28,8 @@ noir-packages: buildDir: noir dockerfile: Dockerfile.packages rebuildPatterns: .rebuild_patterns_packages + dependencies: + - bb.js # Builds and runs *all* noir package tests. noir-packages-tests: @@ -36,6 +38,7 @@ noir-packages-tests: rebuildPatterns: .rebuild_patterns_packages dependencies: - noir + - bb.js # Builds the brillig to avm transpiler. avm-transpiler: From 0b5ab1451a3266401ab8efb73180e118689ce810 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Fri, 8 Mar 2024 21:59:37 +0000 Subject: [PATCH 024/139] remove unnecessary prints --- .../tooling/noir_js/test/node/e2e.test.ts | 58 +++++++++---------- .../noir_js_backend_barretenberg/src/index.ts | 5 -- 2 files changed, 29 insertions(+), 34 deletions(-) diff --git a/noir/noir-repo/tooling/noir_js/test/node/e2e.test.ts b/noir/noir-repo/tooling/noir_js/test/node/e2e.test.ts index 8921314e8ea3..206e681dab35 100644 --- a/noir/noir-repo/tooling/noir_js/test/node/e2e.test.ts +++ b/noir/noir-repo/tooling/noir_js/test/node/e2e.test.ts @@ -98,32 +98,32 @@ it('end-to-end proving and verification with different instances', async () => { // If we only create one type of proof, then this works as expected. // // If we do not create an inner proof, then this will work as expected. -it('[BUG] -- bb.js null function or function signature mismatch (outer-inner) ', async () => { - // Noir.Js part - const inputs = { - x: '2', - y: '3', - }; - - const program = new Noir(assert_lt_program); - - const { witness } = await program.execute(inputs); - - // bb.js part - // - // Proof creation - // - const prover = new Backend(assert_lt_program); - // Create a proof using both proving systems, the majority of the time - // one would only use outer proofs. - const proofOuter = await prover.generateProof(witness); - const _proofInner = await prover.generateProof(witness); - - // Proof verification - // - const isValidOuter = await prover.verifyProof(proofOuter); - expect(isValidOuter).to.be.true; - // We can also try verifying an inner proof and it will fail. - const isValidInner = await prover.verifyProof(_proofInner); - expect(isValidInner).to.be.true; -}); +// it('[BUG] -- bb.js null function or function signature mismatch (outer-inner) ', async () => { +// // Noir.Js part +// const inputs = { +// x: '2', +// y: '3', +// }; + +// const program = new Noir(assert_lt_program); + +// const { witness } = await program.execute(inputs); + +// // bb.js part +// // +// // Proof creation +// // +// const prover = new Backend(assert_lt_program); +// // Create a proof using both proving systems, the majority of the time +// // one would only use outer proofs. +// const proofOuter = await prover.generateProof(witness); +// const _proofInner = await prover.generateProof(witness); + +// // Proof verification +// // +// const isValidOuter = await prover.verifyProof(proofOuter); +// expect(isValidOuter).to.be.true; +// // We can also try verifying an inner proof and it will fail. +// const isValidInner = await prover.verifyProof(_proofInner); +// expect(isValidInner).to.be.true; +// }); diff --git a/noir/noir-repo/tooling/noir_js_backend_barretenberg/src/index.ts b/noir/noir-repo/tooling/noir_js_backend_barretenberg/src/index.ts index c6b3181b510d..bfdf1005a939 100644 --- a/noir/noir-repo/tooling/noir_js_backend_barretenberg/src/index.ts +++ b/noir/noir-repo/tooling/noir_js_backend_barretenberg/src/index.ts @@ -32,7 +32,6 @@ export class BarretenbergBackend implements Backend { /** @ignore */ async instantiate(): Promise { - console.log("in instantiate"); if (!this.api) { if (typeof navigator !== 'undefined' && navigator.hardwareConcurrency) { this.options.threads = navigator.hardwareConcurrency; @@ -44,13 +43,9 @@ export class BarretenbergBackend implements Backend { console.log('Could not detect environment. Falling back to one thread.', e); } } - console.log("about to fetch bberg") const { Barretenberg, RawBuffer, Crs } = await import('@aztec/bb.js'); - console.log("about to fetch bberg api"); const api = await Barretenberg.new(this.options); - console.log("about to call acirGetCircuitSizes") const [_exact, _total, subgroupSize] = await api.acirGetCircuitSizes(this.acirUncompressedBytecode); - console.log("subgroupSize: ", subgroupSize); const crs = await Crs.new(subgroupSize + 1); await api.commonInitSlabAllocator(subgroupSize); await api.srsInitSrs(new RawBuffer(crs.getG1Data()), crs.numPoints, new RawBuffer(crs.getG2Data())); From babb4833ce8d2bdd903caeed9768594081b54d9f Mon Sep 17 00:00:00 2001 From: vezenovm Date: Mon, 11 Mar 2024 17:02:03 +0000 Subject: [PATCH 025/139] uncomment one e2e test --- .../tooling/noir_js/test/node/e2e.test.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/noir/noir-repo/tooling/noir_js/test/node/e2e.test.ts b/noir/noir-repo/tooling/noir_js/test/node/e2e.test.ts index 206e681dab35..0319a7c83187 100644 --- a/noir/noir-repo/tooling/noir_js/test/node/e2e.test.ts +++ b/noir/noir-repo/tooling/noir_js/test/node/e2e.test.ts @@ -91,13 +91,13 @@ it('end-to-end proving and verification with different instances', async () => { expect(proof_is_valid).to.be.true; }); -// This bug occurs when we use the same backend to create an inner proof and then an outer proof -// and then try to verify either one of them. -// -// The panic occurs when we try to verify the outer/inner proof that was created. -// If we only create one type of proof, then this works as expected. -// -// If we do not create an inner proof, then this will work as expected. +// // This bug occurs when we use the same backend to create an inner proof and then an outer proof +// // and then try to verify either one of them. +// // +// // The panic occurs when we try to verify the outer/inner proof that was created. +// // If we only create one type of proof, then this works as expected. +// // +// // If we do not create an inner proof, then this will work as expected. // it('[BUG] -- bb.js null function or function signature mismatch (outer-inner) ', async () => { // // Noir.Js part // const inputs = { From 127e03fc6535dcfd42a631590085c05aed05b213 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Mon, 11 Mar 2024 17:41:23 +0000 Subject: [PATCH 026/139] remove old comment and try bootstrap_packages --- noir/Dockerfile.packages-test | 1 + noir/noir-repo/tooling/nargo_cli/src/cli/fs/witness.rs | 7 +------ 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/noir/Dockerfile.packages-test b/noir/Dockerfile.packages-test index 96bfd51e4da9..0f7e3a8fa64f 100644 --- a/noir/Dockerfile.packages-test +++ b/noir/Dockerfile.packages-test @@ -15,6 +15,7 @@ ENV COMMIT_HASH=${COMMIT_HASH} WORKDIR /usr/src/noir COPY . . +RUN ./scripts/bootstrap_packages.sh RUN ./scripts/test_js_packages.sh # Don't waste time pushing a huge container back to ECR as nothing needs the output. diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/fs/witness.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/fs/witness.rs index 7378a861e499..ea6bf8bbb11f 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/fs/witness.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/fs/witness.rs @@ -17,12 +17,7 @@ pub(crate) fn save_witness_to_dir>( // TODO(https://github.com/noir-lang/noir/issues/4428) let witness_stack: WitnessStack = witnesses.into(); let buf: Vec = witness_stack.try_into()?; - // let x = vec![ - // 31, 139, 8, 0, 0, 0, 0, 0, 2, 255, 173, 206, 185, 13, 0, 48, 8, 67, 209, 144, 107, 30, 146, - // 44, 144, 253, 167, 162, 65, 130, 158, 239, 198, 174, 158, 44, 45, 178, 211, 254, 222, 90, - // 203, 17, 206, 186, 29, 252, 53, 64, 107, 114, 150, 46, 206, 122, 6, 24, 73, 44, 193, 220, - // 1, 0, 0, - // ]; + write_to_file(buf.as_slice(), &witness_path); Ok(witness_path) From 111089e36a1e54e43f2968d00df4fc2b08a24bd0 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Mon, 11 Mar 2024 17:49:38 +0000 Subject: [PATCH 027/139] yarn inside bb ts --- noir/Dockerfile.packages-test | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/noir/Dockerfile.packages-test b/noir/Dockerfile.packages-test index 0f7e3a8fa64f..6c9c7c9ac48a 100644 --- a/noir/Dockerfile.packages-test +++ b/noir/Dockerfile.packages-test @@ -4,6 +4,9 @@ FROM --platform=linux/amd64 aztecprotocol/bb.js as bb.js FROM node:20 AS builder COPY --from=bb.js /usr/src/barretenberg/ts /usr/src/barretenberg/ts +WORKDIR /usr/src/barretenberg/ts +RUN yarn --immutable + COPY --from=noir /usr/src/noir/noir-repo/target/release /usr/src/noir/noir-repo/target/release ENV PATH=${PATH}:/usr/src/noir/noir-repo/target/release RUN curl https://sh.rustup.rs -sSf | bash -s -- -y @@ -15,7 +18,6 @@ ENV COMMIT_HASH=${COMMIT_HASH} WORKDIR /usr/src/noir COPY . . -RUN ./scripts/bootstrap_packages.sh RUN ./scripts/test_js_packages.sh # Don't waste time pushing a huge container back to ECR as nothing needs the output. From 4e361fe6b043359a774fc7d8f4d84fa18ec347c9 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Mon, 11 Mar 2024 22:12:02 +0000 Subject: [PATCH 028/139] appropriately serialize program for smart contract --- .../backend_interface/src/smart_contract.rs | 15 ++++++++------- .../nargo_cli/src/cli/codegen_verifier_cmd.rs | 2 +- noir/scripts/test_js_packages.sh | 2 +- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/noir/noir-repo/tooling/backend_interface/src/smart_contract.rs b/noir/noir-repo/tooling/backend_interface/src/smart_contract.rs index 5af75e48389a..f6beeeb09d99 100644 --- a/noir/noir-repo/tooling/backend_interface/src/smart_contract.rs +++ b/noir/noir-repo/tooling/backend_interface/src/smart_contract.rs @@ -3,11 +3,11 @@ use crate::{ cli::{ContractCommand, WriteVkCommand}, Backend, BackendError, }; -use acvm::acir::circuit::Circuit; +use acvm::acir::circuit::Program; use tempfile::tempdir; impl Backend { - pub fn eth_contract(&self, circuit: &Circuit) -> Result { + pub fn eth_contract(&self, program: &Program) -> Result { let binary_path = self.assert_binary_exists()?; self.assert_correct_version()?; @@ -15,9 +15,9 @@ impl Backend { let temp_directory_path = temp_directory.path().to_path_buf(); // Create a temporary file for the circuit - let bytecode_path = temp_directory_path.join("circuit").with_extension("bytecode"); - let serialized_circuit = Circuit::serialize_circuit(circuit); - write_to_file(&serialized_circuit, &bytecode_path); + let bytecode_path = temp_directory_path.join("program").with_extension("bytecode"); + let serialized_program = Program::serialize_program(program); + write_to_file(&serialized_program, &bytecode_path); // Create the verification key and write it to the specified path let vk_path = temp_directory_path.join("vk"); @@ -38,7 +38,7 @@ mod tests { use std::collections::BTreeSet; use acvm::acir::{ - circuit::{Circuit, ExpressionWidth, Opcode, PublicInputs}, + circuit::{Circuit, ExpressionWidth, Opcode, Program, PublicInputs}, native_types::{Expression, Witness}, }; @@ -59,8 +59,9 @@ mod tests { assert_messages: Default::default(), recursive: false, }; + let program = Program { functions: vec![circuit] }; - let contract = get_mock_backend()?.eth_contract(&circuit)?; + let contract = get_mock_backend()?.eth_contract(&program)?; assert!(contract.contains("contract VerifierContract")); diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/codegen_verifier_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/codegen_verifier_cmd.rs index 10aeadb02965..259e209b65a3 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/codegen_verifier_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/codegen_verifier_cmd.rs @@ -70,7 +70,7 @@ pub(crate) fn run( // that will be inlined at a later step such as by the ACVM compiler or by the backend. // Add appropriate handling here once the compiler enables multiple ACIR functions. assert_eq!(program.program.functions.len(), 1); - let smart_contract_string = backend.eth_contract(&program.program.functions[0])?; + let smart_contract_string = backend.eth_contract(&program.program)?; let contract_dir = workspace.contracts_directory_path(package); create_named_dir(&contract_dir, "contract"); diff --git a/noir/scripts/test_js_packages.sh b/noir/scripts/test_js_packages.sh index 687ab802fee2..0e7452dfd5c1 100755 --- a/noir/scripts/test_js_packages.sh +++ b/noir/scripts/test_js_packages.sh @@ -15,6 +15,6 @@ export PATH="${PATH}:/usr/src/noir/noir-repo/target/release/" yarn --immutable yarn build -./.github/scripts/playwright-install.sh +# ./.github/scripts/playwright-install.sh yarn test From 6905b96eb484721f8078dc4d695035c5724de96a Mon Sep 17 00:00:00 2001 From: vezenovm Date: Mon, 11 Mar 2024 22:54:22 +0000 Subject: [PATCH 029/139] disable simple_verifier_codegen in aztec_packages native CI --- noir/scripts/test_native.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noir/scripts/test_native.sh b/noir/scripts/test_native.sh index e106c5b719b7..744c759e212b 100755 --- a/noir/scripts/test_native.sh +++ b/noir/scripts/test_native.sh @@ -14,4 +14,4 @@ cargo clippy --workspace --locked --release ./.github/scripts/cargo-binstall-install.sh cargo-binstall cargo-nextest --version 0.9.67 -y --secure -cargo nextest run --locked --release -E '!test(hello_world_example)' +cargo nextest run --locked --release -E '!test(hello_world_example)' -E '!test(simple_verifier_codegen)' From 6ddfd3027e5f86ea8fdcd99ae0cde880e2edc5a4 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Mon, 11 Mar 2024 22:56:36 +0000 Subject: [PATCH 030/139] bring back install playwright for CI --- noir/scripts/test_js_packages.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noir/scripts/test_js_packages.sh b/noir/scripts/test_js_packages.sh index 0e7452dfd5c1..687ab802fee2 100755 --- a/noir/scripts/test_js_packages.sh +++ b/noir/scripts/test_js_packages.sh @@ -15,6 +15,6 @@ export PATH="${PATH}:/usr/src/noir/noir-repo/target/release/" yarn --immutable yarn build -# ./.github/scripts/playwright-install.sh +./.github/scripts/playwright-install.sh yarn test From 2b1639a923643eba5ea9cfdd2d570390e1f9819a Mon Sep 17 00:00:00 2001 From: vezenovm Date: Mon, 11 Mar 2024 23:13:01 +0000 Subject: [PATCH 031/139] fix simple_verifier_codegen nextest expr --- noir/scripts/test_native.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noir/scripts/test_native.sh b/noir/scripts/test_native.sh index 744c759e212b..d1341b1e3140 100755 --- a/noir/scripts/test_native.sh +++ b/noir/scripts/test_native.sh @@ -14,4 +14,4 @@ cargo clippy --workspace --locked --release ./.github/scripts/cargo-binstall-install.sh cargo-binstall cargo-nextest --version 0.9.67 -y --secure -cargo nextest run --locked --release -E '!test(hello_world_example)' -E '!test(simple_verifier_codegen)' +cargo nextest run --locked --release -E '!test(hello_world_example) + !test(simple_verifier_codegen)' From a755f8ae1d3cc6a9106d66c45b4367714e78c85a Mon Sep 17 00:00:00 2001 From: vezenovm Date: Mon, 11 Mar 2024 23:23:37 +0000 Subject: [PATCH 032/139] and not or --- noir/scripts/test_native.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noir/scripts/test_native.sh b/noir/scripts/test_native.sh index d1341b1e3140..c1f499d491b3 100755 --- a/noir/scripts/test_native.sh +++ b/noir/scripts/test_native.sh @@ -14,4 +14,4 @@ cargo clippy --workspace --locked --release ./.github/scripts/cargo-binstall-install.sh cargo-binstall cargo-nextest --version 0.9.67 -y --secure -cargo nextest run --locked --release -E '!test(hello_world_example) + !test(simple_verifier_codegen)' +cargo nextest run --locked --release -E '!test(hello_world_example) & !test(simple_verifier_codegen)' From 3b2a7e4d771a24b312c520d8a4da4a204ac3082b Mon Sep 17 00:00:00 2001 From: vezenovm Date: Tue, 12 Mar 2024 02:59:13 +0000 Subject: [PATCH 033/139] passing hardcoded contracts --- .../acir_tests/flows/write_contract.sh | 7 + .../compiler/integration-tests/.gitignore | 1 - .../integration-tests/contracts/1_mul.sol | 2869 +++++++++++++++++ .../contracts/assert_statement.sol | 2869 +++++++++++++++++ .../integration-tests/contracts/recursion.sol | 2869 +++++++++++++++++ .../compiler/integration-tests/package.json | 2 +- .../execution_success/recursion/Nargo.toml | 7 + .../execution_success/recursion/Prover.toml | 4 + .../execution_success/recursion/src/main.nr | 16 + .../backend_interface/src/smart_contract.rs | 3 +- .../tooling/nargo_cli/src/cli/fs/witness.rs | 2 +- 11 files changed, 8645 insertions(+), 4 deletions(-) create mode 100755 barretenberg/acir_tests/flows/write_contract.sh create mode 100644 noir/noir-repo/compiler/integration-tests/contracts/1_mul.sol create mode 100644 noir/noir-repo/compiler/integration-tests/contracts/assert_statement.sol create mode 100644 noir/noir-repo/compiler/integration-tests/contracts/recursion.sol create mode 100644 noir/noir-repo/test_programs/execution_success/recursion/Nargo.toml create mode 100644 noir/noir-repo/test_programs/execution_success/recursion/Prover.toml create mode 100644 noir/noir-repo/test_programs/execution_success/recursion/src/main.nr diff --git a/barretenberg/acir_tests/flows/write_contract.sh b/barretenberg/acir_tests/flows/write_contract.sh new file mode 100755 index 000000000000..4f483395c58d --- /dev/null +++ b/barretenberg/acir_tests/flows/write_contract.sh @@ -0,0 +1,7 @@ +#!/bin/sh +set -eu + +export TEST_NAME=$(basename $(pwd)) + +$BIN write_vk -o vk +$BIN contract -k vk -c $CRS_PATH -b ./target/acir.gz -o $TEST_NAME.sol diff --git a/noir/noir-repo/compiler/integration-tests/.gitignore b/noir/noir-repo/compiler/integration-tests/.gitignore index 40571b83650d..d27cc5f16183 100644 --- a/noir/noir-repo/compiler/integration-tests/.gitignore +++ b/noir/noir-repo/compiler/integration-tests/.gitignore @@ -1,4 +1,3 @@ -contracts crs node_modules diff --git a/noir/noir-repo/compiler/integration-tests/contracts/1_mul.sol b/noir/noir-repo/compiler/integration-tests/contracts/1_mul.sol new file mode 100644 index 000000000000..ff8f36385337 --- /dev/null +++ b/noir/noir-repo/compiler/integration-tests/contracts/1_mul.sol @@ -0,0 +1,2869 @@ +// Verification Key Hash: 81dab81c9312ecc480984185bcdeabfb118f294791980be42c247006c29b27de +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2022 Aztec +pragma solidity >=0.8.4; + +library UltraVerificationKey { + function verificationKeyHash() internal pure returns(bytes32) { + return 0x81dab81c9312ecc480984185bcdeabfb118f294791980be42c247006c29b27de; + } + + function loadVerificationKey(uint256 _vk, uint256 _omegaInverseLoc) internal pure { + assembly { + mstore(add(_vk, 0x00), 0x0000000000000000000000000000000000000000000000000000000000001000) // vk.circuit_size + mstore(add(_vk, 0x20), 0x0000000000000000000000000000000000000000000000000000000000000000) // vk.num_inputs + mstore(add(_vk, 0x40), 0x0931d596de2fd10f01ddd073fd5a90a976f169c76f039bb91c4775720042d43a) // vk.work_root + mstore(add(_vk, 0x60), 0x3061482dfa038d0fb5b4c0b226194047a2616509f531d4fa3acdb77496c10001) // vk.domain_inverse + mstore(add(_vk, 0x80), 0x26dff731489360cd9d88e52bad2198f84d36c1439b77c54f95d6eaf0cef94b8f) // vk.Q1.x + mstore(add(_vk, 0xa0), 0x02acb21f0f38895956e06930708b45106e016ebefc0d24dcdb8c7f959967a90c) // vk.Q1.y + mstore(add(_vk, 0xc0), 0x24ef08dff23f2729f6cd70ed8305655ccec1dfb5e70d8e8a2d4190ce1a1d7e81) // vk.Q2.x + mstore(add(_vk, 0xe0), 0x16ae4c218a37acdb580a2f2c2033d4c93ee06633febe6c96d6bc845b1fbbf7db) // vk.Q2.y + mstore(add(_vk, 0x100), 0x02be54ccdfcf358d15e469f7a7a79d4851996cb90ff7e6ae89734c53b5db89b2) // vk.Q3.x + mstore(add(_vk, 0x120), 0x292fefb96ebc59f41b06421baa766e8949eab20ba1ddbe3cdc0d4a130bdc9dac) // vk.Q3.y + mstore(add(_vk, 0x140), 0x019d7129fa4f0cc04801bd9b9065a25c61b3400244190698a17d73f550c3ad01) // vk.Q4.x + mstore(add(_vk, 0x160), 0x106810b16c402a25c417c5603b70b3ee6b41316be80ba38bb2276f8e9427d8b9) // vk.Q4.y + mstore(add(_vk, 0x180), 0x0efb192384fe64f333475e3c441dcb9d8933a2b4a4179d43b66ee1966199de66) // vk.Q_M.x + mstore(add(_vk, 0x1a0), 0x2a56cfd4a9b725326de5171dd6ec6cba64945cde70652768e4aeecb4a92f193a) // vk.Q_M.y + mstore(add(_vk, 0x1c0), 0x24e321e4d1e65f3c26b32903a432217b5d1c03cf5ac13fa055b5d38216bac3f1) // vk.Q_C.x + mstore(add(_vk, 0x1e0), 0x304c9ace458fbf93f3e9d07fea2b48edc40e9d248862871437a044d557b89085) // vk.Q_C.y + mstore(add(_vk, 0x200), 0x040f659b07806f721e8eeb17773c70a7351a0e59a15027c7f87343d5bd2cac01) // vk.Q_ARITHMETIC.x + mstore(add(_vk, 0x220), 0x215a63918831655a2020158099ebd13bbab94febef4febe815bbca0ac5b0b303) // vk.Q_ARITHMETIC.y + mstore(add(_vk, 0x240), 0x0348ad0a2d9d9a94c78f6c20d7ed0ee0a018bc5a3e51a3453f4256430b0d526c) // vk.QSORT.x + mstore(add(_vk, 0x260), 0x0b711c4268e26d19a11f7560fc53828b7d9e6f920ccb8a0129f8d515c66d99ac) // vk.QSORT.y + mstore(add(_vk, 0x280), 0x13982fd0cf8da5082a77561113bb5ee51e2e82380da3da5ad0f24e49e5f32208) // vk.Q_ELLIPTIC.x + mstore(add(_vk, 0x2a0), 0x1aa5ffd5aa4c16d1c66e18c4574a3ab0b25e9b4e4e04ad1280d1a264237717e0) // vk.Q_ELLIPTIC.y + mstore(add(_vk, 0x2c0), 0x1750f44d3f9dfad78a1e2127ef91051ce018f20536fe45ca28dcc7b248389fc0) // vk.Q_AUX.x + mstore(add(_vk, 0x2e0), 0x1a05418f502a965c39994cd3f83e39164b49c0f27d4f5ac4550751cc0a24bb58) // vk.Q_AUX.y + mstore(add(_vk, 0x300), 0x0e79dad980ecbcba02fa09399f492293608ea5ec55655f381851ab2a7fd9d3e4) // vk.SIGMA1.x + mstore(add(_vk, 0x320), 0x20dcf4e6e84362a1fbb32928b49070375f866ce7334fe5d96572d6a885879066) // vk.SIGMA1.y + mstore(add(_vk, 0x340), 0x04700138101e581226ac624463c28d886eedc87159a518f9c59e117b30dd9fc6) // vk.SIGMA2.x + mstore(add(_vk, 0x360), 0x0766d9586e6192576f6eddb0e2c023f9a574f4d736c9480820431f434b235344) // vk.SIGMA2.y + mstore(add(_vk, 0x380), 0x196fd832eb6b30543b949cd2a124bd2d1504133b34fe6b6346f30cc7a3ed2a75) // vk.SIGMA3.x + mstore(add(_vk, 0x3a0), 0x14bfde5cb996c75c818cdf88d9234ccc0e905f27af5503f42a8f38c2892d6e1c) // vk.SIGMA3.y + mstore(add(_vk, 0x3c0), 0x03c8a1592fca76a3959266b015c120e99a764029d1373ce0a9329d8b441f841a) // vk.SIGMA4.x + mstore(add(_vk, 0x3e0), 0x2239ff07c67a2a59139ef012e667a5fb08293af4abc6dc70e1297e45e744355c) // vk.SIGMA4.y + mstore(add(_vk, 0x400), 0x259f452dc7fd2dda4013dba2196852bcf43c285b1d1f7f85341f3615d25fe97b) // vk.TABLE1.x + mstore(add(_vk, 0x420), 0x117500555dd886209c0b10ee8cd10e711e890a1c99a8f689419da8c52d2e8e9d) // vk.TABLE1.y + mstore(add(_vk, 0x440), 0x2577f542178a07dac262fdabad6f55a84fca32b13b92e520bb91a7455f78ccf1) // vk.TABLE2.x + mstore(add(_vk, 0x460), 0x0fc87ae27122e60eaacc070bd59aafe12644a82ee1345497f8c0302e92925c68) // vk.TABLE2.y + mstore(add(_vk, 0x480), 0x1612f501335a4b72ac55dbe2fd1a75e5fe2c041687603b6577581d673d13be50) // vk.TABLE3.x + mstore(add(_vk, 0x4a0), 0x160e8ef7ff5315cb640ec82e965db270846e904bb7d1c7ff02f32823de6c1c71) // vk.TABLE3.y + mstore(add(_vk, 0x4c0), 0x2d540ff1653b38acbcb9cda315442364007633f529476b2f169a0ff131bfb319) // vk.TABLE4.x + mstore(add(_vk, 0x4e0), 0x2198b9feb61f8160e357b8bb7ca329713898655cc94a0ac2d84944c737cf57e5) // vk.TABLE4.y + mstore(add(_vk, 0x500), 0x11c8df52c3ef754f80d11792cea4b7ad74612e486596cbe7f7d6a05f19c69444) // vk.TABLE_TYPE.x + mstore(add(_vk, 0x520), 0x10c8a36cbb2fd9ed8875b5106a37162ac2932f3bd1b6942b132546d2110a63e2) // vk.TABLE_TYPE.y + mstore(add(_vk, 0x540), 0x122470dc810ee1029ff28334364b1b3dd18193defaf51bb09296275700ee6dd0) // vk.ID1.x + mstore(add(_vk, 0x560), 0x018b2c609f8013a95b1e7c3346e2d3febea6791d393777bfc213831f687070b9) // vk.ID1.y + mstore(add(_vk, 0x580), 0x2fd86e853b82a697cfcd347bad53b66a655813df12ba231808bf65f6561e923c) // vk.ID2.x + mstore(add(_vk, 0x5a0), 0x12b82a7864a782e5afc7f9c85f01ee1b233d94da8bcd1fac485cfdd481db8086) // vk.ID2.y + mstore(add(_vk, 0x5c0), 0x23afba4022c9e1a3eb7ab039a120c48ee661a8e06751225fb989b53f0bfe0b34) // vk.ID3.x + mstore(add(_vk, 0x5e0), 0x04f7c94dc819346aae8a76a89d7d1792c1806ed2e76828e60ee05241952773ec) // vk.ID3.y + mstore(add(_vk, 0x600), 0x282ed40f6896050dc339a08a220ddfb4d33a7c766684e2dde14ca6f452da84b0) // vk.ID4.x + mstore(add(_vk, 0x620), 0x2dadeff4061603c87f4dce0e42c6e145f590062d9bf6e6642f997275bb05b6af) // vk.ID4.y + mstore(add(_vk, 0x640), 0x00) // vk.contains_recursive_proof + mstore(add(_vk, 0x660), 0) // vk.recursive_proof_public_input_indices + mstore(add(_vk, 0x680), 0x260e01b251f6f1c7e7ff4e580791dee8ea51d87a358e038b4efe30fac09383c1) // vk.g2_x.X.c1 + mstore(add(_vk, 0x6a0), 0x0118c4d5b837bcc2bc89b5b398b5974e9f5944073b32078b7e231fec938883b0) // vk.g2_x.X.c0 + mstore(add(_vk, 0x6c0), 0x04fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe4) // vk.g2_x.Y.c1 + mstore(add(_vk, 0x6e0), 0x22febda3c0c0632a56475b4214e5615e11e6dd3f96e6cea2854a87d4dacc5e55) // vk.g2_x.Y.c0 + mstore(_omegaInverseLoc, 0x1af864d211b88d9ccf2e371c2ba088d9269d3fdea04e05acb6f70f8dc79e0e57) // vk.work_root_inverse + } + } +} + +/** + * @title Ultra Plonk proof verification contract + * @dev Top level Plonk proof verification contract, which allows Plonk proof to be verified + */ +abstract contract BaseUltraVerifier { + // VERIFICATION KEY MEMORY LOCATIONS + uint256 internal constant N_LOC = 0x380; + uint256 internal constant NUM_INPUTS_LOC = 0x3a0; + uint256 internal constant OMEGA_LOC = 0x3c0; + uint256 internal constant DOMAIN_INVERSE_LOC = 0x3e0; + uint256 internal constant Q1_X_LOC = 0x400; + uint256 internal constant Q1_Y_LOC = 0x420; + uint256 internal constant Q2_X_LOC = 0x440; + uint256 internal constant Q2_Y_LOC = 0x460; + uint256 internal constant Q3_X_LOC = 0x480; + uint256 internal constant Q3_Y_LOC = 0x4a0; + uint256 internal constant Q4_X_LOC = 0x4c0; + uint256 internal constant Q4_Y_LOC = 0x4e0; + uint256 internal constant QM_X_LOC = 0x500; + uint256 internal constant QM_Y_LOC = 0x520; + uint256 internal constant QC_X_LOC = 0x540; + uint256 internal constant QC_Y_LOC = 0x560; + uint256 internal constant QARITH_X_LOC = 0x580; + uint256 internal constant QARITH_Y_LOC = 0x5a0; + uint256 internal constant QSORT_X_LOC = 0x5c0; + uint256 internal constant QSORT_Y_LOC = 0x5e0; + uint256 internal constant QELLIPTIC_X_LOC = 0x600; + uint256 internal constant QELLIPTIC_Y_LOC = 0x620; + uint256 internal constant QAUX_X_LOC = 0x640; + uint256 internal constant QAUX_Y_LOC = 0x660; + uint256 internal constant SIGMA1_X_LOC = 0x680; + uint256 internal constant SIGMA1_Y_LOC = 0x6a0; + uint256 internal constant SIGMA2_X_LOC = 0x6c0; + uint256 internal constant SIGMA2_Y_LOC = 0x6e0; + uint256 internal constant SIGMA3_X_LOC = 0x700; + uint256 internal constant SIGMA3_Y_LOC = 0x720; + uint256 internal constant SIGMA4_X_LOC = 0x740; + uint256 internal constant SIGMA4_Y_LOC = 0x760; + uint256 internal constant TABLE1_X_LOC = 0x780; + uint256 internal constant TABLE1_Y_LOC = 0x7a0; + uint256 internal constant TABLE2_X_LOC = 0x7c0; + uint256 internal constant TABLE2_Y_LOC = 0x7e0; + uint256 internal constant TABLE3_X_LOC = 0x800; + uint256 internal constant TABLE3_Y_LOC = 0x820; + uint256 internal constant TABLE4_X_LOC = 0x840; + uint256 internal constant TABLE4_Y_LOC = 0x860; + uint256 internal constant TABLE_TYPE_X_LOC = 0x880; + uint256 internal constant TABLE_TYPE_Y_LOC = 0x8a0; + uint256 internal constant ID1_X_LOC = 0x8c0; + uint256 internal constant ID1_Y_LOC = 0x8e0; + uint256 internal constant ID2_X_LOC = 0x900; + uint256 internal constant ID2_Y_LOC = 0x920; + uint256 internal constant ID3_X_LOC = 0x940; + uint256 internal constant ID3_Y_LOC = 0x960; + uint256 internal constant ID4_X_LOC = 0x980; + uint256 internal constant ID4_Y_LOC = 0x9a0; + uint256 internal constant CONTAINS_RECURSIVE_PROOF_LOC = 0x9c0; + uint256 internal constant RECURSIVE_PROOF_PUBLIC_INPUT_INDICES_LOC = 0x9e0; + uint256 internal constant G2X_X0_LOC = 0xa00; + uint256 internal constant G2X_X1_LOC = 0xa20; + uint256 internal constant G2X_Y0_LOC = 0xa40; + uint256 internal constant G2X_Y1_LOC = 0xa60; + + // ### PROOF DATA MEMORY LOCATIONS + uint256 internal constant W1_X_LOC = 0x1200; + uint256 internal constant W1_Y_LOC = 0x1220; + uint256 internal constant W2_X_LOC = 0x1240; + uint256 internal constant W2_Y_LOC = 0x1260; + uint256 internal constant W3_X_LOC = 0x1280; + uint256 internal constant W3_Y_LOC = 0x12a0; + uint256 internal constant W4_X_LOC = 0x12c0; + uint256 internal constant W4_Y_LOC = 0x12e0; + uint256 internal constant S_X_LOC = 0x1300; + uint256 internal constant S_Y_LOC = 0x1320; + uint256 internal constant Z_X_LOC = 0x1340; + uint256 internal constant Z_Y_LOC = 0x1360; + uint256 internal constant Z_LOOKUP_X_LOC = 0x1380; + uint256 internal constant Z_LOOKUP_Y_LOC = 0x13a0; + uint256 internal constant T1_X_LOC = 0x13c0; + uint256 internal constant T1_Y_LOC = 0x13e0; + uint256 internal constant T2_X_LOC = 0x1400; + uint256 internal constant T2_Y_LOC = 0x1420; + uint256 internal constant T3_X_LOC = 0x1440; + uint256 internal constant T3_Y_LOC = 0x1460; + uint256 internal constant T4_X_LOC = 0x1480; + uint256 internal constant T4_Y_LOC = 0x14a0; + + uint256 internal constant W1_EVAL_LOC = 0x1600; + uint256 internal constant W2_EVAL_LOC = 0x1620; + uint256 internal constant W3_EVAL_LOC = 0x1640; + uint256 internal constant W4_EVAL_LOC = 0x1660; + uint256 internal constant S_EVAL_LOC = 0x1680; + uint256 internal constant Z_EVAL_LOC = 0x16a0; + uint256 internal constant Z_LOOKUP_EVAL_LOC = 0x16c0; + uint256 internal constant Q1_EVAL_LOC = 0x16e0; + uint256 internal constant Q2_EVAL_LOC = 0x1700; + uint256 internal constant Q3_EVAL_LOC = 0x1720; + uint256 internal constant Q4_EVAL_LOC = 0x1740; + uint256 internal constant QM_EVAL_LOC = 0x1760; + uint256 internal constant QC_EVAL_LOC = 0x1780; + uint256 internal constant QARITH_EVAL_LOC = 0x17a0; + uint256 internal constant QSORT_EVAL_LOC = 0x17c0; + uint256 internal constant QELLIPTIC_EVAL_LOC = 0x17e0; + uint256 internal constant QAUX_EVAL_LOC = 0x1800; + uint256 internal constant TABLE1_EVAL_LOC = 0x1840; + uint256 internal constant TABLE2_EVAL_LOC = 0x1860; + uint256 internal constant TABLE3_EVAL_LOC = 0x1880; + uint256 internal constant TABLE4_EVAL_LOC = 0x18a0; + uint256 internal constant TABLE_TYPE_EVAL_LOC = 0x18c0; + uint256 internal constant ID1_EVAL_LOC = 0x18e0; + uint256 internal constant ID2_EVAL_LOC = 0x1900; + uint256 internal constant ID3_EVAL_LOC = 0x1920; + uint256 internal constant ID4_EVAL_LOC = 0x1940; + uint256 internal constant SIGMA1_EVAL_LOC = 0x1960; + uint256 internal constant SIGMA2_EVAL_LOC = 0x1980; + uint256 internal constant SIGMA3_EVAL_LOC = 0x19a0; + uint256 internal constant SIGMA4_EVAL_LOC = 0x19c0; + uint256 internal constant W1_OMEGA_EVAL_LOC = 0x19e0; + uint256 internal constant W2_OMEGA_EVAL_LOC = 0x2000; + uint256 internal constant W3_OMEGA_EVAL_LOC = 0x2020; + uint256 internal constant W4_OMEGA_EVAL_LOC = 0x2040; + uint256 internal constant S_OMEGA_EVAL_LOC = 0x2060; + uint256 internal constant Z_OMEGA_EVAL_LOC = 0x2080; + uint256 internal constant Z_LOOKUP_OMEGA_EVAL_LOC = 0x20a0; + uint256 internal constant TABLE1_OMEGA_EVAL_LOC = 0x20c0; + uint256 internal constant TABLE2_OMEGA_EVAL_LOC = 0x20e0; + uint256 internal constant TABLE3_OMEGA_EVAL_LOC = 0x2100; + uint256 internal constant TABLE4_OMEGA_EVAL_LOC = 0x2120; + + uint256 internal constant PI_Z_X_LOC = 0x2300; + uint256 internal constant PI_Z_Y_LOC = 0x2320; + uint256 internal constant PI_Z_OMEGA_X_LOC = 0x2340; + uint256 internal constant PI_Z_OMEGA_Y_LOC = 0x2360; + + // Used for elliptic widget. These are alias names for wire + shifted wire evaluations + uint256 internal constant X1_EVAL_LOC = W2_EVAL_LOC; + uint256 internal constant X2_EVAL_LOC = W1_OMEGA_EVAL_LOC; + uint256 internal constant X3_EVAL_LOC = W2_OMEGA_EVAL_LOC; + uint256 internal constant Y1_EVAL_LOC = W3_EVAL_LOC; + uint256 internal constant Y2_EVAL_LOC = W4_OMEGA_EVAL_LOC; + uint256 internal constant Y3_EVAL_LOC = W3_OMEGA_EVAL_LOC; + uint256 internal constant QBETA_LOC = Q3_EVAL_LOC; + uint256 internal constant QBETA_SQR_LOC = Q4_EVAL_LOC; + uint256 internal constant QSIGN_LOC = Q1_EVAL_LOC; + + // ### CHALLENGES MEMORY OFFSETS + + uint256 internal constant C_BETA_LOC = 0x2600; + uint256 internal constant C_GAMMA_LOC = 0x2620; + uint256 internal constant C_ALPHA_LOC = 0x2640; + uint256 internal constant C_ETA_LOC = 0x2660; + uint256 internal constant C_ETA_SQR_LOC = 0x2680; + uint256 internal constant C_ETA_CUBE_LOC = 0x26a0; + + uint256 internal constant C_ZETA_LOC = 0x26c0; + uint256 internal constant C_CURRENT_LOC = 0x26e0; + uint256 internal constant C_V0_LOC = 0x2700; + uint256 internal constant C_V1_LOC = 0x2720; + uint256 internal constant C_V2_LOC = 0x2740; + uint256 internal constant C_V3_LOC = 0x2760; + uint256 internal constant C_V4_LOC = 0x2780; + uint256 internal constant C_V5_LOC = 0x27a0; + uint256 internal constant C_V6_LOC = 0x27c0; + uint256 internal constant C_V7_LOC = 0x27e0; + uint256 internal constant C_V8_LOC = 0x2800; + uint256 internal constant C_V9_LOC = 0x2820; + uint256 internal constant C_V10_LOC = 0x2840; + uint256 internal constant C_V11_LOC = 0x2860; + uint256 internal constant C_V12_LOC = 0x2880; + uint256 internal constant C_V13_LOC = 0x28a0; + uint256 internal constant C_V14_LOC = 0x28c0; + uint256 internal constant C_V15_LOC = 0x28e0; + uint256 internal constant C_V16_LOC = 0x2900; + uint256 internal constant C_V17_LOC = 0x2920; + uint256 internal constant C_V18_LOC = 0x2940; + uint256 internal constant C_V19_LOC = 0x2960; + uint256 internal constant C_V20_LOC = 0x2980; + uint256 internal constant C_V21_LOC = 0x29a0; + uint256 internal constant C_V22_LOC = 0x29c0; + uint256 internal constant C_V23_LOC = 0x29e0; + uint256 internal constant C_V24_LOC = 0x2a00; + uint256 internal constant C_V25_LOC = 0x2a20; + uint256 internal constant C_V26_LOC = 0x2a40; + uint256 internal constant C_V27_LOC = 0x2a60; + uint256 internal constant C_V28_LOC = 0x2a80; + uint256 internal constant C_V29_LOC = 0x2aa0; + uint256 internal constant C_V30_LOC = 0x2ac0; + + uint256 internal constant C_U_LOC = 0x2b00; + + // ### LOCAL VARIABLES MEMORY OFFSETS + uint256 internal constant DELTA_NUMERATOR_LOC = 0x3000; + uint256 internal constant DELTA_DENOMINATOR_LOC = 0x3020; + uint256 internal constant ZETA_POW_N_LOC = 0x3040; + uint256 internal constant PUBLIC_INPUT_DELTA_LOC = 0x3060; + uint256 internal constant ZERO_POLY_LOC = 0x3080; + uint256 internal constant L_START_LOC = 0x30a0; + uint256 internal constant L_END_LOC = 0x30c0; + uint256 internal constant R_ZERO_EVAL_LOC = 0x30e0; + + uint256 internal constant PLOOKUP_DELTA_NUMERATOR_LOC = 0x3100; + uint256 internal constant PLOOKUP_DELTA_DENOMINATOR_LOC = 0x3120; + uint256 internal constant PLOOKUP_DELTA_LOC = 0x3140; + + uint256 internal constant ACCUMULATOR_X_LOC = 0x3160; + uint256 internal constant ACCUMULATOR_Y_LOC = 0x3180; + uint256 internal constant ACCUMULATOR2_X_LOC = 0x31a0; + uint256 internal constant ACCUMULATOR2_Y_LOC = 0x31c0; + uint256 internal constant PAIRING_LHS_X_LOC = 0x31e0; + uint256 internal constant PAIRING_LHS_Y_LOC = 0x3200; + uint256 internal constant PAIRING_RHS_X_LOC = 0x3220; + uint256 internal constant PAIRING_RHS_Y_LOC = 0x3240; + + // misc stuff + uint256 internal constant OMEGA_INVERSE_LOC = 0x3300; + uint256 internal constant C_ALPHA_SQR_LOC = 0x3320; + uint256 internal constant C_ALPHA_CUBE_LOC = 0x3340; + uint256 internal constant C_ALPHA_QUAD_LOC = 0x3360; + uint256 internal constant C_ALPHA_BASE_LOC = 0x3380; + + // ### RECURSION VARIABLE MEMORY LOCATIONS + uint256 internal constant RECURSIVE_P1_X_LOC = 0x3400; + uint256 internal constant RECURSIVE_P1_Y_LOC = 0x3420; + uint256 internal constant RECURSIVE_P2_X_LOC = 0x3440; + uint256 internal constant RECURSIVE_P2_Y_LOC = 0x3460; + uint256 internal constant PUBLIC_INPUTS_HASH_LOCATION = 0x3480; + + // sub-identity storage + uint256 internal constant PERMUTATION_IDENTITY = 0x3500; + uint256 internal constant PLOOKUP_IDENTITY = 0x3520; + uint256 internal constant ARITHMETIC_IDENTITY = 0x3540; + uint256 internal constant SORT_IDENTITY = 0x3560; + uint256 internal constant ELLIPTIC_IDENTITY = 0x3580; + uint256 internal constant AUX_IDENTITY = 0x35a0; + uint256 internal constant AUX_NON_NATIVE_FIELD_EVALUATION = 0x35c0; + uint256 internal constant AUX_LIMB_ACCUMULATOR_EVALUATION = 0x35e0; + uint256 internal constant AUX_RAM_CONSISTENCY_EVALUATION = 0x3600; + uint256 internal constant AUX_ROM_CONSISTENCY_EVALUATION = 0x3620; + uint256 internal constant AUX_MEMORY_EVALUATION = 0x3640; + + uint256 internal constant QUOTIENT_EVAL_LOC = 0x3660; + uint256 internal constant ZERO_POLY_INVERSE_LOC = 0x3680; + + // when hashing public inputs we use memory at NU_CHALLENGE_INPUT_LOC_A, as the hash input size is unknown at compile time + uint256 internal constant NU_CHALLENGE_INPUT_LOC_A = 0x36a0; + uint256 internal constant NU_CHALLENGE_INPUT_LOC_B = 0x36c0; + uint256 internal constant NU_CHALLENGE_INPUT_LOC_C = 0x36e0; + + bytes4 internal constant INVALID_VERIFICATION_KEY_SELECTOR = 0x7e5769bf; + bytes4 internal constant POINT_NOT_ON_CURVE_SELECTOR = 0xa3dad654; + bytes4 internal constant PUBLIC_INPUT_INVALID_BN128_G1_POINT_SELECTOR = 0xeba9f4a6; + bytes4 internal constant PUBLIC_INPUT_GE_P_SELECTOR = 0x374a972f; + bytes4 internal constant MOD_EXP_FAILURE_SELECTOR = 0xf894a7bc; + bytes4 internal constant PAIRING_PREAMBLE_FAILED_SELECTOR = 0x01882d81; + bytes4 internal constant OPENING_COMMITMENT_FAILED_SELECTOR = 0x4e719763; + bytes4 internal constant PAIRING_FAILED_SELECTOR = 0xd71fd263; + + uint256 internal constant ETA_INPUT_LENGTH = 0xc0; // W1, W2, W3 = 6 * 0x20 bytes + + // We need to hash 41 field elements when generating the NU challenge + // w1, w2, w3, w4, s, z, z_lookup, q1, q2, q3, q4, qm, qc, qarith (14) + // qsort, qelliptic, qaux, sigma1, sigma2, sigma, sigma4, (7) + // table1, table2, table3, table4, tabletype, id1, id2, id3, id4, (9) + // w1_omega, w2_omega, w3_omega, w4_omega, s_omega, z_omega, z_lookup_omega, (7) + // table1_omega, table2_omega, table3_omega, table4_omega (4) + uint256 internal constant NU_INPUT_LENGTH = 0x520; // 0x520 = 41 * 0x20 + + // There are ELEVEN G1 group elements added into the transcript in the `beta` round, that we need to skip over + // W1, W2, W3, W4, S, Z, Z_LOOKUP, T1, T2, T3, T4 + uint256 internal constant NU_CALLDATA_SKIP_LENGTH = 0x2c0; // 11 * 0x40 = 0x2c0 + + uint256 internal constant NEGATIVE_INVERSE_OF_2_MODULO_P = + 0x183227397098d014dc2822db40c0ac2e9419f4243cdcb848a1f0fac9f8000000; + uint256 internal constant LIMB_SIZE = 0x100000000000000000; // 2<<68 + uint256 internal constant SUBLIMB_SHIFT = 0x4000; // 2<<14 + + // y^2 = x^3 + ax + b + // for Grumpkin, a = 0 and b = -17. We use b in a custom gate relation that evaluates elliptic curve arithmetic + uint256 internal constant GRUMPKIN_CURVE_B_PARAMETER_NEGATED = 17; + + error INVALID_VERIFICATION_KEY(); + error POINT_NOT_ON_CURVE(); + error PUBLIC_INPUT_COUNT_INVALID(uint256 expected, uint256 actual); + error PUBLIC_INPUT_INVALID_BN128_G1_POINT(); + error PUBLIC_INPUT_GE_P(); + error MOD_EXP_FAILURE(); + error PAIRING_PREAMBLE_FAILED(); + error OPENING_COMMITMENT_FAILED(); + error PAIRING_FAILED(); + + function getVerificationKeyHash() public pure virtual returns (bytes32); + + /** + * @dev We assume that the verification key loaded by this function is constant as we only verify it on deployment + */ + function loadVerificationKey(uint256 _vk, uint256 _omegaInverseLoc) internal pure virtual; + + constructor() { + loadVerificationKey(N_LOC, OMEGA_INVERSE_LOC); + + // We verify that all of the EC points in the verification key lie on the bn128 curve. + assembly { + let q := 21888242871839275222246405745257275088696311157297823662689037894645226208583 // EC group order + + let success := 1 + + // VALIDATE Q1 + { + let x := mload(Q1_X_LOC) + let y := mload(Q1_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE Q2 + { + let x := mload(Q2_X_LOC) + let y := mload(Q2_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE Q3 + { + let x := mload(Q3_X_LOC) + let y := mload(Q3_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE Q4 + { + let x := mload(Q4_X_LOC) + let y := mload(Q4_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + mstore(0x00, x) + mstore(0x20, y) + } + // VALIDATE QM + { + let x := mload(QM_X_LOC) + let y := mload(QM_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE QC + { + let x := mload(QC_X_LOC) + let y := mload(QC_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE QARITH + { + let x := mload(QARITH_X_LOC) + let y := mload(QARITH_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE QSORT + { + let x := mload(QSORT_X_LOC) + let y := mload(QSORT_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE QELLIPTIC + { + let x := mload(QELLIPTIC_X_LOC) + let y := mload(QELLIPTIC_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE QAUX + { + let x := mload(QAUX_X_LOC) + let y := mload(QAUX_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE SIGMA1 + { + let x := mload(SIGMA1_X_LOC) + let y := mload(SIGMA1_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE SIGMA2 + { + let x := mload(SIGMA2_X_LOC) + let y := mload(SIGMA2_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE SIGMA3 + { + let x := mload(SIGMA3_X_LOC) + let y := mload(SIGMA3_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE SIGMA4 + { + let x := mload(SIGMA4_X_LOC) + let y := mload(SIGMA4_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE TABLE1 + { + let x := mload(TABLE1_X_LOC) + let y := mload(TABLE1_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE TABLE2 + { + let x := mload(TABLE2_X_LOC) + let y := mload(TABLE2_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE TABLE3 + { + let x := mload(TABLE3_X_LOC) + let y := mload(TABLE3_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE TABLE4 + { + let x := mload(TABLE4_X_LOC) + let y := mload(TABLE4_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE TABLE_TYPE + { + let x := mload(TABLE_TYPE_X_LOC) + let y := mload(TABLE_TYPE_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE ID1 + { + let x := mload(ID1_X_LOC) + let y := mload(ID1_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE ID2 + { + let x := mload(ID2_X_LOC) + let y := mload(ID2_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE ID3 + { + let x := mload(ID3_X_LOC) + let y := mload(ID3_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE ID4 + { + let x := mload(ID4_X_LOC) + let y := mload(ID4_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + + if iszero(success) { + mstore(0x0, INVALID_VERIFICATION_KEY_SELECTOR) + revert(0x00, 0x04) + } + } + } + + /** + * @notice Verify a Ultra Plonk proof + * @param _proof - The serialized proof + * @param _publicInputs - An array of the public inputs + * @return True if proof is valid, reverts otherwise + */ + function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool) { + loadVerificationKey(N_LOC, OMEGA_INVERSE_LOC); + + uint256 requiredPublicInputCount; + assembly { + requiredPublicInputCount := mload(NUM_INPUTS_LOC) + } + if (requiredPublicInputCount != _publicInputs.length) { + revert PUBLIC_INPUT_COUNT_INVALID(requiredPublicInputCount, _publicInputs.length); + } + + assembly { + let q := 21888242871839275222246405745257275088696311157297823662689037894645226208583 // EC group order + let p := 21888242871839275222246405745257275088548364400416034343698204186575808495617 // Prime field order + + /** + * LOAD PROOF FROM CALLDATA + */ + { + let data_ptr := add(calldataload(0x04), 0x24) + + mstore(W1_Y_LOC, mod(calldataload(data_ptr), q)) + mstore(W1_X_LOC, mod(calldataload(add(data_ptr, 0x20)), q)) + + mstore(W2_Y_LOC, mod(calldataload(add(data_ptr, 0x40)), q)) + mstore(W2_X_LOC, mod(calldataload(add(data_ptr, 0x60)), q)) + + mstore(W3_Y_LOC, mod(calldataload(add(data_ptr, 0x80)), q)) + mstore(W3_X_LOC, mod(calldataload(add(data_ptr, 0xa0)), q)) + + mstore(W4_Y_LOC, mod(calldataload(add(data_ptr, 0xc0)), q)) + mstore(W4_X_LOC, mod(calldataload(add(data_ptr, 0xe0)), q)) + + mstore(S_Y_LOC, mod(calldataload(add(data_ptr, 0x100)), q)) + mstore(S_X_LOC, mod(calldataload(add(data_ptr, 0x120)), q)) + mstore(Z_Y_LOC, mod(calldataload(add(data_ptr, 0x140)), q)) + mstore(Z_X_LOC, mod(calldataload(add(data_ptr, 0x160)), q)) + mstore(Z_LOOKUP_Y_LOC, mod(calldataload(add(data_ptr, 0x180)), q)) + mstore(Z_LOOKUP_X_LOC, mod(calldataload(add(data_ptr, 0x1a0)), q)) + mstore(T1_Y_LOC, mod(calldataload(add(data_ptr, 0x1c0)), q)) + mstore(T1_X_LOC, mod(calldataload(add(data_ptr, 0x1e0)), q)) + + mstore(T2_Y_LOC, mod(calldataload(add(data_ptr, 0x200)), q)) + mstore(T2_X_LOC, mod(calldataload(add(data_ptr, 0x220)), q)) + + mstore(T3_Y_LOC, mod(calldataload(add(data_ptr, 0x240)), q)) + mstore(T3_X_LOC, mod(calldataload(add(data_ptr, 0x260)), q)) + + mstore(T4_Y_LOC, mod(calldataload(add(data_ptr, 0x280)), q)) + mstore(T4_X_LOC, mod(calldataload(add(data_ptr, 0x2a0)), q)) + + mstore(W1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x2c0)), p)) + mstore(W2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x2e0)), p)) + mstore(W3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x300)), p)) + mstore(W4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x320)), p)) + mstore(S_EVAL_LOC, mod(calldataload(add(data_ptr, 0x340)), p)) + mstore(Z_EVAL_LOC, mod(calldataload(add(data_ptr, 0x360)), p)) + mstore(Z_LOOKUP_EVAL_LOC, mod(calldataload(add(data_ptr, 0x380)), p)) + mstore(Q1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x3a0)), p)) + mstore(Q2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x3c0)), p)) + mstore(Q3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x3e0)), p)) + mstore(Q4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x400)), p)) + mstore(QM_EVAL_LOC, mod(calldataload(add(data_ptr, 0x420)), p)) + mstore(QC_EVAL_LOC, mod(calldataload(add(data_ptr, 0x440)), p)) + mstore(QARITH_EVAL_LOC, mod(calldataload(add(data_ptr, 0x460)), p)) + mstore(QSORT_EVAL_LOC, mod(calldataload(add(data_ptr, 0x480)), p)) + mstore(QELLIPTIC_EVAL_LOC, mod(calldataload(add(data_ptr, 0x4a0)), p)) + mstore(QAUX_EVAL_LOC, mod(calldataload(add(data_ptr, 0x4c0)), p)) + + mstore(SIGMA1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x4e0)), p)) + mstore(SIGMA2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x500)), p)) + + mstore(SIGMA3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x520)), p)) + mstore(SIGMA4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x540)), p)) + + mstore(TABLE1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x560)), p)) + mstore(TABLE2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x580)), p)) + mstore(TABLE3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x5a0)), p)) + mstore(TABLE4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x5c0)), p)) + mstore(TABLE_TYPE_EVAL_LOC, mod(calldataload(add(data_ptr, 0x5e0)), p)) + + mstore(ID1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x600)), p)) + mstore(ID2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x620)), p)) + mstore(ID3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x640)), p)) + mstore(ID4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x660)), p)) + + mstore(W1_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x680)), p)) + mstore(W2_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x6a0)), p)) + mstore(W3_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x6c0)), p)) + mstore(W4_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x6e0)), p)) + mstore(S_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x700)), p)) + + mstore(Z_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x720)), p)) + + mstore(Z_LOOKUP_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x740)), p)) + mstore(TABLE1_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x760)), p)) + mstore(TABLE2_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x780)), p)) + mstore(TABLE3_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x7a0)), p)) + mstore(TABLE4_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x7c0)), p)) + + mstore(PI_Z_Y_LOC, mod(calldataload(add(data_ptr, 0x7e0)), q)) + mstore(PI_Z_X_LOC, mod(calldataload(add(data_ptr, 0x800)), q)) + + mstore(PI_Z_OMEGA_Y_LOC, mod(calldataload(add(data_ptr, 0x820)), q)) + mstore(PI_Z_OMEGA_X_LOC, mod(calldataload(add(data_ptr, 0x840)), q)) + } + + /** + * LOAD RECURSIVE PROOF INTO MEMORY + */ + { + if mload(CONTAINS_RECURSIVE_PROOF_LOC) { + let public_inputs_ptr := add(calldataload(0x24), 0x24) + let index_counter := add(shl(5, mload(RECURSIVE_PROOF_PUBLIC_INPUT_INDICES_LOC)), public_inputs_ptr) + + let x0 := calldataload(index_counter) + x0 := add(x0, shl(68, calldataload(add(index_counter, 0x20)))) + x0 := add(x0, shl(136, calldataload(add(index_counter, 0x40)))) + x0 := add(x0, shl(204, calldataload(add(index_counter, 0x60)))) + let y0 := calldataload(add(index_counter, 0x80)) + y0 := add(y0, shl(68, calldataload(add(index_counter, 0xa0)))) + y0 := add(y0, shl(136, calldataload(add(index_counter, 0xc0)))) + y0 := add(y0, shl(204, calldataload(add(index_counter, 0xe0)))) + let x1 := calldataload(add(index_counter, 0x100)) + x1 := add(x1, shl(68, calldataload(add(index_counter, 0x120)))) + x1 := add(x1, shl(136, calldataload(add(index_counter, 0x140)))) + x1 := add(x1, shl(204, calldataload(add(index_counter, 0x160)))) + let y1 := calldataload(add(index_counter, 0x180)) + y1 := add(y1, shl(68, calldataload(add(index_counter, 0x1a0)))) + y1 := add(y1, shl(136, calldataload(add(index_counter, 0x1c0)))) + y1 := add(y1, shl(204, calldataload(add(index_counter, 0x1e0)))) + mstore(RECURSIVE_P1_X_LOC, x0) + mstore(RECURSIVE_P1_Y_LOC, y0) + mstore(RECURSIVE_P2_X_LOC, x1) + mstore(RECURSIVE_P2_Y_LOC, y1) + + // validate these are valid bn128 G1 points + if iszero(and(and(lt(x0, q), lt(x1, q)), and(lt(y0, q), lt(y1, q)))) { + mstore(0x00, PUBLIC_INPUT_INVALID_BN128_G1_POINT_SELECTOR) + revert(0x00, 0x04) + } + } + } + + { + /** + * Generate initial challenge + */ + mstore(0x00, shl(224, mload(N_LOC))) + mstore(0x04, shl(224, mload(NUM_INPUTS_LOC))) + let challenge := keccak256(0x00, 0x08) + + /** + * Generate eta challenge + */ + mstore(PUBLIC_INPUTS_HASH_LOCATION, challenge) + // The public input location is stored at 0x24, we then add 0x24 to skip selector and the length of public inputs + let public_inputs_start := add(calldataload(0x24), 0x24) + // copy the public inputs over + let public_input_size := mul(mload(NUM_INPUTS_LOC), 0x20) + calldatacopy(add(PUBLIC_INPUTS_HASH_LOCATION, 0x20), public_inputs_start, public_input_size) + + // copy W1, W2, W3 into challenge. Each point is 0x40 bytes, so load 0xc0 = 3 * 0x40 bytes (ETA input length) + let w_start := add(calldataload(0x04), 0x24) + calldatacopy(add(add(PUBLIC_INPUTS_HASH_LOCATION, 0x20), public_input_size), w_start, ETA_INPUT_LENGTH) + + // Challenge is the old challenge + public inputs + W1, W2, W3 (0x20 + public_input_size + 0xc0) + let challenge_bytes_size := add(0x20, add(public_input_size, ETA_INPUT_LENGTH)) + + challenge := keccak256(PUBLIC_INPUTS_HASH_LOCATION, challenge_bytes_size) + { + let eta := mod(challenge, p) + mstore(C_ETA_LOC, eta) + mstore(C_ETA_SQR_LOC, mulmod(eta, eta, p)) + mstore(C_ETA_CUBE_LOC, mulmod(mload(C_ETA_SQR_LOC), eta, p)) + } + + /** + * Generate beta challenge + */ + mstore(0x00, challenge) + mstore(0x20, mload(W4_Y_LOC)) + mstore(0x40, mload(W4_X_LOC)) + mstore(0x60, mload(S_Y_LOC)) + mstore(0x80, mload(S_X_LOC)) + challenge := keccak256(0x00, 0xa0) + mstore(C_BETA_LOC, mod(challenge, p)) + + /** + * Generate gamma challenge + */ + mstore(0x00, challenge) + mstore8(0x20, 0x01) + challenge := keccak256(0x00, 0x21) + mstore(C_GAMMA_LOC, mod(challenge, p)) + + /** + * Generate alpha challenge + */ + mstore(0x00, challenge) + mstore(0x20, mload(Z_Y_LOC)) + mstore(0x40, mload(Z_X_LOC)) + mstore(0x60, mload(Z_LOOKUP_Y_LOC)) + mstore(0x80, mload(Z_LOOKUP_X_LOC)) + challenge := keccak256(0x00, 0xa0) + mstore(C_ALPHA_LOC, mod(challenge, p)) + + /** + * Compute and store some powers of alpha for future computations + */ + let alpha := mload(C_ALPHA_LOC) + mstore(C_ALPHA_SQR_LOC, mulmod(alpha, alpha, p)) + mstore(C_ALPHA_CUBE_LOC, mulmod(mload(C_ALPHA_SQR_LOC), alpha, p)) + mstore(C_ALPHA_QUAD_LOC, mulmod(mload(C_ALPHA_CUBE_LOC), alpha, p)) + mstore(C_ALPHA_BASE_LOC, alpha) + + /** + * Generate zeta challenge + */ + mstore(0x00, challenge) + mstore(0x20, mload(T1_Y_LOC)) + mstore(0x40, mload(T1_X_LOC)) + mstore(0x60, mload(T2_Y_LOC)) + mstore(0x80, mload(T2_X_LOC)) + mstore(0xa0, mload(T3_Y_LOC)) + mstore(0xc0, mload(T3_X_LOC)) + mstore(0xe0, mload(T4_Y_LOC)) + mstore(0x100, mload(T4_X_LOC)) + + challenge := keccak256(0x00, 0x120) + + mstore(C_ZETA_LOC, mod(challenge, p)) + mstore(C_CURRENT_LOC, challenge) + } + + /** + * EVALUATE FIELD OPERATIONS + */ + + /** + * COMPUTE PUBLIC INPUT DELTA + * ΔPI = ∏ᵢ∈ℓ(wᵢ + β σ(i) + γ) / ∏ᵢ∈ℓ(wᵢ + β σ'(i) + γ) + */ + { + let beta := mload(C_BETA_LOC) // β + let gamma := mload(C_GAMMA_LOC) // γ + let work_root := mload(OMEGA_LOC) // ω + let numerator_value := 1 + let denominator_value := 1 + + let p_clone := p // move p to the front of the stack + let valid_inputs := true + + // Load the starting point of the public inputs (jump over the selector and the length of public inputs [0x24]) + let public_inputs_ptr := add(calldataload(0x24), 0x24) + + // endpoint_ptr = public_inputs_ptr + num_inputs * 0x20. // every public input is 0x20 bytes + let endpoint_ptr := add(public_inputs_ptr, mul(mload(NUM_INPUTS_LOC), 0x20)) + + // root_1 = β * 0x05 + let root_1 := mulmod(beta, 0x05, p_clone) // k1.β + // root_2 = β * 0x0c + let root_2 := mulmod(beta, 0x0c, p_clone) + // @note 0x05 + 0x07 == 0x0c == external coset generator + + for {} lt(public_inputs_ptr, endpoint_ptr) { public_inputs_ptr := add(public_inputs_ptr, 0x20) } { + /** + * input = public_input[i] + * valid_inputs &= input < p + * temp = input + gamma + * numerator_value *= (β.σ(i) + wᵢ + γ) // σ(i) = 0x05.ωⁱ + * denominator_value *= (β.σ'(i) + wᵢ + γ) // σ'(i) = 0x0c.ωⁱ + * root_1 *= ω + * root_2 *= ω + */ + + let input := calldataload(public_inputs_ptr) + valid_inputs := and(valid_inputs, lt(input, p_clone)) + let temp := addmod(input, gamma, p_clone) + + numerator_value := mulmod(numerator_value, add(root_1, temp), p_clone) + denominator_value := mulmod(denominator_value, add(root_2, temp), p_clone) + + root_1 := mulmod(root_1, work_root, p_clone) + root_2 := mulmod(root_2, work_root, p_clone) + } + + // Revert if not all public inputs are field elements (i.e. < p) + if iszero(valid_inputs) { + mstore(0x00, PUBLIC_INPUT_GE_P_SELECTOR) + revert(0x00, 0x04) + } + + mstore(DELTA_NUMERATOR_LOC, numerator_value) + mstore(DELTA_DENOMINATOR_LOC, denominator_value) + } + + /** + * Compute Plookup delta factor [γ(1 + β)]^{n-k} + * k = num roots cut out of Z_H = 4 + */ + { + let delta_base := mulmod(mload(C_GAMMA_LOC), addmod(mload(C_BETA_LOC), 1, p), p) + let delta_numerator := delta_base + { + let exponent := mload(N_LOC) + let count := 1 + for {} lt(count, exponent) { count := add(count, count) } { + delta_numerator := mulmod(delta_numerator, delta_numerator, p) + } + } + mstore(PLOOKUP_DELTA_NUMERATOR_LOC, delta_numerator) + + let delta_denominator := mulmod(delta_base, delta_base, p) + delta_denominator := mulmod(delta_denominator, delta_denominator, p) + mstore(PLOOKUP_DELTA_DENOMINATOR_LOC, delta_denominator) + } + /** + * Compute lagrange poly and vanishing poly fractions + */ + { + /** + * vanishing_numerator = zeta + * ZETA_POW_N = zeta^n + * vanishing_numerator -= 1 + * accumulating_root = omega_inverse + * work_root = p - accumulating_root + * domain_inverse = domain_inverse + * vanishing_denominator = zeta + work_root + * work_root *= accumulating_root + * vanishing_denominator *= (zeta + work_root) + * work_root *= accumulating_root + * vanishing_denominator *= (zeta + work_root) + * vanishing_denominator *= (zeta + (zeta + accumulating_root)) + * work_root = omega + * lagrange_numerator = vanishing_numerator * domain_inverse + * l_start_denominator = zeta - 1 + * accumulating_root = work_root^2 + * l_end_denominator = accumulating_root^2 * work_root * zeta - 1 + * Note: l_end_denominator term contains a term \omega^5 to cut out 5 roots of unity from vanishing poly + */ + + let zeta := mload(C_ZETA_LOC) + + // compute zeta^n, where n is a power of 2 + let vanishing_numerator := zeta + { + // pow_small + let exponent := mload(N_LOC) + let count := 1 + for {} lt(count, exponent) { count := add(count, count) } { + vanishing_numerator := mulmod(vanishing_numerator, vanishing_numerator, p) + } + } + mstore(ZETA_POW_N_LOC, vanishing_numerator) + vanishing_numerator := addmod(vanishing_numerator, sub(p, 1), p) + + let accumulating_root := mload(OMEGA_INVERSE_LOC) + let work_root := sub(p, accumulating_root) + let domain_inverse := mload(DOMAIN_INVERSE_LOC) + + let vanishing_denominator := addmod(zeta, work_root, p) + work_root := mulmod(work_root, accumulating_root, p) + vanishing_denominator := mulmod(vanishing_denominator, addmod(zeta, work_root, p), p) + work_root := mulmod(work_root, accumulating_root, p) + vanishing_denominator := mulmod(vanishing_denominator, addmod(zeta, work_root, p), p) + vanishing_denominator := + mulmod(vanishing_denominator, addmod(zeta, mulmod(work_root, accumulating_root, p), p), p) + + work_root := mload(OMEGA_LOC) + + let lagrange_numerator := mulmod(vanishing_numerator, domain_inverse, p) + let l_start_denominator := addmod(zeta, sub(p, 1), p) + + accumulating_root := mulmod(work_root, work_root, p) + + let l_end_denominator := + addmod( + mulmod(mulmod(mulmod(accumulating_root, accumulating_root, p), work_root, p), zeta, p), sub(p, 1), p + ) + + /** + * Compute inversions using Montgomery's batch inversion trick + */ + let accumulator := mload(DELTA_DENOMINATOR_LOC) + let t0 := accumulator + accumulator := mulmod(accumulator, vanishing_denominator, p) + let t1 := accumulator + accumulator := mulmod(accumulator, vanishing_numerator, p) + let t2 := accumulator + accumulator := mulmod(accumulator, l_start_denominator, p) + let t3 := accumulator + accumulator := mulmod(accumulator, mload(PLOOKUP_DELTA_DENOMINATOR_LOC), p) + let t4 := accumulator + { + mstore(0, 0x20) + mstore(0x20, 0x20) + mstore(0x40, 0x20) + mstore(0x60, mulmod(accumulator, l_end_denominator, p)) + mstore(0x80, sub(p, 2)) + mstore(0xa0, p) + if iszero(staticcall(gas(), 0x05, 0x00, 0xc0, 0x00, 0x20)) { + mstore(0x0, MOD_EXP_FAILURE_SELECTOR) + revert(0x00, 0x04) + } + accumulator := mload(0x00) + } + + t4 := mulmod(accumulator, t4, p) + accumulator := mulmod(accumulator, l_end_denominator, p) + + t3 := mulmod(accumulator, t3, p) + accumulator := mulmod(accumulator, mload(PLOOKUP_DELTA_DENOMINATOR_LOC), p) + + t2 := mulmod(accumulator, t2, p) + accumulator := mulmod(accumulator, l_start_denominator, p) + + t1 := mulmod(accumulator, t1, p) + accumulator := mulmod(accumulator, vanishing_numerator, p) + + t0 := mulmod(accumulator, t0, p) + accumulator := mulmod(accumulator, vanishing_denominator, p) + + accumulator := mulmod(mulmod(accumulator, accumulator, p), mload(DELTA_DENOMINATOR_LOC), p) + + mstore(PUBLIC_INPUT_DELTA_LOC, mulmod(mload(DELTA_NUMERATOR_LOC), accumulator, p)) + mstore(ZERO_POLY_LOC, mulmod(vanishing_numerator, t0, p)) + mstore(ZERO_POLY_INVERSE_LOC, mulmod(vanishing_denominator, t1, p)) + mstore(L_START_LOC, mulmod(lagrange_numerator, t2, p)) + mstore(PLOOKUP_DELTA_LOC, mulmod(mload(PLOOKUP_DELTA_NUMERATOR_LOC), t3, p)) + mstore(L_END_LOC, mulmod(lagrange_numerator, t4, p)) + } + + /** + * UltraPlonk Widget Ordering: + * + * 1. Permutation widget + * 2. Plookup widget + * 3. Arithmetic widget + * 4. Fixed base widget (?) + * 5. GenPermSort widget + * 6. Elliptic widget + * 7. Auxiliary widget + */ + + /** + * COMPUTE PERMUTATION WIDGET EVALUATION + */ + { + let alpha := mload(C_ALPHA_LOC) + let beta := mload(C_BETA_LOC) + let gamma := mload(C_GAMMA_LOC) + + /** + * t1 = (W1 + gamma + beta * ID1) * (W2 + gamma + beta * ID2) + * t2 = (W3 + gamma + beta * ID3) * (W4 + gamma + beta * ID4) + * result = alpha_base * z_eval * t1 * t2 + * t1 = (W1 + gamma + beta * sigma_1_eval) * (W2 + gamma + beta * sigma_2_eval) + * t2 = (W2 + gamma + beta * sigma_3_eval) * (W3 + gamma + beta * sigma_4_eval) + * result -= (alpha_base * z_omega_eval * t1 * t2) + */ + let t1 := + mulmod( + add(add(mload(W1_EVAL_LOC), gamma), mulmod(beta, mload(ID1_EVAL_LOC), p)), + add(add(mload(W2_EVAL_LOC), gamma), mulmod(beta, mload(ID2_EVAL_LOC), p)), + p + ) + let t2 := + mulmod( + add(add(mload(W3_EVAL_LOC), gamma), mulmod(beta, mload(ID3_EVAL_LOC), p)), + add(add(mload(W4_EVAL_LOC), gamma), mulmod(beta, mload(ID4_EVAL_LOC), p)), + p + ) + let result := mulmod(mload(C_ALPHA_BASE_LOC), mulmod(mload(Z_EVAL_LOC), mulmod(t1, t2, p), p), p) + t1 := + mulmod( + add(add(mload(W1_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA1_EVAL_LOC), p)), + add(add(mload(W2_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA2_EVAL_LOC), p)), + p + ) + t2 := + mulmod( + add(add(mload(W3_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA3_EVAL_LOC), p)), + add(add(mload(W4_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA4_EVAL_LOC), p)), + p + ) + result := + addmod( + result, + sub(p, mulmod(mload(C_ALPHA_BASE_LOC), mulmod(mload(Z_OMEGA_EVAL_LOC), mulmod(t1, t2, p), p), p)), + p + ) + + /** + * alpha_base *= alpha + * result += alpha_base . (L_{n-k}(ʓ) . (z(ʓ.ω) - ∆_{PI})) + * alpha_base *= alpha + * result += alpha_base . (L_1(ʓ)(Z(ʓ) - 1)) + * alpha_Base *= alpha + */ + mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p)) + result := + addmod( + result, + mulmod( + mload(C_ALPHA_BASE_LOC), + mulmod( + mload(L_END_LOC), + addmod(mload(Z_OMEGA_EVAL_LOC), sub(p, mload(PUBLIC_INPUT_DELTA_LOC)), p), + p + ), + p + ), + p + ) + mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p)) + mstore( + PERMUTATION_IDENTITY, + addmod( + result, + mulmod( + mload(C_ALPHA_BASE_LOC), + mulmod(mload(L_START_LOC), addmod(mload(Z_EVAL_LOC), sub(p, 1), p), p), + p + ), + p + ) + ) + mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p)) + } + + /** + * COMPUTE PLOOKUP WIDGET EVALUATION + */ + { + /** + * Goal: f = (w1(z) + q2.w1(zω)) + η(w2(z) + qm.w2(zω)) + η²(w3(z) + qc.w_3(zω)) + q3(z).η³ + * f = η.q3(z) + * f += (w3(z) + qc.w_3(zω)) + * f *= η + * f += (w2(z) + qm.w2(zω)) + * f *= η + * f += (w1(z) + q2.w1(zω)) + */ + let f := mulmod(mload(C_ETA_LOC), mload(Q3_EVAL_LOC), p) + f := + addmod(f, addmod(mload(W3_EVAL_LOC), mulmod(mload(QC_EVAL_LOC), mload(W3_OMEGA_EVAL_LOC), p), p), p) + f := mulmod(f, mload(C_ETA_LOC), p) + f := + addmod(f, addmod(mload(W2_EVAL_LOC), mulmod(mload(QM_EVAL_LOC), mload(W2_OMEGA_EVAL_LOC), p), p), p) + f := mulmod(f, mload(C_ETA_LOC), p) + f := + addmod(f, addmod(mload(W1_EVAL_LOC), mulmod(mload(Q2_EVAL_LOC), mload(W1_OMEGA_EVAL_LOC), p), p), p) + + // t(z) = table4(z).η³ + table3(z).η² + table2(z).η + table1(z) + let t := + addmod( + addmod( + addmod( + mulmod(mload(TABLE4_EVAL_LOC), mload(C_ETA_CUBE_LOC), p), + mulmod(mload(TABLE3_EVAL_LOC), mload(C_ETA_SQR_LOC), p), + p + ), + mulmod(mload(TABLE2_EVAL_LOC), mload(C_ETA_LOC), p), + p + ), + mload(TABLE1_EVAL_LOC), + p + ) + + // t(zw) = table4(zw).η³ + table3(zw).η² + table2(zw).η + table1(zw) + let t_omega := + addmod( + addmod( + addmod( + mulmod(mload(TABLE4_OMEGA_EVAL_LOC), mload(C_ETA_CUBE_LOC), p), + mulmod(mload(TABLE3_OMEGA_EVAL_LOC), mload(C_ETA_SQR_LOC), p), + p + ), + mulmod(mload(TABLE2_OMEGA_EVAL_LOC), mload(C_ETA_LOC), p), + p + ), + mload(TABLE1_OMEGA_EVAL_LOC), + p + ) + + /** + * Goal: numerator = (TABLE_TYPE_EVAL * f(z) + γ) * (t(z) + βt(zω) + γ(β + 1)) * (β + 1) + * gamma_beta_constant = γ(β + 1) + * numerator = f * TABLE_TYPE_EVAL + gamma + * temp0 = t(z) + t(zω) * β + gamma_beta_constant + * numerator *= temp0 + * numerator *= (β + 1) + * temp0 = alpha * l_1 + * numerator += temp0 + * numerator *= z_lookup(z) + * numerator -= temp0 + */ + let gamma_beta_constant := mulmod(mload(C_GAMMA_LOC), addmod(mload(C_BETA_LOC), 1, p), p) + let numerator := addmod(mulmod(f, mload(TABLE_TYPE_EVAL_LOC), p), mload(C_GAMMA_LOC), p) + let temp0 := addmod(addmod(t, mulmod(t_omega, mload(C_BETA_LOC), p), p), gamma_beta_constant, p) + numerator := mulmod(numerator, temp0, p) + numerator := mulmod(numerator, addmod(mload(C_BETA_LOC), 1, p), p) + temp0 := mulmod(mload(C_ALPHA_LOC), mload(L_START_LOC), p) + numerator := addmod(numerator, temp0, p) + numerator := mulmod(numerator, mload(Z_LOOKUP_EVAL_LOC), p) + numerator := addmod(numerator, sub(p, temp0), p) + + /** + * Goal: denominator = z_lookup(zω)*[s(z) + βs(zω) + γ(1 + β)] - [z_lookup(zω) - [γ(1 + β)]^{n-k}]*α²L_end(z) + * note: delta_factor = [γ(1 + β)]^{n-k} + * denominator = s(z) + βs(zω) + γ(β + 1) + * temp1 = α²L_end(z) + * denominator -= temp1 + * denominator *= z_lookup(zω) + * denominator += temp1 * delta_factor + * PLOOKUP_IDENTITY = (numerator - denominator).alpha_base + * alpha_base *= alpha^3 + */ + let denominator := + addmod( + addmod(mload(S_EVAL_LOC), mulmod(mload(S_OMEGA_EVAL_LOC), mload(C_BETA_LOC), p), p), + gamma_beta_constant, + p + ) + let temp1 := mulmod(mload(C_ALPHA_SQR_LOC), mload(L_END_LOC), p) + denominator := addmod(denominator, sub(p, temp1), p) + denominator := mulmod(denominator, mload(Z_LOOKUP_OMEGA_EVAL_LOC), p) + denominator := addmod(denominator, mulmod(temp1, mload(PLOOKUP_DELTA_LOC), p), p) + + mstore(PLOOKUP_IDENTITY, mulmod(addmod(numerator, sub(p, denominator), p), mload(C_ALPHA_BASE_LOC), p)) + + // update alpha + mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_CUBE_LOC), p)) + } + + /** + * COMPUTE ARITHMETIC WIDGET EVALUATION + */ + { + /** + * The basic arithmetic gate identity in standard plonk is as follows. + * (w_1 . w_2 . q_m) + (w_1 . q_1) + (w_2 . q_2) + (w_3 . q_3) + (w_4 . q_4) + q_c = 0 + * However, for Ultraplonk, we extend this to support "passing" wires between rows (shown without alpha scaling below): + * q_arith * ( ( (-1/2) * (q_arith - 3) * q_m * w_1 * w_2 + q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c ) + + * (q_arith - 1)*( α * (q_arith - 2) * (w_1 + w_4 - w_1_omega + q_m) + w_4_omega) ) = 0 + * + * This formula results in several cases depending on q_arith: + * 1. q_arith == 0: Arithmetic gate is completely disabled + * + * 2. q_arith == 1: Everything in the minigate on the right is disabled. The equation is just a standard plonk equation + * with extra wires: q_m * w_1 * w_2 + q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c = 0 + * + * 3. q_arith == 2: The (w_1 + w_4 - ...) term is disabled. THe equation is: + * (1/2) * q_m * w_1 * w_2 + q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c + w_4_omega = 0 + * It allows defining w_4 at next index (w_4_omega) in terms of current wire values + * + * 4. q_arith == 3: The product of w_1 and w_2 is disabled, but a mini addition gate is enabled. α allows us to split + * the equation into two: + * + * q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c + 2 * w_4_omega = 0 + * and + * w_1 + w_4 - w_1_omega + q_m = 0 (we are reusing q_m here) + * + * 5. q_arith > 3: The product of w_1 and w_2 is scaled by (q_arith - 3), while the w_4_omega term is scaled by (q_arith - 1). + * The equation can be split into two: + * + * (q_arith - 3)* q_m * w_1 * w_ 2 + q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c + (q_arith - 1) * w_4_omega = 0 + * and + * w_1 + w_4 - w_1_omega + q_m = 0 + * + * The problem that q_m is used both in both equations can be dealt with by appropriately changing selector values at + * the next gate. Then we can treat (q_arith - 1) as a simulated q_6 selector and scale q_m to handle (q_arith - 3) at + * product. + */ + + let w1q1 := mulmod(mload(W1_EVAL_LOC), mload(Q1_EVAL_LOC), p) + let w2q2 := mulmod(mload(W2_EVAL_LOC), mload(Q2_EVAL_LOC), p) + let w3q3 := mulmod(mload(W3_EVAL_LOC), mload(Q3_EVAL_LOC), p) + let w4q3 := mulmod(mload(W4_EVAL_LOC), mload(Q4_EVAL_LOC), p) + + // @todo - Add a explicit test that hits QARITH == 3 + // w1w2qm := (w_1 . w_2 . q_m . (QARITH_EVAL_LOC - 3)) / 2 + let w1w2qm := + mulmod( + mulmod( + mulmod(mulmod(mload(W1_EVAL_LOC), mload(W2_EVAL_LOC), p), mload(QM_EVAL_LOC), p), + addmod(mload(QARITH_EVAL_LOC), sub(p, 3), p), + p + ), + NEGATIVE_INVERSE_OF_2_MODULO_P, + p + ) + + // (w_1 . w_2 . q_m . (q_arith - 3)) / -2) + (w_1 . q_1) + (w_2 . q_2) + (w_3 . q_3) + (w_4 . q_4) + q_c + let identity := + addmod( + mload(QC_EVAL_LOC), addmod(w4q3, addmod(w3q3, addmod(w2q2, addmod(w1q1, w1w2qm, p), p), p), p), p + ) + + // if q_arith == 3 we evaluate an additional mini addition gate (on top of the regular one), where: + // w_1 + w_4 - w_1_omega + q_m = 0 + // we use this gate to save an addition gate when adding or subtracting non-native field elements + // α * (q_arith - 2) * (w_1 + w_4 - w_1_omega + q_m) + let extra_small_addition_gate_identity := + mulmod( + mload(C_ALPHA_LOC), + mulmod( + addmod(mload(QARITH_EVAL_LOC), sub(p, 2), p), + addmod( + mload(QM_EVAL_LOC), + addmod( + sub(p, mload(W1_OMEGA_EVAL_LOC)), addmod(mload(W1_EVAL_LOC), mload(W4_EVAL_LOC), p), p + ), + p + ), + p + ), + p + ) + + // if q_arith == 2 OR q_arith == 3 we add the 4th wire of the NEXT gate into the arithmetic identity + // N.B. if q_arith > 2, this wire value will be scaled by (q_arith - 1) relative to the other gate wires! + // alpha_base * q_arith * (identity + (q_arith - 1) * (w_4_omega + extra_small_addition_gate_identity)) + mstore( + ARITHMETIC_IDENTITY, + mulmod( + mload(C_ALPHA_BASE_LOC), + mulmod( + mload(QARITH_EVAL_LOC), + addmod( + identity, + mulmod( + addmod(mload(QARITH_EVAL_LOC), sub(p, 1), p), + addmod(mload(W4_OMEGA_EVAL_LOC), extra_small_addition_gate_identity, p), + p + ), + p + ), + p + ), + p + ) + ) + + // update alpha + mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_SQR_LOC), p)) + } + + /** + * COMPUTE GENPERMSORT WIDGET EVALUATION + */ + { + /** + * D1 = (w2 - w1) + * D2 = (w3 - w2) + * D3 = (w4 - w3) + * D4 = (w1_omega - w4) + * + * α_a = alpha_base + * α_b = alpha_base * α + * α_c = alpha_base * α^2 + * α_d = alpha_base * α^3 + * + * range_accumulator = ( + * D1(D1 - 1)(D1 - 2)(D1 - 3).α_a + + * D2(D2 - 1)(D2 - 2)(D2 - 3).α_b + + * D3(D3 - 1)(D3 - 2)(D3 - 3).α_c + + * D4(D4 - 1)(D4 - 2)(D4 - 3).α_d + + * ) . q_sort + */ + let minus_two := sub(p, 2) + let minus_three := sub(p, 3) + let d1 := addmod(mload(W2_EVAL_LOC), sub(p, mload(W1_EVAL_LOC)), p) + let d2 := addmod(mload(W3_EVAL_LOC), sub(p, mload(W2_EVAL_LOC)), p) + let d3 := addmod(mload(W4_EVAL_LOC), sub(p, mload(W3_EVAL_LOC)), p) + let d4 := addmod(mload(W1_OMEGA_EVAL_LOC), sub(p, mload(W4_EVAL_LOC)), p) + + let range_accumulator := + mulmod( + mulmod( + mulmod(addmod(mulmod(d1, d1, p), sub(p, d1), p), addmod(d1, minus_two, p), p), + addmod(d1, minus_three, p), + p + ), + mload(C_ALPHA_BASE_LOC), + p + ) + range_accumulator := + addmod( + range_accumulator, + mulmod( + mulmod( + mulmod(addmod(mulmod(d2, d2, p), sub(p, d2), p), addmod(d2, minus_two, p), p), + addmod(d2, minus_three, p), + p + ), + mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p), + p + ), + p + ) + range_accumulator := + addmod( + range_accumulator, + mulmod( + mulmod( + mulmod(addmod(mulmod(d3, d3, p), sub(p, d3), p), addmod(d3, minus_two, p), p), + addmod(d3, minus_three, p), + p + ), + mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_SQR_LOC), p), + p + ), + p + ) + range_accumulator := + addmod( + range_accumulator, + mulmod( + mulmod( + mulmod(addmod(mulmod(d4, d4, p), sub(p, d4), p), addmod(d4, minus_two, p), p), + addmod(d4, minus_three, p), + p + ), + mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_CUBE_LOC), p), + p + ), + p + ) + range_accumulator := mulmod(range_accumulator, mload(QSORT_EVAL_LOC), p) + + mstore(SORT_IDENTITY, range_accumulator) + + // update alpha + mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_QUAD_LOC), p)) + } + + /** + * COMPUTE ELLIPTIC WIDGET EVALUATION + */ + { + /** + * endo_term = (-x_2) * x_1 * (x_3 * 2 + x_1) * q_beta + * endo_sqr_term = x_2^2 + * endo_sqr_term *= (x_3 - x_1) + * endo_sqr_term *= q_beta^2 + * leftovers = x_2^2 + * leftovers *= x_2 + * leftovers += x_1^2 * (x_3 + x_1) @follow-up Invalid comment in BB widget + * leftovers -= (y_2^2 + y_1^2) + * sign_term = y_2 * y_1 + * sign_term += sign_term + * sign_term *= q_sign + */ + // q_elliptic * (x3 + x2 + x1)(x2 - x1)(x2 - x1) - y2^2 - y1^2 + 2(y2y1)*q_sign = 0 + let x_diff := addmod(mload(X2_EVAL_LOC), sub(p, mload(X1_EVAL_LOC)), p) + let y2_sqr := mulmod(mload(Y2_EVAL_LOC), mload(Y2_EVAL_LOC), p) + let y1_sqr := mulmod(mload(Y1_EVAL_LOC), mload(Y1_EVAL_LOC), p) + let y1y2 := mulmod(mulmod(mload(Y1_EVAL_LOC), mload(Y2_EVAL_LOC), p), mload(QSIGN_LOC), p) + + let x_add_identity := + addmod( + mulmod( + addmod(mload(X3_EVAL_LOC), addmod(mload(X2_EVAL_LOC), mload(X1_EVAL_LOC), p), p), + mulmod(x_diff, x_diff, p), + p + ), + addmod( + sub( + p, + addmod(y2_sqr, y1_sqr, p) + ), + addmod(y1y2, y1y2, p), + p + ), + p + ) + x_add_identity := + mulmod( + mulmod( + x_add_identity, + addmod( + 1, + sub(p, mload(QM_EVAL_LOC)), + p + ), + p + ), + mload(C_ALPHA_BASE_LOC), + p + ) + + // q_elliptic * (x3 + x2 + x1)(x2 - x1)(x2 - x1) - y2^2 - y1^2 + 2(y2y1)*q_sign = 0 + let y1_plus_y3 := addmod( + mload(Y1_EVAL_LOC), + mload(Y3_EVAL_LOC), + p + ) + let y_diff := addmod(mulmod(mload(Y2_EVAL_LOC), mload(QSIGN_LOC), p), sub(p, mload(Y1_EVAL_LOC)), p) + let y_add_identity := + addmod( + mulmod(y1_plus_y3, x_diff, p), + mulmod(addmod(mload(X3_EVAL_LOC), sub(p, mload(X1_EVAL_LOC)), p), y_diff, p), + p + ) + y_add_identity := + mulmod( + mulmod(y_add_identity, addmod(1, sub(p, mload(QM_EVAL_LOC)), p), p), + mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p), + p + ) + + // ELLIPTIC_IDENTITY = (x_identity + y_identity) * Q_ELLIPTIC_EVAL + mstore( + ELLIPTIC_IDENTITY, mulmod(addmod(x_add_identity, y_add_identity, p), mload(QELLIPTIC_EVAL_LOC), p) + ) + } + { + /** + * x_pow_4 = (y_1_sqr - curve_b) * x_1; + * y_1_sqr_mul_4 = y_1_sqr + y_1_sqr; + * y_1_sqr_mul_4 += y_1_sqr_mul_4; + * x_1_pow_4_mul_9 = x_pow_4; + * x_1_pow_4_mul_9 += x_1_pow_4_mul_9; + * x_1_pow_4_mul_9 += x_1_pow_4_mul_9; + * x_1_pow_4_mul_9 += x_1_pow_4_mul_9; + * x_1_pow_4_mul_9 += x_pow_4; + * x_1_sqr_mul_3 = x_1_sqr + x_1_sqr + x_1_sqr; + * x_double_identity = (x_3 + x_1 + x_1) * y_1_sqr_mul_4 - x_1_pow_4_mul_9; + * y_double_identity = x_1_sqr_mul_3 * (x_1 - x_3) - (y_1 + y_1) * (y_1 + y_3); + */ + // (x3 + x1 + x1) (4y1*y1) - 9 * x1 * x1 * x1 * x1 = 0 + let x1_sqr := mulmod(mload(X1_EVAL_LOC), mload(X1_EVAL_LOC), p) + let y1_sqr := mulmod(mload(Y1_EVAL_LOC), mload(Y1_EVAL_LOC), p) + let x_pow_4 := mulmod(addmod(y1_sqr, GRUMPKIN_CURVE_B_PARAMETER_NEGATED, p), mload(X1_EVAL_LOC), p) + let y1_sqr_mul_4 := mulmod(y1_sqr, 4, p) + let x1_pow_4_mul_9 := mulmod(x_pow_4, 9, p) + let x1_sqr_mul_3 := mulmod(x1_sqr, 3, p) + let x_double_identity := + addmod( + mulmod( + addmod(mload(X3_EVAL_LOC), addmod(mload(X1_EVAL_LOC), mload(X1_EVAL_LOC), p), p), + y1_sqr_mul_4, + p + ), + sub(p, x1_pow_4_mul_9), + p + ) + // (y1 + y1) (2y1) - (3 * x1 * x1)(x1 - x3) = 0 + let y_double_identity := + addmod( + mulmod(x1_sqr_mul_3, addmod(mload(X1_EVAL_LOC), sub(p, mload(X3_EVAL_LOC)), p), p), + sub( + p, + mulmod( + addmod(mload(Y1_EVAL_LOC), mload(Y1_EVAL_LOC), p), + addmod(mload(Y1_EVAL_LOC), mload(Y3_EVAL_LOC), p), + p + ) + ), + p + ) + x_double_identity := mulmod(x_double_identity, mload(C_ALPHA_BASE_LOC), p) + y_double_identity := + mulmod(y_double_identity, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p), p) + x_double_identity := mulmod(x_double_identity, mload(QM_EVAL_LOC), p) + y_double_identity := mulmod(y_double_identity, mload(QM_EVAL_LOC), p) + // ELLIPTIC_IDENTITY += (x_double_identity + y_double_identity) * Q_DOUBLE_EVAL + mstore( + ELLIPTIC_IDENTITY, + addmod( + mload(ELLIPTIC_IDENTITY), + mulmod(addmod(x_double_identity, y_double_identity, p), mload(QELLIPTIC_EVAL_LOC), p), + p + ) + ) + + // update alpha + mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_QUAD_LOC), p)) + } + + /** + * COMPUTE AUXILIARY WIDGET EVALUATION + */ + { + { + /** + * Non native field arithmetic gate 2 + * _ _ + * / _ _ _ 14 \ + * q_2 . q_4 | (w_1 . w_2) + (w_1 . w_2) + (w_1 . w_4 + w_2 . w_3 - w_3) . 2 - w_3 - w_4 | + * \_ _/ + * + * limb_subproduct = w_1 . w_2_omega + w_1_omega . w_2 + * non_native_field_gate_2 = w_1 * w_4 + w_4 * w_3 - w_3_omega + * non_native_field_gate_2 = non_native_field_gate_2 * limb_size + * non_native_field_gate_2 -= w_4_omega + * non_native_field_gate_2 += limb_subproduct + * non_native_field_gate_2 *= q_4 + * limb_subproduct *= limb_size + * limb_subproduct += w_1_omega * w_2_omega + * non_native_field_gate_1 = (limb_subproduct + w_3 + w_4) * q_3 + * non_native_field_gate_3 = (limb_subproduct + w_4 - (w_3_omega + w_4_omega)) * q_m + * non_native_field_identity = (non_native_field_gate_1 + non_native_field_gate_2 + non_native_field_gate_3) * q_2 + */ + + let limb_subproduct := + addmod( + mulmod(mload(W1_EVAL_LOC), mload(W2_OMEGA_EVAL_LOC), p), + mulmod(mload(W1_OMEGA_EVAL_LOC), mload(W2_EVAL_LOC), p), + p + ) + + let non_native_field_gate_2 := + addmod( + addmod( + mulmod(mload(W1_EVAL_LOC), mload(W4_EVAL_LOC), p), + mulmod(mload(W2_EVAL_LOC), mload(W3_EVAL_LOC), p), + p + ), + sub(p, mload(W3_OMEGA_EVAL_LOC)), + p + ) + non_native_field_gate_2 := mulmod(non_native_field_gate_2, LIMB_SIZE, p) + non_native_field_gate_2 := addmod(non_native_field_gate_2, sub(p, mload(W4_OMEGA_EVAL_LOC)), p) + non_native_field_gate_2 := addmod(non_native_field_gate_2, limb_subproduct, p) + non_native_field_gate_2 := mulmod(non_native_field_gate_2, mload(Q4_EVAL_LOC), p) + limb_subproduct := mulmod(limb_subproduct, LIMB_SIZE, p) + limb_subproduct := + addmod(limb_subproduct, mulmod(mload(W1_OMEGA_EVAL_LOC), mload(W2_OMEGA_EVAL_LOC), p), p) + let non_native_field_gate_1 := + mulmod( + addmod(limb_subproduct, sub(p, addmod(mload(W3_EVAL_LOC), mload(W4_EVAL_LOC), p)), p), + mload(Q3_EVAL_LOC), + p + ) + let non_native_field_gate_3 := + mulmod( + addmod( + addmod(limb_subproduct, mload(W4_EVAL_LOC), p), + sub(p, addmod(mload(W3_OMEGA_EVAL_LOC), mload(W4_OMEGA_EVAL_LOC), p)), + p + ), + mload(QM_EVAL_LOC), + p + ) + let non_native_field_identity := + mulmod( + addmod(addmod(non_native_field_gate_1, non_native_field_gate_2, p), non_native_field_gate_3, p), + mload(Q2_EVAL_LOC), + p + ) + + mstore(AUX_NON_NATIVE_FIELD_EVALUATION, non_native_field_identity) + } + + { + /** + * limb_accumulator_1 = w_2_omega; + * limb_accumulator_1 *= SUBLIMB_SHIFT; + * limb_accumulator_1 += w_1_omega; + * limb_accumulator_1 *= SUBLIMB_SHIFT; + * limb_accumulator_1 += w_3; + * limb_accumulator_1 *= SUBLIMB_SHIFT; + * limb_accumulator_1 += w_2; + * limb_accumulator_1 *= SUBLIMB_SHIFT; + * limb_accumulator_1 += w_1; + * limb_accumulator_1 -= w_4; + * limb_accumulator_1 *= q_4; + */ + let limb_accumulator_1 := mulmod(mload(W2_OMEGA_EVAL_LOC), SUBLIMB_SHIFT, p) + limb_accumulator_1 := addmod(limb_accumulator_1, mload(W1_OMEGA_EVAL_LOC), p) + limb_accumulator_1 := mulmod(limb_accumulator_1, SUBLIMB_SHIFT, p) + limb_accumulator_1 := addmod(limb_accumulator_1, mload(W3_EVAL_LOC), p) + limb_accumulator_1 := mulmod(limb_accumulator_1, SUBLIMB_SHIFT, p) + limb_accumulator_1 := addmod(limb_accumulator_1, mload(W2_EVAL_LOC), p) + limb_accumulator_1 := mulmod(limb_accumulator_1, SUBLIMB_SHIFT, p) + limb_accumulator_1 := addmod(limb_accumulator_1, mload(W1_EVAL_LOC), p) + limb_accumulator_1 := addmod(limb_accumulator_1, sub(p, mload(W4_EVAL_LOC)), p) + limb_accumulator_1 := mulmod(limb_accumulator_1, mload(Q4_EVAL_LOC), p) + + /** + * limb_accumulator_2 = w_3_omega; + * limb_accumulator_2 *= SUBLIMB_SHIFT; + * limb_accumulator_2 += w_2_omega; + * limb_accumulator_2 *= SUBLIMB_SHIFT; + * limb_accumulator_2 += w_1_omega; + * limb_accumulator_2 *= SUBLIMB_SHIFT; + * limb_accumulator_2 += w_4; + * limb_accumulator_2 *= SUBLIMB_SHIFT; + * limb_accumulator_2 += w_3; + * limb_accumulator_2 -= w_4_omega; + * limb_accumulator_2 *= q_m; + */ + let limb_accumulator_2 := mulmod(mload(W3_OMEGA_EVAL_LOC), SUBLIMB_SHIFT, p) + limb_accumulator_2 := addmod(limb_accumulator_2, mload(W2_OMEGA_EVAL_LOC), p) + limb_accumulator_2 := mulmod(limb_accumulator_2, SUBLIMB_SHIFT, p) + limb_accumulator_2 := addmod(limb_accumulator_2, mload(W1_OMEGA_EVAL_LOC), p) + limb_accumulator_2 := mulmod(limb_accumulator_2, SUBLIMB_SHIFT, p) + limb_accumulator_2 := addmod(limb_accumulator_2, mload(W4_EVAL_LOC), p) + limb_accumulator_2 := mulmod(limb_accumulator_2, SUBLIMB_SHIFT, p) + limb_accumulator_2 := addmod(limb_accumulator_2, mload(W3_EVAL_LOC), p) + limb_accumulator_2 := addmod(limb_accumulator_2, sub(p, mload(W4_OMEGA_EVAL_LOC)), p) + limb_accumulator_2 := mulmod(limb_accumulator_2, mload(QM_EVAL_LOC), p) + + mstore( + AUX_LIMB_ACCUMULATOR_EVALUATION, + mulmod(addmod(limb_accumulator_1, limb_accumulator_2, p), mload(Q3_EVAL_LOC), p) + ) + } + + { + /** + * memory_record_check = w_3; + * memory_record_check *= eta; + * memory_record_check += w_2; + * memory_record_check *= eta; + * memory_record_check += w_1; + * memory_record_check *= eta; + * memory_record_check += q_c; + * + * partial_record_check = memory_record_check; + * + * memory_record_check -= w_4; + */ + + let memory_record_check := mulmod(mload(W3_EVAL_LOC), mload(C_ETA_LOC), p) + memory_record_check := addmod(memory_record_check, mload(W2_EVAL_LOC), p) + memory_record_check := mulmod(memory_record_check, mload(C_ETA_LOC), p) + memory_record_check := addmod(memory_record_check, mload(W1_EVAL_LOC), p) + memory_record_check := mulmod(memory_record_check, mload(C_ETA_LOC), p) + memory_record_check := addmod(memory_record_check, mload(QC_EVAL_LOC), p) + + let partial_record_check := memory_record_check + memory_record_check := addmod(memory_record_check, sub(p, mload(W4_EVAL_LOC)), p) + + mstore(AUX_MEMORY_EVALUATION, memory_record_check) + + // index_delta = w_1_omega - w_1 + let index_delta := addmod(mload(W1_OMEGA_EVAL_LOC), sub(p, mload(W1_EVAL_LOC)), p) + // record_delta = w_4_omega - w_4 + let record_delta := addmod(mload(W4_OMEGA_EVAL_LOC), sub(p, mload(W4_EVAL_LOC)), p) + // index_is_monotonically_increasing = index_delta * (index_delta - 1) + let index_is_monotonically_increasing := mulmod(index_delta, addmod(index_delta, sub(p, 1), p), p) + + // adjacent_values_match_if_adjacent_indices_match = record_delta * (1 - index_delta) + let adjacent_values_match_if_adjacent_indices_match := + mulmod(record_delta, addmod(1, sub(p, index_delta), p), p) + + // AUX_ROM_CONSISTENCY_EVALUATION = ((adjacent_values_match_if_adjacent_indices_match * alpha) + index_is_monotonically_increasing) * alpha + partial_record_check + mstore( + AUX_ROM_CONSISTENCY_EVALUATION, + addmod( + mulmod( + addmod( + mulmod(adjacent_values_match_if_adjacent_indices_match, mload(C_ALPHA_LOC), p), + index_is_monotonically_increasing, + p + ), + mload(C_ALPHA_LOC), + p + ), + memory_record_check, + p + ) + ) + + { + /** + * next_gate_access_type = w_3_omega; + * next_gate_access_type *= eta; + * next_gate_access_type += w_2_omega; + * next_gate_access_type *= eta; + * next_gate_access_type += w_1_omega; + * next_gate_access_type *= eta; + * next_gate_access_type = w_4_omega - next_gate_access_type; + */ + let next_gate_access_type := mulmod(mload(W3_OMEGA_EVAL_LOC), mload(C_ETA_LOC), p) + next_gate_access_type := addmod(next_gate_access_type, mload(W2_OMEGA_EVAL_LOC), p) + next_gate_access_type := mulmod(next_gate_access_type, mload(C_ETA_LOC), p) + next_gate_access_type := addmod(next_gate_access_type, mload(W1_OMEGA_EVAL_LOC), p) + next_gate_access_type := mulmod(next_gate_access_type, mload(C_ETA_LOC), p) + next_gate_access_type := addmod(mload(W4_OMEGA_EVAL_LOC), sub(p, next_gate_access_type), p) + + // value_delta = w_3_omega - w_3 + let value_delta := addmod(mload(W3_OMEGA_EVAL_LOC), sub(p, mload(W3_EVAL_LOC)), p) + // adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation = (1 - index_delta) * value_delta * (1 - next_gate_access_type); + + let adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation := + mulmod( + addmod(1, sub(p, index_delta), p), + mulmod(value_delta, addmod(1, sub(p, next_gate_access_type), p), p), + p + ) + + // AUX_RAM_CONSISTENCY_EVALUATION + + /** + * access_type = w_4 - partial_record_check + * access_check = access_type^2 - access_type + * next_gate_access_type_is_boolean = next_gate_access_type^2 - next_gate_access_type + * RAM_consistency_check_identity = adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation; + * RAM_consistency_check_identity *= alpha; + * RAM_consistency_check_identity += index_is_monotonically_increasing; + * RAM_consistency_check_identity *= alpha; + * RAM_consistency_check_identity += next_gate_access_type_is_boolean; + * RAM_consistency_check_identity *= alpha; + * RAM_consistency_check_identity += access_check; + */ + + let access_type := addmod(mload(W4_EVAL_LOC), sub(p, partial_record_check), p) + let access_check := mulmod(access_type, addmod(access_type, sub(p, 1), p), p) + let next_gate_access_type_is_boolean := + mulmod(next_gate_access_type, addmod(next_gate_access_type, sub(p, 1), p), p) + let RAM_cci := + mulmod( + adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation, + mload(C_ALPHA_LOC), + p + ) + RAM_cci := addmod(RAM_cci, index_is_monotonically_increasing, p) + RAM_cci := mulmod(RAM_cci, mload(C_ALPHA_LOC), p) + RAM_cci := addmod(RAM_cci, next_gate_access_type_is_boolean, p) + RAM_cci := mulmod(RAM_cci, mload(C_ALPHA_LOC), p) + RAM_cci := addmod(RAM_cci, access_check, p) + + mstore(AUX_RAM_CONSISTENCY_EVALUATION, RAM_cci) + } + + { + // timestamp_delta = w_2_omega - w_2 + let timestamp_delta := addmod(mload(W2_OMEGA_EVAL_LOC), sub(p, mload(W2_EVAL_LOC)), p) + + // RAM_timestamp_check_identity = (1 - index_delta) * timestamp_delta - w_3 + let RAM_timestamp_check_identity := + addmod( + mulmod(timestamp_delta, addmod(1, sub(p, index_delta), p), p), sub(p, mload(W3_EVAL_LOC)), p + ) + + /** + * memory_identity = ROM_consistency_check_identity * q_2; + * memory_identity += RAM_timestamp_check_identity * q_4; + * memory_identity += memory_record_check * q_m; + * memory_identity *= q_1; + * memory_identity += (RAM_consistency_check_identity * q_arith); + * + * auxiliary_identity = memory_identity + non_native_field_identity + limb_accumulator_identity; + * auxiliary_identity *= q_aux; + * auxiliary_identity *= alpha_base; + */ + let memory_identity := mulmod(mload(AUX_ROM_CONSISTENCY_EVALUATION), mload(Q2_EVAL_LOC), p) + memory_identity := + addmod(memory_identity, mulmod(RAM_timestamp_check_identity, mload(Q4_EVAL_LOC), p), p) + memory_identity := + addmod(memory_identity, mulmod(mload(AUX_MEMORY_EVALUATION), mload(QM_EVAL_LOC), p), p) + memory_identity := mulmod(memory_identity, mload(Q1_EVAL_LOC), p) + memory_identity := + addmod( + memory_identity, mulmod(mload(AUX_RAM_CONSISTENCY_EVALUATION), mload(QARITH_EVAL_LOC), p), p + ) + + let auxiliary_identity := addmod(memory_identity, mload(AUX_NON_NATIVE_FIELD_EVALUATION), p) + auxiliary_identity := addmod(auxiliary_identity, mload(AUX_LIMB_ACCUMULATOR_EVALUATION), p) + auxiliary_identity := mulmod(auxiliary_identity, mload(QAUX_EVAL_LOC), p) + auxiliary_identity := mulmod(auxiliary_identity, mload(C_ALPHA_BASE_LOC), p) + + mstore(AUX_IDENTITY, auxiliary_identity) + + // update alpha + mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_CUBE_LOC), p)) + } + } + } + + { + /** + * quotient = ARITHMETIC_IDENTITY + * quotient += PERMUTATION_IDENTITY + * quotient += PLOOKUP_IDENTITY + * quotient += SORT_IDENTITY + * quotient += ELLIPTIC_IDENTITY + * quotient += AUX_IDENTITY + * quotient *= ZERO_POLY_INVERSE + */ + mstore( + QUOTIENT_EVAL_LOC, + mulmod( + addmod( + addmod( + addmod( + addmod( + addmod(mload(PERMUTATION_IDENTITY), mload(PLOOKUP_IDENTITY), p), + mload(ARITHMETIC_IDENTITY), + p + ), + mload(SORT_IDENTITY), + p + ), + mload(ELLIPTIC_IDENTITY), + p + ), + mload(AUX_IDENTITY), + p + ), + mload(ZERO_POLY_INVERSE_LOC), + p + ) + ) + } + + /** + * GENERATE NU AND SEPARATOR CHALLENGES + */ + { + let current_challenge := mload(C_CURRENT_LOC) + // get a calldata pointer that points to the start of the data we want to copy + let calldata_ptr := add(calldataload(0x04), 0x24) + + calldata_ptr := add(calldata_ptr, NU_CALLDATA_SKIP_LENGTH) + + mstore(NU_CHALLENGE_INPUT_LOC_A, current_challenge) + mstore(NU_CHALLENGE_INPUT_LOC_B, mload(QUOTIENT_EVAL_LOC)) + calldatacopy(NU_CHALLENGE_INPUT_LOC_C, calldata_ptr, NU_INPUT_LENGTH) + + // hash length = (0x20 + num field elements), we include the previous challenge in the hash + let challenge := keccak256(NU_CHALLENGE_INPUT_LOC_A, add(NU_INPUT_LENGTH, 0x40)) + + mstore(C_V0_LOC, mod(challenge, p)) + // We need THIRTY-ONE independent nu challenges! + mstore(0x00, challenge) + mstore8(0x20, 0x01) + mstore(C_V1_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x02) + mstore(C_V2_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x03) + mstore(C_V3_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x04) + mstore(C_V4_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x05) + mstore(C_V5_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x06) + mstore(C_V6_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x07) + mstore(C_V7_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x08) + mstore(C_V8_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x09) + mstore(C_V9_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x0a) + mstore(C_V10_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x0b) + mstore(C_V11_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x0c) + mstore(C_V12_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x0d) + mstore(C_V13_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x0e) + mstore(C_V14_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x0f) + mstore(C_V15_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x10) + mstore(C_V16_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x11) + mstore(C_V17_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x12) + mstore(C_V18_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x13) + mstore(C_V19_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x14) + mstore(C_V20_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x15) + mstore(C_V21_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x16) + mstore(C_V22_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x17) + mstore(C_V23_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x18) + mstore(C_V24_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x19) + mstore(C_V25_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x1a) + mstore(C_V26_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x1b) + mstore(C_V27_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x1c) + mstore(C_V28_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x1d) + mstore(C_V29_LOC, mod(keccak256(0x00, 0x21), p)) + + // @follow-up - Why are both v29 and v30 using appending 0x1d to the prior challenge and hashing, should it not change? + mstore8(0x20, 0x1d) + challenge := keccak256(0x00, 0x21) + mstore(C_V30_LOC, mod(challenge, p)) + + // separator + mstore(0x00, challenge) + mstore(0x20, mload(PI_Z_Y_LOC)) + mstore(0x40, mload(PI_Z_X_LOC)) + mstore(0x60, mload(PI_Z_OMEGA_Y_LOC)) + mstore(0x80, mload(PI_Z_OMEGA_X_LOC)) + + mstore(C_U_LOC, mod(keccak256(0x00, 0xa0), p)) + } + + let success := 0 + // VALIDATE T1 + { + let x := mload(T1_X_LOC) + let y := mload(T1_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(ACCUMULATOR_X_LOC, x) + mstore(add(ACCUMULATOR_X_LOC, 0x20), y) + } + // VALIDATE T2 + { + let x := mload(T2_X_LOC) // 0x1400 + let y := mload(T2_Y_LOC) // 0x1420 + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(ZETA_POW_N_LOC)) + // accumulator_2 = [T2].zeta^n + success := staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40) + // accumulator = [T1] + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE T3 + { + let x := mload(T3_X_LOC) + let y := mload(T3_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(mload(ZETA_POW_N_LOC), mload(ZETA_POW_N_LOC), p)) + // accumulator_2 = [T3].zeta^{2n} + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE T4 + { + let x := mload(T4_X_LOC) + let y := mload(T4_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(mulmod(mload(ZETA_POW_N_LOC), mload(ZETA_POW_N_LOC), p), mload(ZETA_POW_N_LOC), p)) + // accumulator_2 = [T4].zeta^{3n} + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE W1 + { + let x := mload(W1_X_LOC) + let y := mload(W1_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V0_LOC), p)) + // accumulator_2 = v0.(u + 1).[W1] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE W2 + { + let x := mload(W2_X_LOC) + let y := mload(W2_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V1_LOC), p)) + // accumulator_2 = v1.(u + 1).[W2] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE W3 + { + let x := mload(W3_X_LOC) + let y := mload(W3_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V2_LOC), p)) + // accumulator_2 = v2.(u + 1).[W3] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE W4 + { + let x := mload(W4_X_LOC) + let y := mload(W4_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V3_LOC), p)) + // accumulator_2 = v3.(u + 1).[W4] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE S + { + let x := mload(S_X_LOC) + let y := mload(S_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V4_LOC), p)) + // accumulator_2 = v4.(u + 1).[S] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE Z + { + let x := mload(Z_X_LOC) + let y := mload(Z_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V5_LOC), p)) + // accumulator_2 = v5.(u + 1).[Z] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE Z_LOOKUP + { + let x := mload(Z_LOOKUP_X_LOC) + let y := mload(Z_LOOKUP_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V6_LOC), p)) + // accumulator_2 = v6.(u + 1).[Z_LOOKUP] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE Q1 + { + let x := mload(Q1_X_LOC) + let y := mload(Q1_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V7_LOC)) + // accumulator_2 = v7.[Q1] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE Q2 + { + let x := mload(Q2_X_LOC) + let y := mload(Q2_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V8_LOC)) + // accumulator_2 = v8.[Q2] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE Q3 + { + let x := mload(Q3_X_LOC) + let y := mload(Q3_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V9_LOC)) + // accumulator_2 = v9.[Q3] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE Q4 + { + let x := mload(Q4_X_LOC) + let y := mload(Q4_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V10_LOC)) + // accumulator_2 = v10.[Q4] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE QM + { + let x := mload(QM_X_LOC) + let y := mload(QM_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V11_LOC)) + // accumulator_2 = v11.[Q;] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE QC + { + let x := mload(QC_X_LOC) + let y := mload(QC_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V12_LOC)) + // accumulator_2 = v12.[QC] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE QARITH + { + let x := mload(QARITH_X_LOC) + let y := mload(QARITH_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V13_LOC)) + // accumulator_2 = v13.[QARITH] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE QSORT + { + let x := mload(QSORT_X_LOC) + let y := mload(QSORT_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V14_LOC)) + // accumulator_2 = v14.[QSORT] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE QELLIPTIC + { + let x := mload(QELLIPTIC_X_LOC) + let y := mload(QELLIPTIC_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V15_LOC)) + // accumulator_2 = v15.[QELLIPTIC] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE QAUX + { + let x := mload(QAUX_X_LOC) + let y := mload(QAUX_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V16_LOC)) + // accumulator_2 = v15.[Q_AUX] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE SIGMA1 + { + let x := mload(SIGMA1_X_LOC) + let y := mload(SIGMA1_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V17_LOC)) + // accumulator_2 = v17.[sigma1] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE SIGMA2 + { + let x := mload(SIGMA2_X_LOC) + let y := mload(SIGMA2_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V18_LOC)) + // accumulator_2 = v18.[sigma2] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE SIGMA3 + { + let x := mload(SIGMA3_X_LOC) + let y := mload(SIGMA3_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V19_LOC)) + // accumulator_2 = v19.[sigma3] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE SIGMA4 + { + let x := mload(SIGMA4_X_LOC) + let y := mload(SIGMA4_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V20_LOC)) + // accumulator_2 = v20.[sigma4] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE TABLE1 + { + let x := mload(TABLE1_X_LOC) + let y := mload(TABLE1_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V21_LOC), p)) + // accumulator_2 = u.[table1] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE TABLE2 + { + let x := mload(TABLE2_X_LOC) + let y := mload(TABLE2_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V22_LOC), p)) + // accumulator_2 = u.[table2] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE TABLE3 + { + let x := mload(TABLE3_X_LOC) + let y := mload(TABLE3_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V23_LOC), p)) + // accumulator_2 = u.[table3] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE TABLE4 + { + let x := mload(TABLE4_X_LOC) + let y := mload(TABLE4_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V24_LOC), p)) + // accumulator_2 = u.[table4] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE TABLE_TYPE + { + let x := mload(TABLE_TYPE_X_LOC) + let y := mload(TABLE_TYPE_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V25_LOC)) + // accumulator_2 = v25.[TableType] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE ID1 + { + let x := mload(ID1_X_LOC) + let y := mload(ID1_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V26_LOC)) + // accumulator_2 = v26.[ID1] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE ID2 + { + let x := mload(ID2_X_LOC) + let y := mload(ID2_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V27_LOC)) + // accumulator_2 = v27.[ID2] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE ID3 + { + let x := mload(ID3_X_LOC) + let y := mload(ID3_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V28_LOC)) + // accumulator_2 = v28.[ID3] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE ID4 + { + let x := mload(ID4_X_LOC) + let y := mload(ID4_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V29_LOC)) + // accumulator_2 = v29.[ID4] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + /** + * COMPUTE BATCH EVALUATION SCALAR MULTIPLIER + */ + { + /** + * batch_evaluation = v0 * (w_1_omega * u + w_1_eval) + * batch_evaluation += v1 * (w_2_omega * u + w_2_eval) + * batch_evaluation += v2 * (w_3_omega * u + w_3_eval) + * batch_evaluation += v3 * (w_4_omega * u + w_4_eval) + * batch_evaluation += v4 * (s_omega_eval * u + s_eval) + * batch_evaluation += v5 * (z_omega_eval * u + z_eval) + * batch_evaluation += v6 * (z_lookup_omega_eval * u + z_lookup_eval) + */ + let batch_evaluation := + mulmod( + mload(C_V0_LOC), + addmod(mulmod(mload(W1_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W1_EVAL_LOC), p), + p + ) + batch_evaluation := + addmod( + batch_evaluation, + mulmod( + mload(C_V1_LOC), + addmod(mulmod(mload(W2_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W2_EVAL_LOC), p), + p + ), + p + ) + batch_evaluation := + addmod( + batch_evaluation, + mulmod( + mload(C_V2_LOC), + addmod(mulmod(mload(W3_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W3_EVAL_LOC), p), + p + ), + p + ) + batch_evaluation := + addmod( + batch_evaluation, + mulmod( + mload(C_V3_LOC), + addmod(mulmod(mload(W4_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W4_EVAL_LOC), p), + p + ), + p + ) + batch_evaluation := + addmod( + batch_evaluation, + mulmod( + mload(C_V4_LOC), + addmod(mulmod(mload(S_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(S_EVAL_LOC), p), + p + ), + p + ) + batch_evaluation := + addmod( + batch_evaluation, + mulmod( + mload(C_V5_LOC), + addmod(mulmod(mload(Z_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(Z_EVAL_LOC), p), + p + ), + p + ) + batch_evaluation := + addmod( + batch_evaluation, + mulmod( + mload(C_V6_LOC), + addmod(mulmod(mload(Z_LOOKUP_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(Z_LOOKUP_EVAL_LOC), p), + p + ), + p + ) + + /** + * batch_evaluation += v7 * Q1_EVAL + * batch_evaluation += v8 * Q2_EVAL + * batch_evaluation += v9 * Q3_EVAL + * batch_evaluation += v10 * Q4_EVAL + * batch_evaluation += v11 * QM_EVAL + * batch_evaluation += v12 * QC_EVAL + * batch_evaluation += v13 * QARITH_EVAL + * batch_evaluation += v14 * QSORT_EVAL_LOC + * batch_evaluation += v15 * QELLIPTIC_EVAL_LOC + * batch_evaluation += v16 * QAUX_EVAL_LOC + * batch_evaluation += v17 * SIGMA1_EVAL_LOC + * batch_evaluation += v18 * SIGMA2_EVAL_LOC + * batch_evaluation += v19 * SIGMA3_EVAL_LOC + * batch_evaluation += v20 * SIGMA4_EVAL_LOC + */ + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V7_LOC), mload(Q1_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V8_LOC), mload(Q2_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V9_LOC), mload(Q3_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V10_LOC), mload(Q4_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V11_LOC), mload(QM_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V12_LOC), mload(QC_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V13_LOC), mload(QARITH_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V14_LOC), mload(QSORT_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V15_LOC), mload(QELLIPTIC_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V16_LOC), mload(QAUX_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V17_LOC), mload(SIGMA1_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V18_LOC), mload(SIGMA2_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V19_LOC), mload(SIGMA3_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V20_LOC), mload(SIGMA4_EVAL_LOC), p), p) + + /** + * batch_evaluation += v21 * (table1(zw) * u + table1(z)) + * batch_evaluation += v22 * (table2(zw) * u + table2(z)) + * batch_evaluation += v23 * (table3(zw) * u + table3(z)) + * batch_evaluation += v24 * (table4(zw) * u + table4(z)) + * batch_evaluation += v25 * table_type_eval + * batch_evaluation += v26 * id1_eval + * batch_evaluation += v27 * id2_eval + * batch_evaluation += v28 * id3_eval + * batch_evaluation += v29 * id4_eval + * batch_evaluation += quotient_eval + */ + batch_evaluation := + addmod( + batch_evaluation, + mulmod( + mload(C_V21_LOC), + addmod(mulmod(mload(TABLE1_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE1_EVAL_LOC), p), + p + ), + p + ) + batch_evaluation := + addmod( + batch_evaluation, + mulmod( + mload(C_V22_LOC), + addmod(mulmod(mload(TABLE2_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE2_EVAL_LOC), p), + p + ), + p + ) + batch_evaluation := + addmod( + batch_evaluation, + mulmod( + mload(C_V23_LOC), + addmod(mulmod(mload(TABLE3_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE3_EVAL_LOC), p), + p + ), + p + ) + batch_evaluation := + addmod( + batch_evaluation, + mulmod( + mload(C_V24_LOC), + addmod(mulmod(mload(TABLE4_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE4_EVAL_LOC), p), + p + ), + p + ) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V25_LOC), mload(TABLE_TYPE_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V26_LOC), mload(ID1_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V27_LOC), mload(ID2_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V28_LOC), mload(ID3_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V29_LOC), mload(ID4_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mload(QUOTIENT_EVAL_LOC), p) + + mstore(0x00, 0x01) // [1].x + mstore(0x20, 0x02) // [1].y + mstore(0x40, sub(p, batch_evaluation)) + // accumulator_2 = -[1].(batch_evaluation) + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + if iszero(success) { + mstore(0x0, OPENING_COMMITMENT_FAILED_SELECTOR) + revert(0x00, 0x04) + } + } + + /** + * PERFORM PAIRING PREAMBLE + */ + { + let u := mload(C_U_LOC) + let zeta := mload(C_ZETA_LOC) + // VALIDATE PI_Z + { + let x := mload(PI_Z_X_LOC) + let y := mload(PI_Z_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + // compute zeta.[PI_Z] and add into accumulator + mstore(0x40, zeta) + success := staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE PI_Z_OMEGA + { + let x := mload(PI_Z_OMEGA_X_LOC) + let y := mload(PI_Z_OMEGA_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(mulmod(u, zeta, p), mload(OMEGA_LOC), p)) + // accumulator_2 = u.zeta.omega.[PI_Z_OMEGA] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // PAIRING_RHS = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, PAIRING_RHS_X_LOC, 0x40)) + + mstore(0x00, mload(PI_Z_X_LOC)) + mstore(0x20, mload(PI_Z_Y_LOC)) + mstore(0x40, mload(PI_Z_OMEGA_X_LOC)) + mstore(0x60, mload(PI_Z_OMEGA_Y_LOC)) + mstore(0x80, u) + success := and(success, staticcall(gas(), 7, 0x40, 0x60, 0x40, 0x40)) + // PAIRING_LHS = [PI_Z] + [PI_Z_OMEGA] * u + success := and(success, staticcall(gas(), 6, 0x00, 0x80, PAIRING_LHS_X_LOC, 0x40)) + // negate lhs y-coordinate + mstore(PAIRING_LHS_Y_LOC, sub(q, mload(PAIRING_LHS_Y_LOC))) + + if mload(CONTAINS_RECURSIVE_PROOF_LOC) { + // VALIDATE RECURSIVE P1 + { + let x := mload(RECURSIVE_P1_X_LOC) + let y := mload(RECURSIVE_P1_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + + // compute u.u.[recursive_p1] and write into 0x60 + mstore(0x40, mulmod(u, u, p)) + success := and(success, staticcall(gas(), 7, 0x00, 0x60, 0x60, 0x40)) + // VALIDATE RECURSIVE P2 + { + let x := mload(RECURSIVE_P2_X_LOC) + let y := mload(RECURSIVE_P2_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + // compute u.u.[recursive_p2] and write into 0x00 + // 0x40 still contains u*u + success := and(success, staticcall(gas(), 7, 0x00, 0x60, 0x00, 0x40)) + + // compute u.u.[recursiveP1] + rhs and write into rhs + mstore(0xa0, mload(PAIRING_RHS_X_LOC)) + mstore(0xc0, mload(PAIRING_RHS_Y_LOC)) + success := and(success, staticcall(gas(), 6, 0x60, 0x80, PAIRING_RHS_X_LOC, 0x40)) + + // compute u.u.[recursiveP2] + lhs and write into lhs + mstore(0x40, mload(PAIRING_LHS_X_LOC)) + mstore(0x60, mload(PAIRING_LHS_Y_LOC)) + success := and(success, staticcall(gas(), 6, 0x00, 0x80, PAIRING_LHS_X_LOC, 0x40)) + } + + if iszero(success) { + mstore(0x0, PAIRING_PREAMBLE_FAILED_SELECTOR) + revert(0x00, 0x04) + } + } + + /** + * PERFORM PAIRING + */ + { + // rhs paired with [1]_2 + // lhs paired with [x]_2 + + mstore(0x00, mload(PAIRING_RHS_X_LOC)) + mstore(0x20, mload(PAIRING_RHS_Y_LOC)) + mstore(0x40, 0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2) // this is [1]_2 + mstore(0x60, 0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed) + mstore(0x80, 0x090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b) + mstore(0xa0, 0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa) + + mstore(0xc0, mload(PAIRING_LHS_X_LOC)) + mstore(0xe0, mload(PAIRING_LHS_Y_LOC)) + mstore(0x100, mload(G2X_X0_LOC)) + mstore(0x120, mload(G2X_X1_LOC)) + mstore(0x140, mload(G2X_Y0_LOC)) + mstore(0x160, mload(G2X_Y1_LOC)) + + success := staticcall(gas(), 8, 0x00, 0x180, 0x00, 0x20) + if iszero(and(success, mload(0x00))) { + mstore(0x0, PAIRING_FAILED_SELECTOR) + revert(0x00, 0x04) + } + } + + { + mstore(0x00, 0x01) + return(0x00, 0x20) // Proof succeeded! + } + } + } +} + +contract UltraVerifier is BaseUltraVerifier { + function getVerificationKeyHash() public pure override(BaseUltraVerifier) returns (bytes32) { + return UltraVerificationKey.verificationKeyHash(); + } + + function loadVerificationKey(uint256 vk, uint256 _omegaInverseLoc) internal pure virtual override(BaseUltraVerifier) { + UltraVerificationKey.loadVerificationKey(vk, _omegaInverseLoc); + } +} diff --git a/noir/noir-repo/compiler/integration-tests/contracts/assert_statement.sol b/noir/noir-repo/compiler/integration-tests/contracts/assert_statement.sol new file mode 100644 index 000000000000..6946be8ee4be --- /dev/null +++ b/noir/noir-repo/compiler/integration-tests/contracts/assert_statement.sol @@ -0,0 +1,2869 @@ +// Verification Key Hash: 203c988709ced4125d5c6138661ba4d16a71092c5f4189d2b3baf2596a93311b +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2022 Aztec +pragma solidity >=0.8.4; + +library UltraVerificationKey { + function verificationKeyHash() internal pure returns(bytes32) { + return 0x203c988709ced4125d5c6138661ba4d16a71092c5f4189d2b3baf2596a93311b; + } + + function loadVerificationKey(uint256 _vk, uint256 _omegaInverseLoc) internal pure { + assembly { + mstore(add(_vk, 0x00), 0x0000000000000000000000000000000000000000000000000000000000000008) // vk.circuit_size + mstore(add(_vk, 0x20), 0x0000000000000000000000000000000000000000000000000000000000000001) // vk.num_inputs + mstore(add(_vk, 0x40), 0x2b337de1c8c14f22ec9b9e2f96afef3652627366f8170a0a948dad4ac1bd5e80) // vk.work_root + mstore(add(_vk, 0x60), 0x2a57c4a4850b6c2481463cffb1512d51832d6b3f6a82427f1b65b6e172000001) // vk.domain_inverse + mstore(add(_vk, 0x80), 0x0160ce4e279582f91bde4f03f5e9a292139c61bae1a44f0fc7689507414be688) // vk.Q1.x + mstore(add(_vk, 0xa0), 0x07e3e8a5d98a1177ec85bf88f163a55dc2d37f658c3b2d60f24740eb13b65d79) // vk.Q1.y + mstore(add(_vk, 0xc0), 0x23d08e2817ac16990004ed11d8fc66dc3035fbd7ff16412a8fd7da587a935298) // vk.Q2.x + mstore(add(_vk, 0xe0), 0x0708529196af3c8e16ffa580c26182356a5ad59c646c746a8d09f5d154e47c4f) // vk.Q2.y + mstore(add(_vk, 0x100), 0x13757e15a0905f298303784a161b212ddfe70eb7a1280596e8e4a804f118a6dd) // vk.Q3.x + mstore(add(_vk, 0x120), 0x05775b6c146c4a59856e869fe5a70ea23a729df796935c7824e3a26be794829b) // vk.Q3.y + mstore(add(_vk, 0x140), 0x1d539ccbfc556d0ad59307a218de65eef0c9e088fd2d45aa40311082d1f2809b) // vk.Q4.x + mstore(add(_vk, 0x160), 0x177004deeb1f9d401fd7b1af1a5ac8a2c848beceb6ab7806fd3b88037b8410fc) // vk.Q4.y + mstore(add(_vk, 0x180), 0x0d82d51f2f75d806285fd248c819b82508eb63672a733f20de1a97644be4f540) // vk.Q_M.x + mstore(add(_vk, 0x1a0), 0x06cd3b0e3460533b9e5ea2cdc0fcbbd002f9100cbba8a29f13b11513c53c59d0) // vk.Q_M.y + mstore(add(_vk, 0x1c0), 0x21791de65f9a28ec7024b1a87ab4f3f45ea38a93b2f810c5633ddb54927c1c96) // vk.Q_C.x + mstore(add(_vk, 0x1e0), 0x29fa14a969c5d81ed3abbbfb11220a926511a0439502c86885a8c6f0327aa7ad) // vk.Q_C.y + mstore(add(_vk, 0x200), 0x2a910445cd8fc895e5d235cd8ea185b84c3258e8206f560e5b5b18cbeafef87e) // vk.Q_ARITHMETIC.x + mstore(add(_vk, 0x220), 0x14dc6643d801c3ef27c2066b6e2bb4887e67f15e84bcb8507a5064a363f6043b) // vk.Q_ARITHMETIC.y + mstore(add(_vk, 0x240), 0x20690fd4869db418306046b38161dce38e900b42c314ba803088e8fbf125203f) // vk.QSORT.x + mstore(add(_vk, 0x260), 0x048a85e0bbac7c60ad3d78f601f63c1e2fa856bf7951b8292b1e88185993629c) // vk.QSORT.y + mstore(add(_vk, 0x280), 0x2623ad892dc62b1fa7d0a650f0d4706f457719495073d3666d77a625aeab0c51) // vk.Q_ELLIPTIC.x + mstore(add(_vk, 0x2a0), 0x295f6f10976c37bd9c6f96bb7187d5dbfcc8a467e021c03b13f74a9f79c3a10c) // vk.Q_ELLIPTIC.y + mstore(add(_vk, 0x2c0), 0x03560a3b334e887532f605c9cb7628c13ef9a937cc12420fb38d9ab8e848e85e) // vk.Q_AUX.x + mstore(add(_vk, 0x2e0), 0x15adc8bb1e01c835f48959d1237bd69bcebf08a4599cdda0fb96312d4dc0c7a9) // vk.Q_AUX.y + mstore(add(_vk, 0x300), 0x24e3690cd89b1f74c96a6b0e03032344488741fb4b129e9cbcb31de91fd06ad8) // vk.SIGMA1.x + mstore(add(_vk, 0x320), 0x2c3b3b2783935f54e840bb7502b0ec734cb8ac2419c90514d0d015a974a9b52b) // vk.SIGMA1.y + mstore(add(_vk, 0x340), 0x060d8aa43fdc434d1942263f364d95ab17c6189d67d3bf5dd2f3885de0151b6f) // vk.SIGMA2.x + mstore(add(_vk, 0x360), 0x1a1018a66221883639f2898a66f3455d292333b3adb497f00b4bc32d45229060) // vk.SIGMA2.y + mstore(add(_vk, 0x380), 0x27730cec8ee6eafbd0e5ccffeab20dbd1c781a61196943647af68c4e39985fdc) // vk.SIGMA3.x + mstore(add(_vk, 0x3a0), 0x0766d1f3a85c923ee23cb3fcd89886f19af23a34217779c58eaeceb38cfdf1eb) // vk.SIGMA3.y + mstore(add(_vk, 0x3c0), 0x09ae6c317ff52520ae05150d89a4678f6f5839296a91685a8f562ca95fa36822) // vk.SIGMA4.x + mstore(add(_vk, 0x3e0), 0x0832680695476b91062cfd71c4663f5bd579304b4448ce5ae6eaa6620db20ab1) // vk.SIGMA4.y + mstore(add(_vk, 0x400), 0x1f54baa07558e5fb055bd9ba49c0679c5d6e08a6605ab4513748ac0fa017dd1c) // vk.TABLE1.x + mstore(add(_vk, 0x420), 0x24aec62a9d9763499267dc98c334281e1ee7ee29bbb5e4b080c6091c1433ce62) // vk.TABLE1.y + mstore(add(_vk, 0x440), 0x28cf3e22bcd53782ebc3e0490e27e51a96755946ff16f0d6632365f0eb0ab4d4) // vk.TABLE2.x + mstore(add(_vk, 0x460), 0x234ce541f1f5117dd404cfaf01a22943148d7d8c9ba43f2133fab4201435a364) // vk.TABLE2.y + mstore(add(_vk, 0x480), 0x3016955028b6390f446c3fd0c5b424a7fb95ffb461d9514a1070e2d2403982ef) // vk.TABLE3.x + mstore(add(_vk, 0x4a0), 0x13ef666111b0be56a235983d397d2a08863c3b7cd7cddc20ba79ce915051c56e) // vk.TABLE3.y + mstore(add(_vk, 0x4c0), 0x217f7c4235161e9a3c16c45b6ca499e3993f465fc9f56e93ac769e597b752c1c) // vk.TABLE4.x + mstore(add(_vk, 0x4e0), 0x256467bfcb63d9fdcb5dde397757ad8ffa4cd96bc67b0b7df5678271e1114075) // vk.TABLE4.y + mstore(add(_vk, 0x500), 0x0e52d1bd75812c33c6f3d79ee4b94c54e5eb270bb64bde6e6ececadfd8c3236c) // vk.TABLE_TYPE.x + mstore(add(_vk, 0x520), 0x0ff417d256be43e73c8b1aa85bdda3484a2c641dce55bc2dd64ef0cd790a7fea) // vk.TABLE_TYPE.y + mstore(add(_vk, 0x540), 0x2914765365b4bb5f48a424db02b30c158b9ace6a8786bf33f65c33e87249f995) // vk.ID1.x + mstore(add(_vk, 0x560), 0x2e606ebd09b7686801932b72c9dbe83a6b1ae341f8cb6d52a568b693630f4643) // vk.ID1.y + mstore(add(_vk, 0x580), 0x1b0d1316756ddd16982a7e98b868244fff53c5d4bdc2b70e371c0d08e994cfd5) // vk.ID2.x + mstore(add(_vk, 0x5a0), 0x27f94b1ce85bf25b95857aaa3b82f6a3706170d67e53462bc635491ec3a29f98) // vk.ID2.y + mstore(add(_vk, 0x5c0), 0x26c5c0971d041a6777e4896896f674670e17bb68e92cbb11e605d2d74c077f66) // vk.ID3.x + mstore(add(_vk, 0x5e0), 0x15d5a580649417ff6523c7ec8e2fce5f1f22fef5be2a9fb4fd3004d9c6562efe) // vk.ID3.y + mstore(add(_vk, 0x600), 0x2eea648c8732596b1314fe2a4d2f05363f0c994e91cecad25835338edee2294f) // vk.ID4.x + mstore(add(_vk, 0x620), 0x0ab49886c2b94bd0bd3f6ed1dbbe2cb2671d2ae51d31c1210433c3972bb64578) // vk.ID4.y + mstore(add(_vk, 0x640), 0x00) // vk.contains_recursive_proof + mstore(add(_vk, 0x660), 0) // vk.recursive_proof_public_input_indices + mstore(add(_vk, 0x680), 0x260e01b251f6f1c7e7ff4e580791dee8ea51d87a358e038b4efe30fac09383c1) // vk.g2_x.X.c1 + mstore(add(_vk, 0x6a0), 0x0118c4d5b837bcc2bc89b5b398b5974e9f5944073b32078b7e231fec938883b0) // vk.g2_x.X.c0 + mstore(add(_vk, 0x6c0), 0x04fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe4) // vk.g2_x.Y.c1 + mstore(add(_vk, 0x6e0), 0x22febda3c0c0632a56475b4214e5615e11e6dd3f96e6cea2854a87d4dacc5e55) // vk.g2_x.Y.c0 + mstore(_omegaInverseLoc, 0x130b17119778465cfb3acaee30f81dee20710ead41671f568b11d9ab07b95a9b) // vk.work_root_inverse + } + } +} + +/** + * @title Ultra Plonk proof verification contract + * @dev Top level Plonk proof verification contract, which allows Plonk proof to be verified + */ +abstract contract BaseUltraVerifier { + // VERIFICATION KEY MEMORY LOCATIONS + uint256 internal constant N_LOC = 0x380; + uint256 internal constant NUM_INPUTS_LOC = 0x3a0; + uint256 internal constant OMEGA_LOC = 0x3c0; + uint256 internal constant DOMAIN_INVERSE_LOC = 0x3e0; + uint256 internal constant Q1_X_LOC = 0x400; + uint256 internal constant Q1_Y_LOC = 0x420; + uint256 internal constant Q2_X_LOC = 0x440; + uint256 internal constant Q2_Y_LOC = 0x460; + uint256 internal constant Q3_X_LOC = 0x480; + uint256 internal constant Q3_Y_LOC = 0x4a0; + uint256 internal constant Q4_X_LOC = 0x4c0; + uint256 internal constant Q4_Y_LOC = 0x4e0; + uint256 internal constant QM_X_LOC = 0x500; + uint256 internal constant QM_Y_LOC = 0x520; + uint256 internal constant QC_X_LOC = 0x540; + uint256 internal constant QC_Y_LOC = 0x560; + uint256 internal constant QARITH_X_LOC = 0x580; + uint256 internal constant QARITH_Y_LOC = 0x5a0; + uint256 internal constant QSORT_X_LOC = 0x5c0; + uint256 internal constant QSORT_Y_LOC = 0x5e0; + uint256 internal constant QELLIPTIC_X_LOC = 0x600; + uint256 internal constant QELLIPTIC_Y_LOC = 0x620; + uint256 internal constant QAUX_X_LOC = 0x640; + uint256 internal constant QAUX_Y_LOC = 0x660; + uint256 internal constant SIGMA1_X_LOC = 0x680; + uint256 internal constant SIGMA1_Y_LOC = 0x6a0; + uint256 internal constant SIGMA2_X_LOC = 0x6c0; + uint256 internal constant SIGMA2_Y_LOC = 0x6e0; + uint256 internal constant SIGMA3_X_LOC = 0x700; + uint256 internal constant SIGMA3_Y_LOC = 0x720; + uint256 internal constant SIGMA4_X_LOC = 0x740; + uint256 internal constant SIGMA4_Y_LOC = 0x760; + uint256 internal constant TABLE1_X_LOC = 0x780; + uint256 internal constant TABLE1_Y_LOC = 0x7a0; + uint256 internal constant TABLE2_X_LOC = 0x7c0; + uint256 internal constant TABLE2_Y_LOC = 0x7e0; + uint256 internal constant TABLE3_X_LOC = 0x800; + uint256 internal constant TABLE3_Y_LOC = 0x820; + uint256 internal constant TABLE4_X_LOC = 0x840; + uint256 internal constant TABLE4_Y_LOC = 0x860; + uint256 internal constant TABLE_TYPE_X_LOC = 0x880; + uint256 internal constant TABLE_TYPE_Y_LOC = 0x8a0; + uint256 internal constant ID1_X_LOC = 0x8c0; + uint256 internal constant ID1_Y_LOC = 0x8e0; + uint256 internal constant ID2_X_LOC = 0x900; + uint256 internal constant ID2_Y_LOC = 0x920; + uint256 internal constant ID3_X_LOC = 0x940; + uint256 internal constant ID3_Y_LOC = 0x960; + uint256 internal constant ID4_X_LOC = 0x980; + uint256 internal constant ID4_Y_LOC = 0x9a0; + uint256 internal constant CONTAINS_RECURSIVE_PROOF_LOC = 0x9c0; + uint256 internal constant RECURSIVE_PROOF_PUBLIC_INPUT_INDICES_LOC = 0x9e0; + uint256 internal constant G2X_X0_LOC = 0xa00; + uint256 internal constant G2X_X1_LOC = 0xa20; + uint256 internal constant G2X_Y0_LOC = 0xa40; + uint256 internal constant G2X_Y1_LOC = 0xa60; + + // ### PROOF DATA MEMORY LOCATIONS + uint256 internal constant W1_X_LOC = 0x1200; + uint256 internal constant W1_Y_LOC = 0x1220; + uint256 internal constant W2_X_LOC = 0x1240; + uint256 internal constant W2_Y_LOC = 0x1260; + uint256 internal constant W3_X_LOC = 0x1280; + uint256 internal constant W3_Y_LOC = 0x12a0; + uint256 internal constant W4_X_LOC = 0x12c0; + uint256 internal constant W4_Y_LOC = 0x12e0; + uint256 internal constant S_X_LOC = 0x1300; + uint256 internal constant S_Y_LOC = 0x1320; + uint256 internal constant Z_X_LOC = 0x1340; + uint256 internal constant Z_Y_LOC = 0x1360; + uint256 internal constant Z_LOOKUP_X_LOC = 0x1380; + uint256 internal constant Z_LOOKUP_Y_LOC = 0x13a0; + uint256 internal constant T1_X_LOC = 0x13c0; + uint256 internal constant T1_Y_LOC = 0x13e0; + uint256 internal constant T2_X_LOC = 0x1400; + uint256 internal constant T2_Y_LOC = 0x1420; + uint256 internal constant T3_X_LOC = 0x1440; + uint256 internal constant T3_Y_LOC = 0x1460; + uint256 internal constant T4_X_LOC = 0x1480; + uint256 internal constant T4_Y_LOC = 0x14a0; + + uint256 internal constant W1_EVAL_LOC = 0x1600; + uint256 internal constant W2_EVAL_LOC = 0x1620; + uint256 internal constant W3_EVAL_LOC = 0x1640; + uint256 internal constant W4_EVAL_LOC = 0x1660; + uint256 internal constant S_EVAL_LOC = 0x1680; + uint256 internal constant Z_EVAL_LOC = 0x16a0; + uint256 internal constant Z_LOOKUP_EVAL_LOC = 0x16c0; + uint256 internal constant Q1_EVAL_LOC = 0x16e0; + uint256 internal constant Q2_EVAL_LOC = 0x1700; + uint256 internal constant Q3_EVAL_LOC = 0x1720; + uint256 internal constant Q4_EVAL_LOC = 0x1740; + uint256 internal constant QM_EVAL_LOC = 0x1760; + uint256 internal constant QC_EVAL_LOC = 0x1780; + uint256 internal constant QARITH_EVAL_LOC = 0x17a0; + uint256 internal constant QSORT_EVAL_LOC = 0x17c0; + uint256 internal constant QELLIPTIC_EVAL_LOC = 0x17e0; + uint256 internal constant QAUX_EVAL_LOC = 0x1800; + uint256 internal constant TABLE1_EVAL_LOC = 0x1840; + uint256 internal constant TABLE2_EVAL_LOC = 0x1860; + uint256 internal constant TABLE3_EVAL_LOC = 0x1880; + uint256 internal constant TABLE4_EVAL_LOC = 0x18a0; + uint256 internal constant TABLE_TYPE_EVAL_LOC = 0x18c0; + uint256 internal constant ID1_EVAL_LOC = 0x18e0; + uint256 internal constant ID2_EVAL_LOC = 0x1900; + uint256 internal constant ID3_EVAL_LOC = 0x1920; + uint256 internal constant ID4_EVAL_LOC = 0x1940; + uint256 internal constant SIGMA1_EVAL_LOC = 0x1960; + uint256 internal constant SIGMA2_EVAL_LOC = 0x1980; + uint256 internal constant SIGMA3_EVAL_LOC = 0x19a0; + uint256 internal constant SIGMA4_EVAL_LOC = 0x19c0; + uint256 internal constant W1_OMEGA_EVAL_LOC = 0x19e0; + uint256 internal constant W2_OMEGA_EVAL_LOC = 0x2000; + uint256 internal constant W3_OMEGA_EVAL_LOC = 0x2020; + uint256 internal constant W4_OMEGA_EVAL_LOC = 0x2040; + uint256 internal constant S_OMEGA_EVAL_LOC = 0x2060; + uint256 internal constant Z_OMEGA_EVAL_LOC = 0x2080; + uint256 internal constant Z_LOOKUP_OMEGA_EVAL_LOC = 0x20a0; + uint256 internal constant TABLE1_OMEGA_EVAL_LOC = 0x20c0; + uint256 internal constant TABLE2_OMEGA_EVAL_LOC = 0x20e0; + uint256 internal constant TABLE3_OMEGA_EVAL_LOC = 0x2100; + uint256 internal constant TABLE4_OMEGA_EVAL_LOC = 0x2120; + + uint256 internal constant PI_Z_X_LOC = 0x2300; + uint256 internal constant PI_Z_Y_LOC = 0x2320; + uint256 internal constant PI_Z_OMEGA_X_LOC = 0x2340; + uint256 internal constant PI_Z_OMEGA_Y_LOC = 0x2360; + + // Used for elliptic widget. These are alias names for wire + shifted wire evaluations + uint256 internal constant X1_EVAL_LOC = W2_EVAL_LOC; + uint256 internal constant X2_EVAL_LOC = W1_OMEGA_EVAL_LOC; + uint256 internal constant X3_EVAL_LOC = W2_OMEGA_EVAL_LOC; + uint256 internal constant Y1_EVAL_LOC = W3_EVAL_LOC; + uint256 internal constant Y2_EVAL_LOC = W4_OMEGA_EVAL_LOC; + uint256 internal constant Y3_EVAL_LOC = W3_OMEGA_EVAL_LOC; + uint256 internal constant QBETA_LOC = Q3_EVAL_LOC; + uint256 internal constant QBETA_SQR_LOC = Q4_EVAL_LOC; + uint256 internal constant QSIGN_LOC = Q1_EVAL_LOC; + + // ### CHALLENGES MEMORY OFFSETS + + uint256 internal constant C_BETA_LOC = 0x2600; + uint256 internal constant C_GAMMA_LOC = 0x2620; + uint256 internal constant C_ALPHA_LOC = 0x2640; + uint256 internal constant C_ETA_LOC = 0x2660; + uint256 internal constant C_ETA_SQR_LOC = 0x2680; + uint256 internal constant C_ETA_CUBE_LOC = 0x26a0; + + uint256 internal constant C_ZETA_LOC = 0x26c0; + uint256 internal constant C_CURRENT_LOC = 0x26e0; + uint256 internal constant C_V0_LOC = 0x2700; + uint256 internal constant C_V1_LOC = 0x2720; + uint256 internal constant C_V2_LOC = 0x2740; + uint256 internal constant C_V3_LOC = 0x2760; + uint256 internal constant C_V4_LOC = 0x2780; + uint256 internal constant C_V5_LOC = 0x27a0; + uint256 internal constant C_V6_LOC = 0x27c0; + uint256 internal constant C_V7_LOC = 0x27e0; + uint256 internal constant C_V8_LOC = 0x2800; + uint256 internal constant C_V9_LOC = 0x2820; + uint256 internal constant C_V10_LOC = 0x2840; + uint256 internal constant C_V11_LOC = 0x2860; + uint256 internal constant C_V12_LOC = 0x2880; + uint256 internal constant C_V13_LOC = 0x28a0; + uint256 internal constant C_V14_LOC = 0x28c0; + uint256 internal constant C_V15_LOC = 0x28e0; + uint256 internal constant C_V16_LOC = 0x2900; + uint256 internal constant C_V17_LOC = 0x2920; + uint256 internal constant C_V18_LOC = 0x2940; + uint256 internal constant C_V19_LOC = 0x2960; + uint256 internal constant C_V20_LOC = 0x2980; + uint256 internal constant C_V21_LOC = 0x29a0; + uint256 internal constant C_V22_LOC = 0x29c0; + uint256 internal constant C_V23_LOC = 0x29e0; + uint256 internal constant C_V24_LOC = 0x2a00; + uint256 internal constant C_V25_LOC = 0x2a20; + uint256 internal constant C_V26_LOC = 0x2a40; + uint256 internal constant C_V27_LOC = 0x2a60; + uint256 internal constant C_V28_LOC = 0x2a80; + uint256 internal constant C_V29_LOC = 0x2aa0; + uint256 internal constant C_V30_LOC = 0x2ac0; + + uint256 internal constant C_U_LOC = 0x2b00; + + // ### LOCAL VARIABLES MEMORY OFFSETS + uint256 internal constant DELTA_NUMERATOR_LOC = 0x3000; + uint256 internal constant DELTA_DENOMINATOR_LOC = 0x3020; + uint256 internal constant ZETA_POW_N_LOC = 0x3040; + uint256 internal constant PUBLIC_INPUT_DELTA_LOC = 0x3060; + uint256 internal constant ZERO_POLY_LOC = 0x3080; + uint256 internal constant L_START_LOC = 0x30a0; + uint256 internal constant L_END_LOC = 0x30c0; + uint256 internal constant R_ZERO_EVAL_LOC = 0x30e0; + + uint256 internal constant PLOOKUP_DELTA_NUMERATOR_LOC = 0x3100; + uint256 internal constant PLOOKUP_DELTA_DENOMINATOR_LOC = 0x3120; + uint256 internal constant PLOOKUP_DELTA_LOC = 0x3140; + + uint256 internal constant ACCUMULATOR_X_LOC = 0x3160; + uint256 internal constant ACCUMULATOR_Y_LOC = 0x3180; + uint256 internal constant ACCUMULATOR2_X_LOC = 0x31a0; + uint256 internal constant ACCUMULATOR2_Y_LOC = 0x31c0; + uint256 internal constant PAIRING_LHS_X_LOC = 0x31e0; + uint256 internal constant PAIRING_LHS_Y_LOC = 0x3200; + uint256 internal constant PAIRING_RHS_X_LOC = 0x3220; + uint256 internal constant PAIRING_RHS_Y_LOC = 0x3240; + + // misc stuff + uint256 internal constant OMEGA_INVERSE_LOC = 0x3300; + uint256 internal constant C_ALPHA_SQR_LOC = 0x3320; + uint256 internal constant C_ALPHA_CUBE_LOC = 0x3340; + uint256 internal constant C_ALPHA_QUAD_LOC = 0x3360; + uint256 internal constant C_ALPHA_BASE_LOC = 0x3380; + + // ### RECURSION VARIABLE MEMORY LOCATIONS + uint256 internal constant RECURSIVE_P1_X_LOC = 0x3400; + uint256 internal constant RECURSIVE_P1_Y_LOC = 0x3420; + uint256 internal constant RECURSIVE_P2_X_LOC = 0x3440; + uint256 internal constant RECURSIVE_P2_Y_LOC = 0x3460; + uint256 internal constant PUBLIC_INPUTS_HASH_LOCATION = 0x3480; + + // sub-identity storage + uint256 internal constant PERMUTATION_IDENTITY = 0x3500; + uint256 internal constant PLOOKUP_IDENTITY = 0x3520; + uint256 internal constant ARITHMETIC_IDENTITY = 0x3540; + uint256 internal constant SORT_IDENTITY = 0x3560; + uint256 internal constant ELLIPTIC_IDENTITY = 0x3580; + uint256 internal constant AUX_IDENTITY = 0x35a0; + uint256 internal constant AUX_NON_NATIVE_FIELD_EVALUATION = 0x35c0; + uint256 internal constant AUX_LIMB_ACCUMULATOR_EVALUATION = 0x35e0; + uint256 internal constant AUX_RAM_CONSISTENCY_EVALUATION = 0x3600; + uint256 internal constant AUX_ROM_CONSISTENCY_EVALUATION = 0x3620; + uint256 internal constant AUX_MEMORY_EVALUATION = 0x3640; + + uint256 internal constant QUOTIENT_EVAL_LOC = 0x3660; + uint256 internal constant ZERO_POLY_INVERSE_LOC = 0x3680; + + // when hashing public inputs we use memory at NU_CHALLENGE_INPUT_LOC_A, as the hash input size is unknown at compile time + uint256 internal constant NU_CHALLENGE_INPUT_LOC_A = 0x36a0; + uint256 internal constant NU_CHALLENGE_INPUT_LOC_B = 0x36c0; + uint256 internal constant NU_CHALLENGE_INPUT_LOC_C = 0x36e0; + + bytes4 internal constant INVALID_VERIFICATION_KEY_SELECTOR = 0x7e5769bf; + bytes4 internal constant POINT_NOT_ON_CURVE_SELECTOR = 0xa3dad654; + bytes4 internal constant PUBLIC_INPUT_INVALID_BN128_G1_POINT_SELECTOR = 0xeba9f4a6; + bytes4 internal constant PUBLIC_INPUT_GE_P_SELECTOR = 0x374a972f; + bytes4 internal constant MOD_EXP_FAILURE_SELECTOR = 0xf894a7bc; + bytes4 internal constant PAIRING_PREAMBLE_FAILED_SELECTOR = 0x01882d81; + bytes4 internal constant OPENING_COMMITMENT_FAILED_SELECTOR = 0x4e719763; + bytes4 internal constant PAIRING_FAILED_SELECTOR = 0xd71fd263; + + uint256 internal constant ETA_INPUT_LENGTH = 0xc0; // W1, W2, W3 = 6 * 0x20 bytes + + // We need to hash 41 field elements when generating the NU challenge + // w1, w2, w3, w4, s, z, z_lookup, q1, q2, q3, q4, qm, qc, qarith (14) + // qsort, qelliptic, qaux, sigma1, sigma2, sigma, sigma4, (7) + // table1, table2, table3, table4, tabletype, id1, id2, id3, id4, (9) + // w1_omega, w2_omega, w3_omega, w4_omega, s_omega, z_omega, z_lookup_omega, (7) + // table1_omega, table2_omega, table3_omega, table4_omega (4) + uint256 internal constant NU_INPUT_LENGTH = 0x520; // 0x520 = 41 * 0x20 + + // There are ELEVEN G1 group elements added into the transcript in the `beta` round, that we need to skip over + // W1, W2, W3, W4, S, Z, Z_LOOKUP, T1, T2, T3, T4 + uint256 internal constant NU_CALLDATA_SKIP_LENGTH = 0x2c0; // 11 * 0x40 = 0x2c0 + + uint256 internal constant NEGATIVE_INVERSE_OF_2_MODULO_P = + 0x183227397098d014dc2822db40c0ac2e9419f4243cdcb848a1f0fac9f8000000; + uint256 internal constant LIMB_SIZE = 0x100000000000000000; // 2<<68 + uint256 internal constant SUBLIMB_SHIFT = 0x4000; // 2<<14 + + // y^2 = x^3 + ax + b + // for Grumpkin, a = 0 and b = -17. We use b in a custom gate relation that evaluates elliptic curve arithmetic + uint256 internal constant GRUMPKIN_CURVE_B_PARAMETER_NEGATED = 17; + + error INVALID_VERIFICATION_KEY(); + error POINT_NOT_ON_CURVE(); + error PUBLIC_INPUT_COUNT_INVALID(uint256 expected, uint256 actual); + error PUBLIC_INPUT_INVALID_BN128_G1_POINT(); + error PUBLIC_INPUT_GE_P(); + error MOD_EXP_FAILURE(); + error PAIRING_PREAMBLE_FAILED(); + error OPENING_COMMITMENT_FAILED(); + error PAIRING_FAILED(); + + function getVerificationKeyHash() public pure virtual returns (bytes32); + + /** + * @dev We assume that the verification key loaded by this function is constant as we only verify it on deployment + */ + function loadVerificationKey(uint256 _vk, uint256 _omegaInverseLoc) internal pure virtual; + + constructor() { + loadVerificationKey(N_LOC, OMEGA_INVERSE_LOC); + + // We verify that all of the EC points in the verification key lie on the bn128 curve. + assembly { + let q := 21888242871839275222246405745257275088696311157297823662689037894645226208583 // EC group order + + let success := 1 + + // VALIDATE Q1 + { + let x := mload(Q1_X_LOC) + let y := mload(Q1_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE Q2 + { + let x := mload(Q2_X_LOC) + let y := mload(Q2_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE Q3 + { + let x := mload(Q3_X_LOC) + let y := mload(Q3_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE Q4 + { + let x := mload(Q4_X_LOC) + let y := mload(Q4_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + mstore(0x00, x) + mstore(0x20, y) + } + // VALIDATE QM + { + let x := mload(QM_X_LOC) + let y := mload(QM_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE QC + { + let x := mload(QC_X_LOC) + let y := mload(QC_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE QARITH + { + let x := mload(QARITH_X_LOC) + let y := mload(QARITH_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE QSORT + { + let x := mload(QSORT_X_LOC) + let y := mload(QSORT_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE QELLIPTIC + { + let x := mload(QELLIPTIC_X_LOC) + let y := mload(QELLIPTIC_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE QAUX + { + let x := mload(QAUX_X_LOC) + let y := mload(QAUX_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE SIGMA1 + { + let x := mload(SIGMA1_X_LOC) + let y := mload(SIGMA1_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE SIGMA2 + { + let x := mload(SIGMA2_X_LOC) + let y := mload(SIGMA2_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE SIGMA3 + { + let x := mload(SIGMA3_X_LOC) + let y := mload(SIGMA3_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE SIGMA4 + { + let x := mload(SIGMA4_X_LOC) + let y := mload(SIGMA4_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE TABLE1 + { + let x := mload(TABLE1_X_LOC) + let y := mload(TABLE1_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE TABLE2 + { + let x := mload(TABLE2_X_LOC) + let y := mload(TABLE2_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE TABLE3 + { + let x := mload(TABLE3_X_LOC) + let y := mload(TABLE3_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE TABLE4 + { + let x := mload(TABLE4_X_LOC) + let y := mload(TABLE4_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE TABLE_TYPE + { + let x := mload(TABLE_TYPE_X_LOC) + let y := mload(TABLE_TYPE_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE ID1 + { + let x := mload(ID1_X_LOC) + let y := mload(ID1_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE ID2 + { + let x := mload(ID2_X_LOC) + let y := mload(ID2_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE ID3 + { + let x := mload(ID3_X_LOC) + let y := mload(ID3_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE ID4 + { + let x := mload(ID4_X_LOC) + let y := mload(ID4_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + + if iszero(success) { + mstore(0x0, INVALID_VERIFICATION_KEY_SELECTOR) + revert(0x00, 0x04) + } + } + } + + /** + * @notice Verify a Ultra Plonk proof + * @param _proof - The serialized proof + * @param _publicInputs - An array of the public inputs + * @return True if proof is valid, reverts otherwise + */ + function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool) { + loadVerificationKey(N_LOC, OMEGA_INVERSE_LOC); + + uint256 requiredPublicInputCount; + assembly { + requiredPublicInputCount := mload(NUM_INPUTS_LOC) + } + if (requiredPublicInputCount != _publicInputs.length) { + revert PUBLIC_INPUT_COUNT_INVALID(requiredPublicInputCount, _publicInputs.length); + } + + assembly { + let q := 21888242871839275222246405745257275088696311157297823662689037894645226208583 // EC group order + let p := 21888242871839275222246405745257275088548364400416034343698204186575808495617 // Prime field order + + /** + * LOAD PROOF FROM CALLDATA + */ + { + let data_ptr := add(calldataload(0x04), 0x24) + + mstore(W1_Y_LOC, mod(calldataload(data_ptr), q)) + mstore(W1_X_LOC, mod(calldataload(add(data_ptr, 0x20)), q)) + + mstore(W2_Y_LOC, mod(calldataload(add(data_ptr, 0x40)), q)) + mstore(W2_X_LOC, mod(calldataload(add(data_ptr, 0x60)), q)) + + mstore(W3_Y_LOC, mod(calldataload(add(data_ptr, 0x80)), q)) + mstore(W3_X_LOC, mod(calldataload(add(data_ptr, 0xa0)), q)) + + mstore(W4_Y_LOC, mod(calldataload(add(data_ptr, 0xc0)), q)) + mstore(W4_X_LOC, mod(calldataload(add(data_ptr, 0xe0)), q)) + + mstore(S_Y_LOC, mod(calldataload(add(data_ptr, 0x100)), q)) + mstore(S_X_LOC, mod(calldataload(add(data_ptr, 0x120)), q)) + mstore(Z_Y_LOC, mod(calldataload(add(data_ptr, 0x140)), q)) + mstore(Z_X_LOC, mod(calldataload(add(data_ptr, 0x160)), q)) + mstore(Z_LOOKUP_Y_LOC, mod(calldataload(add(data_ptr, 0x180)), q)) + mstore(Z_LOOKUP_X_LOC, mod(calldataload(add(data_ptr, 0x1a0)), q)) + mstore(T1_Y_LOC, mod(calldataload(add(data_ptr, 0x1c0)), q)) + mstore(T1_X_LOC, mod(calldataload(add(data_ptr, 0x1e0)), q)) + + mstore(T2_Y_LOC, mod(calldataload(add(data_ptr, 0x200)), q)) + mstore(T2_X_LOC, mod(calldataload(add(data_ptr, 0x220)), q)) + + mstore(T3_Y_LOC, mod(calldataload(add(data_ptr, 0x240)), q)) + mstore(T3_X_LOC, mod(calldataload(add(data_ptr, 0x260)), q)) + + mstore(T4_Y_LOC, mod(calldataload(add(data_ptr, 0x280)), q)) + mstore(T4_X_LOC, mod(calldataload(add(data_ptr, 0x2a0)), q)) + + mstore(W1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x2c0)), p)) + mstore(W2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x2e0)), p)) + mstore(W3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x300)), p)) + mstore(W4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x320)), p)) + mstore(S_EVAL_LOC, mod(calldataload(add(data_ptr, 0x340)), p)) + mstore(Z_EVAL_LOC, mod(calldataload(add(data_ptr, 0x360)), p)) + mstore(Z_LOOKUP_EVAL_LOC, mod(calldataload(add(data_ptr, 0x380)), p)) + mstore(Q1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x3a0)), p)) + mstore(Q2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x3c0)), p)) + mstore(Q3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x3e0)), p)) + mstore(Q4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x400)), p)) + mstore(QM_EVAL_LOC, mod(calldataload(add(data_ptr, 0x420)), p)) + mstore(QC_EVAL_LOC, mod(calldataload(add(data_ptr, 0x440)), p)) + mstore(QARITH_EVAL_LOC, mod(calldataload(add(data_ptr, 0x460)), p)) + mstore(QSORT_EVAL_LOC, mod(calldataload(add(data_ptr, 0x480)), p)) + mstore(QELLIPTIC_EVAL_LOC, mod(calldataload(add(data_ptr, 0x4a0)), p)) + mstore(QAUX_EVAL_LOC, mod(calldataload(add(data_ptr, 0x4c0)), p)) + + mstore(SIGMA1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x4e0)), p)) + mstore(SIGMA2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x500)), p)) + + mstore(SIGMA3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x520)), p)) + mstore(SIGMA4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x540)), p)) + + mstore(TABLE1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x560)), p)) + mstore(TABLE2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x580)), p)) + mstore(TABLE3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x5a0)), p)) + mstore(TABLE4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x5c0)), p)) + mstore(TABLE_TYPE_EVAL_LOC, mod(calldataload(add(data_ptr, 0x5e0)), p)) + + mstore(ID1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x600)), p)) + mstore(ID2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x620)), p)) + mstore(ID3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x640)), p)) + mstore(ID4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x660)), p)) + + mstore(W1_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x680)), p)) + mstore(W2_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x6a0)), p)) + mstore(W3_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x6c0)), p)) + mstore(W4_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x6e0)), p)) + mstore(S_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x700)), p)) + + mstore(Z_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x720)), p)) + + mstore(Z_LOOKUP_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x740)), p)) + mstore(TABLE1_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x760)), p)) + mstore(TABLE2_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x780)), p)) + mstore(TABLE3_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x7a0)), p)) + mstore(TABLE4_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x7c0)), p)) + + mstore(PI_Z_Y_LOC, mod(calldataload(add(data_ptr, 0x7e0)), q)) + mstore(PI_Z_X_LOC, mod(calldataload(add(data_ptr, 0x800)), q)) + + mstore(PI_Z_OMEGA_Y_LOC, mod(calldataload(add(data_ptr, 0x820)), q)) + mstore(PI_Z_OMEGA_X_LOC, mod(calldataload(add(data_ptr, 0x840)), q)) + } + + /** + * LOAD RECURSIVE PROOF INTO MEMORY + */ + { + if mload(CONTAINS_RECURSIVE_PROOF_LOC) { + let public_inputs_ptr := add(calldataload(0x24), 0x24) + let index_counter := add(shl(5, mload(RECURSIVE_PROOF_PUBLIC_INPUT_INDICES_LOC)), public_inputs_ptr) + + let x0 := calldataload(index_counter) + x0 := add(x0, shl(68, calldataload(add(index_counter, 0x20)))) + x0 := add(x0, shl(136, calldataload(add(index_counter, 0x40)))) + x0 := add(x0, shl(204, calldataload(add(index_counter, 0x60)))) + let y0 := calldataload(add(index_counter, 0x80)) + y0 := add(y0, shl(68, calldataload(add(index_counter, 0xa0)))) + y0 := add(y0, shl(136, calldataload(add(index_counter, 0xc0)))) + y0 := add(y0, shl(204, calldataload(add(index_counter, 0xe0)))) + let x1 := calldataload(add(index_counter, 0x100)) + x1 := add(x1, shl(68, calldataload(add(index_counter, 0x120)))) + x1 := add(x1, shl(136, calldataload(add(index_counter, 0x140)))) + x1 := add(x1, shl(204, calldataload(add(index_counter, 0x160)))) + let y1 := calldataload(add(index_counter, 0x180)) + y1 := add(y1, shl(68, calldataload(add(index_counter, 0x1a0)))) + y1 := add(y1, shl(136, calldataload(add(index_counter, 0x1c0)))) + y1 := add(y1, shl(204, calldataload(add(index_counter, 0x1e0)))) + mstore(RECURSIVE_P1_X_LOC, x0) + mstore(RECURSIVE_P1_Y_LOC, y0) + mstore(RECURSIVE_P2_X_LOC, x1) + mstore(RECURSIVE_P2_Y_LOC, y1) + + // validate these are valid bn128 G1 points + if iszero(and(and(lt(x0, q), lt(x1, q)), and(lt(y0, q), lt(y1, q)))) { + mstore(0x00, PUBLIC_INPUT_INVALID_BN128_G1_POINT_SELECTOR) + revert(0x00, 0x04) + } + } + } + + { + /** + * Generate initial challenge + */ + mstore(0x00, shl(224, mload(N_LOC))) + mstore(0x04, shl(224, mload(NUM_INPUTS_LOC))) + let challenge := keccak256(0x00, 0x08) + + /** + * Generate eta challenge + */ + mstore(PUBLIC_INPUTS_HASH_LOCATION, challenge) + // The public input location is stored at 0x24, we then add 0x24 to skip selector and the length of public inputs + let public_inputs_start := add(calldataload(0x24), 0x24) + // copy the public inputs over + let public_input_size := mul(mload(NUM_INPUTS_LOC), 0x20) + calldatacopy(add(PUBLIC_INPUTS_HASH_LOCATION, 0x20), public_inputs_start, public_input_size) + + // copy W1, W2, W3 into challenge. Each point is 0x40 bytes, so load 0xc0 = 3 * 0x40 bytes (ETA input length) + let w_start := add(calldataload(0x04), 0x24) + calldatacopy(add(add(PUBLIC_INPUTS_HASH_LOCATION, 0x20), public_input_size), w_start, ETA_INPUT_LENGTH) + + // Challenge is the old challenge + public inputs + W1, W2, W3 (0x20 + public_input_size + 0xc0) + let challenge_bytes_size := add(0x20, add(public_input_size, ETA_INPUT_LENGTH)) + + challenge := keccak256(PUBLIC_INPUTS_HASH_LOCATION, challenge_bytes_size) + { + let eta := mod(challenge, p) + mstore(C_ETA_LOC, eta) + mstore(C_ETA_SQR_LOC, mulmod(eta, eta, p)) + mstore(C_ETA_CUBE_LOC, mulmod(mload(C_ETA_SQR_LOC), eta, p)) + } + + /** + * Generate beta challenge + */ + mstore(0x00, challenge) + mstore(0x20, mload(W4_Y_LOC)) + mstore(0x40, mload(W4_X_LOC)) + mstore(0x60, mload(S_Y_LOC)) + mstore(0x80, mload(S_X_LOC)) + challenge := keccak256(0x00, 0xa0) + mstore(C_BETA_LOC, mod(challenge, p)) + + /** + * Generate gamma challenge + */ + mstore(0x00, challenge) + mstore8(0x20, 0x01) + challenge := keccak256(0x00, 0x21) + mstore(C_GAMMA_LOC, mod(challenge, p)) + + /** + * Generate alpha challenge + */ + mstore(0x00, challenge) + mstore(0x20, mload(Z_Y_LOC)) + mstore(0x40, mload(Z_X_LOC)) + mstore(0x60, mload(Z_LOOKUP_Y_LOC)) + mstore(0x80, mload(Z_LOOKUP_X_LOC)) + challenge := keccak256(0x00, 0xa0) + mstore(C_ALPHA_LOC, mod(challenge, p)) + + /** + * Compute and store some powers of alpha for future computations + */ + let alpha := mload(C_ALPHA_LOC) + mstore(C_ALPHA_SQR_LOC, mulmod(alpha, alpha, p)) + mstore(C_ALPHA_CUBE_LOC, mulmod(mload(C_ALPHA_SQR_LOC), alpha, p)) + mstore(C_ALPHA_QUAD_LOC, mulmod(mload(C_ALPHA_CUBE_LOC), alpha, p)) + mstore(C_ALPHA_BASE_LOC, alpha) + + /** + * Generate zeta challenge + */ + mstore(0x00, challenge) + mstore(0x20, mload(T1_Y_LOC)) + mstore(0x40, mload(T1_X_LOC)) + mstore(0x60, mload(T2_Y_LOC)) + mstore(0x80, mload(T2_X_LOC)) + mstore(0xa0, mload(T3_Y_LOC)) + mstore(0xc0, mload(T3_X_LOC)) + mstore(0xe0, mload(T4_Y_LOC)) + mstore(0x100, mload(T4_X_LOC)) + + challenge := keccak256(0x00, 0x120) + + mstore(C_ZETA_LOC, mod(challenge, p)) + mstore(C_CURRENT_LOC, challenge) + } + + /** + * EVALUATE FIELD OPERATIONS + */ + + /** + * COMPUTE PUBLIC INPUT DELTA + * ΔPI = ∏ᵢ∈ℓ(wᵢ + β σ(i) + γ) / ∏ᵢ∈ℓ(wᵢ + β σ'(i) + γ) + */ + { + let beta := mload(C_BETA_LOC) // β + let gamma := mload(C_GAMMA_LOC) // γ + let work_root := mload(OMEGA_LOC) // ω + let numerator_value := 1 + let denominator_value := 1 + + let p_clone := p // move p to the front of the stack + let valid_inputs := true + + // Load the starting point of the public inputs (jump over the selector and the length of public inputs [0x24]) + let public_inputs_ptr := add(calldataload(0x24), 0x24) + + // endpoint_ptr = public_inputs_ptr + num_inputs * 0x20. // every public input is 0x20 bytes + let endpoint_ptr := add(public_inputs_ptr, mul(mload(NUM_INPUTS_LOC), 0x20)) + + // root_1 = β * 0x05 + let root_1 := mulmod(beta, 0x05, p_clone) // k1.β + // root_2 = β * 0x0c + let root_2 := mulmod(beta, 0x0c, p_clone) + // @note 0x05 + 0x07 == 0x0c == external coset generator + + for {} lt(public_inputs_ptr, endpoint_ptr) { public_inputs_ptr := add(public_inputs_ptr, 0x20) } { + /** + * input = public_input[i] + * valid_inputs &= input < p + * temp = input + gamma + * numerator_value *= (β.σ(i) + wᵢ + γ) // σ(i) = 0x05.ωⁱ + * denominator_value *= (β.σ'(i) + wᵢ + γ) // σ'(i) = 0x0c.ωⁱ + * root_1 *= ω + * root_2 *= ω + */ + + let input := calldataload(public_inputs_ptr) + valid_inputs := and(valid_inputs, lt(input, p_clone)) + let temp := addmod(input, gamma, p_clone) + + numerator_value := mulmod(numerator_value, add(root_1, temp), p_clone) + denominator_value := mulmod(denominator_value, add(root_2, temp), p_clone) + + root_1 := mulmod(root_1, work_root, p_clone) + root_2 := mulmod(root_2, work_root, p_clone) + } + + // Revert if not all public inputs are field elements (i.e. < p) + if iszero(valid_inputs) { + mstore(0x00, PUBLIC_INPUT_GE_P_SELECTOR) + revert(0x00, 0x04) + } + + mstore(DELTA_NUMERATOR_LOC, numerator_value) + mstore(DELTA_DENOMINATOR_LOC, denominator_value) + } + + /** + * Compute Plookup delta factor [γ(1 + β)]^{n-k} + * k = num roots cut out of Z_H = 4 + */ + { + let delta_base := mulmod(mload(C_GAMMA_LOC), addmod(mload(C_BETA_LOC), 1, p), p) + let delta_numerator := delta_base + { + let exponent := mload(N_LOC) + let count := 1 + for {} lt(count, exponent) { count := add(count, count) } { + delta_numerator := mulmod(delta_numerator, delta_numerator, p) + } + } + mstore(PLOOKUP_DELTA_NUMERATOR_LOC, delta_numerator) + + let delta_denominator := mulmod(delta_base, delta_base, p) + delta_denominator := mulmod(delta_denominator, delta_denominator, p) + mstore(PLOOKUP_DELTA_DENOMINATOR_LOC, delta_denominator) + } + /** + * Compute lagrange poly and vanishing poly fractions + */ + { + /** + * vanishing_numerator = zeta + * ZETA_POW_N = zeta^n + * vanishing_numerator -= 1 + * accumulating_root = omega_inverse + * work_root = p - accumulating_root + * domain_inverse = domain_inverse + * vanishing_denominator = zeta + work_root + * work_root *= accumulating_root + * vanishing_denominator *= (zeta + work_root) + * work_root *= accumulating_root + * vanishing_denominator *= (zeta + work_root) + * vanishing_denominator *= (zeta + (zeta + accumulating_root)) + * work_root = omega + * lagrange_numerator = vanishing_numerator * domain_inverse + * l_start_denominator = zeta - 1 + * accumulating_root = work_root^2 + * l_end_denominator = accumulating_root^2 * work_root * zeta - 1 + * Note: l_end_denominator term contains a term \omega^5 to cut out 5 roots of unity from vanishing poly + */ + + let zeta := mload(C_ZETA_LOC) + + // compute zeta^n, where n is a power of 2 + let vanishing_numerator := zeta + { + // pow_small + let exponent := mload(N_LOC) + let count := 1 + for {} lt(count, exponent) { count := add(count, count) } { + vanishing_numerator := mulmod(vanishing_numerator, vanishing_numerator, p) + } + } + mstore(ZETA_POW_N_LOC, vanishing_numerator) + vanishing_numerator := addmod(vanishing_numerator, sub(p, 1), p) + + let accumulating_root := mload(OMEGA_INVERSE_LOC) + let work_root := sub(p, accumulating_root) + let domain_inverse := mload(DOMAIN_INVERSE_LOC) + + let vanishing_denominator := addmod(zeta, work_root, p) + work_root := mulmod(work_root, accumulating_root, p) + vanishing_denominator := mulmod(vanishing_denominator, addmod(zeta, work_root, p), p) + work_root := mulmod(work_root, accumulating_root, p) + vanishing_denominator := mulmod(vanishing_denominator, addmod(zeta, work_root, p), p) + vanishing_denominator := + mulmod(vanishing_denominator, addmod(zeta, mulmod(work_root, accumulating_root, p), p), p) + + work_root := mload(OMEGA_LOC) + + let lagrange_numerator := mulmod(vanishing_numerator, domain_inverse, p) + let l_start_denominator := addmod(zeta, sub(p, 1), p) + + accumulating_root := mulmod(work_root, work_root, p) + + let l_end_denominator := + addmod( + mulmod(mulmod(mulmod(accumulating_root, accumulating_root, p), work_root, p), zeta, p), sub(p, 1), p + ) + + /** + * Compute inversions using Montgomery's batch inversion trick + */ + let accumulator := mload(DELTA_DENOMINATOR_LOC) + let t0 := accumulator + accumulator := mulmod(accumulator, vanishing_denominator, p) + let t1 := accumulator + accumulator := mulmod(accumulator, vanishing_numerator, p) + let t2 := accumulator + accumulator := mulmod(accumulator, l_start_denominator, p) + let t3 := accumulator + accumulator := mulmod(accumulator, mload(PLOOKUP_DELTA_DENOMINATOR_LOC), p) + let t4 := accumulator + { + mstore(0, 0x20) + mstore(0x20, 0x20) + mstore(0x40, 0x20) + mstore(0x60, mulmod(accumulator, l_end_denominator, p)) + mstore(0x80, sub(p, 2)) + mstore(0xa0, p) + if iszero(staticcall(gas(), 0x05, 0x00, 0xc0, 0x00, 0x20)) { + mstore(0x0, MOD_EXP_FAILURE_SELECTOR) + revert(0x00, 0x04) + } + accumulator := mload(0x00) + } + + t4 := mulmod(accumulator, t4, p) + accumulator := mulmod(accumulator, l_end_denominator, p) + + t3 := mulmod(accumulator, t3, p) + accumulator := mulmod(accumulator, mload(PLOOKUP_DELTA_DENOMINATOR_LOC), p) + + t2 := mulmod(accumulator, t2, p) + accumulator := mulmod(accumulator, l_start_denominator, p) + + t1 := mulmod(accumulator, t1, p) + accumulator := mulmod(accumulator, vanishing_numerator, p) + + t0 := mulmod(accumulator, t0, p) + accumulator := mulmod(accumulator, vanishing_denominator, p) + + accumulator := mulmod(mulmod(accumulator, accumulator, p), mload(DELTA_DENOMINATOR_LOC), p) + + mstore(PUBLIC_INPUT_DELTA_LOC, mulmod(mload(DELTA_NUMERATOR_LOC), accumulator, p)) + mstore(ZERO_POLY_LOC, mulmod(vanishing_numerator, t0, p)) + mstore(ZERO_POLY_INVERSE_LOC, mulmod(vanishing_denominator, t1, p)) + mstore(L_START_LOC, mulmod(lagrange_numerator, t2, p)) + mstore(PLOOKUP_DELTA_LOC, mulmod(mload(PLOOKUP_DELTA_NUMERATOR_LOC), t3, p)) + mstore(L_END_LOC, mulmod(lagrange_numerator, t4, p)) + } + + /** + * UltraPlonk Widget Ordering: + * + * 1. Permutation widget + * 2. Plookup widget + * 3. Arithmetic widget + * 4. Fixed base widget (?) + * 5. GenPermSort widget + * 6. Elliptic widget + * 7. Auxiliary widget + */ + + /** + * COMPUTE PERMUTATION WIDGET EVALUATION + */ + { + let alpha := mload(C_ALPHA_LOC) + let beta := mload(C_BETA_LOC) + let gamma := mload(C_GAMMA_LOC) + + /** + * t1 = (W1 + gamma + beta * ID1) * (W2 + gamma + beta * ID2) + * t2 = (W3 + gamma + beta * ID3) * (W4 + gamma + beta * ID4) + * result = alpha_base * z_eval * t1 * t2 + * t1 = (W1 + gamma + beta * sigma_1_eval) * (W2 + gamma + beta * sigma_2_eval) + * t2 = (W2 + gamma + beta * sigma_3_eval) * (W3 + gamma + beta * sigma_4_eval) + * result -= (alpha_base * z_omega_eval * t1 * t2) + */ + let t1 := + mulmod( + add(add(mload(W1_EVAL_LOC), gamma), mulmod(beta, mload(ID1_EVAL_LOC), p)), + add(add(mload(W2_EVAL_LOC), gamma), mulmod(beta, mload(ID2_EVAL_LOC), p)), + p + ) + let t2 := + mulmod( + add(add(mload(W3_EVAL_LOC), gamma), mulmod(beta, mload(ID3_EVAL_LOC), p)), + add(add(mload(W4_EVAL_LOC), gamma), mulmod(beta, mload(ID4_EVAL_LOC), p)), + p + ) + let result := mulmod(mload(C_ALPHA_BASE_LOC), mulmod(mload(Z_EVAL_LOC), mulmod(t1, t2, p), p), p) + t1 := + mulmod( + add(add(mload(W1_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA1_EVAL_LOC), p)), + add(add(mload(W2_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA2_EVAL_LOC), p)), + p + ) + t2 := + mulmod( + add(add(mload(W3_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA3_EVAL_LOC), p)), + add(add(mload(W4_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA4_EVAL_LOC), p)), + p + ) + result := + addmod( + result, + sub(p, mulmod(mload(C_ALPHA_BASE_LOC), mulmod(mload(Z_OMEGA_EVAL_LOC), mulmod(t1, t2, p), p), p)), + p + ) + + /** + * alpha_base *= alpha + * result += alpha_base . (L_{n-k}(ʓ) . (z(ʓ.ω) - ∆_{PI})) + * alpha_base *= alpha + * result += alpha_base . (L_1(ʓ)(Z(ʓ) - 1)) + * alpha_Base *= alpha + */ + mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p)) + result := + addmod( + result, + mulmod( + mload(C_ALPHA_BASE_LOC), + mulmod( + mload(L_END_LOC), + addmod(mload(Z_OMEGA_EVAL_LOC), sub(p, mload(PUBLIC_INPUT_DELTA_LOC)), p), + p + ), + p + ), + p + ) + mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p)) + mstore( + PERMUTATION_IDENTITY, + addmod( + result, + mulmod( + mload(C_ALPHA_BASE_LOC), + mulmod(mload(L_START_LOC), addmod(mload(Z_EVAL_LOC), sub(p, 1), p), p), + p + ), + p + ) + ) + mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p)) + } + + /** + * COMPUTE PLOOKUP WIDGET EVALUATION + */ + { + /** + * Goal: f = (w1(z) + q2.w1(zω)) + η(w2(z) + qm.w2(zω)) + η²(w3(z) + qc.w_3(zω)) + q3(z).η³ + * f = η.q3(z) + * f += (w3(z) + qc.w_3(zω)) + * f *= η + * f += (w2(z) + qm.w2(zω)) + * f *= η + * f += (w1(z) + q2.w1(zω)) + */ + let f := mulmod(mload(C_ETA_LOC), mload(Q3_EVAL_LOC), p) + f := + addmod(f, addmod(mload(W3_EVAL_LOC), mulmod(mload(QC_EVAL_LOC), mload(W3_OMEGA_EVAL_LOC), p), p), p) + f := mulmod(f, mload(C_ETA_LOC), p) + f := + addmod(f, addmod(mload(W2_EVAL_LOC), mulmod(mload(QM_EVAL_LOC), mload(W2_OMEGA_EVAL_LOC), p), p), p) + f := mulmod(f, mload(C_ETA_LOC), p) + f := + addmod(f, addmod(mload(W1_EVAL_LOC), mulmod(mload(Q2_EVAL_LOC), mload(W1_OMEGA_EVAL_LOC), p), p), p) + + // t(z) = table4(z).η³ + table3(z).η² + table2(z).η + table1(z) + let t := + addmod( + addmod( + addmod( + mulmod(mload(TABLE4_EVAL_LOC), mload(C_ETA_CUBE_LOC), p), + mulmod(mload(TABLE3_EVAL_LOC), mload(C_ETA_SQR_LOC), p), + p + ), + mulmod(mload(TABLE2_EVAL_LOC), mload(C_ETA_LOC), p), + p + ), + mload(TABLE1_EVAL_LOC), + p + ) + + // t(zw) = table4(zw).η³ + table3(zw).η² + table2(zw).η + table1(zw) + let t_omega := + addmod( + addmod( + addmod( + mulmod(mload(TABLE4_OMEGA_EVAL_LOC), mload(C_ETA_CUBE_LOC), p), + mulmod(mload(TABLE3_OMEGA_EVAL_LOC), mload(C_ETA_SQR_LOC), p), + p + ), + mulmod(mload(TABLE2_OMEGA_EVAL_LOC), mload(C_ETA_LOC), p), + p + ), + mload(TABLE1_OMEGA_EVAL_LOC), + p + ) + + /** + * Goal: numerator = (TABLE_TYPE_EVAL * f(z) + γ) * (t(z) + βt(zω) + γ(β + 1)) * (β + 1) + * gamma_beta_constant = γ(β + 1) + * numerator = f * TABLE_TYPE_EVAL + gamma + * temp0 = t(z) + t(zω) * β + gamma_beta_constant + * numerator *= temp0 + * numerator *= (β + 1) + * temp0 = alpha * l_1 + * numerator += temp0 + * numerator *= z_lookup(z) + * numerator -= temp0 + */ + let gamma_beta_constant := mulmod(mload(C_GAMMA_LOC), addmod(mload(C_BETA_LOC), 1, p), p) + let numerator := addmod(mulmod(f, mload(TABLE_TYPE_EVAL_LOC), p), mload(C_GAMMA_LOC), p) + let temp0 := addmod(addmod(t, mulmod(t_omega, mload(C_BETA_LOC), p), p), gamma_beta_constant, p) + numerator := mulmod(numerator, temp0, p) + numerator := mulmod(numerator, addmod(mload(C_BETA_LOC), 1, p), p) + temp0 := mulmod(mload(C_ALPHA_LOC), mload(L_START_LOC), p) + numerator := addmod(numerator, temp0, p) + numerator := mulmod(numerator, mload(Z_LOOKUP_EVAL_LOC), p) + numerator := addmod(numerator, sub(p, temp0), p) + + /** + * Goal: denominator = z_lookup(zω)*[s(z) + βs(zω) + γ(1 + β)] - [z_lookup(zω) - [γ(1 + β)]^{n-k}]*α²L_end(z) + * note: delta_factor = [γ(1 + β)]^{n-k} + * denominator = s(z) + βs(zω) + γ(β + 1) + * temp1 = α²L_end(z) + * denominator -= temp1 + * denominator *= z_lookup(zω) + * denominator += temp1 * delta_factor + * PLOOKUP_IDENTITY = (numerator - denominator).alpha_base + * alpha_base *= alpha^3 + */ + let denominator := + addmod( + addmod(mload(S_EVAL_LOC), mulmod(mload(S_OMEGA_EVAL_LOC), mload(C_BETA_LOC), p), p), + gamma_beta_constant, + p + ) + let temp1 := mulmod(mload(C_ALPHA_SQR_LOC), mload(L_END_LOC), p) + denominator := addmod(denominator, sub(p, temp1), p) + denominator := mulmod(denominator, mload(Z_LOOKUP_OMEGA_EVAL_LOC), p) + denominator := addmod(denominator, mulmod(temp1, mload(PLOOKUP_DELTA_LOC), p), p) + + mstore(PLOOKUP_IDENTITY, mulmod(addmod(numerator, sub(p, denominator), p), mload(C_ALPHA_BASE_LOC), p)) + + // update alpha + mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_CUBE_LOC), p)) + } + + /** + * COMPUTE ARITHMETIC WIDGET EVALUATION + */ + { + /** + * The basic arithmetic gate identity in standard plonk is as follows. + * (w_1 . w_2 . q_m) + (w_1 . q_1) + (w_2 . q_2) + (w_3 . q_3) + (w_4 . q_4) + q_c = 0 + * However, for Ultraplonk, we extend this to support "passing" wires between rows (shown without alpha scaling below): + * q_arith * ( ( (-1/2) * (q_arith - 3) * q_m * w_1 * w_2 + q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c ) + + * (q_arith - 1)*( α * (q_arith - 2) * (w_1 + w_4 - w_1_omega + q_m) + w_4_omega) ) = 0 + * + * This formula results in several cases depending on q_arith: + * 1. q_arith == 0: Arithmetic gate is completely disabled + * + * 2. q_arith == 1: Everything in the minigate on the right is disabled. The equation is just a standard plonk equation + * with extra wires: q_m * w_1 * w_2 + q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c = 0 + * + * 3. q_arith == 2: The (w_1 + w_4 - ...) term is disabled. THe equation is: + * (1/2) * q_m * w_1 * w_2 + q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c + w_4_omega = 0 + * It allows defining w_4 at next index (w_4_omega) in terms of current wire values + * + * 4. q_arith == 3: The product of w_1 and w_2 is disabled, but a mini addition gate is enabled. α allows us to split + * the equation into two: + * + * q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c + 2 * w_4_omega = 0 + * and + * w_1 + w_4 - w_1_omega + q_m = 0 (we are reusing q_m here) + * + * 5. q_arith > 3: The product of w_1 and w_2 is scaled by (q_arith - 3), while the w_4_omega term is scaled by (q_arith - 1). + * The equation can be split into two: + * + * (q_arith - 3)* q_m * w_1 * w_ 2 + q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c + (q_arith - 1) * w_4_omega = 0 + * and + * w_1 + w_4 - w_1_omega + q_m = 0 + * + * The problem that q_m is used both in both equations can be dealt with by appropriately changing selector values at + * the next gate. Then we can treat (q_arith - 1) as a simulated q_6 selector and scale q_m to handle (q_arith - 3) at + * product. + */ + + let w1q1 := mulmod(mload(W1_EVAL_LOC), mload(Q1_EVAL_LOC), p) + let w2q2 := mulmod(mload(W2_EVAL_LOC), mload(Q2_EVAL_LOC), p) + let w3q3 := mulmod(mload(W3_EVAL_LOC), mload(Q3_EVAL_LOC), p) + let w4q3 := mulmod(mload(W4_EVAL_LOC), mload(Q4_EVAL_LOC), p) + + // @todo - Add a explicit test that hits QARITH == 3 + // w1w2qm := (w_1 . w_2 . q_m . (QARITH_EVAL_LOC - 3)) / 2 + let w1w2qm := + mulmod( + mulmod( + mulmod(mulmod(mload(W1_EVAL_LOC), mload(W2_EVAL_LOC), p), mload(QM_EVAL_LOC), p), + addmod(mload(QARITH_EVAL_LOC), sub(p, 3), p), + p + ), + NEGATIVE_INVERSE_OF_2_MODULO_P, + p + ) + + // (w_1 . w_2 . q_m . (q_arith - 3)) / -2) + (w_1 . q_1) + (w_2 . q_2) + (w_3 . q_3) + (w_4 . q_4) + q_c + let identity := + addmod( + mload(QC_EVAL_LOC), addmod(w4q3, addmod(w3q3, addmod(w2q2, addmod(w1q1, w1w2qm, p), p), p), p), p + ) + + // if q_arith == 3 we evaluate an additional mini addition gate (on top of the regular one), where: + // w_1 + w_4 - w_1_omega + q_m = 0 + // we use this gate to save an addition gate when adding or subtracting non-native field elements + // α * (q_arith - 2) * (w_1 + w_4 - w_1_omega + q_m) + let extra_small_addition_gate_identity := + mulmod( + mload(C_ALPHA_LOC), + mulmod( + addmod(mload(QARITH_EVAL_LOC), sub(p, 2), p), + addmod( + mload(QM_EVAL_LOC), + addmod( + sub(p, mload(W1_OMEGA_EVAL_LOC)), addmod(mload(W1_EVAL_LOC), mload(W4_EVAL_LOC), p), p + ), + p + ), + p + ), + p + ) + + // if q_arith == 2 OR q_arith == 3 we add the 4th wire of the NEXT gate into the arithmetic identity + // N.B. if q_arith > 2, this wire value will be scaled by (q_arith - 1) relative to the other gate wires! + // alpha_base * q_arith * (identity + (q_arith - 1) * (w_4_omega + extra_small_addition_gate_identity)) + mstore( + ARITHMETIC_IDENTITY, + mulmod( + mload(C_ALPHA_BASE_LOC), + mulmod( + mload(QARITH_EVAL_LOC), + addmod( + identity, + mulmod( + addmod(mload(QARITH_EVAL_LOC), sub(p, 1), p), + addmod(mload(W4_OMEGA_EVAL_LOC), extra_small_addition_gate_identity, p), + p + ), + p + ), + p + ), + p + ) + ) + + // update alpha + mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_SQR_LOC), p)) + } + + /** + * COMPUTE GENPERMSORT WIDGET EVALUATION + */ + { + /** + * D1 = (w2 - w1) + * D2 = (w3 - w2) + * D3 = (w4 - w3) + * D4 = (w1_omega - w4) + * + * α_a = alpha_base + * α_b = alpha_base * α + * α_c = alpha_base * α^2 + * α_d = alpha_base * α^3 + * + * range_accumulator = ( + * D1(D1 - 1)(D1 - 2)(D1 - 3).α_a + + * D2(D2 - 1)(D2 - 2)(D2 - 3).α_b + + * D3(D3 - 1)(D3 - 2)(D3 - 3).α_c + + * D4(D4 - 1)(D4 - 2)(D4 - 3).α_d + + * ) . q_sort + */ + let minus_two := sub(p, 2) + let minus_three := sub(p, 3) + let d1 := addmod(mload(W2_EVAL_LOC), sub(p, mload(W1_EVAL_LOC)), p) + let d2 := addmod(mload(W3_EVAL_LOC), sub(p, mload(W2_EVAL_LOC)), p) + let d3 := addmod(mload(W4_EVAL_LOC), sub(p, mload(W3_EVAL_LOC)), p) + let d4 := addmod(mload(W1_OMEGA_EVAL_LOC), sub(p, mload(W4_EVAL_LOC)), p) + + let range_accumulator := + mulmod( + mulmod( + mulmod(addmod(mulmod(d1, d1, p), sub(p, d1), p), addmod(d1, minus_two, p), p), + addmod(d1, minus_three, p), + p + ), + mload(C_ALPHA_BASE_LOC), + p + ) + range_accumulator := + addmod( + range_accumulator, + mulmod( + mulmod( + mulmod(addmod(mulmod(d2, d2, p), sub(p, d2), p), addmod(d2, minus_two, p), p), + addmod(d2, minus_three, p), + p + ), + mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p), + p + ), + p + ) + range_accumulator := + addmod( + range_accumulator, + mulmod( + mulmod( + mulmod(addmod(mulmod(d3, d3, p), sub(p, d3), p), addmod(d3, minus_two, p), p), + addmod(d3, minus_three, p), + p + ), + mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_SQR_LOC), p), + p + ), + p + ) + range_accumulator := + addmod( + range_accumulator, + mulmod( + mulmod( + mulmod(addmod(mulmod(d4, d4, p), sub(p, d4), p), addmod(d4, minus_two, p), p), + addmod(d4, minus_three, p), + p + ), + mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_CUBE_LOC), p), + p + ), + p + ) + range_accumulator := mulmod(range_accumulator, mload(QSORT_EVAL_LOC), p) + + mstore(SORT_IDENTITY, range_accumulator) + + // update alpha + mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_QUAD_LOC), p)) + } + + /** + * COMPUTE ELLIPTIC WIDGET EVALUATION + */ + { + /** + * endo_term = (-x_2) * x_1 * (x_3 * 2 + x_1) * q_beta + * endo_sqr_term = x_2^2 + * endo_sqr_term *= (x_3 - x_1) + * endo_sqr_term *= q_beta^2 + * leftovers = x_2^2 + * leftovers *= x_2 + * leftovers += x_1^2 * (x_3 + x_1) @follow-up Invalid comment in BB widget + * leftovers -= (y_2^2 + y_1^2) + * sign_term = y_2 * y_1 + * sign_term += sign_term + * sign_term *= q_sign + */ + // q_elliptic * (x3 + x2 + x1)(x2 - x1)(x2 - x1) - y2^2 - y1^2 + 2(y2y1)*q_sign = 0 + let x_diff := addmod(mload(X2_EVAL_LOC), sub(p, mload(X1_EVAL_LOC)), p) + let y2_sqr := mulmod(mload(Y2_EVAL_LOC), mload(Y2_EVAL_LOC), p) + let y1_sqr := mulmod(mload(Y1_EVAL_LOC), mload(Y1_EVAL_LOC), p) + let y1y2 := mulmod(mulmod(mload(Y1_EVAL_LOC), mload(Y2_EVAL_LOC), p), mload(QSIGN_LOC), p) + + let x_add_identity := + addmod( + mulmod( + addmod(mload(X3_EVAL_LOC), addmod(mload(X2_EVAL_LOC), mload(X1_EVAL_LOC), p), p), + mulmod(x_diff, x_diff, p), + p + ), + addmod( + sub( + p, + addmod(y2_sqr, y1_sqr, p) + ), + addmod(y1y2, y1y2, p), + p + ), + p + ) + x_add_identity := + mulmod( + mulmod( + x_add_identity, + addmod( + 1, + sub(p, mload(QM_EVAL_LOC)), + p + ), + p + ), + mload(C_ALPHA_BASE_LOC), + p + ) + + // q_elliptic * (x3 + x2 + x1)(x2 - x1)(x2 - x1) - y2^2 - y1^2 + 2(y2y1)*q_sign = 0 + let y1_plus_y3 := addmod( + mload(Y1_EVAL_LOC), + mload(Y3_EVAL_LOC), + p + ) + let y_diff := addmod(mulmod(mload(Y2_EVAL_LOC), mload(QSIGN_LOC), p), sub(p, mload(Y1_EVAL_LOC)), p) + let y_add_identity := + addmod( + mulmod(y1_plus_y3, x_diff, p), + mulmod(addmod(mload(X3_EVAL_LOC), sub(p, mload(X1_EVAL_LOC)), p), y_diff, p), + p + ) + y_add_identity := + mulmod( + mulmod(y_add_identity, addmod(1, sub(p, mload(QM_EVAL_LOC)), p), p), + mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p), + p + ) + + // ELLIPTIC_IDENTITY = (x_identity + y_identity) * Q_ELLIPTIC_EVAL + mstore( + ELLIPTIC_IDENTITY, mulmod(addmod(x_add_identity, y_add_identity, p), mload(QELLIPTIC_EVAL_LOC), p) + ) + } + { + /** + * x_pow_4 = (y_1_sqr - curve_b) * x_1; + * y_1_sqr_mul_4 = y_1_sqr + y_1_sqr; + * y_1_sqr_mul_4 += y_1_sqr_mul_4; + * x_1_pow_4_mul_9 = x_pow_4; + * x_1_pow_4_mul_9 += x_1_pow_4_mul_9; + * x_1_pow_4_mul_9 += x_1_pow_4_mul_9; + * x_1_pow_4_mul_9 += x_1_pow_4_mul_9; + * x_1_pow_4_mul_9 += x_pow_4; + * x_1_sqr_mul_3 = x_1_sqr + x_1_sqr + x_1_sqr; + * x_double_identity = (x_3 + x_1 + x_1) * y_1_sqr_mul_4 - x_1_pow_4_mul_9; + * y_double_identity = x_1_sqr_mul_3 * (x_1 - x_3) - (y_1 + y_1) * (y_1 + y_3); + */ + // (x3 + x1 + x1) (4y1*y1) - 9 * x1 * x1 * x1 * x1 = 0 + let x1_sqr := mulmod(mload(X1_EVAL_LOC), mload(X1_EVAL_LOC), p) + let y1_sqr := mulmod(mload(Y1_EVAL_LOC), mload(Y1_EVAL_LOC), p) + let x_pow_4 := mulmod(addmod(y1_sqr, GRUMPKIN_CURVE_B_PARAMETER_NEGATED, p), mload(X1_EVAL_LOC), p) + let y1_sqr_mul_4 := mulmod(y1_sqr, 4, p) + let x1_pow_4_mul_9 := mulmod(x_pow_4, 9, p) + let x1_sqr_mul_3 := mulmod(x1_sqr, 3, p) + let x_double_identity := + addmod( + mulmod( + addmod(mload(X3_EVAL_LOC), addmod(mload(X1_EVAL_LOC), mload(X1_EVAL_LOC), p), p), + y1_sqr_mul_4, + p + ), + sub(p, x1_pow_4_mul_9), + p + ) + // (y1 + y1) (2y1) - (3 * x1 * x1)(x1 - x3) = 0 + let y_double_identity := + addmod( + mulmod(x1_sqr_mul_3, addmod(mload(X1_EVAL_LOC), sub(p, mload(X3_EVAL_LOC)), p), p), + sub( + p, + mulmod( + addmod(mload(Y1_EVAL_LOC), mload(Y1_EVAL_LOC), p), + addmod(mload(Y1_EVAL_LOC), mload(Y3_EVAL_LOC), p), + p + ) + ), + p + ) + x_double_identity := mulmod(x_double_identity, mload(C_ALPHA_BASE_LOC), p) + y_double_identity := + mulmod(y_double_identity, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p), p) + x_double_identity := mulmod(x_double_identity, mload(QM_EVAL_LOC), p) + y_double_identity := mulmod(y_double_identity, mload(QM_EVAL_LOC), p) + // ELLIPTIC_IDENTITY += (x_double_identity + y_double_identity) * Q_DOUBLE_EVAL + mstore( + ELLIPTIC_IDENTITY, + addmod( + mload(ELLIPTIC_IDENTITY), + mulmod(addmod(x_double_identity, y_double_identity, p), mload(QELLIPTIC_EVAL_LOC), p), + p + ) + ) + + // update alpha + mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_QUAD_LOC), p)) + } + + /** + * COMPUTE AUXILIARY WIDGET EVALUATION + */ + { + { + /** + * Non native field arithmetic gate 2 + * _ _ + * / _ _ _ 14 \ + * q_2 . q_4 | (w_1 . w_2) + (w_1 . w_2) + (w_1 . w_4 + w_2 . w_3 - w_3) . 2 - w_3 - w_4 | + * \_ _/ + * + * limb_subproduct = w_1 . w_2_omega + w_1_omega . w_2 + * non_native_field_gate_2 = w_1 * w_4 + w_4 * w_3 - w_3_omega + * non_native_field_gate_2 = non_native_field_gate_2 * limb_size + * non_native_field_gate_2 -= w_4_omega + * non_native_field_gate_2 += limb_subproduct + * non_native_field_gate_2 *= q_4 + * limb_subproduct *= limb_size + * limb_subproduct += w_1_omega * w_2_omega + * non_native_field_gate_1 = (limb_subproduct + w_3 + w_4) * q_3 + * non_native_field_gate_3 = (limb_subproduct + w_4 - (w_3_omega + w_4_omega)) * q_m + * non_native_field_identity = (non_native_field_gate_1 + non_native_field_gate_2 + non_native_field_gate_3) * q_2 + */ + + let limb_subproduct := + addmod( + mulmod(mload(W1_EVAL_LOC), mload(W2_OMEGA_EVAL_LOC), p), + mulmod(mload(W1_OMEGA_EVAL_LOC), mload(W2_EVAL_LOC), p), + p + ) + + let non_native_field_gate_2 := + addmod( + addmod( + mulmod(mload(W1_EVAL_LOC), mload(W4_EVAL_LOC), p), + mulmod(mload(W2_EVAL_LOC), mload(W3_EVAL_LOC), p), + p + ), + sub(p, mload(W3_OMEGA_EVAL_LOC)), + p + ) + non_native_field_gate_2 := mulmod(non_native_field_gate_2, LIMB_SIZE, p) + non_native_field_gate_2 := addmod(non_native_field_gate_2, sub(p, mload(W4_OMEGA_EVAL_LOC)), p) + non_native_field_gate_2 := addmod(non_native_field_gate_2, limb_subproduct, p) + non_native_field_gate_2 := mulmod(non_native_field_gate_2, mload(Q4_EVAL_LOC), p) + limb_subproduct := mulmod(limb_subproduct, LIMB_SIZE, p) + limb_subproduct := + addmod(limb_subproduct, mulmod(mload(W1_OMEGA_EVAL_LOC), mload(W2_OMEGA_EVAL_LOC), p), p) + let non_native_field_gate_1 := + mulmod( + addmod(limb_subproduct, sub(p, addmod(mload(W3_EVAL_LOC), mload(W4_EVAL_LOC), p)), p), + mload(Q3_EVAL_LOC), + p + ) + let non_native_field_gate_3 := + mulmod( + addmod( + addmod(limb_subproduct, mload(W4_EVAL_LOC), p), + sub(p, addmod(mload(W3_OMEGA_EVAL_LOC), mload(W4_OMEGA_EVAL_LOC), p)), + p + ), + mload(QM_EVAL_LOC), + p + ) + let non_native_field_identity := + mulmod( + addmod(addmod(non_native_field_gate_1, non_native_field_gate_2, p), non_native_field_gate_3, p), + mload(Q2_EVAL_LOC), + p + ) + + mstore(AUX_NON_NATIVE_FIELD_EVALUATION, non_native_field_identity) + } + + { + /** + * limb_accumulator_1 = w_2_omega; + * limb_accumulator_1 *= SUBLIMB_SHIFT; + * limb_accumulator_1 += w_1_omega; + * limb_accumulator_1 *= SUBLIMB_SHIFT; + * limb_accumulator_1 += w_3; + * limb_accumulator_1 *= SUBLIMB_SHIFT; + * limb_accumulator_1 += w_2; + * limb_accumulator_1 *= SUBLIMB_SHIFT; + * limb_accumulator_1 += w_1; + * limb_accumulator_1 -= w_4; + * limb_accumulator_1 *= q_4; + */ + let limb_accumulator_1 := mulmod(mload(W2_OMEGA_EVAL_LOC), SUBLIMB_SHIFT, p) + limb_accumulator_1 := addmod(limb_accumulator_1, mload(W1_OMEGA_EVAL_LOC), p) + limb_accumulator_1 := mulmod(limb_accumulator_1, SUBLIMB_SHIFT, p) + limb_accumulator_1 := addmod(limb_accumulator_1, mload(W3_EVAL_LOC), p) + limb_accumulator_1 := mulmod(limb_accumulator_1, SUBLIMB_SHIFT, p) + limb_accumulator_1 := addmod(limb_accumulator_1, mload(W2_EVAL_LOC), p) + limb_accumulator_1 := mulmod(limb_accumulator_1, SUBLIMB_SHIFT, p) + limb_accumulator_1 := addmod(limb_accumulator_1, mload(W1_EVAL_LOC), p) + limb_accumulator_1 := addmod(limb_accumulator_1, sub(p, mload(W4_EVAL_LOC)), p) + limb_accumulator_1 := mulmod(limb_accumulator_1, mload(Q4_EVAL_LOC), p) + + /** + * limb_accumulator_2 = w_3_omega; + * limb_accumulator_2 *= SUBLIMB_SHIFT; + * limb_accumulator_2 += w_2_omega; + * limb_accumulator_2 *= SUBLIMB_SHIFT; + * limb_accumulator_2 += w_1_omega; + * limb_accumulator_2 *= SUBLIMB_SHIFT; + * limb_accumulator_2 += w_4; + * limb_accumulator_2 *= SUBLIMB_SHIFT; + * limb_accumulator_2 += w_3; + * limb_accumulator_2 -= w_4_omega; + * limb_accumulator_2 *= q_m; + */ + let limb_accumulator_2 := mulmod(mload(W3_OMEGA_EVAL_LOC), SUBLIMB_SHIFT, p) + limb_accumulator_2 := addmod(limb_accumulator_2, mload(W2_OMEGA_EVAL_LOC), p) + limb_accumulator_2 := mulmod(limb_accumulator_2, SUBLIMB_SHIFT, p) + limb_accumulator_2 := addmod(limb_accumulator_2, mload(W1_OMEGA_EVAL_LOC), p) + limb_accumulator_2 := mulmod(limb_accumulator_2, SUBLIMB_SHIFT, p) + limb_accumulator_2 := addmod(limb_accumulator_2, mload(W4_EVAL_LOC), p) + limb_accumulator_2 := mulmod(limb_accumulator_2, SUBLIMB_SHIFT, p) + limb_accumulator_2 := addmod(limb_accumulator_2, mload(W3_EVAL_LOC), p) + limb_accumulator_2 := addmod(limb_accumulator_2, sub(p, mload(W4_OMEGA_EVAL_LOC)), p) + limb_accumulator_2 := mulmod(limb_accumulator_2, mload(QM_EVAL_LOC), p) + + mstore( + AUX_LIMB_ACCUMULATOR_EVALUATION, + mulmod(addmod(limb_accumulator_1, limb_accumulator_2, p), mload(Q3_EVAL_LOC), p) + ) + } + + { + /** + * memory_record_check = w_3; + * memory_record_check *= eta; + * memory_record_check += w_2; + * memory_record_check *= eta; + * memory_record_check += w_1; + * memory_record_check *= eta; + * memory_record_check += q_c; + * + * partial_record_check = memory_record_check; + * + * memory_record_check -= w_4; + */ + + let memory_record_check := mulmod(mload(W3_EVAL_LOC), mload(C_ETA_LOC), p) + memory_record_check := addmod(memory_record_check, mload(W2_EVAL_LOC), p) + memory_record_check := mulmod(memory_record_check, mload(C_ETA_LOC), p) + memory_record_check := addmod(memory_record_check, mload(W1_EVAL_LOC), p) + memory_record_check := mulmod(memory_record_check, mload(C_ETA_LOC), p) + memory_record_check := addmod(memory_record_check, mload(QC_EVAL_LOC), p) + + let partial_record_check := memory_record_check + memory_record_check := addmod(memory_record_check, sub(p, mload(W4_EVAL_LOC)), p) + + mstore(AUX_MEMORY_EVALUATION, memory_record_check) + + // index_delta = w_1_omega - w_1 + let index_delta := addmod(mload(W1_OMEGA_EVAL_LOC), sub(p, mload(W1_EVAL_LOC)), p) + // record_delta = w_4_omega - w_4 + let record_delta := addmod(mload(W4_OMEGA_EVAL_LOC), sub(p, mload(W4_EVAL_LOC)), p) + // index_is_monotonically_increasing = index_delta * (index_delta - 1) + let index_is_monotonically_increasing := mulmod(index_delta, addmod(index_delta, sub(p, 1), p), p) + + // adjacent_values_match_if_adjacent_indices_match = record_delta * (1 - index_delta) + let adjacent_values_match_if_adjacent_indices_match := + mulmod(record_delta, addmod(1, sub(p, index_delta), p), p) + + // AUX_ROM_CONSISTENCY_EVALUATION = ((adjacent_values_match_if_adjacent_indices_match * alpha) + index_is_monotonically_increasing) * alpha + partial_record_check + mstore( + AUX_ROM_CONSISTENCY_EVALUATION, + addmod( + mulmod( + addmod( + mulmod(adjacent_values_match_if_adjacent_indices_match, mload(C_ALPHA_LOC), p), + index_is_monotonically_increasing, + p + ), + mload(C_ALPHA_LOC), + p + ), + memory_record_check, + p + ) + ) + + { + /** + * next_gate_access_type = w_3_omega; + * next_gate_access_type *= eta; + * next_gate_access_type += w_2_omega; + * next_gate_access_type *= eta; + * next_gate_access_type += w_1_omega; + * next_gate_access_type *= eta; + * next_gate_access_type = w_4_omega - next_gate_access_type; + */ + let next_gate_access_type := mulmod(mload(W3_OMEGA_EVAL_LOC), mload(C_ETA_LOC), p) + next_gate_access_type := addmod(next_gate_access_type, mload(W2_OMEGA_EVAL_LOC), p) + next_gate_access_type := mulmod(next_gate_access_type, mload(C_ETA_LOC), p) + next_gate_access_type := addmod(next_gate_access_type, mload(W1_OMEGA_EVAL_LOC), p) + next_gate_access_type := mulmod(next_gate_access_type, mload(C_ETA_LOC), p) + next_gate_access_type := addmod(mload(W4_OMEGA_EVAL_LOC), sub(p, next_gate_access_type), p) + + // value_delta = w_3_omega - w_3 + let value_delta := addmod(mload(W3_OMEGA_EVAL_LOC), sub(p, mload(W3_EVAL_LOC)), p) + // adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation = (1 - index_delta) * value_delta * (1 - next_gate_access_type); + + let adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation := + mulmod( + addmod(1, sub(p, index_delta), p), + mulmod(value_delta, addmod(1, sub(p, next_gate_access_type), p), p), + p + ) + + // AUX_RAM_CONSISTENCY_EVALUATION + + /** + * access_type = w_4 - partial_record_check + * access_check = access_type^2 - access_type + * next_gate_access_type_is_boolean = next_gate_access_type^2 - next_gate_access_type + * RAM_consistency_check_identity = adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation; + * RAM_consistency_check_identity *= alpha; + * RAM_consistency_check_identity += index_is_monotonically_increasing; + * RAM_consistency_check_identity *= alpha; + * RAM_consistency_check_identity += next_gate_access_type_is_boolean; + * RAM_consistency_check_identity *= alpha; + * RAM_consistency_check_identity += access_check; + */ + + let access_type := addmod(mload(W4_EVAL_LOC), sub(p, partial_record_check), p) + let access_check := mulmod(access_type, addmod(access_type, sub(p, 1), p), p) + let next_gate_access_type_is_boolean := + mulmod(next_gate_access_type, addmod(next_gate_access_type, sub(p, 1), p), p) + let RAM_cci := + mulmod( + adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation, + mload(C_ALPHA_LOC), + p + ) + RAM_cci := addmod(RAM_cci, index_is_monotonically_increasing, p) + RAM_cci := mulmod(RAM_cci, mload(C_ALPHA_LOC), p) + RAM_cci := addmod(RAM_cci, next_gate_access_type_is_boolean, p) + RAM_cci := mulmod(RAM_cci, mload(C_ALPHA_LOC), p) + RAM_cci := addmod(RAM_cci, access_check, p) + + mstore(AUX_RAM_CONSISTENCY_EVALUATION, RAM_cci) + } + + { + // timestamp_delta = w_2_omega - w_2 + let timestamp_delta := addmod(mload(W2_OMEGA_EVAL_LOC), sub(p, mload(W2_EVAL_LOC)), p) + + // RAM_timestamp_check_identity = (1 - index_delta) * timestamp_delta - w_3 + let RAM_timestamp_check_identity := + addmod( + mulmod(timestamp_delta, addmod(1, sub(p, index_delta), p), p), sub(p, mload(W3_EVAL_LOC)), p + ) + + /** + * memory_identity = ROM_consistency_check_identity * q_2; + * memory_identity += RAM_timestamp_check_identity * q_4; + * memory_identity += memory_record_check * q_m; + * memory_identity *= q_1; + * memory_identity += (RAM_consistency_check_identity * q_arith); + * + * auxiliary_identity = memory_identity + non_native_field_identity + limb_accumulator_identity; + * auxiliary_identity *= q_aux; + * auxiliary_identity *= alpha_base; + */ + let memory_identity := mulmod(mload(AUX_ROM_CONSISTENCY_EVALUATION), mload(Q2_EVAL_LOC), p) + memory_identity := + addmod(memory_identity, mulmod(RAM_timestamp_check_identity, mload(Q4_EVAL_LOC), p), p) + memory_identity := + addmod(memory_identity, mulmod(mload(AUX_MEMORY_EVALUATION), mload(QM_EVAL_LOC), p), p) + memory_identity := mulmod(memory_identity, mload(Q1_EVAL_LOC), p) + memory_identity := + addmod( + memory_identity, mulmod(mload(AUX_RAM_CONSISTENCY_EVALUATION), mload(QARITH_EVAL_LOC), p), p + ) + + let auxiliary_identity := addmod(memory_identity, mload(AUX_NON_NATIVE_FIELD_EVALUATION), p) + auxiliary_identity := addmod(auxiliary_identity, mload(AUX_LIMB_ACCUMULATOR_EVALUATION), p) + auxiliary_identity := mulmod(auxiliary_identity, mload(QAUX_EVAL_LOC), p) + auxiliary_identity := mulmod(auxiliary_identity, mload(C_ALPHA_BASE_LOC), p) + + mstore(AUX_IDENTITY, auxiliary_identity) + + // update alpha + mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_CUBE_LOC), p)) + } + } + } + + { + /** + * quotient = ARITHMETIC_IDENTITY + * quotient += PERMUTATION_IDENTITY + * quotient += PLOOKUP_IDENTITY + * quotient += SORT_IDENTITY + * quotient += ELLIPTIC_IDENTITY + * quotient += AUX_IDENTITY + * quotient *= ZERO_POLY_INVERSE + */ + mstore( + QUOTIENT_EVAL_LOC, + mulmod( + addmod( + addmod( + addmod( + addmod( + addmod(mload(PERMUTATION_IDENTITY), mload(PLOOKUP_IDENTITY), p), + mload(ARITHMETIC_IDENTITY), + p + ), + mload(SORT_IDENTITY), + p + ), + mload(ELLIPTIC_IDENTITY), + p + ), + mload(AUX_IDENTITY), + p + ), + mload(ZERO_POLY_INVERSE_LOC), + p + ) + ) + } + + /** + * GENERATE NU AND SEPARATOR CHALLENGES + */ + { + let current_challenge := mload(C_CURRENT_LOC) + // get a calldata pointer that points to the start of the data we want to copy + let calldata_ptr := add(calldataload(0x04), 0x24) + + calldata_ptr := add(calldata_ptr, NU_CALLDATA_SKIP_LENGTH) + + mstore(NU_CHALLENGE_INPUT_LOC_A, current_challenge) + mstore(NU_CHALLENGE_INPUT_LOC_B, mload(QUOTIENT_EVAL_LOC)) + calldatacopy(NU_CHALLENGE_INPUT_LOC_C, calldata_ptr, NU_INPUT_LENGTH) + + // hash length = (0x20 + num field elements), we include the previous challenge in the hash + let challenge := keccak256(NU_CHALLENGE_INPUT_LOC_A, add(NU_INPUT_LENGTH, 0x40)) + + mstore(C_V0_LOC, mod(challenge, p)) + // We need THIRTY-ONE independent nu challenges! + mstore(0x00, challenge) + mstore8(0x20, 0x01) + mstore(C_V1_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x02) + mstore(C_V2_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x03) + mstore(C_V3_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x04) + mstore(C_V4_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x05) + mstore(C_V5_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x06) + mstore(C_V6_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x07) + mstore(C_V7_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x08) + mstore(C_V8_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x09) + mstore(C_V9_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x0a) + mstore(C_V10_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x0b) + mstore(C_V11_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x0c) + mstore(C_V12_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x0d) + mstore(C_V13_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x0e) + mstore(C_V14_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x0f) + mstore(C_V15_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x10) + mstore(C_V16_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x11) + mstore(C_V17_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x12) + mstore(C_V18_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x13) + mstore(C_V19_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x14) + mstore(C_V20_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x15) + mstore(C_V21_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x16) + mstore(C_V22_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x17) + mstore(C_V23_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x18) + mstore(C_V24_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x19) + mstore(C_V25_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x1a) + mstore(C_V26_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x1b) + mstore(C_V27_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x1c) + mstore(C_V28_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x1d) + mstore(C_V29_LOC, mod(keccak256(0x00, 0x21), p)) + + // @follow-up - Why are both v29 and v30 using appending 0x1d to the prior challenge and hashing, should it not change? + mstore8(0x20, 0x1d) + challenge := keccak256(0x00, 0x21) + mstore(C_V30_LOC, mod(challenge, p)) + + // separator + mstore(0x00, challenge) + mstore(0x20, mload(PI_Z_Y_LOC)) + mstore(0x40, mload(PI_Z_X_LOC)) + mstore(0x60, mload(PI_Z_OMEGA_Y_LOC)) + mstore(0x80, mload(PI_Z_OMEGA_X_LOC)) + + mstore(C_U_LOC, mod(keccak256(0x00, 0xa0), p)) + } + + let success := 0 + // VALIDATE T1 + { + let x := mload(T1_X_LOC) + let y := mload(T1_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(ACCUMULATOR_X_LOC, x) + mstore(add(ACCUMULATOR_X_LOC, 0x20), y) + } + // VALIDATE T2 + { + let x := mload(T2_X_LOC) // 0x1400 + let y := mload(T2_Y_LOC) // 0x1420 + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(ZETA_POW_N_LOC)) + // accumulator_2 = [T2].zeta^n + success := staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40) + // accumulator = [T1] + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE T3 + { + let x := mload(T3_X_LOC) + let y := mload(T3_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(mload(ZETA_POW_N_LOC), mload(ZETA_POW_N_LOC), p)) + // accumulator_2 = [T3].zeta^{2n} + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE T4 + { + let x := mload(T4_X_LOC) + let y := mload(T4_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(mulmod(mload(ZETA_POW_N_LOC), mload(ZETA_POW_N_LOC), p), mload(ZETA_POW_N_LOC), p)) + // accumulator_2 = [T4].zeta^{3n} + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE W1 + { + let x := mload(W1_X_LOC) + let y := mload(W1_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V0_LOC), p)) + // accumulator_2 = v0.(u + 1).[W1] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE W2 + { + let x := mload(W2_X_LOC) + let y := mload(W2_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V1_LOC), p)) + // accumulator_2 = v1.(u + 1).[W2] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE W3 + { + let x := mload(W3_X_LOC) + let y := mload(W3_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V2_LOC), p)) + // accumulator_2 = v2.(u + 1).[W3] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE W4 + { + let x := mload(W4_X_LOC) + let y := mload(W4_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V3_LOC), p)) + // accumulator_2 = v3.(u + 1).[W4] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE S + { + let x := mload(S_X_LOC) + let y := mload(S_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V4_LOC), p)) + // accumulator_2 = v4.(u + 1).[S] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE Z + { + let x := mload(Z_X_LOC) + let y := mload(Z_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V5_LOC), p)) + // accumulator_2 = v5.(u + 1).[Z] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE Z_LOOKUP + { + let x := mload(Z_LOOKUP_X_LOC) + let y := mload(Z_LOOKUP_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V6_LOC), p)) + // accumulator_2 = v6.(u + 1).[Z_LOOKUP] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE Q1 + { + let x := mload(Q1_X_LOC) + let y := mload(Q1_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V7_LOC)) + // accumulator_2 = v7.[Q1] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE Q2 + { + let x := mload(Q2_X_LOC) + let y := mload(Q2_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V8_LOC)) + // accumulator_2 = v8.[Q2] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE Q3 + { + let x := mload(Q3_X_LOC) + let y := mload(Q3_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V9_LOC)) + // accumulator_2 = v9.[Q3] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE Q4 + { + let x := mload(Q4_X_LOC) + let y := mload(Q4_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V10_LOC)) + // accumulator_2 = v10.[Q4] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE QM + { + let x := mload(QM_X_LOC) + let y := mload(QM_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V11_LOC)) + // accumulator_2 = v11.[Q;] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE QC + { + let x := mload(QC_X_LOC) + let y := mload(QC_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V12_LOC)) + // accumulator_2 = v12.[QC] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE QARITH + { + let x := mload(QARITH_X_LOC) + let y := mload(QARITH_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V13_LOC)) + // accumulator_2 = v13.[QARITH] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE QSORT + { + let x := mload(QSORT_X_LOC) + let y := mload(QSORT_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V14_LOC)) + // accumulator_2 = v14.[QSORT] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE QELLIPTIC + { + let x := mload(QELLIPTIC_X_LOC) + let y := mload(QELLIPTIC_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V15_LOC)) + // accumulator_2 = v15.[QELLIPTIC] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE QAUX + { + let x := mload(QAUX_X_LOC) + let y := mload(QAUX_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V16_LOC)) + // accumulator_2 = v15.[Q_AUX] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE SIGMA1 + { + let x := mload(SIGMA1_X_LOC) + let y := mload(SIGMA1_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V17_LOC)) + // accumulator_2 = v17.[sigma1] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE SIGMA2 + { + let x := mload(SIGMA2_X_LOC) + let y := mload(SIGMA2_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V18_LOC)) + // accumulator_2 = v18.[sigma2] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE SIGMA3 + { + let x := mload(SIGMA3_X_LOC) + let y := mload(SIGMA3_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V19_LOC)) + // accumulator_2 = v19.[sigma3] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE SIGMA4 + { + let x := mload(SIGMA4_X_LOC) + let y := mload(SIGMA4_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V20_LOC)) + // accumulator_2 = v20.[sigma4] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE TABLE1 + { + let x := mload(TABLE1_X_LOC) + let y := mload(TABLE1_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V21_LOC), p)) + // accumulator_2 = u.[table1] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE TABLE2 + { + let x := mload(TABLE2_X_LOC) + let y := mload(TABLE2_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V22_LOC), p)) + // accumulator_2 = u.[table2] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE TABLE3 + { + let x := mload(TABLE3_X_LOC) + let y := mload(TABLE3_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V23_LOC), p)) + // accumulator_2 = u.[table3] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE TABLE4 + { + let x := mload(TABLE4_X_LOC) + let y := mload(TABLE4_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V24_LOC), p)) + // accumulator_2 = u.[table4] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE TABLE_TYPE + { + let x := mload(TABLE_TYPE_X_LOC) + let y := mload(TABLE_TYPE_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V25_LOC)) + // accumulator_2 = v25.[TableType] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE ID1 + { + let x := mload(ID1_X_LOC) + let y := mload(ID1_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V26_LOC)) + // accumulator_2 = v26.[ID1] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE ID2 + { + let x := mload(ID2_X_LOC) + let y := mload(ID2_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V27_LOC)) + // accumulator_2 = v27.[ID2] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE ID3 + { + let x := mload(ID3_X_LOC) + let y := mload(ID3_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V28_LOC)) + // accumulator_2 = v28.[ID3] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE ID4 + { + let x := mload(ID4_X_LOC) + let y := mload(ID4_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V29_LOC)) + // accumulator_2 = v29.[ID4] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + /** + * COMPUTE BATCH EVALUATION SCALAR MULTIPLIER + */ + { + /** + * batch_evaluation = v0 * (w_1_omega * u + w_1_eval) + * batch_evaluation += v1 * (w_2_omega * u + w_2_eval) + * batch_evaluation += v2 * (w_3_omega * u + w_3_eval) + * batch_evaluation += v3 * (w_4_omega * u + w_4_eval) + * batch_evaluation += v4 * (s_omega_eval * u + s_eval) + * batch_evaluation += v5 * (z_omega_eval * u + z_eval) + * batch_evaluation += v6 * (z_lookup_omega_eval * u + z_lookup_eval) + */ + let batch_evaluation := + mulmod( + mload(C_V0_LOC), + addmod(mulmod(mload(W1_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W1_EVAL_LOC), p), + p + ) + batch_evaluation := + addmod( + batch_evaluation, + mulmod( + mload(C_V1_LOC), + addmod(mulmod(mload(W2_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W2_EVAL_LOC), p), + p + ), + p + ) + batch_evaluation := + addmod( + batch_evaluation, + mulmod( + mload(C_V2_LOC), + addmod(mulmod(mload(W3_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W3_EVAL_LOC), p), + p + ), + p + ) + batch_evaluation := + addmod( + batch_evaluation, + mulmod( + mload(C_V3_LOC), + addmod(mulmod(mload(W4_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W4_EVAL_LOC), p), + p + ), + p + ) + batch_evaluation := + addmod( + batch_evaluation, + mulmod( + mload(C_V4_LOC), + addmod(mulmod(mload(S_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(S_EVAL_LOC), p), + p + ), + p + ) + batch_evaluation := + addmod( + batch_evaluation, + mulmod( + mload(C_V5_LOC), + addmod(mulmod(mload(Z_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(Z_EVAL_LOC), p), + p + ), + p + ) + batch_evaluation := + addmod( + batch_evaluation, + mulmod( + mload(C_V6_LOC), + addmod(mulmod(mload(Z_LOOKUP_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(Z_LOOKUP_EVAL_LOC), p), + p + ), + p + ) + + /** + * batch_evaluation += v7 * Q1_EVAL + * batch_evaluation += v8 * Q2_EVAL + * batch_evaluation += v9 * Q3_EVAL + * batch_evaluation += v10 * Q4_EVAL + * batch_evaluation += v11 * QM_EVAL + * batch_evaluation += v12 * QC_EVAL + * batch_evaluation += v13 * QARITH_EVAL + * batch_evaluation += v14 * QSORT_EVAL_LOC + * batch_evaluation += v15 * QELLIPTIC_EVAL_LOC + * batch_evaluation += v16 * QAUX_EVAL_LOC + * batch_evaluation += v17 * SIGMA1_EVAL_LOC + * batch_evaluation += v18 * SIGMA2_EVAL_LOC + * batch_evaluation += v19 * SIGMA3_EVAL_LOC + * batch_evaluation += v20 * SIGMA4_EVAL_LOC + */ + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V7_LOC), mload(Q1_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V8_LOC), mload(Q2_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V9_LOC), mload(Q3_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V10_LOC), mload(Q4_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V11_LOC), mload(QM_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V12_LOC), mload(QC_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V13_LOC), mload(QARITH_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V14_LOC), mload(QSORT_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V15_LOC), mload(QELLIPTIC_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V16_LOC), mload(QAUX_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V17_LOC), mload(SIGMA1_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V18_LOC), mload(SIGMA2_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V19_LOC), mload(SIGMA3_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V20_LOC), mload(SIGMA4_EVAL_LOC), p), p) + + /** + * batch_evaluation += v21 * (table1(zw) * u + table1(z)) + * batch_evaluation += v22 * (table2(zw) * u + table2(z)) + * batch_evaluation += v23 * (table3(zw) * u + table3(z)) + * batch_evaluation += v24 * (table4(zw) * u + table4(z)) + * batch_evaluation += v25 * table_type_eval + * batch_evaluation += v26 * id1_eval + * batch_evaluation += v27 * id2_eval + * batch_evaluation += v28 * id3_eval + * batch_evaluation += v29 * id4_eval + * batch_evaluation += quotient_eval + */ + batch_evaluation := + addmod( + batch_evaluation, + mulmod( + mload(C_V21_LOC), + addmod(mulmod(mload(TABLE1_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE1_EVAL_LOC), p), + p + ), + p + ) + batch_evaluation := + addmod( + batch_evaluation, + mulmod( + mload(C_V22_LOC), + addmod(mulmod(mload(TABLE2_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE2_EVAL_LOC), p), + p + ), + p + ) + batch_evaluation := + addmod( + batch_evaluation, + mulmod( + mload(C_V23_LOC), + addmod(mulmod(mload(TABLE3_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE3_EVAL_LOC), p), + p + ), + p + ) + batch_evaluation := + addmod( + batch_evaluation, + mulmod( + mload(C_V24_LOC), + addmod(mulmod(mload(TABLE4_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE4_EVAL_LOC), p), + p + ), + p + ) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V25_LOC), mload(TABLE_TYPE_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V26_LOC), mload(ID1_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V27_LOC), mload(ID2_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V28_LOC), mload(ID3_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V29_LOC), mload(ID4_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mload(QUOTIENT_EVAL_LOC), p) + + mstore(0x00, 0x01) // [1].x + mstore(0x20, 0x02) // [1].y + mstore(0x40, sub(p, batch_evaluation)) + // accumulator_2 = -[1].(batch_evaluation) + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + if iszero(success) { + mstore(0x0, OPENING_COMMITMENT_FAILED_SELECTOR) + revert(0x00, 0x04) + } + } + + /** + * PERFORM PAIRING PREAMBLE + */ + { + let u := mload(C_U_LOC) + let zeta := mload(C_ZETA_LOC) + // VALIDATE PI_Z + { + let x := mload(PI_Z_X_LOC) + let y := mload(PI_Z_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + // compute zeta.[PI_Z] and add into accumulator + mstore(0x40, zeta) + success := staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE PI_Z_OMEGA + { + let x := mload(PI_Z_OMEGA_X_LOC) + let y := mload(PI_Z_OMEGA_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(mulmod(u, zeta, p), mload(OMEGA_LOC), p)) + // accumulator_2 = u.zeta.omega.[PI_Z_OMEGA] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // PAIRING_RHS = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, PAIRING_RHS_X_LOC, 0x40)) + + mstore(0x00, mload(PI_Z_X_LOC)) + mstore(0x20, mload(PI_Z_Y_LOC)) + mstore(0x40, mload(PI_Z_OMEGA_X_LOC)) + mstore(0x60, mload(PI_Z_OMEGA_Y_LOC)) + mstore(0x80, u) + success := and(success, staticcall(gas(), 7, 0x40, 0x60, 0x40, 0x40)) + // PAIRING_LHS = [PI_Z] + [PI_Z_OMEGA] * u + success := and(success, staticcall(gas(), 6, 0x00, 0x80, PAIRING_LHS_X_LOC, 0x40)) + // negate lhs y-coordinate + mstore(PAIRING_LHS_Y_LOC, sub(q, mload(PAIRING_LHS_Y_LOC))) + + if mload(CONTAINS_RECURSIVE_PROOF_LOC) { + // VALIDATE RECURSIVE P1 + { + let x := mload(RECURSIVE_P1_X_LOC) + let y := mload(RECURSIVE_P1_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + + // compute u.u.[recursive_p1] and write into 0x60 + mstore(0x40, mulmod(u, u, p)) + success := and(success, staticcall(gas(), 7, 0x00, 0x60, 0x60, 0x40)) + // VALIDATE RECURSIVE P2 + { + let x := mload(RECURSIVE_P2_X_LOC) + let y := mload(RECURSIVE_P2_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + // compute u.u.[recursive_p2] and write into 0x00 + // 0x40 still contains u*u + success := and(success, staticcall(gas(), 7, 0x00, 0x60, 0x00, 0x40)) + + // compute u.u.[recursiveP1] + rhs and write into rhs + mstore(0xa0, mload(PAIRING_RHS_X_LOC)) + mstore(0xc0, mload(PAIRING_RHS_Y_LOC)) + success := and(success, staticcall(gas(), 6, 0x60, 0x80, PAIRING_RHS_X_LOC, 0x40)) + + // compute u.u.[recursiveP2] + lhs and write into lhs + mstore(0x40, mload(PAIRING_LHS_X_LOC)) + mstore(0x60, mload(PAIRING_LHS_Y_LOC)) + success := and(success, staticcall(gas(), 6, 0x00, 0x80, PAIRING_LHS_X_LOC, 0x40)) + } + + if iszero(success) { + mstore(0x0, PAIRING_PREAMBLE_FAILED_SELECTOR) + revert(0x00, 0x04) + } + } + + /** + * PERFORM PAIRING + */ + { + // rhs paired with [1]_2 + // lhs paired with [x]_2 + + mstore(0x00, mload(PAIRING_RHS_X_LOC)) + mstore(0x20, mload(PAIRING_RHS_Y_LOC)) + mstore(0x40, 0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2) // this is [1]_2 + mstore(0x60, 0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed) + mstore(0x80, 0x090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b) + mstore(0xa0, 0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa) + + mstore(0xc0, mload(PAIRING_LHS_X_LOC)) + mstore(0xe0, mload(PAIRING_LHS_Y_LOC)) + mstore(0x100, mload(G2X_X0_LOC)) + mstore(0x120, mload(G2X_X1_LOC)) + mstore(0x140, mload(G2X_Y0_LOC)) + mstore(0x160, mload(G2X_Y1_LOC)) + + success := staticcall(gas(), 8, 0x00, 0x180, 0x00, 0x20) + if iszero(and(success, mload(0x00))) { + mstore(0x0, PAIRING_FAILED_SELECTOR) + revert(0x00, 0x04) + } + } + + { + mstore(0x00, 0x01) + return(0x00, 0x20) // Proof succeeded! + } + } + } +} + +contract UltraVerifier is BaseUltraVerifier { + function getVerificationKeyHash() public pure override(BaseUltraVerifier) returns (bytes32) { + return UltraVerificationKey.verificationKeyHash(); + } + + function loadVerificationKey(uint256 vk, uint256 _omegaInverseLoc) internal pure virtual override(BaseUltraVerifier) { + UltraVerificationKey.loadVerificationKey(vk, _omegaInverseLoc); + } +} diff --git a/noir/noir-repo/compiler/integration-tests/contracts/recursion.sol b/noir/noir-repo/compiler/integration-tests/contracts/recursion.sol new file mode 100644 index 000000000000..abb5529f12ed --- /dev/null +++ b/noir/noir-repo/compiler/integration-tests/contracts/recursion.sol @@ -0,0 +1,2869 @@ +// Verification Key Hash: e0328cb05dead618095601e226cdeb6dbc39366658b78fabcb8b4d79b64150fe +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2022 Aztec +pragma solidity >=0.8.4; + +library UltraVerificationKey { + function verificationKeyHash() internal pure returns(bytes32) { + return 0xe0328cb05dead618095601e226cdeb6dbc39366658b78fabcb8b4d79b64150fe; + } + + function loadVerificationKey(uint256 _vk, uint256 _omegaInverseLoc) internal pure { + assembly { + mstore(add(_vk, 0x00), 0x0000000000000000000000000000000000000000000000000000000000040000) // vk.circuit_size + mstore(add(_vk, 0x20), 0x0000000000000000000000000000000000000000000000000000000000000010) // vk.num_inputs + mstore(add(_vk, 0x40), 0x19ddbcaf3a8d46c15c0176fbb5b95e4dc57088ff13f4d1bd84c6bfa57dcdc0e0) // vk.work_root + mstore(add(_vk, 0x60), 0x30644259cd94e7dd5045d7a27013b7fcd21c9e3b7fa75222e7bda49b729b0401) // vk.domain_inverse + mstore(add(_vk, 0x80), 0x296cf46c4f739702b3432a7e00d817fd408d994c86c7b2a3d111e60216220ff4) // vk.Q1.x + mstore(add(_vk, 0xa0), 0x23eb5e8befe06db56c45cacc7f6ebe1c5a6d564eacd9ce398f5512f78716db2f) // vk.Q1.y + mstore(add(_vk, 0xc0), 0x1343a11edd4c8f943d25b149f25ce46f3f3d778986116e54e46f19ecea6f222c) // vk.Q2.x + mstore(add(_vk, 0xe0), 0x21465130765a50d22ae703a7f04f1c56d702a1fd8e60ef7ab8643e7d65400d4a) // vk.Q2.y + mstore(add(_vk, 0x100), 0x14ca6d2277d046bfec277680aaef68c036229345162dc5898d4c59c48af3050c) // vk.Q3.x + mstore(add(_vk, 0x120), 0x0193076249ef903f84326def1f71f3e0f8964d6ad9b8169b10373534c5d8ce3a) // vk.Q3.y + mstore(add(_vk, 0x140), 0x19b321f51f228bda6233253f630bd7a4ef8886b0b0b04b8aa5dae7de26262741) // vk.Q4.x + mstore(add(_vk, 0x160), 0x29e642b2b28bb28117bf91a05f4072be4aa7b9e461a30a8b512c9ce550b8bd11) // vk.Q4.y + mstore(add(_vk, 0x180), 0x135c2b4ca117cad1e6de43b35922898f10a215ca4bd212fb235b11f749747a40) // vk.Q_M.x + mstore(add(_vk, 0x1a0), 0x1b5898cbfad83193f396baa1b97d270788e813afeb2a55342f4e01118d7c8d52) // vk.Q_M.y + mstore(add(_vk, 0x1c0), 0x22b15c7b21212709f0670cb679b2f9983b0624880388177e34194a86a8beeec4) // vk.Q_C.x + mstore(add(_vk, 0x1e0), 0x23abf1bb3ae5b994d972821a588c2a181d6f73b19cd63eb97ba3d279280c8d89) // vk.Q_C.y + mstore(add(_vk, 0x200), 0x113b6d3105a628cbad57a3e0d3af01035264182e3730b1e09ec465456c93e237) // vk.Q_ARITHMETIC.x + mstore(add(_vk, 0x220), 0x144c2223ed41c781c7e91e392a785122901565726d0733d1f85d715cf72f46c7) // vk.Q_ARITHMETIC.y + mstore(add(_vk, 0x240), 0x2ef5ddac9f6900407cb286d52468a09ed415e365b5086f5c9b74b4f281c61054) // vk.QSORT.x + mstore(add(_vk, 0x260), 0x010674e24f29b69a54da15ac59911e89cf3fa787ed2cad6a44daa63c67d00fd7) // vk.QSORT.y + mstore(add(_vk, 0x280), 0x26ba1f4d0e050a78621b511228a9c6983f7868dde8d03a3206ba8ecb4745228c) // vk.Q_ELLIPTIC.x + mstore(add(_vk, 0x2a0), 0x00e496fbcd18c30efca8bbab288382270e7c1ca730a6de1c97f1fdb8e8cbb8ae) // vk.Q_ELLIPTIC.y + mstore(add(_vk, 0x2c0), 0x12f33eb7f1ef14f7b9c5eef6fda9e8b915b1505a9fc4fddbe85273bab940215d) // vk.Q_AUX.x + mstore(add(_vk, 0x2e0), 0x0243ce5ba21f31b237dca7bb13bb6552da8e193324813b7269b144f5fc4bb571) // vk.Q_AUX.y + mstore(add(_vk, 0x300), 0x08ba0b0a65af34cf8d99b68d5a1f8ff614a3d2f2b79feeb798b1167cc9a38cc9) // vk.SIGMA1.x + mstore(add(_vk, 0x320), 0x150a1dbd173563cdd0503776c3d59e91d6e78c1f1e6d23785f9da5843b27fc60) // vk.SIGMA1.y + mstore(add(_vk, 0x340), 0x2495d18a5ab5b8e3a2f6f9888d92d349362dde30734049dccc6fa6e07d903231) // vk.SIGMA2.x + mstore(add(_vk, 0x360), 0x0823530dc06e55a763f9a51db768d4bc53ebec26334b3e9d248235e7972624c6) // vk.SIGMA2.y + mstore(add(_vk, 0x380), 0x15b6c07df0304bc78711f6f924f040f63c0a1e6174d1bc4bb20c5cf93444d239) // vk.SIGMA3.x + mstore(add(_vk, 0x3a0), 0x1c7932ed2c40d035d67e80599df3f127fd408c30af2f5dd14805dd5816715881) // vk.SIGMA3.y + mstore(add(_vk, 0x3c0), 0x2644c0b211b5bc8160034e9b4948392266e615c101df2306a82bc2f99ceb2357) // vk.SIGMA4.x + mstore(add(_vk, 0x3e0), 0x245551ceeed8c044a968549997e4d89071e9d65cd887afe82835c4b05394c8dd) // vk.SIGMA4.y + mstore(add(_vk, 0x400), 0x09796190fd3ba909c6530c89811df9b5b4f5f2fe6501ec21dd864b20673fc02c) // vk.TABLE1.x + mstore(add(_vk, 0x420), 0x00b9c2423e310caa43e1eb83b55f53977fccbed85422df8935635d77d146bf39) // vk.TABLE1.y + mstore(add(_vk, 0x440), 0x217dad26ccc0c543ec5750513e9365a5cae8164b08d364efcf4b5890ff05f334) // vk.TABLE2.x + mstore(add(_vk, 0x460), 0x1db28433f6bde424423f3587787f81c48101d2dc6e54b431332cb275f8518c62) // vk.TABLE2.y + mstore(add(_vk, 0x480), 0x2cc2d90f2da7f4ec16b7fe61babd4fb9b580ecff03c471764dd67a8c433afab5) // vk.TABLE3.x + mstore(add(_vk, 0x4a0), 0x3032b9ff096a43ce326cc63ffc6a86dcb913fb1f7700939f5304f6c6beb24574) // vk.TABLE3.y + mstore(add(_vk, 0x4c0), 0x1f4c58502ca713ed0bffb4ff31ed55e557e83a37d31b8e703aa9219d6158e2d2) // vk.TABLE4.x + mstore(add(_vk, 0x4e0), 0x0b0d5ed5432c5e7b56344c1d26ce0d9f632e8f8aa52505d6c89f6da89f357fa8) // vk.TABLE4.y + mstore(add(_vk, 0x500), 0x18f58f41d54253e53e11e950a30712a53ac21c410a53424cf08b5c866aa18ef7) // vk.TABLE_TYPE.x + mstore(add(_vk, 0x520), 0x085b844a9b90e6d79f01271644b9cbc23f81cccb1679ddb7c4cf28f525ff41ad) // vk.TABLE_TYPE.y + mstore(add(_vk, 0x540), 0x1409fc0d97f2c216efc3538236ffa767e74c140c918e041cd17029a30a4a9d44) // vk.ID1.x + mstore(add(_vk, 0x560), 0x26c5c627007675f6a57449fe0df318783b14e9abcf70ff93026059d76f6b9cd7) // vk.ID1.y + mstore(add(_vk, 0x580), 0x2c14b2eb3d66e1ad2ab2f3f572c788cc7fc3c5de27f10dc4b03fb8d24d99a100) // vk.ID2.x + mstore(add(_vk, 0x5a0), 0x12fb35d49297144b9c18d4fedadb24ecaf825a0b16f15429880254c021b848d3) // vk.ID2.y + mstore(add(_vk, 0x5c0), 0x09cd56d13b51b36941752c549fcbf0f91175759cd433aa663380ff74eea969bb) // vk.ID3.x + mstore(add(_vk, 0x5e0), 0x0a8120bced78e668891c2b79e4098b73357660d7ac5d18c38692b82fae92ceae) // vk.ID3.y + mstore(add(_vk, 0x600), 0x23a22f97c87c77b7ec20064f688ad1d82994517560d78cc0366cbaa3ad0fe931) // vk.ID4.x + mstore(add(_vk, 0x620), 0x08d8108812baa0e234edc5109ec726f19dc6efd247eea7d61930f0857844dba1) // vk.ID4.y + mstore(add(_vk, 0x640), 0x01) // vk.contains_recursive_proof + mstore(add(_vk, 0x660), 0) // vk.recursive_proof_public_input_indices + mstore(add(_vk, 0x680), 0x260e01b251f6f1c7e7ff4e580791dee8ea51d87a358e038b4efe30fac09383c1) // vk.g2_x.X.c1 + mstore(add(_vk, 0x6a0), 0x0118c4d5b837bcc2bc89b5b398b5974e9f5944073b32078b7e231fec938883b0) // vk.g2_x.X.c0 + mstore(add(_vk, 0x6c0), 0x04fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe4) // vk.g2_x.Y.c1 + mstore(add(_vk, 0x6e0), 0x22febda3c0c0632a56475b4214e5615e11e6dd3f96e6cea2854a87d4dacc5e55) // vk.g2_x.Y.c0 + mstore(_omegaInverseLoc, 0x036853f083780e87f8d7c71d111119c57dbe118c22d5ad707a82317466c5174c) // vk.work_root_inverse + } + } +} + +/** + * @title Ultra Plonk proof verification contract + * @dev Top level Plonk proof verification contract, which allows Plonk proof to be verified + */ +abstract contract BaseUltraVerifier { + // VERIFICATION KEY MEMORY LOCATIONS + uint256 internal constant N_LOC = 0x380; + uint256 internal constant NUM_INPUTS_LOC = 0x3a0; + uint256 internal constant OMEGA_LOC = 0x3c0; + uint256 internal constant DOMAIN_INVERSE_LOC = 0x3e0; + uint256 internal constant Q1_X_LOC = 0x400; + uint256 internal constant Q1_Y_LOC = 0x420; + uint256 internal constant Q2_X_LOC = 0x440; + uint256 internal constant Q2_Y_LOC = 0x460; + uint256 internal constant Q3_X_LOC = 0x480; + uint256 internal constant Q3_Y_LOC = 0x4a0; + uint256 internal constant Q4_X_LOC = 0x4c0; + uint256 internal constant Q4_Y_LOC = 0x4e0; + uint256 internal constant QM_X_LOC = 0x500; + uint256 internal constant QM_Y_LOC = 0x520; + uint256 internal constant QC_X_LOC = 0x540; + uint256 internal constant QC_Y_LOC = 0x560; + uint256 internal constant QARITH_X_LOC = 0x580; + uint256 internal constant QARITH_Y_LOC = 0x5a0; + uint256 internal constant QSORT_X_LOC = 0x5c0; + uint256 internal constant QSORT_Y_LOC = 0x5e0; + uint256 internal constant QELLIPTIC_X_LOC = 0x600; + uint256 internal constant QELLIPTIC_Y_LOC = 0x620; + uint256 internal constant QAUX_X_LOC = 0x640; + uint256 internal constant QAUX_Y_LOC = 0x660; + uint256 internal constant SIGMA1_X_LOC = 0x680; + uint256 internal constant SIGMA1_Y_LOC = 0x6a0; + uint256 internal constant SIGMA2_X_LOC = 0x6c0; + uint256 internal constant SIGMA2_Y_LOC = 0x6e0; + uint256 internal constant SIGMA3_X_LOC = 0x700; + uint256 internal constant SIGMA3_Y_LOC = 0x720; + uint256 internal constant SIGMA4_X_LOC = 0x740; + uint256 internal constant SIGMA4_Y_LOC = 0x760; + uint256 internal constant TABLE1_X_LOC = 0x780; + uint256 internal constant TABLE1_Y_LOC = 0x7a0; + uint256 internal constant TABLE2_X_LOC = 0x7c0; + uint256 internal constant TABLE2_Y_LOC = 0x7e0; + uint256 internal constant TABLE3_X_LOC = 0x800; + uint256 internal constant TABLE3_Y_LOC = 0x820; + uint256 internal constant TABLE4_X_LOC = 0x840; + uint256 internal constant TABLE4_Y_LOC = 0x860; + uint256 internal constant TABLE_TYPE_X_LOC = 0x880; + uint256 internal constant TABLE_TYPE_Y_LOC = 0x8a0; + uint256 internal constant ID1_X_LOC = 0x8c0; + uint256 internal constant ID1_Y_LOC = 0x8e0; + uint256 internal constant ID2_X_LOC = 0x900; + uint256 internal constant ID2_Y_LOC = 0x920; + uint256 internal constant ID3_X_LOC = 0x940; + uint256 internal constant ID3_Y_LOC = 0x960; + uint256 internal constant ID4_X_LOC = 0x980; + uint256 internal constant ID4_Y_LOC = 0x9a0; + uint256 internal constant CONTAINS_RECURSIVE_PROOF_LOC = 0x9c0; + uint256 internal constant RECURSIVE_PROOF_PUBLIC_INPUT_INDICES_LOC = 0x9e0; + uint256 internal constant G2X_X0_LOC = 0xa00; + uint256 internal constant G2X_X1_LOC = 0xa20; + uint256 internal constant G2X_Y0_LOC = 0xa40; + uint256 internal constant G2X_Y1_LOC = 0xa60; + + // ### PROOF DATA MEMORY LOCATIONS + uint256 internal constant W1_X_LOC = 0x1200; + uint256 internal constant W1_Y_LOC = 0x1220; + uint256 internal constant W2_X_LOC = 0x1240; + uint256 internal constant W2_Y_LOC = 0x1260; + uint256 internal constant W3_X_LOC = 0x1280; + uint256 internal constant W3_Y_LOC = 0x12a0; + uint256 internal constant W4_X_LOC = 0x12c0; + uint256 internal constant W4_Y_LOC = 0x12e0; + uint256 internal constant S_X_LOC = 0x1300; + uint256 internal constant S_Y_LOC = 0x1320; + uint256 internal constant Z_X_LOC = 0x1340; + uint256 internal constant Z_Y_LOC = 0x1360; + uint256 internal constant Z_LOOKUP_X_LOC = 0x1380; + uint256 internal constant Z_LOOKUP_Y_LOC = 0x13a0; + uint256 internal constant T1_X_LOC = 0x13c0; + uint256 internal constant T1_Y_LOC = 0x13e0; + uint256 internal constant T2_X_LOC = 0x1400; + uint256 internal constant T2_Y_LOC = 0x1420; + uint256 internal constant T3_X_LOC = 0x1440; + uint256 internal constant T3_Y_LOC = 0x1460; + uint256 internal constant T4_X_LOC = 0x1480; + uint256 internal constant T4_Y_LOC = 0x14a0; + + uint256 internal constant W1_EVAL_LOC = 0x1600; + uint256 internal constant W2_EVAL_LOC = 0x1620; + uint256 internal constant W3_EVAL_LOC = 0x1640; + uint256 internal constant W4_EVAL_LOC = 0x1660; + uint256 internal constant S_EVAL_LOC = 0x1680; + uint256 internal constant Z_EVAL_LOC = 0x16a0; + uint256 internal constant Z_LOOKUP_EVAL_LOC = 0x16c0; + uint256 internal constant Q1_EVAL_LOC = 0x16e0; + uint256 internal constant Q2_EVAL_LOC = 0x1700; + uint256 internal constant Q3_EVAL_LOC = 0x1720; + uint256 internal constant Q4_EVAL_LOC = 0x1740; + uint256 internal constant QM_EVAL_LOC = 0x1760; + uint256 internal constant QC_EVAL_LOC = 0x1780; + uint256 internal constant QARITH_EVAL_LOC = 0x17a0; + uint256 internal constant QSORT_EVAL_LOC = 0x17c0; + uint256 internal constant QELLIPTIC_EVAL_LOC = 0x17e0; + uint256 internal constant QAUX_EVAL_LOC = 0x1800; + uint256 internal constant TABLE1_EVAL_LOC = 0x1840; + uint256 internal constant TABLE2_EVAL_LOC = 0x1860; + uint256 internal constant TABLE3_EVAL_LOC = 0x1880; + uint256 internal constant TABLE4_EVAL_LOC = 0x18a0; + uint256 internal constant TABLE_TYPE_EVAL_LOC = 0x18c0; + uint256 internal constant ID1_EVAL_LOC = 0x18e0; + uint256 internal constant ID2_EVAL_LOC = 0x1900; + uint256 internal constant ID3_EVAL_LOC = 0x1920; + uint256 internal constant ID4_EVAL_LOC = 0x1940; + uint256 internal constant SIGMA1_EVAL_LOC = 0x1960; + uint256 internal constant SIGMA2_EVAL_LOC = 0x1980; + uint256 internal constant SIGMA3_EVAL_LOC = 0x19a0; + uint256 internal constant SIGMA4_EVAL_LOC = 0x19c0; + uint256 internal constant W1_OMEGA_EVAL_LOC = 0x19e0; + uint256 internal constant W2_OMEGA_EVAL_LOC = 0x2000; + uint256 internal constant W3_OMEGA_EVAL_LOC = 0x2020; + uint256 internal constant W4_OMEGA_EVAL_LOC = 0x2040; + uint256 internal constant S_OMEGA_EVAL_LOC = 0x2060; + uint256 internal constant Z_OMEGA_EVAL_LOC = 0x2080; + uint256 internal constant Z_LOOKUP_OMEGA_EVAL_LOC = 0x20a0; + uint256 internal constant TABLE1_OMEGA_EVAL_LOC = 0x20c0; + uint256 internal constant TABLE2_OMEGA_EVAL_LOC = 0x20e0; + uint256 internal constant TABLE3_OMEGA_EVAL_LOC = 0x2100; + uint256 internal constant TABLE4_OMEGA_EVAL_LOC = 0x2120; + + uint256 internal constant PI_Z_X_LOC = 0x2300; + uint256 internal constant PI_Z_Y_LOC = 0x2320; + uint256 internal constant PI_Z_OMEGA_X_LOC = 0x2340; + uint256 internal constant PI_Z_OMEGA_Y_LOC = 0x2360; + + // Used for elliptic widget. These are alias names for wire + shifted wire evaluations + uint256 internal constant X1_EVAL_LOC = W2_EVAL_LOC; + uint256 internal constant X2_EVAL_LOC = W1_OMEGA_EVAL_LOC; + uint256 internal constant X3_EVAL_LOC = W2_OMEGA_EVAL_LOC; + uint256 internal constant Y1_EVAL_LOC = W3_EVAL_LOC; + uint256 internal constant Y2_EVAL_LOC = W4_OMEGA_EVAL_LOC; + uint256 internal constant Y3_EVAL_LOC = W3_OMEGA_EVAL_LOC; + uint256 internal constant QBETA_LOC = Q3_EVAL_LOC; + uint256 internal constant QBETA_SQR_LOC = Q4_EVAL_LOC; + uint256 internal constant QSIGN_LOC = Q1_EVAL_LOC; + + // ### CHALLENGES MEMORY OFFSETS + + uint256 internal constant C_BETA_LOC = 0x2600; + uint256 internal constant C_GAMMA_LOC = 0x2620; + uint256 internal constant C_ALPHA_LOC = 0x2640; + uint256 internal constant C_ETA_LOC = 0x2660; + uint256 internal constant C_ETA_SQR_LOC = 0x2680; + uint256 internal constant C_ETA_CUBE_LOC = 0x26a0; + + uint256 internal constant C_ZETA_LOC = 0x26c0; + uint256 internal constant C_CURRENT_LOC = 0x26e0; + uint256 internal constant C_V0_LOC = 0x2700; + uint256 internal constant C_V1_LOC = 0x2720; + uint256 internal constant C_V2_LOC = 0x2740; + uint256 internal constant C_V3_LOC = 0x2760; + uint256 internal constant C_V4_LOC = 0x2780; + uint256 internal constant C_V5_LOC = 0x27a0; + uint256 internal constant C_V6_LOC = 0x27c0; + uint256 internal constant C_V7_LOC = 0x27e0; + uint256 internal constant C_V8_LOC = 0x2800; + uint256 internal constant C_V9_LOC = 0x2820; + uint256 internal constant C_V10_LOC = 0x2840; + uint256 internal constant C_V11_LOC = 0x2860; + uint256 internal constant C_V12_LOC = 0x2880; + uint256 internal constant C_V13_LOC = 0x28a0; + uint256 internal constant C_V14_LOC = 0x28c0; + uint256 internal constant C_V15_LOC = 0x28e0; + uint256 internal constant C_V16_LOC = 0x2900; + uint256 internal constant C_V17_LOC = 0x2920; + uint256 internal constant C_V18_LOC = 0x2940; + uint256 internal constant C_V19_LOC = 0x2960; + uint256 internal constant C_V20_LOC = 0x2980; + uint256 internal constant C_V21_LOC = 0x29a0; + uint256 internal constant C_V22_LOC = 0x29c0; + uint256 internal constant C_V23_LOC = 0x29e0; + uint256 internal constant C_V24_LOC = 0x2a00; + uint256 internal constant C_V25_LOC = 0x2a20; + uint256 internal constant C_V26_LOC = 0x2a40; + uint256 internal constant C_V27_LOC = 0x2a60; + uint256 internal constant C_V28_LOC = 0x2a80; + uint256 internal constant C_V29_LOC = 0x2aa0; + uint256 internal constant C_V30_LOC = 0x2ac0; + + uint256 internal constant C_U_LOC = 0x2b00; + + // ### LOCAL VARIABLES MEMORY OFFSETS + uint256 internal constant DELTA_NUMERATOR_LOC = 0x3000; + uint256 internal constant DELTA_DENOMINATOR_LOC = 0x3020; + uint256 internal constant ZETA_POW_N_LOC = 0x3040; + uint256 internal constant PUBLIC_INPUT_DELTA_LOC = 0x3060; + uint256 internal constant ZERO_POLY_LOC = 0x3080; + uint256 internal constant L_START_LOC = 0x30a0; + uint256 internal constant L_END_LOC = 0x30c0; + uint256 internal constant R_ZERO_EVAL_LOC = 0x30e0; + + uint256 internal constant PLOOKUP_DELTA_NUMERATOR_LOC = 0x3100; + uint256 internal constant PLOOKUP_DELTA_DENOMINATOR_LOC = 0x3120; + uint256 internal constant PLOOKUP_DELTA_LOC = 0x3140; + + uint256 internal constant ACCUMULATOR_X_LOC = 0x3160; + uint256 internal constant ACCUMULATOR_Y_LOC = 0x3180; + uint256 internal constant ACCUMULATOR2_X_LOC = 0x31a0; + uint256 internal constant ACCUMULATOR2_Y_LOC = 0x31c0; + uint256 internal constant PAIRING_LHS_X_LOC = 0x31e0; + uint256 internal constant PAIRING_LHS_Y_LOC = 0x3200; + uint256 internal constant PAIRING_RHS_X_LOC = 0x3220; + uint256 internal constant PAIRING_RHS_Y_LOC = 0x3240; + + // misc stuff + uint256 internal constant OMEGA_INVERSE_LOC = 0x3300; + uint256 internal constant C_ALPHA_SQR_LOC = 0x3320; + uint256 internal constant C_ALPHA_CUBE_LOC = 0x3340; + uint256 internal constant C_ALPHA_QUAD_LOC = 0x3360; + uint256 internal constant C_ALPHA_BASE_LOC = 0x3380; + + // ### RECURSION VARIABLE MEMORY LOCATIONS + uint256 internal constant RECURSIVE_P1_X_LOC = 0x3400; + uint256 internal constant RECURSIVE_P1_Y_LOC = 0x3420; + uint256 internal constant RECURSIVE_P2_X_LOC = 0x3440; + uint256 internal constant RECURSIVE_P2_Y_LOC = 0x3460; + uint256 internal constant PUBLIC_INPUTS_HASH_LOCATION = 0x3480; + + // sub-identity storage + uint256 internal constant PERMUTATION_IDENTITY = 0x3500; + uint256 internal constant PLOOKUP_IDENTITY = 0x3520; + uint256 internal constant ARITHMETIC_IDENTITY = 0x3540; + uint256 internal constant SORT_IDENTITY = 0x3560; + uint256 internal constant ELLIPTIC_IDENTITY = 0x3580; + uint256 internal constant AUX_IDENTITY = 0x35a0; + uint256 internal constant AUX_NON_NATIVE_FIELD_EVALUATION = 0x35c0; + uint256 internal constant AUX_LIMB_ACCUMULATOR_EVALUATION = 0x35e0; + uint256 internal constant AUX_RAM_CONSISTENCY_EVALUATION = 0x3600; + uint256 internal constant AUX_ROM_CONSISTENCY_EVALUATION = 0x3620; + uint256 internal constant AUX_MEMORY_EVALUATION = 0x3640; + + uint256 internal constant QUOTIENT_EVAL_LOC = 0x3660; + uint256 internal constant ZERO_POLY_INVERSE_LOC = 0x3680; + + // when hashing public inputs we use memory at NU_CHALLENGE_INPUT_LOC_A, as the hash input size is unknown at compile time + uint256 internal constant NU_CHALLENGE_INPUT_LOC_A = 0x36a0; + uint256 internal constant NU_CHALLENGE_INPUT_LOC_B = 0x36c0; + uint256 internal constant NU_CHALLENGE_INPUT_LOC_C = 0x36e0; + + bytes4 internal constant INVALID_VERIFICATION_KEY_SELECTOR = 0x7e5769bf; + bytes4 internal constant POINT_NOT_ON_CURVE_SELECTOR = 0xa3dad654; + bytes4 internal constant PUBLIC_INPUT_INVALID_BN128_G1_POINT_SELECTOR = 0xeba9f4a6; + bytes4 internal constant PUBLIC_INPUT_GE_P_SELECTOR = 0x374a972f; + bytes4 internal constant MOD_EXP_FAILURE_SELECTOR = 0xf894a7bc; + bytes4 internal constant PAIRING_PREAMBLE_FAILED_SELECTOR = 0x01882d81; + bytes4 internal constant OPENING_COMMITMENT_FAILED_SELECTOR = 0x4e719763; + bytes4 internal constant PAIRING_FAILED_SELECTOR = 0xd71fd263; + + uint256 internal constant ETA_INPUT_LENGTH = 0xc0; // W1, W2, W3 = 6 * 0x20 bytes + + // We need to hash 41 field elements when generating the NU challenge + // w1, w2, w3, w4, s, z, z_lookup, q1, q2, q3, q4, qm, qc, qarith (14) + // qsort, qelliptic, qaux, sigma1, sigma2, sigma, sigma4, (7) + // table1, table2, table3, table4, tabletype, id1, id2, id3, id4, (9) + // w1_omega, w2_omega, w3_omega, w4_omega, s_omega, z_omega, z_lookup_omega, (7) + // table1_omega, table2_omega, table3_omega, table4_omega (4) + uint256 internal constant NU_INPUT_LENGTH = 0x520; // 0x520 = 41 * 0x20 + + // There are ELEVEN G1 group elements added into the transcript in the `beta` round, that we need to skip over + // W1, W2, W3, W4, S, Z, Z_LOOKUP, T1, T2, T3, T4 + uint256 internal constant NU_CALLDATA_SKIP_LENGTH = 0x2c0; // 11 * 0x40 = 0x2c0 + + uint256 internal constant NEGATIVE_INVERSE_OF_2_MODULO_P = + 0x183227397098d014dc2822db40c0ac2e9419f4243cdcb848a1f0fac9f8000000; + uint256 internal constant LIMB_SIZE = 0x100000000000000000; // 2<<68 + uint256 internal constant SUBLIMB_SHIFT = 0x4000; // 2<<14 + + // y^2 = x^3 + ax + b + // for Grumpkin, a = 0 and b = -17. We use b in a custom gate relation that evaluates elliptic curve arithmetic + uint256 internal constant GRUMPKIN_CURVE_B_PARAMETER_NEGATED = 17; + + error INVALID_VERIFICATION_KEY(); + error POINT_NOT_ON_CURVE(); + error PUBLIC_INPUT_COUNT_INVALID(uint256 expected, uint256 actual); + error PUBLIC_INPUT_INVALID_BN128_G1_POINT(); + error PUBLIC_INPUT_GE_P(); + error MOD_EXP_FAILURE(); + error PAIRING_PREAMBLE_FAILED(); + error OPENING_COMMITMENT_FAILED(); + error PAIRING_FAILED(); + + function getVerificationKeyHash() public pure virtual returns (bytes32); + + /** + * @dev We assume that the verification key loaded by this function is constant as we only verify it on deployment + */ + function loadVerificationKey(uint256 _vk, uint256 _omegaInverseLoc) internal pure virtual; + + constructor() { + loadVerificationKey(N_LOC, OMEGA_INVERSE_LOC); + + // We verify that all of the EC points in the verification key lie on the bn128 curve. + assembly { + let q := 21888242871839275222246405745257275088696311157297823662689037894645226208583 // EC group order + + let success := 1 + + // VALIDATE Q1 + { + let x := mload(Q1_X_LOC) + let y := mload(Q1_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE Q2 + { + let x := mload(Q2_X_LOC) + let y := mload(Q2_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE Q3 + { + let x := mload(Q3_X_LOC) + let y := mload(Q3_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE Q4 + { + let x := mload(Q4_X_LOC) + let y := mload(Q4_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + mstore(0x00, x) + mstore(0x20, y) + } + // VALIDATE QM + { + let x := mload(QM_X_LOC) + let y := mload(QM_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE QC + { + let x := mload(QC_X_LOC) + let y := mload(QC_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE QARITH + { + let x := mload(QARITH_X_LOC) + let y := mload(QARITH_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE QSORT + { + let x := mload(QSORT_X_LOC) + let y := mload(QSORT_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE QELLIPTIC + { + let x := mload(QELLIPTIC_X_LOC) + let y := mload(QELLIPTIC_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE QAUX + { + let x := mload(QAUX_X_LOC) + let y := mload(QAUX_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE SIGMA1 + { + let x := mload(SIGMA1_X_LOC) + let y := mload(SIGMA1_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE SIGMA2 + { + let x := mload(SIGMA2_X_LOC) + let y := mload(SIGMA2_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE SIGMA3 + { + let x := mload(SIGMA3_X_LOC) + let y := mload(SIGMA3_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE SIGMA4 + { + let x := mload(SIGMA4_X_LOC) + let y := mload(SIGMA4_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE TABLE1 + { + let x := mload(TABLE1_X_LOC) + let y := mload(TABLE1_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE TABLE2 + { + let x := mload(TABLE2_X_LOC) + let y := mload(TABLE2_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE TABLE3 + { + let x := mload(TABLE3_X_LOC) + let y := mload(TABLE3_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE TABLE4 + { + let x := mload(TABLE4_X_LOC) + let y := mload(TABLE4_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE TABLE_TYPE + { + let x := mload(TABLE_TYPE_X_LOC) + let y := mload(TABLE_TYPE_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE ID1 + { + let x := mload(ID1_X_LOC) + let y := mload(ID1_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE ID2 + { + let x := mload(ID2_X_LOC) + let y := mload(ID2_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE ID3 + { + let x := mload(ID3_X_LOC) + let y := mload(ID3_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE ID4 + { + let x := mload(ID4_X_LOC) + let y := mload(ID4_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + + if iszero(success) { + mstore(0x0, INVALID_VERIFICATION_KEY_SELECTOR) + revert(0x00, 0x04) + } + } + } + + /** + * @notice Verify a Ultra Plonk proof + * @param _proof - The serialized proof + * @param _publicInputs - An array of the public inputs + * @return True if proof is valid, reverts otherwise + */ + function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool) { + loadVerificationKey(N_LOC, OMEGA_INVERSE_LOC); + + uint256 requiredPublicInputCount; + assembly { + requiredPublicInputCount := mload(NUM_INPUTS_LOC) + } + if (requiredPublicInputCount != _publicInputs.length) { + revert PUBLIC_INPUT_COUNT_INVALID(requiredPublicInputCount, _publicInputs.length); + } + + assembly { + let q := 21888242871839275222246405745257275088696311157297823662689037894645226208583 // EC group order + let p := 21888242871839275222246405745257275088548364400416034343698204186575808495617 // Prime field order + + /** + * LOAD PROOF FROM CALLDATA + */ + { + let data_ptr := add(calldataload(0x04), 0x24) + + mstore(W1_Y_LOC, mod(calldataload(data_ptr), q)) + mstore(W1_X_LOC, mod(calldataload(add(data_ptr, 0x20)), q)) + + mstore(W2_Y_LOC, mod(calldataload(add(data_ptr, 0x40)), q)) + mstore(W2_X_LOC, mod(calldataload(add(data_ptr, 0x60)), q)) + + mstore(W3_Y_LOC, mod(calldataload(add(data_ptr, 0x80)), q)) + mstore(W3_X_LOC, mod(calldataload(add(data_ptr, 0xa0)), q)) + + mstore(W4_Y_LOC, mod(calldataload(add(data_ptr, 0xc0)), q)) + mstore(W4_X_LOC, mod(calldataload(add(data_ptr, 0xe0)), q)) + + mstore(S_Y_LOC, mod(calldataload(add(data_ptr, 0x100)), q)) + mstore(S_X_LOC, mod(calldataload(add(data_ptr, 0x120)), q)) + mstore(Z_Y_LOC, mod(calldataload(add(data_ptr, 0x140)), q)) + mstore(Z_X_LOC, mod(calldataload(add(data_ptr, 0x160)), q)) + mstore(Z_LOOKUP_Y_LOC, mod(calldataload(add(data_ptr, 0x180)), q)) + mstore(Z_LOOKUP_X_LOC, mod(calldataload(add(data_ptr, 0x1a0)), q)) + mstore(T1_Y_LOC, mod(calldataload(add(data_ptr, 0x1c0)), q)) + mstore(T1_X_LOC, mod(calldataload(add(data_ptr, 0x1e0)), q)) + + mstore(T2_Y_LOC, mod(calldataload(add(data_ptr, 0x200)), q)) + mstore(T2_X_LOC, mod(calldataload(add(data_ptr, 0x220)), q)) + + mstore(T3_Y_LOC, mod(calldataload(add(data_ptr, 0x240)), q)) + mstore(T3_X_LOC, mod(calldataload(add(data_ptr, 0x260)), q)) + + mstore(T4_Y_LOC, mod(calldataload(add(data_ptr, 0x280)), q)) + mstore(T4_X_LOC, mod(calldataload(add(data_ptr, 0x2a0)), q)) + + mstore(W1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x2c0)), p)) + mstore(W2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x2e0)), p)) + mstore(W3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x300)), p)) + mstore(W4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x320)), p)) + mstore(S_EVAL_LOC, mod(calldataload(add(data_ptr, 0x340)), p)) + mstore(Z_EVAL_LOC, mod(calldataload(add(data_ptr, 0x360)), p)) + mstore(Z_LOOKUP_EVAL_LOC, mod(calldataload(add(data_ptr, 0x380)), p)) + mstore(Q1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x3a0)), p)) + mstore(Q2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x3c0)), p)) + mstore(Q3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x3e0)), p)) + mstore(Q4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x400)), p)) + mstore(QM_EVAL_LOC, mod(calldataload(add(data_ptr, 0x420)), p)) + mstore(QC_EVAL_LOC, mod(calldataload(add(data_ptr, 0x440)), p)) + mstore(QARITH_EVAL_LOC, mod(calldataload(add(data_ptr, 0x460)), p)) + mstore(QSORT_EVAL_LOC, mod(calldataload(add(data_ptr, 0x480)), p)) + mstore(QELLIPTIC_EVAL_LOC, mod(calldataload(add(data_ptr, 0x4a0)), p)) + mstore(QAUX_EVAL_LOC, mod(calldataload(add(data_ptr, 0x4c0)), p)) + + mstore(SIGMA1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x4e0)), p)) + mstore(SIGMA2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x500)), p)) + + mstore(SIGMA3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x520)), p)) + mstore(SIGMA4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x540)), p)) + + mstore(TABLE1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x560)), p)) + mstore(TABLE2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x580)), p)) + mstore(TABLE3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x5a0)), p)) + mstore(TABLE4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x5c0)), p)) + mstore(TABLE_TYPE_EVAL_LOC, mod(calldataload(add(data_ptr, 0x5e0)), p)) + + mstore(ID1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x600)), p)) + mstore(ID2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x620)), p)) + mstore(ID3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x640)), p)) + mstore(ID4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x660)), p)) + + mstore(W1_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x680)), p)) + mstore(W2_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x6a0)), p)) + mstore(W3_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x6c0)), p)) + mstore(W4_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x6e0)), p)) + mstore(S_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x700)), p)) + + mstore(Z_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x720)), p)) + + mstore(Z_LOOKUP_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x740)), p)) + mstore(TABLE1_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x760)), p)) + mstore(TABLE2_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x780)), p)) + mstore(TABLE3_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x7a0)), p)) + mstore(TABLE4_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x7c0)), p)) + + mstore(PI_Z_Y_LOC, mod(calldataload(add(data_ptr, 0x7e0)), q)) + mstore(PI_Z_X_LOC, mod(calldataload(add(data_ptr, 0x800)), q)) + + mstore(PI_Z_OMEGA_Y_LOC, mod(calldataload(add(data_ptr, 0x820)), q)) + mstore(PI_Z_OMEGA_X_LOC, mod(calldataload(add(data_ptr, 0x840)), q)) + } + + /** + * LOAD RECURSIVE PROOF INTO MEMORY + */ + { + if mload(CONTAINS_RECURSIVE_PROOF_LOC) { + let public_inputs_ptr := add(calldataload(0x24), 0x24) + let index_counter := add(shl(5, mload(RECURSIVE_PROOF_PUBLIC_INPUT_INDICES_LOC)), public_inputs_ptr) + + let x0 := calldataload(index_counter) + x0 := add(x0, shl(68, calldataload(add(index_counter, 0x20)))) + x0 := add(x0, shl(136, calldataload(add(index_counter, 0x40)))) + x0 := add(x0, shl(204, calldataload(add(index_counter, 0x60)))) + let y0 := calldataload(add(index_counter, 0x80)) + y0 := add(y0, shl(68, calldataload(add(index_counter, 0xa0)))) + y0 := add(y0, shl(136, calldataload(add(index_counter, 0xc0)))) + y0 := add(y0, shl(204, calldataload(add(index_counter, 0xe0)))) + let x1 := calldataload(add(index_counter, 0x100)) + x1 := add(x1, shl(68, calldataload(add(index_counter, 0x120)))) + x1 := add(x1, shl(136, calldataload(add(index_counter, 0x140)))) + x1 := add(x1, shl(204, calldataload(add(index_counter, 0x160)))) + let y1 := calldataload(add(index_counter, 0x180)) + y1 := add(y1, shl(68, calldataload(add(index_counter, 0x1a0)))) + y1 := add(y1, shl(136, calldataload(add(index_counter, 0x1c0)))) + y1 := add(y1, shl(204, calldataload(add(index_counter, 0x1e0)))) + mstore(RECURSIVE_P1_X_LOC, x0) + mstore(RECURSIVE_P1_Y_LOC, y0) + mstore(RECURSIVE_P2_X_LOC, x1) + mstore(RECURSIVE_P2_Y_LOC, y1) + + // validate these are valid bn128 G1 points + if iszero(and(and(lt(x0, q), lt(x1, q)), and(lt(y0, q), lt(y1, q)))) { + mstore(0x00, PUBLIC_INPUT_INVALID_BN128_G1_POINT_SELECTOR) + revert(0x00, 0x04) + } + } + } + + { + /** + * Generate initial challenge + */ + mstore(0x00, shl(224, mload(N_LOC))) + mstore(0x04, shl(224, mload(NUM_INPUTS_LOC))) + let challenge := keccak256(0x00, 0x08) + + /** + * Generate eta challenge + */ + mstore(PUBLIC_INPUTS_HASH_LOCATION, challenge) + // The public input location is stored at 0x24, we then add 0x24 to skip selector and the length of public inputs + let public_inputs_start := add(calldataload(0x24), 0x24) + // copy the public inputs over + let public_input_size := mul(mload(NUM_INPUTS_LOC), 0x20) + calldatacopy(add(PUBLIC_INPUTS_HASH_LOCATION, 0x20), public_inputs_start, public_input_size) + + // copy W1, W2, W3 into challenge. Each point is 0x40 bytes, so load 0xc0 = 3 * 0x40 bytes (ETA input length) + let w_start := add(calldataload(0x04), 0x24) + calldatacopy(add(add(PUBLIC_INPUTS_HASH_LOCATION, 0x20), public_input_size), w_start, ETA_INPUT_LENGTH) + + // Challenge is the old challenge + public inputs + W1, W2, W3 (0x20 + public_input_size + 0xc0) + let challenge_bytes_size := add(0x20, add(public_input_size, ETA_INPUT_LENGTH)) + + challenge := keccak256(PUBLIC_INPUTS_HASH_LOCATION, challenge_bytes_size) + { + let eta := mod(challenge, p) + mstore(C_ETA_LOC, eta) + mstore(C_ETA_SQR_LOC, mulmod(eta, eta, p)) + mstore(C_ETA_CUBE_LOC, mulmod(mload(C_ETA_SQR_LOC), eta, p)) + } + + /** + * Generate beta challenge + */ + mstore(0x00, challenge) + mstore(0x20, mload(W4_Y_LOC)) + mstore(0x40, mload(W4_X_LOC)) + mstore(0x60, mload(S_Y_LOC)) + mstore(0x80, mload(S_X_LOC)) + challenge := keccak256(0x00, 0xa0) + mstore(C_BETA_LOC, mod(challenge, p)) + + /** + * Generate gamma challenge + */ + mstore(0x00, challenge) + mstore8(0x20, 0x01) + challenge := keccak256(0x00, 0x21) + mstore(C_GAMMA_LOC, mod(challenge, p)) + + /** + * Generate alpha challenge + */ + mstore(0x00, challenge) + mstore(0x20, mload(Z_Y_LOC)) + mstore(0x40, mload(Z_X_LOC)) + mstore(0x60, mload(Z_LOOKUP_Y_LOC)) + mstore(0x80, mload(Z_LOOKUP_X_LOC)) + challenge := keccak256(0x00, 0xa0) + mstore(C_ALPHA_LOC, mod(challenge, p)) + + /** + * Compute and store some powers of alpha for future computations + */ + let alpha := mload(C_ALPHA_LOC) + mstore(C_ALPHA_SQR_LOC, mulmod(alpha, alpha, p)) + mstore(C_ALPHA_CUBE_LOC, mulmod(mload(C_ALPHA_SQR_LOC), alpha, p)) + mstore(C_ALPHA_QUAD_LOC, mulmod(mload(C_ALPHA_CUBE_LOC), alpha, p)) + mstore(C_ALPHA_BASE_LOC, alpha) + + /** + * Generate zeta challenge + */ + mstore(0x00, challenge) + mstore(0x20, mload(T1_Y_LOC)) + mstore(0x40, mload(T1_X_LOC)) + mstore(0x60, mload(T2_Y_LOC)) + mstore(0x80, mload(T2_X_LOC)) + mstore(0xa0, mload(T3_Y_LOC)) + mstore(0xc0, mload(T3_X_LOC)) + mstore(0xe0, mload(T4_Y_LOC)) + mstore(0x100, mload(T4_X_LOC)) + + challenge := keccak256(0x00, 0x120) + + mstore(C_ZETA_LOC, mod(challenge, p)) + mstore(C_CURRENT_LOC, challenge) + } + + /** + * EVALUATE FIELD OPERATIONS + */ + + /** + * COMPUTE PUBLIC INPUT DELTA + * ΔPI = ∏ᵢ∈ℓ(wᵢ + β σ(i) + γ) / ∏ᵢ∈ℓ(wᵢ + β σ'(i) + γ) + */ + { + let beta := mload(C_BETA_LOC) // β + let gamma := mload(C_GAMMA_LOC) // γ + let work_root := mload(OMEGA_LOC) // ω + let numerator_value := 1 + let denominator_value := 1 + + let p_clone := p // move p to the front of the stack + let valid_inputs := true + + // Load the starting point of the public inputs (jump over the selector and the length of public inputs [0x24]) + let public_inputs_ptr := add(calldataload(0x24), 0x24) + + // endpoint_ptr = public_inputs_ptr + num_inputs * 0x20. // every public input is 0x20 bytes + let endpoint_ptr := add(public_inputs_ptr, mul(mload(NUM_INPUTS_LOC), 0x20)) + + // root_1 = β * 0x05 + let root_1 := mulmod(beta, 0x05, p_clone) // k1.β + // root_2 = β * 0x0c + let root_2 := mulmod(beta, 0x0c, p_clone) + // @note 0x05 + 0x07 == 0x0c == external coset generator + + for {} lt(public_inputs_ptr, endpoint_ptr) { public_inputs_ptr := add(public_inputs_ptr, 0x20) } { + /** + * input = public_input[i] + * valid_inputs &= input < p + * temp = input + gamma + * numerator_value *= (β.σ(i) + wᵢ + γ) // σ(i) = 0x05.ωⁱ + * denominator_value *= (β.σ'(i) + wᵢ + γ) // σ'(i) = 0x0c.ωⁱ + * root_1 *= ω + * root_2 *= ω + */ + + let input := calldataload(public_inputs_ptr) + valid_inputs := and(valid_inputs, lt(input, p_clone)) + let temp := addmod(input, gamma, p_clone) + + numerator_value := mulmod(numerator_value, add(root_1, temp), p_clone) + denominator_value := mulmod(denominator_value, add(root_2, temp), p_clone) + + root_1 := mulmod(root_1, work_root, p_clone) + root_2 := mulmod(root_2, work_root, p_clone) + } + + // Revert if not all public inputs are field elements (i.e. < p) + if iszero(valid_inputs) { + mstore(0x00, PUBLIC_INPUT_GE_P_SELECTOR) + revert(0x00, 0x04) + } + + mstore(DELTA_NUMERATOR_LOC, numerator_value) + mstore(DELTA_DENOMINATOR_LOC, denominator_value) + } + + /** + * Compute Plookup delta factor [γ(1 + β)]^{n-k} + * k = num roots cut out of Z_H = 4 + */ + { + let delta_base := mulmod(mload(C_GAMMA_LOC), addmod(mload(C_BETA_LOC), 1, p), p) + let delta_numerator := delta_base + { + let exponent := mload(N_LOC) + let count := 1 + for {} lt(count, exponent) { count := add(count, count) } { + delta_numerator := mulmod(delta_numerator, delta_numerator, p) + } + } + mstore(PLOOKUP_DELTA_NUMERATOR_LOC, delta_numerator) + + let delta_denominator := mulmod(delta_base, delta_base, p) + delta_denominator := mulmod(delta_denominator, delta_denominator, p) + mstore(PLOOKUP_DELTA_DENOMINATOR_LOC, delta_denominator) + } + /** + * Compute lagrange poly and vanishing poly fractions + */ + { + /** + * vanishing_numerator = zeta + * ZETA_POW_N = zeta^n + * vanishing_numerator -= 1 + * accumulating_root = omega_inverse + * work_root = p - accumulating_root + * domain_inverse = domain_inverse + * vanishing_denominator = zeta + work_root + * work_root *= accumulating_root + * vanishing_denominator *= (zeta + work_root) + * work_root *= accumulating_root + * vanishing_denominator *= (zeta + work_root) + * vanishing_denominator *= (zeta + (zeta + accumulating_root)) + * work_root = omega + * lagrange_numerator = vanishing_numerator * domain_inverse + * l_start_denominator = zeta - 1 + * accumulating_root = work_root^2 + * l_end_denominator = accumulating_root^2 * work_root * zeta - 1 + * Note: l_end_denominator term contains a term \omega^5 to cut out 5 roots of unity from vanishing poly + */ + + let zeta := mload(C_ZETA_LOC) + + // compute zeta^n, where n is a power of 2 + let vanishing_numerator := zeta + { + // pow_small + let exponent := mload(N_LOC) + let count := 1 + for {} lt(count, exponent) { count := add(count, count) } { + vanishing_numerator := mulmod(vanishing_numerator, vanishing_numerator, p) + } + } + mstore(ZETA_POW_N_LOC, vanishing_numerator) + vanishing_numerator := addmod(vanishing_numerator, sub(p, 1), p) + + let accumulating_root := mload(OMEGA_INVERSE_LOC) + let work_root := sub(p, accumulating_root) + let domain_inverse := mload(DOMAIN_INVERSE_LOC) + + let vanishing_denominator := addmod(zeta, work_root, p) + work_root := mulmod(work_root, accumulating_root, p) + vanishing_denominator := mulmod(vanishing_denominator, addmod(zeta, work_root, p), p) + work_root := mulmod(work_root, accumulating_root, p) + vanishing_denominator := mulmod(vanishing_denominator, addmod(zeta, work_root, p), p) + vanishing_denominator := + mulmod(vanishing_denominator, addmod(zeta, mulmod(work_root, accumulating_root, p), p), p) + + work_root := mload(OMEGA_LOC) + + let lagrange_numerator := mulmod(vanishing_numerator, domain_inverse, p) + let l_start_denominator := addmod(zeta, sub(p, 1), p) + + accumulating_root := mulmod(work_root, work_root, p) + + let l_end_denominator := + addmod( + mulmod(mulmod(mulmod(accumulating_root, accumulating_root, p), work_root, p), zeta, p), sub(p, 1), p + ) + + /** + * Compute inversions using Montgomery's batch inversion trick + */ + let accumulator := mload(DELTA_DENOMINATOR_LOC) + let t0 := accumulator + accumulator := mulmod(accumulator, vanishing_denominator, p) + let t1 := accumulator + accumulator := mulmod(accumulator, vanishing_numerator, p) + let t2 := accumulator + accumulator := mulmod(accumulator, l_start_denominator, p) + let t3 := accumulator + accumulator := mulmod(accumulator, mload(PLOOKUP_DELTA_DENOMINATOR_LOC), p) + let t4 := accumulator + { + mstore(0, 0x20) + mstore(0x20, 0x20) + mstore(0x40, 0x20) + mstore(0x60, mulmod(accumulator, l_end_denominator, p)) + mstore(0x80, sub(p, 2)) + mstore(0xa0, p) + if iszero(staticcall(gas(), 0x05, 0x00, 0xc0, 0x00, 0x20)) { + mstore(0x0, MOD_EXP_FAILURE_SELECTOR) + revert(0x00, 0x04) + } + accumulator := mload(0x00) + } + + t4 := mulmod(accumulator, t4, p) + accumulator := mulmod(accumulator, l_end_denominator, p) + + t3 := mulmod(accumulator, t3, p) + accumulator := mulmod(accumulator, mload(PLOOKUP_DELTA_DENOMINATOR_LOC), p) + + t2 := mulmod(accumulator, t2, p) + accumulator := mulmod(accumulator, l_start_denominator, p) + + t1 := mulmod(accumulator, t1, p) + accumulator := mulmod(accumulator, vanishing_numerator, p) + + t0 := mulmod(accumulator, t0, p) + accumulator := mulmod(accumulator, vanishing_denominator, p) + + accumulator := mulmod(mulmod(accumulator, accumulator, p), mload(DELTA_DENOMINATOR_LOC), p) + + mstore(PUBLIC_INPUT_DELTA_LOC, mulmod(mload(DELTA_NUMERATOR_LOC), accumulator, p)) + mstore(ZERO_POLY_LOC, mulmod(vanishing_numerator, t0, p)) + mstore(ZERO_POLY_INVERSE_LOC, mulmod(vanishing_denominator, t1, p)) + mstore(L_START_LOC, mulmod(lagrange_numerator, t2, p)) + mstore(PLOOKUP_DELTA_LOC, mulmod(mload(PLOOKUP_DELTA_NUMERATOR_LOC), t3, p)) + mstore(L_END_LOC, mulmod(lagrange_numerator, t4, p)) + } + + /** + * UltraPlonk Widget Ordering: + * + * 1. Permutation widget + * 2. Plookup widget + * 3. Arithmetic widget + * 4. Fixed base widget (?) + * 5. GenPermSort widget + * 6. Elliptic widget + * 7. Auxiliary widget + */ + + /** + * COMPUTE PERMUTATION WIDGET EVALUATION + */ + { + let alpha := mload(C_ALPHA_LOC) + let beta := mload(C_BETA_LOC) + let gamma := mload(C_GAMMA_LOC) + + /** + * t1 = (W1 + gamma + beta * ID1) * (W2 + gamma + beta * ID2) + * t2 = (W3 + gamma + beta * ID3) * (W4 + gamma + beta * ID4) + * result = alpha_base * z_eval * t1 * t2 + * t1 = (W1 + gamma + beta * sigma_1_eval) * (W2 + gamma + beta * sigma_2_eval) + * t2 = (W2 + gamma + beta * sigma_3_eval) * (W3 + gamma + beta * sigma_4_eval) + * result -= (alpha_base * z_omega_eval * t1 * t2) + */ + let t1 := + mulmod( + add(add(mload(W1_EVAL_LOC), gamma), mulmod(beta, mload(ID1_EVAL_LOC), p)), + add(add(mload(W2_EVAL_LOC), gamma), mulmod(beta, mload(ID2_EVAL_LOC), p)), + p + ) + let t2 := + mulmod( + add(add(mload(W3_EVAL_LOC), gamma), mulmod(beta, mload(ID3_EVAL_LOC), p)), + add(add(mload(W4_EVAL_LOC), gamma), mulmod(beta, mload(ID4_EVAL_LOC), p)), + p + ) + let result := mulmod(mload(C_ALPHA_BASE_LOC), mulmod(mload(Z_EVAL_LOC), mulmod(t1, t2, p), p), p) + t1 := + mulmod( + add(add(mload(W1_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA1_EVAL_LOC), p)), + add(add(mload(W2_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA2_EVAL_LOC), p)), + p + ) + t2 := + mulmod( + add(add(mload(W3_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA3_EVAL_LOC), p)), + add(add(mload(W4_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA4_EVAL_LOC), p)), + p + ) + result := + addmod( + result, + sub(p, mulmod(mload(C_ALPHA_BASE_LOC), mulmod(mload(Z_OMEGA_EVAL_LOC), mulmod(t1, t2, p), p), p)), + p + ) + + /** + * alpha_base *= alpha + * result += alpha_base . (L_{n-k}(ʓ) . (z(ʓ.ω) - ∆_{PI})) + * alpha_base *= alpha + * result += alpha_base . (L_1(ʓ)(Z(ʓ) - 1)) + * alpha_Base *= alpha + */ + mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p)) + result := + addmod( + result, + mulmod( + mload(C_ALPHA_BASE_LOC), + mulmod( + mload(L_END_LOC), + addmod(mload(Z_OMEGA_EVAL_LOC), sub(p, mload(PUBLIC_INPUT_DELTA_LOC)), p), + p + ), + p + ), + p + ) + mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p)) + mstore( + PERMUTATION_IDENTITY, + addmod( + result, + mulmod( + mload(C_ALPHA_BASE_LOC), + mulmod(mload(L_START_LOC), addmod(mload(Z_EVAL_LOC), sub(p, 1), p), p), + p + ), + p + ) + ) + mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p)) + } + + /** + * COMPUTE PLOOKUP WIDGET EVALUATION + */ + { + /** + * Goal: f = (w1(z) + q2.w1(zω)) + η(w2(z) + qm.w2(zω)) + η²(w3(z) + qc.w_3(zω)) + q3(z).η³ + * f = η.q3(z) + * f += (w3(z) + qc.w_3(zω)) + * f *= η + * f += (w2(z) + qm.w2(zω)) + * f *= η + * f += (w1(z) + q2.w1(zω)) + */ + let f := mulmod(mload(C_ETA_LOC), mload(Q3_EVAL_LOC), p) + f := + addmod(f, addmod(mload(W3_EVAL_LOC), mulmod(mload(QC_EVAL_LOC), mload(W3_OMEGA_EVAL_LOC), p), p), p) + f := mulmod(f, mload(C_ETA_LOC), p) + f := + addmod(f, addmod(mload(W2_EVAL_LOC), mulmod(mload(QM_EVAL_LOC), mload(W2_OMEGA_EVAL_LOC), p), p), p) + f := mulmod(f, mload(C_ETA_LOC), p) + f := + addmod(f, addmod(mload(W1_EVAL_LOC), mulmod(mload(Q2_EVAL_LOC), mload(W1_OMEGA_EVAL_LOC), p), p), p) + + // t(z) = table4(z).η³ + table3(z).η² + table2(z).η + table1(z) + let t := + addmod( + addmod( + addmod( + mulmod(mload(TABLE4_EVAL_LOC), mload(C_ETA_CUBE_LOC), p), + mulmod(mload(TABLE3_EVAL_LOC), mload(C_ETA_SQR_LOC), p), + p + ), + mulmod(mload(TABLE2_EVAL_LOC), mload(C_ETA_LOC), p), + p + ), + mload(TABLE1_EVAL_LOC), + p + ) + + // t(zw) = table4(zw).η³ + table3(zw).η² + table2(zw).η + table1(zw) + let t_omega := + addmod( + addmod( + addmod( + mulmod(mload(TABLE4_OMEGA_EVAL_LOC), mload(C_ETA_CUBE_LOC), p), + mulmod(mload(TABLE3_OMEGA_EVAL_LOC), mload(C_ETA_SQR_LOC), p), + p + ), + mulmod(mload(TABLE2_OMEGA_EVAL_LOC), mload(C_ETA_LOC), p), + p + ), + mload(TABLE1_OMEGA_EVAL_LOC), + p + ) + + /** + * Goal: numerator = (TABLE_TYPE_EVAL * f(z) + γ) * (t(z) + βt(zω) + γ(β + 1)) * (β + 1) + * gamma_beta_constant = γ(β + 1) + * numerator = f * TABLE_TYPE_EVAL + gamma + * temp0 = t(z) + t(zω) * β + gamma_beta_constant + * numerator *= temp0 + * numerator *= (β + 1) + * temp0 = alpha * l_1 + * numerator += temp0 + * numerator *= z_lookup(z) + * numerator -= temp0 + */ + let gamma_beta_constant := mulmod(mload(C_GAMMA_LOC), addmod(mload(C_BETA_LOC), 1, p), p) + let numerator := addmod(mulmod(f, mload(TABLE_TYPE_EVAL_LOC), p), mload(C_GAMMA_LOC), p) + let temp0 := addmod(addmod(t, mulmod(t_omega, mload(C_BETA_LOC), p), p), gamma_beta_constant, p) + numerator := mulmod(numerator, temp0, p) + numerator := mulmod(numerator, addmod(mload(C_BETA_LOC), 1, p), p) + temp0 := mulmod(mload(C_ALPHA_LOC), mload(L_START_LOC), p) + numerator := addmod(numerator, temp0, p) + numerator := mulmod(numerator, mload(Z_LOOKUP_EVAL_LOC), p) + numerator := addmod(numerator, sub(p, temp0), p) + + /** + * Goal: denominator = z_lookup(zω)*[s(z) + βs(zω) + γ(1 + β)] - [z_lookup(zω) - [γ(1 + β)]^{n-k}]*α²L_end(z) + * note: delta_factor = [γ(1 + β)]^{n-k} + * denominator = s(z) + βs(zω) + γ(β + 1) + * temp1 = α²L_end(z) + * denominator -= temp1 + * denominator *= z_lookup(zω) + * denominator += temp1 * delta_factor + * PLOOKUP_IDENTITY = (numerator - denominator).alpha_base + * alpha_base *= alpha^3 + */ + let denominator := + addmod( + addmod(mload(S_EVAL_LOC), mulmod(mload(S_OMEGA_EVAL_LOC), mload(C_BETA_LOC), p), p), + gamma_beta_constant, + p + ) + let temp1 := mulmod(mload(C_ALPHA_SQR_LOC), mload(L_END_LOC), p) + denominator := addmod(denominator, sub(p, temp1), p) + denominator := mulmod(denominator, mload(Z_LOOKUP_OMEGA_EVAL_LOC), p) + denominator := addmod(denominator, mulmod(temp1, mload(PLOOKUP_DELTA_LOC), p), p) + + mstore(PLOOKUP_IDENTITY, mulmod(addmod(numerator, sub(p, denominator), p), mload(C_ALPHA_BASE_LOC), p)) + + // update alpha + mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_CUBE_LOC), p)) + } + + /** + * COMPUTE ARITHMETIC WIDGET EVALUATION + */ + { + /** + * The basic arithmetic gate identity in standard plonk is as follows. + * (w_1 . w_2 . q_m) + (w_1 . q_1) + (w_2 . q_2) + (w_3 . q_3) + (w_4 . q_4) + q_c = 0 + * However, for Ultraplonk, we extend this to support "passing" wires between rows (shown without alpha scaling below): + * q_arith * ( ( (-1/2) * (q_arith - 3) * q_m * w_1 * w_2 + q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c ) + + * (q_arith - 1)*( α * (q_arith - 2) * (w_1 + w_4 - w_1_omega + q_m) + w_4_omega) ) = 0 + * + * This formula results in several cases depending on q_arith: + * 1. q_arith == 0: Arithmetic gate is completely disabled + * + * 2. q_arith == 1: Everything in the minigate on the right is disabled. The equation is just a standard plonk equation + * with extra wires: q_m * w_1 * w_2 + q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c = 0 + * + * 3. q_arith == 2: The (w_1 + w_4 - ...) term is disabled. THe equation is: + * (1/2) * q_m * w_1 * w_2 + q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c + w_4_omega = 0 + * It allows defining w_4 at next index (w_4_omega) in terms of current wire values + * + * 4. q_arith == 3: The product of w_1 and w_2 is disabled, but a mini addition gate is enabled. α allows us to split + * the equation into two: + * + * q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c + 2 * w_4_omega = 0 + * and + * w_1 + w_4 - w_1_omega + q_m = 0 (we are reusing q_m here) + * + * 5. q_arith > 3: The product of w_1 and w_2 is scaled by (q_arith - 3), while the w_4_omega term is scaled by (q_arith - 1). + * The equation can be split into two: + * + * (q_arith - 3)* q_m * w_1 * w_ 2 + q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c + (q_arith - 1) * w_4_omega = 0 + * and + * w_1 + w_4 - w_1_omega + q_m = 0 + * + * The problem that q_m is used both in both equations can be dealt with by appropriately changing selector values at + * the next gate. Then we can treat (q_arith - 1) as a simulated q_6 selector and scale q_m to handle (q_arith - 3) at + * product. + */ + + let w1q1 := mulmod(mload(W1_EVAL_LOC), mload(Q1_EVAL_LOC), p) + let w2q2 := mulmod(mload(W2_EVAL_LOC), mload(Q2_EVAL_LOC), p) + let w3q3 := mulmod(mload(W3_EVAL_LOC), mload(Q3_EVAL_LOC), p) + let w4q3 := mulmod(mload(W4_EVAL_LOC), mload(Q4_EVAL_LOC), p) + + // @todo - Add a explicit test that hits QARITH == 3 + // w1w2qm := (w_1 . w_2 . q_m . (QARITH_EVAL_LOC - 3)) / 2 + let w1w2qm := + mulmod( + mulmod( + mulmod(mulmod(mload(W1_EVAL_LOC), mload(W2_EVAL_LOC), p), mload(QM_EVAL_LOC), p), + addmod(mload(QARITH_EVAL_LOC), sub(p, 3), p), + p + ), + NEGATIVE_INVERSE_OF_2_MODULO_P, + p + ) + + // (w_1 . w_2 . q_m . (q_arith - 3)) / -2) + (w_1 . q_1) + (w_2 . q_2) + (w_3 . q_3) + (w_4 . q_4) + q_c + let identity := + addmod( + mload(QC_EVAL_LOC), addmod(w4q3, addmod(w3q3, addmod(w2q2, addmod(w1q1, w1w2qm, p), p), p), p), p + ) + + // if q_arith == 3 we evaluate an additional mini addition gate (on top of the regular one), where: + // w_1 + w_4 - w_1_omega + q_m = 0 + // we use this gate to save an addition gate when adding or subtracting non-native field elements + // α * (q_arith - 2) * (w_1 + w_4 - w_1_omega + q_m) + let extra_small_addition_gate_identity := + mulmod( + mload(C_ALPHA_LOC), + mulmod( + addmod(mload(QARITH_EVAL_LOC), sub(p, 2), p), + addmod( + mload(QM_EVAL_LOC), + addmod( + sub(p, mload(W1_OMEGA_EVAL_LOC)), addmod(mload(W1_EVAL_LOC), mload(W4_EVAL_LOC), p), p + ), + p + ), + p + ), + p + ) + + // if q_arith == 2 OR q_arith == 3 we add the 4th wire of the NEXT gate into the arithmetic identity + // N.B. if q_arith > 2, this wire value will be scaled by (q_arith - 1) relative to the other gate wires! + // alpha_base * q_arith * (identity + (q_arith - 1) * (w_4_omega + extra_small_addition_gate_identity)) + mstore( + ARITHMETIC_IDENTITY, + mulmod( + mload(C_ALPHA_BASE_LOC), + mulmod( + mload(QARITH_EVAL_LOC), + addmod( + identity, + mulmod( + addmod(mload(QARITH_EVAL_LOC), sub(p, 1), p), + addmod(mload(W4_OMEGA_EVAL_LOC), extra_small_addition_gate_identity, p), + p + ), + p + ), + p + ), + p + ) + ) + + // update alpha + mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_SQR_LOC), p)) + } + + /** + * COMPUTE GENPERMSORT WIDGET EVALUATION + */ + { + /** + * D1 = (w2 - w1) + * D2 = (w3 - w2) + * D3 = (w4 - w3) + * D4 = (w1_omega - w4) + * + * α_a = alpha_base + * α_b = alpha_base * α + * α_c = alpha_base * α^2 + * α_d = alpha_base * α^3 + * + * range_accumulator = ( + * D1(D1 - 1)(D1 - 2)(D1 - 3).α_a + + * D2(D2 - 1)(D2 - 2)(D2 - 3).α_b + + * D3(D3 - 1)(D3 - 2)(D3 - 3).α_c + + * D4(D4 - 1)(D4 - 2)(D4 - 3).α_d + + * ) . q_sort + */ + let minus_two := sub(p, 2) + let minus_three := sub(p, 3) + let d1 := addmod(mload(W2_EVAL_LOC), sub(p, mload(W1_EVAL_LOC)), p) + let d2 := addmod(mload(W3_EVAL_LOC), sub(p, mload(W2_EVAL_LOC)), p) + let d3 := addmod(mload(W4_EVAL_LOC), sub(p, mload(W3_EVAL_LOC)), p) + let d4 := addmod(mload(W1_OMEGA_EVAL_LOC), sub(p, mload(W4_EVAL_LOC)), p) + + let range_accumulator := + mulmod( + mulmod( + mulmod(addmod(mulmod(d1, d1, p), sub(p, d1), p), addmod(d1, minus_two, p), p), + addmod(d1, minus_three, p), + p + ), + mload(C_ALPHA_BASE_LOC), + p + ) + range_accumulator := + addmod( + range_accumulator, + mulmod( + mulmod( + mulmod(addmod(mulmod(d2, d2, p), sub(p, d2), p), addmod(d2, minus_two, p), p), + addmod(d2, minus_three, p), + p + ), + mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p), + p + ), + p + ) + range_accumulator := + addmod( + range_accumulator, + mulmod( + mulmod( + mulmod(addmod(mulmod(d3, d3, p), sub(p, d3), p), addmod(d3, minus_two, p), p), + addmod(d3, minus_three, p), + p + ), + mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_SQR_LOC), p), + p + ), + p + ) + range_accumulator := + addmod( + range_accumulator, + mulmod( + mulmod( + mulmod(addmod(mulmod(d4, d4, p), sub(p, d4), p), addmod(d4, minus_two, p), p), + addmod(d4, minus_three, p), + p + ), + mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_CUBE_LOC), p), + p + ), + p + ) + range_accumulator := mulmod(range_accumulator, mload(QSORT_EVAL_LOC), p) + + mstore(SORT_IDENTITY, range_accumulator) + + // update alpha + mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_QUAD_LOC), p)) + } + + /** + * COMPUTE ELLIPTIC WIDGET EVALUATION + */ + { + /** + * endo_term = (-x_2) * x_1 * (x_3 * 2 + x_1) * q_beta + * endo_sqr_term = x_2^2 + * endo_sqr_term *= (x_3 - x_1) + * endo_sqr_term *= q_beta^2 + * leftovers = x_2^2 + * leftovers *= x_2 + * leftovers += x_1^2 * (x_3 + x_1) @follow-up Invalid comment in BB widget + * leftovers -= (y_2^2 + y_1^2) + * sign_term = y_2 * y_1 + * sign_term += sign_term + * sign_term *= q_sign + */ + // q_elliptic * (x3 + x2 + x1)(x2 - x1)(x2 - x1) - y2^2 - y1^2 + 2(y2y1)*q_sign = 0 + let x_diff := addmod(mload(X2_EVAL_LOC), sub(p, mload(X1_EVAL_LOC)), p) + let y2_sqr := mulmod(mload(Y2_EVAL_LOC), mload(Y2_EVAL_LOC), p) + let y1_sqr := mulmod(mload(Y1_EVAL_LOC), mload(Y1_EVAL_LOC), p) + let y1y2 := mulmod(mulmod(mload(Y1_EVAL_LOC), mload(Y2_EVAL_LOC), p), mload(QSIGN_LOC), p) + + let x_add_identity := + addmod( + mulmod( + addmod(mload(X3_EVAL_LOC), addmod(mload(X2_EVAL_LOC), mload(X1_EVAL_LOC), p), p), + mulmod(x_diff, x_diff, p), + p + ), + addmod( + sub( + p, + addmod(y2_sqr, y1_sqr, p) + ), + addmod(y1y2, y1y2, p), + p + ), + p + ) + x_add_identity := + mulmod( + mulmod( + x_add_identity, + addmod( + 1, + sub(p, mload(QM_EVAL_LOC)), + p + ), + p + ), + mload(C_ALPHA_BASE_LOC), + p + ) + + // q_elliptic * (x3 + x2 + x1)(x2 - x1)(x2 - x1) - y2^2 - y1^2 + 2(y2y1)*q_sign = 0 + let y1_plus_y3 := addmod( + mload(Y1_EVAL_LOC), + mload(Y3_EVAL_LOC), + p + ) + let y_diff := addmod(mulmod(mload(Y2_EVAL_LOC), mload(QSIGN_LOC), p), sub(p, mload(Y1_EVAL_LOC)), p) + let y_add_identity := + addmod( + mulmod(y1_plus_y3, x_diff, p), + mulmod(addmod(mload(X3_EVAL_LOC), sub(p, mload(X1_EVAL_LOC)), p), y_diff, p), + p + ) + y_add_identity := + mulmod( + mulmod(y_add_identity, addmod(1, sub(p, mload(QM_EVAL_LOC)), p), p), + mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p), + p + ) + + // ELLIPTIC_IDENTITY = (x_identity + y_identity) * Q_ELLIPTIC_EVAL + mstore( + ELLIPTIC_IDENTITY, mulmod(addmod(x_add_identity, y_add_identity, p), mload(QELLIPTIC_EVAL_LOC), p) + ) + } + { + /** + * x_pow_4 = (y_1_sqr - curve_b) * x_1; + * y_1_sqr_mul_4 = y_1_sqr + y_1_sqr; + * y_1_sqr_mul_4 += y_1_sqr_mul_4; + * x_1_pow_4_mul_9 = x_pow_4; + * x_1_pow_4_mul_9 += x_1_pow_4_mul_9; + * x_1_pow_4_mul_9 += x_1_pow_4_mul_9; + * x_1_pow_4_mul_9 += x_1_pow_4_mul_9; + * x_1_pow_4_mul_9 += x_pow_4; + * x_1_sqr_mul_3 = x_1_sqr + x_1_sqr + x_1_sqr; + * x_double_identity = (x_3 + x_1 + x_1) * y_1_sqr_mul_4 - x_1_pow_4_mul_9; + * y_double_identity = x_1_sqr_mul_3 * (x_1 - x_3) - (y_1 + y_1) * (y_1 + y_3); + */ + // (x3 + x1 + x1) (4y1*y1) - 9 * x1 * x1 * x1 * x1 = 0 + let x1_sqr := mulmod(mload(X1_EVAL_LOC), mload(X1_EVAL_LOC), p) + let y1_sqr := mulmod(mload(Y1_EVAL_LOC), mload(Y1_EVAL_LOC), p) + let x_pow_4 := mulmod(addmod(y1_sqr, GRUMPKIN_CURVE_B_PARAMETER_NEGATED, p), mload(X1_EVAL_LOC), p) + let y1_sqr_mul_4 := mulmod(y1_sqr, 4, p) + let x1_pow_4_mul_9 := mulmod(x_pow_4, 9, p) + let x1_sqr_mul_3 := mulmod(x1_sqr, 3, p) + let x_double_identity := + addmod( + mulmod( + addmod(mload(X3_EVAL_LOC), addmod(mload(X1_EVAL_LOC), mload(X1_EVAL_LOC), p), p), + y1_sqr_mul_4, + p + ), + sub(p, x1_pow_4_mul_9), + p + ) + // (y1 + y1) (2y1) - (3 * x1 * x1)(x1 - x3) = 0 + let y_double_identity := + addmod( + mulmod(x1_sqr_mul_3, addmod(mload(X1_EVAL_LOC), sub(p, mload(X3_EVAL_LOC)), p), p), + sub( + p, + mulmod( + addmod(mload(Y1_EVAL_LOC), mload(Y1_EVAL_LOC), p), + addmod(mload(Y1_EVAL_LOC), mload(Y3_EVAL_LOC), p), + p + ) + ), + p + ) + x_double_identity := mulmod(x_double_identity, mload(C_ALPHA_BASE_LOC), p) + y_double_identity := + mulmod(y_double_identity, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p), p) + x_double_identity := mulmod(x_double_identity, mload(QM_EVAL_LOC), p) + y_double_identity := mulmod(y_double_identity, mload(QM_EVAL_LOC), p) + // ELLIPTIC_IDENTITY += (x_double_identity + y_double_identity) * Q_DOUBLE_EVAL + mstore( + ELLIPTIC_IDENTITY, + addmod( + mload(ELLIPTIC_IDENTITY), + mulmod(addmod(x_double_identity, y_double_identity, p), mload(QELLIPTIC_EVAL_LOC), p), + p + ) + ) + + // update alpha + mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_QUAD_LOC), p)) + } + + /** + * COMPUTE AUXILIARY WIDGET EVALUATION + */ + { + { + /** + * Non native field arithmetic gate 2 + * _ _ + * / _ _ _ 14 \ + * q_2 . q_4 | (w_1 . w_2) + (w_1 . w_2) + (w_1 . w_4 + w_2 . w_3 - w_3) . 2 - w_3 - w_4 | + * \_ _/ + * + * limb_subproduct = w_1 . w_2_omega + w_1_omega . w_2 + * non_native_field_gate_2 = w_1 * w_4 + w_4 * w_3 - w_3_omega + * non_native_field_gate_2 = non_native_field_gate_2 * limb_size + * non_native_field_gate_2 -= w_4_omega + * non_native_field_gate_2 += limb_subproduct + * non_native_field_gate_2 *= q_4 + * limb_subproduct *= limb_size + * limb_subproduct += w_1_omega * w_2_omega + * non_native_field_gate_1 = (limb_subproduct + w_3 + w_4) * q_3 + * non_native_field_gate_3 = (limb_subproduct + w_4 - (w_3_omega + w_4_omega)) * q_m + * non_native_field_identity = (non_native_field_gate_1 + non_native_field_gate_2 + non_native_field_gate_3) * q_2 + */ + + let limb_subproduct := + addmod( + mulmod(mload(W1_EVAL_LOC), mload(W2_OMEGA_EVAL_LOC), p), + mulmod(mload(W1_OMEGA_EVAL_LOC), mload(W2_EVAL_LOC), p), + p + ) + + let non_native_field_gate_2 := + addmod( + addmod( + mulmod(mload(W1_EVAL_LOC), mload(W4_EVAL_LOC), p), + mulmod(mload(W2_EVAL_LOC), mload(W3_EVAL_LOC), p), + p + ), + sub(p, mload(W3_OMEGA_EVAL_LOC)), + p + ) + non_native_field_gate_2 := mulmod(non_native_field_gate_2, LIMB_SIZE, p) + non_native_field_gate_2 := addmod(non_native_field_gate_2, sub(p, mload(W4_OMEGA_EVAL_LOC)), p) + non_native_field_gate_2 := addmod(non_native_field_gate_2, limb_subproduct, p) + non_native_field_gate_2 := mulmod(non_native_field_gate_2, mload(Q4_EVAL_LOC), p) + limb_subproduct := mulmod(limb_subproduct, LIMB_SIZE, p) + limb_subproduct := + addmod(limb_subproduct, mulmod(mload(W1_OMEGA_EVAL_LOC), mload(W2_OMEGA_EVAL_LOC), p), p) + let non_native_field_gate_1 := + mulmod( + addmod(limb_subproduct, sub(p, addmod(mload(W3_EVAL_LOC), mload(W4_EVAL_LOC), p)), p), + mload(Q3_EVAL_LOC), + p + ) + let non_native_field_gate_3 := + mulmod( + addmod( + addmod(limb_subproduct, mload(W4_EVAL_LOC), p), + sub(p, addmod(mload(W3_OMEGA_EVAL_LOC), mload(W4_OMEGA_EVAL_LOC), p)), + p + ), + mload(QM_EVAL_LOC), + p + ) + let non_native_field_identity := + mulmod( + addmod(addmod(non_native_field_gate_1, non_native_field_gate_2, p), non_native_field_gate_3, p), + mload(Q2_EVAL_LOC), + p + ) + + mstore(AUX_NON_NATIVE_FIELD_EVALUATION, non_native_field_identity) + } + + { + /** + * limb_accumulator_1 = w_2_omega; + * limb_accumulator_1 *= SUBLIMB_SHIFT; + * limb_accumulator_1 += w_1_omega; + * limb_accumulator_1 *= SUBLIMB_SHIFT; + * limb_accumulator_1 += w_3; + * limb_accumulator_1 *= SUBLIMB_SHIFT; + * limb_accumulator_1 += w_2; + * limb_accumulator_1 *= SUBLIMB_SHIFT; + * limb_accumulator_1 += w_1; + * limb_accumulator_1 -= w_4; + * limb_accumulator_1 *= q_4; + */ + let limb_accumulator_1 := mulmod(mload(W2_OMEGA_EVAL_LOC), SUBLIMB_SHIFT, p) + limb_accumulator_1 := addmod(limb_accumulator_1, mload(W1_OMEGA_EVAL_LOC), p) + limb_accumulator_1 := mulmod(limb_accumulator_1, SUBLIMB_SHIFT, p) + limb_accumulator_1 := addmod(limb_accumulator_1, mload(W3_EVAL_LOC), p) + limb_accumulator_1 := mulmod(limb_accumulator_1, SUBLIMB_SHIFT, p) + limb_accumulator_1 := addmod(limb_accumulator_1, mload(W2_EVAL_LOC), p) + limb_accumulator_1 := mulmod(limb_accumulator_1, SUBLIMB_SHIFT, p) + limb_accumulator_1 := addmod(limb_accumulator_1, mload(W1_EVAL_LOC), p) + limb_accumulator_1 := addmod(limb_accumulator_1, sub(p, mload(W4_EVAL_LOC)), p) + limb_accumulator_1 := mulmod(limb_accumulator_1, mload(Q4_EVAL_LOC), p) + + /** + * limb_accumulator_2 = w_3_omega; + * limb_accumulator_2 *= SUBLIMB_SHIFT; + * limb_accumulator_2 += w_2_omega; + * limb_accumulator_2 *= SUBLIMB_SHIFT; + * limb_accumulator_2 += w_1_omega; + * limb_accumulator_2 *= SUBLIMB_SHIFT; + * limb_accumulator_2 += w_4; + * limb_accumulator_2 *= SUBLIMB_SHIFT; + * limb_accumulator_2 += w_3; + * limb_accumulator_2 -= w_4_omega; + * limb_accumulator_2 *= q_m; + */ + let limb_accumulator_2 := mulmod(mload(W3_OMEGA_EVAL_LOC), SUBLIMB_SHIFT, p) + limb_accumulator_2 := addmod(limb_accumulator_2, mload(W2_OMEGA_EVAL_LOC), p) + limb_accumulator_2 := mulmod(limb_accumulator_2, SUBLIMB_SHIFT, p) + limb_accumulator_2 := addmod(limb_accumulator_2, mload(W1_OMEGA_EVAL_LOC), p) + limb_accumulator_2 := mulmod(limb_accumulator_2, SUBLIMB_SHIFT, p) + limb_accumulator_2 := addmod(limb_accumulator_2, mload(W4_EVAL_LOC), p) + limb_accumulator_2 := mulmod(limb_accumulator_2, SUBLIMB_SHIFT, p) + limb_accumulator_2 := addmod(limb_accumulator_2, mload(W3_EVAL_LOC), p) + limb_accumulator_2 := addmod(limb_accumulator_2, sub(p, mload(W4_OMEGA_EVAL_LOC)), p) + limb_accumulator_2 := mulmod(limb_accumulator_2, mload(QM_EVAL_LOC), p) + + mstore( + AUX_LIMB_ACCUMULATOR_EVALUATION, + mulmod(addmod(limb_accumulator_1, limb_accumulator_2, p), mload(Q3_EVAL_LOC), p) + ) + } + + { + /** + * memory_record_check = w_3; + * memory_record_check *= eta; + * memory_record_check += w_2; + * memory_record_check *= eta; + * memory_record_check += w_1; + * memory_record_check *= eta; + * memory_record_check += q_c; + * + * partial_record_check = memory_record_check; + * + * memory_record_check -= w_4; + */ + + let memory_record_check := mulmod(mload(W3_EVAL_LOC), mload(C_ETA_LOC), p) + memory_record_check := addmod(memory_record_check, mload(W2_EVAL_LOC), p) + memory_record_check := mulmod(memory_record_check, mload(C_ETA_LOC), p) + memory_record_check := addmod(memory_record_check, mload(W1_EVAL_LOC), p) + memory_record_check := mulmod(memory_record_check, mload(C_ETA_LOC), p) + memory_record_check := addmod(memory_record_check, mload(QC_EVAL_LOC), p) + + let partial_record_check := memory_record_check + memory_record_check := addmod(memory_record_check, sub(p, mload(W4_EVAL_LOC)), p) + + mstore(AUX_MEMORY_EVALUATION, memory_record_check) + + // index_delta = w_1_omega - w_1 + let index_delta := addmod(mload(W1_OMEGA_EVAL_LOC), sub(p, mload(W1_EVAL_LOC)), p) + // record_delta = w_4_omega - w_4 + let record_delta := addmod(mload(W4_OMEGA_EVAL_LOC), sub(p, mload(W4_EVAL_LOC)), p) + // index_is_monotonically_increasing = index_delta * (index_delta - 1) + let index_is_monotonically_increasing := mulmod(index_delta, addmod(index_delta, sub(p, 1), p), p) + + // adjacent_values_match_if_adjacent_indices_match = record_delta * (1 - index_delta) + let adjacent_values_match_if_adjacent_indices_match := + mulmod(record_delta, addmod(1, sub(p, index_delta), p), p) + + // AUX_ROM_CONSISTENCY_EVALUATION = ((adjacent_values_match_if_adjacent_indices_match * alpha) + index_is_monotonically_increasing) * alpha + partial_record_check + mstore( + AUX_ROM_CONSISTENCY_EVALUATION, + addmod( + mulmod( + addmod( + mulmod(adjacent_values_match_if_adjacent_indices_match, mload(C_ALPHA_LOC), p), + index_is_monotonically_increasing, + p + ), + mload(C_ALPHA_LOC), + p + ), + memory_record_check, + p + ) + ) + + { + /** + * next_gate_access_type = w_3_omega; + * next_gate_access_type *= eta; + * next_gate_access_type += w_2_omega; + * next_gate_access_type *= eta; + * next_gate_access_type += w_1_omega; + * next_gate_access_type *= eta; + * next_gate_access_type = w_4_omega - next_gate_access_type; + */ + let next_gate_access_type := mulmod(mload(W3_OMEGA_EVAL_LOC), mload(C_ETA_LOC), p) + next_gate_access_type := addmod(next_gate_access_type, mload(W2_OMEGA_EVAL_LOC), p) + next_gate_access_type := mulmod(next_gate_access_type, mload(C_ETA_LOC), p) + next_gate_access_type := addmod(next_gate_access_type, mload(W1_OMEGA_EVAL_LOC), p) + next_gate_access_type := mulmod(next_gate_access_type, mload(C_ETA_LOC), p) + next_gate_access_type := addmod(mload(W4_OMEGA_EVAL_LOC), sub(p, next_gate_access_type), p) + + // value_delta = w_3_omega - w_3 + let value_delta := addmod(mload(W3_OMEGA_EVAL_LOC), sub(p, mload(W3_EVAL_LOC)), p) + // adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation = (1 - index_delta) * value_delta * (1 - next_gate_access_type); + + let adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation := + mulmod( + addmod(1, sub(p, index_delta), p), + mulmod(value_delta, addmod(1, sub(p, next_gate_access_type), p), p), + p + ) + + // AUX_RAM_CONSISTENCY_EVALUATION + + /** + * access_type = w_4 - partial_record_check + * access_check = access_type^2 - access_type + * next_gate_access_type_is_boolean = next_gate_access_type^2 - next_gate_access_type + * RAM_consistency_check_identity = adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation; + * RAM_consistency_check_identity *= alpha; + * RAM_consistency_check_identity += index_is_monotonically_increasing; + * RAM_consistency_check_identity *= alpha; + * RAM_consistency_check_identity += next_gate_access_type_is_boolean; + * RAM_consistency_check_identity *= alpha; + * RAM_consistency_check_identity += access_check; + */ + + let access_type := addmod(mload(W4_EVAL_LOC), sub(p, partial_record_check), p) + let access_check := mulmod(access_type, addmod(access_type, sub(p, 1), p), p) + let next_gate_access_type_is_boolean := + mulmod(next_gate_access_type, addmod(next_gate_access_type, sub(p, 1), p), p) + let RAM_cci := + mulmod( + adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation, + mload(C_ALPHA_LOC), + p + ) + RAM_cci := addmod(RAM_cci, index_is_monotonically_increasing, p) + RAM_cci := mulmod(RAM_cci, mload(C_ALPHA_LOC), p) + RAM_cci := addmod(RAM_cci, next_gate_access_type_is_boolean, p) + RAM_cci := mulmod(RAM_cci, mload(C_ALPHA_LOC), p) + RAM_cci := addmod(RAM_cci, access_check, p) + + mstore(AUX_RAM_CONSISTENCY_EVALUATION, RAM_cci) + } + + { + // timestamp_delta = w_2_omega - w_2 + let timestamp_delta := addmod(mload(W2_OMEGA_EVAL_LOC), sub(p, mload(W2_EVAL_LOC)), p) + + // RAM_timestamp_check_identity = (1 - index_delta) * timestamp_delta - w_3 + let RAM_timestamp_check_identity := + addmod( + mulmod(timestamp_delta, addmod(1, sub(p, index_delta), p), p), sub(p, mload(W3_EVAL_LOC)), p + ) + + /** + * memory_identity = ROM_consistency_check_identity * q_2; + * memory_identity += RAM_timestamp_check_identity * q_4; + * memory_identity += memory_record_check * q_m; + * memory_identity *= q_1; + * memory_identity += (RAM_consistency_check_identity * q_arith); + * + * auxiliary_identity = memory_identity + non_native_field_identity + limb_accumulator_identity; + * auxiliary_identity *= q_aux; + * auxiliary_identity *= alpha_base; + */ + let memory_identity := mulmod(mload(AUX_ROM_CONSISTENCY_EVALUATION), mload(Q2_EVAL_LOC), p) + memory_identity := + addmod(memory_identity, mulmod(RAM_timestamp_check_identity, mload(Q4_EVAL_LOC), p), p) + memory_identity := + addmod(memory_identity, mulmod(mload(AUX_MEMORY_EVALUATION), mload(QM_EVAL_LOC), p), p) + memory_identity := mulmod(memory_identity, mload(Q1_EVAL_LOC), p) + memory_identity := + addmod( + memory_identity, mulmod(mload(AUX_RAM_CONSISTENCY_EVALUATION), mload(QARITH_EVAL_LOC), p), p + ) + + let auxiliary_identity := addmod(memory_identity, mload(AUX_NON_NATIVE_FIELD_EVALUATION), p) + auxiliary_identity := addmod(auxiliary_identity, mload(AUX_LIMB_ACCUMULATOR_EVALUATION), p) + auxiliary_identity := mulmod(auxiliary_identity, mload(QAUX_EVAL_LOC), p) + auxiliary_identity := mulmod(auxiliary_identity, mload(C_ALPHA_BASE_LOC), p) + + mstore(AUX_IDENTITY, auxiliary_identity) + + // update alpha + mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_CUBE_LOC), p)) + } + } + } + + { + /** + * quotient = ARITHMETIC_IDENTITY + * quotient += PERMUTATION_IDENTITY + * quotient += PLOOKUP_IDENTITY + * quotient += SORT_IDENTITY + * quotient += ELLIPTIC_IDENTITY + * quotient += AUX_IDENTITY + * quotient *= ZERO_POLY_INVERSE + */ + mstore( + QUOTIENT_EVAL_LOC, + mulmod( + addmod( + addmod( + addmod( + addmod( + addmod(mload(PERMUTATION_IDENTITY), mload(PLOOKUP_IDENTITY), p), + mload(ARITHMETIC_IDENTITY), + p + ), + mload(SORT_IDENTITY), + p + ), + mload(ELLIPTIC_IDENTITY), + p + ), + mload(AUX_IDENTITY), + p + ), + mload(ZERO_POLY_INVERSE_LOC), + p + ) + ) + } + + /** + * GENERATE NU AND SEPARATOR CHALLENGES + */ + { + let current_challenge := mload(C_CURRENT_LOC) + // get a calldata pointer that points to the start of the data we want to copy + let calldata_ptr := add(calldataload(0x04), 0x24) + + calldata_ptr := add(calldata_ptr, NU_CALLDATA_SKIP_LENGTH) + + mstore(NU_CHALLENGE_INPUT_LOC_A, current_challenge) + mstore(NU_CHALLENGE_INPUT_LOC_B, mload(QUOTIENT_EVAL_LOC)) + calldatacopy(NU_CHALLENGE_INPUT_LOC_C, calldata_ptr, NU_INPUT_LENGTH) + + // hash length = (0x20 + num field elements), we include the previous challenge in the hash + let challenge := keccak256(NU_CHALLENGE_INPUT_LOC_A, add(NU_INPUT_LENGTH, 0x40)) + + mstore(C_V0_LOC, mod(challenge, p)) + // We need THIRTY-ONE independent nu challenges! + mstore(0x00, challenge) + mstore8(0x20, 0x01) + mstore(C_V1_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x02) + mstore(C_V2_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x03) + mstore(C_V3_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x04) + mstore(C_V4_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x05) + mstore(C_V5_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x06) + mstore(C_V6_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x07) + mstore(C_V7_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x08) + mstore(C_V8_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x09) + mstore(C_V9_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x0a) + mstore(C_V10_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x0b) + mstore(C_V11_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x0c) + mstore(C_V12_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x0d) + mstore(C_V13_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x0e) + mstore(C_V14_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x0f) + mstore(C_V15_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x10) + mstore(C_V16_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x11) + mstore(C_V17_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x12) + mstore(C_V18_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x13) + mstore(C_V19_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x14) + mstore(C_V20_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x15) + mstore(C_V21_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x16) + mstore(C_V22_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x17) + mstore(C_V23_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x18) + mstore(C_V24_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x19) + mstore(C_V25_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x1a) + mstore(C_V26_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x1b) + mstore(C_V27_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x1c) + mstore(C_V28_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x1d) + mstore(C_V29_LOC, mod(keccak256(0x00, 0x21), p)) + + // @follow-up - Why are both v29 and v30 using appending 0x1d to the prior challenge and hashing, should it not change? + mstore8(0x20, 0x1d) + challenge := keccak256(0x00, 0x21) + mstore(C_V30_LOC, mod(challenge, p)) + + // separator + mstore(0x00, challenge) + mstore(0x20, mload(PI_Z_Y_LOC)) + mstore(0x40, mload(PI_Z_X_LOC)) + mstore(0x60, mload(PI_Z_OMEGA_Y_LOC)) + mstore(0x80, mload(PI_Z_OMEGA_X_LOC)) + + mstore(C_U_LOC, mod(keccak256(0x00, 0xa0), p)) + } + + let success := 0 + // VALIDATE T1 + { + let x := mload(T1_X_LOC) + let y := mload(T1_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(ACCUMULATOR_X_LOC, x) + mstore(add(ACCUMULATOR_X_LOC, 0x20), y) + } + // VALIDATE T2 + { + let x := mload(T2_X_LOC) // 0x1400 + let y := mload(T2_Y_LOC) // 0x1420 + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(ZETA_POW_N_LOC)) + // accumulator_2 = [T2].zeta^n + success := staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40) + // accumulator = [T1] + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE T3 + { + let x := mload(T3_X_LOC) + let y := mload(T3_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(mload(ZETA_POW_N_LOC), mload(ZETA_POW_N_LOC), p)) + // accumulator_2 = [T3].zeta^{2n} + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE T4 + { + let x := mload(T4_X_LOC) + let y := mload(T4_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(mulmod(mload(ZETA_POW_N_LOC), mload(ZETA_POW_N_LOC), p), mload(ZETA_POW_N_LOC), p)) + // accumulator_2 = [T4].zeta^{3n} + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE W1 + { + let x := mload(W1_X_LOC) + let y := mload(W1_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V0_LOC), p)) + // accumulator_2 = v0.(u + 1).[W1] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE W2 + { + let x := mload(W2_X_LOC) + let y := mload(W2_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V1_LOC), p)) + // accumulator_2 = v1.(u + 1).[W2] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE W3 + { + let x := mload(W3_X_LOC) + let y := mload(W3_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V2_LOC), p)) + // accumulator_2 = v2.(u + 1).[W3] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE W4 + { + let x := mload(W4_X_LOC) + let y := mload(W4_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V3_LOC), p)) + // accumulator_2 = v3.(u + 1).[W4] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE S + { + let x := mload(S_X_LOC) + let y := mload(S_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V4_LOC), p)) + // accumulator_2 = v4.(u + 1).[S] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE Z + { + let x := mload(Z_X_LOC) + let y := mload(Z_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V5_LOC), p)) + // accumulator_2 = v5.(u + 1).[Z] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE Z_LOOKUP + { + let x := mload(Z_LOOKUP_X_LOC) + let y := mload(Z_LOOKUP_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V6_LOC), p)) + // accumulator_2 = v6.(u + 1).[Z_LOOKUP] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE Q1 + { + let x := mload(Q1_X_LOC) + let y := mload(Q1_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V7_LOC)) + // accumulator_2 = v7.[Q1] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE Q2 + { + let x := mload(Q2_X_LOC) + let y := mload(Q2_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V8_LOC)) + // accumulator_2 = v8.[Q2] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE Q3 + { + let x := mload(Q3_X_LOC) + let y := mload(Q3_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V9_LOC)) + // accumulator_2 = v9.[Q3] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE Q4 + { + let x := mload(Q4_X_LOC) + let y := mload(Q4_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V10_LOC)) + // accumulator_2 = v10.[Q4] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE QM + { + let x := mload(QM_X_LOC) + let y := mload(QM_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V11_LOC)) + // accumulator_2 = v11.[Q;] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE QC + { + let x := mload(QC_X_LOC) + let y := mload(QC_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V12_LOC)) + // accumulator_2 = v12.[QC] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE QARITH + { + let x := mload(QARITH_X_LOC) + let y := mload(QARITH_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V13_LOC)) + // accumulator_2 = v13.[QARITH] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE QSORT + { + let x := mload(QSORT_X_LOC) + let y := mload(QSORT_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V14_LOC)) + // accumulator_2 = v14.[QSORT] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE QELLIPTIC + { + let x := mload(QELLIPTIC_X_LOC) + let y := mload(QELLIPTIC_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V15_LOC)) + // accumulator_2 = v15.[QELLIPTIC] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE QAUX + { + let x := mload(QAUX_X_LOC) + let y := mload(QAUX_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V16_LOC)) + // accumulator_2 = v15.[Q_AUX] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE SIGMA1 + { + let x := mload(SIGMA1_X_LOC) + let y := mload(SIGMA1_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V17_LOC)) + // accumulator_2 = v17.[sigma1] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE SIGMA2 + { + let x := mload(SIGMA2_X_LOC) + let y := mload(SIGMA2_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V18_LOC)) + // accumulator_2 = v18.[sigma2] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE SIGMA3 + { + let x := mload(SIGMA3_X_LOC) + let y := mload(SIGMA3_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V19_LOC)) + // accumulator_2 = v19.[sigma3] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE SIGMA4 + { + let x := mload(SIGMA4_X_LOC) + let y := mload(SIGMA4_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V20_LOC)) + // accumulator_2 = v20.[sigma4] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE TABLE1 + { + let x := mload(TABLE1_X_LOC) + let y := mload(TABLE1_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V21_LOC), p)) + // accumulator_2 = u.[table1] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE TABLE2 + { + let x := mload(TABLE2_X_LOC) + let y := mload(TABLE2_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V22_LOC), p)) + // accumulator_2 = u.[table2] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE TABLE3 + { + let x := mload(TABLE3_X_LOC) + let y := mload(TABLE3_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V23_LOC), p)) + // accumulator_2 = u.[table3] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE TABLE4 + { + let x := mload(TABLE4_X_LOC) + let y := mload(TABLE4_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V24_LOC), p)) + // accumulator_2 = u.[table4] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE TABLE_TYPE + { + let x := mload(TABLE_TYPE_X_LOC) + let y := mload(TABLE_TYPE_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V25_LOC)) + // accumulator_2 = v25.[TableType] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE ID1 + { + let x := mload(ID1_X_LOC) + let y := mload(ID1_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V26_LOC)) + // accumulator_2 = v26.[ID1] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE ID2 + { + let x := mload(ID2_X_LOC) + let y := mload(ID2_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V27_LOC)) + // accumulator_2 = v27.[ID2] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE ID3 + { + let x := mload(ID3_X_LOC) + let y := mload(ID3_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V28_LOC)) + // accumulator_2 = v28.[ID3] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE ID4 + { + let x := mload(ID4_X_LOC) + let y := mload(ID4_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V29_LOC)) + // accumulator_2 = v29.[ID4] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + /** + * COMPUTE BATCH EVALUATION SCALAR MULTIPLIER + */ + { + /** + * batch_evaluation = v0 * (w_1_omega * u + w_1_eval) + * batch_evaluation += v1 * (w_2_omega * u + w_2_eval) + * batch_evaluation += v2 * (w_3_omega * u + w_3_eval) + * batch_evaluation += v3 * (w_4_omega * u + w_4_eval) + * batch_evaluation += v4 * (s_omega_eval * u + s_eval) + * batch_evaluation += v5 * (z_omega_eval * u + z_eval) + * batch_evaluation += v6 * (z_lookup_omega_eval * u + z_lookup_eval) + */ + let batch_evaluation := + mulmod( + mload(C_V0_LOC), + addmod(mulmod(mload(W1_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W1_EVAL_LOC), p), + p + ) + batch_evaluation := + addmod( + batch_evaluation, + mulmod( + mload(C_V1_LOC), + addmod(mulmod(mload(W2_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W2_EVAL_LOC), p), + p + ), + p + ) + batch_evaluation := + addmod( + batch_evaluation, + mulmod( + mload(C_V2_LOC), + addmod(mulmod(mload(W3_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W3_EVAL_LOC), p), + p + ), + p + ) + batch_evaluation := + addmod( + batch_evaluation, + mulmod( + mload(C_V3_LOC), + addmod(mulmod(mload(W4_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W4_EVAL_LOC), p), + p + ), + p + ) + batch_evaluation := + addmod( + batch_evaluation, + mulmod( + mload(C_V4_LOC), + addmod(mulmod(mload(S_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(S_EVAL_LOC), p), + p + ), + p + ) + batch_evaluation := + addmod( + batch_evaluation, + mulmod( + mload(C_V5_LOC), + addmod(mulmod(mload(Z_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(Z_EVAL_LOC), p), + p + ), + p + ) + batch_evaluation := + addmod( + batch_evaluation, + mulmod( + mload(C_V6_LOC), + addmod(mulmod(mload(Z_LOOKUP_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(Z_LOOKUP_EVAL_LOC), p), + p + ), + p + ) + + /** + * batch_evaluation += v7 * Q1_EVAL + * batch_evaluation += v8 * Q2_EVAL + * batch_evaluation += v9 * Q3_EVAL + * batch_evaluation += v10 * Q4_EVAL + * batch_evaluation += v11 * QM_EVAL + * batch_evaluation += v12 * QC_EVAL + * batch_evaluation += v13 * QARITH_EVAL + * batch_evaluation += v14 * QSORT_EVAL_LOC + * batch_evaluation += v15 * QELLIPTIC_EVAL_LOC + * batch_evaluation += v16 * QAUX_EVAL_LOC + * batch_evaluation += v17 * SIGMA1_EVAL_LOC + * batch_evaluation += v18 * SIGMA2_EVAL_LOC + * batch_evaluation += v19 * SIGMA3_EVAL_LOC + * batch_evaluation += v20 * SIGMA4_EVAL_LOC + */ + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V7_LOC), mload(Q1_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V8_LOC), mload(Q2_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V9_LOC), mload(Q3_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V10_LOC), mload(Q4_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V11_LOC), mload(QM_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V12_LOC), mload(QC_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V13_LOC), mload(QARITH_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V14_LOC), mload(QSORT_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V15_LOC), mload(QELLIPTIC_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V16_LOC), mload(QAUX_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V17_LOC), mload(SIGMA1_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V18_LOC), mload(SIGMA2_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V19_LOC), mload(SIGMA3_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V20_LOC), mload(SIGMA4_EVAL_LOC), p), p) + + /** + * batch_evaluation += v21 * (table1(zw) * u + table1(z)) + * batch_evaluation += v22 * (table2(zw) * u + table2(z)) + * batch_evaluation += v23 * (table3(zw) * u + table3(z)) + * batch_evaluation += v24 * (table4(zw) * u + table4(z)) + * batch_evaluation += v25 * table_type_eval + * batch_evaluation += v26 * id1_eval + * batch_evaluation += v27 * id2_eval + * batch_evaluation += v28 * id3_eval + * batch_evaluation += v29 * id4_eval + * batch_evaluation += quotient_eval + */ + batch_evaluation := + addmod( + batch_evaluation, + mulmod( + mload(C_V21_LOC), + addmod(mulmod(mload(TABLE1_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE1_EVAL_LOC), p), + p + ), + p + ) + batch_evaluation := + addmod( + batch_evaluation, + mulmod( + mload(C_V22_LOC), + addmod(mulmod(mload(TABLE2_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE2_EVAL_LOC), p), + p + ), + p + ) + batch_evaluation := + addmod( + batch_evaluation, + mulmod( + mload(C_V23_LOC), + addmod(mulmod(mload(TABLE3_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE3_EVAL_LOC), p), + p + ), + p + ) + batch_evaluation := + addmod( + batch_evaluation, + mulmod( + mload(C_V24_LOC), + addmod(mulmod(mload(TABLE4_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE4_EVAL_LOC), p), + p + ), + p + ) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V25_LOC), mload(TABLE_TYPE_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V26_LOC), mload(ID1_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V27_LOC), mload(ID2_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V28_LOC), mload(ID3_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V29_LOC), mload(ID4_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mload(QUOTIENT_EVAL_LOC), p) + + mstore(0x00, 0x01) // [1].x + mstore(0x20, 0x02) // [1].y + mstore(0x40, sub(p, batch_evaluation)) + // accumulator_2 = -[1].(batch_evaluation) + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + if iszero(success) { + mstore(0x0, OPENING_COMMITMENT_FAILED_SELECTOR) + revert(0x00, 0x04) + } + } + + /** + * PERFORM PAIRING PREAMBLE + */ + { + let u := mload(C_U_LOC) + let zeta := mload(C_ZETA_LOC) + // VALIDATE PI_Z + { + let x := mload(PI_Z_X_LOC) + let y := mload(PI_Z_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + // compute zeta.[PI_Z] and add into accumulator + mstore(0x40, zeta) + success := staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE PI_Z_OMEGA + { + let x := mload(PI_Z_OMEGA_X_LOC) + let y := mload(PI_Z_OMEGA_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(mulmod(u, zeta, p), mload(OMEGA_LOC), p)) + // accumulator_2 = u.zeta.omega.[PI_Z_OMEGA] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // PAIRING_RHS = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, PAIRING_RHS_X_LOC, 0x40)) + + mstore(0x00, mload(PI_Z_X_LOC)) + mstore(0x20, mload(PI_Z_Y_LOC)) + mstore(0x40, mload(PI_Z_OMEGA_X_LOC)) + mstore(0x60, mload(PI_Z_OMEGA_Y_LOC)) + mstore(0x80, u) + success := and(success, staticcall(gas(), 7, 0x40, 0x60, 0x40, 0x40)) + // PAIRING_LHS = [PI_Z] + [PI_Z_OMEGA] * u + success := and(success, staticcall(gas(), 6, 0x00, 0x80, PAIRING_LHS_X_LOC, 0x40)) + // negate lhs y-coordinate + mstore(PAIRING_LHS_Y_LOC, sub(q, mload(PAIRING_LHS_Y_LOC))) + + if mload(CONTAINS_RECURSIVE_PROOF_LOC) { + // VALIDATE RECURSIVE P1 + { + let x := mload(RECURSIVE_P1_X_LOC) + let y := mload(RECURSIVE_P1_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + + // compute u.u.[recursive_p1] and write into 0x60 + mstore(0x40, mulmod(u, u, p)) + success := and(success, staticcall(gas(), 7, 0x00, 0x60, 0x60, 0x40)) + // VALIDATE RECURSIVE P2 + { + let x := mload(RECURSIVE_P2_X_LOC) + let y := mload(RECURSIVE_P2_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + // compute u.u.[recursive_p2] and write into 0x00 + // 0x40 still contains u*u + success := and(success, staticcall(gas(), 7, 0x00, 0x60, 0x00, 0x40)) + + // compute u.u.[recursiveP1] + rhs and write into rhs + mstore(0xa0, mload(PAIRING_RHS_X_LOC)) + mstore(0xc0, mload(PAIRING_RHS_Y_LOC)) + success := and(success, staticcall(gas(), 6, 0x60, 0x80, PAIRING_RHS_X_LOC, 0x40)) + + // compute u.u.[recursiveP2] + lhs and write into lhs + mstore(0x40, mload(PAIRING_LHS_X_LOC)) + mstore(0x60, mload(PAIRING_LHS_Y_LOC)) + success := and(success, staticcall(gas(), 6, 0x00, 0x80, PAIRING_LHS_X_LOC, 0x40)) + } + + if iszero(success) { + mstore(0x0, PAIRING_PREAMBLE_FAILED_SELECTOR) + revert(0x00, 0x04) + } + } + + /** + * PERFORM PAIRING + */ + { + // rhs paired with [1]_2 + // lhs paired with [x]_2 + + mstore(0x00, mload(PAIRING_RHS_X_LOC)) + mstore(0x20, mload(PAIRING_RHS_Y_LOC)) + mstore(0x40, 0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2) // this is [1]_2 + mstore(0x60, 0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed) + mstore(0x80, 0x090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b) + mstore(0xa0, 0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa) + + mstore(0xc0, mload(PAIRING_LHS_X_LOC)) + mstore(0xe0, mload(PAIRING_LHS_Y_LOC)) + mstore(0x100, mload(G2X_X0_LOC)) + mstore(0x120, mload(G2X_X1_LOC)) + mstore(0x140, mload(G2X_Y0_LOC)) + mstore(0x160, mload(G2X_Y1_LOC)) + + success := staticcall(gas(), 8, 0x00, 0x180, 0x00, 0x20) + if iszero(and(success, mload(0x00))) { + mstore(0x0, PAIRING_FAILED_SELECTOR) + revert(0x00, 0x04) + } + } + + { + mstore(0x00, 0x01) + return(0x00, 0x20) // Proof succeeded! + } + } + } +} + +contract UltraVerifier is BaseUltraVerifier { + function getVerificationKeyHash() public pure override(BaseUltraVerifier) returns (bytes32) { + return UltraVerificationKey.verificationKeyHash(); + } + + function loadVerificationKey(uint256 vk, uint256 _omegaInverseLoc) internal pure virtual override(BaseUltraVerifier) { + UltraVerificationKey.loadVerificationKey(vk, _omegaInverseLoc); + } +} diff --git a/noir/noir-repo/compiler/integration-tests/package.json b/noir/noir-repo/compiler/integration-tests/package.json index 798b7c553123..511df534110f 100644 --- a/noir/noir-repo/compiler/integration-tests/package.json +++ b/noir/noir-repo/compiler/integration-tests/package.json @@ -6,7 +6,7 @@ "scripts": { "build": "echo Integration Test build step", "test": "yarn test:browser && yarn test:node", - "test:node": "bash ./scripts/codegen-verifiers.sh && hardhat test test/node/**/*", + "test:node": "hardhat test test/node/**/*", "test:browser": "web-test-runner", "test:integration:browser": "web-test-runner test/browser/**/*.test.ts", "test:integration:browser:watch": "web-test-runner test/browser/**/*.test.ts --watch", diff --git a/noir/noir-repo/test_programs/execution_success/recursion/Nargo.toml b/noir/noir-repo/test_programs/execution_success/recursion/Nargo.toml new file mode 100644 index 000000000000..fe1ba8b1ce62 --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/recursion/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "recursion" +type = "bin" +authors = [""] +compiler_version = ">=0.24.0" + +[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/execution_success/recursion/Prover.toml b/noir/noir-repo/test_programs/execution_success/recursion/Prover.toml new file mode 100644 index 000000000000..b00cd8661d8f --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/recursion/Prover.toml @@ -0,0 +1,4 @@ +key_hash = "0" +public_inputs = ["0"] +verification_key = ['0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'] +proof = ['0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/execution_success/recursion/src/main.nr b/noir/noir-repo/test_programs/execution_success/recursion/src/main.nr new file mode 100644 index 000000000000..f1b3875e1d4c --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/recursion/src/main.nr @@ -0,0 +1,16 @@ +use dep::std; + +// This test is used to generate artifacts for the compiler `integration-tests` +fn main( + verification_key: [Field; 114], + proof: [Field; 93], + public_inputs: [Field; 1], + key_hash: Field +) { + std::verify_proof( + verification_key.as_slice(), + proof.as_slice(), + public_inputs.as_slice(), + key_hash + ) +} diff --git a/noir/noir-repo/tooling/backend_interface/src/smart_contract.rs b/noir/noir-repo/tooling/backend_interface/src/smart_contract.rs index f6beeeb09d99..e2addeb66dff 100644 --- a/noir/noir-repo/tooling/backend_interface/src/smart_contract.rs +++ b/noir/noir-repo/tooling/backend_interface/src/smart_contract.rs @@ -3,7 +3,7 @@ use crate::{ cli::{ContractCommand, WriteVkCommand}, Backend, BackendError, }; -use acvm::acir::circuit::Program; +use acvm::acir::circuit::{Circuit, Program}; use tempfile::tempdir; impl Backend { @@ -17,6 +17,7 @@ impl Backend { // Create a temporary file for the circuit let bytecode_path = temp_directory_path.join("program").with_extension("bytecode"); let serialized_program = Program::serialize_program(program); + // let serialized_program = Circuit::serialize_circuit(&program.functions[0]); write_to_file(&serialized_program, &bytecode_path); // Create the verification key and write it to the specified path diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/fs/witness.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/fs/witness.rs index ea6bf8bbb11f..52b5c385e5df 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/fs/witness.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/fs/witness.rs @@ -13,7 +13,7 @@ pub(crate) fn save_witness_to_dir>( ) -> Result { create_named_dir(witness_dir.as_ref(), "witness"); let witness_path = witness_dir.as_ref().join(witness_name).with_extension(WITNESS_EXT); - dbg!(witnesses.clone()); + // TODO(https://github.com/noir-lang/noir/issues/4428) let witness_stack: WitnessStack = witnesses.into(); let buf: Vec = witness_stack.try_into()?; From 24749d929c8e749d711e5c8d3bf3f608019ca57d Mon Sep 17 00:00:00 2001 From: vezenovm Date: Tue, 12 Mar 2024 03:12:08 +0000 Subject: [PATCH 034/139] skip recursion in acir tests --- barretenberg/acir_tests/run_acir_tests.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/barretenberg/acir_tests/run_acir_tests.sh b/barretenberg/acir_tests/run_acir_tests.sh index 88189a434380..4203d9448f91 100755 --- a/barretenberg/acir_tests/run_acir_tests.sh +++ b/barretenberg/acir_tests/run_acir_tests.sh @@ -35,7 +35,7 @@ export BIN CRS_PATH VERBOSE BRANCH cd acir_tests # Convert them to array -SKIP_ARRAY=(diamond_deps_0 workspace workspace_default_member) +SKIP_ARRAY=(diamond_deps_0 workspace workspace_default_member recursion) function test() { cd $1 From d6707ca6545bddfe5e76154ef49c9a54cb7dfb40 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Tue, 12 Mar 2024 03:41:49 +0000 Subject: [PATCH 035/139] Revert "merge conflicts w/ master" This reverts commit c6cc6315dddf4d42d5b9a59a56d60bfffd91d04e, reversing changes made to 5ce2b3e5bfe08fb3ac9b6c9e57e2742d64a9c1b1. --- .circleci/config.yml | 214 +- .vscode/settings.json | 1 - avm-transpiler/src/transpile_contract.rs | 13 +- .../acir_tests/flows/write_contract.sh | 7 - barretenberg/acir_tests/run_acir_tests.sh | 2 +- .../acir_format/acir_to_constraint_buf.hpp | 82 +- .../dsl/acir_format/serde/acir.hpp | 1797 +++++------ .../dsl/acir_format/serde/index.hpp | 4 +- .../dsl/acir_format/serde/witness_map.hpp | 123 + .../dsl/acir_format/serde/witness_stack.hpp | 247 -- build_manifest.yml | 3 - noir/Dockerfile.packages | 6 - noir/Dockerfile.packages-test | 6 - .../noir-repo/acvm-repo/acir/codegen/acir.cpp | 1712 +++++----- .../acvm-repo/acir/codegen/witness.cpp | 130 +- .../acvm-repo/acir/src/circuit/mod.rs | 74 - noir/noir-repo/acvm-repo/acir/src/lib.rs | 10 +- .../acvm-repo/acir/src/native_types/mod.rs | 4 +- .../acir/src/native_types/witness_stack.rs | 64 - .../acir/tests/test_program_serialization.rs | 119 +- .../acvm-repo/acvm_js/src/compression.rs | 15 +- .../acvm-repo/acvm_js/src/execute.rs | 8 +- .../acvm-repo/acvm_js/src/public_witness.rs | 29 +- .../acvm-repo/acvm_js/test/shared/addition.ts | 11 +- .../test/shared/complex_foreign_call.ts | 16 +- .../test/shared/fixed_base_scalar_mul.ts | 6 +- .../acvm_js/test/shared/foreign_call.ts | 9 +- .../acvm_js/test/shared/memory_op.ts | 9 +- .../acvm-repo/acvm_js/test/shared/pedersen.ts | 5 +- .../acvm_js/test/shared/schnorr_verify.ts | 28 +- .../test/shared/witness_compression.ts | 23 +- .../compiler/integration-tests/.gitignore | 1 + .../integration-tests/contracts/1_mul.sol | 2869 ----------------- .../contracts/assert_statement.sol | 2869 ----------------- .../integration-tests/contracts/recursion.sol | 2869 ----------------- .../compiler/integration-tests/package.json | 2 +- .../compiler/noirc_driver/src/contract.rs | 8 +- .../compiler/noirc_driver/src/lib.rs | 9 +- .../compiler/noirc_driver/src/program.rs | 8 +- .../execution_success/recursion/Nargo.toml | 7 - .../execution_success/recursion/Prover.toml | 4 - .../execution_success/recursion/src/main.nr | 16 - .../witness_compression/Nargo.toml | 7 - .../witness_compression/Prover.toml | 2 - .../witness_compression/src/main.nr | 4 - .../backend_interface/src/proof_system.rs | 27 +- .../backend_interface/src/smart_contract.rs | 16 +- noir/noir-repo/tooling/debugger/src/dap.rs | 9 +- .../tooling/nargo/src/artifacts/contract.rs | 8 +- .../tooling/nargo/src/artifacts/program.rs | 24 +- .../tooling/nargo/src/ops/optimize.rs | 20 +- noir/noir-repo/tooling/nargo/src/ops/test.rs | 15 +- .../tooling/nargo/src/ops/transform.rs | 18 +- .../nargo_cli/src/cli/codegen_verifier_cmd.rs | 8 +- .../tooling/nargo_cli/src/cli/compile_cmd.rs | 4 +- .../tooling/nargo_cli/src/cli/debug_cmd.rs | 2 +- .../tooling/nargo_cli/src/cli/execute_cmd.rs | 3 +- .../tooling/nargo_cli/src/cli/fs/program.rs | 9 +- .../tooling/nargo_cli/src/cli/fs/witness.rs | 6 +- .../tooling/nargo_cli/src/cli/info_cmd.rs | 8 +- .../tooling/nargo_cli/src/cli/prove_cmd.rs | 4 +- .../tooling/nargo_cli/src/cli/verify_cmd.rs | 2 +- .../noir-repo/tooling/nargo_cli/src/errors.rs | 6 +- .../tooling/noir_js/test/node/e2e.test.ts | 72 +- .../noir_js_backend_barretenberg/package.json | 2 +- .../noir_js_backend_barretenberg/src/index.ts | 1 + noir/noir-repo/yarn.lock | 13 +- noir/scripts/test_native.sh | 2 +- 68 files changed, 2250 insertions(+), 11481 deletions(-) delete mode 100755 barretenberg/acir_tests/flows/write_contract.sh create mode 100644 barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/witness_map.hpp delete mode 100644 barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/witness_stack.hpp delete mode 100644 noir/noir-repo/acvm-repo/acir/src/native_types/witness_stack.rs delete mode 100644 noir/noir-repo/compiler/integration-tests/contracts/1_mul.sol delete mode 100644 noir/noir-repo/compiler/integration-tests/contracts/assert_statement.sol delete mode 100644 noir/noir-repo/compiler/integration-tests/contracts/recursion.sol delete mode 100644 noir/noir-repo/test_programs/execution_success/recursion/Nargo.toml delete mode 100644 noir/noir-repo/test_programs/execution_success/recursion/Prover.toml delete mode 100644 noir/noir-repo/test_programs/execution_success/recursion/src/main.nr delete mode 100644 noir/noir-repo/test_programs/execution_success/witness_compression/Nargo.toml delete mode 100644 noir/noir-repo/test_programs/execution_success/witness_compression/Prover.toml delete mode 100644 noir/noir-repo/test_programs/execution_success/witness_compression/src/main.nr diff --git a/.circleci/config.yml b/.circleci/config.yml index d30da596fb5b..3579c1e18e5f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -92,6 +92,103 @@ jobs: - continuation/continue: configuration_path: .circleci/generated_config.yml + # Noir + noir-x86_64: + docker: + - image: aztecprotocol/alpine-build-image + resource_class: small + steps: + - *checkout + - *setup_env + - run: + name: "Build" + command: cond_spot_run_build noir 32 + aztec_manifest_key: noir + + noir-arm64: + docker: + - image: aztecprotocol/alpine-build-image + resource_class: small + steps: + - *checkout + - *setup_env + - run: + name: "Build" + command: cond_spot_run_build noir 32 arm64 + aztec_manifest_key: noir + + noir-ecr-manifest: + machine: + image: default + resource_class: medium + steps: + - *checkout + - *setup_env + - run: + name: "Create ECR manifest" + command: create_ecr_manifest noir x86_64,arm64 + aztec_manifest_key: noir + + noir-tests: + docker: + - image: aztecprotocol/alpine-build-image + resource_class: small + steps: + - *checkout + - *setup_env + - run: + name: "Build" + command: cond_spot_run_build noir-tests 32 + aztec_manifest_key: noir-tests + + noir-packages: + docker: + - image: aztecprotocol/alpine-build-image + resource_class: small + steps: + - *checkout + - *setup_env + - run: + name: "Build" + command: cond_spot_run_build noir-packages 32 + aztec_manifest_key: noir-packages + + noir-packages-tests: + docker: + - image: aztecprotocol/alpine-build-image + resource_class: small + steps: + - *checkout + - *setup_env + - run: + name: "Build" + command: cond_spot_run_build noir-packages-tests 32 + aztec_manifest_key: noir-packages-tests + + noir-compile-acir-tests: + docker: + - image: aztecprotocol/alpine-build-image + resource_class: small + steps: + - *checkout + - *setup_env + - run: + name: "Build" + command: cond_spot_run_build noir-compile-acir-tests 32 + aztec_manifest_key: noir-compile-acir-tests + + avm-transpiler: + docker: + - image: aztecprotocol/alpine-build-image + resource_class: small + steps: + - *checkout + - *setup_env + - run: + name: "Build" + command: cond_spot_run_build avm-transpiler 32 + aztec_manifest_key: avm-transpiler + # Barretenberg barretenberg-wasm-linux-clang: docker: @@ -259,7 +356,7 @@ jobs: command: cond_spot_run_test barretenberg-x86_64-linux-clang-assert 32 ./scripts/run_tests 3 stdlib_recursion_tests --gtest_filter=-*turbo* aztec_manifest_key: barretenberg-x86_64-linux-clang-assert - barretenberg-join-split-tests: + barretenberg-acir-tests-bb: docker: - image: aztecprotocol/alpine-build-image resource_class: small @@ -267,9 +364,9 @@ jobs: - *checkout - *setup_env - run: - name: "Test" - command: cond_spot_run_test barretenberg-x86_64-linux-clang-assert 32 ./scripts/run_tests 3 join_split_example_proofs_join_split_tests --gtest_filter=-*full_proof* - aztec_manifest_key: barretenberg-x86_64-linux-clang-assert + name: "Build and test" + command: cond_spot_run_build barretenberg-acir-tests-bb 32 + aztec_manifest_key: barretenberg-acir-tests-bb barretenberg-acir-tests-bb-sol: docker: @@ -306,115 +403,6 @@ jobs: name: "Build and test" command: cond_spot_run_test bb.js 32 ./scripts/run_tests aztec_manifest_key: bb.js - - # Noir - noir-x86_64: - docker: - - image: aztecprotocol/alpine-build-image - resource_class: small - steps: - - *checkout - - *setup_env - - run: - name: "Build" - command: cond_spot_run_build noir 32 - aztec_manifest_key: noir - - noir-arm64: - docker: - - image: aztecprotocol/alpine-build-image - resource_class: small - steps: - - *checkout - - *setup_env - - run: - name: "Build" - command: cond_spot_run_build noir 32 arm64 - aztec_manifest_key: noir - - noir-ecr-manifest: - machine: - image: default - resource_class: medium - steps: - - *checkout - - *setup_env - - run: - name: "Create ECR manifest" - command: create_ecr_manifest noir x86_64,arm64 - aztec_manifest_key: noir - - noir-tests: - docker: - - image: aztecprotocol/alpine-build-image - resource_class: small - steps: - - *checkout - - *setup_env - - run: - name: "Build" - command: cond_spot_run_build noir-tests 32 - aztec_manifest_key: noir-tests - - noir-packages: - docker: - - image: aztecprotocol/alpine-build-image - resource_class: small - steps: - - *checkout - - *setup_env - - run: - name: "Build" - command: cond_spot_run_build noir-packages 32 - aztec_manifest_key: noir-packages - - noir-packages-tests: - docker: - - image: aztecprotocol/alpine-build-image - resource_class: small - steps: - - *checkout - - *setup_env - - run: - name: "Build" - command: cond_spot_run_build noir-packages-tests 32 - aztec_manifest_key: noir-packages-tests - - noir-compile-acir-tests: - docker: - - image: aztecprotocol/alpine-build-image - resource_class: small - steps: - - *checkout - - *setup_env - - run: - name: "Build" - command: cond_spot_run_build noir-compile-acir-tests 32 - aztec_manifest_key: noir-compile-acir-tests - - avm-transpiler: - docker: - - image: aztecprotocol/alpine-build-image - resource_class: small - steps: - - *checkout - - *setup_env - - run: - name: "Build" - command: cond_spot_run_build avm-transpiler 32 - aztec_manifest_key: avm-transpiler - - barretenberg-acir-tests-bb: - docker: - - image: aztecprotocol/alpine-build-image - resource_class: small - steps: - - *checkout - - *setup_env - - run: - name: "Build and test" - command: cond_spot_run_build barretenberg-acir-tests-bb 32 - aztec_manifest_key: barretenberg-acir-tests-bb bb-js-acir-tests: docker: diff --git a/.vscode/settings.json b/.vscode/settings.json index 98b15088b502..2e610b828f9d 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -158,7 +158,6 @@ "C_Cpp.default.includePath": ["barretenberg/cpp/src"], "rust-analyzer.linkedProjects": [ "noir/noir-repo/Cargo.toml", - "noir/noir-repo/acvm-repo/acvm_js/Cargo.toml", "avm-transpiler/Cargo.toml" ] } diff --git a/avm-transpiler/src/transpile_contract.rs b/avm-transpiler/src/transpile_contract.rs index dc3453bf8b5c..77528a460571 100644 --- a/avm-transpiler/src/transpile_contract.rs +++ b/avm-transpiler/src/transpile_contract.rs @@ -3,8 +3,7 @@ use log::info; use regex::Regex; use serde::{Deserialize, Serialize}; -use acvm::acir::circuit::Program; -use noirc_driver::ContractFunctionType; +use acvm::acir::circuit::Circuit; use crate::transpile::brillig_to_avm; use crate::utils::extract_brillig_from_acir; @@ -56,10 +55,10 @@ pub struct AcirContractFunction { pub custom_attributes: Vec, pub abi: serde_json::Value, #[serde( - serialize_with = "Program::serialize_program_base64", - deserialize_with = "Program::deserialize_program_base64" + serialize_with = "Circuit::serialize_circuit_base64", + deserialize_with = "Circuit::deserialize_circuit_base64" )] - pub bytecode: Program, + pub bytecode: Circuit, pub debug_symbols: serde_json::Value, } @@ -92,8 +91,8 @@ impl From for TranspiledContract { function.name, contract.name ); // Extract Brillig Opcodes from acir - let acir_program = function.bytecode; - let brillig = extract_brillig_from_acir(&acir_program.functions[0].opcodes); + let acir_circuit = function.bytecode.clone(); + let brillig = extract_brillig_from_acir(&acir_circuit.opcodes); // Transpile to AVM let avm_bytecode = brillig_to_avm(brillig); diff --git a/barretenberg/acir_tests/flows/write_contract.sh b/barretenberg/acir_tests/flows/write_contract.sh deleted file mode 100755 index 4f483395c58d..000000000000 --- a/barretenberg/acir_tests/flows/write_contract.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/sh -set -eu - -export TEST_NAME=$(basename $(pwd)) - -$BIN write_vk -o vk -$BIN contract -k vk -c $CRS_PATH -b ./target/acir.gz -o $TEST_NAME.sol diff --git a/barretenberg/acir_tests/run_acir_tests.sh b/barretenberg/acir_tests/run_acir_tests.sh index 4203d9448f91..88189a434380 100755 --- a/barretenberg/acir_tests/run_acir_tests.sh +++ b/barretenberg/acir_tests/run_acir_tests.sh @@ -35,7 +35,7 @@ export BIN CRS_PATH VERBOSE BRANCH cd acir_tests # Convert them to array -SKIP_ARRAY=(diamond_deps_0 workspace workspace_default_member recursion) +SKIP_ARRAY=(diamond_deps_0 workspace workspace_default_member) function test() { cd $1 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 58d036f4e165..f7a5cbcf44d1 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 @@ -26,10 +26,10 @@ namespace acir_format { * * @param arg acir representation of an 3-wire arithmetic operation * @return poly_triple - * @note In principle Program::Expression can accommodate arbitrarily many quadratic and linear terms but in practice + * @note In principle Circuit::Expression can accommodate arbitrarily many quadratic and linear terms but in practice * the ones processed here have a max of 1 and 3 respectively, in accordance with the standard width-3 arithmetic gate. */ -poly_triple serialize_arithmetic_gate(Program::Expression const& arg) +poly_triple serialize_arithmetic_gate(Circuit::Expression const& arg) { // TODO(https://github.com/AztecProtocol/barretenberg/issues/816): The initialization of the witness indices a,b,c // to 0 is implicitly assuming that (builder.zero_idx == 0) which is no longer the case. Now, witness idx 0 in @@ -98,17 +98,17 @@ poly_triple serialize_arithmetic_gate(Program::Expression const& arg) return pt; } -void handle_arithmetic(Program::Opcode::AssertZero const& arg, AcirFormat& af) +void handle_arithmetic(Circuit::Opcode::AssertZero const& arg, AcirFormat& af) { af.constraints.push_back(serialize_arithmetic_gate(arg.value)); } -void handle_blackbox_func_call(Program::Opcode::BlackBoxFuncCall const& arg, AcirFormat& af) +void handle_blackbox_func_call(Circuit::Opcode::BlackBoxFuncCall const& arg, AcirFormat& af) { std::visit( [&](auto&& arg) { using T = std::decay_t; - if constexpr (std::is_same_v) { + if constexpr (std::is_same_v) { af.logic_constraints.push_back(LogicConstraint{ .a = arg.lhs.witness.value, .b = arg.rhs.witness.value, @@ -116,7 +116,7 @@ void handle_blackbox_func_call(Program::Opcode::BlackBoxFuncCall const& arg, Aci .num_bits = arg.lhs.num_bits, .is_xor_gate = false, }); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { af.logic_constraints.push_back(LogicConstraint{ .a = arg.lhs.witness.value, .b = arg.rhs.witness.value, @@ -124,12 +124,12 @@ void handle_blackbox_func_call(Program::Opcode::BlackBoxFuncCall const& arg, Aci .num_bits = arg.lhs.num_bits, .is_xor_gate = true, }); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { af.range_constraints.push_back(RangeConstraint{ .witness = arg.input.witness.value, .num_bits = arg.input.num_bits, }); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { af.sha256_constraints.push_back(Sha256Constraint{ .inputs = map(arg.inputs, [](auto& e) { @@ -140,7 +140,7 @@ void handle_blackbox_func_call(Program::Opcode::BlackBoxFuncCall const& arg, Aci }), .result = map(arg.outputs, [](auto& e) { return e.value; }), }); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { af.sha256_compression.push_back(Sha256Compression{ .inputs = map(arg.inputs, [](auto& e) { @@ -158,7 +158,7 @@ void handle_blackbox_func_call(Program::Opcode::BlackBoxFuncCall const& arg, Aci }), .result = map(arg.outputs, [](auto& e) { return e.value; }), }); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { af.blake2s_constraints.push_back(Blake2sConstraint{ .inputs = map(arg.inputs, [](auto& e) { @@ -169,7 +169,7 @@ void handle_blackbox_func_call(Program::Opcode::BlackBoxFuncCall const& arg, Aci }), .result = map(arg.outputs, [](auto& e) { return e.value; }), }); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { af.blake3_constraints.push_back(Blake3Constraint{ .inputs = map(arg.inputs, [](auto& e) { @@ -180,7 +180,7 @@ void handle_blackbox_func_call(Program::Opcode::BlackBoxFuncCall const& arg, Aci }), .result = map(arg.outputs, [](auto& e) { return e.value; }), }); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { af.schnorr_constraints.push_back(SchnorrConstraint{ .message = map(arg.message, [](auto& e) { return e.witness.value; }), .public_key_x = arg.public_key_x.witness.value, @@ -188,20 +188,20 @@ void handle_blackbox_func_call(Program::Opcode::BlackBoxFuncCall const& arg, Aci .result = arg.output.value, .signature = map(arg.signature, [](auto& e) { return e.witness.value; }), }); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { af.pedersen_constraints.push_back(PedersenConstraint{ .scalars = map(arg.inputs, [](auto& e) { return e.witness.value; }), .hash_index = arg.domain_separator, .result_x = arg.outputs[0].value, .result_y = arg.outputs[1].value, }); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { af.pedersen_hash_constraints.push_back(PedersenHashConstraint{ .scalars = map(arg.inputs, [](auto& e) { return e.witness.value; }), .hash_index = arg.domain_separator, .result = arg.output.value, }); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { af.ecdsa_k1_constraints.push_back(EcdsaSecp256k1Constraint{ .hashed_message = map(arg.hashed_message, [](auto& e) { return e.witness.value; }), .signature = map(arg.signature, [](auto& e) { return e.witness.value; }), @@ -209,7 +209,7 @@ void handle_blackbox_func_call(Program::Opcode::BlackBoxFuncCall const& arg, Aci .pub_y_indices = map(arg.public_key_y, [](auto& e) { return e.witness.value; }), .result = arg.output.value, }); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { af.ecdsa_r1_constraints.push_back(EcdsaSecp256r1Constraint{ .hashed_message = map(arg.hashed_message, [](auto& e) { return e.witness.value; }), .pub_x_indices = map(arg.public_key_x, [](auto& e) { return e.witness.value; }), @@ -217,14 +217,14 @@ void handle_blackbox_func_call(Program::Opcode::BlackBoxFuncCall const& arg, Aci .result = arg.output.value, .signature = map(arg.signature, [](auto& e) { return e.witness.value; }), }); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { af.fixed_base_scalar_mul_constraints.push_back(FixedBaseScalarMul{ .low = arg.low.witness.value, .high = arg.high.witness.value, .pub_key_x = arg.outputs[0].value, .pub_key_y = arg.outputs[1].value, }); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { af.ec_add_constraints.push_back(EcAdd{ .input1_x = arg.input1_x.witness.value, .input1_y = arg.input1_y.witness.value, @@ -233,7 +233,7 @@ void handle_blackbox_func_call(Program::Opcode::BlackBoxFuncCall const& arg, Aci .result_x = arg.outputs[0].value, .result_y = arg.outputs[1].value, }); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { af.keccak_constraints.push_back(KeccakConstraint{ .inputs = map(arg.inputs, [](auto& e) { @@ -244,7 +244,7 @@ void handle_blackbox_func_call(Program::Opcode::BlackBoxFuncCall const& arg, Aci }), .result = map(arg.outputs, [](auto& e) { return e.value; }), }); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { af.keccak_var_constraints.push_back(KeccakVarConstraint{ .inputs = map(arg.inputs, [](auto& e) { @@ -256,12 +256,12 @@ void handle_blackbox_func_call(Program::Opcode::BlackBoxFuncCall const& arg, Aci .result = map(arg.outputs, [](auto& e) { return e.value; }), .var_message_size = arg.var_message_size.witness.value, }); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { af.keccak_permutations.push_back(Keccakf1600{ .state = map(arg.inputs, [](auto& e) { return e.witness.value; }), .result = map(arg.outputs, [](auto& e) { return e.value; }), }); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { auto c = RecursionConstraint{ .key = map(arg.verification_key, [](auto& e) { return e.witness.value; }), .proof = map(arg.proof, [](auto& e) { return e.witness.value; }), @@ -269,46 +269,46 @@ void handle_blackbox_func_call(Program::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) { + } 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) { + } else if constexpr (std::is_same_v) { af.bigint_to_le_bytes_constraints.push_back(BigIntToLeBytes{ .input = arg.input, .result = map(arg.outputs, [](auto& e) { return e.value; }), }); - } else if constexpr (std::is_same_v) { + } 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) { + } else if constexpr (std::is_same_v) { af.bigint_operations.push_back(BigIntOperation{ .lhs = arg.lhs, .rhs = arg.rhs, .result = arg.output, .opcode = BigIntOperationType::Sub, }); - } else if constexpr (std::is_same_v) { + } 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) { + } 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, }); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { af.poseidon2_constraints.push_back(Poseidon2Constraint{ .state = map(arg.inputs, [](auto& e) { return e.witness.value; }), .result = map(arg.outputs, [](auto& e) { return e.value; }), @@ -319,7 +319,7 @@ void handle_blackbox_func_call(Program::Opcode::BlackBoxFuncCall const& arg, Aci arg.value.value); } -BlockConstraint handle_memory_init(Program::Opcode::MemoryInit const& mem_init) +BlockConstraint handle_memory_init(Circuit::Opcode::MemoryInit const& mem_init) { BlockConstraint block{ .init = {}, .trace = {}, .type = BlockType::ROM }; std::vector init; @@ -341,13 +341,13 @@ BlockConstraint handle_memory_init(Program::Opcode::MemoryInit const& mem_init) return block; } -bool is_rom(Program::MemOp const& mem_op) +bool is_rom(Circuit::MemOp const& mem_op) { return mem_op.operation.mul_terms.size() == 0 && mem_op.operation.linear_combinations.size() == 0 && uint256_t(mem_op.operation.q_c) == 0; } -void handle_memory_op(Program::Opcode::MemoryOp const& mem_op, BlockConstraint& block) +void handle_memory_op(Circuit::Opcode::MemoryOp const& mem_op, BlockConstraint& block) { uint8_t access_type = 1; if (is_rom(mem_op.op)) { @@ -365,9 +365,7 @@ void handle_memory_op(Program::Opcode::MemoryOp const& mem_op, BlockConstraint& AcirFormat circuit_buf_to_acir_format(std::vector const& buf) { - // TODO(maxim): Handle the new `Program` structure once ACVM supports a function call stack. - // For now we expect a single ACIR function - auto circuit = Program::Program::bincodeDeserialize(buf).functions[0]; + auto circuit = Circuit::Circuit::bincodeDeserialize(buf); AcirFormat af; // `varnum` is the true number of variables, thus we add one to the index which starts at zero @@ -380,15 +378,15 @@ AcirFormat circuit_buf_to_acir_format(std::vector const& buf) std::visit( [&](auto&& arg) { using T = std::decay_t; - if constexpr (std::is_same_v) { + if constexpr (std::is_same_v) { handle_arithmetic(arg, af); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { handle_blackbox_func_call(arg, af); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { auto block = handle_memory_init(arg); uint32_t block_id = arg.block_id.value; block_id_to_block_constraint[block_id] = block; - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { auto block = block_id_to_block_constraint.find(arg.block_id.value); if (block == block_id_to_block_constraint.end()) { throw_or_abort("unitialized MemoryOp"); @@ -416,11 +414,7 @@ AcirFormat circuit_buf_to_acir_format(std::vector const& buf) */ WitnessVector witness_buf_to_witness_data(std::vector const& buf) { - // TODO(maxim): Handle the new `WitnessStack` structure once ACVM supports a function call stack - // A `StackItem` contains an index to an ACIR circuit and its respective ACIR-native `WitnessMap`. - // For now we expect the `WitnessStack` to contain a single witness. - auto w = WitnessStack::WitnessStack::bincodeDeserialize(buf).stack[0].witness; - + auto w = WitnessMap::WitnessMap::bincodeDeserialize(buf); WitnessVector wv; size_t index = 0; for (auto& e : w.value) { 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 82b105315afe..0170896c722f 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/acir.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/acir.hpp @@ -3,7 +3,7 @@ #include "bincode.hpp" #include "serde.hpp" -namespace Program { +namespace Circuit { struct BinaryFieldOp { @@ -140,7 +140,7 @@ struct MemoryAddress { }; struct HeapArray { - Program::MemoryAddress pointer; + Circuit::MemoryAddress pointer; uint64_t size; friend bool operator==(const HeapArray&, const HeapArray&); @@ -149,8 +149,8 @@ struct HeapArray { }; struct HeapVector { - Program::MemoryAddress pointer; - Program::MemoryAddress size; + Circuit::MemoryAddress pointer; + Circuit::MemoryAddress size; friend bool operator==(const HeapVector&, const HeapVector&); std::vector bincodeSerialize() const; @@ -160,8 +160,8 @@ struct HeapVector { struct BlackBoxOp { struct Sha256 { - Program::HeapVector message; - Program::HeapArray output; + Circuit::HeapVector message; + Circuit::HeapArray output; friend bool operator==(const Sha256&, const Sha256&); std::vector bincodeSerialize() const; @@ -169,8 +169,8 @@ struct BlackBoxOp { }; struct Blake2s { - Program::HeapVector message; - Program::HeapArray output; + Circuit::HeapVector message; + Circuit::HeapArray output; friend bool operator==(const Blake2s&, const Blake2s&); std::vector bincodeSerialize() const; @@ -178,8 +178,8 @@ struct BlackBoxOp { }; struct Blake3 { - Program::HeapVector message; - Program::HeapArray output; + Circuit::HeapVector message; + Circuit::HeapArray output; friend bool operator==(const Blake3&, const Blake3&); std::vector bincodeSerialize() const; @@ -187,8 +187,8 @@ struct BlackBoxOp { }; struct Keccak256 { - Program::HeapVector message; - Program::HeapArray output; + Circuit::HeapVector message; + Circuit::HeapArray output; friend bool operator==(const Keccak256&, const Keccak256&); std::vector bincodeSerialize() const; @@ -196,8 +196,8 @@ struct BlackBoxOp { }; struct Keccakf1600 { - Program::HeapVector message; - Program::HeapArray output; + Circuit::HeapVector message; + Circuit::HeapArray output; friend bool operator==(const Keccakf1600&, const Keccakf1600&); std::vector bincodeSerialize() const; @@ -205,11 +205,11 @@ struct BlackBoxOp { }; struct EcdsaSecp256k1 { - Program::HeapVector hashed_msg; - Program::HeapArray public_key_x; - Program::HeapArray public_key_y; - Program::HeapArray signature; - Program::MemoryAddress result; + Circuit::HeapVector hashed_msg; + Circuit::HeapArray public_key_x; + Circuit::HeapArray public_key_y; + Circuit::HeapArray signature; + Circuit::MemoryAddress result; friend bool operator==(const EcdsaSecp256k1&, const EcdsaSecp256k1&); std::vector bincodeSerialize() const; @@ -217,11 +217,11 @@ struct BlackBoxOp { }; struct EcdsaSecp256r1 { - Program::HeapVector hashed_msg; - Program::HeapArray public_key_x; - Program::HeapArray public_key_y; - Program::HeapArray signature; - Program::MemoryAddress result; + Circuit::HeapVector hashed_msg; + Circuit::HeapArray public_key_x; + Circuit::HeapArray public_key_y; + Circuit::HeapArray signature; + Circuit::MemoryAddress result; friend bool operator==(const EcdsaSecp256r1&, const EcdsaSecp256r1&); std::vector bincodeSerialize() const; @@ -229,11 +229,11 @@ struct BlackBoxOp { }; struct SchnorrVerify { - Program::MemoryAddress public_key_x; - Program::MemoryAddress public_key_y; - Program::HeapVector message; - Program::HeapVector signature; - Program::MemoryAddress result; + Circuit::MemoryAddress public_key_x; + Circuit::MemoryAddress public_key_y; + Circuit::HeapVector message; + Circuit::HeapVector signature; + Circuit::MemoryAddress result; friend bool operator==(const SchnorrVerify&, const SchnorrVerify&); std::vector bincodeSerialize() const; @@ -241,9 +241,9 @@ struct BlackBoxOp { }; struct PedersenCommitment { - Program::HeapVector inputs; - Program::MemoryAddress domain_separator; - Program::HeapArray output; + Circuit::HeapVector inputs; + Circuit::MemoryAddress domain_separator; + Circuit::HeapArray output; friend bool operator==(const PedersenCommitment&, const PedersenCommitment&); std::vector bincodeSerialize() const; @@ -251,9 +251,9 @@ struct BlackBoxOp { }; struct PedersenHash { - Program::HeapVector inputs; - Program::MemoryAddress domain_separator; - Program::MemoryAddress output; + Circuit::HeapVector inputs; + Circuit::MemoryAddress domain_separator; + Circuit::MemoryAddress output; friend bool operator==(const PedersenHash&, const PedersenHash&); std::vector bincodeSerialize() const; @@ -261,9 +261,9 @@ struct BlackBoxOp { }; struct FixedBaseScalarMul { - Program::MemoryAddress low; - Program::MemoryAddress high; - Program::HeapArray result; + Circuit::MemoryAddress low; + Circuit::MemoryAddress high; + Circuit::HeapArray result; friend bool operator==(const FixedBaseScalarMul&, const FixedBaseScalarMul&); std::vector bincodeSerialize() const; @@ -271,11 +271,11 @@ struct BlackBoxOp { }; struct EmbeddedCurveAdd { - Program::MemoryAddress input1_x; - Program::MemoryAddress input1_y; - Program::MemoryAddress input2_x; - Program::MemoryAddress input2_y; - Program::HeapArray result; + Circuit::MemoryAddress input1_x; + Circuit::MemoryAddress input1_y; + Circuit::MemoryAddress input2_x; + Circuit::MemoryAddress input2_y; + Circuit::HeapArray result; friend bool operator==(const EmbeddedCurveAdd&, const EmbeddedCurveAdd&); std::vector bincodeSerialize() const; @@ -283,9 +283,9 @@ struct BlackBoxOp { }; struct BigIntAdd { - Program::MemoryAddress lhs; - Program::MemoryAddress rhs; - Program::MemoryAddress output; + Circuit::MemoryAddress lhs; + Circuit::MemoryAddress rhs; + Circuit::MemoryAddress output; friend bool operator==(const BigIntAdd&, const BigIntAdd&); std::vector bincodeSerialize() const; @@ -293,9 +293,9 @@ struct BlackBoxOp { }; struct BigIntSub { - Program::MemoryAddress lhs; - Program::MemoryAddress rhs; - Program::MemoryAddress output; + Circuit::MemoryAddress lhs; + Circuit::MemoryAddress rhs; + Circuit::MemoryAddress output; friend bool operator==(const BigIntSub&, const BigIntSub&); std::vector bincodeSerialize() const; @@ -303,9 +303,9 @@ struct BlackBoxOp { }; struct BigIntMul { - Program::MemoryAddress lhs; - Program::MemoryAddress rhs; - Program::MemoryAddress output; + Circuit::MemoryAddress lhs; + Circuit::MemoryAddress rhs; + Circuit::MemoryAddress output; friend bool operator==(const BigIntMul&, const BigIntMul&); std::vector bincodeSerialize() const; @@ -313,9 +313,9 @@ struct BlackBoxOp { }; struct BigIntDiv { - Program::MemoryAddress lhs; - Program::MemoryAddress rhs; - Program::MemoryAddress output; + Circuit::MemoryAddress lhs; + Circuit::MemoryAddress rhs; + Circuit::MemoryAddress output; friend bool operator==(const BigIntDiv&, const BigIntDiv&); std::vector bincodeSerialize() const; @@ -323,9 +323,9 @@ struct BlackBoxOp { }; struct BigIntFromLeBytes { - Program::HeapVector inputs; - Program::HeapVector modulus; - Program::MemoryAddress output; + Circuit::HeapVector inputs; + Circuit::HeapVector modulus; + Circuit::MemoryAddress output; friend bool operator==(const BigIntFromLeBytes&, const BigIntFromLeBytes&); std::vector bincodeSerialize() const; @@ -333,8 +333,8 @@ struct BlackBoxOp { }; struct BigIntToLeBytes { - Program::MemoryAddress input; - Program::HeapVector output; + Circuit::MemoryAddress input; + Circuit::HeapVector output; friend bool operator==(const BigIntToLeBytes&, const BigIntToLeBytes&); std::vector bincodeSerialize() const; @@ -342,9 +342,9 @@ struct BlackBoxOp { }; struct Poseidon2Permutation { - Program::HeapVector message; - Program::HeapArray output; - Program::MemoryAddress len; + Circuit::HeapVector message; + Circuit::HeapArray output; + Circuit::MemoryAddress len; friend bool operator==(const Poseidon2Permutation&, const Poseidon2Permutation&); std::vector bincodeSerialize() const; @@ -352,9 +352,9 @@ struct BlackBoxOp { }; struct Sha256Compression { - Program::HeapVector input; - Program::HeapVector hash_values; - Program::HeapArray output; + Circuit::HeapVector input; + Circuit::HeapVector hash_values; + Circuit::HeapArray output; friend bool operator==(const Sha256Compression&, const Sha256Compression&); std::vector bincodeSerialize() const; @@ -399,7 +399,7 @@ struct HeapValueType { }; struct Array { - std::vector value_types; + std::vector value_types; uint64_t size; friend bool operator==(const Array&, const Array&); @@ -408,7 +408,7 @@ struct HeapValueType { }; struct Vector { - std::vector value_types; + std::vector value_types; friend bool operator==(const Vector&, const Vector&); std::vector bincodeSerialize() const; @@ -433,7 +433,7 @@ struct Value { struct ValueOrArray { struct MemoryAddress { - Program::MemoryAddress value; + Circuit::MemoryAddress value; friend bool operator==(const MemoryAddress&, const MemoryAddress&); std::vector bincodeSerialize() const; @@ -441,7 +441,7 @@ struct ValueOrArray { }; struct HeapArray { - Program::HeapArray value; + Circuit::HeapArray value; friend bool operator==(const HeapArray&, const HeapArray&); std::vector bincodeSerialize() const; @@ -449,7 +449,7 @@ struct ValueOrArray { }; struct HeapVector { - Program::HeapVector value; + Circuit::HeapVector value; friend bool operator==(const HeapVector&, const HeapVector&); std::vector bincodeSerialize() const; @@ -466,10 +466,10 @@ struct ValueOrArray { struct BrilligOpcode { struct BinaryFieldOp { - Program::MemoryAddress destination; - Program::BinaryFieldOp op; - Program::MemoryAddress lhs; - Program::MemoryAddress rhs; + Circuit::MemoryAddress destination; + Circuit::BinaryFieldOp op; + Circuit::MemoryAddress lhs; + Circuit::MemoryAddress rhs; friend bool operator==(const BinaryFieldOp&, const BinaryFieldOp&); std::vector bincodeSerialize() const; @@ -477,11 +477,11 @@ struct BrilligOpcode { }; struct BinaryIntOp { - Program::MemoryAddress destination; - Program::BinaryIntOp op; + Circuit::MemoryAddress destination; + Circuit::BinaryIntOp op; uint32_t bit_size; - Program::MemoryAddress lhs; - Program::MemoryAddress rhs; + Circuit::MemoryAddress lhs; + Circuit::MemoryAddress rhs; friend bool operator==(const BinaryIntOp&, const BinaryIntOp&); std::vector bincodeSerialize() const; @@ -489,8 +489,8 @@ struct BrilligOpcode { }; struct Cast { - Program::MemoryAddress destination; - Program::MemoryAddress source; + Circuit::MemoryAddress destination; + Circuit::MemoryAddress source; uint32_t bit_size; friend bool operator==(const Cast&, const Cast&); @@ -499,7 +499,7 @@ struct BrilligOpcode { }; struct JumpIfNot { - Program::MemoryAddress condition; + Circuit::MemoryAddress condition; uint64_t location; friend bool operator==(const JumpIfNot&, const JumpIfNot&); @@ -508,7 +508,7 @@ struct BrilligOpcode { }; struct JumpIf { - Program::MemoryAddress condition; + Circuit::MemoryAddress condition; uint64_t location; friend bool operator==(const JumpIf&, const JumpIf&); @@ -525,7 +525,7 @@ struct BrilligOpcode { }; struct CalldataCopy { - Program::MemoryAddress destination_address; + Circuit::MemoryAddress destination_address; uint64_t size; uint64_t offset; @@ -543,9 +543,9 @@ struct BrilligOpcode { }; struct Const { - Program::MemoryAddress destination; + Circuit::MemoryAddress destination; uint32_t bit_size; - Program::Value value; + Circuit::Value value; friend bool operator==(const Const&, const Const&); std::vector bincodeSerialize() const; @@ -560,10 +560,10 @@ struct BrilligOpcode { struct ForeignCall { std::string function; - std::vector destinations; - std::vector destination_value_types; - std::vector inputs; - std::vector input_value_types; + std::vector destinations; + std::vector destination_value_types; + std::vector inputs; + std::vector input_value_types; friend bool operator==(const ForeignCall&, const ForeignCall&); std::vector bincodeSerialize() const; @@ -571,8 +571,8 @@ struct BrilligOpcode { }; struct Mov { - Program::MemoryAddress destination; - Program::MemoryAddress source; + Circuit::MemoryAddress destination; + Circuit::MemoryAddress source; friend bool operator==(const Mov&, const Mov&); std::vector bincodeSerialize() const; @@ -580,8 +580,8 @@ struct BrilligOpcode { }; struct Load { - Program::MemoryAddress destination; - Program::MemoryAddress source_pointer; + Circuit::MemoryAddress destination; + Circuit::MemoryAddress source_pointer; friend bool operator==(const Load&, const Load&); std::vector bincodeSerialize() const; @@ -589,8 +589,8 @@ struct BrilligOpcode { }; struct Store { - Program::MemoryAddress destination_pointer; - Program::MemoryAddress source; + Circuit::MemoryAddress destination_pointer; + Circuit::MemoryAddress source; friend bool operator==(const Store&, const Store&); std::vector bincodeSerialize() const; @@ -598,7 +598,7 @@ struct BrilligOpcode { }; struct BlackBox { - Program::BlackBoxOp value; + Circuit::BlackBoxOp value; friend bool operator==(const BlackBox&, const BlackBox&); std::vector bincodeSerialize() const; @@ -653,7 +653,7 @@ struct Witness { }; struct FunctionInput { - Program::Witness witness; + Circuit::Witness witness; uint32_t num_bits; friend bool operator==(const FunctionInput&, const FunctionInput&); @@ -664,9 +664,9 @@ struct FunctionInput { struct BlackBoxFuncCall { struct AND { - Program::FunctionInput lhs; - Program::FunctionInput rhs; - Program::Witness output; + Circuit::FunctionInput lhs; + Circuit::FunctionInput rhs; + Circuit::Witness output; friend bool operator==(const AND&, const AND&); std::vector bincodeSerialize() const; @@ -674,9 +674,9 @@ struct BlackBoxFuncCall { }; struct XOR { - Program::FunctionInput lhs; - Program::FunctionInput rhs; - Program::Witness output; + Circuit::FunctionInput lhs; + Circuit::FunctionInput rhs; + Circuit::Witness output; friend bool operator==(const XOR&, const XOR&); std::vector bincodeSerialize() const; @@ -684,7 +684,7 @@ struct BlackBoxFuncCall { }; struct RANGE { - Program::FunctionInput input; + Circuit::FunctionInput input; friend bool operator==(const RANGE&, const RANGE&); std::vector bincodeSerialize() const; @@ -692,8 +692,8 @@ struct BlackBoxFuncCall { }; struct SHA256 { - std::vector inputs; - std::vector outputs; + std::vector inputs; + std::vector outputs; friend bool operator==(const SHA256&, const SHA256&); std::vector bincodeSerialize() const; @@ -701,8 +701,8 @@ struct BlackBoxFuncCall { }; struct Blake2s { - std::vector inputs; - std::vector outputs; + std::vector inputs; + std::vector outputs; friend bool operator==(const Blake2s&, const Blake2s&); std::vector bincodeSerialize() const; @@ -710,8 +710,8 @@ struct BlackBoxFuncCall { }; struct Blake3 { - std::vector inputs; - std::vector outputs; + std::vector inputs; + std::vector outputs; friend bool operator==(const Blake3&, const Blake3&); std::vector bincodeSerialize() const; @@ -719,11 +719,11 @@ struct BlackBoxFuncCall { }; struct SchnorrVerify { - Program::FunctionInput public_key_x; - Program::FunctionInput public_key_y; - std::vector signature; - std::vector message; - Program::Witness output; + Circuit::FunctionInput public_key_x; + Circuit::FunctionInput public_key_y; + std::vector signature; + std::vector message; + Circuit::Witness output; friend bool operator==(const SchnorrVerify&, const SchnorrVerify&); std::vector bincodeSerialize() const; @@ -731,9 +731,9 @@ struct BlackBoxFuncCall { }; struct PedersenCommitment { - std::vector inputs; + std::vector inputs; uint32_t domain_separator; - std::array outputs; + std::array outputs; friend bool operator==(const PedersenCommitment&, const PedersenCommitment&); std::vector bincodeSerialize() const; @@ -741,9 +741,9 @@ struct BlackBoxFuncCall { }; struct PedersenHash { - std::vector inputs; + std::vector inputs; uint32_t domain_separator; - Program::Witness output; + Circuit::Witness output; friend bool operator==(const PedersenHash&, const PedersenHash&); std::vector bincodeSerialize() const; @@ -751,11 +751,11 @@ struct BlackBoxFuncCall { }; struct EcdsaSecp256k1 { - std::vector public_key_x; - std::vector public_key_y; - std::vector signature; - std::vector hashed_message; - Program::Witness output; + std::vector public_key_x; + std::vector public_key_y; + std::vector signature; + std::vector hashed_message; + Circuit::Witness output; friend bool operator==(const EcdsaSecp256k1&, const EcdsaSecp256k1&); std::vector bincodeSerialize() const; @@ -763,11 +763,11 @@ struct BlackBoxFuncCall { }; struct EcdsaSecp256r1 { - std::vector public_key_x; - std::vector public_key_y; - std::vector signature; - std::vector hashed_message; - Program::Witness output; + std::vector public_key_x; + std::vector public_key_y; + std::vector signature; + std::vector hashed_message; + Circuit::Witness output; friend bool operator==(const EcdsaSecp256r1&, const EcdsaSecp256r1&); std::vector bincodeSerialize() const; @@ -775,9 +775,9 @@ struct BlackBoxFuncCall { }; struct FixedBaseScalarMul { - Program::FunctionInput low; - Program::FunctionInput high; - std::array outputs; + Circuit::FunctionInput low; + Circuit::FunctionInput high; + std::array outputs; friend bool operator==(const FixedBaseScalarMul&, const FixedBaseScalarMul&); std::vector bincodeSerialize() const; @@ -785,11 +785,11 @@ struct BlackBoxFuncCall { }; struct EmbeddedCurveAdd { - Program::FunctionInput input1_x; - Program::FunctionInput input1_y; - Program::FunctionInput input2_x; - Program::FunctionInput input2_y; - std::array outputs; + Circuit::FunctionInput input1_x; + Circuit::FunctionInput input1_y; + Circuit::FunctionInput input2_x; + Circuit::FunctionInput input2_y; + std::array outputs; friend bool operator==(const EmbeddedCurveAdd&, const EmbeddedCurveAdd&); std::vector bincodeSerialize() const; @@ -797,8 +797,8 @@ struct BlackBoxFuncCall { }; struct Keccak256 { - std::vector inputs; - std::vector outputs; + std::vector inputs; + std::vector outputs; friend bool operator==(const Keccak256&, const Keccak256&); std::vector bincodeSerialize() const; @@ -806,9 +806,9 @@ struct BlackBoxFuncCall { }; struct Keccak256VariableLength { - std::vector inputs; - Program::FunctionInput var_message_size; - std::vector outputs; + std::vector inputs; + Circuit::FunctionInput var_message_size; + std::vector outputs; friend bool operator==(const Keccak256VariableLength&, const Keccak256VariableLength&); std::vector bincodeSerialize() const; @@ -816,8 +816,8 @@ struct BlackBoxFuncCall { }; struct Keccakf1600 { - std::vector inputs; - std::vector outputs; + std::vector inputs; + std::vector outputs; friend bool operator==(const Keccakf1600&, const Keccakf1600&); std::vector bincodeSerialize() const; @@ -825,10 +825,10 @@ struct BlackBoxFuncCall { }; struct RecursiveAggregation { - std::vector verification_key; - std::vector proof; - std::vector public_inputs; - Program::FunctionInput key_hash; + std::vector verification_key; + std::vector proof; + std::vector public_inputs; + Circuit::FunctionInput key_hash; friend bool operator==(const RecursiveAggregation&, const RecursiveAggregation&); std::vector bincodeSerialize() const; @@ -876,7 +876,7 @@ struct BlackBoxFuncCall { }; struct BigIntFromLeBytes { - std::vector inputs; + std::vector inputs; std::vector modulus; uint32_t output; @@ -887,7 +887,7 @@ struct BlackBoxFuncCall { struct BigIntToLeBytes { uint32_t input; - std::vector outputs; + std::vector outputs; friend bool operator==(const BigIntToLeBytes&, const BigIntToLeBytes&); std::vector bincodeSerialize() const; @@ -895,8 +895,8 @@ struct BlackBoxFuncCall { }; struct Poseidon2Permutation { - std::vector inputs; - std::vector outputs; + std::vector inputs; + std::vector outputs; uint32_t len; friend bool operator==(const Poseidon2Permutation&, const Poseidon2Permutation&); @@ -905,9 +905,9 @@ struct BlackBoxFuncCall { }; struct Sha256Compression { - std::vector inputs; - std::vector hash_values; - std::vector outputs; + std::vector inputs; + std::vector hash_values; + std::vector outputs; friend bool operator==(const Sha256Compression&, const Sha256Compression&); std::vector bincodeSerialize() const; @@ -955,8 +955,8 @@ struct BlockId { }; struct Expression { - std::vector> mul_terms; - std::vector> linear_combinations; + std::vector> mul_terms; + std::vector> linear_combinations; std::string q_c; friend bool operator==(const Expression&, const Expression&); @@ -967,7 +967,7 @@ struct Expression { struct BrilligInputs { struct Single { - Program::Expression value; + Circuit::Expression value; friend bool operator==(const Single&, const Single&); std::vector bincodeSerialize() const; @@ -975,7 +975,7 @@ struct BrilligInputs { }; struct Array { - std::vector value; + std::vector value; friend bool operator==(const Array&, const Array&); std::vector bincodeSerialize() const; @@ -983,7 +983,7 @@ struct BrilligInputs { }; struct MemoryArray { - Program::BlockId value; + Circuit::BlockId value; friend bool operator==(const MemoryArray&, const MemoryArray&); std::vector bincodeSerialize() const; @@ -1000,7 +1000,7 @@ struct BrilligInputs { struct BrilligOutputs { struct Simple { - Program::Witness value; + Circuit::Witness value; friend bool operator==(const Simple&, const Simple&); std::vector bincodeSerialize() const; @@ -1008,7 +1008,7 @@ struct BrilligOutputs { }; struct Array { - std::vector value; + std::vector value; friend bool operator==(const Array&, const Array&); std::vector bincodeSerialize() const; @@ -1023,10 +1023,10 @@ struct BrilligOutputs { }; struct Brillig { - std::vector inputs; - std::vector outputs; - std::vector bytecode; - std::optional predicate; + std::vector inputs; + std::vector outputs; + std::vector bytecode; + std::optional predicate; friend bool operator==(const Brillig&, const Brillig&); std::vector bincodeSerialize() const; @@ -1036,8 +1036,8 @@ struct Brillig { struct Directive { struct ToLeRadix { - Program::Expression a; - std::vector b; + Circuit::Expression a; + std::vector b; uint32_t radix; friend bool operator==(const ToLeRadix&, const ToLeRadix&); @@ -1053,9 +1053,9 @@ struct Directive { }; struct MemOp { - Program::Expression operation; - Program::Expression index; - Program::Expression value; + Circuit::Expression operation; + Circuit::Expression index; + Circuit::Expression value; friend bool operator==(const MemOp&, const MemOp&); std::vector bincodeSerialize() const; @@ -1065,7 +1065,7 @@ struct MemOp { struct Opcode { struct AssertZero { - Program::Expression value; + Circuit::Expression value; friend bool operator==(const AssertZero&, const AssertZero&); std::vector bincodeSerialize() const; @@ -1073,7 +1073,7 @@ struct Opcode { }; struct BlackBoxFuncCall { - Program::BlackBoxFuncCall value; + Circuit::BlackBoxFuncCall value; friend bool operator==(const BlackBoxFuncCall&, const BlackBoxFuncCall&); std::vector bincodeSerialize() const; @@ -1081,7 +1081,7 @@ struct Opcode { }; struct Directive { - Program::Directive value; + Circuit::Directive value; friend bool operator==(const Directive&, const Directive&); std::vector bincodeSerialize() const; @@ -1089,7 +1089,7 @@ struct Opcode { }; struct Brillig { - Program::Brillig value; + Circuit::Brillig value; friend bool operator==(const Brillig&, const Brillig&); std::vector bincodeSerialize() const; @@ -1097,9 +1097,9 @@ struct Opcode { }; struct MemoryOp { - Program::BlockId block_id; - Program::MemOp op; - std::optional predicate; + Circuit::BlockId block_id; + Circuit::MemOp op; + std::optional predicate; friend bool operator==(const MemoryOp&, const MemoryOp&); std::vector bincodeSerialize() const; @@ -1107,8 +1107,8 @@ struct Opcode { }; struct MemoryInit { - Program::BlockId block_id; - std::vector init; + Circuit::BlockId block_id; + std::vector init; friend bool operator==(const MemoryInit&, const MemoryInit&); std::vector bincodeSerialize() const; @@ -1117,8 +1117,8 @@ struct Opcode { struct Call { uint32_t id; - std::vector inputs; - std::vector outputs; + std::vector inputs; + std::vector outputs; friend bool operator==(const Call&, const Call&); std::vector bincodeSerialize() const; @@ -1182,7 +1182,7 @@ struct OpcodeLocation { }; struct PublicInputs { - std::vector value; + std::vector value; friend bool operator==(const PublicInputs&, const PublicInputs&); std::vector bincodeSerialize() const; @@ -1191,12 +1191,12 @@ struct PublicInputs { struct Circuit { uint32_t current_witness_index; - std::vector opcodes; - Program::ExpressionWidth expression_width; - std::vector private_parameters; - Program::PublicInputs public_parameters; - Program::PublicInputs return_values; - std::vector> assert_messages; + std::vector opcodes; + ExpressionWidth expression_width; + std::vector private_parameters; + PublicInputs public_parameters; + PublicInputs return_values; + std::vector> assert_messages; bool recursive; friend bool operator==(const Circuit&, const Circuit&); @@ -1204,17 +1204,9 @@ struct Circuit { static Circuit bincodeDeserialize(std::vector); }; -struct Program { - std::vector functions; +} // end of namespace Circuit - friend bool operator==(const Program&, const Program&); - std::vector bincodeSerialize() const; - static Program bincodeDeserialize(std::vector); -}; - -} // end of namespace Program - -namespace Program { +namespace Circuit { inline bool operator==(const BinaryFieldOp& lhs, const BinaryFieldOp& rhs) { @@ -1241,11 +1233,11 @@ inline BinaryFieldOp BinaryFieldOp::bincodeDeserialize(std::vector inpu return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BinaryFieldOp& obj, Serializer& serializer) +void serde::Serializable::serialize(const Circuit::BinaryFieldOp& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); @@ -1254,16 +1246,16 @@ void serde::Serializable::serialize(const Program::Binar template <> template -Program::BinaryFieldOp serde::Deserializable::deserialize(Deserializer& deserializer) +Circuit::BinaryFieldOp serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Program::BinaryFieldOp obj; + Circuit::BinaryFieldOp obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BinaryFieldOp::Add& lhs, const BinaryFieldOp::Add& rhs) { @@ -1287,23 +1279,23 @@ inline BinaryFieldOp::Add BinaryFieldOp::Add::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Program::BinaryFieldOp::Add& obj, +void serde::Serializable::serialize(const Circuit::BinaryFieldOp::Add& obj, Serializer& serializer) {} template <> template -Program::BinaryFieldOp::Add serde::Deserializable::deserialize(Deserializer& deserializer) +Circuit::BinaryFieldOp::Add serde::Deserializable::deserialize(Deserializer& deserializer) { - Program::BinaryFieldOp::Add obj; + Circuit::BinaryFieldOp::Add obj; return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BinaryFieldOp::Sub& lhs, const BinaryFieldOp::Sub& rhs) { @@ -1327,23 +1319,23 @@ inline BinaryFieldOp::Sub BinaryFieldOp::Sub::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Program::BinaryFieldOp::Sub& obj, +void serde::Serializable::serialize(const Circuit::BinaryFieldOp::Sub& obj, Serializer& serializer) {} template <> template -Program::BinaryFieldOp::Sub serde::Deserializable::deserialize(Deserializer& deserializer) +Circuit::BinaryFieldOp::Sub serde::Deserializable::deserialize(Deserializer& deserializer) { - Program::BinaryFieldOp::Sub obj; + Circuit::BinaryFieldOp::Sub obj; return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BinaryFieldOp::Mul& lhs, const BinaryFieldOp::Mul& rhs) { @@ -1367,23 +1359,23 @@ inline BinaryFieldOp::Mul BinaryFieldOp::Mul::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Program::BinaryFieldOp::Mul& obj, +void serde::Serializable::serialize(const Circuit::BinaryFieldOp::Mul& obj, Serializer& serializer) {} template <> template -Program::BinaryFieldOp::Mul serde::Deserializable::deserialize(Deserializer& deserializer) +Circuit::BinaryFieldOp::Mul serde::Deserializable::deserialize(Deserializer& deserializer) { - Program::BinaryFieldOp::Mul obj; + Circuit::BinaryFieldOp::Mul obj; return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BinaryFieldOp::Div& lhs, const BinaryFieldOp::Div& rhs) { @@ -1407,23 +1399,23 @@ inline BinaryFieldOp::Div BinaryFieldOp::Div::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Program::BinaryFieldOp::Div& obj, +void serde::Serializable::serialize(const Circuit::BinaryFieldOp::Div& obj, Serializer& serializer) {} template <> template -Program::BinaryFieldOp::Div serde::Deserializable::deserialize(Deserializer& deserializer) +Circuit::BinaryFieldOp::Div serde::Deserializable::deserialize(Deserializer& deserializer) { - Program::BinaryFieldOp::Div obj; + Circuit::BinaryFieldOp::Div obj; return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BinaryFieldOp::Equals& lhs, const BinaryFieldOp::Equals& rhs) { @@ -1447,24 +1439,24 @@ inline BinaryFieldOp::Equals BinaryFieldOp::Equals::bincodeDeserialize(std::vect return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BinaryFieldOp::Equals& obj, +void serde::Serializable::serialize(const Circuit::BinaryFieldOp::Equals& obj, Serializer& serializer) {} template <> template -Program::BinaryFieldOp::Equals serde::Deserializable::deserialize( +Circuit::BinaryFieldOp::Equals serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::BinaryFieldOp::Equals obj; + Circuit::BinaryFieldOp::Equals obj; return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BinaryIntOp& lhs, const BinaryIntOp& rhs) { @@ -1491,11 +1483,11 @@ inline BinaryIntOp BinaryIntOp::bincodeDeserialize(std::vector input) return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BinaryIntOp& obj, Serializer& serializer) +void serde::Serializable::serialize(const Circuit::BinaryIntOp& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); @@ -1504,16 +1496,16 @@ void serde::Serializable::serialize(const Program::BinaryI template <> template -Program::BinaryIntOp serde::Deserializable::deserialize(Deserializer& deserializer) +Circuit::BinaryIntOp serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Program::BinaryIntOp obj; + Circuit::BinaryIntOp obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BinaryIntOp::Add& lhs, const BinaryIntOp::Add& rhs) { @@ -1537,23 +1529,23 @@ inline BinaryIntOp::Add BinaryIntOp::Add::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Program::BinaryIntOp::Add& obj, +void serde::Serializable::serialize(const Circuit::BinaryIntOp::Add& obj, Serializer& serializer) {} template <> template -Program::BinaryIntOp::Add serde::Deserializable::deserialize(Deserializer& deserializer) +Circuit::BinaryIntOp::Add serde::Deserializable::deserialize(Deserializer& deserializer) { - Program::BinaryIntOp::Add obj; + Circuit::BinaryIntOp::Add obj; return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BinaryIntOp::Sub& lhs, const BinaryIntOp::Sub& rhs) { @@ -1577,23 +1569,23 @@ inline BinaryIntOp::Sub BinaryIntOp::Sub::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Program::BinaryIntOp::Sub& obj, +void serde::Serializable::serialize(const Circuit::BinaryIntOp::Sub& obj, Serializer& serializer) {} template <> template -Program::BinaryIntOp::Sub serde::Deserializable::deserialize(Deserializer& deserializer) +Circuit::BinaryIntOp::Sub serde::Deserializable::deserialize(Deserializer& deserializer) { - Program::BinaryIntOp::Sub obj; + Circuit::BinaryIntOp::Sub obj; return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BinaryIntOp::Mul& lhs, const BinaryIntOp::Mul& rhs) { @@ -1617,23 +1609,23 @@ inline BinaryIntOp::Mul BinaryIntOp::Mul::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Program::BinaryIntOp::Mul& obj, +void serde::Serializable::serialize(const Circuit::BinaryIntOp::Mul& obj, Serializer& serializer) {} template <> template -Program::BinaryIntOp::Mul serde::Deserializable::deserialize(Deserializer& deserializer) +Circuit::BinaryIntOp::Mul serde::Deserializable::deserialize(Deserializer& deserializer) { - Program::BinaryIntOp::Mul obj; + Circuit::BinaryIntOp::Mul obj; return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BinaryIntOp::SignedDiv& lhs, const BinaryIntOp::SignedDiv& rhs) { @@ -1657,24 +1649,24 @@ inline BinaryIntOp::SignedDiv BinaryIntOp::SignedDiv::bincodeDeserialize(std::ve return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BinaryIntOp::SignedDiv& obj, +void serde::Serializable::serialize(const Circuit::BinaryIntOp::SignedDiv& obj, Serializer& serializer) {} template <> template -Program::BinaryIntOp::SignedDiv serde::Deserializable::deserialize( +Circuit::BinaryIntOp::SignedDiv serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::BinaryIntOp::SignedDiv obj; + Circuit::BinaryIntOp::SignedDiv obj; return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BinaryIntOp::UnsignedDiv& lhs, const BinaryIntOp::UnsignedDiv& rhs) { @@ -1698,24 +1690,24 @@ inline BinaryIntOp::UnsignedDiv BinaryIntOp::UnsignedDiv::bincodeDeserialize(std return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BinaryIntOp::UnsignedDiv& obj, +void serde::Serializable::serialize(const Circuit::BinaryIntOp::UnsignedDiv& obj, Serializer& serializer) {} template <> template -Program::BinaryIntOp::UnsignedDiv serde::Deserializable::deserialize( +Circuit::BinaryIntOp::UnsignedDiv serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::BinaryIntOp::UnsignedDiv obj; + Circuit::BinaryIntOp::UnsignedDiv obj; return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BinaryIntOp::Equals& lhs, const BinaryIntOp::Equals& rhs) { @@ -1739,24 +1731,24 @@ inline BinaryIntOp::Equals BinaryIntOp::Equals::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Program::BinaryIntOp::Equals& obj, +void serde::Serializable::serialize(const Circuit::BinaryIntOp::Equals& obj, Serializer& serializer) {} template <> template -Program::BinaryIntOp::Equals serde::Deserializable::deserialize( +Circuit::BinaryIntOp::Equals serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::BinaryIntOp::Equals obj; + Circuit::BinaryIntOp::Equals obj; return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BinaryIntOp::LessThan& lhs, const BinaryIntOp::LessThan& rhs) { @@ -1780,24 +1772,24 @@ inline BinaryIntOp::LessThan BinaryIntOp::LessThan::bincodeDeserialize(std::vect return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BinaryIntOp::LessThan& obj, +void serde::Serializable::serialize(const Circuit::BinaryIntOp::LessThan& obj, Serializer& serializer) {} template <> template -Program::BinaryIntOp::LessThan serde::Deserializable::deserialize( +Circuit::BinaryIntOp::LessThan serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::BinaryIntOp::LessThan obj; + Circuit::BinaryIntOp::LessThan obj; return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BinaryIntOp::LessThanEquals& lhs, const BinaryIntOp::LessThanEquals& rhs) { @@ -1821,24 +1813,24 @@ inline BinaryIntOp::LessThanEquals BinaryIntOp::LessThanEquals::bincodeDeseriali return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize( - const Program::BinaryIntOp::LessThanEquals& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Circuit::BinaryIntOp::LessThanEquals& obj, Serializer& serializer) {} template <> template -Program::BinaryIntOp::LessThanEquals serde::Deserializable::deserialize( +Circuit::BinaryIntOp::LessThanEquals serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::BinaryIntOp::LessThanEquals obj; + Circuit::BinaryIntOp::LessThanEquals obj; return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BinaryIntOp::And& lhs, const BinaryIntOp::And& rhs) { @@ -1862,23 +1854,23 @@ inline BinaryIntOp::And BinaryIntOp::And::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Program::BinaryIntOp::And& obj, +void serde::Serializable::serialize(const Circuit::BinaryIntOp::And& obj, Serializer& serializer) {} template <> template -Program::BinaryIntOp::And serde::Deserializable::deserialize(Deserializer& deserializer) +Circuit::BinaryIntOp::And serde::Deserializable::deserialize(Deserializer& deserializer) { - Program::BinaryIntOp::And obj; + Circuit::BinaryIntOp::And obj; return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BinaryIntOp::Or& lhs, const BinaryIntOp::Or& rhs) { @@ -1902,23 +1894,23 @@ inline BinaryIntOp::Or BinaryIntOp::Or::bincodeDeserialize(std::vector return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BinaryIntOp::Or& obj, +void serde::Serializable::serialize(const Circuit::BinaryIntOp::Or& obj, Serializer& serializer) {} template <> template -Program::BinaryIntOp::Or serde::Deserializable::deserialize(Deserializer& deserializer) +Circuit::BinaryIntOp::Or serde::Deserializable::deserialize(Deserializer& deserializer) { - Program::BinaryIntOp::Or obj; + Circuit::BinaryIntOp::Or obj; return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BinaryIntOp::Xor& lhs, const BinaryIntOp::Xor& rhs) { @@ -1942,23 +1934,23 @@ inline BinaryIntOp::Xor BinaryIntOp::Xor::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Program::BinaryIntOp::Xor& obj, +void serde::Serializable::serialize(const Circuit::BinaryIntOp::Xor& obj, Serializer& serializer) {} template <> template -Program::BinaryIntOp::Xor serde::Deserializable::deserialize(Deserializer& deserializer) +Circuit::BinaryIntOp::Xor serde::Deserializable::deserialize(Deserializer& deserializer) { - Program::BinaryIntOp::Xor obj; + Circuit::BinaryIntOp::Xor obj; return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BinaryIntOp::Shl& lhs, const BinaryIntOp::Shl& rhs) { @@ -1982,23 +1974,23 @@ inline BinaryIntOp::Shl BinaryIntOp::Shl::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Program::BinaryIntOp::Shl& obj, +void serde::Serializable::serialize(const Circuit::BinaryIntOp::Shl& obj, Serializer& serializer) {} template <> template -Program::BinaryIntOp::Shl serde::Deserializable::deserialize(Deserializer& deserializer) +Circuit::BinaryIntOp::Shl serde::Deserializable::deserialize(Deserializer& deserializer) { - Program::BinaryIntOp::Shl obj; + Circuit::BinaryIntOp::Shl obj; return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BinaryIntOp::Shr& lhs, const BinaryIntOp::Shr& rhs) { @@ -2022,23 +2014,23 @@ inline BinaryIntOp::Shr BinaryIntOp::Shr::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Program::BinaryIntOp::Shr& obj, +void serde::Serializable::serialize(const Circuit::BinaryIntOp::Shr& obj, Serializer& serializer) {} template <> template -Program::BinaryIntOp::Shr serde::Deserializable::deserialize(Deserializer& deserializer) +Circuit::BinaryIntOp::Shr serde::Deserializable::deserialize(Deserializer& deserializer) { - Program::BinaryIntOp::Shr obj; + Circuit::BinaryIntOp::Shr obj; return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BlackBoxFuncCall& lhs, const BlackBoxFuncCall& rhs) { @@ -2065,11 +2057,11 @@ inline BlackBoxFuncCall BlackBoxFuncCall::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Program::BlackBoxFuncCall& obj, +void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall& obj, Serializer& serializer) { serializer.increase_container_depth(); @@ -2079,16 +2071,16 @@ void serde::Serializable::serialize(const Program::Bl template <> template -Program::BlackBoxFuncCall serde::Deserializable::deserialize(Deserializer& deserializer) +Circuit::BlackBoxFuncCall serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Program::BlackBoxFuncCall obj; + Circuit::BlackBoxFuncCall obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BlackBoxFuncCall::AND& lhs, const BlackBoxFuncCall::AND& rhs) { @@ -2121,11 +2113,11 @@ inline BlackBoxFuncCall::AND BlackBoxFuncCall::AND::bincodeDeserialize(std::vect return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BlackBoxFuncCall::AND& obj, +void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::AND& obj, Serializer& serializer) { serde::Serializable::serialize(obj.lhs, serializer); @@ -2135,17 +2127,17 @@ void serde::Serializable::serialize(const Progra template <> template -Program::BlackBoxFuncCall::AND serde::Deserializable::deserialize( +Circuit::BlackBoxFuncCall::AND serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::BlackBoxFuncCall::AND obj; + Circuit::BlackBoxFuncCall::AND obj; obj.lhs = serde::Deserializable::deserialize(deserializer); obj.rhs = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BlackBoxFuncCall::XOR& lhs, const BlackBoxFuncCall::XOR& rhs) { @@ -2178,11 +2170,11 @@ inline BlackBoxFuncCall::XOR BlackBoxFuncCall::XOR::bincodeDeserialize(std::vect return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BlackBoxFuncCall::XOR& obj, +void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::XOR& obj, Serializer& serializer) { serde::Serializable::serialize(obj.lhs, serializer); @@ -2192,17 +2184,17 @@ void serde::Serializable::serialize(const Progra template <> template -Program::BlackBoxFuncCall::XOR serde::Deserializable::deserialize( +Circuit::BlackBoxFuncCall::XOR serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::BlackBoxFuncCall::XOR obj; + Circuit::BlackBoxFuncCall::XOR obj; obj.lhs = serde::Deserializable::deserialize(deserializer); obj.rhs = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BlackBoxFuncCall::RANGE& lhs, const BlackBoxFuncCall::RANGE& rhs) { @@ -2229,11 +2221,11 @@ inline BlackBoxFuncCall::RANGE BlackBoxFuncCall::RANGE::bincodeDeserialize(std:: return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BlackBoxFuncCall::RANGE& obj, +void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::RANGE& obj, Serializer& serializer) { serde::Serializable::serialize(obj.input, serializer); @@ -2241,15 +2233,15 @@ void serde::Serializable::serialize(const Prog template <> template -Program::BlackBoxFuncCall::RANGE serde::Deserializable::deserialize( +Circuit::BlackBoxFuncCall::RANGE serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::BlackBoxFuncCall::RANGE obj; + Circuit::BlackBoxFuncCall::RANGE obj; obj.input = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BlackBoxFuncCall::SHA256& lhs, const BlackBoxFuncCall::SHA256& rhs) { @@ -2279,11 +2271,11 @@ inline BlackBoxFuncCall::SHA256 BlackBoxFuncCall::SHA256::bincodeDeserialize(std return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BlackBoxFuncCall::SHA256& obj, +void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::SHA256& obj, Serializer& serializer) { serde::Serializable::serialize(obj.inputs, serializer); @@ -2292,16 +2284,16 @@ void serde::Serializable::serialize(const Pro template <> template -Program::BlackBoxFuncCall::SHA256 serde::Deserializable::deserialize( +Circuit::BlackBoxFuncCall::SHA256 serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::BlackBoxFuncCall::SHA256 obj; + Circuit::BlackBoxFuncCall::SHA256 obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BlackBoxFuncCall::Blake2s& lhs, const BlackBoxFuncCall::Blake2s& rhs) { @@ -2331,11 +2323,11 @@ inline BlackBoxFuncCall::Blake2s BlackBoxFuncCall::Blake2s::bincodeDeserialize(s return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BlackBoxFuncCall::Blake2s& obj, +void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::Blake2s& obj, Serializer& serializer) { serde::Serializable::serialize(obj.inputs, serializer); @@ -2344,16 +2336,16 @@ void serde::Serializable::serialize(const Pr template <> template -Program::BlackBoxFuncCall::Blake2s serde::Deserializable::deserialize( +Circuit::BlackBoxFuncCall::Blake2s serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::BlackBoxFuncCall::Blake2s obj; + Circuit::BlackBoxFuncCall::Blake2s obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BlackBoxFuncCall::Blake3& lhs, const BlackBoxFuncCall::Blake3& rhs) { @@ -2383,11 +2375,11 @@ inline BlackBoxFuncCall::Blake3 BlackBoxFuncCall::Blake3::bincodeDeserialize(std return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BlackBoxFuncCall::Blake3& obj, +void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::Blake3& obj, Serializer& serializer) { serde::Serializable::serialize(obj.inputs, serializer); @@ -2396,16 +2388,16 @@ void serde::Serializable::serialize(const Pro template <> template -Program::BlackBoxFuncCall::Blake3 serde::Deserializable::deserialize( +Circuit::BlackBoxFuncCall::Blake3 serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::BlackBoxFuncCall::Blake3 obj; + Circuit::BlackBoxFuncCall::Blake3 obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BlackBoxFuncCall::SchnorrVerify& lhs, const BlackBoxFuncCall::SchnorrVerify& rhs) { @@ -2444,12 +2436,12 @@ inline BlackBoxFuncCall::SchnorrVerify BlackBoxFuncCall::SchnorrVerify::bincodeD return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize( - const Program::BlackBoxFuncCall::SchnorrVerify& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Circuit::BlackBoxFuncCall::SchnorrVerify& obj, Serializer& serializer) { serde::Serializable::serialize(obj.public_key_x, serializer); serde::Serializable::serialize(obj.public_key_y, serializer); @@ -2460,10 +2452,10 @@ void serde::Serializable::serialize( template <> template -Program::BlackBoxFuncCall::SchnorrVerify serde::Deserializable::deserialize( +Circuit::BlackBoxFuncCall::SchnorrVerify serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::BlackBoxFuncCall::SchnorrVerify obj; + Circuit::BlackBoxFuncCall::SchnorrVerify obj; obj.public_key_x = serde::Deserializable::deserialize(deserializer); obj.public_key_y = serde::Deserializable::deserialize(deserializer); obj.signature = serde::Deserializable::deserialize(deserializer); @@ -2472,7 +2464,7 @@ Program::BlackBoxFuncCall::SchnorrVerify serde::Deserializable template -void serde::Serializable::serialize( - const Program::BlackBoxFuncCall::PedersenCommitment& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Circuit::BlackBoxFuncCall::PedersenCommitment& obj, Serializer& serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.domain_separator, serializer); @@ -2520,17 +2512,17 @@ void serde::Serializable::seriali template <> template -Program::BlackBoxFuncCall::PedersenCommitment serde::Deserializable< - Program::BlackBoxFuncCall::PedersenCommitment>::deserialize(Deserializer& deserializer) +Circuit::BlackBoxFuncCall::PedersenCommitment serde::Deserializable< + Circuit::BlackBoxFuncCall::PedersenCommitment>::deserialize(Deserializer& deserializer) { - Program::BlackBoxFuncCall::PedersenCommitment obj; + Circuit::BlackBoxFuncCall::PedersenCommitment obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.domain_separator = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BlackBoxFuncCall::PedersenHash& lhs, const BlackBoxFuncCall::PedersenHash& rhs) { @@ -2563,12 +2555,12 @@ inline BlackBoxFuncCall::PedersenHash BlackBoxFuncCall::PedersenHash::bincodeDes return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize( - const Program::BlackBoxFuncCall::PedersenHash& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Circuit::BlackBoxFuncCall::PedersenHash& obj, Serializer& serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.domain_separator, serializer); @@ -2577,17 +2569,17 @@ void serde::Serializable::serialize( template <> template -Program::BlackBoxFuncCall::PedersenHash serde::Deserializable::deserialize( +Circuit::BlackBoxFuncCall::PedersenHash serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::BlackBoxFuncCall::PedersenHash obj; + Circuit::BlackBoxFuncCall::PedersenHash obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.domain_separator = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BlackBoxFuncCall::EcdsaSecp256k1& lhs, const BlackBoxFuncCall::EcdsaSecp256k1& rhs) { @@ -2626,12 +2618,12 @@ inline BlackBoxFuncCall::EcdsaSecp256k1 BlackBoxFuncCall::EcdsaSecp256k1::bincod return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize( - const Program::BlackBoxFuncCall::EcdsaSecp256k1& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Circuit::BlackBoxFuncCall::EcdsaSecp256k1& obj, Serializer& serializer) { serde::Serializable::serialize(obj.public_key_x, serializer); serde::Serializable::serialize(obj.public_key_y, serializer); @@ -2642,10 +2634,10 @@ void serde::Serializable::serialize( template <> template -Program::BlackBoxFuncCall::EcdsaSecp256k1 serde::Deserializable::deserialize( +Circuit::BlackBoxFuncCall::EcdsaSecp256k1 serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::BlackBoxFuncCall::EcdsaSecp256k1 obj; + Circuit::BlackBoxFuncCall::EcdsaSecp256k1 obj; obj.public_key_x = serde::Deserializable::deserialize(deserializer); obj.public_key_y = serde::Deserializable::deserialize(deserializer); obj.signature = serde::Deserializable::deserialize(deserializer); @@ -2654,7 +2646,7 @@ Program::BlackBoxFuncCall::EcdsaSecp256k1 serde::Deserializable template -void serde::Serializable::serialize( - const Program::BlackBoxFuncCall::EcdsaSecp256r1& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Circuit::BlackBoxFuncCall::EcdsaSecp256r1& obj, Serializer& serializer) { serde::Serializable::serialize(obj.public_key_x, serializer); serde::Serializable::serialize(obj.public_key_y, serializer); @@ -2709,10 +2701,10 @@ void serde::Serializable::serialize( template <> template -Program::BlackBoxFuncCall::EcdsaSecp256r1 serde::Deserializable::deserialize( +Circuit::BlackBoxFuncCall::EcdsaSecp256r1 serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::BlackBoxFuncCall::EcdsaSecp256r1 obj; + Circuit::BlackBoxFuncCall::EcdsaSecp256r1 obj; obj.public_key_x = serde::Deserializable::deserialize(deserializer); obj.public_key_y = serde::Deserializable::deserialize(deserializer); obj.signature = serde::Deserializable::deserialize(deserializer); @@ -2721,7 +2713,7 @@ Program::BlackBoxFuncCall::EcdsaSecp256r1 serde::Deserializable template -void serde::Serializable::serialize( - const Program::BlackBoxFuncCall::FixedBaseScalarMul& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Circuit::BlackBoxFuncCall::FixedBaseScalarMul& obj, Serializer& serializer) { serde::Serializable::serialize(obj.low, serializer); serde::Serializable::serialize(obj.high, serializer); @@ -2769,17 +2761,17 @@ void serde::Serializable::seriali template <> template -Program::BlackBoxFuncCall::FixedBaseScalarMul serde::Deserializable< - Program::BlackBoxFuncCall::FixedBaseScalarMul>::deserialize(Deserializer& deserializer) +Circuit::BlackBoxFuncCall::FixedBaseScalarMul serde::Deserializable< + Circuit::BlackBoxFuncCall::FixedBaseScalarMul>::deserialize(Deserializer& deserializer) { - Program::BlackBoxFuncCall::FixedBaseScalarMul obj; + Circuit::BlackBoxFuncCall::FixedBaseScalarMul obj; obj.low = serde::Deserializable::deserialize(deserializer); obj.high = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BlackBoxFuncCall::EmbeddedCurveAdd& lhs, const BlackBoxFuncCall::EmbeddedCurveAdd& rhs) { @@ -2819,12 +2811,12 @@ inline BlackBoxFuncCall::EmbeddedCurveAdd BlackBoxFuncCall::EmbeddedCurveAdd::bi return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize( - const Program::BlackBoxFuncCall::EmbeddedCurveAdd& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Circuit::BlackBoxFuncCall::EmbeddedCurveAdd& obj, Serializer& serializer) { serde::Serializable::serialize(obj.input1_x, serializer); serde::Serializable::serialize(obj.input1_y, serializer); @@ -2835,10 +2827,10 @@ void serde::Serializable::serialize template <> template -Program::BlackBoxFuncCall::EmbeddedCurveAdd serde::Deserializable< - Program::BlackBoxFuncCall::EmbeddedCurveAdd>::deserialize(Deserializer& deserializer) +Circuit::BlackBoxFuncCall::EmbeddedCurveAdd serde::Deserializable< + Circuit::BlackBoxFuncCall::EmbeddedCurveAdd>::deserialize(Deserializer& deserializer) { - Program::BlackBoxFuncCall::EmbeddedCurveAdd obj; + Circuit::BlackBoxFuncCall::EmbeddedCurveAdd obj; obj.input1_x = serde::Deserializable::deserialize(deserializer); obj.input1_y = serde::Deserializable::deserialize(deserializer); obj.input2_x = serde::Deserializable::deserialize(deserializer); @@ -2847,7 +2839,7 @@ Program::BlackBoxFuncCall::EmbeddedCurveAdd serde::Deserializable< return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BlackBoxFuncCall::Keccak256& lhs, const BlackBoxFuncCall::Keccak256& rhs) { @@ -2877,12 +2869,12 @@ inline BlackBoxFuncCall::Keccak256 BlackBoxFuncCall::Keccak256::bincodeDeseriali return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize( - const Program::BlackBoxFuncCall::Keccak256& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Circuit::BlackBoxFuncCall::Keccak256& obj, Serializer& serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.outputs, serializer); @@ -2890,16 +2882,16 @@ void serde::Serializable::serialize( template <> template -Program::BlackBoxFuncCall::Keccak256 serde::Deserializable::deserialize( +Circuit::BlackBoxFuncCall::Keccak256 serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::BlackBoxFuncCall::Keccak256 obj; + Circuit::BlackBoxFuncCall::Keccak256 obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BlackBoxFuncCall::Keccak256VariableLength& lhs, const BlackBoxFuncCall::Keccak256VariableLength& rhs) @@ -2934,12 +2926,12 @@ inline BlackBoxFuncCall::Keccak256VariableLength BlackBoxFuncCall::Keccak256Vari return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize( - const Program::BlackBoxFuncCall::Keccak256VariableLength& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Circuit::BlackBoxFuncCall::Keccak256VariableLength& obj, Serializer& serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.var_message_size, serializer); @@ -2948,17 +2940,17 @@ void serde::Serializable::se template <> template -Program::BlackBoxFuncCall::Keccak256VariableLength serde::Deserializable< - Program::BlackBoxFuncCall::Keccak256VariableLength>::deserialize(Deserializer& deserializer) +Circuit::BlackBoxFuncCall::Keccak256VariableLength serde::Deserializable< + Circuit::BlackBoxFuncCall::Keccak256VariableLength>::deserialize(Deserializer& deserializer) { - Program::BlackBoxFuncCall::Keccak256VariableLength obj; + Circuit::BlackBoxFuncCall::Keccak256VariableLength obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.var_message_size = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BlackBoxFuncCall::Keccakf1600& lhs, const BlackBoxFuncCall::Keccakf1600& rhs) { @@ -2988,12 +2980,12 @@ inline BlackBoxFuncCall::Keccakf1600 BlackBoxFuncCall::Keccakf1600::bincodeDeser return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize( - const Program::BlackBoxFuncCall::Keccakf1600& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Circuit::BlackBoxFuncCall::Keccakf1600& obj, Serializer& serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.outputs, serializer); @@ -3001,16 +2993,16 @@ void serde::Serializable::serialize( template <> template -Program::BlackBoxFuncCall::Keccakf1600 serde::Deserializable::deserialize( +Circuit::BlackBoxFuncCall::Keccakf1600 serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::BlackBoxFuncCall::Keccakf1600 obj; + Circuit::BlackBoxFuncCall::Keccakf1600 obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BlackBoxFuncCall::RecursiveAggregation& lhs, const BlackBoxFuncCall::RecursiveAggregation& rhs) @@ -3048,12 +3040,12 @@ inline BlackBoxFuncCall::RecursiveAggregation BlackBoxFuncCall::RecursiveAggrega return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize( - const Program::BlackBoxFuncCall::RecursiveAggregation& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Circuit::BlackBoxFuncCall::RecursiveAggregation& obj, Serializer& serializer) { serde::Serializable::serialize(obj.verification_key, serializer); serde::Serializable::serialize(obj.proof, serializer); @@ -3063,10 +3055,10 @@ void serde::Serializable::seria template <> template -Program::BlackBoxFuncCall::RecursiveAggregation serde::Deserializable< - Program::BlackBoxFuncCall::RecursiveAggregation>::deserialize(Deserializer& deserializer) +Circuit::BlackBoxFuncCall::RecursiveAggregation serde::Deserializable< + Circuit::BlackBoxFuncCall::RecursiveAggregation>::deserialize(Deserializer& deserializer) { - Program::BlackBoxFuncCall::RecursiveAggregation obj; + Circuit::BlackBoxFuncCall::RecursiveAggregation obj; obj.verification_key = serde::Deserializable::deserialize(deserializer); obj.proof = serde::Deserializable::deserialize(deserializer); obj.public_inputs = serde::Deserializable::deserialize(deserializer); @@ -3074,7 +3066,7 @@ Program::BlackBoxFuncCall::RecursiveAggregation serde::Deserializable< return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BlackBoxFuncCall::BigIntAdd& lhs, const BlackBoxFuncCall::BigIntAdd& rhs) { @@ -3107,12 +3099,12 @@ inline BlackBoxFuncCall::BigIntAdd BlackBoxFuncCall::BigIntAdd::bincodeDeseriali return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize( - const Program::BlackBoxFuncCall::BigIntAdd& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Circuit::BlackBoxFuncCall::BigIntAdd& obj, Serializer& serializer) { serde::Serializable::serialize(obj.lhs, serializer); serde::Serializable::serialize(obj.rhs, serializer); @@ -3121,17 +3113,17 @@ void serde::Serializable::serialize( template <> template -Program::BlackBoxFuncCall::BigIntAdd serde::Deserializable::deserialize( +Circuit::BlackBoxFuncCall::BigIntAdd serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::BlackBoxFuncCall::BigIntAdd obj; + 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 Program { +namespace Circuit { inline bool operator==(const BlackBoxFuncCall::BigIntSub& lhs, const BlackBoxFuncCall::BigIntSub& rhs) { @@ -3164,12 +3156,12 @@ inline BlackBoxFuncCall::BigIntSub BlackBoxFuncCall::BigIntSub::bincodeDeseriali return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize( - const Program::BlackBoxFuncCall::BigIntSub& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Circuit::BlackBoxFuncCall::BigIntSub& obj, Serializer& serializer) { serde::Serializable::serialize(obj.lhs, serializer); serde::Serializable::serialize(obj.rhs, serializer); @@ -3178,17 +3170,17 @@ void serde::Serializable::serialize( template <> template -Program::BlackBoxFuncCall::BigIntSub serde::Deserializable::deserialize( +Circuit::BlackBoxFuncCall::BigIntSub serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::BlackBoxFuncCall::BigIntSub obj; + Circuit::BlackBoxFuncCall::BigIntSub obj; obj.lhs = serde::Deserializable::deserialize(deserializer); obj.rhs = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BlackBoxFuncCall::BigIntMul& lhs, const BlackBoxFuncCall::BigIntMul& rhs) { @@ -3221,12 +3213,12 @@ inline BlackBoxFuncCall::BigIntMul BlackBoxFuncCall::BigIntMul::bincodeDeseriali return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize( - const Program::BlackBoxFuncCall::BigIntMul& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Circuit::BlackBoxFuncCall::BigIntMul& obj, Serializer& serializer) { serde::Serializable::serialize(obj.lhs, serializer); serde::Serializable::serialize(obj.rhs, serializer); @@ -3235,17 +3227,17 @@ void serde::Serializable::serialize( template <> template -Program::BlackBoxFuncCall::BigIntMul serde::Deserializable::deserialize( +Circuit::BlackBoxFuncCall::BigIntMul serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::BlackBoxFuncCall::BigIntMul obj; + 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 Program { +namespace Circuit { inline bool operator==(const BlackBoxFuncCall::BigIntDiv& lhs, const BlackBoxFuncCall::BigIntDiv& rhs) { @@ -3278,12 +3270,12 @@ inline BlackBoxFuncCall::BigIntDiv BlackBoxFuncCall::BigIntDiv::bincodeDeseriali return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize( - const Program::BlackBoxFuncCall::BigIntDiv& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Circuit::BlackBoxFuncCall::BigIntDiv& obj, Serializer& serializer) { serde::Serializable::serialize(obj.lhs, serializer); serde::Serializable::serialize(obj.rhs, serializer); @@ -3292,17 +3284,17 @@ void serde::Serializable::serialize( template <> template -Program::BlackBoxFuncCall::BigIntDiv serde::Deserializable::deserialize( +Circuit::BlackBoxFuncCall::BigIntDiv serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::BlackBoxFuncCall::BigIntDiv obj; + 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 Program { +namespace Circuit { inline bool operator==(const BlackBoxFuncCall::BigIntFromLeBytes& lhs, const BlackBoxFuncCall::BigIntFromLeBytes& rhs) { @@ -3336,12 +3328,12 @@ inline BlackBoxFuncCall::BigIntFromLeBytes BlackBoxFuncCall::BigIntFromLeBytes:: return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize( - const Program::BlackBoxFuncCall::BigIntFromLeBytes& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Circuit::BlackBoxFuncCall::BigIntFromLeBytes& obj, Serializer& serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.modulus, serializer); @@ -3350,17 +3342,17 @@ void serde::Serializable::serializ template <> template -Program::BlackBoxFuncCall::BigIntFromLeBytes serde::Deserializable< - Program::BlackBoxFuncCall::BigIntFromLeBytes>::deserialize(Deserializer& deserializer) +Circuit::BlackBoxFuncCall::BigIntFromLeBytes serde::Deserializable< + Circuit::BlackBoxFuncCall::BigIntFromLeBytes>::deserialize(Deserializer& deserializer) { - Program::BlackBoxFuncCall::BigIntFromLeBytes obj; + 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 Program { +namespace Circuit { inline bool operator==(const BlackBoxFuncCall::BigIntToLeBytes& lhs, const BlackBoxFuncCall::BigIntToLeBytes& rhs) { @@ -3391,12 +3383,12 @@ inline BlackBoxFuncCall::BigIntToLeBytes BlackBoxFuncCall::BigIntToLeBytes::binc return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize( - const Program::BlackBoxFuncCall::BigIntToLeBytes& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Circuit::BlackBoxFuncCall::BigIntToLeBytes& obj, Serializer& serializer) { serde::Serializable::serialize(obj.input, serializer); serde::Serializable::serialize(obj.outputs, serializer); @@ -3404,16 +3396,16 @@ void serde::Serializable::serialize( template <> template -Program::BlackBoxFuncCall::BigIntToLeBytes serde::Deserializable< - Program::BlackBoxFuncCall::BigIntToLeBytes>::deserialize(Deserializer& deserializer) +Circuit::BlackBoxFuncCall::BigIntToLeBytes serde::Deserializable< + Circuit::BlackBoxFuncCall::BigIntToLeBytes>::deserialize(Deserializer& deserializer) { - Program::BlackBoxFuncCall::BigIntToLeBytes obj; + Circuit::BlackBoxFuncCall::BigIntToLeBytes obj; obj.input = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BlackBoxFuncCall::Poseidon2Permutation& lhs, const BlackBoxFuncCall::Poseidon2Permutation& rhs) @@ -3448,12 +3440,12 @@ inline BlackBoxFuncCall::Poseidon2Permutation BlackBoxFuncCall::Poseidon2Permuta return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize( - const Program::BlackBoxFuncCall::Poseidon2Permutation& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Circuit::BlackBoxFuncCall::Poseidon2Permutation& obj, Serializer& serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.outputs, serializer); @@ -3462,17 +3454,17 @@ void serde::Serializable::seria template <> template -Program::BlackBoxFuncCall::Poseidon2Permutation serde::Deserializable< - Program::BlackBoxFuncCall::Poseidon2Permutation>::deserialize(Deserializer& deserializer) +Circuit::BlackBoxFuncCall::Poseidon2Permutation serde::Deserializable< + Circuit::BlackBoxFuncCall::Poseidon2Permutation>::deserialize(Deserializer& deserializer) { - Program::BlackBoxFuncCall::Poseidon2Permutation obj; + Circuit::BlackBoxFuncCall::Poseidon2Permutation obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); obj.len = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BlackBoxFuncCall::Sha256Compression& lhs, const BlackBoxFuncCall::Sha256Compression& rhs) { @@ -3506,12 +3498,12 @@ inline BlackBoxFuncCall::Sha256Compression BlackBoxFuncCall::Sha256Compression:: return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize( - const Program::BlackBoxFuncCall::Sha256Compression& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Circuit::BlackBoxFuncCall::Sha256Compression& obj, Serializer& serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.hash_values, serializer); @@ -3520,17 +3512,17 @@ void serde::Serializable::serializ template <> template -Program::BlackBoxFuncCall::Sha256Compression serde::Deserializable< - Program::BlackBoxFuncCall::Sha256Compression>::deserialize(Deserializer& deserializer) +Circuit::BlackBoxFuncCall::Sha256Compression serde::Deserializable< + Circuit::BlackBoxFuncCall::Sha256Compression>::deserialize(Deserializer& deserializer) { - Program::BlackBoxFuncCall::Sha256Compression obj; + Circuit::BlackBoxFuncCall::Sha256Compression obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.hash_values = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BlackBoxOp& lhs, const BlackBoxOp& rhs) { @@ -3557,11 +3549,11 @@ inline BlackBoxOp BlackBoxOp::bincodeDeserialize(std::vector input) return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BlackBoxOp& obj, Serializer& serializer) +void serde::Serializable::serialize(const Circuit::BlackBoxOp& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); @@ -3570,16 +3562,16 @@ void serde::Serializable::serialize(const Program::BlackBox template <> template -Program::BlackBoxOp serde::Deserializable::deserialize(Deserializer& deserializer) +Circuit::BlackBoxOp serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Program::BlackBoxOp obj; + Circuit::BlackBoxOp obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BlackBoxOp::Sha256& lhs, const BlackBoxOp::Sha256& rhs) { @@ -3609,11 +3601,11 @@ inline BlackBoxOp::Sha256 BlackBoxOp::Sha256::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Program::BlackBoxOp::Sha256& obj, +void serde::Serializable::serialize(const Circuit::BlackBoxOp::Sha256& obj, Serializer& serializer) { serde::Serializable::serialize(obj.message, serializer); @@ -3622,15 +3614,15 @@ void serde::Serializable::serialize(const Program:: template <> template -Program::BlackBoxOp::Sha256 serde::Deserializable::deserialize(Deserializer& deserializer) +Circuit::BlackBoxOp::Sha256 serde::Deserializable::deserialize(Deserializer& deserializer) { - Program::BlackBoxOp::Sha256 obj; + Circuit::BlackBoxOp::Sha256 obj; obj.message = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BlackBoxOp::Blake2s& lhs, const BlackBoxOp::Blake2s& rhs) { @@ -3660,11 +3652,11 @@ inline BlackBoxOp::Blake2s BlackBoxOp::Blake2s::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Program::BlackBoxOp::Blake2s& obj, +void serde::Serializable::serialize(const Circuit::BlackBoxOp::Blake2s& obj, Serializer& serializer) { serde::Serializable::serialize(obj.message, serializer); @@ -3673,16 +3665,16 @@ void serde::Serializable::serialize(const Program: template <> template -Program::BlackBoxOp::Blake2s serde::Deserializable::deserialize( +Circuit::BlackBoxOp::Blake2s serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::BlackBoxOp::Blake2s obj; + Circuit::BlackBoxOp::Blake2s obj; obj.message = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BlackBoxOp::Blake3& lhs, const BlackBoxOp::Blake3& rhs) { @@ -3712,11 +3704,11 @@ inline BlackBoxOp::Blake3 BlackBoxOp::Blake3::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Program::BlackBoxOp::Blake3& obj, +void serde::Serializable::serialize(const Circuit::BlackBoxOp::Blake3& obj, Serializer& serializer) { serde::Serializable::serialize(obj.message, serializer); @@ -3725,15 +3717,15 @@ void serde::Serializable::serialize(const Program:: template <> template -Program::BlackBoxOp::Blake3 serde::Deserializable::deserialize(Deserializer& deserializer) +Circuit::BlackBoxOp::Blake3 serde::Deserializable::deserialize(Deserializer& deserializer) { - Program::BlackBoxOp::Blake3 obj; + Circuit::BlackBoxOp::Blake3 obj; obj.message = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BlackBoxOp::Keccak256& lhs, const BlackBoxOp::Keccak256& rhs) { @@ -3763,11 +3755,11 @@ inline BlackBoxOp::Keccak256 BlackBoxOp::Keccak256::bincodeDeserialize(std::vect return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BlackBoxOp::Keccak256& obj, +void serde::Serializable::serialize(const Circuit::BlackBoxOp::Keccak256& obj, Serializer& serializer) { serde::Serializable::serialize(obj.message, serializer); @@ -3776,16 +3768,16 @@ void serde::Serializable::serialize(const Progra template <> template -Program::BlackBoxOp::Keccak256 serde::Deserializable::deserialize( +Circuit::BlackBoxOp::Keccak256 serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::BlackBoxOp::Keccak256 obj; + Circuit::BlackBoxOp::Keccak256 obj; obj.message = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BlackBoxOp::Keccakf1600& lhs, const BlackBoxOp::Keccakf1600& rhs) { @@ -3815,11 +3807,11 @@ inline BlackBoxOp::Keccakf1600 BlackBoxOp::Keccakf1600::bincodeDeserialize(std:: return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BlackBoxOp::Keccakf1600& obj, +void serde::Serializable::serialize(const Circuit::BlackBoxOp::Keccakf1600& obj, Serializer& serializer) { serde::Serializable::serialize(obj.message, serializer); @@ -3828,16 +3820,16 @@ void serde::Serializable::serialize(const Prog template <> template -Program::BlackBoxOp::Keccakf1600 serde::Deserializable::deserialize( +Circuit::BlackBoxOp::Keccakf1600 serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::BlackBoxOp::Keccakf1600 obj; + Circuit::BlackBoxOp::Keccakf1600 obj; obj.message = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BlackBoxOp::EcdsaSecp256k1& lhs, const BlackBoxOp::EcdsaSecp256k1& rhs) { @@ -3876,11 +3868,11 @@ inline BlackBoxOp::EcdsaSecp256k1 BlackBoxOp::EcdsaSecp256k1::bincodeDeserialize return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BlackBoxOp::EcdsaSecp256k1& obj, +void serde::Serializable::serialize(const Circuit::BlackBoxOp::EcdsaSecp256k1& obj, Serializer& serializer) { serde::Serializable::serialize(obj.hashed_msg, serializer); @@ -3892,10 +3884,10 @@ void serde::Serializable::serialize(const P template <> template -Program::BlackBoxOp::EcdsaSecp256k1 serde::Deserializable::deserialize( +Circuit::BlackBoxOp::EcdsaSecp256k1 serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::BlackBoxOp::EcdsaSecp256k1 obj; + 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); @@ -3904,7 +3896,7 @@ Program::BlackBoxOp::EcdsaSecp256k1 serde::Deserializable template -void serde::Serializable::serialize(const Program::BlackBoxOp::EcdsaSecp256r1& obj, +void serde::Serializable::serialize(const Circuit::BlackBoxOp::EcdsaSecp256r1& obj, Serializer& serializer) { serde::Serializable::serialize(obj.hashed_msg, serializer); @@ -3959,10 +3951,10 @@ void serde::Serializable::serialize(const P template <> template -Program::BlackBoxOp::EcdsaSecp256r1 serde::Deserializable::deserialize( +Circuit::BlackBoxOp::EcdsaSecp256r1 serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::BlackBoxOp::EcdsaSecp256r1 obj; + 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); @@ -3971,7 +3963,7 @@ Program::BlackBoxOp::EcdsaSecp256r1 serde::Deserializable template -void serde::Serializable::serialize(const Program::BlackBoxOp::SchnorrVerify& obj, +void serde::Serializable::serialize(const Circuit::BlackBoxOp::SchnorrVerify& obj, Serializer& serializer) { serde::Serializable::serialize(obj.public_key_x, serializer); @@ -4026,10 +4018,10 @@ void serde::Serializable::serialize(const Pr template <> template -Program::BlackBoxOp::SchnorrVerify serde::Deserializable::deserialize( +Circuit::BlackBoxOp::SchnorrVerify serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::BlackBoxOp::SchnorrVerify obj; + 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); @@ -4038,7 +4030,7 @@ Program::BlackBoxOp::SchnorrVerify serde::Deserializable template -void serde::Serializable::serialize( - const Program::BlackBoxOp::PedersenCommitment& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Circuit::BlackBoxOp::PedersenCommitment& obj, Serializer& serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.domain_separator, serializer); @@ -4085,17 +4077,17 @@ void serde::Serializable::serialize( template <> template -Program::BlackBoxOp::PedersenCommitment serde::Deserializable::deserialize( +Circuit::BlackBoxOp::PedersenCommitment serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::BlackBoxOp::PedersenCommitment obj; + 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 Program { +namespace Circuit { inline bool operator==(const BlackBoxOp::PedersenHash& lhs, const BlackBoxOp::PedersenHash& rhs) { @@ -4128,11 +4120,11 @@ inline BlackBoxOp::PedersenHash BlackBoxOp::PedersenHash::bincodeDeserialize(std return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BlackBoxOp::PedersenHash& obj, +void serde::Serializable::serialize(const Circuit::BlackBoxOp::PedersenHash& obj, Serializer& serializer) { serde::Serializable::serialize(obj.inputs, serializer); @@ -4142,17 +4134,17 @@ void serde::Serializable::serialize(const Pro template <> template -Program::BlackBoxOp::PedersenHash serde::Deserializable::deserialize( +Circuit::BlackBoxOp::PedersenHash serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::BlackBoxOp::PedersenHash obj; + 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 Program { +namespace Circuit { inline bool operator==(const BlackBoxOp::FixedBaseScalarMul& lhs, const BlackBoxOp::FixedBaseScalarMul& rhs) { @@ -4185,12 +4177,12 @@ inline BlackBoxOp::FixedBaseScalarMul BlackBoxOp::FixedBaseScalarMul::bincodeDes return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize( - const Program::BlackBoxOp::FixedBaseScalarMul& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Circuit::BlackBoxOp::FixedBaseScalarMul& obj, Serializer& serializer) { serde::Serializable::serialize(obj.low, serializer); serde::Serializable::serialize(obj.high, serializer); @@ -4199,17 +4191,17 @@ void serde::Serializable::serialize( template <> template -Program::BlackBoxOp::FixedBaseScalarMul serde::Deserializable::deserialize( +Circuit::BlackBoxOp::FixedBaseScalarMul serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::BlackBoxOp::FixedBaseScalarMul obj; + 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 Program { +namespace Circuit { inline bool operator==(const BlackBoxOp::EmbeddedCurveAdd& lhs, const BlackBoxOp::EmbeddedCurveAdd& rhs) { @@ -4248,12 +4240,12 @@ inline BlackBoxOp::EmbeddedCurveAdd BlackBoxOp::EmbeddedCurveAdd::bincodeDeseria return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize( - const Program::BlackBoxOp::EmbeddedCurveAdd& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Circuit::BlackBoxOp::EmbeddedCurveAdd& obj, Serializer& serializer) { serde::Serializable::serialize(obj.input1_x, serializer); serde::Serializable::serialize(obj.input1_y, serializer); @@ -4264,10 +4256,10 @@ void serde::Serializable::serialize( template <> template -Program::BlackBoxOp::EmbeddedCurveAdd serde::Deserializable::deserialize( +Circuit::BlackBoxOp::EmbeddedCurveAdd serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::BlackBoxOp::EmbeddedCurveAdd obj; + 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); @@ -4276,7 +4268,7 @@ Program::BlackBoxOp::EmbeddedCurveAdd serde::Deserializable template -void serde::Serializable::serialize(const Program::BlackBoxOp::BigIntAdd& obj, +void serde::Serializable::serialize(const Circuit::BlackBoxOp::BigIntAdd& obj, Serializer& serializer) { serde::Serializable::serialize(obj.lhs, serializer); @@ -4323,17 +4315,17 @@ void serde::Serializable::serialize(const Progra template <> template -Program::BlackBoxOp::BigIntAdd serde::Deserializable::deserialize( +Circuit::BlackBoxOp::BigIntAdd serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::BlackBoxOp::BigIntAdd obj; + 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 Program { +namespace Circuit { inline bool operator==(const BlackBoxOp::BigIntSub& lhs, const BlackBoxOp::BigIntSub& rhs) { @@ -4366,11 +4358,11 @@ inline BlackBoxOp::BigIntSub BlackBoxOp::BigIntSub::bincodeDeserialize(std::vect return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BlackBoxOp::BigIntSub& obj, +void serde::Serializable::serialize(const Circuit::BlackBoxOp::BigIntSub& obj, Serializer& serializer) { serde::Serializable::serialize(obj.lhs, serializer); @@ -4380,17 +4372,17 @@ void serde::Serializable::serialize(const Progra template <> template -Program::BlackBoxOp::BigIntSub serde::Deserializable::deserialize( +Circuit::BlackBoxOp::BigIntSub serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::BlackBoxOp::BigIntSub obj; + Circuit::BlackBoxOp::BigIntSub obj; obj.lhs = serde::Deserializable::deserialize(deserializer); obj.rhs = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BlackBoxOp::BigIntMul& lhs, const BlackBoxOp::BigIntMul& rhs) { @@ -4423,11 +4415,11 @@ inline BlackBoxOp::BigIntMul BlackBoxOp::BigIntMul::bincodeDeserialize(std::vect return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BlackBoxOp::BigIntMul& obj, +void serde::Serializable::serialize(const Circuit::BlackBoxOp::BigIntMul& obj, Serializer& serializer) { serde::Serializable::serialize(obj.lhs, serializer); @@ -4437,17 +4429,17 @@ void serde::Serializable::serialize(const Progra template <> template -Program::BlackBoxOp::BigIntMul serde::Deserializable::deserialize( +Circuit::BlackBoxOp::BigIntMul serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::BlackBoxOp::BigIntMul obj; + 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 Program { +namespace Circuit { inline bool operator==(const BlackBoxOp::BigIntDiv& lhs, const BlackBoxOp::BigIntDiv& rhs) { @@ -4480,11 +4472,11 @@ inline BlackBoxOp::BigIntDiv BlackBoxOp::BigIntDiv::bincodeDeserialize(std::vect return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BlackBoxOp::BigIntDiv& obj, +void serde::Serializable::serialize(const Circuit::BlackBoxOp::BigIntDiv& obj, Serializer& serializer) { serde::Serializable::serialize(obj.lhs, serializer); @@ -4494,17 +4486,17 @@ void serde::Serializable::serialize(const Progra template <> template -Program::BlackBoxOp::BigIntDiv serde::Deserializable::deserialize( +Circuit::BlackBoxOp::BigIntDiv serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::BlackBoxOp::BigIntDiv obj; + 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 Program { +namespace Circuit { inline bool operator==(const BlackBoxOp::BigIntFromLeBytes& lhs, const BlackBoxOp::BigIntFromLeBytes& rhs) { @@ -4537,12 +4529,12 @@ inline BlackBoxOp::BigIntFromLeBytes BlackBoxOp::BigIntFromLeBytes::bincodeDeser return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize( - const Program::BlackBoxOp::BigIntFromLeBytes& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Circuit::BlackBoxOp::BigIntFromLeBytes& obj, Serializer& serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.modulus, serializer); @@ -4551,17 +4543,17 @@ void serde::Serializable::serialize( template <> template -Program::BlackBoxOp::BigIntFromLeBytes serde::Deserializable::deserialize( +Circuit::BlackBoxOp::BigIntFromLeBytes serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::BlackBoxOp::BigIntFromLeBytes obj; + 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 Program { +namespace Circuit { inline bool operator==(const BlackBoxOp::BigIntToLeBytes& lhs, const BlackBoxOp::BigIntToLeBytes& rhs) { @@ -4591,12 +4583,12 @@ inline BlackBoxOp::BigIntToLeBytes BlackBoxOp::BigIntToLeBytes::bincodeDeseriali return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize( - const Program::BlackBoxOp::BigIntToLeBytes& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Circuit::BlackBoxOp::BigIntToLeBytes& obj, Serializer& serializer) { serde::Serializable::serialize(obj.input, serializer); serde::Serializable::serialize(obj.output, serializer); @@ -4604,16 +4596,16 @@ void serde::Serializable::serialize( template <> template -Program::BlackBoxOp::BigIntToLeBytes serde::Deserializable::deserialize( +Circuit::BlackBoxOp::BigIntToLeBytes serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::BlackBoxOp::BigIntToLeBytes obj; + Circuit::BlackBoxOp::BigIntToLeBytes obj; obj.input = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BlackBoxOp::Poseidon2Permutation& lhs, const BlackBoxOp::Poseidon2Permutation& rhs) { @@ -4646,12 +4638,12 @@ inline BlackBoxOp::Poseidon2Permutation BlackBoxOp::Poseidon2Permutation::bincod return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize( - const Program::BlackBoxOp::Poseidon2Permutation& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Circuit::BlackBoxOp::Poseidon2Permutation& obj, Serializer& serializer) { serde::Serializable::serialize(obj.message, serializer); serde::Serializable::serialize(obj.output, serializer); @@ -4660,17 +4652,17 @@ void serde::Serializable::serialize( template <> template -Program::BlackBoxOp::Poseidon2Permutation serde::Deserializable::deserialize( +Circuit::BlackBoxOp::Poseidon2Permutation serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::BlackBoxOp::Poseidon2Permutation obj; + Circuit::BlackBoxOp::Poseidon2Permutation obj; obj.message = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); obj.len = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BlackBoxOp::Sha256Compression& lhs, const BlackBoxOp::Sha256Compression& rhs) { @@ -4703,12 +4695,12 @@ inline BlackBoxOp::Sha256Compression BlackBoxOp::Sha256Compression::bincodeDeser return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize( - const Program::BlackBoxOp::Sha256Compression& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Circuit::BlackBoxOp::Sha256Compression& obj, Serializer& serializer) { serde::Serializable::serialize(obj.input, serializer); serde::Serializable::serialize(obj.hash_values, serializer); @@ -4717,17 +4709,17 @@ void serde::Serializable::serialize( template <> template -Program::BlackBoxOp::Sha256Compression serde::Deserializable::deserialize( +Circuit::BlackBoxOp::Sha256Compression serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::BlackBoxOp::Sha256Compression obj; + Circuit::BlackBoxOp::Sha256Compression obj; obj.input = serde::Deserializable::deserialize(deserializer); obj.hash_values = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BlockId& lhs, const BlockId& rhs) { @@ -4754,11 +4746,11 @@ inline BlockId BlockId::bincodeDeserialize(std::vector input) return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BlockId& obj, Serializer& serializer) +void serde::Serializable::serialize(const Circuit::BlockId& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); @@ -4767,16 +4759,16 @@ void serde::Serializable::serialize(const Program::BlockId& ob template <> template -Program::BlockId serde::Deserializable::deserialize(Deserializer& deserializer) +Circuit::BlockId serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Program::BlockId obj; + Circuit::BlockId obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const Brillig& lhs, const Brillig& rhs) { @@ -4812,11 +4804,11 @@ inline Brillig Brillig::bincodeDeserialize(std::vector input) return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::Brillig& obj, Serializer& serializer) +void serde::Serializable::serialize(const Circuit::Brillig& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.inputs, serializer); @@ -4828,10 +4820,10 @@ void serde::Serializable::serialize(const Program::Brillig& ob template <> template -Program::Brillig serde::Deserializable::deserialize(Deserializer& deserializer) +Circuit::Brillig serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Program::Brillig obj; + Circuit::Brillig obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); obj.bytecode = serde::Deserializable::deserialize(deserializer); @@ -4840,7 +4832,7 @@ Program::Brillig serde::Deserializable::deserialize(Deserializ return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BrilligInputs& lhs, const BrilligInputs& rhs) { @@ -4867,11 +4859,11 @@ inline BrilligInputs BrilligInputs::bincodeDeserialize(std::vector inpu return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BrilligInputs& obj, Serializer& serializer) +void serde::Serializable::serialize(const Circuit::BrilligInputs& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); @@ -4880,16 +4872,16 @@ void serde::Serializable::serialize(const Program::Brill template <> template -Program::BrilligInputs serde::Deserializable::deserialize(Deserializer& deserializer) +Circuit::BrilligInputs serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Program::BrilligInputs obj; + Circuit::BrilligInputs obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BrilligInputs::Single& lhs, const BrilligInputs::Single& rhs) { @@ -4916,11 +4908,11 @@ inline BrilligInputs::Single BrilligInputs::Single::bincodeDeserialize(std::vect return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BrilligInputs::Single& obj, +void serde::Serializable::serialize(const Circuit::BrilligInputs::Single& obj, Serializer& serializer) { serde::Serializable::serialize(obj.value, serializer); @@ -4928,15 +4920,15 @@ void serde::Serializable::serialize(const Progra template <> template -Program::BrilligInputs::Single serde::Deserializable::deserialize( +Circuit::BrilligInputs::Single serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::BrilligInputs::Single obj; + Circuit::BrilligInputs::Single obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BrilligInputs::Array& lhs, const BrilligInputs::Array& rhs) { @@ -4963,11 +4955,11 @@ inline BrilligInputs::Array BrilligInputs::Array::bincodeDeserialize(std::vector return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BrilligInputs::Array& obj, +void serde::Serializable::serialize(const Circuit::BrilligInputs::Array& obj, Serializer& serializer) { serde::Serializable::serialize(obj.value, serializer); @@ -4975,15 +4967,15 @@ void serde::Serializable::serialize(const Program template <> template -Program::BrilligInputs::Array serde::Deserializable::deserialize( +Circuit::BrilligInputs::Array serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::BrilligInputs::Array obj; + Circuit::BrilligInputs::Array obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BrilligInputs::MemoryArray& lhs, const BrilligInputs::MemoryArray& rhs) { @@ -5010,11 +5002,11 @@ inline BrilligInputs::MemoryArray BrilligInputs::MemoryArray::bincodeDeserialize return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BrilligInputs::MemoryArray& obj, +void serde::Serializable::serialize(const Circuit::BrilligInputs::MemoryArray& obj, Serializer& serializer) { serde::Serializable::serialize(obj.value, serializer); @@ -5022,15 +5014,15 @@ void serde::Serializable::serialize(const P template <> template -Program::BrilligInputs::MemoryArray serde::Deserializable::deserialize( +Circuit::BrilligInputs::MemoryArray serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::BrilligInputs::MemoryArray obj; + Circuit::BrilligInputs::MemoryArray obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BrilligOpcode& lhs, const BrilligOpcode& rhs) { @@ -5057,11 +5049,11 @@ inline BrilligOpcode BrilligOpcode::bincodeDeserialize(std::vector inpu return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BrilligOpcode& obj, Serializer& serializer) +void serde::Serializable::serialize(const Circuit::BrilligOpcode& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); @@ -5070,16 +5062,16 @@ void serde::Serializable::serialize(const Program::Brill template <> template -Program::BrilligOpcode serde::Deserializable::deserialize(Deserializer& deserializer) +Circuit::BrilligOpcode serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Program::BrilligOpcode obj; + Circuit::BrilligOpcode obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BrilligOpcode::BinaryFieldOp& lhs, const BrilligOpcode::BinaryFieldOp& rhs) { @@ -5115,12 +5107,12 @@ inline BrilligOpcode::BinaryFieldOp BrilligOpcode::BinaryFieldOp::bincodeDeseria return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize( - const Program::BrilligOpcode::BinaryFieldOp& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Circuit::BrilligOpcode::BinaryFieldOp& obj, Serializer& serializer) { serde::Serializable::serialize(obj.destination, serializer); serde::Serializable::serialize(obj.op, serializer); @@ -5130,10 +5122,10 @@ void serde::Serializable::serialize( template <> template -Program::BrilligOpcode::BinaryFieldOp serde::Deserializable::deserialize( +Circuit::BrilligOpcode::BinaryFieldOp serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::BrilligOpcode::BinaryFieldOp obj; + Circuit::BrilligOpcode::BinaryFieldOp obj; obj.destination = serde::Deserializable::deserialize(deserializer); obj.op = serde::Deserializable::deserialize(deserializer); obj.lhs = serde::Deserializable::deserialize(deserializer); @@ -5141,7 +5133,7 @@ Program::BrilligOpcode::BinaryFieldOp serde::Deserializable template -void serde::Serializable::serialize(const Program::BrilligOpcode::BinaryIntOp& obj, +void serde::Serializable::serialize(const Circuit::BrilligOpcode::BinaryIntOp& obj, Serializer& serializer) { serde::Serializable::serialize(obj.destination, serializer); @@ -5196,10 +5188,10 @@ void serde::Serializable::serialize(const P template <> template -Program::BrilligOpcode::BinaryIntOp serde::Deserializable::deserialize( +Circuit::BrilligOpcode::BinaryIntOp serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::BrilligOpcode::BinaryIntOp obj; + Circuit::BrilligOpcode::BinaryIntOp obj; obj.destination = serde::Deserializable::deserialize(deserializer); obj.op = serde::Deserializable::deserialize(deserializer); obj.bit_size = serde::Deserializable::deserialize(deserializer); @@ -5208,7 +5200,7 @@ Program::BrilligOpcode::BinaryIntOp serde::Deserializable template -void serde::Serializable::serialize(const Program::BrilligOpcode::Cast& obj, +void serde::Serializable::serialize(const Circuit::BrilligOpcode::Cast& obj, Serializer& serializer) { serde::Serializable::serialize(obj.destination, serializer); @@ -5255,17 +5247,17 @@ void serde::Serializable::serialize(const Program: template <> template -Program::BrilligOpcode::Cast serde::Deserializable::deserialize( +Circuit::BrilligOpcode::Cast serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::BrilligOpcode::Cast obj; + Circuit::BrilligOpcode::Cast obj; obj.destination = serde::Deserializable::deserialize(deserializer); obj.source = serde::Deserializable::deserialize(deserializer); obj.bit_size = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BrilligOpcode::JumpIfNot& lhs, const BrilligOpcode::JumpIfNot& rhs) { @@ -5295,11 +5287,11 @@ inline BrilligOpcode::JumpIfNot BrilligOpcode::JumpIfNot::bincodeDeserialize(std return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BrilligOpcode::JumpIfNot& obj, +void serde::Serializable::serialize(const Circuit::BrilligOpcode::JumpIfNot& obj, Serializer& serializer) { serde::Serializable::serialize(obj.condition, serializer); @@ -5308,16 +5300,16 @@ void serde::Serializable::serialize(const Pro template <> template -Program::BrilligOpcode::JumpIfNot serde::Deserializable::deserialize( +Circuit::BrilligOpcode::JumpIfNot serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::BrilligOpcode::JumpIfNot obj; + Circuit::BrilligOpcode::JumpIfNot obj; obj.condition = serde::Deserializable::deserialize(deserializer); obj.location = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BrilligOpcode::JumpIf& lhs, const BrilligOpcode::JumpIf& rhs) { @@ -5347,11 +5339,11 @@ inline BrilligOpcode::JumpIf BrilligOpcode::JumpIf::bincodeDeserialize(std::vect return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BrilligOpcode::JumpIf& obj, +void serde::Serializable::serialize(const Circuit::BrilligOpcode::JumpIf& obj, Serializer& serializer) { serde::Serializable::serialize(obj.condition, serializer); @@ -5360,16 +5352,16 @@ void serde::Serializable::serialize(const Progra template <> template -Program::BrilligOpcode::JumpIf serde::Deserializable::deserialize( +Circuit::BrilligOpcode::JumpIf serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::BrilligOpcode::JumpIf obj; + Circuit::BrilligOpcode::JumpIf obj; obj.condition = serde::Deserializable::deserialize(deserializer); obj.location = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BrilligOpcode::Jump& lhs, const BrilligOpcode::Jump& rhs) { @@ -5396,11 +5388,11 @@ inline BrilligOpcode::Jump BrilligOpcode::Jump::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Program::BrilligOpcode::Jump& obj, +void serde::Serializable::serialize(const Circuit::BrilligOpcode::Jump& obj, Serializer& serializer) { serde::Serializable::serialize(obj.location, serializer); @@ -5408,15 +5400,15 @@ void serde::Serializable::serialize(const Program: template <> template -Program::BrilligOpcode::Jump serde::Deserializable::deserialize( +Circuit::BrilligOpcode::Jump serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::BrilligOpcode::Jump obj; + Circuit::BrilligOpcode::Jump obj; obj.location = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BrilligOpcode::CalldataCopy& lhs, const BrilligOpcode::CalldataCopy& rhs) { @@ -5449,12 +5441,12 @@ inline BrilligOpcode::CalldataCopy BrilligOpcode::CalldataCopy::bincodeDeseriali return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize( - const Program::BrilligOpcode::CalldataCopy& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Circuit::BrilligOpcode::CalldataCopy& obj, Serializer& serializer) { serde::Serializable::serialize(obj.destination_address, serializer); serde::Serializable::serialize(obj.size, serializer); @@ -5463,17 +5455,17 @@ void serde::Serializable::serialize( template <> template -Program::BrilligOpcode::CalldataCopy serde::Deserializable::deserialize( +Circuit::BrilligOpcode::CalldataCopy serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::BrilligOpcode::CalldataCopy obj; + Circuit::BrilligOpcode::CalldataCopy obj; obj.destination_address = serde::Deserializable::deserialize(deserializer); obj.size = serde::Deserializable::deserialize(deserializer); obj.offset = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BrilligOpcode::Call& lhs, const BrilligOpcode::Call& rhs) { @@ -5500,11 +5492,11 @@ inline BrilligOpcode::Call BrilligOpcode::Call::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Program::BrilligOpcode::Call& obj, +void serde::Serializable::serialize(const Circuit::BrilligOpcode::Call& obj, Serializer& serializer) { serde::Serializable::serialize(obj.location, serializer); @@ -5512,15 +5504,15 @@ void serde::Serializable::serialize(const Program: template <> template -Program::BrilligOpcode::Call serde::Deserializable::deserialize( +Circuit::BrilligOpcode::Call serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::BrilligOpcode::Call obj; + Circuit::BrilligOpcode::Call obj; obj.location = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BrilligOpcode::Const& lhs, const BrilligOpcode::Const& rhs) { @@ -5553,11 +5545,11 @@ inline BrilligOpcode::Const BrilligOpcode::Const::bincodeDeserialize(std::vector return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BrilligOpcode::Const& obj, +void serde::Serializable::serialize(const Circuit::BrilligOpcode::Const& obj, Serializer& serializer) { serde::Serializable::serialize(obj.destination, serializer); @@ -5567,17 +5559,17 @@ void serde::Serializable::serialize(const Program template <> template -Program::BrilligOpcode::Const serde::Deserializable::deserialize( +Circuit::BrilligOpcode::Const serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::BrilligOpcode::Const obj; + Circuit::BrilligOpcode::Const obj; obj.destination = serde::Deserializable::deserialize(deserializer); obj.bit_size = serde::Deserializable::deserialize(deserializer); obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BrilligOpcode::Return& lhs, const BrilligOpcode::Return& rhs) { @@ -5601,24 +5593,24 @@ inline BrilligOpcode::Return BrilligOpcode::Return::bincodeDeserialize(std::vect return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BrilligOpcode::Return& obj, +void serde::Serializable::serialize(const Circuit::BrilligOpcode::Return& obj, Serializer& serializer) {} template <> template -Program::BrilligOpcode::Return serde::Deserializable::deserialize( +Circuit::BrilligOpcode::Return serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::BrilligOpcode::Return obj; + Circuit::BrilligOpcode::Return obj; return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BrilligOpcode::ForeignCall& lhs, const BrilligOpcode::ForeignCall& rhs) { @@ -5657,11 +5649,11 @@ inline BrilligOpcode::ForeignCall BrilligOpcode::ForeignCall::bincodeDeserialize return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BrilligOpcode::ForeignCall& obj, +void serde::Serializable::serialize(const Circuit::BrilligOpcode::ForeignCall& obj, Serializer& serializer) { serde::Serializable::serialize(obj.function, serializer); @@ -5673,10 +5665,10 @@ void serde::Serializable::serialize(const P template <> template -Program::BrilligOpcode::ForeignCall serde::Deserializable::deserialize( +Circuit::BrilligOpcode::ForeignCall serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::BrilligOpcode::ForeignCall obj; + Circuit::BrilligOpcode::ForeignCall obj; obj.function = serde::Deserializable::deserialize(deserializer); obj.destinations = serde::Deserializable::deserialize(deserializer); obj.destination_value_types = @@ -5686,7 +5678,7 @@ Program::BrilligOpcode::ForeignCall serde::Deserializable template -void serde::Serializable::serialize(const Program::BrilligOpcode::Mov& obj, +void serde::Serializable::serialize(const Circuit::BrilligOpcode::Mov& obj, Serializer& serializer) { serde::Serializable::serialize(obj.destination, serializer); @@ -5729,15 +5721,15 @@ void serde::Serializable::serialize(const Program:: template <> template -Program::BrilligOpcode::Mov serde::Deserializable::deserialize(Deserializer& deserializer) +Circuit::BrilligOpcode::Mov serde::Deserializable::deserialize(Deserializer& deserializer) { - Program::BrilligOpcode::Mov obj; + Circuit::BrilligOpcode::Mov obj; obj.destination = serde::Deserializable::deserialize(deserializer); obj.source = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BrilligOpcode::Load& lhs, const BrilligOpcode::Load& rhs) { @@ -5767,11 +5759,11 @@ inline BrilligOpcode::Load BrilligOpcode::Load::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Program::BrilligOpcode::Load& obj, +void serde::Serializable::serialize(const Circuit::BrilligOpcode::Load& obj, Serializer& serializer) { serde::Serializable::serialize(obj.destination, serializer); @@ -5780,16 +5772,16 @@ void serde::Serializable::serialize(const Program: template <> template -Program::BrilligOpcode::Load serde::Deserializable::deserialize( +Circuit::BrilligOpcode::Load serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::BrilligOpcode::Load obj; + Circuit::BrilligOpcode::Load obj; obj.destination = serde::Deserializable::deserialize(deserializer); obj.source_pointer = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BrilligOpcode::Store& lhs, const BrilligOpcode::Store& rhs) { @@ -5819,11 +5811,11 @@ inline BrilligOpcode::Store BrilligOpcode::Store::bincodeDeserialize(std::vector return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BrilligOpcode::Store& obj, +void serde::Serializable::serialize(const Circuit::BrilligOpcode::Store& obj, Serializer& serializer) { serde::Serializable::serialize(obj.destination_pointer, serializer); @@ -5832,16 +5824,16 @@ void serde::Serializable::serialize(const Program template <> template -Program::BrilligOpcode::Store serde::Deserializable::deserialize( +Circuit::BrilligOpcode::Store serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::BrilligOpcode::Store obj; + Circuit::BrilligOpcode::Store obj; obj.destination_pointer = serde::Deserializable::deserialize(deserializer); obj.source = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BrilligOpcode::BlackBox& lhs, const BrilligOpcode::BlackBox& rhs) { @@ -5868,11 +5860,11 @@ inline BrilligOpcode::BlackBox BrilligOpcode::BlackBox::bincodeDeserialize(std:: return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BrilligOpcode::BlackBox& obj, +void serde::Serializable::serialize(const Circuit::BrilligOpcode::BlackBox& obj, Serializer& serializer) { serde::Serializable::serialize(obj.value, serializer); @@ -5880,15 +5872,15 @@ void serde::Serializable::serialize(const Prog template <> template -Program::BrilligOpcode::BlackBox serde::Deserializable::deserialize( +Circuit::BrilligOpcode::BlackBox serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::BrilligOpcode::BlackBox obj; + Circuit::BrilligOpcode::BlackBox obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BrilligOpcode::Trap& lhs, const BrilligOpcode::Trap& rhs) { @@ -5912,24 +5904,24 @@ inline BrilligOpcode::Trap BrilligOpcode::Trap::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Program::BrilligOpcode::Trap& obj, +void serde::Serializable::serialize(const Circuit::BrilligOpcode::Trap& obj, Serializer& serializer) {} template <> template -Program::BrilligOpcode::Trap serde::Deserializable::deserialize( +Circuit::BrilligOpcode::Trap serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::BrilligOpcode::Trap obj; + Circuit::BrilligOpcode::Trap obj; return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BrilligOpcode::Stop& lhs, const BrilligOpcode::Stop& rhs) { @@ -5959,11 +5951,11 @@ inline BrilligOpcode::Stop BrilligOpcode::Stop::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Program::BrilligOpcode::Stop& obj, +void serde::Serializable::serialize(const Circuit::BrilligOpcode::Stop& obj, Serializer& serializer) { serde::Serializable::serialize(obj.return_data_offset, serializer); @@ -5972,16 +5964,16 @@ void serde::Serializable::serialize(const Program: template <> template -Program::BrilligOpcode::Stop serde::Deserializable::deserialize( +Circuit::BrilligOpcode::Stop serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::BrilligOpcode::Stop obj; + Circuit::BrilligOpcode::Stop obj; obj.return_data_offset = serde::Deserializable::deserialize(deserializer); obj.return_data_size = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BrilligOutputs& lhs, const BrilligOutputs& rhs) { @@ -6008,11 +6000,11 @@ inline BrilligOutputs BrilligOutputs::bincodeDeserialize(std::vector in return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BrilligOutputs& obj, Serializer& serializer) +void serde::Serializable::serialize(const Circuit::BrilligOutputs& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); @@ -6021,16 +6013,16 @@ void serde::Serializable::serialize(const Program::Bril template <> template -Program::BrilligOutputs serde::Deserializable::deserialize(Deserializer& deserializer) +Circuit::BrilligOutputs serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Program::BrilligOutputs obj; + Circuit::BrilligOutputs obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BrilligOutputs::Simple& lhs, const BrilligOutputs::Simple& rhs) { @@ -6057,11 +6049,11 @@ inline BrilligOutputs::Simple BrilligOutputs::Simple::bincodeDeserialize(std::ve return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BrilligOutputs::Simple& obj, +void serde::Serializable::serialize(const Circuit::BrilligOutputs::Simple& obj, Serializer& serializer) { serde::Serializable::serialize(obj.value, serializer); @@ -6069,15 +6061,15 @@ void serde::Serializable::serialize(const Progr template <> template -Program::BrilligOutputs::Simple serde::Deserializable::deserialize( +Circuit::BrilligOutputs::Simple serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::BrilligOutputs::Simple obj; + Circuit::BrilligOutputs::Simple obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BrilligOutputs::Array& lhs, const BrilligOutputs::Array& rhs) { @@ -6104,11 +6096,11 @@ inline BrilligOutputs::Array BrilligOutputs::Array::bincodeDeserialize(std::vect return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BrilligOutputs::Array& obj, +void serde::Serializable::serialize(const Circuit::BrilligOutputs::Array& obj, Serializer& serializer) { serde::Serializable::serialize(obj.value, serializer); @@ -6116,15 +6108,15 @@ void serde::Serializable::serialize(const Progra template <> template -Program::BrilligOutputs::Array serde::Deserializable::deserialize( +Circuit::BrilligOutputs::Array serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::BrilligOutputs::Array obj; + Circuit::BrilligOutputs::Array obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const Circuit& lhs, const Circuit& rhs) { @@ -6172,11 +6164,11 @@ inline Circuit Circuit::bincodeDeserialize(std::vector input) return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::Circuit& obj, Serializer& serializer) +void serde::Serializable::serialize(const Circuit::Circuit& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.current_witness_index, serializer); @@ -6192,10 +6184,10 @@ void serde::Serializable::serialize(const Program::Circuit& ob template <> template -Program::Circuit serde::Deserializable::deserialize(Deserializer& deserializer) +Circuit::Circuit serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Program::Circuit obj; + Circuit::Circuit obj; obj.current_witness_index = serde::Deserializable::deserialize(deserializer); obj.opcodes = serde::Deserializable::deserialize(deserializer); obj.expression_width = serde::Deserializable::deserialize(deserializer); @@ -6208,7 +6200,7 @@ Program::Circuit serde::Deserializable::deserialize(Deserializ return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const Directive& lhs, const Directive& rhs) { @@ -6235,11 +6227,11 @@ inline Directive Directive::bincodeDeserialize(std::vector input) return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::Directive& obj, Serializer& serializer) +void serde::Serializable::serialize(const Circuit::Directive& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); @@ -6248,16 +6240,16 @@ void serde::Serializable::serialize(const Program::Directive template <> template -Program::Directive serde::Deserializable::deserialize(Deserializer& deserializer) +Circuit::Directive serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Program::Directive obj; + Circuit::Directive obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const Directive::ToLeRadix& lhs, const Directive::ToLeRadix& rhs) { @@ -6290,11 +6282,11 @@ inline Directive::ToLeRadix Directive::ToLeRadix::bincodeDeserialize(std::vector return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::Directive::ToLeRadix& obj, +void serde::Serializable::serialize(const Circuit::Directive::ToLeRadix& obj, Serializer& serializer) { serde::Serializable::serialize(obj.a, serializer); @@ -6304,17 +6296,17 @@ void serde::Serializable::serialize(const Program template <> template -Program::Directive::ToLeRadix serde::Deserializable::deserialize( +Circuit::Directive::ToLeRadix serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::Directive::ToLeRadix obj; + Circuit::Directive::ToLeRadix obj; obj.a = serde::Deserializable::deserialize(deserializer); obj.b = serde::Deserializable::deserialize(deserializer); obj.radix = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const Expression& lhs, const Expression& rhs) { @@ -6347,11 +6339,11 @@ inline Expression Expression::bincodeDeserialize(std::vector input) return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::Expression& obj, Serializer& serializer) +void serde::Serializable::serialize(const Circuit::Expression& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.mul_terms, serializer); @@ -6362,10 +6354,10 @@ void serde::Serializable::serialize(const Program::Expressi template <> template -Program::Expression serde::Deserializable::deserialize(Deserializer& deserializer) +Circuit::Expression serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Program::Expression obj; + Circuit::Expression obj; obj.mul_terms = serde::Deserializable::deserialize(deserializer); obj.linear_combinations = serde::Deserializable::deserialize(deserializer); obj.q_c = serde::Deserializable::deserialize(deserializer); @@ -6373,7 +6365,7 @@ Program::Expression serde::Deserializable::deserialize(Dese return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const ExpressionWidth& lhs, const ExpressionWidth& rhs) { @@ -6400,11 +6392,11 @@ inline ExpressionWidth ExpressionWidth::bincodeDeserialize(std::vector return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::ExpressionWidth& obj, +void serde::Serializable::serialize(const Circuit::ExpressionWidth& obj, Serializer& serializer) { serializer.increase_container_depth(); @@ -6414,16 +6406,16 @@ void serde::Serializable::serialize(const Program::Exp template <> template -Program::ExpressionWidth serde::Deserializable::deserialize(Deserializer& deserializer) +Circuit::ExpressionWidth serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Program::ExpressionWidth obj; + Circuit::ExpressionWidth obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const ExpressionWidth::Unbounded& lhs, const ExpressionWidth::Unbounded& rhs) { @@ -6447,24 +6439,24 @@ inline ExpressionWidth::Unbounded ExpressionWidth::Unbounded::bincodeDeserialize return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::ExpressionWidth::Unbounded& obj, +void serde::Serializable::serialize(const Circuit::ExpressionWidth::Unbounded& obj, Serializer& serializer) {} template <> template -Program::ExpressionWidth::Unbounded serde::Deserializable::deserialize( +Circuit::ExpressionWidth::Unbounded serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::ExpressionWidth::Unbounded obj; + Circuit::ExpressionWidth::Unbounded obj; return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const ExpressionWidth::Bounded& lhs, const ExpressionWidth::Bounded& rhs) { @@ -6491,11 +6483,11 @@ inline ExpressionWidth::Bounded ExpressionWidth::Bounded::bincodeDeserialize(std return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::ExpressionWidth::Bounded& obj, +void serde::Serializable::serialize(const Circuit::ExpressionWidth::Bounded& obj, Serializer& serializer) { serde::Serializable::serialize(obj.width, serializer); @@ -6503,15 +6495,15 @@ void serde::Serializable::serialize(const Pro template <> template -Program::ExpressionWidth::Bounded serde::Deserializable::deserialize( +Circuit::ExpressionWidth::Bounded serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::ExpressionWidth::Bounded obj; + Circuit::ExpressionWidth::Bounded obj; obj.width = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const FunctionInput& lhs, const FunctionInput& rhs) { @@ -6541,11 +6533,11 @@ inline FunctionInput FunctionInput::bincodeDeserialize(std::vector inpu return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::FunctionInput& obj, Serializer& serializer) +void serde::Serializable::serialize(const Circuit::FunctionInput& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.witness, serializer); @@ -6555,17 +6547,17 @@ void serde::Serializable::serialize(const Program::Funct template <> template -Program::FunctionInput serde::Deserializable::deserialize(Deserializer& deserializer) +Circuit::FunctionInput serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Program::FunctionInput obj; + Circuit::FunctionInput obj; obj.witness = serde::Deserializable::deserialize(deserializer); obj.num_bits = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const HeapArray& lhs, const HeapArray& rhs) { @@ -6595,11 +6587,11 @@ inline HeapArray HeapArray::bincodeDeserialize(std::vector input) return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::HeapArray& obj, Serializer& serializer) +void serde::Serializable::serialize(const Circuit::HeapArray& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.pointer, serializer); @@ -6609,17 +6601,17 @@ void serde::Serializable::serialize(const Program::HeapArray template <> template -Program::HeapArray serde::Deserializable::deserialize(Deserializer& deserializer) +Circuit::HeapArray serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Program::HeapArray obj; + Circuit::HeapArray obj; obj.pointer = serde::Deserializable::deserialize(deserializer); obj.size = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const HeapValueType& lhs, const HeapValueType& rhs) { @@ -6646,11 +6638,11 @@ inline HeapValueType HeapValueType::bincodeDeserialize(std::vector inpu return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::HeapValueType& obj, Serializer& serializer) +void serde::Serializable::serialize(const Circuit::HeapValueType& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); @@ -6659,16 +6651,16 @@ void serde::Serializable::serialize(const Program::HeapV template <> template -Program::HeapValueType serde::Deserializable::deserialize(Deserializer& deserializer) +Circuit::HeapValueType serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Program::HeapValueType obj; + Circuit::HeapValueType obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const HeapValueType::Simple& lhs, const HeapValueType::Simple& rhs) { @@ -6692,24 +6684,24 @@ inline HeapValueType::Simple HeapValueType::Simple::bincodeDeserialize(std::vect return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::HeapValueType::Simple& obj, +void serde::Serializable::serialize(const Circuit::HeapValueType::Simple& obj, Serializer& serializer) {} template <> template -Program::HeapValueType::Simple serde::Deserializable::deserialize( +Circuit::HeapValueType::Simple serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::HeapValueType::Simple obj; + Circuit::HeapValueType::Simple obj; return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const HeapValueType::Array& lhs, const HeapValueType::Array& rhs) { @@ -6739,11 +6731,11 @@ inline HeapValueType::Array HeapValueType::Array::bincodeDeserialize(std::vector return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::HeapValueType::Array& obj, +void serde::Serializable::serialize(const Circuit::HeapValueType::Array& obj, Serializer& serializer) { serde::Serializable::serialize(obj.value_types, serializer); @@ -6752,16 +6744,16 @@ void serde::Serializable::serialize(const Program template <> template -Program::HeapValueType::Array serde::Deserializable::deserialize( +Circuit::HeapValueType::Array serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::HeapValueType::Array obj; + Circuit::HeapValueType::Array obj; obj.value_types = serde::Deserializable::deserialize(deserializer); obj.size = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const HeapValueType::Vector& lhs, const HeapValueType::Vector& rhs) { @@ -6788,11 +6780,11 @@ inline HeapValueType::Vector HeapValueType::Vector::bincodeDeserialize(std::vect return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::HeapValueType::Vector& obj, +void serde::Serializable::serialize(const Circuit::HeapValueType::Vector& obj, Serializer& serializer) { serde::Serializable::serialize(obj.value_types, serializer); @@ -6800,15 +6792,15 @@ void serde::Serializable::serialize(const Progra template <> template -Program::HeapValueType::Vector serde::Deserializable::deserialize( +Circuit::HeapValueType::Vector serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::HeapValueType::Vector obj; + Circuit::HeapValueType::Vector obj; obj.value_types = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const HeapVector& lhs, const HeapVector& rhs) { @@ -6838,11 +6830,11 @@ inline HeapVector HeapVector::bincodeDeserialize(std::vector input) return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::HeapVector& obj, Serializer& serializer) +void serde::Serializable::serialize(const Circuit::HeapVector& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.pointer, serializer); @@ -6852,17 +6844,17 @@ void serde::Serializable::serialize(const Program::HeapVect template <> template -Program::HeapVector serde::Deserializable::deserialize(Deserializer& deserializer) +Circuit::HeapVector serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Program::HeapVector obj; + Circuit::HeapVector obj; obj.pointer = serde::Deserializable::deserialize(deserializer); obj.size = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const MemOp& lhs, const MemOp& rhs) { @@ -6895,11 +6887,11 @@ inline MemOp MemOp::bincodeDeserialize(std::vector input) return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::MemOp& obj, Serializer& serializer) +void serde::Serializable::serialize(const Circuit::MemOp& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.operation, serializer); @@ -6910,10 +6902,10 @@ void serde::Serializable::serialize(const Program::MemOp& obj, S template <> template -Program::MemOp serde::Deserializable::deserialize(Deserializer& deserializer) +Circuit::MemOp serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Program::MemOp obj; + Circuit::MemOp obj; obj.operation = serde::Deserializable::deserialize(deserializer); obj.index = serde::Deserializable::deserialize(deserializer); obj.value = serde::Deserializable::deserialize(deserializer); @@ -6921,7 +6913,7 @@ Program::MemOp serde::Deserializable::deserialize(Deserializer& return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const MemoryAddress& lhs, const MemoryAddress& rhs) { @@ -6948,11 +6940,11 @@ inline MemoryAddress MemoryAddress::bincodeDeserialize(std::vector inpu return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::MemoryAddress& obj, Serializer& serializer) +void serde::Serializable::serialize(const Circuit::MemoryAddress& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); @@ -6961,16 +6953,16 @@ void serde::Serializable::serialize(const Program::Memor template <> template -Program::MemoryAddress serde::Deserializable::deserialize(Deserializer& deserializer) +Circuit::MemoryAddress serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Program::MemoryAddress obj; + Circuit::MemoryAddress obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const Opcode& lhs, const Opcode& rhs) { @@ -6997,11 +6989,11 @@ inline Opcode Opcode::bincodeDeserialize(std::vector input) return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::Opcode& obj, Serializer& serializer) +void serde::Serializable::serialize(const Circuit::Opcode& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); @@ -7010,16 +7002,16 @@ void serde::Serializable::serialize(const Program::Opcode& obj, template <> template -Program::Opcode serde::Deserializable::deserialize(Deserializer& deserializer) +Circuit::Opcode serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Program::Opcode obj; + Circuit::Opcode obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const Opcode::AssertZero& lhs, const Opcode::AssertZero& rhs) { @@ -7046,11 +7038,11 @@ inline Opcode::AssertZero Opcode::AssertZero::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Program::Opcode::AssertZero& obj, +void serde::Serializable::serialize(const Circuit::Opcode::AssertZero& obj, Serializer& serializer) { serde::Serializable::serialize(obj.value, serializer); @@ -7058,14 +7050,14 @@ void serde::Serializable::serialize(const Program:: template <> template -Program::Opcode::AssertZero serde::Deserializable::deserialize(Deserializer& deserializer) +Circuit::Opcode::AssertZero serde::Deserializable::deserialize(Deserializer& deserializer) { - Program::Opcode::AssertZero obj; + Circuit::Opcode::AssertZero obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const Opcode::BlackBoxFuncCall& lhs, const Opcode::BlackBoxFuncCall& rhs) { @@ -7092,11 +7084,11 @@ inline Opcode::BlackBoxFuncCall Opcode::BlackBoxFuncCall::bincodeDeserialize(std return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::Opcode::BlackBoxFuncCall& obj, +void serde::Serializable::serialize(const Circuit::Opcode::BlackBoxFuncCall& obj, Serializer& serializer) { serde::Serializable::serialize(obj.value, serializer); @@ -7104,15 +7096,15 @@ void serde::Serializable::serialize(const Pro template <> template -Program::Opcode::BlackBoxFuncCall serde::Deserializable::deserialize( +Circuit::Opcode::BlackBoxFuncCall serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::Opcode::BlackBoxFuncCall obj; + Circuit::Opcode::BlackBoxFuncCall obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const Opcode::Directive& lhs, const Opcode::Directive& rhs) { @@ -7139,11 +7131,11 @@ inline Opcode::Directive Opcode::Directive::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Program::Opcode::Directive& obj, +void serde::Serializable::serialize(const Circuit::Opcode::Directive& obj, Serializer& serializer) { serde::Serializable::serialize(obj.value, serializer); @@ -7151,14 +7143,14 @@ void serde::Serializable::serialize(const Program::O template <> template -Program::Opcode::Directive serde::Deserializable::deserialize(Deserializer& deserializer) +Circuit::Opcode::Directive serde::Deserializable::deserialize(Deserializer& deserializer) { - Program::Opcode::Directive obj; + Circuit::Opcode::Directive obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const Opcode::Brillig& lhs, const Opcode::Brillig& rhs) { @@ -7185,11 +7177,11 @@ inline Opcode::Brillig Opcode::Brillig::bincodeDeserialize(std::vector return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::Opcode::Brillig& obj, +void serde::Serializable::serialize(const Circuit::Opcode::Brillig& obj, Serializer& serializer) { serde::Serializable::serialize(obj.value, serializer); @@ -7197,14 +7189,14 @@ void serde::Serializable::serialize(const Program::Opc template <> template -Program::Opcode::Brillig serde::Deserializable::deserialize(Deserializer& deserializer) +Circuit::Opcode::Brillig serde::Deserializable::deserialize(Deserializer& deserializer) { - Program::Opcode::Brillig obj; + Circuit::Opcode::Brillig obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const Opcode::MemoryOp& lhs, const Opcode::MemoryOp& rhs) { @@ -7237,11 +7229,11 @@ inline Opcode::MemoryOp Opcode::MemoryOp::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Program::Opcode::MemoryOp& obj, +void serde::Serializable::serialize(const Circuit::Opcode::MemoryOp& obj, Serializer& serializer) { serde::Serializable::serialize(obj.block_id, serializer); @@ -7251,16 +7243,16 @@ void serde::Serializable::serialize(const Program::Op template <> template -Program::Opcode::MemoryOp serde::Deserializable::deserialize(Deserializer& deserializer) +Circuit::Opcode::MemoryOp serde::Deserializable::deserialize(Deserializer& deserializer) { - Program::Opcode::MemoryOp obj; + Circuit::Opcode::MemoryOp obj; obj.block_id = serde::Deserializable::deserialize(deserializer); obj.op = serde::Deserializable::deserialize(deserializer); obj.predicate = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const Opcode::MemoryInit& lhs, const Opcode::MemoryInit& rhs) { @@ -7290,11 +7282,11 @@ inline Opcode::MemoryInit Opcode::MemoryInit::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Program::Opcode::MemoryInit& obj, +void serde::Serializable::serialize(const Circuit::Opcode::MemoryInit& obj, Serializer& serializer) { serde::Serializable::serialize(obj.block_id, serializer); @@ -7303,15 +7295,15 @@ void serde::Serializable::serialize(const Program:: template <> template -Program::Opcode::MemoryInit serde::Deserializable::deserialize(Deserializer& deserializer) +Circuit::Opcode::MemoryInit serde::Deserializable::deserialize(Deserializer& deserializer) { - Program::Opcode::MemoryInit obj; + Circuit::Opcode::MemoryInit obj; obj.block_id = serde::Deserializable::deserialize(deserializer); obj.init = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const Opcode::Call& lhs, const Opcode::Call& rhs) { @@ -7344,11 +7336,11 @@ inline Opcode::Call Opcode::Call::bincodeDeserialize(std::vector input) return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::Opcode::Call& obj, Serializer& serializer) +void serde::Serializable::serialize(const Circuit::Opcode::Call& obj, Serializer& serializer) { serde::Serializable::serialize(obj.id, serializer); serde::Serializable::serialize(obj.inputs, serializer); @@ -7357,16 +7349,16 @@ void serde::Serializable::serialize(const Program::Opcode template <> template -Program::Opcode::Call serde::Deserializable::deserialize(Deserializer& deserializer) +Circuit::Opcode::Call serde::Deserializable::deserialize(Deserializer& deserializer) { - Program::Opcode::Call obj; + Circuit::Opcode::Call obj; obj.id = serde::Deserializable::deserialize(deserializer); obj.inputs = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const OpcodeLocation& lhs, const OpcodeLocation& rhs) { @@ -7393,11 +7385,11 @@ inline OpcodeLocation OpcodeLocation::bincodeDeserialize(std::vector in return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::OpcodeLocation& obj, Serializer& serializer) +void serde::Serializable::serialize(const Circuit::OpcodeLocation& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); @@ -7406,16 +7398,16 @@ void serde::Serializable::serialize(const Program::Opco template <> template -Program::OpcodeLocation serde::Deserializable::deserialize(Deserializer& deserializer) +Circuit::OpcodeLocation serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Program::OpcodeLocation obj; + Circuit::OpcodeLocation obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const OpcodeLocation::Acir& lhs, const OpcodeLocation::Acir& rhs) { @@ -7442,11 +7434,11 @@ inline OpcodeLocation::Acir OpcodeLocation::Acir::bincodeDeserialize(std::vector return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::OpcodeLocation::Acir& obj, +void serde::Serializable::serialize(const Circuit::OpcodeLocation::Acir& obj, Serializer& serializer) { serde::Serializable::serialize(obj.value, serializer); @@ -7454,15 +7446,15 @@ void serde::Serializable::serialize(const Program template <> template -Program::OpcodeLocation::Acir serde::Deserializable::deserialize( +Circuit::OpcodeLocation::Acir serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::OpcodeLocation::Acir obj; + Circuit::OpcodeLocation::Acir obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const OpcodeLocation::Brillig& lhs, const OpcodeLocation::Brillig& rhs) { @@ -7492,11 +7484,11 @@ inline OpcodeLocation::Brillig OpcodeLocation::Brillig::bincodeDeserialize(std:: return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::OpcodeLocation::Brillig& obj, +void serde::Serializable::serialize(const Circuit::OpcodeLocation::Brillig& obj, Serializer& serializer) { serde::Serializable::serialize(obj.acir_index, serializer); @@ -7505,65 +7497,16 @@ void serde::Serializable::serialize(const Prog template <> template -Program::OpcodeLocation::Brillig serde::Deserializable::deserialize( +Circuit::OpcodeLocation::Brillig serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::OpcodeLocation::Brillig obj; + Circuit::OpcodeLocation::Brillig obj; obj.acir_index = serde::Deserializable::deserialize(deserializer); obj.brillig_index = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { - -inline bool operator==(const Program& lhs, const Program& rhs) -{ - if (!(lhs.functions == rhs.functions)) { - return false; - } - return true; -} - -inline std::vector Program::bincodeSerialize() const -{ - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} - -inline Program Program::bincodeDeserialize(std::vector input) -{ - auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); - if (deserializer.get_buffer_offset() < input.size()) { - throw_or_abort("Some input bytes were not read"); - } - return value; -} - -} // end of namespace Program - -template <> -template -void serde::Serializable::serialize(const Program::Program& obj, Serializer& serializer) -{ - serializer.increase_container_depth(); - serde::Serializable::serialize(obj.functions, serializer); - serializer.decrease_container_depth(); -} - -template <> -template -Program::Program serde::Deserializable::deserialize(Deserializer& deserializer) -{ - deserializer.increase_container_depth(); - Program::Program obj; - obj.functions = serde::Deserializable::deserialize(deserializer); - deserializer.decrease_container_depth(); - return obj; -} - -namespace Program { +namespace Circuit { inline bool operator==(const PublicInputs& lhs, const PublicInputs& rhs) { @@ -7590,11 +7533,11 @@ inline PublicInputs PublicInputs::bincodeDeserialize(std::vector input) return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::PublicInputs& obj, Serializer& serializer) +void serde::Serializable::serialize(const Circuit::PublicInputs& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); @@ -7603,16 +7546,16 @@ void serde::Serializable::serialize(const Program::Public template <> template -Program::PublicInputs serde::Deserializable::deserialize(Deserializer& deserializer) +Circuit::PublicInputs serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Program::PublicInputs obj; + Circuit::PublicInputs obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const Value& lhs, const Value& rhs) { @@ -7639,11 +7582,11 @@ inline Value Value::bincodeDeserialize(std::vector input) return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::Value& obj, Serializer& serializer) +void serde::Serializable::serialize(const Circuit::Value& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.inner, serializer); @@ -7652,16 +7595,16 @@ void serde::Serializable::serialize(const Program::Value& obj, S template <> template -Program::Value serde::Deserializable::deserialize(Deserializer& deserializer) +Circuit::Value serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Program::Value obj; + Circuit::Value obj; obj.inner = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const ValueOrArray& lhs, const ValueOrArray& rhs) { @@ -7688,11 +7631,11 @@ inline ValueOrArray ValueOrArray::bincodeDeserialize(std::vector input) return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::ValueOrArray& obj, Serializer& serializer) +void serde::Serializable::serialize(const Circuit::ValueOrArray& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); @@ -7701,16 +7644,16 @@ void serde::Serializable::serialize(const Program::ValueO template <> template -Program::ValueOrArray serde::Deserializable::deserialize(Deserializer& deserializer) +Circuit::ValueOrArray serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Program::ValueOrArray obj; + Circuit::ValueOrArray obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const ValueOrArray::MemoryAddress& lhs, const ValueOrArray::MemoryAddress& rhs) { @@ -7737,27 +7680,27 @@ inline ValueOrArray::MemoryAddress ValueOrArray::MemoryAddress::bincodeDeseriali return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize( - const Program::ValueOrArray::MemoryAddress& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Circuit::ValueOrArray::MemoryAddress& obj, Serializer& serializer) { serde::Serializable::serialize(obj.value, serializer); } template <> template -Program::ValueOrArray::MemoryAddress serde::Deserializable::deserialize( +Circuit::ValueOrArray::MemoryAddress serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::ValueOrArray::MemoryAddress obj; + Circuit::ValueOrArray::MemoryAddress obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const ValueOrArray::HeapArray& lhs, const ValueOrArray::HeapArray& rhs) { @@ -7784,11 +7727,11 @@ inline ValueOrArray::HeapArray ValueOrArray::HeapArray::bincodeDeserialize(std:: return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::ValueOrArray::HeapArray& obj, +void serde::Serializable::serialize(const Circuit::ValueOrArray::HeapArray& obj, Serializer& serializer) { serde::Serializable::serialize(obj.value, serializer); @@ -7796,15 +7739,15 @@ void serde::Serializable::serialize(const Prog template <> template -Program::ValueOrArray::HeapArray serde::Deserializable::deserialize( +Circuit::ValueOrArray::HeapArray serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::ValueOrArray::HeapArray obj; + Circuit::ValueOrArray::HeapArray obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const ValueOrArray::HeapVector& lhs, const ValueOrArray::HeapVector& rhs) { @@ -7831,11 +7774,11 @@ inline ValueOrArray::HeapVector ValueOrArray::HeapVector::bincodeDeserialize(std return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::ValueOrArray::HeapVector& obj, +void serde::Serializable::serialize(const Circuit::ValueOrArray::HeapVector& obj, Serializer& serializer) { serde::Serializable::serialize(obj.value, serializer); @@ -7843,15 +7786,15 @@ void serde::Serializable::serialize(const Pro template <> template -Program::ValueOrArray::HeapVector serde::Deserializable::deserialize( +Circuit::ValueOrArray::HeapVector serde::Deserializable::deserialize( Deserializer& deserializer) { - Program::ValueOrArray::HeapVector obj; + Circuit::ValueOrArray::HeapVector obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const Witness& lhs, const Witness& rhs) { @@ -7878,11 +7821,11 @@ inline Witness Witness::bincodeDeserialize(std::vector input) return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::Witness& obj, Serializer& serializer) +void serde::Serializable::serialize(const Circuit::Witness& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); @@ -7891,10 +7834,10 @@ void serde::Serializable::serialize(const Program::Witness& ob template <> template -Program::Witness serde::Deserializable::deserialize(Deserializer& deserializer) +Circuit::Witness serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Program::Witness obj; + Circuit::Witness obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/index.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/index.hpp index da0e55ad1c55..82716cef883c 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/index.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/index.hpp @@ -6,7 +6,7 @@ #pragma clang diagnostic ignored "-Wshorten-64-to-32" #pragma clang diagnostic ignored "-Wunused-parameter" #include "acir.hpp" -#include "witness_stack.hpp" +#include "witness_map.hpp" #pragma clang diagnostic pop #else #pragma GCC diagnostic push @@ -16,6 +16,6 @@ #pragma GCC diagnostic ignored "-Wsign-conversion" #pragma GCC diagnostic ignored "-Wconversion" #include "acir.hpp" -#include "witness_stack.hpp" +#include "witness_map.hpp" #pragma GCC diagnostic pop #endif \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/witness_map.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/witness_map.hpp new file mode 100644 index 000000000000..de4523e7020a --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/witness_map.hpp @@ -0,0 +1,123 @@ +#pragma once + +#include "bincode.hpp" +#include "serde.hpp" + +namespace WitnessMap { + +struct Witness { + uint32_t value; + + friend bool operator==(const Witness&, const Witness&); + bool operator<(Witness const& rhs) const { return value < rhs.value; } + std::vector bincodeSerialize() const; + static Witness bincodeDeserialize(std::vector); +}; + +struct WitnessMap { + std::map value; + + friend bool operator==(const WitnessMap&, const WitnessMap&); + std::vector bincodeSerialize() const; + static WitnessMap bincodeDeserialize(std::vector); +}; + +} // end of namespace WitnessMap + +namespace WitnessMap { + +inline bool operator==(const Witness& lhs, const Witness& rhs) +{ + if (!(lhs.value == rhs.value)) { + return false; + } + return true; +} + +inline std::vector Witness::bincodeSerialize() const +{ + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); +} + +inline Witness Witness::bincodeDeserialize(std::vector input) +{ + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw_or_abort("Some input bytes were not read"); + } + return value; +} + +} // end of namespace WitnessMap + +template <> +template +void serde::Serializable::serialize(const WitnessMap::Witness& obj, Serializer& serializer) +{ + serializer.increase_container_depth(); + serde::Serializable::serialize(obj.value, serializer); + serializer.decrease_container_depth(); +} + +template <> +template +WitnessMap::Witness serde::Deserializable::deserialize(Deserializer& deserializer) +{ + deserializer.increase_container_depth(); + WitnessMap::Witness obj; + obj.value = serde::Deserializable::deserialize(deserializer); + deserializer.decrease_container_depth(); + return obj; +} + +namespace WitnessMap { + +inline bool operator==(const WitnessMap& lhs, const WitnessMap& rhs) +{ + if (!(lhs.value == rhs.value)) { + return false; + } + return true; +} + +inline std::vector WitnessMap::bincodeSerialize() const +{ + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); +} + +inline WitnessMap WitnessMap::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 WitnessMap + +template <> +template +void serde::Serializable::serialize(const WitnessMap::WitnessMap& obj, Serializer& serializer) +{ + serializer.increase_container_depth(); + serde::Serializable::serialize(obj.value, serializer); + serializer.decrease_container_depth(); +} + +template <> +template +WitnessMap::WitnessMap serde::Deserializable::deserialize(Deserializer& deserializer) +{ + deserializer.increase_container_depth(); + WitnessMap::WitnessMap obj; + obj.value = serde::Deserializable::deserialize(deserializer); + deserializer.decrease_container_depth(); + return obj; +} \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/witness_stack.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/witness_stack.hpp deleted file mode 100644 index 67ef655babfd..000000000000 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/witness_stack.hpp +++ /dev/null @@ -1,247 +0,0 @@ -#pragma once - -#include "bincode.hpp" -#include "serde.hpp" - -namespace WitnessStack { - -struct Witness { - uint32_t value; - - friend bool operator==(const Witness&, const Witness&); - - bool operator<(Witness const& rhs) const { return value < rhs.value; } - - std::vector bincodeSerialize() const; - static Witness bincodeDeserialize(std::vector); -}; - -struct WitnessMap { - std::map value; - - friend bool operator==(const WitnessMap&, const WitnessMap&); - std::vector bincodeSerialize() const; - static WitnessMap bincodeDeserialize(std::vector); -}; - -struct StackItem { - uint32_t index; - WitnessStack::WitnessMap witness; - - friend bool operator==(const StackItem&, const StackItem&); - std::vector bincodeSerialize() const; - static StackItem bincodeDeserialize(std::vector); -}; - -struct WitnessStack { - std::vector stack; - - friend bool operator==(const WitnessStack&, const WitnessStack&); - std::vector bincodeSerialize() const; - static WitnessStack bincodeDeserialize(std::vector); -}; - -} // end of namespace WitnessStack - -namespace WitnessStack { - -inline bool operator==(const StackItem& lhs, const StackItem& rhs) -{ - if (!(lhs.index == rhs.index)) { - return false; - } - if (!(lhs.witness == rhs.witness)) { - return false; - } - return true; -} - -inline std::vector StackItem::bincodeSerialize() const -{ - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} - -inline StackItem StackItem::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 WitnessStack - -template <> -template -void serde::Serializable::serialize(const WitnessStack::StackItem& obj, Serializer& serializer) -{ - serializer.increase_container_depth(); - serde::Serializable::serialize(obj.index, serializer); - serde::Serializable::serialize(obj.witness, serializer); - serializer.decrease_container_depth(); -} - -template <> -template -WitnessStack::StackItem serde::Deserializable::deserialize(Deserializer& deserializer) -{ - deserializer.increase_container_depth(); - WitnessStack::StackItem obj; - obj.index = serde::Deserializable::deserialize(deserializer); - obj.witness = serde::Deserializable::deserialize(deserializer); - deserializer.decrease_container_depth(); - return obj; -} - -namespace WitnessStack { - -inline bool operator==(const Witness& lhs, const Witness& rhs) -{ - if (!(lhs.value == rhs.value)) { - return false; - } - return true; -} - -inline std::vector Witness::bincodeSerialize() const -{ - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} - -inline Witness Witness::bincodeDeserialize(std::vector input) -{ - auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); - if (deserializer.get_buffer_offset() < input.size()) { - throw_or_abort("Some input bytes were not read"); - } - return value; -} - -} // end of namespace WitnessStack - -template <> -template -void serde::Serializable::serialize(const WitnessStack::Witness& obj, Serializer& serializer) -{ - serializer.increase_container_depth(); - serde::Serializable::serialize(obj.value, serializer); - serializer.decrease_container_depth(); -} - -template <> -template -WitnessStack::Witness serde::Deserializable::deserialize(Deserializer& deserializer) -{ - deserializer.increase_container_depth(); - WitnessStack::Witness obj; - obj.value = serde::Deserializable::deserialize(deserializer); - deserializer.decrease_container_depth(); - return obj; -} - -namespace WitnessStack { - -inline bool operator==(const WitnessMap& lhs, const WitnessMap& rhs) -{ - if (!(lhs.value == rhs.value)) { - return false; - } - return true; -} - -inline std::vector WitnessMap::bincodeSerialize() const -{ - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} - -inline WitnessMap WitnessMap::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 WitnessStack - -template <> -template -void serde::Serializable::serialize(const WitnessStack::WitnessMap& obj, - Serializer& serializer) -{ - serializer.increase_container_depth(); - serde::Serializable::serialize(obj.value, serializer); - serializer.decrease_container_depth(); -} - -template <> -template -WitnessStack::WitnessMap serde::Deserializable::deserialize(Deserializer& deserializer) -{ - deserializer.increase_container_depth(); - WitnessStack::WitnessMap obj; - obj.value = serde::Deserializable::deserialize(deserializer); - deserializer.decrease_container_depth(); - return obj; -} - -namespace WitnessStack { - -inline bool operator==(const WitnessStack& lhs, const WitnessStack& rhs) -{ - if (!(lhs.stack == rhs.stack)) { - return false; - } - return true; -} - -inline std::vector WitnessStack::bincodeSerialize() const -{ - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} - -inline WitnessStack WitnessStack::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 WitnessStack - -template <> -template -void serde::Serializable::serialize(const WitnessStack::WitnessStack& obj, - Serializer& serializer) -{ - serializer.increase_container_depth(); - serde::Serializable::serialize(obj.stack, serializer); - serializer.decrease_container_depth(); -} - -template <> -template -WitnessStack::WitnessStack serde::Deserializable::deserialize(Deserializer& deserializer) -{ - deserializer.increase_container_depth(); - WitnessStack::WitnessStack obj; - obj.stack = serde::Deserializable::deserialize(deserializer); - deserializer.decrease_container_depth(); - return obj; -} diff --git a/build_manifest.yml b/build_manifest.yml index 9ae9eea56d6b..c07877468bc0 100644 --- a/build_manifest.yml +++ b/build_manifest.yml @@ -28,8 +28,6 @@ noir-packages: buildDir: noir dockerfile: Dockerfile.packages rebuildPatterns: .rebuild_patterns_packages - dependencies: - - bb.js # Builds and runs *all* noir package tests. noir-packages-tests: @@ -38,7 +36,6 @@ noir-packages-tests: rebuildPatterns: .rebuild_patterns_packages dependencies: - noir - - bb.js # Builds the brillig to avm transpiler. avm-transpiler: diff --git a/noir/Dockerfile.packages b/noir/Dockerfile.packages index f6bf8ad67568..c45260afaf4d 100644 --- a/noir/Dockerfile.packages +++ b/noir/Dockerfile.packages @@ -1,10 +1,4 @@ -FROM --platform=linux/amd64 aztecprotocol/bb.js as bb.js - FROM node:20 AS builder - -# Copy in portalled packages. -COPY --from=bb.js /usr/src/barretenberg/ts /usr/src/barretenberg/ts - ENV PATH=${PATH}:/usr/src/noir/noir-repo/target/release RUN curl https://sh.rustup.rs -sSf | bash -s -- -y RUN echo 'source $HOME/.cargo/env' >> $HOME/.bashrc diff --git a/noir/Dockerfile.packages-test b/noir/Dockerfile.packages-test index 6c9c7c9ac48a..33fac5120fb4 100644 --- a/noir/Dockerfile.packages-test +++ b/noir/Dockerfile.packages-test @@ -1,12 +1,6 @@ FROM aztecprotocol/noir AS noir -FROM --platform=linux/amd64 aztecprotocol/bb.js as bb.js FROM node:20 AS builder -COPY --from=bb.js /usr/src/barretenberg/ts /usr/src/barretenberg/ts - -WORKDIR /usr/src/barretenberg/ts -RUN yarn --immutable - COPY --from=noir /usr/src/noir/noir-repo/target/release /usr/src/noir/noir-repo/target/release ENV PATH=${PATH}:/usr/src/noir/noir-repo/target/release RUN curl https://sh.rustup.rs -sSf | bash -s -- -y diff --git a/noir/noir-repo/acvm-repo/acir/codegen/acir.cpp b/noir/noir-repo/acvm-repo/acir/codegen/acir.cpp index 2fd8180b5b7f..46809727000a 100644 --- a/noir/noir-repo/acvm-repo/acir/codegen/acir.cpp +++ b/noir/noir-repo/acvm-repo/acir/codegen/acir.cpp @@ -3,7 +3,7 @@ #include "serde.hpp" #include "bincode.hpp" -namespace Program { +namespace Circuit { struct BinaryFieldOp { @@ -140,7 +140,7 @@ namespace Program { }; struct HeapArray { - Program::MemoryAddress pointer; + Circuit::MemoryAddress pointer; uint64_t size; friend bool operator==(const HeapArray&, const HeapArray&); @@ -149,8 +149,8 @@ namespace Program { }; struct HeapVector { - Program::MemoryAddress pointer; - Program::MemoryAddress size; + Circuit::MemoryAddress pointer; + Circuit::MemoryAddress size; friend bool operator==(const HeapVector&, const HeapVector&); std::vector bincodeSerialize() const; @@ -160,8 +160,8 @@ namespace Program { struct BlackBoxOp { struct Sha256 { - Program::HeapVector message; - Program::HeapArray output; + Circuit::HeapVector message; + Circuit::HeapArray output; friend bool operator==(const Sha256&, const Sha256&); std::vector bincodeSerialize() const; @@ -169,8 +169,8 @@ namespace Program { }; struct Blake2s { - Program::HeapVector message; - Program::HeapArray output; + Circuit::HeapVector message; + Circuit::HeapArray output; friend bool operator==(const Blake2s&, const Blake2s&); std::vector bincodeSerialize() const; @@ -178,8 +178,8 @@ namespace Program { }; struct Blake3 { - Program::HeapVector message; - Program::HeapArray output; + Circuit::HeapVector message; + Circuit::HeapArray output; friend bool operator==(const Blake3&, const Blake3&); std::vector bincodeSerialize() const; @@ -187,8 +187,8 @@ namespace Program { }; struct Keccak256 { - Program::HeapVector message; - Program::HeapArray output; + Circuit::HeapVector message; + Circuit::HeapArray output; friend bool operator==(const Keccak256&, const Keccak256&); std::vector bincodeSerialize() const; @@ -196,8 +196,8 @@ namespace Program { }; struct Keccakf1600 { - Program::HeapVector message; - Program::HeapArray output; + Circuit::HeapVector message; + Circuit::HeapArray output; friend bool operator==(const Keccakf1600&, const Keccakf1600&); std::vector bincodeSerialize() const; @@ -205,11 +205,11 @@ namespace Program { }; struct EcdsaSecp256k1 { - Program::HeapVector hashed_msg; - Program::HeapArray public_key_x; - Program::HeapArray public_key_y; - Program::HeapArray signature; - Program::MemoryAddress result; + Circuit::HeapVector hashed_msg; + Circuit::HeapArray public_key_x; + Circuit::HeapArray public_key_y; + Circuit::HeapArray signature; + Circuit::MemoryAddress result; friend bool operator==(const EcdsaSecp256k1&, const EcdsaSecp256k1&); std::vector bincodeSerialize() const; @@ -217,11 +217,11 @@ namespace Program { }; struct EcdsaSecp256r1 { - Program::HeapVector hashed_msg; - Program::HeapArray public_key_x; - Program::HeapArray public_key_y; - Program::HeapArray signature; - Program::MemoryAddress result; + Circuit::HeapVector hashed_msg; + Circuit::HeapArray public_key_x; + Circuit::HeapArray public_key_y; + Circuit::HeapArray signature; + Circuit::MemoryAddress result; friend bool operator==(const EcdsaSecp256r1&, const EcdsaSecp256r1&); std::vector bincodeSerialize() const; @@ -229,11 +229,11 @@ namespace Program { }; struct SchnorrVerify { - Program::MemoryAddress public_key_x; - Program::MemoryAddress public_key_y; - Program::HeapVector message; - Program::HeapVector signature; - Program::MemoryAddress result; + Circuit::MemoryAddress public_key_x; + Circuit::MemoryAddress public_key_y; + Circuit::HeapVector message; + Circuit::HeapVector signature; + Circuit::MemoryAddress result; friend bool operator==(const SchnorrVerify&, const SchnorrVerify&); std::vector bincodeSerialize() const; @@ -241,9 +241,9 @@ namespace Program { }; struct PedersenCommitment { - Program::HeapVector inputs; - Program::MemoryAddress domain_separator; - Program::HeapArray output; + Circuit::HeapVector inputs; + Circuit::MemoryAddress domain_separator; + Circuit::HeapArray output; friend bool operator==(const PedersenCommitment&, const PedersenCommitment&); std::vector bincodeSerialize() const; @@ -251,9 +251,9 @@ namespace Program { }; struct PedersenHash { - Program::HeapVector inputs; - Program::MemoryAddress domain_separator; - Program::MemoryAddress output; + Circuit::HeapVector inputs; + Circuit::MemoryAddress domain_separator; + Circuit::MemoryAddress output; friend bool operator==(const PedersenHash&, const PedersenHash&); std::vector bincodeSerialize() const; @@ -261,9 +261,9 @@ namespace Program { }; struct FixedBaseScalarMul { - Program::MemoryAddress low; - Program::MemoryAddress high; - Program::HeapArray result; + Circuit::MemoryAddress low; + Circuit::MemoryAddress high; + Circuit::HeapArray result; friend bool operator==(const FixedBaseScalarMul&, const FixedBaseScalarMul&); std::vector bincodeSerialize() const; @@ -271,11 +271,11 @@ namespace Program { }; struct EmbeddedCurveAdd { - Program::MemoryAddress input1_x; - Program::MemoryAddress input1_y; - Program::MemoryAddress input2_x; - Program::MemoryAddress input2_y; - Program::HeapArray result; + Circuit::MemoryAddress input1_x; + Circuit::MemoryAddress input1_y; + Circuit::MemoryAddress input2_x; + Circuit::MemoryAddress input2_y; + Circuit::HeapArray result; friend bool operator==(const EmbeddedCurveAdd&, const EmbeddedCurveAdd&); std::vector bincodeSerialize() const; @@ -283,9 +283,9 @@ namespace Program { }; struct BigIntAdd { - Program::MemoryAddress lhs; - Program::MemoryAddress rhs; - Program::MemoryAddress output; + Circuit::MemoryAddress lhs; + Circuit::MemoryAddress rhs; + Circuit::MemoryAddress output; friend bool operator==(const BigIntAdd&, const BigIntAdd&); std::vector bincodeSerialize() const; @@ -293,9 +293,9 @@ namespace Program { }; struct BigIntSub { - Program::MemoryAddress lhs; - Program::MemoryAddress rhs; - Program::MemoryAddress output; + Circuit::MemoryAddress lhs; + Circuit::MemoryAddress rhs; + Circuit::MemoryAddress output; friend bool operator==(const BigIntSub&, const BigIntSub&); std::vector bincodeSerialize() const; @@ -303,9 +303,9 @@ namespace Program { }; struct BigIntMul { - Program::MemoryAddress lhs; - Program::MemoryAddress rhs; - Program::MemoryAddress output; + Circuit::MemoryAddress lhs; + Circuit::MemoryAddress rhs; + Circuit::MemoryAddress output; friend bool operator==(const BigIntMul&, const BigIntMul&); std::vector bincodeSerialize() const; @@ -313,9 +313,9 @@ namespace Program { }; struct BigIntDiv { - Program::MemoryAddress lhs; - Program::MemoryAddress rhs; - Program::MemoryAddress output; + Circuit::MemoryAddress lhs; + Circuit::MemoryAddress rhs; + Circuit::MemoryAddress output; friend bool operator==(const BigIntDiv&, const BigIntDiv&); std::vector bincodeSerialize() const; @@ -323,9 +323,9 @@ namespace Program { }; struct BigIntFromLeBytes { - Program::HeapVector inputs; - Program::HeapVector modulus; - Program::MemoryAddress output; + Circuit::HeapVector inputs; + Circuit::HeapVector modulus; + Circuit::MemoryAddress output; friend bool operator==(const BigIntFromLeBytes&, const BigIntFromLeBytes&); std::vector bincodeSerialize() const; @@ -333,8 +333,8 @@ namespace Program { }; struct BigIntToLeBytes { - Program::MemoryAddress input; - Program::HeapVector output; + Circuit::MemoryAddress input; + Circuit::HeapVector output; friend bool operator==(const BigIntToLeBytes&, const BigIntToLeBytes&); std::vector bincodeSerialize() const; @@ -342,9 +342,9 @@ namespace Program { }; struct Poseidon2Permutation { - Program::HeapVector message; - Program::HeapArray output; - Program::MemoryAddress len; + Circuit::HeapVector message; + Circuit::HeapArray output; + Circuit::MemoryAddress len; friend bool operator==(const Poseidon2Permutation&, const Poseidon2Permutation&); std::vector bincodeSerialize() const; @@ -352,9 +352,9 @@ namespace Program { }; struct Sha256Compression { - Program::HeapVector input; - Program::HeapVector hash_values; - Program::HeapArray output; + Circuit::HeapVector input; + Circuit::HeapVector hash_values; + Circuit::HeapArray output; friend bool operator==(const Sha256Compression&, const Sha256Compression&); std::vector bincodeSerialize() const; @@ -379,7 +379,7 @@ namespace Program { }; struct Array { - std::vector value_types; + std::vector value_types; uint64_t size; friend bool operator==(const Array&, const Array&); @@ -388,7 +388,7 @@ namespace Program { }; struct Vector { - std::vector value_types; + std::vector value_types; friend bool operator==(const Vector&, const Vector&); std::vector bincodeSerialize() const; @@ -413,7 +413,7 @@ namespace Program { struct ValueOrArray { struct MemoryAddress { - Program::MemoryAddress value; + Circuit::MemoryAddress value; friend bool operator==(const MemoryAddress&, const MemoryAddress&); std::vector bincodeSerialize() const; @@ -421,7 +421,7 @@ namespace Program { }; struct HeapArray { - Program::HeapArray value; + Circuit::HeapArray value; friend bool operator==(const HeapArray&, const HeapArray&); std::vector bincodeSerialize() const; @@ -429,7 +429,7 @@ namespace Program { }; struct HeapVector { - Program::HeapVector value; + Circuit::HeapVector value; friend bool operator==(const HeapVector&, const HeapVector&); std::vector bincodeSerialize() const; @@ -446,10 +446,10 @@ namespace Program { struct BrilligOpcode { struct BinaryFieldOp { - Program::MemoryAddress destination; - Program::BinaryFieldOp op; - Program::MemoryAddress lhs; - Program::MemoryAddress rhs; + Circuit::MemoryAddress destination; + Circuit::BinaryFieldOp op; + Circuit::MemoryAddress lhs; + Circuit::MemoryAddress rhs; friend bool operator==(const BinaryFieldOp&, const BinaryFieldOp&); std::vector bincodeSerialize() const; @@ -457,11 +457,11 @@ namespace Program { }; struct BinaryIntOp { - Program::MemoryAddress destination; - Program::BinaryIntOp op; + Circuit::MemoryAddress destination; + Circuit::BinaryIntOp op; uint32_t bit_size; - Program::MemoryAddress lhs; - Program::MemoryAddress rhs; + Circuit::MemoryAddress lhs; + Circuit::MemoryAddress rhs; friend bool operator==(const BinaryIntOp&, const BinaryIntOp&); std::vector bincodeSerialize() const; @@ -469,8 +469,8 @@ namespace Program { }; struct Cast { - Program::MemoryAddress destination; - Program::MemoryAddress source; + Circuit::MemoryAddress destination; + Circuit::MemoryAddress source; uint32_t bit_size; friend bool operator==(const Cast&, const Cast&); @@ -479,7 +479,7 @@ namespace Program { }; struct JumpIfNot { - Program::MemoryAddress condition; + Circuit::MemoryAddress condition; uint64_t location; friend bool operator==(const JumpIfNot&, const JumpIfNot&); @@ -488,7 +488,7 @@ namespace Program { }; struct JumpIf { - Program::MemoryAddress condition; + Circuit::MemoryAddress condition; uint64_t location; friend bool operator==(const JumpIf&, const JumpIf&); @@ -505,7 +505,7 @@ namespace Program { }; struct CalldataCopy { - Program::MemoryAddress destination_address; + Circuit::MemoryAddress destination_address; uint64_t size; uint64_t offset; @@ -523,9 +523,9 @@ namespace Program { }; struct Const { - Program::MemoryAddress destination; + Circuit::MemoryAddress destination; uint32_t bit_size; - Program::Value value; + Circuit::Value value; friend bool operator==(const Const&, const Const&); std::vector bincodeSerialize() const; @@ -540,10 +540,10 @@ namespace Program { struct ForeignCall { std::string function; - std::vector destinations; - std::vector destination_value_types; - std::vector inputs; - std::vector input_value_types; + std::vector destinations; + std::vector destination_value_types; + std::vector inputs; + std::vector input_value_types; friend bool operator==(const ForeignCall&, const ForeignCall&); std::vector bincodeSerialize() const; @@ -551,8 +551,8 @@ namespace Program { }; struct Mov { - Program::MemoryAddress destination; - Program::MemoryAddress source; + Circuit::MemoryAddress destination; + Circuit::MemoryAddress source; friend bool operator==(const Mov&, const Mov&); std::vector bincodeSerialize() const; @@ -560,8 +560,8 @@ namespace Program { }; struct Load { - Program::MemoryAddress destination; - Program::MemoryAddress source_pointer; + Circuit::MemoryAddress destination; + Circuit::MemoryAddress source_pointer; friend bool operator==(const Load&, const Load&); std::vector bincodeSerialize() const; @@ -569,8 +569,8 @@ namespace Program { }; struct Store { - Program::MemoryAddress destination_pointer; - Program::MemoryAddress source; + Circuit::MemoryAddress destination_pointer; + Circuit::MemoryAddress source; friend bool operator==(const Store&, const Store&); std::vector bincodeSerialize() const; @@ -578,7 +578,7 @@ namespace Program { }; struct BlackBox { - Program::BlackBoxOp value; + Circuit::BlackBoxOp value; friend bool operator==(const BlackBox&, const BlackBox&); std::vector bincodeSerialize() const; @@ -616,7 +616,7 @@ namespace Program { }; struct FunctionInput { - Program::Witness witness; + Circuit::Witness witness; uint32_t num_bits; friend bool operator==(const FunctionInput&, const FunctionInput&); @@ -627,9 +627,9 @@ namespace Program { struct BlackBoxFuncCall { struct AND { - Program::FunctionInput lhs; - Program::FunctionInput rhs; - Program::Witness output; + Circuit::FunctionInput lhs; + Circuit::FunctionInput rhs; + Circuit::Witness output; friend bool operator==(const AND&, const AND&); std::vector bincodeSerialize() const; @@ -637,9 +637,9 @@ namespace Program { }; struct XOR { - Program::FunctionInput lhs; - Program::FunctionInput rhs; - Program::Witness output; + Circuit::FunctionInput lhs; + Circuit::FunctionInput rhs; + Circuit::Witness output; friend bool operator==(const XOR&, const XOR&); std::vector bincodeSerialize() const; @@ -647,7 +647,7 @@ namespace Program { }; struct RANGE { - Program::FunctionInput input; + Circuit::FunctionInput input; friend bool operator==(const RANGE&, const RANGE&); std::vector bincodeSerialize() const; @@ -655,8 +655,8 @@ namespace Program { }; struct SHA256 { - std::vector inputs; - std::vector outputs; + std::vector inputs; + std::vector outputs; friend bool operator==(const SHA256&, const SHA256&); std::vector bincodeSerialize() const; @@ -664,8 +664,8 @@ namespace Program { }; struct Blake2s { - std::vector inputs; - std::vector outputs; + std::vector inputs; + std::vector outputs; friend bool operator==(const Blake2s&, const Blake2s&); std::vector bincodeSerialize() const; @@ -673,8 +673,8 @@ namespace Program { }; struct Blake3 { - std::vector inputs; - std::vector outputs; + std::vector inputs; + std::vector outputs; friend bool operator==(const Blake3&, const Blake3&); std::vector bincodeSerialize() const; @@ -682,11 +682,11 @@ namespace Program { }; struct SchnorrVerify { - Program::FunctionInput public_key_x; - Program::FunctionInput public_key_y; - std::vector signature; - std::vector message; - Program::Witness output; + Circuit::FunctionInput public_key_x; + Circuit::FunctionInput public_key_y; + std::vector signature; + std::vector message; + Circuit::Witness output; friend bool operator==(const SchnorrVerify&, const SchnorrVerify&); std::vector bincodeSerialize() const; @@ -694,9 +694,9 @@ namespace Program { }; struct PedersenCommitment { - std::vector inputs; + std::vector inputs; uint32_t domain_separator; - std::array outputs; + std::array outputs; friend bool operator==(const PedersenCommitment&, const PedersenCommitment&); std::vector bincodeSerialize() const; @@ -704,9 +704,9 @@ namespace Program { }; struct PedersenHash { - std::vector inputs; + std::vector inputs; uint32_t domain_separator; - Program::Witness output; + Circuit::Witness output; friend bool operator==(const PedersenHash&, const PedersenHash&); std::vector bincodeSerialize() const; @@ -714,11 +714,11 @@ namespace Program { }; struct EcdsaSecp256k1 { - std::vector public_key_x; - std::vector public_key_y; - std::vector signature; - std::vector hashed_message; - Program::Witness output; + std::vector public_key_x; + std::vector public_key_y; + std::vector signature; + std::vector hashed_message; + Circuit::Witness output; friend bool operator==(const EcdsaSecp256k1&, const EcdsaSecp256k1&); std::vector bincodeSerialize() const; @@ -726,11 +726,11 @@ namespace Program { }; struct EcdsaSecp256r1 { - std::vector public_key_x; - std::vector public_key_y; - std::vector signature; - std::vector hashed_message; - Program::Witness output; + std::vector public_key_x; + std::vector public_key_y; + std::vector signature; + std::vector hashed_message; + Circuit::Witness output; friend bool operator==(const EcdsaSecp256r1&, const EcdsaSecp256r1&); std::vector bincodeSerialize() const; @@ -738,9 +738,9 @@ namespace Program { }; struct FixedBaseScalarMul { - Program::FunctionInput low; - Program::FunctionInput high; - std::array outputs; + Circuit::FunctionInput low; + Circuit::FunctionInput high; + std::array outputs; friend bool operator==(const FixedBaseScalarMul&, const FixedBaseScalarMul&); std::vector bincodeSerialize() const; @@ -748,11 +748,11 @@ namespace Program { }; struct EmbeddedCurveAdd { - Program::FunctionInput input1_x; - Program::FunctionInput input1_y; - Program::FunctionInput input2_x; - Program::FunctionInput input2_y; - std::array outputs; + Circuit::FunctionInput input1_x; + Circuit::FunctionInput input1_y; + Circuit::FunctionInput input2_x; + Circuit::FunctionInput input2_y; + std::array outputs; friend bool operator==(const EmbeddedCurveAdd&, const EmbeddedCurveAdd&); std::vector bincodeSerialize() const; @@ -760,8 +760,8 @@ namespace Program { }; struct Keccak256 { - std::vector inputs; - std::vector outputs; + std::vector inputs; + std::vector outputs; friend bool operator==(const Keccak256&, const Keccak256&); std::vector bincodeSerialize() const; @@ -769,9 +769,9 @@ namespace Program { }; struct Keccak256VariableLength { - std::vector inputs; - Program::FunctionInput var_message_size; - std::vector outputs; + std::vector inputs; + Circuit::FunctionInput var_message_size; + std::vector outputs; friend bool operator==(const Keccak256VariableLength&, const Keccak256VariableLength&); std::vector bincodeSerialize() const; @@ -779,8 +779,8 @@ namespace Program { }; struct Keccakf1600 { - std::vector inputs; - std::vector outputs; + std::vector inputs; + std::vector outputs; friend bool operator==(const Keccakf1600&, const Keccakf1600&); std::vector bincodeSerialize() const; @@ -788,10 +788,10 @@ namespace Program { }; struct RecursiveAggregation { - std::vector verification_key; - std::vector proof; - std::vector public_inputs; - Program::FunctionInput key_hash; + std::vector verification_key; + std::vector proof; + std::vector public_inputs; + Circuit::FunctionInput key_hash; friend bool operator==(const RecursiveAggregation&, const RecursiveAggregation&); std::vector bincodeSerialize() const; @@ -839,7 +839,7 @@ namespace Program { }; struct BigIntFromLeBytes { - std::vector inputs; + std::vector inputs; std::vector modulus; uint32_t output; @@ -850,7 +850,7 @@ namespace Program { struct BigIntToLeBytes { uint32_t input; - std::vector outputs; + std::vector outputs; friend bool operator==(const BigIntToLeBytes&, const BigIntToLeBytes&); std::vector bincodeSerialize() const; @@ -858,8 +858,8 @@ namespace Program { }; struct Poseidon2Permutation { - std::vector inputs; - std::vector outputs; + std::vector inputs; + std::vector outputs; uint32_t len; friend bool operator==(const Poseidon2Permutation&, const Poseidon2Permutation&); @@ -868,9 +868,9 @@ namespace Program { }; struct Sha256Compression { - std::vector inputs; - std::vector hash_values; - std::vector outputs; + std::vector inputs; + std::vector hash_values; + std::vector outputs; friend bool operator==(const Sha256Compression&, const Sha256Compression&); std::vector bincodeSerialize() const; @@ -893,8 +893,8 @@ namespace Program { }; struct Expression { - std::vector> mul_terms; - std::vector> linear_combinations; + std::vector> mul_terms; + std::vector> linear_combinations; std::string q_c; friend bool operator==(const Expression&, const Expression&); @@ -905,7 +905,7 @@ namespace Program { struct BrilligInputs { struct Single { - Program::Expression value; + Circuit::Expression value; friend bool operator==(const Single&, const Single&); std::vector bincodeSerialize() const; @@ -913,7 +913,7 @@ namespace Program { }; struct Array { - std::vector value; + std::vector value; friend bool operator==(const Array&, const Array&); std::vector bincodeSerialize() const; @@ -921,7 +921,7 @@ namespace Program { }; struct MemoryArray { - Program::BlockId value; + Circuit::BlockId value; friend bool operator==(const MemoryArray&, const MemoryArray&); std::vector bincodeSerialize() const; @@ -938,7 +938,7 @@ namespace Program { struct BrilligOutputs { struct Simple { - Program::Witness value; + Circuit::Witness value; friend bool operator==(const Simple&, const Simple&); std::vector bincodeSerialize() const; @@ -946,7 +946,7 @@ namespace Program { }; struct Array { - std::vector value; + std::vector value; friend bool operator==(const Array&, const Array&); std::vector bincodeSerialize() const; @@ -961,10 +961,10 @@ namespace Program { }; struct Brillig { - std::vector inputs; - std::vector outputs; - std::vector bytecode; - std::optional predicate; + std::vector inputs; + std::vector outputs; + std::vector bytecode; + std::optional predicate; friend bool operator==(const Brillig&, const Brillig&); std::vector bincodeSerialize() const; @@ -974,8 +974,8 @@ namespace Program { struct Directive { struct ToLeRadix { - Program::Expression a; - std::vector b; + Circuit::Expression a; + std::vector b; uint32_t radix; friend bool operator==(const ToLeRadix&, const ToLeRadix&); @@ -991,9 +991,9 @@ namespace Program { }; struct MemOp { - Program::Expression operation; - Program::Expression index; - Program::Expression value; + Circuit::Expression operation; + Circuit::Expression index; + Circuit::Expression value; friend bool operator==(const MemOp&, const MemOp&); std::vector bincodeSerialize() const; @@ -1003,7 +1003,7 @@ namespace Program { struct Opcode { struct AssertZero { - Program::Expression value; + Circuit::Expression value; friend bool operator==(const AssertZero&, const AssertZero&); std::vector bincodeSerialize() const; @@ -1011,7 +1011,7 @@ namespace Program { }; struct BlackBoxFuncCall { - Program::BlackBoxFuncCall value; + Circuit::BlackBoxFuncCall value; friend bool operator==(const BlackBoxFuncCall&, const BlackBoxFuncCall&); std::vector bincodeSerialize() const; @@ -1019,7 +1019,7 @@ namespace Program { }; struct Directive { - Program::Directive value; + Circuit::Directive value; friend bool operator==(const Directive&, const Directive&); std::vector bincodeSerialize() const; @@ -1027,7 +1027,7 @@ namespace Program { }; struct Brillig { - Program::Brillig value; + Circuit::Brillig value; friend bool operator==(const Brillig&, const Brillig&); std::vector bincodeSerialize() const; @@ -1035,9 +1035,9 @@ namespace Program { }; struct MemoryOp { - Program::BlockId block_id; - Program::MemOp op; - std::optional predicate; + Circuit::BlockId block_id; + Circuit::MemOp op; + std::optional predicate; friend bool operator==(const MemoryOp&, const MemoryOp&); std::vector bincodeSerialize() const; @@ -1045,8 +1045,8 @@ namespace Program { }; struct MemoryInit { - Program::BlockId block_id; - std::vector init; + Circuit::BlockId block_id; + std::vector init; friend bool operator==(const MemoryInit&, const MemoryInit&); std::vector bincodeSerialize() const; @@ -1055,8 +1055,8 @@ namespace Program { struct Call { uint32_t id; - std::vector inputs; - std::vector outputs; + std::vector inputs; + std::vector outputs; friend bool operator==(const Call&, const Call&); std::vector bincodeSerialize() const; @@ -1120,7 +1120,7 @@ namespace Program { }; struct PublicInputs { - std::vector value; + std::vector value; friend bool operator==(const PublicInputs&, const PublicInputs&); std::vector bincodeSerialize() const; @@ -1129,12 +1129,12 @@ namespace Program { struct Circuit { uint32_t current_witness_index; - std::vector opcodes; - Program::ExpressionWidth expression_width; - std::vector private_parameters; - Program::PublicInputs public_parameters; - Program::PublicInputs return_values; - std::vector> assert_messages; + std::vector opcodes; + Circuit::ExpressionWidth expression_width; + std::vector private_parameters; + Circuit::PublicInputs public_parameters; + Circuit::PublicInputs return_values; + std::vector> assert_messages; bool recursive; friend bool operator==(const Circuit&, const Circuit&); @@ -1142,18 +1142,10 @@ namespace Program { static Circuit bincodeDeserialize(std::vector); }; - struct Program { - std::vector functions; +} // end of namespace Circuit - friend bool operator==(const Program&, const Program&); - std::vector bincodeSerialize() const; - static Program bincodeDeserialize(std::vector); - }; - -} // end of namespace Program - -namespace Program { +namespace Circuit { inline bool operator==(const BinaryFieldOp &lhs, const BinaryFieldOp &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -1175,11 +1167,11 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BinaryFieldOp &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BinaryFieldOp &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -1187,15 +1179,15 @@ void serde::Serializable::serialize(const Program::Binar template <> template -Program::BinaryFieldOp serde::Deserializable::deserialize(Deserializer &deserializer) { +Circuit::BinaryFieldOp serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Program::BinaryFieldOp obj; + Circuit::BinaryFieldOp obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BinaryFieldOp::Add &lhs, const BinaryFieldOp::Add &rhs) { return true; @@ -1216,21 +1208,21 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BinaryFieldOp::Add &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BinaryFieldOp::Add &obj, Serializer &serializer) { } template <> template -Program::BinaryFieldOp::Add serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BinaryFieldOp::Add obj; +Circuit::BinaryFieldOp::Add serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BinaryFieldOp::Add obj; return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BinaryFieldOp::Sub &lhs, const BinaryFieldOp::Sub &rhs) { return true; @@ -1251,21 +1243,21 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BinaryFieldOp::Sub &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BinaryFieldOp::Sub &obj, Serializer &serializer) { } template <> template -Program::BinaryFieldOp::Sub serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BinaryFieldOp::Sub obj; +Circuit::BinaryFieldOp::Sub serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BinaryFieldOp::Sub obj; return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BinaryFieldOp::Mul &lhs, const BinaryFieldOp::Mul &rhs) { return true; @@ -1286,21 +1278,21 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BinaryFieldOp::Mul &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BinaryFieldOp::Mul &obj, Serializer &serializer) { } template <> template -Program::BinaryFieldOp::Mul serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BinaryFieldOp::Mul obj; +Circuit::BinaryFieldOp::Mul serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BinaryFieldOp::Mul obj; return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BinaryFieldOp::Div &lhs, const BinaryFieldOp::Div &rhs) { return true; @@ -1321,21 +1313,21 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BinaryFieldOp::Div &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BinaryFieldOp::Div &obj, Serializer &serializer) { } template <> template -Program::BinaryFieldOp::Div serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BinaryFieldOp::Div obj; +Circuit::BinaryFieldOp::Div serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BinaryFieldOp::Div obj; return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BinaryFieldOp::Equals &lhs, const BinaryFieldOp::Equals &rhs) { return true; @@ -1356,21 +1348,21 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BinaryFieldOp::Equals &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BinaryFieldOp::Equals &obj, Serializer &serializer) { } template <> template -Program::BinaryFieldOp::Equals serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BinaryFieldOp::Equals obj; +Circuit::BinaryFieldOp::Equals serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BinaryFieldOp::Equals obj; return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BinaryIntOp &lhs, const BinaryIntOp &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -1392,11 +1384,11 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BinaryIntOp &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BinaryIntOp &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -1404,15 +1396,15 @@ void serde::Serializable::serialize(const Program::BinaryI template <> template -Program::BinaryIntOp serde::Deserializable::deserialize(Deserializer &deserializer) { +Circuit::BinaryIntOp serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Program::BinaryIntOp obj; + Circuit::BinaryIntOp obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BinaryIntOp::Add &lhs, const BinaryIntOp::Add &rhs) { return true; @@ -1433,21 +1425,21 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BinaryIntOp::Add &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BinaryIntOp::Add &obj, Serializer &serializer) { } template <> template -Program::BinaryIntOp::Add serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BinaryIntOp::Add obj; +Circuit::BinaryIntOp::Add serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BinaryIntOp::Add obj; return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BinaryIntOp::Sub &lhs, const BinaryIntOp::Sub &rhs) { return true; @@ -1468,21 +1460,21 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BinaryIntOp::Sub &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BinaryIntOp::Sub &obj, Serializer &serializer) { } template <> template -Program::BinaryIntOp::Sub serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BinaryIntOp::Sub obj; +Circuit::BinaryIntOp::Sub serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BinaryIntOp::Sub obj; return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BinaryIntOp::Mul &lhs, const BinaryIntOp::Mul &rhs) { return true; @@ -1503,21 +1495,21 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BinaryIntOp::Mul &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BinaryIntOp::Mul &obj, Serializer &serializer) { } template <> template -Program::BinaryIntOp::Mul serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BinaryIntOp::Mul obj; +Circuit::BinaryIntOp::Mul serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BinaryIntOp::Mul obj; return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BinaryIntOp::SignedDiv &lhs, const BinaryIntOp::SignedDiv &rhs) { return true; @@ -1538,21 +1530,21 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BinaryIntOp::SignedDiv &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BinaryIntOp::SignedDiv &obj, Serializer &serializer) { } template <> template -Program::BinaryIntOp::SignedDiv serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BinaryIntOp::SignedDiv obj; +Circuit::BinaryIntOp::SignedDiv serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BinaryIntOp::SignedDiv obj; return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BinaryIntOp::UnsignedDiv &lhs, const BinaryIntOp::UnsignedDiv &rhs) { return true; @@ -1573,21 +1565,21 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BinaryIntOp::UnsignedDiv &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BinaryIntOp::UnsignedDiv &obj, Serializer &serializer) { } template <> template -Program::BinaryIntOp::UnsignedDiv serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BinaryIntOp::UnsignedDiv obj; +Circuit::BinaryIntOp::UnsignedDiv serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BinaryIntOp::UnsignedDiv obj; return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BinaryIntOp::Equals &lhs, const BinaryIntOp::Equals &rhs) { return true; @@ -1608,21 +1600,21 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BinaryIntOp::Equals &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BinaryIntOp::Equals &obj, Serializer &serializer) { } template <> template -Program::BinaryIntOp::Equals serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BinaryIntOp::Equals obj; +Circuit::BinaryIntOp::Equals serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BinaryIntOp::Equals obj; return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BinaryIntOp::LessThan &lhs, const BinaryIntOp::LessThan &rhs) { return true; @@ -1643,21 +1635,21 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BinaryIntOp::LessThan &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BinaryIntOp::LessThan &obj, Serializer &serializer) { } template <> template -Program::BinaryIntOp::LessThan serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BinaryIntOp::LessThan obj; +Circuit::BinaryIntOp::LessThan serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BinaryIntOp::LessThan obj; return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BinaryIntOp::LessThanEquals &lhs, const BinaryIntOp::LessThanEquals &rhs) { return true; @@ -1678,21 +1670,21 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BinaryIntOp::LessThanEquals &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BinaryIntOp::LessThanEquals &obj, Serializer &serializer) { } template <> template -Program::BinaryIntOp::LessThanEquals serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BinaryIntOp::LessThanEquals obj; +Circuit::BinaryIntOp::LessThanEquals serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BinaryIntOp::LessThanEquals obj; return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BinaryIntOp::And &lhs, const BinaryIntOp::And &rhs) { return true; @@ -1713,21 +1705,21 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BinaryIntOp::And &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BinaryIntOp::And &obj, Serializer &serializer) { } template <> template -Program::BinaryIntOp::And serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BinaryIntOp::And obj; +Circuit::BinaryIntOp::And serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BinaryIntOp::And obj; return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BinaryIntOp::Or &lhs, const BinaryIntOp::Or &rhs) { return true; @@ -1748,21 +1740,21 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BinaryIntOp::Or &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BinaryIntOp::Or &obj, Serializer &serializer) { } template <> template -Program::BinaryIntOp::Or serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BinaryIntOp::Or obj; +Circuit::BinaryIntOp::Or serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BinaryIntOp::Or obj; return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BinaryIntOp::Xor &lhs, const BinaryIntOp::Xor &rhs) { return true; @@ -1783,21 +1775,21 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BinaryIntOp::Xor &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BinaryIntOp::Xor &obj, Serializer &serializer) { } template <> template -Program::BinaryIntOp::Xor serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BinaryIntOp::Xor obj; +Circuit::BinaryIntOp::Xor serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BinaryIntOp::Xor obj; return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BinaryIntOp::Shl &lhs, const BinaryIntOp::Shl &rhs) { return true; @@ -1818,21 +1810,21 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BinaryIntOp::Shl &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BinaryIntOp::Shl &obj, Serializer &serializer) { } template <> template -Program::BinaryIntOp::Shl serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BinaryIntOp::Shl obj; +Circuit::BinaryIntOp::Shl serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BinaryIntOp::Shl obj; return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BinaryIntOp::Shr &lhs, const BinaryIntOp::Shr &rhs) { return true; @@ -1853,21 +1845,21 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BinaryIntOp::Shr &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BinaryIntOp::Shr &obj, Serializer &serializer) { } template <> template -Program::BinaryIntOp::Shr serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BinaryIntOp::Shr obj; +Circuit::BinaryIntOp::Shr serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BinaryIntOp::Shr obj; return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BlackBoxFuncCall &lhs, const BlackBoxFuncCall &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -1889,11 +1881,11 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BlackBoxFuncCall &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -1901,15 +1893,15 @@ void serde::Serializable::serialize(const Program::Bl template <> template -Program::BlackBoxFuncCall serde::Deserializable::deserialize(Deserializer &deserializer) { +Circuit::BlackBoxFuncCall serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Program::BlackBoxFuncCall obj; + Circuit::BlackBoxFuncCall obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BlackBoxFuncCall::AND &lhs, const BlackBoxFuncCall::AND &rhs) { if (!(lhs.lhs == rhs.lhs)) { return false; } @@ -1933,11 +1925,11 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BlackBoxFuncCall::AND &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::AND &obj, Serializer &serializer) { serde::Serializable::serialize(obj.lhs, serializer); serde::Serializable::serialize(obj.rhs, serializer); serde::Serializable::serialize(obj.output, serializer); @@ -1945,15 +1937,15 @@ void serde::Serializable::serialize(const Progra template <> template -Program::BlackBoxFuncCall::AND serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BlackBoxFuncCall::AND obj; +Circuit::BlackBoxFuncCall::AND serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BlackBoxFuncCall::AND obj; obj.lhs = serde::Deserializable::deserialize(deserializer); obj.rhs = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BlackBoxFuncCall::XOR &lhs, const BlackBoxFuncCall::XOR &rhs) { if (!(lhs.lhs == rhs.lhs)) { return false; } @@ -1977,11 +1969,11 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BlackBoxFuncCall::XOR &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::XOR &obj, Serializer &serializer) { serde::Serializable::serialize(obj.lhs, serializer); serde::Serializable::serialize(obj.rhs, serializer); serde::Serializable::serialize(obj.output, serializer); @@ -1989,15 +1981,15 @@ void serde::Serializable::serialize(const Progra template <> template -Program::BlackBoxFuncCall::XOR serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BlackBoxFuncCall::XOR obj; +Circuit::BlackBoxFuncCall::XOR serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BlackBoxFuncCall::XOR obj; obj.lhs = serde::Deserializable::deserialize(deserializer); obj.rhs = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BlackBoxFuncCall::RANGE &lhs, const BlackBoxFuncCall::RANGE &rhs) { if (!(lhs.input == rhs.input)) { return false; } @@ -2019,23 +2011,23 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BlackBoxFuncCall::RANGE &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::RANGE &obj, Serializer &serializer) { serde::Serializable::serialize(obj.input, serializer); } template <> template -Program::BlackBoxFuncCall::RANGE serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BlackBoxFuncCall::RANGE obj; +Circuit::BlackBoxFuncCall::RANGE serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BlackBoxFuncCall::RANGE obj; obj.input = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BlackBoxFuncCall::SHA256 &lhs, const BlackBoxFuncCall::SHA256 &rhs) { if (!(lhs.inputs == rhs.inputs)) { return false; } @@ -2058,25 +2050,25 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BlackBoxFuncCall::SHA256 &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::SHA256 &obj, Serializer &serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.outputs, serializer); } template <> template -Program::BlackBoxFuncCall::SHA256 serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BlackBoxFuncCall::SHA256 obj; +Circuit::BlackBoxFuncCall::SHA256 serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BlackBoxFuncCall::SHA256 obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BlackBoxFuncCall::Blake2s &lhs, const BlackBoxFuncCall::Blake2s &rhs) { if (!(lhs.inputs == rhs.inputs)) { return false; } @@ -2099,25 +2091,25 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BlackBoxFuncCall::Blake2s &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::Blake2s &obj, Serializer &serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.outputs, serializer); } template <> template -Program::BlackBoxFuncCall::Blake2s serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BlackBoxFuncCall::Blake2s obj; +Circuit::BlackBoxFuncCall::Blake2s serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BlackBoxFuncCall::Blake2s obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BlackBoxFuncCall::Blake3 &lhs, const BlackBoxFuncCall::Blake3 &rhs) { if (!(lhs.inputs == rhs.inputs)) { return false; } @@ -2140,25 +2132,25 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BlackBoxFuncCall::Blake3 &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::Blake3 &obj, Serializer &serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.outputs, serializer); } template <> template -Program::BlackBoxFuncCall::Blake3 serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BlackBoxFuncCall::Blake3 obj; +Circuit::BlackBoxFuncCall::Blake3 serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BlackBoxFuncCall::Blake3 obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BlackBoxFuncCall::SchnorrVerify &lhs, const BlackBoxFuncCall::SchnorrVerify &rhs) { if (!(lhs.public_key_x == rhs.public_key_x)) { return false; } @@ -2184,11 +2176,11 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BlackBoxFuncCall::SchnorrVerify &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::SchnorrVerify &obj, Serializer &serializer) { serde::Serializable::serialize(obj.public_key_x, serializer); serde::Serializable::serialize(obj.public_key_y, serializer); serde::Serializable::serialize(obj.signature, serializer); @@ -2198,8 +2190,8 @@ void serde::Serializable::serialize(co template <> template -Program::BlackBoxFuncCall::SchnorrVerify serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BlackBoxFuncCall::SchnorrVerify obj; +Circuit::BlackBoxFuncCall::SchnorrVerify serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BlackBoxFuncCall::SchnorrVerify obj; obj.public_key_x = serde::Deserializable::deserialize(deserializer); obj.public_key_y = serde::Deserializable::deserialize(deserializer); obj.signature = serde::Deserializable::deserialize(deserializer); @@ -2208,7 +2200,7 @@ Program::BlackBoxFuncCall::SchnorrVerify serde::Deserializable template -void serde::Serializable::serialize(const Program::BlackBoxFuncCall::PedersenCommitment &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::PedersenCommitment &obj, Serializer &serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.domain_separator, serializer); serde::Serializable::serialize(obj.outputs, serializer); @@ -2244,15 +2236,15 @@ void serde::Serializable::seriali template <> template -Program::BlackBoxFuncCall::PedersenCommitment serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BlackBoxFuncCall::PedersenCommitment obj; +Circuit::BlackBoxFuncCall::PedersenCommitment serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BlackBoxFuncCall::PedersenCommitment obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.domain_separator = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BlackBoxFuncCall::PedersenHash &lhs, const BlackBoxFuncCall::PedersenHash &rhs) { if (!(lhs.inputs == rhs.inputs)) { return false; } @@ -2276,11 +2268,11 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BlackBoxFuncCall::PedersenHash &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::PedersenHash &obj, Serializer &serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.domain_separator, serializer); serde::Serializable::serialize(obj.output, serializer); @@ -2288,15 +2280,15 @@ void serde::Serializable::serialize(con template <> template -Program::BlackBoxFuncCall::PedersenHash serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BlackBoxFuncCall::PedersenHash obj; +Circuit::BlackBoxFuncCall::PedersenHash serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BlackBoxFuncCall::PedersenHash obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.domain_separator = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BlackBoxFuncCall::EcdsaSecp256k1 &lhs, const BlackBoxFuncCall::EcdsaSecp256k1 &rhs) { if (!(lhs.public_key_x == rhs.public_key_x)) { return false; } @@ -2322,11 +2314,11 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BlackBoxFuncCall::EcdsaSecp256k1 &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::EcdsaSecp256k1 &obj, Serializer &serializer) { serde::Serializable::serialize(obj.public_key_x, serializer); serde::Serializable::serialize(obj.public_key_y, serializer); serde::Serializable::serialize(obj.signature, serializer); @@ -2336,8 +2328,8 @@ void serde::Serializable::serialize(c template <> template -Program::BlackBoxFuncCall::EcdsaSecp256k1 serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BlackBoxFuncCall::EcdsaSecp256k1 obj; +Circuit::BlackBoxFuncCall::EcdsaSecp256k1 serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BlackBoxFuncCall::EcdsaSecp256k1 obj; obj.public_key_x = serde::Deserializable::deserialize(deserializer); obj.public_key_y = serde::Deserializable::deserialize(deserializer); obj.signature = serde::Deserializable::deserialize(deserializer); @@ -2346,7 +2338,7 @@ Program::BlackBoxFuncCall::EcdsaSecp256k1 serde::Deserializable template -void serde::Serializable::serialize(const Program::BlackBoxFuncCall::EcdsaSecp256r1 &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::EcdsaSecp256r1 &obj, Serializer &serializer) { serde::Serializable::serialize(obj.public_key_x, serializer); serde::Serializable::serialize(obj.public_key_y, serializer); serde::Serializable::serialize(obj.signature, serializer); @@ -2386,8 +2378,8 @@ void serde::Serializable::serialize(c template <> template -Program::BlackBoxFuncCall::EcdsaSecp256r1 serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BlackBoxFuncCall::EcdsaSecp256r1 obj; +Circuit::BlackBoxFuncCall::EcdsaSecp256r1 serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BlackBoxFuncCall::EcdsaSecp256r1 obj; obj.public_key_x = serde::Deserializable::deserialize(deserializer); obj.public_key_y = serde::Deserializable::deserialize(deserializer); obj.signature = serde::Deserializable::deserialize(deserializer); @@ -2396,7 +2388,7 @@ Program::BlackBoxFuncCall::EcdsaSecp256r1 serde::Deserializable template -void serde::Serializable::serialize(const Program::BlackBoxFuncCall::FixedBaseScalarMul &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::FixedBaseScalarMul &obj, Serializer &serializer) { serde::Serializable::serialize(obj.low, serializer); serde::Serializable::serialize(obj.high, serializer); serde::Serializable::serialize(obj.outputs, serializer); @@ -2432,15 +2424,15 @@ void serde::Serializable::seriali template <> template -Program::BlackBoxFuncCall::FixedBaseScalarMul serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BlackBoxFuncCall::FixedBaseScalarMul obj; +Circuit::BlackBoxFuncCall::FixedBaseScalarMul serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BlackBoxFuncCall::FixedBaseScalarMul obj; obj.low = serde::Deserializable::deserialize(deserializer); obj.high = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BlackBoxFuncCall::EmbeddedCurveAdd &lhs, const BlackBoxFuncCall::EmbeddedCurveAdd &rhs) { if (!(lhs.input1_x == rhs.input1_x)) { return false; } @@ -2466,11 +2458,11 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BlackBoxFuncCall::EmbeddedCurveAdd &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::EmbeddedCurveAdd &obj, Serializer &serializer) { serde::Serializable::serialize(obj.input1_x, serializer); serde::Serializable::serialize(obj.input1_y, serializer); serde::Serializable::serialize(obj.input2_x, serializer); @@ -2480,8 +2472,8 @@ void serde::Serializable::serialize template <> template -Program::BlackBoxFuncCall::EmbeddedCurveAdd serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BlackBoxFuncCall::EmbeddedCurveAdd obj; +Circuit::BlackBoxFuncCall::EmbeddedCurveAdd serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BlackBoxFuncCall::EmbeddedCurveAdd obj; obj.input1_x = serde::Deserializable::deserialize(deserializer); obj.input1_y = serde::Deserializable::deserialize(deserializer); obj.input2_x = serde::Deserializable::deserialize(deserializer); @@ -2490,7 +2482,7 @@ Program::BlackBoxFuncCall::EmbeddedCurveAdd serde::Deserializable template -void serde::Serializable::serialize(const Program::BlackBoxFuncCall::Keccak256 &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::Keccak256 &obj, Serializer &serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.outputs, serializer); } template <> template -Program::BlackBoxFuncCall::Keccak256 serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BlackBoxFuncCall::Keccak256 obj; +Circuit::BlackBoxFuncCall::Keccak256 serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BlackBoxFuncCall::Keccak256 obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BlackBoxFuncCall::Keccak256VariableLength &lhs, const BlackBoxFuncCall::Keccak256VariableLength &rhs) { if (!(lhs.inputs == rhs.inputs)) { return false; } @@ -2555,11 +2547,11 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BlackBoxFuncCall::Keccak256VariableLength &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::Keccak256VariableLength &obj, Serializer &serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.var_message_size, serializer); serde::Serializable::serialize(obj.outputs, serializer); @@ -2567,15 +2559,15 @@ void serde::Serializable::se template <> template -Program::BlackBoxFuncCall::Keccak256VariableLength serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BlackBoxFuncCall::Keccak256VariableLength obj; +Circuit::BlackBoxFuncCall::Keccak256VariableLength serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BlackBoxFuncCall::Keccak256VariableLength obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.var_message_size = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BlackBoxFuncCall::Keccakf1600 &lhs, const BlackBoxFuncCall::Keccakf1600 &rhs) { if (!(lhs.inputs == rhs.inputs)) { return false; } @@ -2598,25 +2590,25 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BlackBoxFuncCall::Keccakf1600 &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::Keccakf1600 &obj, Serializer &serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.outputs, serializer); } template <> template -Program::BlackBoxFuncCall::Keccakf1600 serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BlackBoxFuncCall::Keccakf1600 obj; +Circuit::BlackBoxFuncCall::Keccakf1600 serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BlackBoxFuncCall::Keccakf1600 obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BlackBoxFuncCall::RecursiveAggregation &lhs, const BlackBoxFuncCall::RecursiveAggregation &rhs) { if (!(lhs.verification_key == rhs.verification_key)) { return false; } @@ -2641,11 +2633,11 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BlackBoxFuncCall::RecursiveAggregation &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::RecursiveAggregation &obj, Serializer &serializer) { serde::Serializable::serialize(obj.verification_key, serializer); serde::Serializable::serialize(obj.proof, serializer); serde::Serializable::serialize(obj.public_inputs, serializer); @@ -2654,8 +2646,8 @@ void serde::Serializable::seria template <> template -Program::BlackBoxFuncCall::RecursiveAggregation serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BlackBoxFuncCall::RecursiveAggregation obj; +Circuit::BlackBoxFuncCall::RecursiveAggregation serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BlackBoxFuncCall::RecursiveAggregation obj; obj.verification_key = serde::Deserializable::deserialize(deserializer); obj.proof = serde::Deserializable::deserialize(deserializer); obj.public_inputs = serde::Deserializable::deserialize(deserializer); @@ -2663,7 +2655,7 @@ Program::BlackBoxFuncCall::RecursiveAggregation serde::Deserializable template -void serde::Serializable::serialize(const Program::BlackBoxFuncCall::BigIntAdd &obj, Serializer &serializer) { +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); @@ -2699,15 +2691,15 @@ void serde::Serializable::serialize(const template <> template -Program::BlackBoxFuncCall::BigIntAdd serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BlackBoxFuncCall::BigIntAdd obj; +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 Program { +namespace Circuit { inline bool operator==(const BlackBoxFuncCall::BigIntSub &lhs, const BlackBoxFuncCall::BigIntSub &rhs) { if (!(lhs.lhs == rhs.lhs)) { return false; } @@ -2731,11 +2723,11 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BlackBoxFuncCall::BigIntSub &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::BigIntSub &obj, Serializer &serializer) { serde::Serializable::serialize(obj.lhs, serializer); serde::Serializable::serialize(obj.rhs, serializer); serde::Serializable::serialize(obj.output, serializer); @@ -2743,15 +2735,15 @@ void serde::Serializable::serialize(const template <> template -Program::BlackBoxFuncCall::BigIntSub serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BlackBoxFuncCall::BigIntSub obj; +Circuit::BlackBoxFuncCall::BigIntSub serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BlackBoxFuncCall::BigIntSub obj; obj.lhs = serde::Deserializable::deserialize(deserializer); obj.rhs = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BlackBoxFuncCall::BigIntMul &lhs, const BlackBoxFuncCall::BigIntMul &rhs) { if (!(lhs.lhs == rhs.lhs)) { return false; } @@ -2775,11 +2767,11 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BlackBoxFuncCall::BigIntMul &obj, Serializer &serializer) { +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); @@ -2787,15 +2779,15 @@ void serde::Serializable::serialize(const template <> template -Program::BlackBoxFuncCall::BigIntMul serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BlackBoxFuncCall::BigIntMul obj; +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 Program { +namespace Circuit { inline bool operator==(const BlackBoxFuncCall::BigIntDiv &lhs, const BlackBoxFuncCall::BigIntDiv &rhs) { if (!(lhs.lhs == rhs.lhs)) { return false; } @@ -2819,11 +2811,11 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BlackBoxFuncCall::BigIntDiv &obj, Serializer &serializer) { +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); @@ -2831,15 +2823,15 @@ void serde::Serializable::serialize(const template <> template -Program::BlackBoxFuncCall::BigIntDiv serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BlackBoxFuncCall::BigIntDiv obj; +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 Program { +namespace Circuit { inline bool operator==(const BlackBoxFuncCall::BigIntFromLeBytes &lhs, const BlackBoxFuncCall::BigIntFromLeBytes &rhs) { if (!(lhs.inputs == rhs.inputs)) { return false; } @@ -2863,11 +2855,11 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BlackBoxFuncCall::BigIntFromLeBytes &obj, Serializer &serializer) { +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); @@ -2875,15 +2867,15 @@ void serde::Serializable::serializ template <> template -Program::BlackBoxFuncCall::BigIntFromLeBytes serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BlackBoxFuncCall::BigIntFromLeBytes obj; +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 Program { +namespace Circuit { inline bool operator==(const BlackBoxFuncCall::BigIntToLeBytes &lhs, const BlackBoxFuncCall::BigIntToLeBytes &rhs) { if (!(lhs.input == rhs.input)) { return false; } @@ -2906,25 +2898,25 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BlackBoxFuncCall::BigIntToLeBytes &obj, Serializer &serializer) { +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 -Program::BlackBoxFuncCall::BigIntToLeBytes serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BlackBoxFuncCall::BigIntToLeBytes obj; +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 Program { +namespace Circuit { inline bool operator==(const BlackBoxFuncCall::Poseidon2Permutation &lhs, const BlackBoxFuncCall::Poseidon2Permutation &rhs) { if (!(lhs.inputs == rhs.inputs)) { return false; } @@ -2948,11 +2940,11 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BlackBoxFuncCall::Poseidon2Permutation &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::Poseidon2Permutation &obj, Serializer &serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.outputs, serializer); serde::Serializable::serialize(obj.len, serializer); @@ -2960,15 +2952,15 @@ void serde::Serializable::seria template <> template -Program::BlackBoxFuncCall::Poseidon2Permutation serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BlackBoxFuncCall::Poseidon2Permutation obj; +Circuit::BlackBoxFuncCall::Poseidon2Permutation serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BlackBoxFuncCall::Poseidon2Permutation obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); obj.len = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BlackBoxFuncCall::Sha256Compression &lhs, const BlackBoxFuncCall::Sha256Compression &rhs) { if (!(lhs.inputs == rhs.inputs)) { return false; } @@ -2992,11 +2984,11 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BlackBoxFuncCall::Sha256Compression &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::Sha256Compression &obj, Serializer &serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.hash_values, serializer); serde::Serializable::serialize(obj.outputs, serializer); @@ -3004,15 +2996,15 @@ void serde::Serializable::serializ template <> template -Program::BlackBoxFuncCall::Sha256Compression serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BlackBoxFuncCall::Sha256Compression obj; +Circuit::BlackBoxFuncCall::Sha256Compression serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BlackBoxFuncCall::Sha256Compression obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.hash_values = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BlackBoxOp &lhs, const BlackBoxOp &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -3034,11 +3026,11 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BlackBoxOp &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BlackBoxOp &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -3046,15 +3038,15 @@ void serde::Serializable::serialize(const Program::BlackBox template <> template -Program::BlackBoxOp serde::Deserializable::deserialize(Deserializer &deserializer) { +Circuit::BlackBoxOp serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Program::BlackBoxOp obj; + Circuit::BlackBoxOp obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BlackBoxOp::Sha256 &lhs, const BlackBoxOp::Sha256 &rhs) { if (!(lhs.message == rhs.message)) { return false; } @@ -3077,25 +3069,25 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BlackBoxOp::Sha256 &obj, Serializer &serializer) { +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 -Program::BlackBoxOp::Sha256 serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BlackBoxOp::Sha256 obj; +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 Program { +namespace Circuit { inline bool operator==(const BlackBoxOp::Blake2s &lhs, const BlackBoxOp::Blake2s &rhs) { if (!(lhs.message == rhs.message)) { return false; } @@ -3118,25 +3110,25 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BlackBoxOp::Blake2s &obj, Serializer &serializer) { +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 -Program::BlackBoxOp::Blake2s serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BlackBoxOp::Blake2s obj; +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 Program { +namespace Circuit { inline bool operator==(const BlackBoxOp::Blake3 &lhs, const BlackBoxOp::Blake3 &rhs) { if (!(lhs.message == rhs.message)) { return false; } @@ -3159,25 +3151,25 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BlackBoxOp::Blake3 &obj, Serializer &serializer) { +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 -Program::BlackBoxOp::Blake3 serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BlackBoxOp::Blake3 obj; +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 Program { +namespace Circuit { inline bool operator==(const BlackBoxOp::Keccak256 &lhs, const BlackBoxOp::Keccak256 &rhs) { if (!(lhs.message == rhs.message)) { return false; } @@ -3200,25 +3192,25 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BlackBoxOp::Keccak256 &obj, Serializer &serializer) { +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 -Program::BlackBoxOp::Keccak256 serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BlackBoxOp::Keccak256 obj; +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 Program { +namespace Circuit { inline bool operator==(const BlackBoxOp::Keccakf1600 &lhs, const BlackBoxOp::Keccakf1600 &rhs) { if (!(lhs.message == rhs.message)) { return false; } @@ -3241,25 +3233,25 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BlackBoxOp::Keccakf1600 &obj, Serializer &serializer) { +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 -Program::BlackBoxOp::Keccakf1600 serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BlackBoxOp::Keccakf1600 obj; +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 Program { +namespace Circuit { inline bool operator==(const BlackBoxOp::EcdsaSecp256k1 &lhs, const BlackBoxOp::EcdsaSecp256k1 &rhs) { if (!(lhs.hashed_msg == rhs.hashed_msg)) { return false; } @@ -3285,11 +3277,11 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BlackBoxOp::EcdsaSecp256k1 &obj, Serializer &serializer) { +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); @@ -3299,8 +3291,8 @@ void serde::Serializable::serialize(const P template <> template -Program::BlackBoxOp::EcdsaSecp256k1 serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BlackBoxOp::EcdsaSecp256k1 obj; +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); @@ -3309,7 +3301,7 @@ Program::BlackBoxOp::EcdsaSecp256k1 serde::Deserializable template -void serde::Serializable::serialize(const Program::BlackBoxOp::EcdsaSecp256r1 &obj, Serializer &serializer) { +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); @@ -3349,8 +3341,8 @@ void serde::Serializable::serialize(const P template <> template -Program::BlackBoxOp::EcdsaSecp256r1 serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BlackBoxOp::EcdsaSecp256r1 obj; +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); @@ -3359,7 +3351,7 @@ Program::BlackBoxOp::EcdsaSecp256r1 serde::Deserializable template -void serde::Serializable::serialize(const Program::BlackBoxOp::SchnorrVerify &obj, Serializer &serializer) { +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); @@ -3399,8 +3391,8 @@ void serde::Serializable::serialize(const Pr template <> template -Program::BlackBoxOp::SchnorrVerify serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BlackBoxOp::SchnorrVerify obj; +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); @@ -3409,7 +3401,7 @@ Program::BlackBoxOp::SchnorrVerify serde::Deserializable template -void serde::Serializable::serialize(const Program::BlackBoxOp::PedersenCommitment &obj, Serializer &serializer) { +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); @@ -3445,15 +3437,15 @@ void serde::Serializable::serialize(con template <> template -Program::BlackBoxOp::PedersenCommitment serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BlackBoxOp::PedersenCommitment obj; +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 Program { +namespace Circuit { inline bool operator==(const BlackBoxOp::PedersenHash &lhs, const BlackBoxOp::PedersenHash &rhs) { if (!(lhs.inputs == rhs.inputs)) { return false; } @@ -3477,11 +3469,11 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BlackBoxOp::PedersenHash &obj, Serializer &serializer) { +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); @@ -3489,15 +3481,15 @@ void serde::Serializable::serialize(const Pro template <> template -Program::BlackBoxOp::PedersenHash serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BlackBoxOp::PedersenHash obj; +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 Program { +namespace Circuit { inline bool operator==(const BlackBoxOp::FixedBaseScalarMul &lhs, const BlackBoxOp::FixedBaseScalarMul &rhs) { if (!(lhs.low == rhs.low)) { return false; } @@ -3521,11 +3513,11 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BlackBoxOp::FixedBaseScalarMul &obj, Serializer &serializer) { +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); @@ -3533,15 +3525,15 @@ void serde::Serializable::serialize(con template <> template -Program::BlackBoxOp::FixedBaseScalarMul serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BlackBoxOp::FixedBaseScalarMul obj; +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 Program { +namespace Circuit { inline bool operator==(const BlackBoxOp::EmbeddedCurveAdd &lhs, const BlackBoxOp::EmbeddedCurveAdd &rhs) { if (!(lhs.input1_x == rhs.input1_x)) { return false; } @@ -3567,11 +3559,11 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BlackBoxOp::EmbeddedCurveAdd &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BlackBoxOp::EmbeddedCurveAdd &obj, Serializer &serializer) { serde::Serializable::serialize(obj.input1_x, serializer); serde::Serializable::serialize(obj.input1_y, serializer); serde::Serializable::serialize(obj.input2_x, serializer); @@ -3581,8 +3573,8 @@ void serde::Serializable::serialize(const template <> template -Program::BlackBoxOp::EmbeddedCurveAdd serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BlackBoxOp::EmbeddedCurveAdd obj; +Circuit::BlackBoxOp::EmbeddedCurveAdd 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); @@ -3591,7 +3583,7 @@ Program::BlackBoxOp::EmbeddedCurveAdd serde::Deserializable template -void serde::Serializable::serialize(const Program::BlackBoxOp::BigIntAdd &obj, Serializer &serializer) { +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); @@ -3627,15 +3619,15 @@ void serde::Serializable::serialize(const Progra template <> template -Program::BlackBoxOp::BigIntAdd serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BlackBoxOp::BigIntAdd obj; +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 Program { +namespace Circuit { inline bool operator==(const BlackBoxOp::BigIntSub &lhs, const BlackBoxOp::BigIntSub &rhs) { if (!(lhs.lhs == rhs.lhs)) { return false; } @@ -3659,11 +3651,11 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BlackBoxOp::BigIntSub &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BlackBoxOp::BigIntSub &obj, Serializer &serializer) { serde::Serializable::serialize(obj.lhs, serializer); serde::Serializable::serialize(obj.rhs, serializer); serde::Serializable::serialize(obj.output, serializer); @@ -3671,15 +3663,15 @@ void serde::Serializable::serialize(const Progra template <> template -Program::BlackBoxOp::BigIntSub serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BlackBoxOp::BigIntSub obj; +Circuit::BlackBoxOp::BigIntSub serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BlackBoxOp::BigIntSub obj; obj.lhs = serde::Deserializable::deserialize(deserializer); obj.rhs = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BlackBoxOp::BigIntMul &lhs, const BlackBoxOp::BigIntMul &rhs) { if (!(lhs.lhs == rhs.lhs)) { return false; } @@ -3703,11 +3695,11 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BlackBoxOp::BigIntMul &obj, Serializer &serializer) { +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); @@ -3715,15 +3707,15 @@ void serde::Serializable::serialize(const Progra template <> template -Program::BlackBoxOp::BigIntMul serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BlackBoxOp::BigIntMul obj; +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 Program { +namespace Circuit { inline bool operator==(const BlackBoxOp::BigIntDiv &lhs, const BlackBoxOp::BigIntDiv &rhs) { if (!(lhs.lhs == rhs.lhs)) { return false; } @@ -3747,11 +3739,11 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BlackBoxOp::BigIntDiv &obj, Serializer &serializer) { +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); @@ -3759,15 +3751,15 @@ void serde::Serializable::serialize(const Progra template <> template -Program::BlackBoxOp::BigIntDiv serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BlackBoxOp::BigIntDiv obj; +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 Program { +namespace Circuit { inline bool operator==(const BlackBoxOp::BigIntFromLeBytes &lhs, const BlackBoxOp::BigIntFromLeBytes &rhs) { if (!(lhs.inputs == rhs.inputs)) { return false; } @@ -3791,11 +3783,11 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BlackBoxOp::BigIntFromLeBytes &obj, Serializer &serializer) { +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); @@ -3803,15 +3795,15 @@ void serde::Serializable::serialize(cons template <> template -Program::BlackBoxOp::BigIntFromLeBytes serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BlackBoxOp::BigIntFromLeBytes obj; +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 Program { +namespace Circuit { inline bool operator==(const BlackBoxOp::BigIntToLeBytes &lhs, const BlackBoxOp::BigIntToLeBytes &rhs) { if (!(lhs.input == rhs.input)) { return false; } @@ -3834,25 +3826,25 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BlackBoxOp::BigIntToLeBytes &obj, Serializer &serializer) { +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 -Program::BlackBoxOp::BigIntToLeBytes serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BlackBoxOp::BigIntToLeBytes obj; +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 Program { +namespace Circuit { inline bool operator==(const BlackBoxOp::Poseidon2Permutation &lhs, const BlackBoxOp::Poseidon2Permutation &rhs) { if (!(lhs.message == rhs.message)) { return false; } @@ -3876,11 +3868,11 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BlackBoxOp::Poseidon2Permutation &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BlackBoxOp::Poseidon2Permutation &obj, Serializer &serializer) { serde::Serializable::serialize(obj.message, serializer); serde::Serializable::serialize(obj.output, serializer); serde::Serializable::serialize(obj.len, serializer); @@ -3888,15 +3880,15 @@ void serde::Serializable::serialize(c template <> template -Program::BlackBoxOp::Poseidon2Permutation serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BlackBoxOp::Poseidon2Permutation obj; +Circuit::BlackBoxOp::Poseidon2Permutation serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BlackBoxOp::Poseidon2Permutation obj; obj.message = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); obj.len = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BlackBoxOp::Sha256Compression &lhs, const BlackBoxOp::Sha256Compression &rhs) { if (!(lhs.input == rhs.input)) { return false; } @@ -3920,11 +3912,11 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BlackBoxOp::Sha256Compression &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BlackBoxOp::Sha256Compression &obj, Serializer &serializer) { serde::Serializable::serialize(obj.input, serializer); serde::Serializable::serialize(obj.hash_values, serializer); serde::Serializable::serialize(obj.output, serializer); @@ -3932,15 +3924,15 @@ void serde::Serializable::serialize(cons template <> template -Program::BlackBoxOp::Sha256Compression serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BlackBoxOp::Sha256Compression obj; +Circuit::BlackBoxOp::Sha256Compression serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BlackBoxOp::Sha256Compression obj; obj.input = serde::Deserializable::deserialize(deserializer); obj.hash_values = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BlockId &lhs, const BlockId &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -3962,11 +3954,11 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BlockId &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BlockId &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -3974,15 +3966,15 @@ void serde::Serializable::serialize(const Program::BlockId &ob template <> template -Program::BlockId serde::Deserializable::deserialize(Deserializer &deserializer) { +Circuit::BlockId serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Program::BlockId obj; + Circuit::BlockId obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const Brillig &lhs, const Brillig &rhs) { if (!(lhs.inputs == rhs.inputs)) { return false; } @@ -4007,11 +3999,11 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::Brillig &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::Brillig &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.outputs, serializer); @@ -4022,9 +4014,9 @@ void serde::Serializable::serialize(const Program::Brillig &ob template <> template -Program::Brillig serde::Deserializable::deserialize(Deserializer &deserializer) { +Circuit::Brillig serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Program::Brillig obj; + Circuit::Brillig obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); obj.bytecode = serde::Deserializable::deserialize(deserializer); @@ -4033,7 +4025,7 @@ Program::Brillig serde::Deserializable::deserialize(Deserializ return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BrilligInputs &lhs, const BrilligInputs &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -4055,11 +4047,11 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BrilligInputs &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BrilligInputs &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -4067,15 +4059,15 @@ void serde::Serializable::serialize(const Program::Brill template <> template -Program::BrilligInputs serde::Deserializable::deserialize(Deserializer &deserializer) { +Circuit::BrilligInputs serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Program::BrilligInputs obj; + Circuit::BrilligInputs obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BrilligInputs::Single &lhs, const BrilligInputs::Single &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -4097,23 +4089,23 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BrilligInputs::Single &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BrilligInputs::Single &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value, serializer); } template <> template -Program::BrilligInputs::Single serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BrilligInputs::Single obj; +Circuit::BrilligInputs::Single serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BrilligInputs::Single obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BrilligInputs::Array &lhs, const BrilligInputs::Array &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -4135,23 +4127,23 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BrilligInputs::Array &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BrilligInputs::Array &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value, serializer); } template <> template -Program::BrilligInputs::Array serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BrilligInputs::Array obj; +Circuit::BrilligInputs::Array serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BrilligInputs::Array obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BrilligInputs::MemoryArray &lhs, const BrilligInputs::MemoryArray &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -4173,23 +4165,23 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BrilligInputs::MemoryArray &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BrilligInputs::MemoryArray &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value, serializer); } template <> template -Program::BrilligInputs::MemoryArray serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BrilligInputs::MemoryArray obj; +Circuit::BrilligInputs::MemoryArray serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BrilligInputs::MemoryArray obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BrilligOpcode &lhs, const BrilligOpcode &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -4211,11 +4203,11 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BrilligOpcode &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BrilligOpcode &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -4223,15 +4215,15 @@ void serde::Serializable::serialize(const Program::Brill template <> template -Program::BrilligOpcode serde::Deserializable::deserialize(Deserializer &deserializer) { +Circuit::BrilligOpcode serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Program::BrilligOpcode obj; + Circuit::BrilligOpcode obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BrilligOpcode::BinaryFieldOp &lhs, const BrilligOpcode::BinaryFieldOp &rhs) { if (!(lhs.destination == rhs.destination)) { return false; } @@ -4256,11 +4248,11 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BrilligOpcode::BinaryFieldOp &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BrilligOpcode::BinaryFieldOp &obj, Serializer &serializer) { serde::Serializable::serialize(obj.destination, serializer); serde::Serializable::serialize(obj.op, serializer); serde::Serializable::serialize(obj.lhs, serializer); @@ -4269,8 +4261,8 @@ void serde::Serializable::serialize(const template <> template -Program::BrilligOpcode::BinaryFieldOp serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BrilligOpcode::BinaryFieldOp obj; +Circuit::BrilligOpcode::BinaryFieldOp serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BrilligOpcode::BinaryFieldOp obj; obj.destination = serde::Deserializable::deserialize(deserializer); obj.op = serde::Deserializable::deserialize(deserializer); obj.lhs = serde::Deserializable::deserialize(deserializer); @@ -4278,7 +4270,7 @@ Program::BrilligOpcode::BinaryFieldOp serde::Deserializable template -void serde::Serializable::serialize(const Program::BrilligOpcode::BinaryIntOp &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BrilligOpcode::BinaryIntOp &obj, Serializer &serializer) { serde::Serializable::serialize(obj.destination, serializer); serde::Serializable::serialize(obj.op, serializer); serde::Serializable::serialize(obj.bit_size, serializer); @@ -4318,8 +4310,8 @@ void serde::Serializable::serialize(const P template <> template -Program::BrilligOpcode::BinaryIntOp serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BrilligOpcode::BinaryIntOp obj; +Circuit::BrilligOpcode::BinaryIntOp serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BrilligOpcode::BinaryIntOp obj; obj.destination = serde::Deserializable::deserialize(deserializer); obj.op = serde::Deserializable::deserialize(deserializer); obj.bit_size = serde::Deserializable::deserialize(deserializer); @@ -4328,7 +4320,7 @@ Program::BrilligOpcode::BinaryIntOp serde::Deserializable template -void serde::Serializable::serialize(const Program::BrilligOpcode::Cast &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BrilligOpcode::Cast &obj, Serializer &serializer) { serde::Serializable::serialize(obj.destination, serializer); serde::Serializable::serialize(obj.source, serializer); serde::Serializable::serialize(obj.bit_size, serializer); @@ -4364,15 +4356,15 @@ void serde::Serializable::serialize(const Program: template <> template -Program::BrilligOpcode::Cast serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BrilligOpcode::Cast obj; +Circuit::BrilligOpcode::Cast serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BrilligOpcode::Cast obj; obj.destination = serde::Deserializable::deserialize(deserializer); obj.source = serde::Deserializable::deserialize(deserializer); obj.bit_size = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BrilligOpcode::JumpIfNot &lhs, const BrilligOpcode::JumpIfNot &rhs) { if (!(lhs.condition == rhs.condition)) { return false; } @@ -4395,25 +4387,25 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BrilligOpcode::JumpIfNot &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BrilligOpcode::JumpIfNot &obj, Serializer &serializer) { serde::Serializable::serialize(obj.condition, serializer); serde::Serializable::serialize(obj.location, serializer); } template <> template -Program::BrilligOpcode::JumpIfNot serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BrilligOpcode::JumpIfNot obj; +Circuit::BrilligOpcode::JumpIfNot serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BrilligOpcode::JumpIfNot obj; obj.condition = serde::Deserializable::deserialize(deserializer); obj.location = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BrilligOpcode::JumpIf &lhs, const BrilligOpcode::JumpIf &rhs) { if (!(lhs.condition == rhs.condition)) { return false; } @@ -4436,25 +4428,25 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BrilligOpcode::JumpIf &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BrilligOpcode::JumpIf &obj, Serializer &serializer) { serde::Serializable::serialize(obj.condition, serializer); serde::Serializable::serialize(obj.location, serializer); } template <> template -Program::BrilligOpcode::JumpIf serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BrilligOpcode::JumpIf obj; +Circuit::BrilligOpcode::JumpIf serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BrilligOpcode::JumpIf obj; obj.condition = serde::Deserializable::deserialize(deserializer); obj.location = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BrilligOpcode::Jump &lhs, const BrilligOpcode::Jump &rhs) { if (!(lhs.location == rhs.location)) { return false; } @@ -4476,23 +4468,23 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BrilligOpcode::Jump &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BrilligOpcode::Jump &obj, Serializer &serializer) { serde::Serializable::serialize(obj.location, serializer); } template <> template -Program::BrilligOpcode::Jump serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BrilligOpcode::Jump obj; +Circuit::BrilligOpcode::Jump serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BrilligOpcode::Jump obj; obj.location = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BrilligOpcode::CalldataCopy &lhs, const BrilligOpcode::CalldataCopy &rhs) { if (!(lhs.destination_address == rhs.destination_address)) { return false; } @@ -4516,11 +4508,11 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BrilligOpcode::CalldataCopy &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BrilligOpcode::CalldataCopy &obj, Serializer &serializer) { serde::Serializable::serialize(obj.destination_address, serializer); serde::Serializable::serialize(obj.size, serializer); serde::Serializable::serialize(obj.offset, serializer); @@ -4528,15 +4520,15 @@ void serde::Serializable::serialize(const template <> template -Program::BrilligOpcode::CalldataCopy serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BrilligOpcode::CalldataCopy obj; +Circuit::BrilligOpcode::CalldataCopy serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BrilligOpcode::CalldataCopy obj; obj.destination_address = serde::Deserializable::deserialize(deserializer); obj.size = serde::Deserializable::deserialize(deserializer); obj.offset = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BrilligOpcode::Call &lhs, const BrilligOpcode::Call &rhs) { if (!(lhs.location == rhs.location)) { return false; } @@ -4558,23 +4550,23 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BrilligOpcode::Call &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BrilligOpcode::Call &obj, Serializer &serializer) { serde::Serializable::serialize(obj.location, serializer); } template <> template -Program::BrilligOpcode::Call serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BrilligOpcode::Call obj; +Circuit::BrilligOpcode::Call serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BrilligOpcode::Call obj; obj.location = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BrilligOpcode::Const &lhs, const BrilligOpcode::Const &rhs) { if (!(lhs.destination == rhs.destination)) { return false; } @@ -4598,11 +4590,11 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BrilligOpcode::Const &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BrilligOpcode::Const &obj, Serializer &serializer) { serde::Serializable::serialize(obj.destination, serializer); serde::Serializable::serialize(obj.bit_size, serializer); serde::Serializable::serialize(obj.value, serializer); @@ -4610,15 +4602,15 @@ void serde::Serializable::serialize(const Program template <> template -Program::BrilligOpcode::Const serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BrilligOpcode::Const obj; +Circuit::BrilligOpcode::Const serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BrilligOpcode::Const obj; obj.destination = serde::Deserializable::deserialize(deserializer); obj.bit_size = serde::Deserializable::deserialize(deserializer); obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BrilligOpcode::Return &lhs, const BrilligOpcode::Return &rhs) { return true; @@ -4639,21 +4631,21 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BrilligOpcode::Return &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BrilligOpcode::Return &obj, Serializer &serializer) { } template <> template -Program::BrilligOpcode::Return serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BrilligOpcode::Return obj; +Circuit::BrilligOpcode::Return serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BrilligOpcode::Return obj; return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BrilligOpcode::ForeignCall &lhs, const BrilligOpcode::ForeignCall &rhs) { if (!(lhs.function == rhs.function)) { return false; } @@ -4679,11 +4671,11 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BrilligOpcode::ForeignCall &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BrilligOpcode::ForeignCall &obj, Serializer &serializer) { serde::Serializable::serialize(obj.function, serializer); serde::Serializable::serialize(obj.destinations, serializer); serde::Serializable::serialize(obj.destination_value_types, serializer); @@ -4693,8 +4685,8 @@ void serde::Serializable::serialize(const P template <> template -Program::BrilligOpcode::ForeignCall serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BrilligOpcode::ForeignCall obj; +Circuit::BrilligOpcode::ForeignCall serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BrilligOpcode::ForeignCall obj; obj.function = serde::Deserializable::deserialize(deserializer); obj.destinations = serde::Deserializable::deserialize(deserializer); obj.destination_value_types = serde::Deserializable::deserialize(deserializer); @@ -4703,7 +4695,7 @@ Program::BrilligOpcode::ForeignCall serde::Deserializable template -void serde::Serializable::serialize(const Program::BrilligOpcode::Mov &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BrilligOpcode::Mov &obj, Serializer &serializer) { serde::Serializable::serialize(obj.destination, serializer); serde::Serializable::serialize(obj.source, serializer); } template <> template -Program::BrilligOpcode::Mov serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BrilligOpcode::Mov obj; +Circuit::BrilligOpcode::Mov serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BrilligOpcode::Mov obj; obj.destination = serde::Deserializable::deserialize(deserializer); obj.source = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BrilligOpcode::Load &lhs, const BrilligOpcode::Load &rhs) { if (!(lhs.destination == rhs.destination)) { return false; } @@ -4767,25 +4759,25 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BrilligOpcode::Load &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BrilligOpcode::Load &obj, Serializer &serializer) { serde::Serializable::serialize(obj.destination, serializer); serde::Serializable::serialize(obj.source_pointer, serializer); } template <> template -Program::BrilligOpcode::Load serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BrilligOpcode::Load obj; +Circuit::BrilligOpcode::Load serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BrilligOpcode::Load obj; obj.destination = serde::Deserializable::deserialize(deserializer); obj.source_pointer = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BrilligOpcode::Store &lhs, const BrilligOpcode::Store &rhs) { if (!(lhs.destination_pointer == rhs.destination_pointer)) { return false; } @@ -4808,25 +4800,25 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BrilligOpcode::Store &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BrilligOpcode::Store &obj, Serializer &serializer) { serde::Serializable::serialize(obj.destination_pointer, serializer); serde::Serializable::serialize(obj.source, serializer); } template <> template -Program::BrilligOpcode::Store serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BrilligOpcode::Store obj; +Circuit::BrilligOpcode::Store serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BrilligOpcode::Store obj; obj.destination_pointer = serde::Deserializable::deserialize(deserializer); obj.source = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BrilligOpcode::BlackBox &lhs, const BrilligOpcode::BlackBox &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -4848,23 +4840,23 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BrilligOpcode::BlackBox &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BrilligOpcode::BlackBox &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value, serializer); } template <> template -Program::BrilligOpcode::BlackBox serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BrilligOpcode::BlackBox obj; +Circuit::BrilligOpcode::BlackBox serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BrilligOpcode::BlackBox obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BrilligOpcode::Trap &lhs, const BrilligOpcode::Trap &rhs) { return true; @@ -4885,21 +4877,21 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BrilligOpcode::Trap &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BrilligOpcode::Trap &obj, Serializer &serializer) { } template <> template -Program::BrilligOpcode::Trap serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BrilligOpcode::Trap obj; +Circuit::BrilligOpcode::Trap serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BrilligOpcode::Trap obj; return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BrilligOpcode::Stop &lhs, const BrilligOpcode::Stop &rhs) { if (!(lhs.return_data_offset == rhs.return_data_offset)) { return false; } @@ -4922,25 +4914,25 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BrilligOpcode::Stop &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BrilligOpcode::Stop &obj, Serializer &serializer) { serde::Serializable::serialize(obj.return_data_offset, serializer); serde::Serializable::serialize(obj.return_data_size, serializer); } template <> template -Program::BrilligOpcode::Stop serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BrilligOpcode::Stop obj; +Circuit::BrilligOpcode::Stop serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BrilligOpcode::Stop obj; obj.return_data_offset = serde::Deserializable::deserialize(deserializer); obj.return_data_size = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BrilligOutputs &lhs, const BrilligOutputs &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -4962,11 +4954,11 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BrilligOutputs &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BrilligOutputs &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -4974,15 +4966,15 @@ void serde::Serializable::serialize(const Program::Bril template <> template -Program::BrilligOutputs serde::Deserializable::deserialize(Deserializer &deserializer) { +Circuit::BrilligOutputs serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Program::BrilligOutputs obj; + Circuit::BrilligOutputs obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BrilligOutputs::Simple &lhs, const BrilligOutputs::Simple &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -5004,23 +4996,23 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BrilligOutputs::Simple &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BrilligOutputs::Simple &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value, serializer); } template <> template -Program::BrilligOutputs::Simple serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BrilligOutputs::Simple obj; +Circuit::BrilligOutputs::Simple serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BrilligOutputs::Simple obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const BrilligOutputs::Array &lhs, const BrilligOutputs::Array &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -5042,23 +5034,23 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::BrilligOutputs::Array &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::BrilligOutputs::Array &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value, serializer); } template <> template -Program::BrilligOutputs::Array serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::BrilligOutputs::Array obj; +Circuit::BrilligOutputs::Array serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::BrilligOutputs::Array obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const Circuit &lhs, const Circuit &rhs) { if (!(lhs.current_witness_index == rhs.current_witness_index)) { return false; } @@ -5087,11 +5079,11 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::Circuit &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::Circuit &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.current_witness_index, serializer); serde::Serializable::serialize(obj.opcodes, serializer); @@ -5106,9 +5098,9 @@ void serde::Serializable::serialize(const Program::Circuit &ob template <> template -Program::Circuit serde::Deserializable::deserialize(Deserializer &deserializer) { +Circuit::Circuit serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Program::Circuit obj; + Circuit::Circuit obj; obj.current_witness_index = serde::Deserializable::deserialize(deserializer); obj.opcodes = serde::Deserializable::deserialize(deserializer); obj.expression_width = serde::Deserializable::deserialize(deserializer); @@ -5121,7 +5113,7 @@ Program::Circuit serde::Deserializable::deserialize(Deserializ return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const Directive &lhs, const Directive &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -5143,11 +5135,11 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::Directive &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::Directive &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -5155,15 +5147,15 @@ void serde::Serializable::serialize(const Program::Directive template <> template -Program::Directive serde::Deserializable::deserialize(Deserializer &deserializer) { +Circuit::Directive serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Program::Directive obj; + Circuit::Directive obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const Directive::ToLeRadix &lhs, const Directive::ToLeRadix &rhs) { if (!(lhs.a == rhs.a)) { return false; } @@ -5187,11 +5179,11 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::Directive::ToLeRadix &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::Directive::ToLeRadix &obj, Serializer &serializer) { serde::Serializable::serialize(obj.a, serializer); serde::Serializable::serialize(obj.b, serializer); serde::Serializable::serialize(obj.radix, serializer); @@ -5199,15 +5191,15 @@ void serde::Serializable::serialize(const Program template <> template -Program::Directive::ToLeRadix serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::Directive::ToLeRadix obj; +Circuit::Directive::ToLeRadix serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::Directive::ToLeRadix obj; obj.a = serde::Deserializable::deserialize(deserializer); obj.b = serde::Deserializable::deserialize(deserializer); obj.radix = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const Expression &lhs, const Expression &rhs) { if (!(lhs.mul_terms == rhs.mul_terms)) { return false; } @@ -5231,11 +5223,11 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::Expression &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::Expression &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.mul_terms, serializer); serde::Serializable::serialize(obj.linear_combinations, serializer); @@ -5245,9 +5237,9 @@ void serde::Serializable::serialize(const Program::Expressi template <> template -Program::Expression serde::Deserializable::deserialize(Deserializer &deserializer) { +Circuit::Expression serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Program::Expression obj; + Circuit::Expression obj; obj.mul_terms = serde::Deserializable::deserialize(deserializer); obj.linear_combinations = serde::Deserializable::deserialize(deserializer); obj.q_c = serde::Deserializable::deserialize(deserializer); @@ -5255,7 +5247,7 @@ Program::Expression serde::Deserializable::deserialize(Dese return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const ExpressionWidth &lhs, const ExpressionWidth &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -5277,11 +5269,11 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::ExpressionWidth &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::ExpressionWidth &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -5289,15 +5281,15 @@ void serde::Serializable::serialize(const Program::Exp template <> template -Program::ExpressionWidth serde::Deserializable::deserialize(Deserializer &deserializer) { +Circuit::ExpressionWidth serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Program::ExpressionWidth obj; + Circuit::ExpressionWidth obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const ExpressionWidth::Unbounded &lhs, const ExpressionWidth::Unbounded &rhs) { return true; @@ -5318,21 +5310,21 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::ExpressionWidth::Unbounded &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::ExpressionWidth::Unbounded &obj, Serializer &serializer) { } template <> template -Program::ExpressionWidth::Unbounded serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::ExpressionWidth::Unbounded obj; +Circuit::ExpressionWidth::Unbounded serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::ExpressionWidth::Unbounded obj; return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const ExpressionWidth::Bounded &lhs, const ExpressionWidth::Bounded &rhs) { if (!(lhs.width == rhs.width)) { return false; } @@ -5354,23 +5346,23 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::ExpressionWidth::Bounded &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::ExpressionWidth::Bounded &obj, Serializer &serializer) { serde::Serializable::serialize(obj.width, serializer); } template <> template -Program::ExpressionWidth::Bounded serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::ExpressionWidth::Bounded obj; +Circuit::ExpressionWidth::Bounded serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::ExpressionWidth::Bounded obj; obj.width = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const FunctionInput &lhs, const FunctionInput &rhs) { if (!(lhs.witness == rhs.witness)) { return false; } @@ -5393,11 +5385,11 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::FunctionInput &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::FunctionInput &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.witness, serializer); serde::Serializable::serialize(obj.num_bits, serializer); @@ -5406,16 +5398,16 @@ void serde::Serializable::serialize(const Program::Funct template <> template -Program::FunctionInput serde::Deserializable::deserialize(Deserializer &deserializer) { +Circuit::FunctionInput serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Program::FunctionInput obj; + Circuit::FunctionInput obj; obj.witness = serde::Deserializable::deserialize(deserializer); obj.num_bits = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const HeapArray &lhs, const HeapArray &rhs) { if (!(lhs.pointer == rhs.pointer)) { return false; } @@ -5438,11 +5430,11 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::HeapArray &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::HeapArray &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.pointer, serializer); serde::Serializable::serialize(obj.size, serializer); @@ -5451,16 +5443,16 @@ void serde::Serializable::serialize(const Program::HeapArray template <> template -Program::HeapArray serde::Deserializable::deserialize(Deserializer &deserializer) { +Circuit::HeapArray serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Program::HeapArray obj; + Circuit::HeapArray obj; obj.pointer = serde::Deserializable::deserialize(deserializer); obj.size = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const HeapValueType &lhs, const HeapValueType &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -5482,11 +5474,11 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::HeapValueType &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::HeapValueType &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -5494,15 +5486,15 @@ void serde::Serializable::serialize(const Program::HeapV template <> template -Program::HeapValueType serde::Deserializable::deserialize(Deserializer &deserializer) { +Circuit::HeapValueType serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Program::HeapValueType obj; + Circuit::HeapValueType obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const HeapValueType::Simple &lhs, const HeapValueType::Simple &rhs) { return true; @@ -5523,21 +5515,21 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::HeapValueType::Simple &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::HeapValueType::Simple &obj, Serializer &serializer) { } template <> template -Program::HeapValueType::Simple serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::HeapValueType::Simple obj; +Circuit::HeapValueType::Simple serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::HeapValueType::Simple obj; return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const HeapValueType::Array &lhs, const HeapValueType::Array &rhs) { if (!(lhs.value_types == rhs.value_types)) { return false; } @@ -5560,25 +5552,25 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::HeapValueType::Array &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::HeapValueType::Array &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value_types, serializer); serde::Serializable::serialize(obj.size, serializer); } template <> template -Program::HeapValueType::Array serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::HeapValueType::Array obj; +Circuit::HeapValueType::Array serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::HeapValueType::Array obj; obj.value_types = serde::Deserializable::deserialize(deserializer); obj.size = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const HeapValueType::Vector &lhs, const HeapValueType::Vector &rhs) { if (!(lhs.value_types == rhs.value_types)) { return false; } @@ -5600,23 +5592,23 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::HeapValueType::Vector &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::HeapValueType::Vector &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value_types, serializer); } template <> template -Program::HeapValueType::Vector serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::HeapValueType::Vector obj; +Circuit::HeapValueType::Vector serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::HeapValueType::Vector obj; obj.value_types = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const HeapVector &lhs, const HeapVector &rhs) { if (!(lhs.pointer == rhs.pointer)) { return false; } @@ -5639,11 +5631,11 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::HeapVector &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::HeapVector &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.pointer, serializer); serde::Serializable::serialize(obj.size, serializer); @@ -5652,16 +5644,16 @@ void serde::Serializable::serialize(const Program::HeapVect template <> template -Program::HeapVector serde::Deserializable::deserialize(Deserializer &deserializer) { +Circuit::HeapVector serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Program::HeapVector obj; + Circuit::HeapVector obj; obj.pointer = serde::Deserializable::deserialize(deserializer); obj.size = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const MemOp &lhs, const MemOp &rhs) { if (!(lhs.operation == rhs.operation)) { return false; } @@ -5685,11 +5677,11 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::MemOp &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::MemOp &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.operation, serializer); serde::Serializable::serialize(obj.index, serializer); @@ -5699,9 +5691,9 @@ void serde::Serializable::serialize(const Program::MemOp &obj, S template <> template -Program::MemOp serde::Deserializable::deserialize(Deserializer &deserializer) { +Circuit::MemOp serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Program::MemOp obj; + Circuit::MemOp obj; obj.operation = serde::Deserializable::deserialize(deserializer); obj.index = serde::Deserializable::deserialize(deserializer); obj.value = serde::Deserializable::deserialize(deserializer); @@ -5709,7 +5701,7 @@ Program::MemOp serde::Deserializable::deserialize(Deserializer & return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const MemoryAddress &lhs, const MemoryAddress &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -5731,11 +5723,11 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::MemoryAddress &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::MemoryAddress &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -5743,15 +5735,15 @@ void serde::Serializable::serialize(const Program::Memor template <> template -Program::MemoryAddress serde::Deserializable::deserialize(Deserializer &deserializer) { +Circuit::MemoryAddress serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Program::MemoryAddress obj; + Circuit::MemoryAddress obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const Opcode &lhs, const Opcode &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -5773,11 +5765,11 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::Opcode &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::Opcode &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -5785,15 +5777,15 @@ void serde::Serializable::serialize(const Program::Opcode &obj, template <> template -Program::Opcode serde::Deserializable::deserialize(Deserializer &deserializer) { +Circuit::Opcode serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Program::Opcode obj; + Circuit::Opcode obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const Opcode::AssertZero &lhs, const Opcode::AssertZero &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -5815,23 +5807,23 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::Opcode::AssertZero &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::Opcode::AssertZero &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value, serializer); } template <> template -Program::Opcode::AssertZero serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::Opcode::AssertZero obj; +Circuit::Opcode::AssertZero serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::Opcode::AssertZero obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const Opcode::BlackBoxFuncCall &lhs, const Opcode::BlackBoxFuncCall &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -5853,23 +5845,23 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::Opcode::BlackBoxFuncCall &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::Opcode::BlackBoxFuncCall &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value, serializer); } template <> template -Program::Opcode::BlackBoxFuncCall serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::Opcode::BlackBoxFuncCall obj; +Circuit::Opcode::BlackBoxFuncCall serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::Opcode::BlackBoxFuncCall obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const Opcode::Directive &lhs, const Opcode::Directive &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -5891,23 +5883,23 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::Opcode::Directive &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::Opcode::Directive &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value, serializer); } template <> template -Program::Opcode::Directive serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::Opcode::Directive obj; +Circuit::Opcode::Directive serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::Opcode::Directive obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const Opcode::Brillig &lhs, const Opcode::Brillig &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -5929,23 +5921,23 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::Opcode::Brillig &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::Opcode::Brillig &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value, serializer); } template <> template -Program::Opcode::Brillig serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::Opcode::Brillig obj; +Circuit::Opcode::Brillig serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::Opcode::Brillig obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const Opcode::MemoryOp &lhs, const Opcode::MemoryOp &rhs) { if (!(lhs.block_id == rhs.block_id)) { return false; } @@ -5969,11 +5961,11 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::Opcode::MemoryOp &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::Opcode::MemoryOp &obj, Serializer &serializer) { serde::Serializable::serialize(obj.block_id, serializer); serde::Serializable::serialize(obj.op, serializer); serde::Serializable::serialize(obj.predicate, serializer); @@ -5981,15 +5973,15 @@ void serde::Serializable::serialize(const Program::Op template <> template -Program::Opcode::MemoryOp serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::Opcode::MemoryOp obj; +Circuit::Opcode::MemoryOp serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::Opcode::MemoryOp obj; obj.block_id = serde::Deserializable::deserialize(deserializer); obj.op = serde::Deserializable::deserialize(deserializer); obj.predicate = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const Opcode::MemoryInit &lhs, const Opcode::MemoryInit &rhs) { if (!(lhs.block_id == rhs.block_id)) { return false; } @@ -6012,25 +6004,25 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::Opcode::MemoryInit &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::Opcode::MemoryInit &obj, Serializer &serializer) { serde::Serializable::serialize(obj.block_id, serializer); serde::Serializable::serialize(obj.init, serializer); } template <> template -Program::Opcode::MemoryInit serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::Opcode::MemoryInit obj; +Circuit::Opcode::MemoryInit serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::Opcode::MemoryInit obj; obj.block_id = serde::Deserializable::deserialize(deserializer); obj.init = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const Opcode::Call &lhs, const Opcode::Call &rhs) { if (!(lhs.id == rhs.id)) { return false; } @@ -6054,11 +6046,11 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::Opcode::Call &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::Opcode::Call &obj, Serializer &serializer) { serde::Serializable::serialize(obj.id, serializer); serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.outputs, serializer); @@ -6066,15 +6058,15 @@ void serde::Serializable::serialize(const Program::Opcode template <> template -Program::Opcode::Call serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::Opcode::Call obj; +Circuit::Opcode::Call serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::Opcode::Call obj; obj.id = serde::Deserializable::deserialize(deserializer); obj.inputs = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const OpcodeLocation &lhs, const OpcodeLocation &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -6096,11 +6088,11 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::OpcodeLocation &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::OpcodeLocation &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -6108,15 +6100,15 @@ void serde::Serializable::serialize(const Program::Opco template <> template -Program::OpcodeLocation serde::Deserializable::deserialize(Deserializer &deserializer) { +Circuit::OpcodeLocation serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Program::OpcodeLocation obj; + Circuit::OpcodeLocation obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const OpcodeLocation::Acir &lhs, const OpcodeLocation::Acir &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -6138,23 +6130,23 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::OpcodeLocation::Acir &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::OpcodeLocation::Acir &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value, serializer); } template <> template -Program::OpcodeLocation::Acir serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::OpcodeLocation::Acir obj; +Circuit::OpcodeLocation::Acir serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::OpcodeLocation::Acir obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const OpcodeLocation::Brillig &lhs, const OpcodeLocation::Brillig &rhs) { if (!(lhs.acir_index == rhs.acir_index)) { return false; } @@ -6177,67 +6169,25 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::OpcodeLocation::Brillig &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::OpcodeLocation::Brillig &obj, Serializer &serializer) { serde::Serializable::serialize(obj.acir_index, serializer); serde::Serializable::serialize(obj.brillig_index, serializer); } template <> template -Program::OpcodeLocation::Brillig serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::OpcodeLocation::Brillig obj; +Circuit::OpcodeLocation::Brillig serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::OpcodeLocation::Brillig obj; obj.acir_index = serde::Deserializable::deserialize(deserializer); obj.brillig_index = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { - - inline bool operator==(const Program &lhs, const Program &rhs) { - if (!(lhs.functions == rhs.functions)) { return false; } - return true; - } - - inline std::vector Program::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); - } - - inline Program Program::bincodeDeserialize(std::vector input) { - auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); - if (deserializer.get_buffer_offset() < input.size()) { - throw serde::deserialization_error("Some input bytes were not read"); - } - return value; - } - -} // end of namespace Program - -template <> -template -void serde::Serializable::serialize(const Program::Program &obj, Serializer &serializer) { - serializer.increase_container_depth(); - serde::Serializable::serialize(obj.functions, serializer); - serializer.decrease_container_depth(); -} - -template <> -template -Program::Program serde::Deserializable::deserialize(Deserializer &deserializer) { - deserializer.increase_container_depth(); - Program::Program obj; - obj.functions = serde::Deserializable::deserialize(deserializer); - deserializer.decrease_container_depth(); - return obj; -} - -namespace Program { +namespace Circuit { inline bool operator==(const PublicInputs &lhs, const PublicInputs &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -6259,11 +6209,11 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::PublicInputs &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::PublicInputs &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -6271,15 +6221,15 @@ void serde::Serializable::serialize(const Program::Public template <> template -Program::PublicInputs serde::Deserializable::deserialize(Deserializer &deserializer) { +Circuit::PublicInputs serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Program::PublicInputs obj; + Circuit::PublicInputs obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const Value &lhs, const Value &rhs) { if (!(lhs.inner == rhs.inner)) { return false; } @@ -6301,11 +6251,11 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::Value &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::Value &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.inner, serializer); serializer.decrease_container_depth(); @@ -6313,15 +6263,15 @@ void serde::Serializable::serialize(const Program::Value &obj, S template <> template -Program::Value serde::Deserializable::deserialize(Deserializer &deserializer) { +Circuit::Value serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Program::Value obj; + Circuit::Value obj; obj.inner = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const ValueOrArray &lhs, const ValueOrArray &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -6343,11 +6293,11 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::ValueOrArray &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::ValueOrArray &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -6355,15 +6305,15 @@ void serde::Serializable::serialize(const Program::ValueO template <> template -Program::ValueOrArray serde::Deserializable::deserialize(Deserializer &deserializer) { +Circuit::ValueOrArray serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Program::ValueOrArray obj; + Circuit::ValueOrArray obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const ValueOrArray::MemoryAddress &lhs, const ValueOrArray::MemoryAddress &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -6385,23 +6335,23 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::ValueOrArray::MemoryAddress &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::ValueOrArray::MemoryAddress &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value, serializer); } template <> template -Program::ValueOrArray::MemoryAddress serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::ValueOrArray::MemoryAddress obj; +Circuit::ValueOrArray::MemoryAddress serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::ValueOrArray::MemoryAddress obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const ValueOrArray::HeapArray &lhs, const ValueOrArray::HeapArray &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -6423,23 +6373,23 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::ValueOrArray::HeapArray &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::ValueOrArray::HeapArray &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value, serializer); } template <> template -Program::ValueOrArray::HeapArray serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::ValueOrArray::HeapArray obj; +Circuit::ValueOrArray::HeapArray serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::ValueOrArray::HeapArray obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const ValueOrArray::HeapVector &lhs, const ValueOrArray::HeapVector &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -6461,23 +6411,23 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::ValueOrArray::HeapVector &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::ValueOrArray::HeapVector &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value, serializer); } template <> template -Program::ValueOrArray::HeapVector serde::Deserializable::deserialize(Deserializer &deserializer) { - Program::ValueOrArray::HeapVector obj; +Circuit::ValueOrArray::HeapVector serde::Deserializable::deserialize(Deserializer &deserializer) { + Circuit::ValueOrArray::HeapVector obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Program { +namespace Circuit { inline bool operator==(const Witness &lhs, const Witness &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -6499,11 +6449,11 @@ namespace Program { return value; } -} // end of namespace Program +} // end of namespace Circuit template <> template -void serde::Serializable::serialize(const Program::Witness &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Circuit::Witness &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -6511,9 +6461,9 @@ void serde::Serializable::serialize(const Program::Witness &ob template <> template -Program::Witness serde::Deserializable::deserialize(Deserializer &deserializer) { +Circuit::Witness serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Program::Witness obj; + Circuit::Witness obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; diff --git a/noir/noir-repo/acvm-repo/acir/codegen/witness.cpp b/noir/noir-repo/acvm-repo/acir/codegen/witness.cpp index ad2b0550db2e..118d4ca7ac5b 100644 --- a/noir/noir-repo/acvm-repo/acir/codegen/witness.cpp +++ b/noir/noir-repo/acvm-repo/acir/codegen/witness.cpp @@ -3,7 +3,7 @@ #include "serde.hpp" #include "bincode.hpp" -namespace WitnessStack { +namespace WitnessMap { struct Witness { uint32_t value; @@ -14,79 +14,17 @@ namespace WitnessStack { }; struct WitnessMap { - std::map value; + std::map value; friend bool operator==(const WitnessMap&, const WitnessMap&); std::vector bincodeSerialize() const; static WitnessMap bincodeDeserialize(std::vector); }; - struct StackItem { - uint32_t index; - WitnessStack::WitnessMap witness; +} // end of namespace WitnessMap - friend bool operator==(const StackItem&, const StackItem&); - std::vector bincodeSerialize() const; - static StackItem bincodeDeserialize(std::vector); - }; - - struct WitnessStack { - std::vector stack; - - friend bool operator==(const WitnessStack&, const WitnessStack&); - std::vector bincodeSerialize() const; - static WitnessStack bincodeDeserialize(std::vector); - }; - -} // end of namespace WitnessStack - - -namespace WitnessStack { - - inline bool operator==(const StackItem &lhs, const StackItem &rhs) { - if (!(lhs.index == rhs.index)) { return false; } - if (!(lhs.witness == rhs.witness)) { return false; } - return true; - } - - inline std::vector StackItem::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); - } - - inline StackItem StackItem::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 WitnessStack - -template <> -template -void serde::Serializable::serialize(const WitnessStack::StackItem &obj, Serializer &serializer) { - serializer.increase_container_depth(); - serde::Serializable::serialize(obj.index, serializer); - serde::Serializable::serialize(obj.witness, serializer); - serializer.decrease_container_depth(); -} - -template <> -template -WitnessStack::StackItem serde::Deserializable::deserialize(Deserializer &deserializer) { - deserializer.increase_container_depth(); - WitnessStack::StackItem obj; - obj.index = serde::Deserializable::deserialize(deserializer); - obj.witness = serde::Deserializable::deserialize(deserializer); - deserializer.decrease_container_depth(); - return obj; -} -namespace WitnessStack { +namespace WitnessMap { inline bool operator==(const Witness &lhs, const Witness &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -108,11 +46,11 @@ namespace WitnessStack { return value; } -} // end of namespace WitnessStack +} // end of namespace WitnessMap template <> template -void serde::Serializable::serialize(const WitnessStack::Witness &obj, Serializer &serializer) { +void serde::Serializable::serialize(const WitnessMap::Witness &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -120,15 +58,15 @@ void serde::Serializable::serialize(const WitnessStack::W template <> template -WitnessStack::Witness serde::Deserializable::deserialize(Deserializer &deserializer) { +WitnessMap::Witness serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - WitnessStack::Witness obj; + WitnessMap::Witness obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace WitnessStack { +namespace WitnessMap { inline bool operator==(const WitnessMap &lhs, const WitnessMap &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -150,11 +88,11 @@ namespace WitnessStack { return value; } -} // end of namespace WitnessStack +} // end of namespace WitnessMap template <> template -void serde::Serializable::serialize(const WitnessStack::WitnessMap &obj, Serializer &serializer) { +void serde::Serializable::serialize(const WitnessMap::WitnessMap &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -162,52 +100,10 @@ void serde::Serializable::serialize(const WitnessStack template <> template -WitnessStack::WitnessMap serde::Deserializable::deserialize(Deserializer &deserializer) { +WitnessMap::WitnessMap serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - WitnessStack::WitnessMap obj; + WitnessMap::WitnessMap obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } - -namespace WitnessStack { - - inline bool operator==(const WitnessStack &lhs, const WitnessStack &rhs) { - if (!(lhs.stack == rhs.stack)) { return false; } - return true; - } - - inline std::vector WitnessStack::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); - } - - inline WitnessStack WitnessStack::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 WitnessStack - -template <> -template -void serde::Serializable::serialize(const WitnessStack::WitnessStack &obj, Serializer &serializer) { - serializer.increase_container_depth(); - serde::Serializable::serialize(obj.stack, serializer); - serializer.decrease_container_depth(); -} - -template <> -template -WitnessStack::WitnessStack serde::Deserializable::deserialize(Deserializer &deserializer) { - deserializer.increase_container_depth(); - WitnessStack::WitnessStack obj; - obj.stack = serde::Deserializable::deserialize(deserializer); - deserializer.decrease_container_depth(); - return obj; -} diff --git a/noir/noir-repo/acvm-repo/acir/src/circuit/mod.rs b/noir/noir-repo/acvm-repo/acir/src/circuit/mod.rs index 3d4d62969815..7e6cbf238039 100644 --- a/noir/noir-repo/acvm-repo/acir/src/circuit/mod.rs +++ b/noir/noir-repo/acvm-repo/acir/src/circuit/mod.rs @@ -32,13 +32,6 @@ pub enum ExpressionWidth { }, } -/// A program represented by multiple ACIR circuits. The execution trace of these -/// circuits is dictated by construction of the [crate::native_types::WitnessStack]. -#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Default)] -pub struct Program { - pub functions: Vec, -} - #[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Default)] pub struct Circuit { // current_witness_index is the highest witness index in the circuit. The next witness to be added to this circuit @@ -210,57 +203,6 @@ impl Circuit { } } -impl Program { - fn write(&self, writer: W) -> std::io::Result<()> { - let buf = bincode::serialize(self).unwrap(); - let mut encoder = flate2::write::GzEncoder::new(writer, Compression::default()); - encoder.write_all(&buf)?; - encoder.finish()?; - Ok(()) - } - - fn read(reader: R) -> std::io::Result { - let mut gz_decoder = flate2::read::GzDecoder::new(reader); - let mut buf_d = Vec::new(); - gz_decoder.read_to_end(&mut buf_d)?; - bincode::deserialize(&buf_d) - .map_err(|err| std::io::Error::new(std::io::ErrorKind::InvalidInput, err)) - } - - pub fn serialize_program(program: &Program) -> Vec { - let mut program_bytes: Vec = Vec::new(); - program.write(&mut program_bytes).expect("expected circuit to be serializable"); - program_bytes - } - - pub fn deserialize_program(serialized_circuit: &[u8]) -> std::io::Result { - Program::read(serialized_circuit) - } - - // Serialize and base64 encode program - pub fn serialize_program_base64(program: &Program, s: S) -> Result - where - S: Serializer, - { - let program_bytes = Program::serialize_program(program); - let encoded_b64 = base64::engine::general_purpose::STANDARD.encode(program_bytes); - s.serialize_str(&encoded_b64) - } - - // Deserialize and base64 decode program - pub fn deserialize_program_base64<'de, D>(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - let bytecode_b64: String = serde::Deserialize::deserialize(deserializer)?; - let program_bytes = base64::engine::general_purpose::STANDARD - .decode(bytecode_b64) - .map_err(D::Error::custom)?; - let circuit = Self::deserialize_program(&program_bytes).map_err(D::Error::custom)?; - Ok(circuit) - } -} - impl std::fmt::Display for Circuit { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { writeln!(f, "current witness index : {}", self.current_witness_index)?; @@ -298,22 +240,6 @@ impl std::fmt::Debug for Circuit { } } -impl std::fmt::Display for Program { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - for (func_index, function) in self.functions.iter().enumerate() { - writeln!(f, "func {}", func_index)?; - writeln!(f, "{}", function)?; - } - Ok(()) - } -} - -impl std::fmt::Debug for Program { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - std::fmt::Display::fmt(self, f) - } -} - #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Default)] pub struct PublicInputs(pub BTreeSet); diff --git a/noir/noir-repo/acvm-repo/acir/src/lib.rs b/noir/noir-repo/acvm-repo/acir/src/lib.rs index d14159f34a16..c7be50268502 100644 --- a/noir/noir-repo/acvm-repo/acir/src/lib.rs +++ b/noir/noir-repo/acvm-repo/acir/src/lib.rs @@ -42,9 +42,9 @@ mod reflection { brillig::{BrilligInputs, BrilligOutputs}, directives::Directive, opcodes::BlackBoxFuncCall, - Circuit, ExpressionWidth, Opcode, OpcodeLocation, Program, + Circuit, ExpressionWidth, Opcode, OpcodeLocation, }, - native_types::{Witness, WitnessMap, WitnessStack}, + native_types::{Witness, WitnessMap}, }; #[test] @@ -59,7 +59,6 @@ mod reflection { }; let mut tracer = Tracer::new(TracerConfig::default()); - tracer.trace_simple_type::().unwrap(); tracer.trace_simple_type::().unwrap(); tracer.trace_simple_type::().unwrap(); tracer.trace_simple_type::().unwrap(); @@ -79,7 +78,7 @@ mod reflection { // Create C++ class definitions. let mut source = Vec::new(); - let config = serde_generate::CodeGeneratorConfig::new("Program".to_string()) + let config = serde_generate::CodeGeneratorConfig::new("Circuit".to_string()) .with_encodings(vec![serde_generate::Encoding::Bincode]); let generator = serde_generate::cpp::CodeGenerator::new(&config); generator.output(&mut source, ®istry).unwrap(); @@ -107,13 +106,12 @@ mod reflection { let mut tracer = Tracer::new(TracerConfig::default()); tracer.trace_simple_type::().unwrap(); tracer.trace_simple_type::().unwrap(); - tracer.trace_simple_type::().unwrap(); let registry = tracer.registry().unwrap(); // Create C++ class definitions. let mut source = Vec::new(); - let config = serde_generate::CodeGeneratorConfig::new("WitnessStack".to_string()) + let config = serde_generate::CodeGeneratorConfig::new("WitnessMap".to_string()) .with_encodings(vec![serde_generate::Encoding::Bincode]); let generator = serde_generate::cpp::CodeGenerator::new(&config); generator.output(&mut source, ®istry).unwrap(); diff --git a/noir/noir-repo/acvm-repo/acir/src/native_types/mod.rs b/noir/noir-repo/acvm-repo/acir/src/native_types/mod.rs index eb9d1f6fd038..66c822bfff87 100644 --- a/noir/noir-repo/acvm-repo/acir/src/native_types/mod.rs +++ b/noir/noir-repo/acvm-repo/acir/src/native_types/mod.rs @@ -1,10 +1,8 @@ mod expression; mod witness; mod witness_map; -mod witness_stack; pub use expression::Expression; pub use witness::Witness; pub use witness_map::WitnessMap; -pub use witness_stack::WitnessStack; -pub use witness_stack::WitnessStackError; +pub use witness_map::WitnessMapError; diff --git a/noir/noir-repo/acvm-repo/acir/src/native_types/witness_stack.rs b/noir/noir-repo/acvm-repo/acir/src/native_types/witness_stack.rs deleted file mode 100644 index 9592d90b014b..000000000000 --- a/noir/noir-repo/acvm-repo/acir/src/native_types/witness_stack.rs +++ /dev/null @@ -1,64 +0,0 @@ -use std::io::Read; - -use flate2::bufread::GzDecoder; -use flate2::bufread::GzEncoder; -use flate2::Compression; -use serde::{Deserialize, Serialize}; -use thiserror::Error; - -use super::WitnessMap; - -#[derive(Debug, Error)] -enum SerializationError { - #[error(transparent)] - Deflate(#[from] std::io::Error), -} - -#[derive(Debug, Error)] -#[error(transparent)] -pub struct WitnessStackError(#[from] SerializationError); - -/// An ordered set of witness maps for separate circuits -#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Default, Serialize, Deserialize)] -pub struct WitnessStack { - pub stack: Vec, -} - -#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Default, Serialize, Deserialize)] -pub struct StackItem { - /// Index into a [crate::circuit::Program] function list for which we have an associated witness - pub index: u32, - /// A full witness for the respective constraint system specified by the index - pub witness: WitnessMap, -} - -impl From for WitnessStack { - fn from(witness: WitnessMap) -> Self { - let stack = vec![StackItem { index: 0, witness }]; - Self { stack } - } -} - -impl TryFrom for Vec { - type Error = WitnessStackError; - - fn try_from(val: WitnessStack) -> Result { - let buf = bincode::serialize(&val).unwrap(); - let mut deflater = GzEncoder::new(buf.as_slice(), Compression::best()); - let mut buf_c = Vec::new(); - deflater.read_to_end(&mut buf_c).map_err(|err| WitnessStackError(err.into()))?; - Ok(buf_c) - } -} - -impl TryFrom<&[u8]> for WitnessStack { - type Error = WitnessStackError; - - fn try_from(bytes: &[u8]) -> Result { - let mut deflater = GzDecoder::new(bytes); - let mut buf_d = Vec::new(); - deflater.read_to_end(&mut buf_d).map_err(|err| WitnessStackError(err.into()))?; - let witness_stack = bincode::deserialize(&buf_d).unwrap(); - Ok(witness_stack) - } -} diff --git a/noir/noir-repo/acvm-repo/acir/tests/test_program_serialization.rs b/noir/noir-repo/acvm-repo/acir/tests/test_program_serialization.rs index 238f51b1e280..2c8ad2b99868 100644 --- a/noir/noir-repo/acvm-repo/acir/tests/test_program_serialization.rs +++ b/noir/noir-repo/acvm-repo/acir/tests/test_program_serialization.rs @@ -1,13 +1,13 @@ //! This integration test defines a set of circuits which are used in order to test the acvm_js package. //! -//! The acvm_js test suite contains serialized program [circuits][`Program`] which must be kept in sync with the format +//! The acvm_js test suite contains serialized [circuits][`Circuit`] which must be kept in sync with the format //! outputted from the [ACIR crate][acir]. //! Breaking changes to the serialization format then require refreshing acvm_js's test suite. //! This file contains Rust definitions of these circuits and outputs the updated serialized format. //! //! These tests also check this circuit serialization against an expected value, erroring if the serialization changes. //! Generally in this situation we just need to refresh the `expected_serialization` variables to match the -//! actual output, **HOWEVER** note that this results in a breaking change to the backend ACIR format. +//! actual output, **HOWEVER** note that this results in a breaking change to the ACIR format. use std::collections::BTreeSet; @@ -15,7 +15,7 @@ use acir::{ circuit::{ brillig::{Brillig, BrilligInputs, BrilligOutputs}, opcodes::{BlackBoxFuncCall, BlockId, FunctionInput, MemOp}, - Circuit, Opcode, Program, PublicInputs, + Circuit, Opcode, PublicInputs, }, native_types::{Expression, Witness}, }; @@ -41,17 +41,16 @@ fn addition_circuit() { return_values: PublicInputs([Witness(3)].into()), ..Circuit::default() }; - let program = Program { functions: vec![circuit] }; - let bytes = Program::serialize_program(&program); + let bytes = Circuit::serialize_circuit(&circuit); let expected_serialization: Vec = vec![ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 144, 75, 14, 128, 32, 12, 68, 249, 120, 160, 150, - 182, 208, 238, 188, 138, 68, 184, 255, 17, 212, 200, 130, 196, 165, 188, 164, 153, 174, 94, - 38, 227, 221, 203, 118, 159, 119, 95, 226, 200, 125, 36, 252, 3, 253, 66, 87, 152, 92, 4, - 153, 185, 149, 212, 144, 240, 128, 100, 85, 5, 88, 106, 86, 84, 20, 149, 51, 41, 81, 83, - 214, 98, 213, 10, 24, 50, 53, 236, 98, 212, 135, 44, 174, 235, 5, 143, 35, 12, 151, 159, - 126, 55, 109, 28, 231, 145, 47, 245, 105, 191, 143, 133, 1, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 208, 49, 14, 192, 32, 8, 5, 80, 212, 30, 8, 4, 20, + 182, 94, 165, 166, 122, 255, 35, 52, 77, 28, 76, 58, 214, 191, 124, 166, 23, 242, 15, 0, 8, + 240, 77, 154, 125, 206, 198, 127, 161, 176, 209, 138, 139, 197, 88, 68, 122, 205, 157, 152, + 46, 204, 222, 76, 81, 180, 21, 35, 35, 53, 189, 179, 49, 119, 19, 171, 222, 188, 162, 147, + 112, 167, 161, 206, 99, 98, 105, 223, 95, 248, 26, 113, 90, 97, 185, 97, 217, 56, 173, 35, + 63, 243, 81, 87, 163, 125, 1, 0, 0, ]; assert_eq!(bytes, expected_serialization) @@ -72,14 +71,13 @@ fn fixed_base_scalar_mul_circuit() { return_values: PublicInputs(BTreeSet::from_iter(vec![Witness(3), Witness(4)])), ..Circuit::default() }; - let program = Program { functions: vec![circuit] }; - let bytes = Program::serialize_program(&program); + let bytes = Circuit::serialize_circuit(&circuit); let expected_serialization: Vec = vec![ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 77, 138, 81, 10, 0, 48, 8, 66, 87, 219, 190, 118, 233, - 29, 61, 43, 3, 5, 121, 34, 207, 86, 231, 162, 198, 157, 124, 228, 71, 157, 220, 232, 161, - 227, 226, 206, 214, 95, 221, 74, 0, 116, 58, 13, 182, 105, 0, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 77, 138, 91, 10, 0, 32, 16, 2, 109, 171, 175, 46, 221, + 209, 247, 229, 130, 130, 140, 200, 92, 0, 11, 157, 228, 35, 127, 212, 200, 29, 61, 116, 76, + 220, 217, 250, 171, 91, 113, 160, 66, 104, 242, 97, 0, 0, 0, ]; assert_eq!(bytes, expected_serialization) @@ -100,14 +98,13 @@ fn pedersen_circuit() { return_values: PublicInputs(BTreeSet::from_iter(vec![Witness(2), Witness(3)])), ..Circuit::default() }; - let program = Program { functions: vec![circuit] }; - let bytes = Program::serialize_program(&program); + let bytes = Circuit::serialize_circuit(&circuit); let expected_serialization: Vec = vec![ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 93, 74, 7, 6, 0, 0, 8, 108, 209, 255, 63, 156, 54, 233, - 56, 55, 17, 26, 18, 196, 241, 169, 250, 178, 141, 167, 32, 159, 254, 234, 238, 255, 87, - 112, 52, 63, 63, 101, 105, 0, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 93, 74, 135, 9, 0, 48, 8, 75, 171, 224, 255, 15, 139, + 27, 196, 64, 200, 100, 0, 15, 133, 80, 57, 89, 219, 127, 39, 173, 126, 235, 236, 247, 151, + 48, 224, 71, 90, 33, 97, 0, 0, 0, ]; assert_eq!(bytes, expected_serialization) @@ -142,27 +139,26 @@ fn schnorr_verify_circuit() { return_values: PublicInputs(BTreeSet::from([output])), ..Circuit::default() }; - let program = Program { functions: vec![circuit] }; - let bytes = Program::serialize_program(&program); + let bytes = Circuit::serialize_circuit(&circuit); let expected_serialization: Vec = vec![ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 77, 210, 7, 78, 2, 1, 20, 69, 81, 236, 189, 247, 222, - 123, 239, 93, 177, 33, 34, 238, 194, 253, 47, 193, 200, 147, 67, 194, 36, 147, 163, 33, 33, - 228, 191, 219, 82, 168, 63, 63, 181, 183, 197, 223, 177, 147, 191, 181, 183, 149, 69, 159, - 183, 213, 222, 238, 218, 219, 206, 14, 118, 178, 139, 141, 183, 135, 189, 236, 99, 63, 7, - 56, 200, 33, 14, 115, 132, 163, 28, 227, 56, 39, 56, 201, 41, 78, 115, 134, 179, 156, 227, - 60, 23, 184, 200, 37, 46, 115, 133, 171, 92, 227, 58, 55, 184, 201, 45, 110, 115, 135, 187, - 220, 227, 62, 15, 120, 200, 35, 30, 243, 132, 167, 60, 227, 57, 47, 120, 201, 43, 94, 243, - 134, 183, 188, 227, 61, 31, 248, 200, 39, 22, 249, 204, 151, 166, 29, 243, 188, 250, 255, - 141, 239, 44, 241, 131, 101, 126, 178, 194, 47, 86, 249, 237, 123, 171, 76, 127, 105, 47, - 189, 165, 181, 116, 150, 198, 26, 125, 245, 248, 45, 233, 41, 45, 165, 163, 52, 148, 126, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 77, 210, 7, 74, 3, 1, 20, 69, 209, 177, 247, 222, 123, + 239, 189, 119, 141, 93, 99, 220, 133, 251, 95, 130, 152, 103, 78, 32, 3, 195, 33, 4, 66, + 248, 239, 254, 20, 69, 209, 84, 212, 158, 216, 206, 223, 234, 219, 204, 146, 239, 91, 170, + 111, 103, 245, 109, 101, 27, 219, 217, 193, 250, 219, 197, 110, 246, 176, 151, 125, 236, + 231, 0, 7, 57, 196, 97, 142, 112, 148, 99, 28, 231, 4, 39, 57, 197, 105, 206, 112, 150, + 115, 156, 231, 2, 23, 185, 196, 101, 174, 112, 149, 107, 92, 231, 6, 55, 185, 197, 109, + 238, 112, 151, 123, 220, 231, 1, 15, 121, 196, 99, 158, 240, 148, 103, 60, 231, 5, 47, 121, + 197, 107, 222, 240, 150, 119, 188, 231, 3, 75, 124, 228, 83, 195, 142, 121, 158, 125, 126, + 225, 43, 223, 248, 206, 15, 126, 178, 204, 47, 86, 248, 237, 119, 43, 76, 127, 105, 47, + 189, 165, 181, 116, 150, 198, 234, 125, 117, 249, 47, 233, 41, 45, 165, 163, 52, 148, 126, 210, 78, 186, 73, 51, 233, 37, 173, 164, 147, 52, 146, 62, 210, 70, 186, 72, 19, 233, 33, - 45, 164, 131, 52, 144, 253, 151, 11, 245, 221, 179, 121, 246, 206, 214, 217, 57, 27, 103, - 223, 109, 187, 238, 218, 115, 223, 142, 135, 246, 59, 182, 219, 169, 189, 206, 237, 116, - 105, 159, 107, 187, 220, 218, 227, 222, 14, 143, 238, 95, 116, 247, 23, 119, 126, 115, 223, - 146, 187, 150, 221, 179, 226, 142, 141, 155, 53, 238, 86, 104, 186, 231, 255, 243, 7, 100, - 141, 232, 192, 233, 3, 0, 0, + 45, 164, 131, 52, 144, 253, 23, 139, 218, 238, 217, 60, 123, 103, 235, 236, 156, 141, 179, + 239, 166, 93, 183, 237, 185, 107, 199, 125, 251, 29, 218, 237, 216, 94, 167, 118, 58, 183, + 207, 165, 93, 174, 237, 113, 107, 135, 123, 247, 47, 185, 251, 147, 59, 191, 184, 239, 155, + 187, 126, 184, 103, 217, 29, 235, 55, 171, 223, 173, 104, 184, 231, 255, 243, 7, 236, 52, + 239, 128, 225, 3, 0, 0, ]; assert_eq!(bytes, expected_serialization) @@ -206,16 +202,15 @@ fn simple_brillig_foreign_call() { private_parameters: BTreeSet::from([Witness(1), Witness(2)]), ..Circuit::default() }; - let program = Program { functions: vec![circuit] }; - let bytes = Program::serialize_program(&program); + let bytes = Circuit::serialize_circuit(&circuit); let expected_serialization: Vec = vec![ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 143, 65, 10, 192, 32, 12, 4, 77, 10, 165, 244, 212, - 167, 216, 31, 244, 51, 61, 120, 241, 32, 226, 251, 85, 140, 176, 136, 122, 209, 129, 144, - 176, 9, 97, 151, 84, 225, 74, 69, 50, 31, 48, 35, 85, 251, 164, 235, 53, 94, 218, 247, 75, - 163, 95, 150, 12, 153, 179, 227, 191, 114, 195, 222, 216, 240, 59, 63, 75, 221, 251, 208, - 106, 207, 232, 150, 65, 100, 53, 33, 2, 9, 69, 91, 82, 144, 1, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 143, 177, 10, 192, 32, 16, 67, 227, 21, 74, 233, + 212, 79, 177, 127, 208, 159, 233, 224, 226, 32, 226, 247, 139, 168, 16, 68, 93, 244, 45, + 119, 228, 142, 144, 92, 0, 20, 50, 7, 237, 76, 213, 190, 50, 245, 26, 175, 218, 231, 165, + 57, 175, 148, 14, 137, 179, 147, 191, 114, 211, 221, 216, 240, 59, 63, 107, 221, 115, 104, + 181, 103, 244, 43, 36, 10, 38, 68, 108, 25, 253, 238, 136, 1, 0, 0, ]; assert_eq!(bytes, expected_serialization) @@ -306,20 +301,19 @@ fn complex_brillig_foreign_call() { private_parameters: BTreeSet::from([Witness(1), Witness(2), Witness(3)]), ..Circuit::default() }; - let program = Program { functions: vec![circuit] }; - let bytes = Program::serialize_program(&program); + let bytes = Circuit::serialize_circuit(&circuit); let expected_serialization: Vec = vec![ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 84, 65, 14, 132, 32, 12, 108, 101, 117, 205, 158, - 246, 9, 38, 187, 15, 96, 247, 5, 254, 197, 120, 211, 232, 209, 231, 139, 113, 136, 181, 65, - 47, 98, 162, 147, 52, 20, 24, 202, 164, 45, 48, 205, 200, 157, 49, 124, 227, 44, 129, 207, - 152, 75, 120, 94, 137, 209, 30, 195, 143, 227, 197, 178, 103, 105, 76, 110, 160, 209, 156, - 160, 209, 247, 195, 69, 235, 29, 179, 46, 81, 243, 103, 2, 239, 231, 225, 44, 117, 150, 97, - 254, 196, 152, 99, 157, 176, 87, 168, 188, 147, 224, 121, 20, 209, 180, 254, 109, 70, 75, - 47, 178, 186, 251, 37, 116, 86, 93, 219, 55, 245, 96, 20, 85, 75, 253, 8, 255, 171, 246, - 121, 231, 220, 4, 249, 237, 132, 56, 28, 224, 109, 113, 223, 180, 164, 50, 165, 0, 137, 17, - 72, 139, 88, 97, 4, 198, 90, 226, 196, 33, 5, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 84, 75, 10, 132, 48, 12, 125, 177, 163, 35, 179, + 154, 35, 8, 51, 7, 232, 204, 9, 188, 139, 184, 83, 116, 233, 241, 173, 152, 98, 12, 213, + 141, 21, 244, 65, 232, 39, 175, 233, 35, 73, 155, 3, 32, 204, 48, 206, 18, 158, 19, 175, + 37, 60, 175, 228, 209, 30, 195, 143, 226, 197, 178, 103, 105, 76, 110, 160, 209, 156, 160, + 209, 247, 195, 69, 235, 29, 179, 46, 81, 243, 103, 2, 239, 231, 225, 44, 117, 150, 241, + 250, 201, 99, 206, 251, 96, 95, 161, 242, 14, 193, 243, 40, 162, 105, 253, 219, 12, 75, 47, + 146, 186, 251, 37, 116, 86, 93, 219, 55, 245, 96, 20, 85, 75, 253, 136, 249, 87, 249, 105, + 231, 220, 4, 249, 237, 132, 56, 20, 224, 109, 113, 223, 88, 82, 153, 34, 64, 34, 14, 164, + 69, 172, 48, 2, 23, 243, 6, 31, 25, 5, 0, 0, ]; assert_eq!(bytes, expected_serialization) @@ -348,16 +342,13 @@ fn memory_op_circuit() { return_values: PublicInputs([Witness(4)].into()), ..Circuit::default() }; - let program = Program { functions: vec![circuit] }; - - let bytes = Program::serialize_program(&program); + let bytes = Circuit::serialize_circuit(&circuit); let expected_serialization: Vec = vec![ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 81, 201, 13, 0, 32, 8, 147, 195, 125, 112, 3, 247, - 159, 74, 141, 60, 106, 226, 79, 120, 216, 132, 180, 124, 154, 82, 168, 108, 212, 57, 2, - 122, 129, 157, 201, 181, 150, 59, 186, 179, 189, 161, 101, 251, 82, 176, 175, 196, 121, 89, - 118, 185, 246, 91, 185, 26, 125, 187, 64, 80, 134, 29, 195, 31, 79, 24, 2, 250, 167, 252, - 27, 3, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 145, 187, 17, 0, 32, 8, 67, 195, 111, 31, 220, 192, + 253, 167, 178, 144, 2, 239, 236, 132, 194, 52, 129, 230, 93, 8, 6, 64, 176, 101, 225, 28, + 78, 49, 43, 238, 154, 225, 254, 166, 209, 205, 165, 98, 174, 212, 177, 188, 187, 92, 255, + 173, 92, 173, 190, 93, 82, 80, 78, 123, 14, 127, 60, 97, 1, 210, 144, 46, 242, 19, 3, 0, 0, ]; assert_eq!(bytes, expected_serialization) diff --git a/noir/noir-repo/acvm-repo/acvm_js/src/compression.rs b/noir/noir-repo/acvm-repo/acvm_js/src/compression.rs index 73bcd02ecd1b..fedaa514bf06 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/src/compression.rs +++ b/noir/noir-repo/acvm-repo/acvm_js/src/compression.rs @@ -1,4 +1,4 @@ -use acvm::acir::native_types::{WitnessMap, WitnessStack}; +use acvm::acir::native_types::WitnessMap; use js_sys::JsString; use wasm_bindgen::prelude::wasm_bindgen; @@ -13,11 +13,10 @@ pub fn compress_witness(witness_map: JsWitnessMap) -> Result, JsString> console_error_panic_hook::set_once(); let witness_map = WitnessMap::from(witness_map); - let witness_stack: WitnessStack = witness_map.into(); - let compressed_witness_stack: Vec = - Vec::::try_from(witness_stack).map_err(|err| err.to_string())?; + let compressed_witness_map: Vec = + Vec::::try_from(witness_map).map_err(|err| err.to_string())?; - Ok(compressed_witness_stack) + Ok(compressed_witness_map) } /// Decompresses a compressed witness as outputted by Nargo into a `WitnessMap`. @@ -28,8 +27,8 @@ pub fn compress_witness(witness_map: JsWitnessMap) -> Result, JsString> pub fn decompress_witness(compressed_witness: Vec) -> Result { console_error_panic_hook::set_once(); - let witness_stack = - WitnessStack::try_from(compressed_witness.as_slice()).map_err(|err| err.to_string())?; + let witness_map = + WitnessMap::try_from(compressed_witness.as_slice()).map_err(|err| err.to_string())?; - Ok(witness_stack.stack[0].witness.clone().into()) + Ok(witness_map.into()) } diff --git a/noir/noir-repo/acvm-repo/acvm_js/src/execute.rs b/noir/noir-repo/acvm-repo/acvm_js/src/execute.rs index 6985183a8a07..3f691e1abf29 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/src/execute.rs +++ b/noir/noir-repo/acvm-repo/acvm_js/src/execute.rs @@ -1,5 +1,5 @@ use acvm::{ - acir::circuit::Program, + acir::circuit::Circuit, pwg::{ACVMStatus, ErrorLocation, OpcodeResolutionError, ACVM}, }; use bn254_blackbox_solver::Bn254BlackBoxSolver; @@ -56,17 +56,13 @@ pub async fn execute_circuit( #[wasm_bindgen(js_name = executeCircuitWithBlackBoxSolver, skip_jsdoc)] pub async fn execute_circuit_with_black_box_solver( solver: &WasmBlackBoxFunctionSolver, - // TODO(https://github.com/noir-lang/noir/issues/4428): These need to be updated to match the same interfaces - // as the native ACVM executor. Right now native execution still only handles one circuit so I do not feel the need - // to break the JS interface just yet. circuit: Vec, initial_witness: JsWitnessMap, foreign_call_handler: ForeignCallHandler, ) -> Result { console_error_panic_hook::set_once(); - let program: Program = Program::deserialize_program(&circuit) + let circuit: Circuit = Circuit::deserialize_circuit(&circuit) .map_err(|_| JsExecutionError::new("Failed to deserialize circuit. This is likely due to differing serialization formats between ACVM_JS and your compiler".to_string(), None))?; - let circuit = &program.functions[0]; let mut acvm = ACVM::new(&solver.0, &circuit.opcodes, initial_witness.into()); diff --git a/noir/noir-repo/acvm-repo/acvm_js/src/public_witness.rs b/noir/noir-repo/acvm-repo/acvm_js/src/public_witness.rs index 2ae90b79a6a5..8dc66c435b3c 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/src/public_witness.rs +++ b/noir/noir-repo/acvm-repo/acvm_js/src/public_witness.rs @@ -1,5 +1,5 @@ use acvm::acir::{ - circuit::Program, + circuit::Circuit, native_types::{Witness, WitnessMap}, }; use js_sys::JsString; @@ -26,21 +26,16 @@ fn extract_indices(witness_map: &WitnessMap, indices: Vec) -> Result, witness_map: JsWitnessMap, ) -> Result { console_error_panic_hook::set_once(); - let program: Program = - Program::deserialize_program(&circuit).expect("Failed to deserialize circuit"); - let circuit = &program.functions[0]; - + let circuit: Circuit = + Circuit::deserialize_circuit(&circuit).expect("Failed to deserialize circuit"); let witness_map = WitnessMap::from(witness_map); let return_witness = - extract_indices(&witness_map, circuit.return_values.0.clone().into_iter().collect())?; + extract_indices(&witness_map, circuit.return_values.0.into_iter().collect())?; Ok(JsWitnessMap::from(return_witness)) } @@ -56,14 +51,12 @@ pub fn get_public_parameters_witness( solved_witness: JsWitnessMap, ) -> Result { console_error_panic_hook::set_once(); - let program: Program = - Program::deserialize_program(&circuit).expect("Failed to deserialize circuit"); - let circuit = &program.functions[0]; - + let circuit: Circuit = + Circuit::deserialize_circuit(&circuit).expect("Failed to deserialize circuit"); let witness_map = WitnessMap::from(solved_witness); let public_params_witness = - extract_indices(&witness_map, circuit.public_parameters.0.clone().into_iter().collect())?; + extract_indices(&witness_map, circuit.public_parameters.0.into_iter().collect())?; Ok(JsWitnessMap::from(public_params_witness)) } @@ -79,14 +72,12 @@ pub fn get_public_witness( solved_witness: JsWitnessMap, ) -> Result { console_error_panic_hook::set_once(); - let program: Program = - Program::deserialize_program(&circuit).expect("Failed to deserialize circuit"); - let circuit = &program.functions[0]; - + let circuit: Circuit = + Circuit::deserialize_circuit(&circuit).expect("Failed to deserialize circuit"); let witness_map = WitnessMap::from(solved_witness); let public_witness = - extract_indices(&witness_map, circuit.public_inputs().0.clone().into_iter().collect())?; + extract_indices(&witness_map, circuit.public_inputs().0.into_iter().collect())?; Ok(JsWitnessMap::from(public_witness)) } diff --git a/noir/noir-repo/acvm-repo/acvm_js/test/shared/addition.ts b/noir/noir-repo/acvm-repo/acvm_js/test/shared/addition.ts index f5b0bda2d07a..217902bdea61 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/test/shared/addition.ts +++ b/noir/noir-repo/acvm-repo/acvm_js/test/shared/addition.ts @@ -2,12 +2,11 @@ import { WitnessMap } from '@noir-lang/acvm_js'; // See `addition_circuit` integration test in `acir/tests/test_program_serialization.rs`. export const bytecode = Uint8Array.from([ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 144, 75, 14, 128, 32, 12, 68, 249, 120, 160, 150, - 182, 208, 238, 188, 138, 68, 184, 255, 17, 212, 200, 130, 196, 165, 188, 164, 153, 174, 94, - 38, 227, 221, 203, 118, 159, 119, 95, 226, 200, 125, 36, 252, 3, 253, 66, 87, 152, 92, 4, - 153, 185, 149, 212, 144, 240, 128, 100, 85, 5, 88, 106, 86, 84, 20, 149, 51, 41, 81, 83, - 214, 98, 213, 10, 24, 50, 53, 236, 98, 212, 135, 44, 174, 235, 5, 143, 35, 12, 151, 159, - 126, 55, 109, 28, 231, 145, 47, 245, 105, 191, 143, 133, 1, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 208, 49, 14, 192, 32, 8, 5, 80, 212, 30, 8, 4, 20, 182, 94, 165, 166, 122, + 255, 35, 52, 77, 28, 76, 58, 214, 191, 124, 166, 23, 242, 15, 0, 8, 240, 77, 154, 125, 206, 198, 127, 161, 176, 209, + 138, 139, 197, 88, 68, 122, 205, 157, 152, 46, 204, 222, 76, 81, 180, 21, 35, 35, 53, 189, 179, 49, 119, 19, 171, 222, + 188, 162, 147, 112, 167, 161, 206, 99, 98, 105, 223, 95, 248, 26, 113, 90, 97, 185, 97, 217, 56, 173, 35, 63, 243, 81, + 87, 163, 125, 1, 0, 0, ]); export const initialWitnessMap: WitnessMap = new Map([ diff --git a/noir/noir-repo/acvm-repo/acvm_js/test/shared/complex_foreign_call.ts b/noir/noir-repo/acvm-repo/acvm_js/test/shared/complex_foreign_call.ts index c75a59643473..27abd72305f0 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/test/shared/complex_foreign_call.ts +++ b/noir/noir-repo/acvm-repo/acvm_js/test/shared/complex_foreign_call.ts @@ -2,15 +2,13 @@ import { WitnessMap } from '@noir-lang/acvm_js'; // See `complex_brillig_foreign_call` integration test in `acir/tests/test_program_serialization.rs`. export const bytecode = Uint8Array.from([ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 84, 65, 14, 132, 32, 12, 108, 101, 117, 205, 158, - 246, 9, 38, 187, 15, 96, 247, 5, 254, 197, 120, 211, 232, 209, 231, 139, 113, 136, 181, 65, - 47, 98, 162, 147, 52, 20, 24, 202, 164, 45, 48, 205, 200, 157, 49, 124, 227, 44, 129, 207, - 152, 75, 120, 94, 137, 209, 30, 195, 143, 227, 197, 178, 103, 105, 76, 110, 160, 209, 156, - 160, 209, 247, 195, 69, 235, 29, 179, 46, 81, 243, 103, 2, 239, 231, 225, 44, 117, 150, 97, - 254, 196, 152, 99, 157, 176, 87, 168, 188, 147, 224, 121, 20, 209, 180, 254, 109, 70, 75, - 47, 178, 186, 251, 37, 116, 86, 93, 219, 55, 245, 96, 20, 85, 75, 253, 8, 255, 171, 246, - 121, 231, 220, 4, 249, 237, 132, 56, 28, 224, 109, 113, 223, 180, 164, 50, 165, 0, 137, 17, - 72, 139, 88, 97, 4, 198, 90, 226, 196, 33, 5, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 84, 75, 10, 132, 48, 12, 125, 177, 163, 35, 179, 154, 35, 8, 51, 7, 232, 204, + 9, 188, 139, 184, 83, 116, 233, 241, 173, 152, 98, 12, 213, 141, 21, 244, 65, 232, 39, 175, 233, 35, 73, 155, 3, 32, + 204, 48, 206, 18, 158, 19, 175, 37, 60, 175, 228, 209, 30, 195, 143, 226, 197, 178, 103, 105, 76, 110, 160, 209, 156, + 160, 209, 247, 195, 69, 235, 29, 179, 46, 81, 243, 103, 2, 239, 231, 225, 44, 117, 150, 241, 250, 201, 99, 206, 251, + 96, 95, 161, 242, 14, 193, 243, 40, 162, 105, 253, 219, 12, 75, 47, 146, 186, 251, 37, 116, 86, 93, 219, 55, 245, 96, + 20, 85, 75, 253, 136, 249, 87, 249, 105, 231, 220, 4, 249, 237, 132, 56, 20, 224, 109, 113, 223, 88, 82, 153, 34, 64, + 34, 14, 164, 69, 172, 48, 2, 23, 243, 6, 31, 25, 5, 0, 0, ]); export const initialWitnessMap: WitnessMap = new Map([ [1, '0x0000000000000000000000000000000000000000000000000000000000000001'], diff --git a/noir/noir-repo/acvm-repo/acvm_js/test/shared/fixed_base_scalar_mul.ts b/noir/noir-repo/acvm-repo/acvm_js/test/shared/fixed_base_scalar_mul.ts index 46e1f66fb211..c0859f50135b 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/test/shared/fixed_base_scalar_mul.ts +++ b/noir/noir-repo/acvm-repo/acvm_js/test/shared/fixed_base_scalar_mul.ts @@ -1,8 +1,8 @@ // See `fixed_base_scalar_mul_circuit` integration test in `acir/tests/test_program_serialization.rs`. export const bytecode = Uint8Array.from([ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 77, 138, 81, 10, 0, 48, 8, 66, 87, 219, 190, 118, 233, - 29, 61, 43, 3, 5, 121, 34, 207, 86, 231, 162, 198, 157, 124, 228, 71, 157, 220, 232, 161, - 227, 226, 206, 214, 95, 221, 74, 0, 116, 58, 13, 182, 105, 0, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 77, 138, 91, 10, 0, 32, 16, 2, 109, 171, 175, 46, 221, 209, 247, 229, 130, 130, + 140, 200, 92, 0, 11, 157, 228, 35, 127, 212, 200, 29, 61, 116, 76, 220, 217, 250, 171, 91, 113, 160, 66, 104, 242, 97, + 0, 0, 0, ]); export const initialWitnessMap = new Map([ [1, '0x0000000000000000000000000000000000000000000000000000000000000001'], diff --git a/noir/noir-repo/acvm-repo/acvm_js/test/shared/foreign_call.ts b/noir/noir-repo/acvm-repo/acvm_js/test/shared/foreign_call.ts index 527f26b4ae39..0be8937b57d3 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/test/shared/foreign_call.ts +++ b/noir/noir-repo/acvm-repo/acvm_js/test/shared/foreign_call.ts @@ -2,11 +2,10 @@ import { WitnessMap } from '@noir-lang/acvm_js'; // See `simple_brillig_foreign_call` integration test in `acir/tests/test_program_serialization.rs`. export const bytecode = Uint8Array.from([ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 143, 65, 10, 192, 32, 12, 4, 77, 10, 165, 244, 212, - 167, 216, 31, 244, 51, 61, 120, 241, 32, 226, 251, 85, 140, 176, 136, 122, 209, 129, 144, - 176, 9, 97, 151, 84, 225, 74, 69, 50, 31, 48, 35, 85, 251, 164, 235, 53, 94, 218, 247, 75, - 163, 95, 150, 12, 153, 179, 227, 191, 114, 195, 222, 216, 240, 59, 63, 75, 221, 251, 208, - 106, 207, 232, 150, 65, 100, 53, 33, 2, 9, 69, 91, 82, 144, 1, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 143, 177, 10, 192, 32, 16, 67, 227, 21, 74, 233, 212, 79, 177, 127, 208, 159, + 233, 224, 226, 32, 226, 247, 139, 168, 16, 68, 93, 244, 45, 119, 228, 142, 144, 92, 0, 20, 50, 7, 237, 76, 213, 190, + 50, 245, 26, 175, 218, 231, 165, 57, 175, 148, 14, 137, 179, 147, 191, 114, 211, 221, 216, 240, 59, 63, 107, 221, 115, + 104, 181, 103, 244, 43, 36, 10, 38, 68, 108, 25, 253, 238, 136, 1, 0, 0, ]); export const initialWitnessMap: WitnessMap = new Map([ [1, '0x0000000000000000000000000000000000000000000000000000000000000005'], diff --git a/noir/noir-repo/acvm-repo/acvm_js/test/shared/memory_op.ts b/noir/noir-repo/acvm-repo/acvm_js/test/shared/memory_op.ts index f2e5ab4af491..b5ab64b3447e 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/test/shared/memory_op.ts +++ b/noir/noir-repo/acvm-repo/acvm_js/test/shared/memory_op.ts @@ -1,10 +1,9 @@ // See `memory_op_circuit` integration test in `acir/tests/test_program_serialization.rs`. export const bytecode = Uint8Array.from([ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 81, 201, 13, 0, 32, 8, 147, 195, 125, 112, 3, 247, - 159, 74, 141, 60, 106, 226, 79, 120, 216, 132, 180, 124, 154, 82, 168, 108, 212, 57, 2, - 122, 129, 157, 201, 181, 150, 59, 186, 179, 189, 161, 101, 251, 82, 176, 175, 196, 121, 89, - 118, 185, 246, 91, 185, 26, 125, 187, 64, 80, 134, 29, 195, 31, 79, 24, 2, 250, 167, 252, - 27, 3, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 145, 187, 17, 0, 32, 8, 67, 195, 111, 31, 220, 192, 253, 167, 178, 144, 2, + 239, 236, 132, 194, 52, 129, 230, 93, 8, 6, 64, 176, 101, 225, 28, 78, 49, 43, 238, 154, 225, 254, 166, 209, 205, 165, + 98, 174, 212, 177, 188, 187, 92, 255, 173, 92, 173, 190, 93, 82, 80, 78, 123, 14, 127, 60, 97, 1, 210, 144, 46, 242, + 19, 3, 0, 0, ]); export const initialWitnessMap = new Map([ diff --git a/noir/noir-repo/acvm-repo/acvm_js/test/shared/pedersen.ts b/noir/noir-repo/acvm-repo/acvm_js/test/shared/pedersen.ts index 0882874136ee..5150d24131c4 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/test/shared/pedersen.ts +++ b/noir/noir-repo/acvm-repo/acvm_js/test/shared/pedersen.ts @@ -1,8 +1,7 @@ // See `pedersen_circuit` integration test in `acir/tests/test_program_serialization.rs`. export const bytecode = Uint8Array.from([ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 93, 74, 7, 6, 0, 0, 8, 108, 209, 255, 63, 156, 54, 233, - 56, 55, 17, 26, 18, 196, 241, 169, 250, 178, 141, 167, 32, 159, 254, 234, 238, 255, 87, - 112, 52, 63, 63, 101, 105, 0, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 93, 74, 135, 9, 0, 48, 8, 75, 171, 224, 255, 15, 139, 27, 196, 64, 200, 100, 0, 15, + 133, 80, 57, 89, 219, 127, 39, 173, 126, 235, 236, 247, 151, 48, 224, 71, 90, 33, 97, 0, 0, 0, ]); export const initialWitnessMap = new Map([[1, '0x0000000000000000000000000000000000000000000000000000000000000001']]); diff --git a/noir/noir-repo/acvm-repo/acvm_js/test/shared/schnorr_verify.ts b/noir/noir-repo/acvm-repo/acvm_js/test/shared/schnorr_verify.ts index 8f5667bd8883..2127de66f694 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/test/shared/schnorr_verify.ts +++ b/noir/noir-repo/acvm-repo/acvm_js/test/shared/schnorr_verify.ts @@ -1,21 +1,17 @@ // See `schnorr_verify_circuit` integration test in `acir/tests/test_program_serialization.rs`. export const bytecode = Uint8Array.from([ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 77, 210, 7, 78, 2, 1, 20, 69, 81, 236, 189, 247, 222, - 123, 239, 93, 177, 33, 34, 238, 194, 253, 47, 193, 200, 147, 67, 194, 36, 147, 163, 33, 33, - 228, 191, 219, 82, 168, 63, 63, 181, 183, 197, 223, 177, 147, 191, 181, 183, 149, 69, 159, - 183, 213, 222, 238, 218, 219, 206, 14, 118, 178, 139, 141, 183, 135, 189, 236, 99, 63, 7, - 56, 200, 33, 14, 115, 132, 163, 28, 227, 56, 39, 56, 201, 41, 78, 115, 134, 179, 156, 227, - 60, 23, 184, 200, 37, 46, 115, 133, 171, 92, 227, 58, 55, 184, 201, 45, 110, 115, 135, 187, - 220, 227, 62, 15, 120, 200, 35, 30, 243, 132, 167, 60, 227, 57, 47, 120, 201, 43, 94, 243, - 134, 183, 188, 227, 61, 31, 248, 200, 39, 22, 249, 204, 151, 166, 29, 243, 188, 250, 255, - 141, 239, 44, 241, 131, 101, 126, 178, 194, 47, 86, 249, 237, 123, 171, 76, 127, 105, 47, - 189, 165, 181, 116, 150, 198, 26, 125, 245, 248, 45, 233, 41, 45, 165, 163, 52, 148, 126, - 210, 78, 186, 73, 51, 233, 37, 173, 164, 147, 52, 146, 62, 210, 70, 186, 72, 19, 233, 33, - 45, 164, 131, 52, 144, 253, 151, 11, 245, 221, 179, 121, 246, 206, 214, 217, 57, 27, 103, - 223, 109, 187, 238, 218, 115, 223, 142, 135, 246, 59, 182, 219, 169, 189, 206, 237, 116, - 105, 159, 107, 187, 220, 218, 227, 222, 14, 143, 238, 95, 116, 247, 23, 119, 126, 115, 223, - 146, 187, 150, 221, 179, 226, 142, 141, 155, 53, 238, 86, 104, 186, 231, 255, 243, 7, 100, - 141, 232, 192, 233, 3, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 77, 210, 7, 74, 3, 1, 20, 69, 209, 177, 247, 222, 123, 239, 189, 119, 141, 93, 99, + 220, 133, 251, 95, 130, 152, 103, 78, 32, 3, 195, 33, 4, 66, 248, 239, 254, 20, 69, 209, 84, 212, 158, 216, 206, 223, + 234, 219, 204, 146, 239, 91, 170, 111, 103, 245, 109, 101, 27, 219, 217, 193, 250, 219, 197, 110, 246, 176, 151, 125, + 236, 231, 0, 7, 57, 196, 97, 142, 112, 148, 99, 28, 231, 4, 39, 57, 197, 105, 206, 112, 150, 115, 156, 231, 2, 23, + 185, 196, 101, 174, 112, 149, 107, 92, 231, 6, 55, 185, 197, 109, 238, 112, 151, 123, 220, 231, 1, 15, 121, 196, 99, + 158, 240, 148, 103, 60, 231, 5, 47, 121, 197, 107, 222, 240, 150, 119, 188, 231, 3, 75, 124, 228, 83, 195, 142, 121, + 158, 125, 126, 225, 43, 223, 248, 206, 15, 126, 178, 204, 47, 86, 248, 237, 119, 43, 76, 127, 105, 47, 189, 165, 181, + 116, 150, 198, 234, 125, 117, 249, 47, 233, 41, 45, 165, 163, 52, 148, 126, 210, 78, 186, 73, 51, 233, 37, 173, 164, + 147, 52, 146, 62, 210, 70, 186, 72, 19, 233, 33, 45, 164, 131, 52, 144, 253, 23, 139, 218, 238, 217, 60, 123, 103, + 235, 236, 156, 141, 179, 239, 166, 93, 183, 237, 185, 107, 199, 125, 251, 29, 218, 237, 216, 94, 167, 118, 58, 183, + 207, 165, 93, 174, 237, 113, 107, 135, 123, 247, 47, 185, 251, 147, 59, 191, 184, 239, 155, 187, 126, 184, 103, 217, + 29, 235, 55, 171, 223, 173, 104, 184, 231, 255, 243, 7, 236, 52, 239, 128, 225, 3, 0, 0, ]); export const initialWitnessMap = new Map([ diff --git a/noir/noir-repo/acvm-repo/acvm_js/test/shared/witness_compression.ts b/noir/noir-repo/acvm-repo/acvm_js/test/shared/witness_compression.ts index f9d66c2c8d0e..36b9a0284af6 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/test/shared/witness_compression.ts +++ b/noir/noir-repo/acvm-repo/acvm_js/test/shared/witness_compression.ts @@ -4,22 +4,19 @@ // assert(x != y); // x + y // } -// -// Regenerate this byte array by going to the Noir integration tests and running `/test_programs/execution_success/witness_compression` -// after recompiling Noir to print the witness byte array to be written to file after execution export const expectedCompressedWitnessMap = Uint8Array.from([ - 31, 139, 8, 0, 0, 0, 0, 0, 2, 255, 173, 206, 185, 13, 0, 48, 8, 67, 209, 144, 107, 30, 146, - 44, 144, 253, 167, 162, 65, 130, 158, 239, 198, 174, 158, 44, 45, 178, 211, 254, 222, 90, - 203, 17, 206, 186, 29, 252, 53, 64, 107, 114, 150, 46, 206, 122, 6, 24, 73, 44, 193, 220, - 1, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 2, 255, 173, 208, 187, 13, 128, 48, 12, 4, 80, 190, 153, 199, 142, 237, 196, 238, 88, 133, + 8, 103, 255, 17, 64, 34, 5, 61, 62, 233, 164, 171, 94, 113, 105, 122, 51, 63, 61, 198, 134, 127, 193, 37, 206, 202, + 235, 199, 34, 40, 204, 94, 179, 35, 225, 9, 217, 154, 10, 176, 180, 162, 168, 40, 42, 87, 86, 34, 87, 214, 106, 205, + 42, 24, 50, 57, 118, 49, 234, 3, 219, 2, 173, 61, 240, 175, 20, 103, 209, 13, 151, 252, 77, 33, 208, 1, 0, 0, ]); export const expectedWitnessMap = new Map([ - [0, '0x0000000000000000000000000000000000000000000000000000000000000001'], - [1, '0x0000000000000000000000000000000000000000000000000000000000000002'], - [2, '0x0000000000000000000000000000000000000000000000000000000000000001'], - [3, '0x0000000000000000000000000000000000000000000000000000000000000001'], - [4, '0x0000000000000000000000000000000000000000000000000000000000000000'], - [5, '0x0000000000000000000000000000000000000000000000000000000000000003'], + [1, '0x0000000000000000000000000000000000000000000000000000000000000001'], + [2, '0x0000000000000000000000000000000000000000000000000000000000000002'], + [3, '0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000'], + [4, '0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000'], + [5, '0x0000000000000000000000000000000000000000000000000000000000000001'], + [6, '0x0000000000000000000000000000000000000000000000000000000000000003'], ]); diff --git a/noir/noir-repo/compiler/integration-tests/.gitignore b/noir/noir-repo/compiler/integration-tests/.gitignore index d27cc5f16183..40571b83650d 100644 --- a/noir/noir-repo/compiler/integration-tests/.gitignore +++ b/noir/noir-repo/compiler/integration-tests/.gitignore @@ -1,3 +1,4 @@ +contracts crs node_modules diff --git a/noir/noir-repo/compiler/integration-tests/contracts/1_mul.sol b/noir/noir-repo/compiler/integration-tests/contracts/1_mul.sol deleted file mode 100644 index ff8f36385337..000000000000 --- a/noir/noir-repo/compiler/integration-tests/contracts/1_mul.sol +++ /dev/null @@ -1,2869 +0,0 @@ -// Verification Key Hash: 81dab81c9312ecc480984185bcdeabfb118f294791980be42c247006c29b27de -// SPDX-License-Identifier: Apache-2.0 -// Copyright 2022 Aztec -pragma solidity >=0.8.4; - -library UltraVerificationKey { - function verificationKeyHash() internal pure returns(bytes32) { - return 0x81dab81c9312ecc480984185bcdeabfb118f294791980be42c247006c29b27de; - } - - function loadVerificationKey(uint256 _vk, uint256 _omegaInverseLoc) internal pure { - assembly { - mstore(add(_vk, 0x00), 0x0000000000000000000000000000000000000000000000000000000000001000) // vk.circuit_size - mstore(add(_vk, 0x20), 0x0000000000000000000000000000000000000000000000000000000000000000) // vk.num_inputs - mstore(add(_vk, 0x40), 0x0931d596de2fd10f01ddd073fd5a90a976f169c76f039bb91c4775720042d43a) // vk.work_root - mstore(add(_vk, 0x60), 0x3061482dfa038d0fb5b4c0b226194047a2616509f531d4fa3acdb77496c10001) // vk.domain_inverse - mstore(add(_vk, 0x80), 0x26dff731489360cd9d88e52bad2198f84d36c1439b77c54f95d6eaf0cef94b8f) // vk.Q1.x - mstore(add(_vk, 0xa0), 0x02acb21f0f38895956e06930708b45106e016ebefc0d24dcdb8c7f959967a90c) // vk.Q1.y - mstore(add(_vk, 0xc0), 0x24ef08dff23f2729f6cd70ed8305655ccec1dfb5e70d8e8a2d4190ce1a1d7e81) // vk.Q2.x - mstore(add(_vk, 0xe0), 0x16ae4c218a37acdb580a2f2c2033d4c93ee06633febe6c96d6bc845b1fbbf7db) // vk.Q2.y - mstore(add(_vk, 0x100), 0x02be54ccdfcf358d15e469f7a7a79d4851996cb90ff7e6ae89734c53b5db89b2) // vk.Q3.x - mstore(add(_vk, 0x120), 0x292fefb96ebc59f41b06421baa766e8949eab20ba1ddbe3cdc0d4a130bdc9dac) // vk.Q3.y - mstore(add(_vk, 0x140), 0x019d7129fa4f0cc04801bd9b9065a25c61b3400244190698a17d73f550c3ad01) // vk.Q4.x - mstore(add(_vk, 0x160), 0x106810b16c402a25c417c5603b70b3ee6b41316be80ba38bb2276f8e9427d8b9) // vk.Q4.y - mstore(add(_vk, 0x180), 0x0efb192384fe64f333475e3c441dcb9d8933a2b4a4179d43b66ee1966199de66) // vk.Q_M.x - mstore(add(_vk, 0x1a0), 0x2a56cfd4a9b725326de5171dd6ec6cba64945cde70652768e4aeecb4a92f193a) // vk.Q_M.y - mstore(add(_vk, 0x1c0), 0x24e321e4d1e65f3c26b32903a432217b5d1c03cf5ac13fa055b5d38216bac3f1) // vk.Q_C.x - mstore(add(_vk, 0x1e0), 0x304c9ace458fbf93f3e9d07fea2b48edc40e9d248862871437a044d557b89085) // vk.Q_C.y - mstore(add(_vk, 0x200), 0x040f659b07806f721e8eeb17773c70a7351a0e59a15027c7f87343d5bd2cac01) // vk.Q_ARITHMETIC.x - mstore(add(_vk, 0x220), 0x215a63918831655a2020158099ebd13bbab94febef4febe815bbca0ac5b0b303) // vk.Q_ARITHMETIC.y - mstore(add(_vk, 0x240), 0x0348ad0a2d9d9a94c78f6c20d7ed0ee0a018bc5a3e51a3453f4256430b0d526c) // vk.QSORT.x - mstore(add(_vk, 0x260), 0x0b711c4268e26d19a11f7560fc53828b7d9e6f920ccb8a0129f8d515c66d99ac) // vk.QSORT.y - mstore(add(_vk, 0x280), 0x13982fd0cf8da5082a77561113bb5ee51e2e82380da3da5ad0f24e49e5f32208) // vk.Q_ELLIPTIC.x - mstore(add(_vk, 0x2a0), 0x1aa5ffd5aa4c16d1c66e18c4574a3ab0b25e9b4e4e04ad1280d1a264237717e0) // vk.Q_ELLIPTIC.y - mstore(add(_vk, 0x2c0), 0x1750f44d3f9dfad78a1e2127ef91051ce018f20536fe45ca28dcc7b248389fc0) // vk.Q_AUX.x - mstore(add(_vk, 0x2e0), 0x1a05418f502a965c39994cd3f83e39164b49c0f27d4f5ac4550751cc0a24bb58) // vk.Q_AUX.y - mstore(add(_vk, 0x300), 0x0e79dad980ecbcba02fa09399f492293608ea5ec55655f381851ab2a7fd9d3e4) // vk.SIGMA1.x - mstore(add(_vk, 0x320), 0x20dcf4e6e84362a1fbb32928b49070375f866ce7334fe5d96572d6a885879066) // vk.SIGMA1.y - mstore(add(_vk, 0x340), 0x04700138101e581226ac624463c28d886eedc87159a518f9c59e117b30dd9fc6) // vk.SIGMA2.x - mstore(add(_vk, 0x360), 0x0766d9586e6192576f6eddb0e2c023f9a574f4d736c9480820431f434b235344) // vk.SIGMA2.y - mstore(add(_vk, 0x380), 0x196fd832eb6b30543b949cd2a124bd2d1504133b34fe6b6346f30cc7a3ed2a75) // vk.SIGMA3.x - mstore(add(_vk, 0x3a0), 0x14bfde5cb996c75c818cdf88d9234ccc0e905f27af5503f42a8f38c2892d6e1c) // vk.SIGMA3.y - mstore(add(_vk, 0x3c0), 0x03c8a1592fca76a3959266b015c120e99a764029d1373ce0a9329d8b441f841a) // vk.SIGMA4.x - mstore(add(_vk, 0x3e0), 0x2239ff07c67a2a59139ef012e667a5fb08293af4abc6dc70e1297e45e744355c) // vk.SIGMA4.y - mstore(add(_vk, 0x400), 0x259f452dc7fd2dda4013dba2196852bcf43c285b1d1f7f85341f3615d25fe97b) // vk.TABLE1.x - mstore(add(_vk, 0x420), 0x117500555dd886209c0b10ee8cd10e711e890a1c99a8f689419da8c52d2e8e9d) // vk.TABLE1.y - mstore(add(_vk, 0x440), 0x2577f542178a07dac262fdabad6f55a84fca32b13b92e520bb91a7455f78ccf1) // vk.TABLE2.x - mstore(add(_vk, 0x460), 0x0fc87ae27122e60eaacc070bd59aafe12644a82ee1345497f8c0302e92925c68) // vk.TABLE2.y - mstore(add(_vk, 0x480), 0x1612f501335a4b72ac55dbe2fd1a75e5fe2c041687603b6577581d673d13be50) // vk.TABLE3.x - mstore(add(_vk, 0x4a0), 0x160e8ef7ff5315cb640ec82e965db270846e904bb7d1c7ff02f32823de6c1c71) // vk.TABLE3.y - mstore(add(_vk, 0x4c0), 0x2d540ff1653b38acbcb9cda315442364007633f529476b2f169a0ff131bfb319) // vk.TABLE4.x - mstore(add(_vk, 0x4e0), 0x2198b9feb61f8160e357b8bb7ca329713898655cc94a0ac2d84944c737cf57e5) // vk.TABLE4.y - mstore(add(_vk, 0x500), 0x11c8df52c3ef754f80d11792cea4b7ad74612e486596cbe7f7d6a05f19c69444) // vk.TABLE_TYPE.x - mstore(add(_vk, 0x520), 0x10c8a36cbb2fd9ed8875b5106a37162ac2932f3bd1b6942b132546d2110a63e2) // vk.TABLE_TYPE.y - mstore(add(_vk, 0x540), 0x122470dc810ee1029ff28334364b1b3dd18193defaf51bb09296275700ee6dd0) // vk.ID1.x - mstore(add(_vk, 0x560), 0x018b2c609f8013a95b1e7c3346e2d3febea6791d393777bfc213831f687070b9) // vk.ID1.y - mstore(add(_vk, 0x580), 0x2fd86e853b82a697cfcd347bad53b66a655813df12ba231808bf65f6561e923c) // vk.ID2.x - mstore(add(_vk, 0x5a0), 0x12b82a7864a782e5afc7f9c85f01ee1b233d94da8bcd1fac485cfdd481db8086) // vk.ID2.y - mstore(add(_vk, 0x5c0), 0x23afba4022c9e1a3eb7ab039a120c48ee661a8e06751225fb989b53f0bfe0b34) // vk.ID3.x - mstore(add(_vk, 0x5e0), 0x04f7c94dc819346aae8a76a89d7d1792c1806ed2e76828e60ee05241952773ec) // vk.ID3.y - mstore(add(_vk, 0x600), 0x282ed40f6896050dc339a08a220ddfb4d33a7c766684e2dde14ca6f452da84b0) // vk.ID4.x - mstore(add(_vk, 0x620), 0x2dadeff4061603c87f4dce0e42c6e145f590062d9bf6e6642f997275bb05b6af) // vk.ID4.y - mstore(add(_vk, 0x640), 0x00) // vk.contains_recursive_proof - mstore(add(_vk, 0x660), 0) // vk.recursive_proof_public_input_indices - mstore(add(_vk, 0x680), 0x260e01b251f6f1c7e7ff4e580791dee8ea51d87a358e038b4efe30fac09383c1) // vk.g2_x.X.c1 - mstore(add(_vk, 0x6a0), 0x0118c4d5b837bcc2bc89b5b398b5974e9f5944073b32078b7e231fec938883b0) // vk.g2_x.X.c0 - mstore(add(_vk, 0x6c0), 0x04fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe4) // vk.g2_x.Y.c1 - mstore(add(_vk, 0x6e0), 0x22febda3c0c0632a56475b4214e5615e11e6dd3f96e6cea2854a87d4dacc5e55) // vk.g2_x.Y.c0 - mstore(_omegaInverseLoc, 0x1af864d211b88d9ccf2e371c2ba088d9269d3fdea04e05acb6f70f8dc79e0e57) // vk.work_root_inverse - } - } -} - -/** - * @title Ultra Plonk proof verification contract - * @dev Top level Plonk proof verification contract, which allows Plonk proof to be verified - */ -abstract contract BaseUltraVerifier { - // VERIFICATION KEY MEMORY LOCATIONS - uint256 internal constant N_LOC = 0x380; - uint256 internal constant NUM_INPUTS_LOC = 0x3a0; - uint256 internal constant OMEGA_LOC = 0x3c0; - uint256 internal constant DOMAIN_INVERSE_LOC = 0x3e0; - uint256 internal constant Q1_X_LOC = 0x400; - uint256 internal constant Q1_Y_LOC = 0x420; - uint256 internal constant Q2_X_LOC = 0x440; - uint256 internal constant Q2_Y_LOC = 0x460; - uint256 internal constant Q3_X_LOC = 0x480; - uint256 internal constant Q3_Y_LOC = 0x4a0; - uint256 internal constant Q4_X_LOC = 0x4c0; - uint256 internal constant Q4_Y_LOC = 0x4e0; - uint256 internal constant QM_X_LOC = 0x500; - uint256 internal constant QM_Y_LOC = 0x520; - uint256 internal constant QC_X_LOC = 0x540; - uint256 internal constant QC_Y_LOC = 0x560; - uint256 internal constant QARITH_X_LOC = 0x580; - uint256 internal constant QARITH_Y_LOC = 0x5a0; - uint256 internal constant QSORT_X_LOC = 0x5c0; - uint256 internal constant QSORT_Y_LOC = 0x5e0; - uint256 internal constant QELLIPTIC_X_LOC = 0x600; - uint256 internal constant QELLIPTIC_Y_LOC = 0x620; - uint256 internal constant QAUX_X_LOC = 0x640; - uint256 internal constant QAUX_Y_LOC = 0x660; - uint256 internal constant SIGMA1_X_LOC = 0x680; - uint256 internal constant SIGMA1_Y_LOC = 0x6a0; - uint256 internal constant SIGMA2_X_LOC = 0x6c0; - uint256 internal constant SIGMA2_Y_LOC = 0x6e0; - uint256 internal constant SIGMA3_X_LOC = 0x700; - uint256 internal constant SIGMA3_Y_LOC = 0x720; - uint256 internal constant SIGMA4_X_LOC = 0x740; - uint256 internal constant SIGMA4_Y_LOC = 0x760; - uint256 internal constant TABLE1_X_LOC = 0x780; - uint256 internal constant TABLE1_Y_LOC = 0x7a0; - uint256 internal constant TABLE2_X_LOC = 0x7c0; - uint256 internal constant TABLE2_Y_LOC = 0x7e0; - uint256 internal constant TABLE3_X_LOC = 0x800; - uint256 internal constant TABLE3_Y_LOC = 0x820; - uint256 internal constant TABLE4_X_LOC = 0x840; - uint256 internal constant TABLE4_Y_LOC = 0x860; - uint256 internal constant TABLE_TYPE_X_LOC = 0x880; - uint256 internal constant TABLE_TYPE_Y_LOC = 0x8a0; - uint256 internal constant ID1_X_LOC = 0x8c0; - uint256 internal constant ID1_Y_LOC = 0x8e0; - uint256 internal constant ID2_X_LOC = 0x900; - uint256 internal constant ID2_Y_LOC = 0x920; - uint256 internal constant ID3_X_LOC = 0x940; - uint256 internal constant ID3_Y_LOC = 0x960; - uint256 internal constant ID4_X_LOC = 0x980; - uint256 internal constant ID4_Y_LOC = 0x9a0; - uint256 internal constant CONTAINS_RECURSIVE_PROOF_LOC = 0x9c0; - uint256 internal constant RECURSIVE_PROOF_PUBLIC_INPUT_INDICES_LOC = 0x9e0; - uint256 internal constant G2X_X0_LOC = 0xa00; - uint256 internal constant G2X_X1_LOC = 0xa20; - uint256 internal constant G2X_Y0_LOC = 0xa40; - uint256 internal constant G2X_Y1_LOC = 0xa60; - - // ### PROOF DATA MEMORY LOCATIONS - uint256 internal constant W1_X_LOC = 0x1200; - uint256 internal constant W1_Y_LOC = 0x1220; - uint256 internal constant W2_X_LOC = 0x1240; - uint256 internal constant W2_Y_LOC = 0x1260; - uint256 internal constant W3_X_LOC = 0x1280; - uint256 internal constant W3_Y_LOC = 0x12a0; - uint256 internal constant W4_X_LOC = 0x12c0; - uint256 internal constant W4_Y_LOC = 0x12e0; - uint256 internal constant S_X_LOC = 0x1300; - uint256 internal constant S_Y_LOC = 0x1320; - uint256 internal constant Z_X_LOC = 0x1340; - uint256 internal constant Z_Y_LOC = 0x1360; - uint256 internal constant Z_LOOKUP_X_LOC = 0x1380; - uint256 internal constant Z_LOOKUP_Y_LOC = 0x13a0; - uint256 internal constant T1_X_LOC = 0x13c0; - uint256 internal constant T1_Y_LOC = 0x13e0; - uint256 internal constant T2_X_LOC = 0x1400; - uint256 internal constant T2_Y_LOC = 0x1420; - uint256 internal constant T3_X_LOC = 0x1440; - uint256 internal constant T3_Y_LOC = 0x1460; - uint256 internal constant T4_X_LOC = 0x1480; - uint256 internal constant T4_Y_LOC = 0x14a0; - - uint256 internal constant W1_EVAL_LOC = 0x1600; - uint256 internal constant W2_EVAL_LOC = 0x1620; - uint256 internal constant W3_EVAL_LOC = 0x1640; - uint256 internal constant W4_EVAL_LOC = 0x1660; - uint256 internal constant S_EVAL_LOC = 0x1680; - uint256 internal constant Z_EVAL_LOC = 0x16a0; - uint256 internal constant Z_LOOKUP_EVAL_LOC = 0x16c0; - uint256 internal constant Q1_EVAL_LOC = 0x16e0; - uint256 internal constant Q2_EVAL_LOC = 0x1700; - uint256 internal constant Q3_EVAL_LOC = 0x1720; - uint256 internal constant Q4_EVAL_LOC = 0x1740; - uint256 internal constant QM_EVAL_LOC = 0x1760; - uint256 internal constant QC_EVAL_LOC = 0x1780; - uint256 internal constant QARITH_EVAL_LOC = 0x17a0; - uint256 internal constant QSORT_EVAL_LOC = 0x17c0; - uint256 internal constant QELLIPTIC_EVAL_LOC = 0x17e0; - uint256 internal constant QAUX_EVAL_LOC = 0x1800; - uint256 internal constant TABLE1_EVAL_LOC = 0x1840; - uint256 internal constant TABLE2_EVAL_LOC = 0x1860; - uint256 internal constant TABLE3_EVAL_LOC = 0x1880; - uint256 internal constant TABLE4_EVAL_LOC = 0x18a0; - uint256 internal constant TABLE_TYPE_EVAL_LOC = 0x18c0; - uint256 internal constant ID1_EVAL_LOC = 0x18e0; - uint256 internal constant ID2_EVAL_LOC = 0x1900; - uint256 internal constant ID3_EVAL_LOC = 0x1920; - uint256 internal constant ID4_EVAL_LOC = 0x1940; - uint256 internal constant SIGMA1_EVAL_LOC = 0x1960; - uint256 internal constant SIGMA2_EVAL_LOC = 0x1980; - uint256 internal constant SIGMA3_EVAL_LOC = 0x19a0; - uint256 internal constant SIGMA4_EVAL_LOC = 0x19c0; - uint256 internal constant W1_OMEGA_EVAL_LOC = 0x19e0; - uint256 internal constant W2_OMEGA_EVAL_LOC = 0x2000; - uint256 internal constant W3_OMEGA_EVAL_LOC = 0x2020; - uint256 internal constant W4_OMEGA_EVAL_LOC = 0x2040; - uint256 internal constant S_OMEGA_EVAL_LOC = 0x2060; - uint256 internal constant Z_OMEGA_EVAL_LOC = 0x2080; - uint256 internal constant Z_LOOKUP_OMEGA_EVAL_LOC = 0x20a0; - uint256 internal constant TABLE1_OMEGA_EVAL_LOC = 0x20c0; - uint256 internal constant TABLE2_OMEGA_EVAL_LOC = 0x20e0; - uint256 internal constant TABLE3_OMEGA_EVAL_LOC = 0x2100; - uint256 internal constant TABLE4_OMEGA_EVAL_LOC = 0x2120; - - uint256 internal constant PI_Z_X_LOC = 0x2300; - uint256 internal constant PI_Z_Y_LOC = 0x2320; - uint256 internal constant PI_Z_OMEGA_X_LOC = 0x2340; - uint256 internal constant PI_Z_OMEGA_Y_LOC = 0x2360; - - // Used for elliptic widget. These are alias names for wire + shifted wire evaluations - uint256 internal constant X1_EVAL_LOC = W2_EVAL_LOC; - uint256 internal constant X2_EVAL_LOC = W1_OMEGA_EVAL_LOC; - uint256 internal constant X3_EVAL_LOC = W2_OMEGA_EVAL_LOC; - uint256 internal constant Y1_EVAL_LOC = W3_EVAL_LOC; - uint256 internal constant Y2_EVAL_LOC = W4_OMEGA_EVAL_LOC; - uint256 internal constant Y3_EVAL_LOC = W3_OMEGA_EVAL_LOC; - uint256 internal constant QBETA_LOC = Q3_EVAL_LOC; - uint256 internal constant QBETA_SQR_LOC = Q4_EVAL_LOC; - uint256 internal constant QSIGN_LOC = Q1_EVAL_LOC; - - // ### CHALLENGES MEMORY OFFSETS - - uint256 internal constant C_BETA_LOC = 0x2600; - uint256 internal constant C_GAMMA_LOC = 0x2620; - uint256 internal constant C_ALPHA_LOC = 0x2640; - uint256 internal constant C_ETA_LOC = 0x2660; - uint256 internal constant C_ETA_SQR_LOC = 0x2680; - uint256 internal constant C_ETA_CUBE_LOC = 0x26a0; - - uint256 internal constant C_ZETA_LOC = 0x26c0; - uint256 internal constant C_CURRENT_LOC = 0x26e0; - uint256 internal constant C_V0_LOC = 0x2700; - uint256 internal constant C_V1_LOC = 0x2720; - uint256 internal constant C_V2_LOC = 0x2740; - uint256 internal constant C_V3_LOC = 0x2760; - uint256 internal constant C_V4_LOC = 0x2780; - uint256 internal constant C_V5_LOC = 0x27a0; - uint256 internal constant C_V6_LOC = 0x27c0; - uint256 internal constant C_V7_LOC = 0x27e0; - uint256 internal constant C_V8_LOC = 0x2800; - uint256 internal constant C_V9_LOC = 0x2820; - uint256 internal constant C_V10_LOC = 0x2840; - uint256 internal constant C_V11_LOC = 0x2860; - uint256 internal constant C_V12_LOC = 0x2880; - uint256 internal constant C_V13_LOC = 0x28a0; - uint256 internal constant C_V14_LOC = 0x28c0; - uint256 internal constant C_V15_LOC = 0x28e0; - uint256 internal constant C_V16_LOC = 0x2900; - uint256 internal constant C_V17_LOC = 0x2920; - uint256 internal constant C_V18_LOC = 0x2940; - uint256 internal constant C_V19_LOC = 0x2960; - uint256 internal constant C_V20_LOC = 0x2980; - uint256 internal constant C_V21_LOC = 0x29a0; - uint256 internal constant C_V22_LOC = 0x29c0; - uint256 internal constant C_V23_LOC = 0x29e0; - uint256 internal constant C_V24_LOC = 0x2a00; - uint256 internal constant C_V25_LOC = 0x2a20; - uint256 internal constant C_V26_LOC = 0x2a40; - uint256 internal constant C_V27_LOC = 0x2a60; - uint256 internal constant C_V28_LOC = 0x2a80; - uint256 internal constant C_V29_LOC = 0x2aa0; - uint256 internal constant C_V30_LOC = 0x2ac0; - - uint256 internal constant C_U_LOC = 0x2b00; - - // ### LOCAL VARIABLES MEMORY OFFSETS - uint256 internal constant DELTA_NUMERATOR_LOC = 0x3000; - uint256 internal constant DELTA_DENOMINATOR_LOC = 0x3020; - uint256 internal constant ZETA_POW_N_LOC = 0x3040; - uint256 internal constant PUBLIC_INPUT_DELTA_LOC = 0x3060; - uint256 internal constant ZERO_POLY_LOC = 0x3080; - uint256 internal constant L_START_LOC = 0x30a0; - uint256 internal constant L_END_LOC = 0x30c0; - uint256 internal constant R_ZERO_EVAL_LOC = 0x30e0; - - uint256 internal constant PLOOKUP_DELTA_NUMERATOR_LOC = 0x3100; - uint256 internal constant PLOOKUP_DELTA_DENOMINATOR_LOC = 0x3120; - uint256 internal constant PLOOKUP_DELTA_LOC = 0x3140; - - uint256 internal constant ACCUMULATOR_X_LOC = 0x3160; - uint256 internal constant ACCUMULATOR_Y_LOC = 0x3180; - uint256 internal constant ACCUMULATOR2_X_LOC = 0x31a0; - uint256 internal constant ACCUMULATOR2_Y_LOC = 0x31c0; - uint256 internal constant PAIRING_LHS_X_LOC = 0x31e0; - uint256 internal constant PAIRING_LHS_Y_LOC = 0x3200; - uint256 internal constant PAIRING_RHS_X_LOC = 0x3220; - uint256 internal constant PAIRING_RHS_Y_LOC = 0x3240; - - // misc stuff - uint256 internal constant OMEGA_INVERSE_LOC = 0x3300; - uint256 internal constant C_ALPHA_SQR_LOC = 0x3320; - uint256 internal constant C_ALPHA_CUBE_LOC = 0x3340; - uint256 internal constant C_ALPHA_QUAD_LOC = 0x3360; - uint256 internal constant C_ALPHA_BASE_LOC = 0x3380; - - // ### RECURSION VARIABLE MEMORY LOCATIONS - uint256 internal constant RECURSIVE_P1_X_LOC = 0x3400; - uint256 internal constant RECURSIVE_P1_Y_LOC = 0x3420; - uint256 internal constant RECURSIVE_P2_X_LOC = 0x3440; - uint256 internal constant RECURSIVE_P2_Y_LOC = 0x3460; - uint256 internal constant PUBLIC_INPUTS_HASH_LOCATION = 0x3480; - - // sub-identity storage - uint256 internal constant PERMUTATION_IDENTITY = 0x3500; - uint256 internal constant PLOOKUP_IDENTITY = 0x3520; - uint256 internal constant ARITHMETIC_IDENTITY = 0x3540; - uint256 internal constant SORT_IDENTITY = 0x3560; - uint256 internal constant ELLIPTIC_IDENTITY = 0x3580; - uint256 internal constant AUX_IDENTITY = 0x35a0; - uint256 internal constant AUX_NON_NATIVE_FIELD_EVALUATION = 0x35c0; - uint256 internal constant AUX_LIMB_ACCUMULATOR_EVALUATION = 0x35e0; - uint256 internal constant AUX_RAM_CONSISTENCY_EVALUATION = 0x3600; - uint256 internal constant AUX_ROM_CONSISTENCY_EVALUATION = 0x3620; - uint256 internal constant AUX_MEMORY_EVALUATION = 0x3640; - - uint256 internal constant QUOTIENT_EVAL_LOC = 0x3660; - uint256 internal constant ZERO_POLY_INVERSE_LOC = 0x3680; - - // when hashing public inputs we use memory at NU_CHALLENGE_INPUT_LOC_A, as the hash input size is unknown at compile time - uint256 internal constant NU_CHALLENGE_INPUT_LOC_A = 0x36a0; - uint256 internal constant NU_CHALLENGE_INPUT_LOC_B = 0x36c0; - uint256 internal constant NU_CHALLENGE_INPUT_LOC_C = 0x36e0; - - bytes4 internal constant INVALID_VERIFICATION_KEY_SELECTOR = 0x7e5769bf; - bytes4 internal constant POINT_NOT_ON_CURVE_SELECTOR = 0xa3dad654; - bytes4 internal constant PUBLIC_INPUT_INVALID_BN128_G1_POINT_SELECTOR = 0xeba9f4a6; - bytes4 internal constant PUBLIC_INPUT_GE_P_SELECTOR = 0x374a972f; - bytes4 internal constant MOD_EXP_FAILURE_SELECTOR = 0xf894a7bc; - bytes4 internal constant PAIRING_PREAMBLE_FAILED_SELECTOR = 0x01882d81; - bytes4 internal constant OPENING_COMMITMENT_FAILED_SELECTOR = 0x4e719763; - bytes4 internal constant PAIRING_FAILED_SELECTOR = 0xd71fd263; - - uint256 internal constant ETA_INPUT_LENGTH = 0xc0; // W1, W2, W3 = 6 * 0x20 bytes - - // We need to hash 41 field elements when generating the NU challenge - // w1, w2, w3, w4, s, z, z_lookup, q1, q2, q3, q4, qm, qc, qarith (14) - // qsort, qelliptic, qaux, sigma1, sigma2, sigma, sigma4, (7) - // table1, table2, table3, table4, tabletype, id1, id2, id3, id4, (9) - // w1_omega, w2_omega, w3_omega, w4_omega, s_omega, z_omega, z_lookup_omega, (7) - // table1_omega, table2_omega, table3_omega, table4_omega (4) - uint256 internal constant NU_INPUT_LENGTH = 0x520; // 0x520 = 41 * 0x20 - - // There are ELEVEN G1 group elements added into the transcript in the `beta` round, that we need to skip over - // W1, W2, W3, W4, S, Z, Z_LOOKUP, T1, T2, T3, T4 - uint256 internal constant NU_CALLDATA_SKIP_LENGTH = 0x2c0; // 11 * 0x40 = 0x2c0 - - uint256 internal constant NEGATIVE_INVERSE_OF_2_MODULO_P = - 0x183227397098d014dc2822db40c0ac2e9419f4243cdcb848a1f0fac9f8000000; - uint256 internal constant LIMB_SIZE = 0x100000000000000000; // 2<<68 - uint256 internal constant SUBLIMB_SHIFT = 0x4000; // 2<<14 - - // y^2 = x^3 + ax + b - // for Grumpkin, a = 0 and b = -17. We use b in a custom gate relation that evaluates elliptic curve arithmetic - uint256 internal constant GRUMPKIN_CURVE_B_PARAMETER_NEGATED = 17; - - error INVALID_VERIFICATION_KEY(); - error POINT_NOT_ON_CURVE(); - error PUBLIC_INPUT_COUNT_INVALID(uint256 expected, uint256 actual); - error PUBLIC_INPUT_INVALID_BN128_G1_POINT(); - error PUBLIC_INPUT_GE_P(); - error MOD_EXP_FAILURE(); - error PAIRING_PREAMBLE_FAILED(); - error OPENING_COMMITMENT_FAILED(); - error PAIRING_FAILED(); - - function getVerificationKeyHash() public pure virtual returns (bytes32); - - /** - * @dev We assume that the verification key loaded by this function is constant as we only verify it on deployment - */ - function loadVerificationKey(uint256 _vk, uint256 _omegaInverseLoc) internal pure virtual; - - constructor() { - loadVerificationKey(N_LOC, OMEGA_INVERSE_LOC); - - // We verify that all of the EC points in the verification key lie on the bn128 curve. - assembly { - let q := 21888242871839275222246405745257275088696311157297823662689037894645226208583 // EC group order - - let success := 1 - - // VALIDATE Q1 - { - let x := mload(Q1_X_LOC) - let y := mload(Q1_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE Q2 - { - let x := mload(Q2_X_LOC) - let y := mload(Q2_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE Q3 - { - let x := mload(Q3_X_LOC) - let y := mload(Q3_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE Q4 - { - let x := mload(Q4_X_LOC) - let y := mload(Q4_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - mstore(0x00, x) - mstore(0x20, y) - } - // VALIDATE QM - { - let x := mload(QM_X_LOC) - let y := mload(QM_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE QC - { - let x := mload(QC_X_LOC) - let y := mload(QC_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE QARITH - { - let x := mload(QARITH_X_LOC) - let y := mload(QARITH_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE QSORT - { - let x := mload(QSORT_X_LOC) - let y := mload(QSORT_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE QELLIPTIC - { - let x := mload(QELLIPTIC_X_LOC) - let y := mload(QELLIPTIC_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE QAUX - { - let x := mload(QAUX_X_LOC) - let y := mload(QAUX_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE SIGMA1 - { - let x := mload(SIGMA1_X_LOC) - let y := mload(SIGMA1_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE SIGMA2 - { - let x := mload(SIGMA2_X_LOC) - let y := mload(SIGMA2_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE SIGMA3 - { - let x := mload(SIGMA3_X_LOC) - let y := mload(SIGMA3_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE SIGMA4 - { - let x := mload(SIGMA4_X_LOC) - let y := mload(SIGMA4_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE TABLE1 - { - let x := mload(TABLE1_X_LOC) - let y := mload(TABLE1_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE TABLE2 - { - let x := mload(TABLE2_X_LOC) - let y := mload(TABLE2_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE TABLE3 - { - let x := mload(TABLE3_X_LOC) - let y := mload(TABLE3_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE TABLE4 - { - let x := mload(TABLE4_X_LOC) - let y := mload(TABLE4_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE TABLE_TYPE - { - let x := mload(TABLE_TYPE_X_LOC) - let y := mload(TABLE_TYPE_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE ID1 - { - let x := mload(ID1_X_LOC) - let y := mload(ID1_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE ID2 - { - let x := mload(ID2_X_LOC) - let y := mload(ID2_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE ID3 - { - let x := mload(ID3_X_LOC) - let y := mload(ID3_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE ID4 - { - let x := mload(ID4_X_LOC) - let y := mload(ID4_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - - if iszero(success) { - mstore(0x0, INVALID_VERIFICATION_KEY_SELECTOR) - revert(0x00, 0x04) - } - } - } - - /** - * @notice Verify a Ultra Plonk proof - * @param _proof - The serialized proof - * @param _publicInputs - An array of the public inputs - * @return True if proof is valid, reverts otherwise - */ - function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool) { - loadVerificationKey(N_LOC, OMEGA_INVERSE_LOC); - - uint256 requiredPublicInputCount; - assembly { - requiredPublicInputCount := mload(NUM_INPUTS_LOC) - } - if (requiredPublicInputCount != _publicInputs.length) { - revert PUBLIC_INPUT_COUNT_INVALID(requiredPublicInputCount, _publicInputs.length); - } - - assembly { - let q := 21888242871839275222246405745257275088696311157297823662689037894645226208583 // EC group order - let p := 21888242871839275222246405745257275088548364400416034343698204186575808495617 // Prime field order - - /** - * LOAD PROOF FROM CALLDATA - */ - { - let data_ptr := add(calldataload(0x04), 0x24) - - mstore(W1_Y_LOC, mod(calldataload(data_ptr), q)) - mstore(W1_X_LOC, mod(calldataload(add(data_ptr, 0x20)), q)) - - mstore(W2_Y_LOC, mod(calldataload(add(data_ptr, 0x40)), q)) - mstore(W2_X_LOC, mod(calldataload(add(data_ptr, 0x60)), q)) - - mstore(W3_Y_LOC, mod(calldataload(add(data_ptr, 0x80)), q)) - mstore(W3_X_LOC, mod(calldataload(add(data_ptr, 0xa0)), q)) - - mstore(W4_Y_LOC, mod(calldataload(add(data_ptr, 0xc0)), q)) - mstore(W4_X_LOC, mod(calldataload(add(data_ptr, 0xe0)), q)) - - mstore(S_Y_LOC, mod(calldataload(add(data_ptr, 0x100)), q)) - mstore(S_X_LOC, mod(calldataload(add(data_ptr, 0x120)), q)) - mstore(Z_Y_LOC, mod(calldataload(add(data_ptr, 0x140)), q)) - mstore(Z_X_LOC, mod(calldataload(add(data_ptr, 0x160)), q)) - mstore(Z_LOOKUP_Y_LOC, mod(calldataload(add(data_ptr, 0x180)), q)) - mstore(Z_LOOKUP_X_LOC, mod(calldataload(add(data_ptr, 0x1a0)), q)) - mstore(T1_Y_LOC, mod(calldataload(add(data_ptr, 0x1c0)), q)) - mstore(T1_X_LOC, mod(calldataload(add(data_ptr, 0x1e0)), q)) - - mstore(T2_Y_LOC, mod(calldataload(add(data_ptr, 0x200)), q)) - mstore(T2_X_LOC, mod(calldataload(add(data_ptr, 0x220)), q)) - - mstore(T3_Y_LOC, mod(calldataload(add(data_ptr, 0x240)), q)) - mstore(T3_X_LOC, mod(calldataload(add(data_ptr, 0x260)), q)) - - mstore(T4_Y_LOC, mod(calldataload(add(data_ptr, 0x280)), q)) - mstore(T4_X_LOC, mod(calldataload(add(data_ptr, 0x2a0)), q)) - - mstore(W1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x2c0)), p)) - mstore(W2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x2e0)), p)) - mstore(W3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x300)), p)) - mstore(W4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x320)), p)) - mstore(S_EVAL_LOC, mod(calldataload(add(data_ptr, 0x340)), p)) - mstore(Z_EVAL_LOC, mod(calldataload(add(data_ptr, 0x360)), p)) - mstore(Z_LOOKUP_EVAL_LOC, mod(calldataload(add(data_ptr, 0x380)), p)) - mstore(Q1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x3a0)), p)) - mstore(Q2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x3c0)), p)) - mstore(Q3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x3e0)), p)) - mstore(Q4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x400)), p)) - mstore(QM_EVAL_LOC, mod(calldataload(add(data_ptr, 0x420)), p)) - mstore(QC_EVAL_LOC, mod(calldataload(add(data_ptr, 0x440)), p)) - mstore(QARITH_EVAL_LOC, mod(calldataload(add(data_ptr, 0x460)), p)) - mstore(QSORT_EVAL_LOC, mod(calldataload(add(data_ptr, 0x480)), p)) - mstore(QELLIPTIC_EVAL_LOC, mod(calldataload(add(data_ptr, 0x4a0)), p)) - mstore(QAUX_EVAL_LOC, mod(calldataload(add(data_ptr, 0x4c0)), p)) - - mstore(SIGMA1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x4e0)), p)) - mstore(SIGMA2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x500)), p)) - - mstore(SIGMA3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x520)), p)) - mstore(SIGMA4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x540)), p)) - - mstore(TABLE1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x560)), p)) - mstore(TABLE2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x580)), p)) - mstore(TABLE3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x5a0)), p)) - mstore(TABLE4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x5c0)), p)) - mstore(TABLE_TYPE_EVAL_LOC, mod(calldataload(add(data_ptr, 0x5e0)), p)) - - mstore(ID1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x600)), p)) - mstore(ID2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x620)), p)) - mstore(ID3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x640)), p)) - mstore(ID4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x660)), p)) - - mstore(W1_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x680)), p)) - mstore(W2_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x6a0)), p)) - mstore(W3_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x6c0)), p)) - mstore(W4_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x6e0)), p)) - mstore(S_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x700)), p)) - - mstore(Z_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x720)), p)) - - mstore(Z_LOOKUP_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x740)), p)) - mstore(TABLE1_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x760)), p)) - mstore(TABLE2_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x780)), p)) - mstore(TABLE3_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x7a0)), p)) - mstore(TABLE4_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x7c0)), p)) - - mstore(PI_Z_Y_LOC, mod(calldataload(add(data_ptr, 0x7e0)), q)) - mstore(PI_Z_X_LOC, mod(calldataload(add(data_ptr, 0x800)), q)) - - mstore(PI_Z_OMEGA_Y_LOC, mod(calldataload(add(data_ptr, 0x820)), q)) - mstore(PI_Z_OMEGA_X_LOC, mod(calldataload(add(data_ptr, 0x840)), q)) - } - - /** - * LOAD RECURSIVE PROOF INTO MEMORY - */ - { - if mload(CONTAINS_RECURSIVE_PROOF_LOC) { - let public_inputs_ptr := add(calldataload(0x24), 0x24) - let index_counter := add(shl(5, mload(RECURSIVE_PROOF_PUBLIC_INPUT_INDICES_LOC)), public_inputs_ptr) - - let x0 := calldataload(index_counter) - x0 := add(x0, shl(68, calldataload(add(index_counter, 0x20)))) - x0 := add(x0, shl(136, calldataload(add(index_counter, 0x40)))) - x0 := add(x0, shl(204, calldataload(add(index_counter, 0x60)))) - let y0 := calldataload(add(index_counter, 0x80)) - y0 := add(y0, shl(68, calldataload(add(index_counter, 0xa0)))) - y0 := add(y0, shl(136, calldataload(add(index_counter, 0xc0)))) - y0 := add(y0, shl(204, calldataload(add(index_counter, 0xe0)))) - let x1 := calldataload(add(index_counter, 0x100)) - x1 := add(x1, shl(68, calldataload(add(index_counter, 0x120)))) - x1 := add(x1, shl(136, calldataload(add(index_counter, 0x140)))) - x1 := add(x1, shl(204, calldataload(add(index_counter, 0x160)))) - let y1 := calldataload(add(index_counter, 0x180)) - y1 := add(y1, shl(68, calldataload(add(index_counter, 0x1a0)))) - y1 := add(y1, shl(136, calldataload(add(index_counter, 0x1c0)))) - y1 := add(y1, shl(204, calldataload(add(index_counter, 0x1e0)))) - mstore(RECURSIVE_P1_X_LOC, x0) - mstore(RECURSIVE_P1_Y_LOC, y0) - mstore(RECURSIVE_P2_X_LOC, x1) - mstore(RECURSIVE_P2_Y_LOC, y1) - - // validate these are valid bn128 G1 points - if iszero(and(and(lt(x0, q), lt(x1, q)), and(lt(y0, q), lt(y1, q)))) { - mstore(0x00, PUBLIC_INPUT_INVALID_BN128_G1_POINT_SELECTOR) - revert(0x00, 0x04) - } - } - } - - { - /** - * Generate initial challenge - */ - mstore(0x00, shl(224, mload(N_LOC))) - mstore(0x04, shl(224, mload(NUM_INPUTS_LOC))) - let challenge := keccak256(0x00, 0x08) - - /** - * Generate eta challenge - */ - mstore(PUBLIC_INPUTS_HASH_LOCATION, challenge) - // The public input location is stored at 0x24, we then add 0x24 to skip selector and the length of public inputs - let public_inputs_start := add(calldataload(0x24), 0x24) - // copy the public inputs over - let public_input_size := mul(mload(NUM_INPUTS_LOC), 0x20) - calldatacopy(add(PUBLIC_INPUTS_HASH_LOCATION, 0x20), public_inputs_start, public_input_size) - - // copy W1, W2, W3 into challenge. Each point is 0x40 bytes, so load 0xc0 = 3 * 0x40 bytes (ETA input length) - let w_start := add(calldataload(0x04), 0x24) - calldatacopy(add(add(PUBLIC_INPUTS_HASH_LOCATION, 0x20), public_input_size), w_start, ETA_INPUT_LENGTH) - - // Challenge is the old challenge + public inputs + W1, W2, W3 (0x20 + public_input_size + 0xc0) - let challenge_bytes_size := add(0x20, add(public_input_size, ETA_INPUT_LENGTH)) - - challenge := keccak256(PUBLIC_INPUTS_HASH_LOCATION, challenge_bytes_size) - { - let eta := mod(challenge, p) - mstore(C_ETA_LOC, eta) - mstore(C_ETA_SQR_LOC, mulmod(eta, eta, p)) - mstore(C_ETA_CUBE_LOC, mulmod(mload(C_ETA_SQR_LOC), eta, p)) - } - - /** - * Generate beta challenge - */ - mstore(0x00, challenge) - mstore(0x20, mload(W4_Y_LOC)) - mstore(0x40, mload(W4_X_LOC)) - mstore(0x60, mload(S_Y_LOC)) - mstore(0x80, mload(S_X_LOC)) - challenge := keccak256(0x00, 0xa0) - mstore(C_BETA_LOC, mod(challenge, p)) - - /** - * Generate gamma challenge - */ - mstore(0x00, challenge) - mstore8(0x20, 0x01) - challenge := keccak256(0x00, 0x21) - mstore(C_GAMMA_LOC, mod(challenge, p)) - - /** - * Generate alpha challenge - */ - mstore(0x00, challenge) - mstore(0x20, mload(Z_Y_LOC)) - mstore(0x40, mload(Z_X_LOC)) - mstore(0x60, mload(Z_LOOKUP_Y_LOC)) - mstore(0x80, mload(Z_LOOKUP_X_LOC)) - challenge := keccak256(0x00, 0xa0) - mstore(C_ALPHA_LOC, mod(challenge, p)) - - /** - * Compute and store some powers of alpha for future computations - */ - let alpha := mload(C_ALPHA_LOC) - mstore(C_ALPHA_SQR_LOC, mulmod(alpha, alpha, p)) - mstore(C_ALPHA_CUBE_LOC, mulmod(mload(C_ALPHA_SQR_LOC), alpha, p)) - mstore(C_ALPHA_QUAD_LOC, mulmod(mload(C_ALPHA_CUBE_LOC), alpha, p)) - mstore(C_ALPHA_BASE_LOC, alpha) - - /** - * Generate zeta challenge - */ - mstore(0x00, challenge) - mstore(0x20, mload(T1_Y_LOC)) - mstore(0x40, mload(T1_X_LOC)) - mstore(0x60, mload(T2_Y_LOC)) - mstore(0x80, mload(T2_X_LOC)) - mstore(0xa0, mload(T3_Y_LOC)) - mstore(0xc0, mload(T3_X_LOC)) - mstore(0xe0, mload(T4_Y_LOC)) - mstore(0x100, mload(T4_X_LOC)) - - challenge := keccak256(0x00, 0x120) - - mstore(C_ZETA_LOC, mod(challenge, p)) - mstore(C_CURRENT_LOC, challenge) - } - - /** - * EVALUATE FIELD OPERATIONS - */ - - /** - * COMPUTE PUBLIC INPUT DELTA - * ΔPI = ∏ᵢ∈ℓ(wᵢ + β σ(i) + γ) / ∏ᵢ∈ℓ(wᵢ + β σ'(i) + γ) - */ - { - let beta := mload(C_BETA_LOC) // β - let gamma := mload(C_GAMMA_LOC) // γ - let work_root := mload(OMEGA_LOC) // ω - let numerator_value := 1 - let denominator_value := 1 - - let p_clone := p // move p to the front of the stack - let valid_inputs := true - - // Load the starting point of the public inputs (jump over the selector and the length of public inputs [0x24]) - let public_inputs_ptr := add(calldataload(0x24), 0x24) - - // endpoint_ptr = public_inputs_ptr + num_inputs * 0x20. // every public input is 0x20 bytes - let endpoint_ptr := add(public_inputs_ptr, mul(mload(NUM_INPUTS_LOC), 0x20)) - - // root_1 = β * 0x05 - let root_1 := mulmod(beta, 0x05, p_clone) // k1.β - // root_2 = β * 0x0c - let root_2 := mulmod(beta, 0x0c, p_clone) - // @note 0x05 + 0x07 == 0x0c == external coset generator - - for {} lt(public_inputs_ptr, endpoint_ptr) { public_inputs_ptr := add(public_inputs_ptr, 0x20) } { - /** - * input = public_input[i] - * valid_inputs &= input < p - * temp = input + gamma - * numerator_value *= (β.σ(i) + wᵢ + γ) // σ(i) = 0x05.ωⁱ - * denominator_value *= (β.σ'(i) + wᵢ + γ) // σ'(i) = 0x0c.ωⁱ - * root_1 *= ω - * root_2 *= ω - */ - - let input := calldataload(public_inputs_ptr) - valid_inputs := and(valid_inputs, lt(input, p_clone)) - let temp := addmod(input, gamma, p_clone) - - numerator_value := mulmod(numerator_value, add(root_1, temp), p_clone) - denominator_value := mulmod(denominator_value, add(root_2, temp), p_clone) - - root_1 := mulmod(root_1, work_root, p_clone) - root_2 := mulmod(root_2, work_root, p_clone) - } - - // Revert if not all public inputs are field elements (i.e. < p) - if iszero(valid_inputs) { - mstore(0x00, PUBLIC_INPUT_GE_P_SELECTOR) - revert(0x00, 0x04) - } - - mstore(DELTA_NUMERATOR_LOC, numerator_value) - mstore(DELTA_DENOMINATOR_LOC, denominator_value) - } - - /** - * Compute Plookup delta factor [γ(1 + β)]^{n-k} - * k = num roots cut out of Z_H = 4 - */ - { - let delta_base := mulmod(mload(C_GAMMA_LOC), addmod(mload(C_BETA_LOC), 1, p), p) - let delta_numerator := delta_base - { - let exponent := mload(N_LOC) - let count := 1 - for {} lt(count, exponent) { count := add(count, count) } { - delta_numerator := mulmod(delta_numerator, delta_numerator, p) - } - } - mstore(PLOOKUP_DELTA_NUMERATOR_LOC, delta_numerator) - - let delta_denominator := mulmod(delta_base, delta_base, p) - delta_denominator := mulmod(delta_denominator, delta_denominator, p) - mstore(PLOOKUP_DELTA_DENOMINATOR_LOC, delta_denominator) - } - /** - * Compute lagrange poly and vanishing poly fractions - */ - { - /** - * vanishing_numerator = zeta - * ZETA_POW_N = zeta^n - * vanishing_numerator -= 1 - * accumulating_root = omega_inverse - * work_root = p - accumulating_root - * domain_inverse = domain_inverse - * vanishing_denominator = zeta + work_root - * work_root *= accumulating_root - * vanishing_denominator *= (zeta + work_root) - * work_root *= accumulating_root - * vanishing_denominator *= (zeta + work_root) - * vanishing_denominator *= (zeta + (zeta + accumulating_root)) - * work_root = omega - * lagrange_numerator = vanishing_numerator * domain_inverse - * l_start_denominator = zeta - 1 - * accumulating_root = work_root^2 - * l_end_denominator = accumulating_root^2 * work_root * zeta - 1 - * Note: l_end_denominator term contains a term \omega^5 to cut out 5 roots of unity from vanishing poly - */ - - let zeta := mload(C_ZETA_LOC) - - // compute zeta^n, where n is a power of 2 - let vanishing_numerator := zeta - { - // pow_small - let exponent := mload(N_LOC) - let count := 1 - for {} lt(count, exponent) { count := add(count, count) } { - vanishing_numerator := mulmod(vanishing_numerator, vanishing_numerator, p) - } - } - mstore(ZETA_POW_N_LOC, vanishing_numerator) - vanishing_numerator := addmod(vanishing_numerator, sub(p, 1), p) - - let accumulating_root := mload(OMEGA_INVERSE_LOC) - let work_root := sub(p, accumulating_root) - let domain_inverse := mload(DOMAIN_INVERSE_LOC) - - let vanishing_denominator := addmod(zeta, work_root, p) - work_root := mulmod(work_root, accumulating_root, p) - vanishing_denominator := mulmod(vanishing_denominator, addmod(zeta, work_root, p), p) - work_root := mulmod(work_root, accumulating_root, p) - vanishing_denominator := mulmod(vanishing_denominator, addmod(zeta, work_root, p), p) - vanishing_denominator := - mulmod(vanishing_denominator, addmod(zeta, mulmod(work_root, accumulating_root, p), p), p) - - work_root := mload(OMEGA_LOC) - - let lagrange_numerator := mulmod(vanishing_numerator, domain_inverse, p) - let l_start_denominator := addmod(zeta, sub(p, 1), p) - - accumulating_root := mulmod(work_root, work_root, p) - - let l_end_denominator := - addmod( - mulmod(mulmod(mulmod(accumulating_root, accumulating_root, p), work_root, p), zeta, p), sub(p, 1), p - ) - - /** - * Compute inversions using Montgomery's batch inversion trick - */ - let accumulator := mload(DELTA_DENOMINATOR_LOC) - let t0 := accumulator - accumulator := mulmod(accumulator, vanishing_denominator, p) - let t1 := accumulator - accumulator := mulmod(accumulator, vanishing_numerator, p) - let t2 := accumulator - accumulator := mulmod(accumulator, l_start_denominator, p) - let t3 := accumulator - accumulator := mulmod(accumulator, mload(PLOOKUP_DELTA_DENOMINATOR_LOC), p) - let t4 := accumulator - { - mstore(0, 0x20) - mstore(0x20, 0x20) - mstore(0x40, 0x20) - mstore(0x60, mulmod(accumulator, l_end_denominator, p)) - mstore(0x80, sub(p, 2)) - mstore(0xa0, p) - if iszero(staticcall(gas(), 0x05, 0x00, 0xc0, 0x00, 0x20)) { - mstore(0x0, MOD_EXP_FAILURE_SELECTOR) - revert(0x00, 0x04) - } - accumulator := mload(0x00) - } - - t4 := mulmod(accumulator, t4, p) - accumulator := mulmod(accumulator, l_end_denominator, p) - - t3 := mulmod(accumulator, t3, p) - accumulator := mulmod(accumulator, mload(PLOOKUP_DELTA_DENOMINATOR_LOC), p) - - t2 := mulmod(accumulator, t2, p) - accumulator := mulmod(accumulator, l_start_denominator, p) - - t1 := mulmod(accumulator, t1, p) - accumulator := mulmod(accumulator, vanishing_numerator, p) - - t0 := mulmod(accumulator, t0, p) - accumulator := mulmod(accumulator, vanishing_denominator, p) - - accumulator := mulmod(mulmod(accumulator, accumulator, p), mload(DELTA_DENOMINATOR_LOC), p) - - mstore(PUBLIC_INPUT_DELTA_LOC, mulmod(mload(DELTA_NUMERATOR_LOC), accumulator, p)) - mstore(ZERO_POLY_LOC, mulmod(vanishing_numerator, t0, p)) - mstore(ZERO_POLY_INVERSE_LOC, mulmod(vanishing_denominator, t1, p)) - mstore(L_START_LOC, mulmod(lagrange_numerator, t2, p)) - mstore(PLOOKUP_DELTA_LOC, mulmod(mload(PLOOKUP_DELTA_NUMERATOR_LOC), t3, p)) - mstore(L_END_LOC, mulmod(lagrange_numerator, t4, p)) - } - - /** - * UltraPlonk Widget Ordering: - * - * 1. Permutation widget - * 2. Plookup widget - * 3. Arithmetic widget - * 4. Fixed base widget (?) - * 5. GenPermSort widget - * 6. Elliptic widget - * 7. Auxiliary widget - */ - - /** - * COMPUTE PERMUTATION WIDGET EVALUATION - */ - { - let alpha := mload(C_ALPHA_LOC) - let beta := mload(C_BETA_LOC) - let gamma := mload(C_GAMMA_LOC) - - /** - * t1 = (W1 + gamma + beta * ID1) * (W2 + gamma + beta * ID2) - * t2 = (W3 + gamma + beta * ID3) * (W4 + gamma + beta * ID4) - * result = alpha_base * z_eval * t1 * t2 - * t1 = (W1 + gamma + beta * sigma_1_eval) * (W2 + gamma + beta * sigma_2_eval) - * t2 = (W2 + gamma + beta * sigma_3_eval) * (W3 + gamma + beta * sigma_4_eval) - * result -= (alpha_base * z_omega_eval * t1 * t2) - */ - let t1 := - mulmod( - add(add(mload(W1_EVAL_LOC), gamma), mulmod(beta, mload(ID1_EVAL_LOC), p)), - add(add(mload(W2_EVAL_LOC), gamma), mulmod(beta, mload(ID2_EVAL_LOC), p)), - p - ) - let t2 := - mulmod( - add(add(mload(W3_EVAL_LOC), gamma), mulmod(beta, mload(ID3_EVAL_LOC), p)), - add(add(mload(W4_EVAL_LOC), gamma), mulmod(beta, mload(ID4_EVAL_LOC), p)), - p - ) - let result := mulmod(mload(C_ALPHA_BASE_LOC), mulmod(mload(Z_EVAL_LOC), mulmod(t1, t2, p), p), p) - t1 := - mulmod( - add(add(mload(W1_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA1_EVAL_LOC), p)), - add(add(mload(W2_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA2_EVAL_LOC), p)), - p - ) - t2 := - mulmod( - add(add(mload(W3_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA3_EVAL_LOC), p)), - add(add(mload(W4_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA4_EVAL_LOC), p)), - p - ) - result := - addmod( - result, - sub(p, mulmod(mload(C_ALPHA_BASE_LOC), mulmod(mload(Z_OMEGA_EVAL_LOC), mulmod(t1, t2, p), p), p)), - p - ) - - /** - * alpha_base *= alpha - * result += alpha_base . (L_{n-k}(ʓ) . (z(ʓ.ω) - ∆_{PI})) - * alpha_base *= alpha - * result += alpha_base . (L_1(ʓ)(Z(ʓ) - 1)) - * alpha_Base *= alpha - */ - mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p)) - result := - addmod( - result, - mulmod( - mload(C_ALPHA_BASE_LOC), - mulmod( - mload(L_END_LOC), - addmod(mload(Z_OMEGA_EVAL_LOC), sub(p, mload(PUBLIC_INPUT_DELTA_LOC)), p), - p - ), - p - ), - p - ) - mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p)) - mstore( - PERMUTATION_IDENTITY, - addmod( - result, - mulmod( - mload(C_ALPHA_BASE_LOC), - mulmod(mload(L_START_LOC), addmod(mload(Z_EVAL_LOC), sub(p, 1), p), p), - p - ), - p - ) - ) - mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p)) - } - - /** - * COMPUTE PLOOKUP WIDGET EVALUATION - */ - { - /** - * Goal: f = (w1(z) + q2.w1(zω)) + η(w2(z) + qm.w2(zω)) + η²(w3(z) + qc.w_3(zω)) + q3(z).η³ - * f = η.q3(z) - * f += (w3(z) + qc.w_3(zω)) - * f *= η - * f += (w2(z) + qm.w2(zω)) - * f *= η - * f += (w1(z) + q2.w1(zω)) - */ - let f := mulmod(mload(C_ETA_LOC), mload(Q3_EVAL_LOC), p) - f := - addmod(f, addmod(mload(W3_EVAL_LOC), mulmod(mload(QC_EVAL_LOC), mload(W3_OMEGA_EVAL_LOC), p), p), p) - f := mulmod(f, mload(C_ETA_LOC), p) - f := - addmod(f, addmod(mload(W2_EVAL_LOC), mulmod(mload(QM_EVAL_LOC), mload(W2_OMEGA_EVAL_LOC), p), p), p) - f := mulmod(f, mload(C_ETA_LOC), p) - f := - addmod(f, addmod(mload(W1_EVAL_LOC), mulmod(mload(Q2_EVAL_LOC), mload(W1_OMEGA_EVAL_LOC), p), p), p) - - // t(z) = table4(z).η³ + table3(z).η² + table2(z).η + table1(z) - let t := - addmod( - addmod( - addmod( - mulmod(mload(TABLE4_EVAL_LOC), mload(C_ETA_CUBE_LOC), p), - mulmod(mload(TABLE3_EVAL_LOC), mload(C_ETA_SQR_LOC), p), - p - ), - mulmod(mload(TABLE2_EVAL_LOC), mload(C_ETA_LOC), p), - p - ), - mload(TABLE1_EVAL_LOC), - p - ) - - // t(zw) = table4(zw).η³ + table3(zw).η² + table2(zw).η + table1(zw) - let t_omega := - addmod( - addmod( - addmod( - mulmod(mload(TABLE4_OMEGA_EVAL_LOC), mload(C_ETA_CUBE_LOC), p), - mulmod(mload(TABLE3_OMEGA_EVAL_LOC), mload(C_ETA_SQR_LOC), p), - p - ), - mulmod(mload(TABLE2_OMEGA_EVAL_LOC), mload(C_ETA_LOC), p), - p - ), - mload(TABLE1_OMEGA_EVAL_LOC), - p - ) - - /** - * Goal: numerator = (TABLE_TYPE_EVAL * f(z) + γ) * (t(z) + βt(zω) + γ(β + 1)) * (β + 1) - * gamma_beta_constant = γ(β + 1) - * numerator = f * TABLE_TYPE_EVAL + gamma - * temp0 = t(z) + t(zω) * β + gamma_beta_constant - * numerator *= temp0 - * numerator *= (β + 1) - * temp0 = alpha * l_1 - * numerator += temp0 - * numerator *= z_lookup(z) - * numerator -= temp0 - */ - let gamma_beta_constant := mulmod(mload(C_GAMMA_LOC), addmod(mload(C_BETA_LOC), 1, p), p) - let numerator := addmod(mulmod(f, mload(TABLE_TYPE_EVAL_LOC), p), mload(C_GAMMA_LOC), p) - let temp0 := addmod(addmod(t, mulmod(t_omega, mload(C_BETA_LOC), p), p), gamma_beta_constant, p) - numerator := mulmod(numerator, temp0, p) - numerator := mulmod(numerator, addmod(mload(C_BETA_LOC), 1, p), p) - temp0 := mulmod(mload(C_ALPHA_LOC), mload(L_START_LOC), p) - numerator := addmod(numerator, temp0, p) - numerator := mulmod(numerator, mload(Z_LOOKUP_EVAL_LOC), p) - numerator := addmod(numerator, sub(p, temp0), p) - - /** - * Goal: denominator = z_lookup(zω)*[s(z) + βs(zω) + γ(1 + β)] - [z_lookup(zω) - [γ(1 + β)]^{n-k}]*α²L_end(z) - * note: delta_factor = [γ(1 + β)]^{n-k} - * denominator = s(z) + βs(zω) + γ(β + 1) - * temp1 = α²L_end(z) - * denominator -= temp1 - * denominator *= z_lookup(zω) - * denominator += temp1 * delta_factor - * PLOOKUP_IDENTITY = (numerator - denominator).alpha_base - * alpha_base *= alpha^3 - */ - let denominator := - addmod( - addmod(mload(S_EVAL_LOC), mulmod(mload(S_OMEGA_EVAL_LOC), mload(C_BETA_LOC), p), p), - gamma_beta_constant, - p - ) - let temp1 := mulmod(mload(C_ALPHA_SQR_LOC), mload(L_END_LOC), p) - denominator := addmod(denominator, sub(p, temp1), p) - denominator := mulmod(denominator, mload(Z_LOOKUP_OMEGA_EVAL_LOC), p) - denominator := addmod(denominator, mulmod(temp1, mload(PLOOKUP_DELTA_LOC), p), p) - - mstore(PLOOKUP_IDENTITY, mulmod(addmod(numerator, sub(p, denominator), p), mload(C_ALPHA_BASE_LOC), p)) - - // update alpha - mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_CUBE_LOC), p)) - } - - /** - * COMPUTE ARITHMETIC WIDGET EVALUATION - */ - { - /** - * The basic arithmetic gate identity in standard plonk is as follows. - * (w_1 . w_2 . q_m) + (w_1 . q_1) + (w_2 . q_2) + (w_3 . q_3) + (w_4 . q_4) + q_c = 0 - * However, for Ultraplonk, we extend this to support "passing" wires between rows (shown without alpha scaling below): - * q_arith * ( ( (-1/2) * (q_arith - 3) * q_m * w_1 * w_2 + q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c ) + - * (q_arith - 1)*( α * (q_arith - 2) * (w_1 + w_4 - w_1_omega + q_m) + w_4_omega) ) = 0 - * - * This formula results in several cases depending on q_arith: - * 1. q_arith == 0: Arithmetic gate is completely disabled - * - * 2. q_arith == 1: Everything in the minigate on the right is disabled. The equation is just a standard plonk equation - * with extra wires: q_m * w_1 * w_2 + q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c = 0 - * - * 3. q_arith == 2: The (w_1 + w_4 - ...) term is disabled. THe equation is: - * (1/2) * q_m * w_1 * w_2 + q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c + w_4_omega = 0 - * It allows defining w_4 at next index (w_4_omega) in terms of current wire values - * - * 4. q_arith == 3: The product of w_1 and w_2 is disabled, but a mini addition gate is enabled. α allows us to split - * the equation into two: - * - * q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c + 2 * w_4_omega = 0 - * and - * w_1 + w_4 - w_1_omega + q_m = 0 (we are reusing q_m here) - * - * 5. q_arith > 3: The product of w_1 and w_2 is scaled by (q_arith - 3), while the w_4_omega term is scaled by (q_arith - 1). - * The equation can be split into two: - * - * (q_arith - 3)* q_m * w_1 * w_ 2 + q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c + (q_arith - 1) * w_4_omega = 0 - * and - * w_1 + w_4 - w_1_omega + q_m = 0 - * - * The problem that q_m is used both in both equations can be dealt with by appropriately changing selector values at - * the next gate. Then we can treat (q_arith - 1) as a simulated q_6 selector and scale q_m to handle (q_arith - 3) at - * product. - */ - - let w1q1 := mulmod(mload(W1_EVAL_LOC), mload(Q1_EVAL_LOC), p) - let w2q2 := mulmod(mload(W2_EVAL_LOC), mload(Q2_EVAL_LOC), p) - let w3q3 := mulmod(mload(W3_EVAL_LOC), mload(Q3_EVAL_LOC), p) - let w4q3 := mulmod(mload(W4_EVAL_LOC), mload(Q4_EVAL_LOC), p) - - // @todo - Add a explicit test that hits QARITH == 3 - // w1w2qm := (w_1 . w_2 . q_m . (QARITH_EVAL_LOC - 3)) / 2 - let w1w2qm := - mulmod( - mulmod( - mulmod(mulmod(mload(W1_EVAL_LOC), mload(W2_EVAL_LOC), p), mload(QM_EVAL_LOC), p), - addmod(mload(QARITH_EVAL_LOC), sub(p, 3), p), - p - ), - NEGATIVE_INVERSE_OF_2_MODULO_P, - p - ) - - // (w_1 . w_2 . q_m . (q_arith - 3)) / -2) + (w_1 . q_1) + (w_2 . q_2) + (w_3 . q_3) + (w_4 . q_4) + q_c - let identity := - addmod( - mload(QC_EVAL_LOC), addmod(w4q3, addmod(w3q3, addmod(w2q2, addmod(w1q1, w1w2qm, p), p), p), p), p - ) - - // if q_arith == 3 we evaluate an additional mini addition gate (on top of the regular one), where: - // w_1 + w_4 - w_1_omega + q_m = 0 - // we use this gate to save an addition gate when adding or subtracting non-native field elements - // α * (q_arith - 2) * (w_1 + w_4 - w_1_omega + q_m) - let extra_small_addition_gate_identity := - mulmod( - mload(C_ALPHA_LOC), - mulmod( - addmod(mload(QARITH_EVAL_LOC), sub(p, 2), p), - addmod( - mload(QM_EVAL_LOC), - addmod( - sub(p, mload(W1_OMEGA_EVAL_LOC)), addmod(mload(W1_EVAL_LOC), mload(W4_EVAL_LOC), p), p - ), - p - ), - p - ), - p - ) - - // if q_arith == 2 OR q_arith == 3 we add the 4th wire of the NEXT gate into the arithmetic identity - // N.B. if q_arith > 2, this wire value will be scaled by (q_arith - 1) relative to the other gate wires! - // alpha_base * q_arith * (identity + (q_arith - 1) * (w_4_omega + extra_small_addition_gate_identity)) - mstore( - ARITHMETIC_IDENTITY, - mulmod( - mload(C_ALPHA_BASE_LOC), - mulmod( - mload(QARITH_EVAL_LOC), - addmod( - identity, - mulmod( - addmod(mload(QARITH_EVAL_LOC), sub(p, 1), p), - addmod(mload(W4_OMEGA_EVAL_LOC), extra_small_addition_gate_identity, p), - p - ), - p - ), - p - ), - p - ) - ) - - // update alpha - mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_SQR_LOC), p)) - } - - /** - * COMPUTE GENPERMSORT WIDGET EVALUATION - */ - { - /** - * D1 = (w2 - w1) - * D2 = (w3 - w2) - * D3 = (w4 - w3) - * D4 = (w1_omega - w4) - * - * α_a = alpha_base - * α_b = alpha_base * α - * α_c = alpha_base * α^2 - * α_d = alpha_base * α^3 - * - * range_accumulator = ( - * D1(D1 - 1)(D1 - 2)(D1 - 3).α_a + - * D2(D2 - 1)(D2 - 2)(D2 - 3).α_b + - * D3(D3 - 1)(D3 - 2)(D3 - 3).α_c + - * D4(D4 - 1)(D4 - 2)(D4 - 3).α_d + - * ) . q_sort - */ - let minus_two := sub(p, 2) - let minus_three := sub(p, 3) - let d1 := addmod(mload(W2_EVAL_LOC), sub(p, mload(W1_EVAL_LOC)), p) - let d2 := addmod(mload(W3_EVAL_LOC), sub(p, mload(W2_EVAL_LOC)), p) - let d3 := addmod(mload(W4_EVAL_LOC), sub(p, mload(W3_EVAL_LOC)), p) - let d4 := addmod(mload(W1_OMEGA_EVAL_LOC), sub(p, mload(W4_EVAL_LOC)), p) - - let range_accumulator := - mulmod( - mulmod( - mulmod(addmod(mulmod(d1, d1, p), sub(p, d1), p), addmod(d1, minus_two, p), p), - addmod(d1, minus_three, p), - p - ), - mload(C_ALPHA_BASE_LOC), - p - ) - range_accumulator := - addmod( - range_accumulator, - mulmod( - mulmod( - mulmod(addmod(mulmod(d2, d2, p), sub(p, d2), p), addmod(d2, minus_two, p), p), - addmod(d2, minus_three, p), - p - ), - mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p), - p - ), - p - ) - range_accumulator := - addmod( - range_accumulator, - mulmod( - mulmod( - mulmod(addmod(mulmod(d3, d3, p), sub(p, d3), p), addmod(d3, minus_two, p), p), - addmod(d3, minus_three, p), - p - ), - mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_SQR_LOC), p), - p - ), - p - ) - range_accumulator := - addmod( - range_accumulator, - mulmod( - mulmod( - mulmod(addmod(mulmod(d4, d4, p), sub(p, d4), p), addmod(d4, minus_two, p), p), - addmod(d4, minus_three, p), - p - ), - mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_CUBE_LOC), p), - p - ), - p - ) - range_accumulator := mulmod(range_accumulator, mload(QSORT_EVAL_LOC), p) - - mstore(SORT_IDENTITY, range_accumulator) - - // update alpha - mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_QUAD_LOC), p)) - } - - /** - * COMPUTE ELLIPTIC WIDGET EVALUATION - */ - { - /** - * endo_term = (-x_2) * x_1 * (x_3 * 2 + x_1) * q_beta - * endo_sqr_term = x_2^2 - * endo_sqr_term *= (x_3 - x_1) - * endo_sqr_term *= q_beta^2 - * leftovers = x_2^2 - * leftovers *= x_2 - * leftovers += x_1^2 * (x_3 + x_1) @follow-up Invalid comment in BB widget - * leftovers -= (y_2^2 + y_1^2) - * sign_term = y_2 * y_1 - * sign_term += sign_term - * sign_term *= q_sign - */ - // q_elliptic * (x3 + x2 + x1)(x2 - x1)(x2 - x1) - y2^2 - y1^2 + 2(y2y1)*q_sign = 0 - let x_diff := addmod(mload(X2_EVAL_LOC), sub(p, mload(X1_EVAL_LOC)), p) - let y2_sqr := mulmod(mload(Y2_EVAL_LOC), mload(Y2_EVAL_LOC), p) - let y1_sqr := mulmod(mload(Y1_EVAL_LOC), mload(Y1_EVAL_LOC), p) - let y1y2 := mulmod(mulmod(mload(Y1_EVAL_LOC), mload(Y2_EVAL_LOC), p), mload(QSIGN_LOC), p) - - let x_add_identity := - addmod( - mulmod( - addmod(mload(X3_EVAL_LOC), addmod(mload(X2_EVAL_LOC), mload(X1_EVAL_LOC), p), p), - mulmod(x_diff, x_diff, p), - p - ), - addmod( - sub( - p, - addmod(y2_sqr, y1_sqr, p) - ), - addmod(y1y2, y1y2, p), - p - ), - p - ) - x_add_identity := - mulmod( - mulmod( - x_add_identity, - addmod( - 1, - sub(p, mload(QM_EVAL_LOC)), - p - ), - p - ), - mload(C_ALPHA_BASE_LOC), - p - ) - - // q_elliptic * (x3 + x2 + x1)(x2 - x1)(x2 - x1) - y2^2 - y1^2 + 2(y2y1)*q_sign = 0 - let y1_plus_y3 := addmod( - mload(Y1_EVAL_LOC), - mload(Y3_EVAL_LOC), - p - ) - let y_diff := addmod(mulmod(mload(Y2_EVAL_LOC), mload(QSIGN_LOC), p), sub(p, mload(Y1_EVAL_LOC)), p) - let y_add_identity := - addmod( - mulmod(y1_plus_y3, x_diff, p), - mulmod(addmod(mload(X3_EVAL_LOC), sub(p, mload(X1_EVAL_LOC)), p), y_diff, p), - p - ) - y_add_identity := - mulmod( - mulmod(y_add_identity, addmod(1, sub(p, mload(QM_EVAL_LOC)), p), p), - mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p), - p - ) - - // ELLIPTIC_IDENTITY = (x_identity + y_identity) * Q_ELLIPTIC_EVAL - mstore( - ELLIPTIC_IDENTITY, mulmod(addmod(x_add_identity, y_add_identity, p), mload(QELLIPTIC_EVAL_LOC), p) - ) - } - { - /** - * x_pow_4 = (y_1_sqr - curve_b) * x_1; - * y_1_sqr_mul_4 = y_1_sqr + y_1_sqr; - * y_1_sqr_mul_4 += y_1_sqr_mul_4; - * x_1_pow_4_mul_9 = x_pow_4; - * x_1_pow_4_mul_9 += x_1_pow_4_mul_9; - * x_1_pow_4_mul_9 += x_1_pow_4_mul_9; - * x_1_pow_4_mul_9 += x_1_pow_4_mul_9; - * x_1_pow_4_mul_9 += x_pow_4; - * x_1_sqr_mul_3 = x_1_sqr + x_1_sqr + x_1_sqr; - * x_double_identity = (x_3 + x_1 + x_1) * y_1_sqr_mul_4 - x_1_pow_4_mul_9; - * y_double_identity = x_1_sqr_mul_3 * (x_1 - x_3) - (y_1 + y_1) * (y_1 + y_3); - */ - // (x3 + x1 + x1) (4y1*y1) - 9 * x1 * x1 * x1 * x1 = 0 - let x1_sqr := mulmod(mload(X1_EVAL_LOC), mload(X1_EVAL_LOC), p) - let y1_sqr := mulmod(mload(Y1_EVAL_LOC), mload(Y1_EVAL_LOC), p) - let x_pow_4 := mulmod(addmod(y1_sqr, GRUMPKIN_CURVE_B_PARAMETER_NEGATED, p), mload(X1_EVAL_LOC), p) - let y1_sqr_mul_4 := mulmod(y1_sqr, 4, p) - let x1_pow_4_mul_9 := mulmod(x_pow_4, 9, p) - let x1_sqr_mul_3 := mulmod(x1_sqr, 3, p) - let x_double_identity := - addmod( - mulmod( - addmod(mload(X3_EVAL_LOC), addmod(mload(X1_EVAL_LOC), mload(X1_EVAL_LOC), p), p), - y1_sqr_mul_4, - p - ), - sub(p, x1_pow_4_mul_9), - p - ) - // (y1 + y1) (2y1) - (3 * x1 * x1)(x1 - x3) = 0 - let y_double_identity := - addmod( - mulmod(x1_sqr_mul_3, addmod(mload(X1_EVAL_LOC), sub(p, mload(X3_EVAL_LOC)), p), p), - sub( - p, - mulmod( - addmod(mload(Y1_EVAL_LOC), mload(Y1_EVAL_LOC), p), - addmod(mload(Y1_EVAL_LOC), mload(Y3_EVAL_LOC), p), - p - ) - ), - p - ) - x_double_identity := mulmod(x_double_identity, mload(C_ALPHA_BASE_LOC), p) - y_double_identity := - mulmod(y_double_identity, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p), p) - x_double_identity := mulmod(x_double_identity, mload(QM_EVAL_LOC), p) - y_double_identity := mulmod(y_double_identity, mload(QM_EVAL_LOC), p) - // ELLIPTIC_IDENTITY += (x_double_identity + y_double_identity) * Q_DOUBLE_EVAL - mstore( - ELLIPTIC_IDENTITY, - addmod( - mload(ELLIPTIC_IDENTITY), - mulmod(addmod(x_double_identity, y_double_identity, p), mload(QELLIPTIC_EVAL_LOC), p), - p - ) - ) - - // update alpha - mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_QUAD_LOC), p)) - } - - /** - * COMPUTE AUXILIARY WIDGET EVALUATION - */ - { - { - /** - * Non native field arithmetic gate 2 - * _ _ - * / _ _ _ 14 \ - * q_2 . q_4 | (w_1 . w_2) + (w_1 . w_2) + (w_1 . w_4 + w_2 . w_3 - w_3) . 2 - w_3 - w_4 | - * \_ _/ - * - * limb_subproduct = w_1 . w_2_omega + w_1_omega . w_2 - * non_native_field_gate_2 = w_1 * w_4 + w_4 * w_3 - w_3_omega - * non_native_field_gate_2 = non_native_field_gate_2 * limb_size - * non_native_field_gate_2 -= w_4_omega - * non_native_field_gate_2 += limb_subproduct - * non_native_field_gate_2 *= q_4 - * limb_subproduct *= limb_size - * limb_subproduct += w_1_omega * w_2_omega - * non_native_field_gate_1 = (limb_subproduct + w_3 + w_4) * q_3 - * non_native_field_gate_3 = (limb_subproduct + w_4 - (w_3_omega + w_4_omega)) * q_m - * non_native_field_identity = (non_native_field_gate_1 + non_native_field_gate_2 + non_native_field_gate_3) * q_2 - */ - - let limb_subproduct := - addmod( - mulmod(mload(W1_EVAL_LOC), mload(W2_OMEGA_EVAL_LOC), p), - mulmod(mload(W1_OMEGA_EVAL_LOC), mload(W2_EVAL_LOC), p), - p - ) - - let non_native_field_gate_2 := - addmod( - addmod( - mulmod(mload(W1_EVAL_LOC), mload(W4_EVAL_LOC), p), - mulmod(mload(W2_EVAL_LOC), mload(W3_EVAL_LOC), p), - p - ), - sub(p, mload(W3_OMEGA_EVAL_LOC)), - p - ) - non_native_field_gate_2 := mulmod(non_native_field_gate_2, LIMB_SIZE, p) - non_native_field_gate_2 := addmod(non_native_field_gate_2, sub(p, mload(W4_OMEGA_EVAL_LOC)), p) - non_native_field_gate_2 := addmod(non_native_field_gate_2, limb_subproduct, p) - non_native_field_gate_2 := mulmod(non_native_field_gate_2, mload(Q4_EVAL_LOC), p) - limb_subproduct := mulmod(limb_subproduct, LIMB_SIZE, p) - limb_subproduct := - addmod(limb_subproduct, mulmod(mload(W1_OMEGA_EVAL_LOC), mload(W2_OMEGA_EVAL_LOC), p), p) - let non_native_field_gate_1 := - mulmod( - addmod(limb_subproduct, sub(p, addmod(mload(W3_EVAL_LOC), mload(W4_EVAL_LOC), p)), p), - mload(Q3_EVAL_LOC), - p - ) - let non_native_field_gate_3 := - mulmod( - addmod( - addmod(limb_subproduct, mload(W4_EVAL_LOC), p), - sub(p, addmod(mload(W3_OMEGA_EVAL_LOC), mload(W4_OMEGA_EVAL_LOC), p)), - p - ), - mload(QM_EVAL_LOC), - p - ) - let non_native_field_identity := - mulmod( - addmod(addmod(non_native_field_gate_1, non_native_field_gate_2, p), non_native_field_gate_3, p), - mload(Q2_EVAL_LOC), - p - ) - - mstore(AUX_NON_NATIVE_FIELD_EVALUATION, non_native_field_identity) - } - - { - /** - * limb_accumulator_1 = w_2_omega; - * limb_accumulator_1 *= SUBLIMB_SHIFT; - * limb_accumulator_1 += w_1_omega; - * limb_accumulator_1 *= SUBLIMB_SHIFT; - * limb_accumulator_1 += w_3; - * limb_accumulator_1 *= SUBLIMB_SHIFT; - * limb_accumulator_1 += w_2; - * limb_accumulator_1 *= SUBLIMB_SHIFT; - * limb_accumulator_1 += w_1; - * limb_accumulator_1 -= w_4; - * limb_accumulator_1 *= q_4; - */ - let limb_accumulator_1 := mulmod(mload(W2_OMEGA_EVAL_LOC), SUBLIMB_SHIFT, p) - limb_accumulator_1 := addmod(limb_accumulator_1, mload(W1_OMEGA_EVAL_LOC), p) - limb_accumulator_1 := mulmod(limb_accumulator_1, SUBLIMB_SHIFT, p) - limb_accumulator_1 := addmod(limb_accumulator_1, mload(W3_EVAL_LOC), p) - limb_accumulator_1 := mulmod(limb_accumulator_1, SUBLIMB_SHIFT, p) - limb_accumulator_1 := addmod(limb_accumulator_1, mload(W2_EVAL_LOC), p) - limb_accumulator_1 := mulmod(limb_accumulator_1, SUBLIMB_SHIFT, p) - limb_accumulator_1 := addmod(limb_accumulator_1, mload(W1_EVAL_LOC), p) - limb_accumulator_1 := addmod(limb_accumulator_1, sub(p, mload(W4_EVAL_LOC)), p) - limb_accumulator_1 := mulmod(limb_accumulator_1, mload(Q4_EVAL_LOC), p) - - /** - * limb_accumulator_2 = w_3_omega; - * limb_accumulator_2 *= SUBLIMB_SHIFT; - * limb_accumulator_2 += w_2_omega; - * limb_accumulator_2 *= SUBLIMB_SHIFT; - * limb_accumulator_2 += w_1_omega; - * limb_accumulator_2 *= SUBLIMB_SHIFT; - * limb_accumulator_2 += w_4; - * limb_accumulator_2 *= SUBLIMB_SHIFT; - * limb_accumulator_2 += w_3; - * limb_accumulator_2 -= w_4_omega; - * limb_accumulator_2 *= q_m; - */ - let limb_accumulator_2 := mulmod(mload(W3_OMEGA_EVAL_LOC), SUBLIMB_SHIFT, p) - limb_accumulator_2 := addmod(limb_accumulator_2, mload(W2_OMEGA_EVAL_LOC), p) - limb_accumulator_2 := mulmod(limb_accumulator_2, SUBLIMB_SHIFT, p) - limb_accumulator_2 := addmod(limb_accumulator_2, mload(W1_OMEGA_EVAL_LOC), p) - limb_accumulator_2 := mulmod(limb_accumulator_2, SUBLIMB_SHIFT, p) - limb_accumulator_2 := addmod(limb_accumulator_2, mload(W4_EVAL_LOC), p) - limb_accumulator_2 := mulmod(limb_accumulator_2, SUBLIMB_SHIFT, p) - limb_accumulator_2 := addmod(limb_accumulator_2, mload(W3_EVAL_LOC), p) - limb_accumulator_2 := addmod(limb_accumulator_2, sub(p, mload(W4_OMEGA_EVAL_LOC)), p) - limb_accumulator_2 := mulmod(limb_accumulator_2, mload(QM_EVAL_LOC), p) - - mstore( - AUX_LIMB_ACCUMULATOR_EVALUATION, - mulmod(addmod(limb_accumulator_1, limb_accumulator_2, p), mload(Q3_EVAL_LOC), p) - ) - } - - { - /** - * memory_record_check = w_3; - * memory_record_check *= eta; - * memory_record_check += w_2; - * memory_record_check *= eta; - * memory_record_check += w_1; - * memory_record_check *= eta; - * memory_record_check += q_c; - * - * partial_record_check = memory_record_check; - * - * memory_record_check -= w_4; - */ - - let memory_record_check := mulmod(mload(W3_EVAL_LOC), mload(C_ETA_LOC), p) - memory_record_check := addmod(memory_record_check, mload(W2_EVAL_LOC), p) - memory_record_check := mulmod(memory_record_check, mload(C_ETA_LOC), p) - memory_record_check := addmod(memory_record_check, mload(W1_EVAL_LOC), p) - memory_record_check := mulmod(memory_record_check, mload(C_ETA_LOC), p) - memory_record_check := addmod(memory_record_check, mload(QC_EVAL_LOC), p) - - let partial_record_check := memory_record_check - memory_record_check := addmod(memory_record_check, sub(p, mload(W4_EVAL_LOC)), p) - - mstore(AUX_MEMORY_EVALUATION, memory_record_check) - - // index_delta = w_1_omega - w_1 - let index_delta := addmod(mload(W1_OMEGA_EVAL_LOC), sub(p, mload(W1_EVAL_LOC)), p) - // record_delta = w_4_omega - w_4 - let record_delta := addmod(mload(W4_OMEGA_EVAL_LOC), sub(p, mload(W4_EVAL_LOC)), p) - // index_is_monotonically_increasing = index_delta * (index_delta - 1) - let index_is_monotonically_increasing := mulmod(index_delta, addmod(index_delta, sub(p, 1), p), p) - - // adjacent_values_match_if_adjacent_indices_match = record_delta * (1 - index_delta) - let adjacent_values_match_if_adjacent_indices_match := - mulmod(record_delta, addmod(1, sub(p, index_delta), p), p) - - // AUX_ROM_CONSISTENCY_EVALUATION = ((adjacent_values_match_if_adjacent_indices_match * alpha) + index_is_monotonically_increasing) * alpha + partial_record_check - mstore( - AUX_ROM_CONSISTENCY_EVALUATION, - addmod( - mulmod( - addmod( - mulmod(adjacent_values_match_if_adjacent_indices_match, mload(C_ALPHA_LOC), p), - index_is_monotonically_increasing, - p - ), - mload(C_ALPHA_LOC), - p - ), - memory_record_check, - p - ) - ) - - { - /** - * next_gate_access_type = w_3_omega; - * next_gate_access_type *= eta; - * next_gate_access_type += w_2_omega; - * next_gate_access_type *= eta; - * next_gate_access_type += w_1_omega; - * next_gate_access_type *= eta; - * next_gate_access_type = w_4_omega - next_gate_access_type; - */ - let next_gate_access_type := mulmod(mload(W3_OMEGA_EVAL_LOC), mload(C_ETA_LOC), p) - next_gate_access_type := addmod(next_gate_access_type, mload(W2_OMEGA_EVAL_LOC), p) - next_gate_access_type := mulmod(next_gate_access_type, mload(C_ETA_LOC), p) - next_gate_access_type := addmod(next_gate_access_type, mload(W1_OMEGA_EVAL_LOC), p) - next_gate_access_type := mulmod(next_gate_access_type, mload(C_ETA_LOC), p) - next_gate_access_type := addmod(mload(W4_OMEGA_EVAL_LOC), sub(p, next_gate_access_type), p) - - // value_delta = w_3_omega - w_3 - let value_delta := addmod(mload(W3_OMEGA_EVAL_LOC), sub(p, mload(W3_EVAL_LOC)), p) - // adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation = (1 - index_delta) * value_delta * (1 - next_gate_access_type); - - let adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation := - mulmod( - addmod(1, sub(p, index_delta), p), - mulmod(value_delta, addmod(1, sub(p, next_gate_access_type), p), p), - p - ) - - // AUX_RAM_CONSISTENCY_EVALUATION - - /** - * access_type = w_4 - partial_record_check - * access_check = access_type^2 - access_type - * next_gate_access_type_is_boolean = next_gate_access_type^2 - next_gate_access_type - * RAM_consistency_check_identity = adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation; - * RAM_consistency_check_identity *= alpha; - * RAM_consistency_check_identity += index_is_monotonically_increasing; - * RAM_consistency_check_identity *= alpha; - * RAM_consistency_check_identity += next_gate_access_type_is_boolean; - * RAM_consistency_check_identity *= alpha; - * RAM_consistency_check_identity += access_check; - */ - - let access_type := addmod(mload(W4_EVAL_LOC), sub(p, partial_record_check), p) - let access_check := mulmod(access_type, addmod(access_type, sub(p, 1), p), p) - let next_gate_access_type_is_boolean := - mulmod(next_gate_access_type, addmod(next_gate_access_type, sub(p, 1), p), p) - let RAM_cci := - mulmod( - adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation, - mload(C_ALPHA_LOC), - p - ) - RAM_cci := addmod(RAM_cci, index_is_monotonically_increasing, p) - RAM_cci := mulmod(RAM_cci, mload(C_ALPHA_LOC), p) - RAM_cci := addmod(RAM_cci, next_gate_access_type_is_boolean, p) - RAM_cci := mulmod(RAM_cci, mload(C_ALPHA_LOC), p) - RAM_cci := addmod(RAM_cci, access_check, p) - - mstore(AUX_RAM_CONSISTENCY_EVALUATION, RAM_cci) - } - - { - // timestamp_delta = w_2_omega - w_2 - let timestamp_delta := addmod(mload(W2_OMEGA_EVAL_LOC), sub(p, mload(W2_EVAL_LOC)), p) - - // RAM_timestamp_check_identity = (1 - index_delta) * timestamp_delta - w_3 - let RAM_timestamp_check_identity := - addmod( - mulmod(timestamp_delta, addmod(1, sub(p, index_delta), p), p), sub(p, mload(W3_EVAL_LOC)), p - ) - - /** - * memory_identity = ROM_consistency_check_identity * q_2; - * memory_identity += RAM_timestamp_check_identity * q_4; - * memory_identity += memory_record_check * q_m; - * memory_identity *= q_1; - * memory_identity += (RAM_consistency_check_identity * q_arith); - * - * auxiliary_identity = memory_identity + non_native_field_identity + limb_accumulator_identity; - * auxiliary_identity *= q_aux; - * auxiliary_identity *= alpha_base; - */ - let memory_identity := mulmod(mload(AUX_ROM_CONSISTENCY_EVALUATION), mload(Q2_EVAL_LOC), p) - memory_identity := - addmod(memory_identity, mulmod(RAM_timestamp_check_identity, mload(Q4_EVAL_LOC), p), p) - memory_identity := - addmod(memory_identity, mulmod(mload(AUX_MEMORY_EVALUATION), mload(QM_EVAL_LOC), p), p) - memory_identity := mulmod(memory_identity, mload(Q1_EVAL_LOC), p) - memory_identity := - addmod( - memory_identity, mulmod(mload(AUX_RAM_CONSISTENCY_EVALUATION), mload(QARITH_EVAL_LOC), p), p - ) - - let auxiliary_identity := addmod(memory_identity, mload(AUX_NON_NATIVE_FIELD_EVALUATION), p) - auxiliary_identity := addmod(auxiliary_identity, mload(AUX_LIMB_ACCUMULATOR_EVALUATION), p) - auxiliary_identity := mulmod(auxiliary_identity, mload(QAUX_EVAL_LOC), p) - auxiliary_identity := mulmod(auxiliary_identity, mload(C_ALPHA_BASE_LOC), p) - - mstore(AUX_IDENTITY, auxiliary_identity) - - // update alpha - mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_CUBE_LOC), p)) - } - } - } - - { - /** - * quotient = ARITHMETIC_IDENTITY - * quotient += PERMUTATION_IDENTITY - * quotient += PLOOKUP_IDENTITY - * quotient += SORT_IDENTITY - * quotient += ELLIPTIC_IDENTITY - * quotient += AUX_IDENTITY - * quotient *= ZERO_POLY_INVERSE - */ - mstore( - QUOTIENT_EVAL_LOC, - mulmod( - addmod( - addmod( - addmod( - addmod( - addmod(mload(PERMUTATION_IDENTITY), mload(PLOOKUP_IDENTITY), p), - mload(ARITHMETIC_IDENTITY), - p - ), - mload(SORT_IDENTITY), - p - ), - mload(ELLIPTIC_IDENTITY), - p - ), - mload(AUX_IDENTITY), - p - ), - mload(ZERO_POLY_INVERSE_LOC), - p - ) - ) - } - - /** - * GENERATE NU AND SEPARATOR CHALLENGES - */ - { - let current_challenge := mload(C_CURRENT_LOC) - // get a calldata pointer that points to the start of the data we want to copy - let calldata_ptr := add(calldataload(0x04), 0x24) - - calldata_ptr := add(calldata_ptr, NU_CALLDATA_SKIP_LENGTH) - - mstore(NU_CHALLENGE_INPUT_LOC_A, current_challenge) - mstore(NU_CHALLENGE_INPUT_LOC_B, mload(QUOTIENT_EVAL_LOC)) - calldatacopy(NU_CHALLENGE_INPUT_LOC_C, calldata_ptr, NU_INPUT_LENGTH) - - // hash length = (0x20 + num field elements), we include the previous challenge in the hash - let challenge := keccak256(NU_CHALLENGE_INPUT_LOC_A, add(NU_INPUT_LENGTH, 0x40)) - - mstore(C_V0_LOC, mod(challenge, p)) - // We need THIRTY-ONE independent nu challenges! - mstore(0x00, challenge) - mstore8(0x20, 0x01) - mstore(C_V1_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x02) - mstore(C_V2_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x03) - mstore(C_V3_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x04) - mstore(C_V4_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x05) - mstore(C_V5_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x06) - mstore(C_V6_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x07) - mstore(C_V7_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x08) - mstore(C_V8_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x09) - mstore(C_V9_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x0a) - mstore(C_V10_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x0b) - mstore(C_V11_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x0c) - mstore(C_V12_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x0d) - mstore(C_V13_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x0e) - mstore(C_V14_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x0f) - mstore(C_V15_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x10) - mstore(C_V16_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x11) - mstore(C_V17_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x12) - mstore(C_V18_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x13) - mstore(C_V19_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x14) - mstore(C_V20_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x15) - mstore(C_V21_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x16) - mstore(C_V22_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x17) - mstore(C_V23_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x18) - mstore(C_V24_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x19) - mstore(C_V25_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x1a) - mstore(C_V26_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x1b) - mstore(C_V27_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x1c) - mstore(C_V28_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x1d) - mstore(C_V29_LOC, mod(keccak256(0x00, 0x21), p)) - - // @follow-up - Why are both v29 and v30 using appending 0x1d to the prior challenge and hashing, should it not change? - mstore8(0x20, 0x1d) - challenge := keccak256(0x00, 0x21) - mstore(C_V30_LOC, mod(challenge, p)) - - // separator - mstore(0x00, challenge) - mstore(0x20, mload(PI_Z_Y_LOC)) - mstore(0x40, mload(PI_Z_X_LOC)) - mstore(0x60, mload(PI_Z_OMEGA_Y_LOC)) - mstore(0x80, mload(PI_Z_OMEGA_X_LOC)) - - mstore(C_U_LOC, mod(keccak256(0x00, 0xa0), p)) - } - - let success := 0 - // VALIDATE T1 - { - let x := mload(T1_X_LOC) - let y := mload(T1_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(ACCUMULATOR_X_LOC, x) - mstore(add(ACCUMULATOR_X_LOC, 0x20), y) - } - // VALIDATE T2 - { - let x := mload(T2_X_LOC) // 0x1400 - let y := mload(T2_Y_LOC) // 0x1420 - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(ZETA_POW_N_LOC)) - // accumulator_2 = [T2].zeta^n - success := staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40) - // accumulator = [T1] + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE T3 - { - let x := mload(T3_X_LOC) - let y := mload(T3_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(mload(ZETA_POW_N_LOC), mload(ZETA_POW_N_LOC), p)) - // accumulator_2 = [T3].zeta^{2n} - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE T4 - { - let x := mload(T4_X_LOC) - let y := mload(T4_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(mulmod(mload(ZETA_POW_N_LOC), mload(ZETA_POW_N_LOC), p), mload(ZETA_POW_N_LOC), p)) - // accumulator_2 = [T4].zeta^{3n} - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE W1 - { - let x := mload(W1_X_LOC) - let y := mload(W1_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V0_LOC), p)) - // accumulator_2 = v0.(u + 1).[W1] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE W2 - { - let x := mload(W2_X_LOC) - let y := mload(W2_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V1_LOC), p)) - // accumulator_2 = v1.(u + 1).[W2] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE W3 - { - let x := mload(W3_X_LOC) - let y := mload(W3_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V2_LOC), p)) - // accumulator_2 = v2.(u + 1).[W3] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE W4 - { - let x := mload(W4_X_LOC) - let y := mload(W4_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V3_LOC), p)) - // accumulator_2 = v3.(u + 1).[W4] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE S - { - let x := mload(S_X_LOC) - let y := mload(S_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V4_LOC), p)) - // accumulator_2 = v4.(u + 1).[S] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE Z - { - let x := mload(Z_X_LOC) - let y := mload(Z_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V5_LOC), p)) - // accumulator_2 = v5.(u + 1).[Z] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE Z_LOOKUP - { - let x := mload(Z_LOOKUP_X_LOC) - let y := mload(Z_LOOKUP_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V6_LOC), p)) - // accumulator_2 = v6.(u + 1).[Z_LOOKUP] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE Q1 - { - let x := mload(Q1_X_LOC) - let y := mload(Q1_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V7_LOC)) - // accumulator_2 = v7.[Q1] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE Q2 - { - let x := mload(Q2_X_LOC) - let y := mload(Q2_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V8_LOC)) - // accumulator_2 = v8.[Q2] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE Q3 - { - let x := mload(Q3_X_LOC) - let y := mload(Q3_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V9_LOC)) - // accumulator_2 = v9.[Q3] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE Q4 - { - let x := mload(Q4_X_LOC) - let y := mload(Q4_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V10_LOC)) - // accumulator_2 = v10.[Q4] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE QM - { - let x := mload(QM_X_LOC) - let y := mload(QM_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V11_LOC)) - // accumulator_2 = v11.[Q;] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE QC - { - let x := mload(QC_X_LOC) - let y := mload(QC_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V12_LOC)) - // accumulator_2 = v12.[QC] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE QARITH - { - let x := mload(QARITH_X_LOC) - let y := mload(QARITH_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V13_LOC)) - // accumulator_2 = v13.[QARITH] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE QSORT - { - let x := mload(QSORT_X_LOC) - let y := mload(QSORT_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V14_LOC)) - // accumulator_2 = v14.[QSORT] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE QELLIPTIC - { - let x := mload(QELLIPTIC_X_LOC) - let y := mload(QELLIPTIC_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V15_LOC)) - // accumulator_2 = v15.[QELLIPTIC] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE QAUX - { - let x := mload(QAUX_X_LOC) - let y := mload(QAUX_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V16_LOC)) - // accumulator_2 = v15.[Q_AUX] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE SIGMA1 - { - let x := mload(SIGMA1_X_LOC) - let y := mload(SIGMA1_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V17_LOC)) - // accumulator_2 = v17.[sigma1] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE SIGMA2 - { - let x := mload(SIGMA2_X_LOC) - let y := mload(SIGMA2_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V18_LOC)) - // accumulator_2 = v18.[sigma2] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE SIGMA3 - { - let x := mload(SIGMA3_X_LOC) - let y := mload(SIGMA3_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V19_LOC)) - // accumulator_2 = v19.[sigma3] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE SIGMA4 - { - let x := mload(SIGMA4_X_LOC) - let y := mload(SIGMA4_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V20_LOC)) - // accumulator_2 = v20.[sigma4] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE TABLE1 - { - let x := mload(TABLE1_X_LOC) - let y := mload(TABLE1_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V21_LOC), p)) - // accumulator_2 = u.[table1] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE TABLE2 - { - let x := mload(TABLE2_X_LOC) - let y := mload(TABLE2_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V22_LOC), p)) - // accumulator_2 = u.[table2] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE TABLE3 - { - let x := mload(TABLE3_X_LOC) - let y := mload(TABLE3_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V23_LOC), p)) - // accumulator_2 = u.[table3] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE TABLE4 - { - let x := mload(TABLE4_X_LOC) - let y := mload(TABLE4_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V24_LOC), p)) - // accumulator_2 = u.[table4] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE TABLE_TYPE - { - let x := mload(TABLE_TYPE_X_LOC) - let y := mload(TABLE_TYPE_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V25_LOC)) - // accumulator_2 = v25.[TableType] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE ID1 - { - let x := mload(ID1_X_LOC) - let y := mload(ID1_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V26_LOC)) - // accumulator_2 = v26.[ID1] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE ID2 - { - let x := mload(ID2_X_LOC) - let y := mload(ID2_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V27_LOC)) - // accumulator_2 = v27.[ID2] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE ID3 - { - let x := mload(ID3_X_LOC) - let y := mload(ID3_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V28_LOC)) - // accumulator_2 = v28.[ID3] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE ID4 - { - let x := mload(ID4_X_LOC) - let y := mload(ID4_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V29_LOC)) - // accumulator_2 = v29.[ID4] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - /** - * COMPUTE BATCH EVALUATION SCALAR MULTIPLIER - */ - { - /** - * batch_evaluation = v0 * (w_1_omega * u + w_1_eval) - * batch_evaluation += v1 * (w_2_omega * u + w_2_eval) - * batch_evaluation += v2 * (w_3_omega * u + w_3_eval) - * batch_evaluation += v3 * (w_4_omega * u + w_4_eval) - * batch_evaluation += v4 * (s_omega_eval * u + s_eval) - * batch_evaluation += v5 * (z_omega_eval * u + z_eval) - * batch_evaluation += v6 * (z_lookup_omega_eval * u + z_lookup_eval) - */ - let batch_evaluation := - mulmod( - mload(C_V0_LOC), - addmod(mulmod(mload(W1_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W1_EVAL_LOC), p), - p - ) - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V1_LOC), - addmod(mulmod(mload(W2_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W2_EVAL_LOC), p), - p - ), - p - ) - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V2_LOC), - addmod(mulmod(mload(W3_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W3_EVAL_LOC), p), - p - ), - p - ) - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V3_LOC), - addmod(mulmod(mload(W4_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W4_EVAL_LOC), p), - p - ), - p - ) - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V4_LOC), - addmod(mulmod(mload(S_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(S_EVAL_LOC), p), - p - ), - p - ) - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V5_LOC), - addmod(mulmod(mload(Z_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(Z_EVAL_LOC), p), - p - ), - p - ) - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V6_LOC), - addmod(mulmod(mload(Z_LOOKUP_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(Z_LOOKUP_EVAL_LOC), p), - p - ), - p - ) - - /** - * batch_evaluation += v7 * Q1_EVAL - * batch_evaluation += v8 * Q2_EVAL - * batch_evaluation += v9 * Q3_EVAL - * batch_evaluation += v10 * Q4_EVAL - * batch_evaluation += v11 * QM_EVAL - * batch_evaluation += v12 * QC_EVAL - * batch_evaluation += v13 * QARITH_EVAL - * batch_evaluation += v14 * QSORT_EVAL_LOC - * batch_evaluation += v15 * QELLIPTIC_EVAL_LOC - * batch_evaluation += v16 * QAUX_EVAL_LOC - * batch_evaluation += v17 * SIGMA1_EVAL_LOC - * batch_evaluation += v18 * SIGMA2_EVAL_LOC - * batch_evaluation += v19 * SIGMA3_EVAL_LOC - * batch_evaluation += v20 * SIGMA4_EVAL_LOC - */ - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V7_LOC), mload(Q1_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V8_LOC), mload(Q2_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V9_LOC), mload(Q3_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V10_LOC), mload(Q4_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V11_LOC), mload(QM_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V12_LOC), mload(QC_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V13_LOC), mload(QARITH_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V14_LOC), mload(QSORT_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V15_LOC), mload(QELLIPTIC_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V16_LOC), mload(QAUX_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V17_LOC), mload(SIGMA1_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V18_LOC), mload(SIGMA2_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V19_LOC), mload(SIGMA3_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V20_LOC), mload(SIGMA4_EVAL_LOC), p), p) - - /** - * batch_evaluation += v21 * (table1(zw) * u + table1(z)) - * batch_evaluation += v22 * (table2(zw) * u + table2(z)) - * batch_evaluation += v23 * (table3(zw) * u + table3(z)) - * batch_evaluation += v24 * (table4(zw) * u + table4(z)) - * batch_evaluation += v25 * table_type_eval - * batch_evaluation += v26 * id1_eval - * batch_evaluation += v27 * id2_eval - * batch_evaluation += v28 * id3_eval - * batch_evaluation += v29 * id4_eval - * batch_evaluation += quotient_eval - */ - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V21_LOC), - addmod(mulmod(mload(TABLE1_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE1_EVAL_LOC), p), - p - ), - p - ) - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V22_LOC), - addmod(mulmod(mload(TABLE2_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE2_EVAL_LOC), p), - p - ), - p - ) - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V23_LOC), - addmod(mulmod(mload(TABLE3_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE3_EVAL_LOC), p), - p - ), - p - ) - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V24_LOC), - addmod(mulmod(mload(TABLE4_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE4_EVAL_LOC), p), - p - ), - p - ) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V25_LOC), mload(TABLE_TYPE_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V26_LOC), mload(ID1_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V27_LOC), mload(ID2_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V28_LOC), mload(ID3_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V29_LOC), mload(ID4_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mload(QUOTIENT_EVAL_LOC), p) - - mstore(0x00, 0x01) // [1].x - mstore(0x20, 0x02) // [1].y - mstore(0x40, sub(p, batch_evaluation)) - // accumulator_2 = -[1].(batch_evaluation) - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - if iszero(success) { - mstore(0x0, OPENING_COMMITMENT_FAILED_SELECTOR) - revert(0x00, 0x04) - } - } - - /** - * PERFORM PAIRING PREAMBLE - */ - { - let u := mload(C_U_LOC) - let zeta := mload(C_ZETA_LOC) - // VALIDATE PI_Z - { - let x := mload(PI_Z_X_LOC) - let y := mload(PI_Z_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - // compute zeta.[PI_Z] and add into accumulator - mstore(0x40, zeta) - success := staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE PI_Z_OMEGA - { - let x := mload(PI_Z_OMEGA_X_LOC) - let y := mload(PI_Z_OMEGA_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(mulmod(u, zeta, p), mload(OMEGA_LOC), p)) - // accumulator_2 = u.zeta.omega.[PI_Z_OMEGA] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // PAIRING_RHS = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, PAIRING_RHS_X_LOC, 0x40)) - - mstore(0x00, mload(PI_Z_X_LOC)) - mstore(0x20, mload(PI_Z_Y_LOC)) - mstore(0x40, mload(PI_Z_OMEGA_X_LOC)) - mstore(0x60, mload(PI_Z_OMEGA_Y_LOC)) - mstore(0x80, u) - success := and(success, staticcall(gas(), 7, 0x40, 0x60, 0x40, 0x40)) - // PAIRING_LHS = [PI_Z] + [PI_Z_OMEGA] * u - success := and(success, staticcall(gas(), 6, 0x00, 0x80, PAIRING_LHS_X_LOC, 0x40)) - // negate lhs y-coordinate - mstore(PAIRING_LHS_Y_LOC, sub(q, mload(PAIRING_LHS_Y_LOC))) - - if mload(CONTAINS_RECURSIVE_PROOF_LOC) { - // VALIDATE RECURSIVE P1 - { - let x := mload(RECURSIVE_P1_X_LOC) - let y := mload(RECURSIVE_P1_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - - // compute u.u.[recursive_p1] and write into 0x60 - mstore(0x40, mulmod(u, u, p)) - success := and(success, staticcall(gas(), 7, 0x00, 0x60, 0x60, 0x40)) - // VALIDATE RECURSIVE P2 - { - let x := mload(RECURSIVE_P2_X_LOC) - let y := mload(RECURSIVE_P2_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - // compute u.u.[recursive_p2] and write into 0x00 - // 0x40 still contains u*u - success := and(success, staticcall(gas(), 7, 0x00, 0x60, 0x00, 0x40)) - - // compute u.u.[recursiveP1] + rhs and write into rhs - mstore(0xa0, mload(PAIRING_RHS_X_LOC)) - mstore(0xc0, mload(PAIRING_RHS_Y_LOC)) - success := and(success, staticcall(gas(), 6, 0x60, 0x80, PAIRING_RHS_X_LOC, 0x40)) - - // compute u.u.[recursiveP2] + lhs and write into lhs - mstore(0x40, mload(PAIRING_LHS_X_LOC)) - mstore(0x60, mload(PAIRING_LHS_Y_LOC)) - success := and(success, staticcall(gas(), 6, 0x00, 0x80, PAIRING_LHS_X_LOC, 0x40)) - } - - if iszero(success) { - mstore(0x0, PAIRING_PREAMBLE_FAILED_SELECTOR) - revert(0x00, 0x04) - } - } - - /** - * PERFORM PAIRING - */ - { - // rhs paired with [1]_2 - // lhs paired with [x]_2 - - mstore(0x00, mload(PAIRING_RHS_X_LOC)) - mstore(0x20, mload(PAIRING_RHS_Y_LOC)) - mstore(0x40, 0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2) // this is [1]_2 - mstore(0x60, 0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed) - mstore(0x80, 0x090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b) - mstore(0xa0, 0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa) - - mstore(0xc0, mload(PAIRING_LHS_X_LOC)) - mstore(0xe0, mload(PAIRING_LHS_Y_LOC)) - mstore(0x100, mload(G2X_X0_LOC)) - mstore(0x120, mload(G2X_X1_LOC)) - mstore(0x140, mload(G2X_Y0_LOC)) - mstore(0x160, mload(G2X_Y1_LOC)) - - success := staticcall(gas(), 8, 0x00, 0x180, 0x00, 0x20) - if iszero(and(success, mload(0x00))) { - mstore(0x0, PAIRING_FAILED_SELECTOR) - revert(0x00, 0x04) - } - } - - { - mstore(0x00, 0x01) - return(0x00, 0x20) // Proof succeeded! - } - } - } -} - -contract UltraVerifier is BaseUltraVerifier { - function getVerificationKeyHash() public pure override(BaseUltraVerifier) returns (bytes32) { - return UltraVerificationKey.verificationKeyHash(); - } - - function loadVerificationKey(uint256 vk, uint256 _omegaInverseLoc) internal pure virtual override(BaseUltraVerifier) { - UltraVerificationKey.loadVerificationKey(vk, _omegaInverseLoc); - } -} diff --git a/noir/noir-repo/compiler/integration-tests/contracts/assert_statement.sol b/noir/noir-repo/compiler/integration-tests/contracts/assert_statement.sol deleted file mode 100644 index 6946be8ee4be..000000000000 --- a/noir/noir-repo/compiler/integration-tests/contracts/assert_statement.sol +++ /dev/null @@ -1,2869 +0,0 @@ -// Verification Key Hash: 203c988709ced4125d5c6138661ba4d16a71092c5f4189d2b3baf2596a93311b -// SPDX-License-Identifier: Apache-2.0 -// Copyright 2022 Aztec -pragma solidity >=0.8.4; - -library UltraVerificationKey { - function verificationKeyHash() internal pure returns(bytes32) { - return 0x203c988709ced4125d5c6138661ba4d16a71092c5f4189d2b3baf2596a93311b; - } - - function loadVerificationKey(uint256 _vk, uint256 _omegaInverseLoc) internal pure { - assembly { - mstore(add(_vk, 0x00), 0x0000000000000000000000000000000000000000000000000000000000000008) // vk.circuit_size - mstore(add(_vk, 0x20), 0x0000000000000000000000000000000000000000000000000000000000000001) // vk.num_inputs - mstore(add(_vk, 0x40), 0x2b337de1c8c14f22ec9b9e2f96afef3652627366f8170a0a948dad4ac1bd5e80) // vk.work_root - mstore(add(_vk, 0x60), 0x2a57c4a4850b6c2481463cffb1512d51832d6b3f6a82427f1b65b6e172000001) // vk.domain_inverse - mstore(add(_vk, 0x80), 0x0160ce4e279582f91bde4f03f5e9a292139c61bae1a44f0fc7689507414be688) // vk.Q1.x - mstore(add(_vk, 0xa0), 0x07e3e8a5d98a1177ec85bf88f163a55dc2d37f658c3b2d60f24740eb13b65d79) // vk.Q1.y - mstore(add(_vk, 0xc0), 0x23d08e2817ac16990004ed11d8fc66dc3035fbd7ff16412a8fd7da587a935298) // vk.Q2.x - mstore(add(_vk, 0xe0), 0x0708529196af3c8e16ffa580c26182356a5ad59c646c746a8d09f5d154e47c4f) // vk.Q2.y - mstore(add(_vk, 0x100), 0x13757e15a0905f298303784a161b212ddfe70eb7a1280596e8e4a804f118a6dd) // vk.Q3.x - mstore(add(_vk, 0x120), 0x05775b6c146c4a59856e869fe5a70ea23a729df796935c7824e3a26be794829b) // vk.Q3.y - mstore(add(_vk, 0x140), 0x1d539ccbfc556d0ad59307a218de65eef0c9e088fd2d45aa40311082d1f2809b) // vk.Q4.x - mstore(add(_vk, 0x160), 0x177004deeb1f9d401fd7b1af1a5ac8a2c848beceb6ab7806fd3b88037b8410fc) // vk.Q4.y - mstore(add(_vk, 0x180), 0x0d82d51f2f75d806285fd248c819b82508eb63672a733f20de1a97644be4f540) // vk.Q_M.x - mstore(add(_vk, 0x1a0), 0x06cd3b0e3460533b9e5ea2cdc0fcbbd002f9100cbba8a29f13b11513c53c59d0) // vk.Q_M.y - mstore(add(_vk, 0x1c0), 0x21791de65f9a28ec7024b1a87ab4f3f45ea38a93b2f810c5633ddb54927c1c96) // vk.Q_C.x - mstore(add(_vk, 0x1e0), 0x29fa14a969c5d81ed3abbbfb11220a926511a0439502c86885a8c6f0327aa7ad) // vk.Q_C.y - mstore(add(_vk, 0x200), 0x2a910445cd8fc895e5d235cd8ea185b84c3258e8206f560e5b5b18cbeafef87e) // vk.Q_ARITHMETIC.x - mstore(add(_vk, 0x220), 0x14dc6643d801c3ef27c2066b6e2bb4887e67f15e84bcb8507a5064a363f6043b) // vk.Q_ARITHMETIC.y - mstore(add(_vk, 0x240), 0x20690fd4869db418306046b38161dce38e900b42c314ba803088e8fbf125203f) // vk.QSORT.x - mstore(add(_vk, 0x260), 0x048a85e0bbac7c60ad3d78f601f63c1e2fa856bf7951b8292b1e88185993629c) // vk.QSORT.y - mstore(add(_vk, 0x280), 0x2623ad892dc62b1fa7d0a650f0d4706f457719495073d3666d77a625aeab0c51) // vk.Q_ELLIPTIC.x - mstore(add(_vk, 0x2a0), 0x295f6f10976c37bd9c6f96bb7187d5dbfcc8a467e021c03b13f74a9f79c3a10c) // vk.Q_ELLIPTIC.y - mstore(add(_vk, 0x2c0), 0x03560a3b334e887532f605c9cb7628c13ef9a937cc12420fb38d9ab8e848e85e) // vk.Q_AUX.x - mstore(add(_vk, 0x2e0), 0x15adc8bb1e01c835f48959d1237bd69bcebf08a4599cdda0fb96312d4dc0c7a9) // vk.Q_AUX.y - mstore(add(_vk, 0x300), 0x24e3690cd89b1f74c96a6b0e03032344488741fb4b129e9cbcb31de91fd06ad8) // vk.SIGMA1.x - mstore(add(_vk, 0x320), 0x2c3b3b2783935f54e840bb7502b0ec734cb8ac2419c90514d0d015a974a9b52b) // vk.SIGMA1.y - mstore(add(_vk, 0x340), 0x060d8aa43fdc434d1942263f364d95ab17c6189d67d3bf5dd2f3885de0151b6f) // vk.SIGMA2.x - mstore(add(_vk, 0x360), 0x1a1018a66221883639f2898a66f3455d292333b3adb497f00b4bc32d45229060) // vk.SIGMA2.y - mstore(add(_vk, 0x380), 0x27730cec8ee6eafbd0e5ccffeab20dbd1c781a61196943647af68c4e39985fdc) // vk.SIGMA3.x - mstore(add(_vk, 0x3a0), 0x0766d1f3a85c923ee23cb3fcd89886f19af23a34217779c58eaeceb38cfdf1eb) // vk.SIGMA3.y - mstore(add(_vk, 0x3c0), 0x09ae6c317ff52520ae05150d89a4678f6f5839296a91685a8f562ca95fa36822) // vk.SIGMA4.x - mstore(add(_vk, 0x3e0), 0x0832680695476b91062cfd71c4663f5bd579304b4448ce5ae6eaa6620db20ab1) // vk.SIGMA4.y - mstore(add(_vk, 0x400), 0x1f54baa07558e5fb055bd9ba49c0679c5d6e08a6605ab4513748ac0fa017dd1c) // vk.TABLE1.x - mstore(add(_vk, 0x420), 0x24aec62a9d9763499267dc98c334281e1ee7ee29bbb5e4b080c6091c1433ce62) // vk.TABLE1.y - mstore(add(_vk, 0x440), 0x28cf3e22bcd53782ebc3e0490e27e51a96755946ff16f0d6632365f0eb0ab4d4) // vk.TABLE2.x - mstore(add(_vk, 0x460), 0x234ce541f1f5117dd404cfaf01a22943148d7d8c9ba43f2133fab4201435a364) // vk.TABLE2.y - mstore(add(_vk, 0x480), 0x3016955028b6390f446c3fd0c5b424a7fb95ffb461d9514a1070e2d2403982ef) // vk.TABLE3.x - mstore(add(_vk, 0x4a0), 0x13ef666111b0be56a235983d397d2a08863c3b7cd7cddc20ba79ce915051c56e) // vk.TABLE3.y - mstore(add(_vk, 0x4c0), 0x217f7c4235161e9a3c16c45b6ca499e3993f465fc9f56e93ac769e597b752c1c) // vk.TABLE4.x - mstore(add(_vk, 0x4e0), 0x256467bfcb63d9fdcb5dde397757ad8ffa4cd96bc67b0b7df5678271e1114075) // vk.TABLE4.y - mstore(add(_vk, 0x500), 0x0e52d1bd75812c33c6f3d79ee4b94c54e5eb270bb64bde6e6ececadfd8c3236c) // vk.TABLE_TYPE.x - mstore(add(_vk, 0x520), 0x0ff417d256be43e73c8b1aa85bdda3484a2c641dce55bc2dd64ef0cd790a7fea) // vk.TABLE_TYPE.y - mstore(add(_vk, 0x540), 0x2914765365b4bb5f48a424db02b30c158b9ace6a8786bf33f65c33e87249f995) // vk.ID1.x - mstore(add(_vk, 0x560), 0x2e606ebd09b7686801932b72c9dbe83a6b1ae341f8cb6d52a568b693630f4643) // vk.ID1.y - mstore(add(_vk, 0x580), 0x1b0d1316756ddd16982a7e98b868244fff53c5d4bdc2b70e371c0d08e994cfd5) // vk.ID2.x - mstore(add(_vk, 0x5a0), 0x27f94b1ce85bf25b95857aaa3b82f6a3706170d67e53462bc635491ec3a29f98) // vk.ID2.y - mstore(add(_vk, 0x5c0), 0x26c5c0971d041a6777e4896896f674670e17bb68e92cbb11e605d2d74c077f66) // vk.ID3.x - mstore(add(_vk, 0x5e0), 0x15d5a580649417ff6523c7ec8e2fce5f1f22fef5be2a9fb4fd3004d9c6562efe) // vk.ID3.y - mstore(add(_vk, 0x600), 0x2eea648c8732596b1314fe2a4d2f05363f0c994e91cecad25835338edee2294f) // vk.ID4.x - mstore(add(_vk, 0x620), 0x0ab49886c2b94bd0bd3f6ed1dbbe2cb2671d2ae51d31c1210433c3972bb64578) // vk.ID4.y - mstore(add(_vk, 0x640), 0x00) // vk.contains_recursive_proof - mstore(add(_vk, 0x660), 0) // vk.recursive_proof_public_input_indices - mstore(add(_vk, 0x680), 0x260e01b251f6f1c7e7ff4e580791dee8ea51d87a358e038b4efe30fac09383c1) // vk.g2_x.X.c1 - mstore(add(_vk, 0x6a0), 0x0118c4d5b837bcc2bc89b5b398b5974e9f5944073b32078b7e231fec938883b0) // vk.g2_x.X.c0 - mstore(add(_vk, 0x6c0), 0x04fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe4) // vk.g2_x.Y.c1 - mstore(add(_vk, 0x6e0), 0x22febda3c0c0632a56475b4214e5615e11e6dd3f96e6cea2854a87d4dacc5e55) // vk.g2_x.Y.c0 - mstore(_omegaInverseLoc, 0x130b17119778465cfb3acaee30f81dee20710ead41671f568b11d9ab07b95a9b) // vk.work_root_inverse - } - } -} - -/** - * @title Ultra Plonk proof verification contract - * @dev Top level Plonk proof verification contract, which allows Plonk proof to be verified - */ -abstract contract BaseUltraVerifier { - // VERIFICATION KEY MEMORY LOCATIONS - uint256 internal constant N_LOC = 0x380; - uint256 internal constant NUM_INPUTS_LOC = 0x3a0; - uint256 internal constant OMEGA_LOC = 0x3c0; - uint256 internal constant DOMAIN_INVERSE_LOC = 0x3e0; - uint256 internal constant Q1_X_LOC = 0x400; - uint256 internal constant Q1_Y_LOC = 0x420; - uint256 internal constant Q2_X_LOC = 0x440; - uint256 internal constant Q2_Y_LOC = 0x460; - uint256 internal constant Q3_X_LOC = 0x480; - uint256 internal constant Q3_Y_LOC = 0x4a0; - uint256 internal constant Q4_X_LOC = 0x4c0; - uint256 internal constant Q4_Y_LOC = 0x4e0; - uint256 internal constant QM_X_LOC = 0x500; - uint256 internal constant QM_Y_LOC = 0x520; - uint256 internal constant QC_X_LOC = 0x540; - uint256 internal constant QC_Y_LOC = 0x560; - uint256 internal constant QARITH_X_LOC = 0x580; - uint256 internal constant QARITH_Y_LOC = 0x5a0; - uint256 internal constant QSORT_X_LOC = 0x5c0; - uint256 internal constant QSORT_Y_LOC = 0x5e0; - uint256 internal constant QELLIPTIC_X_LOC = 0x600; - uint256 internal constant QELLIPTIC_Y_LOC = 0x620; - uint256 internal constant QAUX_X_LOC = 0x640; - uint256 internal constant QAUX_Y_LOC = 0x660; - uint256 internal constant SIGMA1_X_LOC = 0x680; - uint256 internal constant SIGMA1_Y_LOC = 0x6a0; - uint256 internal constant SIGMA2_X_LOC = 0x6c0; - uint256 internal constant SIGMA2_Y_LOC = 0x6e0; - uint256 internal constant SIGMA3_X_LOC = 0x700; - uint256 internal constant SIGMA3_Y_LOC = 0x720; - uint256 internal constant SIGMA4_X_LOC = 0x740; - uint256 internal constant SIGMA4_Y_LOC = 0x760; - uint256 internal constant TABLE1_X_LOC = 0x780; - uint256 internal constant TABLE1_Y_LOC = 0x7a0; - uint256 internal constant TABLE2_X_LOC = 0x7c0; - uint256 internal constant TABLE2_Y_LOC = 0x7e0; - uint256 internal constant TABLE3_X_LOC = 0x800; - uint256 internal constant TABLE3_Y_LOC = 0x820; - uint256 internal constant TABLE4_X_LOC = 0x840; - uint256 internal constant TABLE4_Y_LOC = 0x860; - uint256 internal constant TABLE_TYPE_X_LOC = 0x880; - uint256 internal constant TABLE_TYPE_Y_LOC = 0x8a0; - uint256 internal constant ID1_X_LOC = 0x8c0; - uint256 internal constant ID1_Y_LOC = 0x8e0; - uint256 internal constant ID2_X_LOC = 0x900; - uint256 internal constant ID2_Y_LOC = 0x920; - uint256 internal constant ID3_X_LOC = 0x940; - uint256 internal constant ID3_Y_LOC = 0x960; - uint256 internal constant ID4_X_LOC = 0x980; - uint256 internal constant ID4_Y_LOC = 0x9a0; - uint256 internal constant CONTAINS_RECURSIVE_PROOF_LOC = 0x9c0; - uint256 internal constant RECURSIVE_PROOF_PUBLIC_INPUT_INDICES_LOC = 0x9e0; - uint256 internal constant G2X_X0_LOC = 0xa00; - uint256 internal constant G2X_X1_LOC = 0xa20; - uint256 internal constant G2X_Y0_LOC = 0xa40; - uint256 internal constant G2X_Y1_LOC = 0xa60; - - // ### PROOF DATA MEMORY LOCATIONS - uint256 internal constant W1_X_LOC = 0x1200; - uint256 internal constant W1_Y_LOC = 0x1220; - uint256 internal constant W2_X_LOC = 0x1240; - uint256 internal constant W2_Y_LOC = 0x1260; - uint256 internal constant W3_X_LOC = 0x1280; - uint256 internal constant W3_Y_LOC = 0x12a0; - uint256 internal constant W4_X_LOC = 0x12c0; - uint256 internal constant W4_Y_LOC = 0x12e0; - uint256 internal constant S_X_LOC = 0x1300; - uint256 internal constant S_Y_LOC = 0x1320; - uint256 internal constant Z_X_LOC = 0x1340; - uint256 internal constant Z_Y_LOC = 0x1360; - uint256 internal constant Z_LOOKUP_X_LOC = 0x1380; - uint256 internal constant Z_LOOKUP_Y_LOC = 0x13a0; - uint256 internal constant T1_X_LOC = 0x13c0; - uint256 internal constant T1_Y_LOC = 0x13e0; - uint256 internal constant T2_X_LOC = 0x1400; - uint256 internal constant T2_Y_LOC = 0x1420; - uint256 internal constant T3_X_LOC = 0x1440; - uint256 internal constant T3_Y_LOC = 0x1460; - uint256 internal constant T4_X_LOC = 0x1480; - uint256 internal constant T4_Y_LOC = 0x14a0; - - uint256 internal constant W1_EVAL_LOC = 0x1600; - uint256 internal constant W2_EVAL_LOC = 0x1620; - uint256 internal constant W3_EVAL_LOC = 0x1640; - uint256 internal constant W4_EVAL_LOC = 0x1660; - uint256 internal constant S_EVAL_LOC = 0x1680; - uint256 internal constant Z_EVAL_LOC = 0x16a0; - uint256 internal constant Z_LOOKUP_EVAL_LOC = 0x16c0; - uint256 internal constant Q1_EVAL_LOC = 0x16e0; - uint256 internal constant Q2_EVAL_LOC = 0x1700; - uint256 internal constant Q3_EVAL_LOC = 0x1720; - uint256 internal constant Q4_EVAL_LOC = 0x1740; - uint256 internal constant QM_EVAL_LOC = 0x1760; - uint256 internal constant QC_EVAL_LOC = 0x1780; - uint256 internal constant QARITH_EVAL_LOC = 0x17a0; - uint256 internal constant QSORT_EVAL_LOC = 0x17c0; - uint256 internal constant QELLIPTIC_EVAL_LOC = 0x17e0; - uint256 internal constant QAUX_EVAL_LOC = 0x1800; - uint256 internal constant TABLE1_EVAL_LOC = 0x1840; - uint256 internal constant TABLE2_EVAL_LOC = 0x1860; - uint256 internal constant TABLE3_EVAL_LOC = 0x1880; - uint256 internal constant TABLE4_EVAL_LOC = 0x18a0; - uint256 internal constant TABLE_TYPE_EVAL_LOC = 0x18c0; - uint256 internal constant ID1_EVAL_LOC = 0x18e0; - uint256 internal constant ID2_EVAL_LOC = 0x1900; - uint256 internal constant ID3_EVAL_LOC = 0x1920; - uint256 internal constant ID4_EVAL_LOC = 0x1940; - uint256 internal constant SIGMA1_EVAL_LOC = 0x1960; - uint256 internal constant SIGMA2_EVAL_LOC = 0x1980; - uint256 internal constant SIGMA3_EVAL_LOC = 0x19a0; - uint256 internal constant SIGMA4_EVAL_LOC = 0x19c0; - uint256 internal constant W1_OMEGA_EVAL_LOC = 0x19e0; - uint256 internal constant W2_OMEGA_EVAL_LOC = 0x2000; - uint256 internal constant W3_OMEGA_EVAL_LOC = 0x2020; - uint256 internal constant W4_OMEGA_EVAL_LOC = 0x2040; - uint256 internal constant S_OMEGA_EVAL_LOC = 0x2060; - uint256 internal constant Z_OMEGA_EVAL_LOC = 0x2080; - uint256 internal constant Z_LOOKUP_OMEGA_EVAL_LOC = 0x20a0; - uint256 internal constant TABLE1_OMEGA_EVAL_LOC = 0x20c0; - uint256 internal constant TABLE2_OMEGA_EVAL_LOC = 0x20e0; - uint256 internal constant TABLE3_OMEGA_EVAL_LOC = 0x2100; - uint256 internal constant TABLE4_OMEGA_EVAL_LOC = 0x2120; - - uint256 internal constant PI_Z_X_LOC = 0x2300; - uint256 internal constant PI_Z_Y_LOC = 0x2320; - uint256 internal constant PI_Z_OMEGA_X_LOC = 0x2340; - uint256 internal constant PI_Z_OMEGA_Y_LOC = 0x2360; - - // Used for elliptic widget. These are alias names for wire + shifted wire evaluations - uint256 internal constant X1_EVAL_LOC = W2_EVAL_LOC; - uint256 internal constant X2_EVAL_LOC = W1_OMEGA_EVAL_LOC; - uint256 internal constant X3_EVAL_LOC = W2_OMEGA_EVAL_LOC; - uint256 internal constant Y1_EVAL_LOC = W3_EVAL_LOC; - uint256 internal constant Y2_EVAL_LOC = W4_OMEGA_EVAL_LOC; - uint256 internal constant Y3_EVAL_LOC = W3_OMEGA_EVAL_LOC; - uint256 internal constant QBETA_LOC = Q3_EVAL_LOC; - uint256 internal constant QBETA_SQR_LOC = Q4_EVAL_LOC; - uint256 internal constant QSIGN_LOC = Q1_EVAL_LOC; - - // ### CHALLENGES MEMORY OFFSETS - - uint256 internal constant C_BETA_LOC = 0x2600; - uint256 internal constant C_GAMMA_LOC = 0x2620; - uint256 internal constant C_ALPHA_LOC = 0x2640; - uint256 internal constant C_ETA_LOC = 0x2660; - uint256 internal constant C_ETA_SQR_LOC = 0x2680; - uint256 internal constant C_ETA_CUBE_LOC = 0x26a0; - - uint256 internal constant C_ZETA_LOC = 0x26c0; - uint256 internal constant C_CURRENT_LOC = 0x26e0; - uint256 internal constant C_V0_LOC = 0x2700; - uint256 internal constant C_V1_LOC = 0x2720; - uint256 internal constant C_V2_LOC = 0x2740; - uint256 internal constant C_V3_LOC = 0x2760; - uint256 internal constant C_V4_LOC = 0x2780; - uint256 internal constant C_V5_LOC = 0x27a0; - uint256 internal constant C_V6_LOC = 0x27c0; - uint256 internal constant C_V7_LOC = 0x27e0; - uint256 internal constant C_V8_LOC = 0x2800; - uint256 internal constant C_V9_LOC = 0x2820; - uint256 internal constant C_V10_LOC = 0x2840; - uint256 internal constant C_V11_LOC = 0x2860; - uint256 internal constant C_V12_LOC = 0x2880; - uint256 internal constant C_V13_LOC = 0x28a0; - uint256 internal constant C_V14_LOC = 0x28c0; - uint256 internal constant C_V15_LOC = 0x28e0; - uint256 internal constant C_V16_LOC = 0x2900; - uint256 internal constant C_V17_LOC = 0x2920; - uint256 internal constant C_V18_LOC = 0x2940; - uint256 internal constant C_V19_LOC = 0x2960; - uint256 internal constant C_V20_LOC = 0x2980; - uint256 internal constant C_V21_LOC = 0x29a0; - uint256 internal constant C_V22_LOC = 0x29c0; - uint256 internal constant C_V23_LOC = 0x29e0; - uint256 internal constant C_V24_LOC = 0x2a00; - uint256 internal constant C_V25_LOC = 0x2a20; - uint256 internal constant C_V26_LOC = 0x2a40; - uint256 internal constant C_V27_LOC = 0x2a60; - uint256 internal constant C_V28_LOC = 0x2a80; - uint256 internal constant C_V29_LOC = 0x2aa0; - uint256 internal constant C_V30_LOC = 0x2ac0; - - uint256 internal constant C_U_LOC = 0x2b00; - - // ### LOCAL VARIABLES MEMORY OFFSETS - uint256 internal constant DELTA_NUMERATOR_LOC = 0x3000; - uint256 internal constant DELTA_DENOMINATOR_LOC = 0x3020; - uint256 internal constant ZETA_POW_N_LOC = 0x3040; - uint256 internal constant PUBLIC_INPUT_DELTA_LOC = 0x3060; - uint256 internal constant ZERO_POLY_LOC = 0x3080; - uint256 internal constant L_START_LOC = 0x30a0; - uint256 internal constant L_END_LOC = 0x30c0; - uint256 internal constant R_ZERO_EVAL_LOC = 0x30e0; - - uint256 internal constant PLOOKUP_DELTA_NUMERATOR_LOC = 0x3100; - uint256 internal constant PLOOKUP_DELTA_DENOMINATOR_LOC = 0x3120; - uint256 internal constant PLOOKUP_DELTA_LOC = 0x3140; - - uint256 internal constant ACCUMULATOR_X_LOC = 0x3160; - uint256 internal constant ACCUMULATOR_Y_LOC = 0x3180; - uint256 internal constant ACCUMULATOR2_X_LOC = 0x31a0; - uint256 internal constant ACCUMULATOR2_Y_LOC = 0x31c0; - uint256 internal constant PAIRING_LHS_X_LOC = 0x31e0; - uint256 internal constant PAIRING_LHS_Y_LOC = 0x3200; - uint256 internal constant PAIRING_RHS_X_LOC = 0x3220; - uint256 internal constant PAIRING_RHS_Y_LOC = 0x3240; - - // misc stuff - uint256 internal constant OMEGA_INVERSE_LOC = 0x3300; - uint256 internal constant C_ALPHA_SQR_LOC = 0x3320; - uint256 internal constant C_ALPHA_CUBE_LOC = 0x3340; - uint256 internal constant C_ALPHA_QUAD_LOC = 0x3360; - uint256 internal constant C_ALPHA_BASE_LOC = 0x3380; - - // ### RECURSION VARIABLE MEMORY LOCATIONS - uint256 internal constant RECURSIVE_P1_X_LOC = 0x3400; - uint256 internal constant RECURSIVE_P1_Y_LOC = 0x3420; - uint256 internal constant RECURSIVE_P2_X_LOC = 0x3440; - uint256 internal constant RECURSIVE_P2_Y_LOC = 0x3460; - uint256 internal constant PUBLIC_INPUTS_HASH_LOCATION = 0x3480; - - // sub-identity storage - uint256 internal constant PERMUTATION_IDENTITY = 0x3500; - uint256 internal constant PLOOKUP_IDENTITY = 0x3520; - uint256 internal constant ARITHMETIC_IDENTITY = 0x3540; - uint256 internal constant SORT_IDENTITY = 0x3560; - uint256 internal constant ELLIPTIC_IDENTITY = 0x3580; - uint256 internal constant AUX_IDENTITY = 0x35a0; - uint256 internal constant AUX_NON_NATIVE_FIELD_EVALUATION = 0x35c0; - uint256 internal constant AUX_LIMB_ACCUMULATOR_EVALUATION = 0x35e0; - uint256 internal constant AUX_RAM_CONSISTENCY_EVALUATION = 0x3600; - uint256 internal constant AUX_ROM_CONSISTENCY_EVALUATION = 0x3620; - uint256 internal constant AUX_MEMORY_EVALUATION = 0x3640; - - uint256 internal constant QUOTIENT_EVAL_LOC = 0x3660; - uint256 internal constant ZERO_POLY_INVERSE_LOC = 0x3680; - - // when hashing public inputs we use memory at NU_CHALLENGE_INPUT_LOC_A, as the hash input size is unknown at compile time - uint256 internal constant NU_CHALLENGE_INPUT_LOC_A = 0x36a0; - uint256 internal constant NU_CHALLENGE_INPUT_LOC_B = 0x36c0; - uint256 internal constant NU_CHALLENGE_INPUT_LOC_C = 0x36e0; - - bytes4 internal constant INVALID_VERIFICATION_KEY_SELECTOR = 0x7e5769bf; - bytes4 internal constant POINT_NOT_ON_CURVE_SELECTOR = 0xa3dad654; - bytes4 internal constant PUBLIC_INPUT_INVALID_BN128_G1_POINT_SELECTOR = 0xeba9f4a6; - bytes4 internal constant PUBLIC_INPUT_GE_P_SELECTOR = 0x374a972f; - bytes4 internal constant MOD_EXP_FAILURE_SELECTOR = 0xf894a7bc; - bytes4 internal constant PAIRING_PREAMBLE_FAILED_SELECTOR = 0x01882d81; - bytes4 internal constant OPENING_COMMITMENT_FAILED_SELECTOR = 0x4e719763; - bytes4 internal constant PAIRING_FAILED_SELECTOR = 0xd71fd263; - - uint256 internal constant ETA_INPUT_LENGTH = 0xc0; // W1, W2, W3 = 6 * 0x20 bytes - - // We need to hash 41 field elements when generating the NU challenge - // w1, w2, w3, w4, s, z, z_lookup, q1, q2, q3, q4, qm, qc, qarith (14) - // qsort, qelliptic, qaux, sigma1, sigma2, sigma, sigma4, (7) - // table1, table2, table3, table4, tabletype, id1, id2, id3, id4, (9) - // w1_omega, w2_omega, w3_omega, w4_omega, s_omega, z_omega, z_lookup_omega, (7) - // table1_omega, table2_omega, table3_omega, table4_omega (4) - uint256 internal constant NU_INPUT_LENGTH = 0x520; // 0x520 = 41 * 0x20 - - // There are ELEVEN G1 group elements added into the transcript in the `beta` round, that we need to skip over - // W1, W2, W3, W4, S, Z, Z_LOOKUP, T1, T2, T3, T4 - uint256 internal constant NU_CALLDATA_SKIP_LENGTH = 0x2c0; // 11 * 0x40 = 0x2c0 - - uint256 internal constant NEGATIVE_INVERSE_OF_2_MODULO_P = - 0x183227397098d014dc2822db40c0ac2e9419f4243cdcb848a1f0fac9f8000000; - uint256 internal constant LIMB_SIZE = 0x100000000000000000; // 2<<68 - uint256 internal constant SUBLIMB_SHIFT = 0x4000; // 2<<14 - - // y^2 = x^3 + ax + b - // for Grumpkin, a = 0 and b = -17. We use b in a custom gate relation that evaluates elliptic curve arithmetic - uint256 internal constant GRUMPKIN_CURVE_B_PARAMETER_NEGATED = 17; - - error INVALID_VERIFICATION_KEY(); - error POINT_NOT_ON_CURVE(); - error PUBLIC_INPUT_COUNT_INVALID(uint256 expected, uint256 actual); - error PUBLIC_INPUT_INVALID_BN128_G1_POINT(); - error PUBLIC_INPUT_GE_P(); - error MOD_EXP_FAILURE(); - error PAIRING_PREAMBLE_FAILED(); - error OPENING_COMMITMENT_FAILED(); - error PAIRING_FAILED(); - - function getVerificationKeyHash() public pure virtual returns (bytes32); - - /** - * @dev We assume that the verification key loaded by this function is constant as we only verify it on deployment - */ - function loadVerificationKey(uint256 _vk, uint256 _omegaInverseLoc) internal pure virtual; - - constructor() { - loadVerificationKey(N_LOC, OMEGA_INVERSE_LOC); - - // We verify that all of the EC points in the verification key lie on the bn128 curve. - assembly { - let q := 21888242871839275222246405745257275088696311157297823662689037894645226208583 // EC group order - - let success := 1 - - // VALIDATE Q1 - { - let x := mload(Q1_X_LOC) - let y := mload(Q1_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE Q2 - { - let x := mload(Q2_X_LOC) - let y := mload(Q2_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE Q3 - { - let x := mload(Q3_X_LOC) - let y := mload(Q3_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE Q4 - { - let x := mload(Q4_X_LOC) - let y := mload(Q4_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - mstore(0x00, x) - mstore(0x20, y) - } - // VALIDATE QM - { - let x := mload(QM_X_LOC) - let y := mload(QM_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE QC - { - let x := mload(QC_X_LOC) - let y := mload(QC_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE QARITH - { - let x := mload(QARITH_X_LOC) - let y := mload(QARITH_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE QSORT - { - let x := mload(QSORT_X_LOC) - let y := mload(QSORT_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE QELLIPTIC - { - let x := mload(QELLIPTIC_X_LOC) - let y := mload(QELLIPTIC_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE QAUX - { - let x := mload(QAUX_X_LOC) - let y := mload(QAUX_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE SIGMA1 - { - let x := mload(SIGMA1_X_LOC) - let y := mload(SIGMA1_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE SIGMA2 - { - let x := mload(SIGMA2_X_LOC) - let y := mload(SIGMA2_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE SIGMA3 - { - let x := mload(SIGMA3_X_LOC) - let y := mload(SIGMA3_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE SIGMA4 - { - let x := mload(SIGMA4_X_LOC) - let y := mload(SIGMA4_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE TABLE1 - { - let x := mload(TABLE1_X_LOC) - let y := mload(TABLE1_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE TABLE2 - { - let x := mload(TABLE2_X_LOC) - let y := mload(TABLE2_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE TABLE3 - { - let x := mload(TABLE3_X_LOC) - let y := mload(TABLE3_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE TABLE4 - { - let x := mload(TABLE4_X_LOC) - let y := mload(TABLE4_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE TABLE_TYPE - { - let x := mload(TABLE_TYPE_X_LOC) - let y := mload(TABLE_TYPE_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE ID1 - { - let x := mload(ID1_X_LOC) - let y := mload(ID1_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE ID2 - { - let x := mload(ID2_X_LOC) - let y := mload(ID2_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE ID3 - { - let x := mload(ID3_X_LOC) - let y := mload(ID3_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE ID4 - { - let x := mload(ID4_X_LOC) - let y := mload(ID4_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - - if iszero(success) { - mstore(0x0, INVALID_VERIFICATION_KEY_SELECTOR) - revert(0x00, 0x04) - } - } - } - - /** - * @notice Verify a Ultra Plonk proof - * @param _proof - The serialized proof - * @param _publicInputs - An array of the public inputs - * @return True if proof is valid, reverts otherwise - */ - function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool) { - loadVerificationKey(N_LOC, OMEGA_INVERSE_LOC); - - uint256 requiredPublicInputCount; - assembly { - requiredPublicInputCount := mload(NUM_INPUTS_LOC) - } - if (requiredPublicInputCount != _publicInputs.length) { - revert PUBLIC_INPUT_COUNT_INVALID(requiredPublicInputCount, _publicInputs.length); - } - - assembly { - let q := 21888242871839275222246405745257275088696311157297823662689037894645226208583 // EC group order - let p := 21888242871839275222246405745257275088548364400416034343698204186575808495617 // Prime field order - - /** - * LOAD PROOF FROM CALLDATA - */ - { - let data_ptr := add(calldataload(0x04), 0x24) - - mstore(W1_Y_LOC, mod(calldataload(data_ptr), q)) - mstore(W1_X_LOC, mod(calldataload(add(data_ptr, 0x20)), q)) - - mstore(W2_Y_LOC, mod(calldataload(add(data_ptr, 0x40)), q)) - mstore(W2_X_LOC, mod(calldataload(add(data_ptr, 0x60)), q)) - - mstore(W3_Y_LOC, mod(calldataload(add(data_ptr, 0x80)), q)) - mstore(W3_X_LOC, mod(calldataload(add(data_ptr, 0xa0)), q)) - - mstore(W4_Y_LOC, mod(calldataload(add(data_ptr, 0xc0)), q)) - mstore(W4_X_LOC, mod(calldataload(add(data_ptr, 0xe0)), q)) - - mstore(S_Y_LOC, mod(calldataload(add(data_ptr, 0x100)), q)) - mstore(S_X_LOC, mod(calldataload(add(data_ptr, 0x120)), q)) - mstore(Z_Y_LOC, mod(calldataload(add(data_ptr, 0x140)), q)) - mstore(Z_X_LOC, mod(calldataload(add(data_ptr, 0x160)), q)) - mstore(Z_LOOKUP_Y_LOC, mod(calldataload(add(data_ptr, 0x180)), q)) - mstore(Z_LOOKUP_X_LOC, mod(calldataload(add(data_ptr, 0x1a0)), q)) - mstore(T1_Y_LOC, mod(calldataload(add(data_ptr, 0x1c0)), q)) - mstore(T1_X_LOC, mod(calldataload(add(data_ptr, 0x1e0)), q)) - - mstore(T2_Y_LOC, mod(calldataload(add(data_ptr, 0x200)), q)) - mstore(T2_X_LOC, mod(calldataload(add(data_ptr, 0x220)), q)) - - mstore(T3_Y_LOC, mod(calldataload(add(data_ptr, 0x240)), q)) - mstore(T3_X_LOC, mod(calldataload(add(data_ptr, 0x260)), q)) - - mstore(T4_Y_LOC, mod(calldataload(add(data_ptr, 0x280)), q)) - mstore(T4_X_LOC, mod(calldataload(add(data_ptr, 0x2a0)), q)) - - mstore(W1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x2c0)), p)) - mstore(W2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x2e0)), p)) - mstore(W3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x300)), p)) - mstore(W4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x320)), p)) - mstore(S_EVAL_LOC, mod(calldataload(add(data_ptr, 0x340)), p)) - mstore(Z_EVAL_LOC, mod(calldataload(add(data_ptr, 0x360)), p)) - mstore(Z_LOOKUP_EVAL_LOC, mod(calldataload(add(data_ptr, 0x380)), p)) - mstore(Q1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x3a0)), p)) - mstore(Q2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x3c0)), p)) - mstore(Q3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x3e0)), p)) - mstore(Q4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x400)), p)) - mstore(QM_EVAL_LOC, mod(calldataload(add(data_ptr, 0x420)), p)) - mstore(QC_EVAL_LOC, mod(calldataload(add(data_ptr, 0x440)), p)) - mstore(QARITH_EVAL_LOC, mod(calldataload(add(data_ptr, 0x460)), p)) - mstore(QSORT_EVAL_LOC, mod(calldataload(add(data_ptr, 0x480)), p)) - mstore(QELLIPTIC_EVAL_LOC, mod(calldataload(add(data_ptr, 0x4a0)), p)) - mstore(QAUX_EVAL_LOC, mod(calldataload(add(data_ptr, 0x4c0)), p)) - - mstore(SIGMA1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x4e0)), p)) - mstore(SIGMA2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x500)), p)) - - mstore(SIGMA3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x520)), p)) - mstore(SIGMA4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x540)), p)) - - mstore(TABLE1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x560)), p)) - mstore(TABLE2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x580)), p)) - mstore(TABLE3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x5a0)), p)) - mstore(TABLE4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x5c0)), p)) - mstore(TABLE_TYPE_EVAL_LOC, mod(calldataload(add(data_ptr, 0x5e0)), p)) - - mstore(ID1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x600)), p)) - mstore(ID2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x620)), p)) - mstore(ID3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x640)), p)) - mstore(ID4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x660)), p)) - - mstore(W1_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x680)), p)) - mstore(W2_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x6a0)), p)) - mstore(W3_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x6c0)), p)) - mstore(W4_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x6e0)), p)) - mstore(S_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x700)), p)) - - mstore(Z_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x720)), p)) - - mstore(Z_LOOKUP_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x740)), p)) - mstore(TABLE1_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x760)), p)) - mstore(TABLE2_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x780)), p)) - mstore(TABLE3_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x7a0)), p)) - mstore(TABLE4_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x7c0)), p)) - - mstore(PI_Z_Y_LOC, mod(calldataload(add(data_ptr, 0x7e0)), q)) - mstore(PI_Z_X_LOC, mod(calldataload(add(data_ptr, 0x800)), q)) - - mstore(PI_Z_OMEGA_Y_LOC, mod(calldataload(add(data_ptr, 0x820)), q)) - mstore(PI_Z_OMEGA_X_LOC, mod(calldataload(add(data_ptr, 0x840)), q)) - } - - /** - * LOAD RECURSIVE PROOF INTO MEMORY - */ - { - if mload(CONTAINS_RECURSIVE_PROOF_LOC) { - let public_inputs_ptr := add(calldataload(0x24), 0x24) - let index_counter := add(shl(5, mload(RECURSIVE_PROOF_PUBLIC_INPUT_INDICES_LOC)), public_inputs_ptr) - - let x0 := calldataload(index_counter) - x0 := add(x0, shl(68, calldataload(add(index_counter, 0x20)))) - x0 := add(x0, shl(136, calldataload(add(index_counter, 0x40)))) - x0 := add(x0, shl(204, calldataload(add(index_counter, 0x60)))) - let y0 := calldataload(add(index_counter, 0x80)) - y0 := add(y0, shl(68, calldataload(add(index_counter, 0xa0)))) - y0 := add(y0, shl(136, calldataload(add(index_counter, 0xc0)))) - y0 := add(y0, shl(204, calldataload(add(index_counter, 0xe0)))) - let x1 := calldataload(add(index_counter, 0x100)) - x1 := add(x1, shl(68, calldataload(add(index_counter, 0x120)))) - x1 := add(x1, shl(136, calldataload(add(index_counter, 0x140)))) - x1 := add(x1, shl(204, calldataload(add(index_counter, 0x160)))) - let y1 := calldataload(add(index_counter, 0x180)) - y1 := add(y1, shl(68, calldataload(add(index_counter, 0x1a0)))) - y1 := add(y1, shl(136, calldataload(add(index_counter, 0x1c0)))) - y1 := add(y1, shl(204, calldataload(add(index_counter, 0x1e0)))) - mstore(RECURSIVE_P1_X_LOC, x0) - mstore(RECURSIVE_P1_Y_LOC, y0) - mstore(RECURSIVE_P2_X_LOC, x1) - mstore(RECURSIVE_P2_Y_LOC, y1) - - // validate these are valid bn128 G1 points - if iszero(and(and(lt(x0, q), lt(x1, q)), and(lt(y0, q), lt(y1, q)))) { - mstore(0x00, PUBLIC_INPUT_INVALID_BN128_G1_POINT_SELECTOR) - revert(0x00, 0x04) - } - } - } - - { - /** - * Generate initial challenge - */ - mstore(0x00, shl(224, mload(N_LOC))) - mstore(0x04, shl(224, mload(NUM_INPUTS_LOC))) - let challenge := keccak256(0x00, 0x08) - - /** - * Generate eta challenge - */ - mstore(PUBLIC_INPUTS_HASH_LOCATION, challenge) - // The public input location is stored at 0x24, we then add 0x24 to skip selector and the length of public inputs - let public_inputs_start := add(calldataload(0x24), 0x24) - // copy the public inputs over - let public_input_size := mul(mload(NUM_INPUTS_LOC), 0x20) - calldatacopy(add(PUBLIC_INPUTS_HASH_LOCATION, 0x20), public_inputs_start, public_input_size) - - // copy W1, W2, W3 into challenge. Each point is 0x40 bytes, so load 0xc0 = 3 * 0x40 bytes (ETA input length) - let w_start := add(calldataload(0x04), 0x24) - calldatacopy(add(add(PUBLIC_INPUTS_HASH_LOCATION, 0x20), public_input_size), w_start, ETA_INPUT_LENGTH) - - // Challenge is the old challenge + public inputs + W1, W2, W3 (0x20 + public_input_size + 0xc0) - let challenge_bytes_size := add(0x20, add(public_input_size, ETA_INPUT_LENGTH)) - - challenge := keccak256(PUBLIC_INPUTS_HASH_LOCATION, challenge_bytes_size) - { - let eta := mod(challenge, p) - mstore(C_ETA_LOC, eta) - mstore(C_ETA_SQR_LOC, mulmod(eta, eta, p)) - mstore(C_ETA_CUBE_LOC, mulmod(mload(C_ETA_SQR_LOC), eta, p)) - } - - /** - * Generate beta challenge - */ - mstore(0x00, challenge) - mstore(0x20, mload(W4_Y_LOC)) - mstore(0x40, mload(W4_X_LOC)) - mstore(0x60, mload(S_Y_LOC)) - mstore(0x80, mload(S_X_LOC)) - challenge := keccak256(0x00, 0xa0) - mstore(C_BETA_LOC, mod(challenge, p)) - - /** - * Generate gamma challenge - */ - mstore(0x00, challenge) - mstore8(0x20, 0x01) - challenge := keccak256(0x00, 0x21) - mstore(C_GAMMA_LOC, mod(challenge, p)) - - /** - * Generate alpha challenge - */ - mstore(0x00, challenge) - mstore(0x20, mload(Z_Y_LOC)) - mstore(0x40, mload(Z_X_LOC)) - mstore(0x60, mload(Z_LOOKUP_Y_LOC)) - mstore(0x80, mload(Z_LOOKUP_X_LOC)) - challenge := keccak256(0x00, 0xa0) - mstore(C_ALPHA_LOC, mod(challenge, p)) - - /** - * Compute and store some powers of alpha for future computations - */ - let alpha := mload(C_ALPHA_LOC) - mstore(C_ALPHA_SQR_LOC, mulmod(alpha, alpha, p)) - mstore(C_ALPHA_CUBE_LOC, mulmod(mload(C_ALPHA_SQR_LOC), alpha, p)) - mstore(C_ALPHA_QUAD_LOC, mulmod(mload(C_ALPHA_CUBE_LOC), alpha, p)) - mstore(C_ALPHA_BASE_LOC, alpha) - - /** - * Generate zeta challenge - */ - mstore(0x00, challenge) - mstore(0x20, mload(T1_Y_LOC)) - mstore(0x40, mload(T1_X_LOC)) - mstore(0x60, mload(T2_Y_LOC)) - mstore(0x80, mload(T2_X_LOC)) - mstore(0xa0, mload(T3_Y_LOC)) - mstore(0xc0, mload(T3_X_LOC)) - mstore(0xe0, mload(T4_Y_LOC)) - mstore(0x100, mload(T4_X_LOC)) - - challenge := keccak256(0x00, 0x120) - - mstore(C_ZETA_LOC, mod(challenge, p)) - mstore(C_CURRENT_LOC, challenge) - } - - /** - * EVALUATE FIELD OPERATIONS - */ - - /** - * COMPUTE PUBLIC INPUT DELTA - * ΔPI = ∏ᵢ∈ℓ(wᵢ + β σ(i) + γ) / ∏ᵢ∈ℓ(wᵢ + β σ'(i) + γ) - */ - { - let beta := mload(C_BETA_LOC) // β - let gamma := mload(C_GAMMA_LOC) // γ - let work_root := mload(OMEGA_LOC) // ω - let numerator_value := 1 - let denominator_value := 1 - - let p_clone := p // move p to the front of the stack - let valid_inputs := true - - // Load the starting point of the public inputs (jump over the selector and the length of public inputs [0x24]) - let public_inputs_ptr := add(calldataload(0x24), 0x24) - - // endpoint_ptr = public_inputs_ptr + num_inputs * 0x20. // every public input is 0x20 bytes - let endpoint_ptr := add(public_inputs_ptr, mul(mload(NUM_INPUTS_LOC), 0x20)) - - // root_1 = β * 0x05 - let root_1 := mulmod(beta, 0x05, p_clone) // k1.β - // root_2 = β * 0x0c - let root_2 := mulmod(beta, 0x0c, p_clone) - // @note 0x05 + 0x07 == 0x0c == external coset generator - - for {} lt(public_inputs_ptr, endpoint_ptr) { public_inputs_ptr := add(public_inputs_ptr, 0x20) } { - /** - * input = public_input[i] - * valid_inputs &= input < p - * temp = input + gamma - * numerator_value *= (β.σ(i) + wᵢ + γ) // σ(i) = 0x05.ωⁱ - * denominator_value *= (β.σ'(i) + wᵢ + γ) // σ'(i) = 0x0c.ωⁱ - * root_1 *= ω - * root_2 *= ω - */ - - let input := calldataload(public_inputs_ptr) - valid_inputs := and(valid_inputs, lt(input, p_clone)) - let temp := addmod(input, gamma, p_clone) - - numerator_value := mulmod(numerator_value, add(root_1, temp), p_clone) - denominator_value := mulmod(denominator_value, add(root_2, temp), p_clone) - - root_1 := mulmod(root_1, work_root, p_clone) - root_2 := mulmod(root_2, work_root, p_clone) - } - - // Revert if not all public inputs are field elements (i.e. < p) - if iszero(valid_inputs) { - mstore(0x00, PUBLIC_INPUT_GE_P_SELECTOR) - revert(0x00, 0x04) - } - - mstore(DELTA_NUMERATOR_LOC, numerator_value) - mstore(DELTA_DENOMINATOR_LOC, denominator_value) - } - - /** - * Compute Plookup delta factor [γ(1 + β)]^{n-k} - * k = num roots cut out of Z_H = 4 - */ - { - let delta_base := mulmod(mload(C_GAMMA_LOC), addmod(mload(C_BETA_LOC), 1, p), p) - let delta_numerator := delta_base - { - let exponent := mload(N_LOC) - let count := 1 - for {} lt(count, exponent) { count := add(count, count) } { - delta_numerator := mulmod(delta_numerator, delta_numerator, p) - } - } - mstore(PLOOKUP_DELTA_NUMERATOR_LOC, delta_numerator) - - let delta_denominator := mulmod(delta_base, delta_base, p) - delta_denominator := mulmod(delta_denominator, delta_denominator, p) - mstore(PLOOKUP_DELTA_DENOMINATOR_LOC, delta_denominator) - } - /** - * Compute lagrange poly and vanishing poly fractions - */ - { - /** - * vanishing_numerator = zeta - * ZETA_POW_N = zeta^n - * vanishing_numerator -= 1 - * accumulating_root = omega_inverse - * work_root = p - accumulating_root - * domain_inverse = domain_inverse - * vanishing_denominator = zeta + work_root - * work_root *= accumulating_root - * vanishing_denominator *= (zeta + work_root) - * work_root *= accumulating_root - * vanishing_denominator *= (zeta + work_root) - * vanishing_denominator *= (zeta + (zeta + accumulating_root)) - * work_root = omega - * lagrange_numerator = vanishing_numerator * domain_inverse - * l_start_denominator = zeta - 1 - * accumulating_root = work_root^2 - * l_end_denominator = accumulating_root^2 * work_root * zeta - 1 - * Note: l_end_denominator term contains a term \omega^5 to cut out 5 roots of unity from vanishing poly - */ - - let zeta := mload(C_ZETA_LOC) - - // compute zeta^n, where n is a power of 2 - let vanishing_numerator := zeta - { - // pow_small - let exponent := mload(N_LOC) - let count := 1 - for {} lt(count, exponent) { count := add(count, count) } { - vanishing_numerator := mulmod(vanishing_numerator, vanishing_numerator, p) - } - } - mstore(ZETA_POW_N_LOC, vanishing_numerator) - vanishing_numerator := addmod(vanishing_numerator, sub(p, 1), p) - - let accumulating_root := mload(OMEGA_INVERSE_LOC) - let work_root := sub(p, accumulating_root) - let domain_inverse := mload(DOMAIN_INVERSE_LOC) - - let vanishing_denominator := addmod(zeta, work_root, p) - work_root := mulmod(work_root, accumulating_root, p) - vanishing_denominator := mulmod(vanishing_denominator, addmod(zeta, work_root, p), p) - work_root := mulmod(work_root, accumulating_root, p) - vanishing_denominator := mulmod(vanishing_denominator, addmod(zeta, work_root, p), p) - vanishing_denominator := - mulmod(vanishing_denominator, addmod(zeta, mulmod(work_root, accumulating_root, p), p), p) - - work_root := mload(OMEGA_LOC) - - let lagrange_numerator := mulmod(vanishing_numerator, domain_inverse, p) - let l_start_denominator := addmod(zeta, sub(p, 1), p) - - accumulating_root := mulmod(work_root, work_root, p) - - let l_end_denominator := - addmod( - mulmod(mulmod(mulmod(accumulating_root, accumulating_root, p), work_root, p), zeta, p), sub(p, 1), p - ) - - /** - * Compute inversions using Montgomery's batch inversion trick - */ - let accumulator := mload(DELTA_DENOMINATOR_LOC) - let t0 := accumulator - accumulator := mulmod(accumulator, vanishing_denominator, p) - let t1 := accumulator - accumulator := mulmod(accumulator, vanishing_numerator, p) - let t2 := accumulator - accumulator := mulmod(accumulator, l_start_denominator, p) - let t3 := accumulator - accumulator := mulmod(accumulator, mload(PLOOKUP_DELTA_DENOMINATOR_LOC), p) - let t4 := accumulator - { - mstore(0, 0x20) - mstore(0x20, 0x20) - mstore(0x40, 0x20) - mstore(0x60, mulmod(accumulator, l_end_denominator, p)) - mstore(0x80, sub(p, 2)) - mstore(0xa0, p) - if iszero(staticcall(gas(), 0x05, 0x00, 0xc0, 0x00, 0x20)) { - mstore(0x0, MOD_EXP_FAILURE_SELECTOR) - revert(0x00, 0x04) - } - accumulator := mload(0x00) - } - - t4 := mulmod(accumulator, t4, p) - accumulator := mulmod(accumulator, l_end_denominator, p) - - t3 := mulmod(accumulator, t3, p) - accumulator := mulmod(accumulator, mload(PLOOKUP_DELTA_DENOMINATOR_LOC), p) - - t2 := mulmod(accumulator, t2, p) - accumulator := mulmod(accumulator, l_start_denominator, p) - - t1 := mulmod(accumulator, t1, p) - accumulator := mulmod(accumulator, vanishing_numerator, p) - - t0 := mulmod(accumulator, t0, p) - accumulator := mulmod(accumulator, vanishing_denominator, p) - - accumulator := mulmod(mulmod(accumulator, accumulator, p), mload(DELTA_DENOMINATOR_LOC), p) - - mstore(PUBLIC_INPUT_DELTA_LOC, mulmod(mload(DELTA_NUMERATOR_LOC), accumulator, p)) - mstore(ZERO_POLY_LOC, mulmod(vanishing_numerator, t0, p)) - mstore(ZERO_POLY_INVERSE_LOC, mulmod(vanishing_denominator, t1, p)) - mstore(L_START_LOC, mulmod(lagrange_numerator, t2, p)) - mstore(PLOOKUP_DELTA_LOC, mulmod(mload(PLOOKUP_DELTA_NUMERATOR_LOC), t3, p)) - mstore(L_END_LOC, mulmod(lagrange_numerator, t4, p)) - } - - /** - * UltraPlonk Widget Ordering: - * - * 1. Permutation widget - * 2. Plookup widget - * 3. Arithmetic widget - * 4. Fixed base widget (?) - * 5. GenPermSort widget - * 6. Elliptic widget - * 7. Auxiliary widget - */ - - /** - * COMPUTE PERMUTATION WIDGET EVALUATION - */ - { - let alpha := mload(C_ALPHA_LOC) - let beta := mload(C_BETA_LOC) - let gamma := mload(C_GAMMA_LOC) - - /** - * t1 = (W1 + gamma + beta * ID1) * (W2 + gamma + beta * ID2) - * t2 = (W3 + gamma + beta * ID3) * (W4 + gamma + beta * ID4) - * result = alpha_base * z_eval * t1 * t2 - * t1 = (W1 + gamma + beta * sigma_1_eval) * (W2 + gamma + beta * sigma_2_eval) - * t2 = (W2 + gamma + beta * sigma_3_eval) * (W3 + gamma + beta * sigma_4_eval) - * result -= (alpha_base * z_omega_eval * t1 * t2) - */ - let t1 := - mulmod( - add(add(mload(W1_EVAL_LOC), gamma), mulmod(beta, mload(ID1_EVAL_LOC), p)), - add(add(mload(W2_EVAL_LOC), gamma), mulmod(beta, mload(ID2_EVAL_LOC), p)), - p - ) - let t2 := - mulmod( - add(add(mload(W3_EVAL_LOC), gamma), mulmod(beta, mload(ID3_EVAL_LOC), p)), - add(add(mload(W4_EVAL_LOC), gamma), mulmod(beta, mload(ID4_EVAL_LOC), p)), - p - ) - let result := mulmod(mload(C_ALPHA_BASE_LOC), mulmod(mload(Z_EVAL_LOC), mulmod(t1, t2, p), p), p) - t1 := - mulmod( - add(add(mload(W1_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA1_EVAL_LOC), p)), - add(add(mload(W2_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA2_EVAL_LOC), p)), - p - ) - t2 := - mulmod( - add(add(mload(W3_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA3_EVAL_LOC), p)), - add(add(mload(W4_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA4_EVAL_LOC), p)), - p - ) - result := - addmod( - result, - sub(p, mulmod(mload(C_ALPHA_BASE_LOC), mulmod(mload(Z_OMEGA_EVAL_LOC), mulmod(t1, t2, p), p), p)), - p - ) - - /** - * alpha_base *= alpha - * result += alpha_base . (L_{n-k}(ʓ) . (z(ʓ.ω) - ∆_{PI})) - * alpha_base *= alpha - * result += alpha_base . (L_1(ʓ)(Z(ʓ) - 1)) - * alpha_Base *= alpha - */ - mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p)) - result := - addmod( - result, - mulmod( - mload(C_ALPHA_BASE_LOC), - mulmod( - mload(L_END_LOC), - addmod(mload(Z_OMEGA_EVAL_LOC), sub(p, mload(PUBLIC_INPUT_DELTA_LOC)), p), - p - ), - p - ), - p - ) - mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p)) - mstore( - PERMUTATION_IDENTITY, - addmod( - result, - mulmod( - mload(C_ALPHA_BASE_LOC), - mulmod(mload(L_START_LOC), addmod(mload(Z_EVAL_LOC), sub(p, 1), p), p), - p - ), - p - ) - ) - mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p)) - } - - /** - * COMPUTE PLOOKUP WIDGET EVALUATION - */ - { - /** - * Goal: f = (w1(z) + q2.w1(zω)) + η(w2(z) + qm.w2(zω)) + η²(w3(z) + qc.w_3(zω)) + q3(z).η³ - * f = η.q3(z) - * f += (w3(z) + qc.w_3(zω)) - * f *= η - * f += (w2(z) + qm.w2(zω)) - * f *= η - * f += (w1(z) + q2.w1(zω)) - */ - let f := mulmod(mload(C_ETA_LOC), mload(Q3_EVAL_LOC), p) - f := - addmod(f, addmod(mload(W3_EVAL_LOC), mulmod(mload(QC_EVAL_LOC), mload(W3_OMEGA_EVAL_LOC), p), p), p) - f := mulmod(f, mload(C_ETA_LOC), p) - f := - addmod(f, addmod(mload(W2_EVAL_LOC), mulmod(mload(QM_EVAL_LOC), mload(W2_OMEGA_EVAL_LOC), p), p), p) - f := mulmod(f, mload(C_ETA_LOC), p) - f := - addmod(f, addmod(mload(W1_EVAL_LOC), mulmod(mload(Q2_EVAL_LOC), mload(W1_OMEGA_EVAL_LOC), p), p), p) - - // t(z) = table4(z).η³ + table3(z).η² + table2(z).η + table1(z) - let t := - addmod( - addmod( - addmod( - mulmod(mload(TABLE4_EVAL_LOC), mload(C_ETA_CUBE_LOC), p), - mulmod(mload(TABLE3_EVAL_LOC), mload(C_ETA_SQR_LOC), p), - p - ), - mulmod(mload(TABLE2_EVAL_LOC), mload(C_ETA_LOC), p), - p - ), - mload(TABLE1_EVAL_LOC), - p - ) - - // t(zw) = table4(zw).η³ + table3(zw).η² + table2(zw).η + table1(zw) - let t_omega := - addmod( - addmod( - addmod( - mulmod(mload(TABLE4_OMEGA_EVAL_LOC), mload(C_ETA_CUBE_LOC), p), - mulmod(mload(TABLE3_OMEGA_EVAL_LOC), mload(C_ETA_SQR_LOC), p), - p - ), - mulmod(mload(TABLE2_OMEGA_EVAL_LOC), mload(C_ETA_LOC), p), - p - ), - mload(TABLE1_OMEGA_EVAL_LOC), - p - ) - - /** - * Goal: numerator = (TABLE_TYPE_EVAL * f(z) + γ) * (t(z) + βt(zω) + γ(β + 1)) * (β + 1) - * gamma_beta_constant = γ(β + 1) - * numerator = f * TABLE_TYPE_EVAL + gamma - * temp0 = t(z) + t(zω) * β + gamma_beta_constant - * numerator *= temp0 - * numerator *= (β + 1) - * temp0 = alpha * l_1 - * numerator += temp0 - * numerator *= z_lookup(z) - * numerator -= temp0 - */ - let gamma_beta_constant := mulmod(mload(C_GAMMA_LOC), addmod(mload(C_BETA_LOC), 1, p), p) - let numerator := addmod(mulmod(f, mload(TABLE_TYPE_EVAL_LOC), p), mload(C_GAMMA_LOC), p) - let temp0 := addmod(addmod(t, mulmod(t_omega, mload(C_BETA_LOC), p), p), gamma_beta_constant, p) - numerator := mulmod(numerator, temp0, p) - numerator := mulmod(numerator, addmod(mload(C_BETA_LOC), 1, p), p) - temp0 := mulmod(mload(C_ALPHA_LOC), mload(L_START_LOC), p) - numerator := addmod(numerator, temp0, p) - numerator := mulmod(numerator, mload(Z_LOOKUP_EVAL_LOC), p) - numerator := addmod(numerator, sub(p, temp0), p) - - /** - * Goal: denominator = z_lookup(zω)*[s(z) + βs(zω) + γ(1 + β)] - [z_lookup(zω) - [γ(1 + β)]^{n-k}]*α²L_end(z) - * note: delta_factor = [γ(1 + β)]^{n-k} - * denominator = s(z) + βs(zω) + γ(β + 1) - * temp1 = α²L_end(z) - * denominator -= temp1 - * denominator *= z_lookup(zω) - * denominator += temp1 * delta_factor - * PLOOKUP_IDENTITY = (numerator - denominator).alpha_base - * alpha_base *= alpha^3 - */ - let denominator := - addmod( - addmod(mload(S_EVAL_LOC), mulmod(mload(S_OMEGA_EVAL_LOC), mload(C_BETA_LOC), p), p), - gamma_beta_constant, - p - ) - let temp1 := mulmod(mload(C_ALPHA_SQR_LOC), mload(L_END_LOC), p) - denominator := addmod(denominator, sub(p, temp1), p) - denominator := mulmod(denominator, mload(Z_LOOKUP_OMEGA_EVAL_LOC), p) - denominator := addmod(denominator, mulmod(temp1, mload(PLOOKUP_DELTA_LOC), p), p) - - mstore(PLOOKUP_IDENTITY, mulmod(addmod(numerator, sub(p, denominator), p), mload(C_ALPHA_BASE_LOC), p)) - - // update alpha - mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_CUBE_LOC), p)) - } - - /** - * COMPUTE ARITHMETIC WIDGET EVALUATION - */ - { - /** - * The basic arithmetic gate identity in standard plonk is as follows. - * (w_1 . w_2 . q_m) + (w_1 . q_1) + (w_2 . q_2) + (w_3 . q_3) + (w_4 . q_4) + q_c = 0 - * However, for Ultraplonk, we extend this to support "passing" wires between rows (shown without alpha scaling below): - * q_arith * ( ( (-1/2) * (q_arith - 3) * q_m * w_1 * w_2 + q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c ) + - * (q_arith - 1)*( α * (q_arith - 2) * (w_1 + w_4 - w_1_omega + q_m) + w_4_omega) ) = 0 - * - * This formula results in several cases depending on q_arith: - * 1. q_arith == 0: Arithmetic gate is completely disabled - * - * 2. q_arith == 1: Everything in the minigate on the right is disabled. The equation is just a standard plonk equation - * with extra wires: q_m * w_1 * w_2 + q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c = 0 - * - * 3. q_arith == 2: The (w_1 + w_4 - ...) term is disabled. THe equation is: - * (1/2) * q_m * w_1 * w_2 + q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c + w_4_omega = 0 - * It allows defining w_4 at next index (w_4_omega) in terms of current wire values - * - * 4. q_arith == 3: The product of w_1 and w_2 is disabled, but a mini addition gate is enabled. α allows us to split - * the equation into two: - * - * q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c + 2 * w_4_omega = 0 - * and - * w_1 + w_4 - w_1_omega + q_m = 0 (we are reusing q_m here) - * - * 5. q_arith > 3: The product of w_1 and w_2 is scaled by (q_arith - 3), while the w_4_omega term is scaled by (q_arith - 1). - * The equation can be split into two: - * - * (q_arith - 3)* q_m * w_1 * w_ 2 + q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c + (q_arith - 1) * w_4_omega = 0 - * and - * w_1 + w_4 - w_1_omega + q_m = 0 - * - * The problem that q_m is used both in both equations can be dealt with by appropriately changing selector values at - * the next gate. Then we can treat (q_arith - 1) as a simulated q_6 selector and scale q_m to handle (q_arith - 3) at - * product. - */ - - let w1q1 := mulmod(mload(W1_EVAL_LOC), mload(Q1_EVAL_LOC), p) - let w2q2 := mulmod(mload(W2_EVAL_LOC), mload(Q2_EVAL_LOC), p) - let w3q3 := mulmod(mload(W3_EVAL_LOC), mload(Q3_EVAL_LOC), p) - let w4q3 := mulmod(mload(W4_EVAL_LOC), mload(Q4_EVAL_LOC), p) - - // @todo - Add a explicit test that hits QARITH == 3 - // w1w2qm := (w_1 . w_2 . q_m . (QARITH_EVAL_LOC - 3)) / 2 - let w1w2qm := - mulmod( - mulmod( - mulmod(mulmod(mload(W1_EVAL_LOC), mload(W2_EVAL_LOC), p), mload(QM_EVAL_LOC), p), - addmod(mload(QARITH_EVAL_LOC), sub(p, 3), p), - p - ), - NEGATIVE_INVERSE_OF_2_MODULO_P, - p - ) - - // (w_1 . w_2 . q_m . (q_arith - 3)) / -2) + (w_1 . q_1) + (w_2 . q_2) + (w_3 . q_3) + (w_4 . q_4) + q_c - let identity := - addmod( - mload(QC_EVAL_LOC), addmod(w4q3, addmod(w3q3, addmod(w2q2, addmod(w1q1, w1w2qm, p), p), p), p), p - ) - - // if q_arith == 3 we evaluate an additional mini addition gate (on top of the regular one), where: - // w_1 + w_4 - w_1_omega + q_m = 0 - // we use this gate to save an addition gate when adding or subtracting non-native field elements - // α * (q_arith - 2) * (w_1 + w_4 - w_1_omega + q_m) - let extra_small_addition_gate_identity := - mulmod( - mload(C_ALPHA_LOC), - mulmod( - addmod(mload(QARITH_EVAL_LOC), sub(p, 2), p), - addmod( - mload(QM_EVAL_LOC), - addmod( - sub(p, mload(W1_OMEGA_EVAL_LOC)), addmod(mload(W1_EVAL_LOC), mload(W4_EVAL_LOC), p), p - ), - p - ), - p - ), - p - ) - - // if q_arith == 2 OR q_arith == 3 we add the 4th wire of the NEXT gate into the arithmetic identity - // N.B. if q_arith > 2, this wire value will be scaled by (q_arith - 1) relative to the other gate wires! - // alpha_base * q_arith * (identity + (q_arith - 1) * (w_4_omega + extra_small_addition_gate_identity)) - mstore( - ARITHMETIC_IDENTITY, - mulmod( - mload(C_ALPHA_BASE_LOC), - mulmod( - mload(QARITH_EVAL_LOC), - addmod( - identity, - mulmod( - addmod(mload(QARITH_EVAL_LOC), sub(p, 1), p), - addmod(mload(W4_OMEGA_EVAL_LOC), extra_small_addition_gate_identity, p), - p - ), - p - ), - p - ), - p - ) - ) - - // update alpha - mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_SQR_LOC), p)) - } - - /** - * COMPUTE GENPERMSORT WIDGET EVALUATION - */ - { - /** - * D1 = (w2 - w1) - * D2 = (w3 - w2) - * D3 = (w4 - w3) - * D4 = (w1_omega - w4) - * - * α_a = alpha_base - * α_b = alpha_base * α - * α_c = alpha_base * α^2 - * α_d = alpha_base * α^3 - * - * range_accumulator = ( - * D1(D1 - 1)(D1 - 2)(D1 - 3).α_a + - * D2(D2 - 1)(D2 - 2)(D2 - 3).α_b + - * D3(D3 - 1)(D3 - 2)(D3 - 3).α_c + - * D4(D4 - 1)(D4 - 2)(D4 - 3).α_d + - * ) . q_sort - */ - let minus_two := sub(p, 2) - let minus_three := sub(p, 3) - let d1 := addmod(mload(W2_EVAL_LOC), sub(p, mload(W1_EVAL_LOC)), p) - let d2 := addmod(mload(W3_EVAL_LOC), sub(p, mload(W2_EVAL_LOC)), p) - let d3 := addmod(mload(W4_EVAL_LOC), sub(p, mload(W3_EVAL_LOC)), p) - let d4 := addmod(mload(W1_OMEGA_EVAL_LOC), sub(p, mload(W4_EVAL_LOC)), p) - - let range_accumulator := - mulmod( - mulmod( - mulmod(addmod(mulmod(d1, d1, p), sub(p, d1), p), addmod(d1, minus_two, p), p), - addmod(d1, minus_three, p), - p - ), - mload(C_ALPHA_BASE_LOC), - p - ) - range_accumulator := - addmod( - range_accumulator, - mulmod( - mulmod( - mulmod(addmod(mulmod(d2, d2, p), sub(p, d2), p), addmod(d2, minus_two, p), p), - addmod(d2, minus_three, p), - p - ), - mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p), - p - ), - p - ) - range_accumulator := - addmod( - range_accumulator, - mulmod( - mulmod( - mulmod(addmod(mulmod(d3, d3, p), sub(p, d3), p), addmod(d3, minus_two, p), p), - addmod(d3, minus_three, p), - p - ), - mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_SQR_LOC), p), - p - ), - p - ) - range_accumulator := - addmod( - range_accumulator, - mulmod( - mulmod( - mulmod(addmod(mulmod(d4, d4, p), sub(p, d4), p), addmod(d4, minus_two, p), p), - addmod(d4, minus_three, p), - p - ), - mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_CUBE_LOC), p), - p - ), - p - ) - range_accumulator := mulmod(range_accumulator, mload(QSORT_EVAL_LOC), p) - - mstore(SORT_IDENTITY, range_accumulator) - - // update alpha - mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_QUAD_LOC), p)) - } - - /** - * COMPUTE ELLIPTIC WIDGET EVALUATION - */ - { - /** - * endo_term = (-x_2) * x_1 * (x_3 * 2 + x_1) * q_beta - * endo_sqr_term = x_2^2 - * endo_sqr_term *= (x_3 - x_1) - * endo_sqr_term *= q_beta^2 - * leftovers = x_2^2 - * leftovers *= x_2 - * leftovers += x_1^2 * (x_3 + x_1) @follow-up Invalid comment in BB widget - * leftovers -= (y_2^2 + y_1^2) - * sign_term = y_2 * y_1 - * sign_term += sign_term - * sign_term *= q_sign - */ - // q_elliptic * (x3 + x2 + x1)(x2 - x1)(x2 - x1) - y2^2 - y1^2 + 2(y2y1)*q_sign = 0 - let x_diff := addmod(mload(X2_EVAL_LOC), sub(p, mload(X1_EVAL_LOC)), p) - let y2_sqr := mulmod(mload(Y2_EVAL_LOC), mload(Y2_EVAL_LOC), p) - let y1_sqr := mulmod(mload(Y1_EVAL_LOC), mload(Y1_EVAL_LOC), p) - let y1y2 := mulmod(mulmod(mload(Y1_EVAL_LOC), mload(Y2_EVAL_LOC), p), mload(QSIGN_LOC), p) - - let x_add_identity := - addmod( - mulmod( - addmod(mload(X3_EVAL_LOC), addmod(mload(X2_EVAL_LOC), mload(X1_EVAL_LOC), p), p), - mulmod(x_diff, x_diff, p), - p - ), - addmod( - sub( - p, - addmod(y2_sqr, y1_sqr, p) - ), - addmod(y1y2, y1y2, p), - p - ), - p - ) - x_add_identity := - mulmod( - mulmod( - x_add_identity, - addmod( - 1, - sub(p, mload(QM_EVAL_LOC)), - p - ), - p - ), - mload(C_ALPHA_BASE_LOC), - p - ) - - // q_elliptic * (x3 + x2 + x1)(x2 - x1)(x2 - x1) - y2^2 - y1^2 + 2(y2y1)*q_sign = 0 - let y1_plus_y3 := addmod( - mload(Y1_EVAL_LOC), - mload(Y3_EVAL_LOC), - p - ) - let y_diff := addmod(mulmod(mload(Y2_EVAL_LOC), mload(QSIGN_LOC), p), sub(p, mload(Y1_EVAL_LOC)), p) - let y_add_identity := - addmod( - mulmod(y1_plus_y3, x_diff, p), - mulmod(addmod(mload(X3_EVAL_LOC), sub(p, mload(X1_EVAL_LOC)), p), y_diff, p), - p - ) - y_add_identity := - mulmod( - mulmod(y_add_identity, addmod(1, sub(p, mload(QM_EVAL_LOC)), p), p), - mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p), - p - ) - - // ELLIPTIC_IDENTITY = (x_identity + y_identity) * Q_ELLIPTIC_EVAL - mstore( - ELLIPTIC_IDENTITY, mulmod(addmod(x_add_identity, y_add_identity, p), mload(QELLIPTIC_EVAL_LOC), p) - ) - } - { - /** - * x_pow_4 = (y_1_sqr - curve_b) * x_1; - * y_1_sqr_mul_4 = y_1_sqr + y_1_sqr; - * y_1_sqr_mul_4 += y_1_sqr_mul_4; - * x_1_pow_4_mul_9 = x_pow_4; - * x_1_pow_4_mul_9 += x_1_pow_4_mul_9; - * x_1_pow_4_mul_9 += x_1_pow_4_mul_9; - * x_1_pow_4_mul_9 += x_1_pow_4_mul_9; - * x_1_pow_4_mul_9 += x_pow_4; - * x_1_sqr_mul_3 = x_1_sqr + x_1_sqr + x_1_sqr; - * x_double_identity = (x_3 + x_1 + x_1) * y_1_sqr_mul_4 - x_1_pow_4_mul_9; - * y_double_identity = x_1_sqr_mul_3 * (x_1 - x_3) - (y_1 + y_1) * (y_1 + y_3); - */ - // (x3 + x1 + x1) (4y1*y1) - 9 * x1 * x1 * x1 * x1 = 0 - let x1_sqr := mulmod(mload(X1_EVAL_LOC), mload(X1_EVAL_LOC), p) - let y1_sqr := mulmod(mload(Y1_EVAL_LOC), mload(Y1_EVAL_LOC), p) - let x_pow_4 := mulmod(addmod(y1_sqr, GRUMPKIN_CURVE_B_PARAMETER_NEGATED, p), mload(X1_EVAL_LOC), p) - let y1_sqr_mul_4 := mulmod(y1_sqr, 4, p) - let x1_pow_4_mul_9 := mulmod(x_pow_4, 9, p) - let x1_sqr_mul_3 := mulmod(x1_sqr, 3, p) - let x_double_identity := - addmod( - mulmod( - addmod(mload(X3_EVAL_LOC), addmod(mload(X1_EVAL_LOC), mload(X1_EVAL_LOC), p), p), - y1_sqr_mul_4, - p - ), - sub(p, x1_pow_4_mul_9), - p - ) - // (y1 + y1) (2y1) - (3 * x1 * x1)(x1 - x3) = 0 - let y_double_identity := - addmod( - mulmod(x1_sqr_mul_3, addmod(mload(X1_EVAL_LOC), sub(p, mload(X3_EVAL_LOC)), p), p), - sub( - p, - mulmod( - addmod(mload(Y1_EVAL_LOC), mload(Y1_EVAL_LOC), p), - addmod(mload(Y1_EVAL_LOC), mload(Y3_EVAL_LOC), p), - p - ) - ), - p - ) - x_double_identity := mulmod(x_double_identity, mload(C_ALPHA_BASE_LOC), p) - y_double_identity := - mulmod(y_double_identity, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p), p) - x_double_identity := mulmod(x_double_identity, mload(QM_EVAL_LOC), p) - y_double_identity := mulmod(y_double_identity, mload(QM_EVAL_LOC), p) - // ELLIPTIC_IDENTITY += (x_double_identity + y_double_identity) * Q_DOUBLE_EVAL - mstore( - ELLIPTIC_IDENTITY, - addmod( - mload(ELLIPTIC_IDENTITY), - mulmod(addmod(x_double_identity, y_double_identity, p), mload(QELLIPTIC_EVAL_LOC), p), - p - ) - ) - - // update alpha - mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_QUAD_LOC), p)) - } - - /** - * COMPUTE AUXILIARY WIDGET EVALUATION - */ - { - { - /** - * Non native field arithmetic gate 2 - * _ _ - * / _ _ _ 14 \ - * q_2 . q_4 | (w_1 . w_2) + (w_1 . w_2) + (w_1 . w_4 + w_2 . w_3 - w_3) . 2 - w_3 - w_4 | - * \_ _/ - * - * limb_subproduct = w_1 . w_2_omega + w_1_omega . w_2 - * non_native_field_gate_2 = w_1 * w_4 + w_4 * w_3 - w_3_omega - * non_native_field_gate_2 = non_native_field_gate_2 * limb_size - * non_native_field_gate_2 -= w_4_omega - * non_native_field_gate_2 += limb_subproduct - * non_native_field_gate_2 *= q_4 - * limb_subproduct *= limb_size - * limb_subproduct += w_1_omega * w_2_omega - * non_native_field_gate_1 = (limb_subproduct + w_3 + w_4) * q_3 - * non_native_field_gate_3 = (limb_subproduct + w_4 - (w_3_omega + w_4_omega)) * q_m - * non_native_field_identity = (non_native_field_gate_1 + non_native_field_gate_2 + non_native_field_gate_3) * q_2 - */ - - let limb_subproduct := - addmod( - mulmod(mload(W1_EVAL_LOC), mload(W2_OMEGA_EVAL_LOC), p), - mulmod(mload(W1_OMEGA_EVAL_LOC), mload(W2_EVAL_LOC), p), - p - ) - - let non_native_field_gate_2 := - addmod( - addmod( - mulmod(mload(W1_EVAL_LOC), mload(W4_EVAL_LOC), p), - mulmod(mload(W2_EVAL_LOC), mload(W3_EVAL_LOC), p), - p - ), - sub(p, mload(W3_OMEGA_EVAL_LOC)), - p - ) - non_native_field_gate_2 := mulmod(non_native_field_gate_2, LIMB_SIZE, p) - non_native_field_gate_2 := addmod(non_native_field_gate_2, sub(p, mload(W4_OMEGA_EVAL_LOC)), p) - non_native_field_gate_2 := addmod(non_native_field_gate_2, limb_subproduct, p) - non_native_field_gate_2 := mulmod(non_native_field_gate_2, mload(Q4_EVAL_LOC), p) - limb_subproduct := mulmod(limb_subproduct, LIMB_SIZE, p) - limb_subproduct := - addmod(limb_subproduct, mulmod(mload(W1_OMEGA_EVAL_LOC), mload(W2_OMEGA_EVAL_LOC), p), p) - let non_native_field_gate_1 := - mulmod( - addmod(limb_subproduct, sub(p, addmod(mload(W3_EVAL_LOC), mload(W4_EVAL_LOC), p)), p), - mload(Q3_EVAL_LOC), - p - ) - let non_native_field_gate_3 := - mulmod( - addmod( - addmod(limb_subproduct, mload(W4_EVAL_LOC), p), - sub(p, addmod(mload(W3_OMEGA_EVAL_LOC), mload(W4_OMEGA_EVAL_LOC), p)), - p - ), - mload(QM_EVAL_LOC), - p - ) - let non_native_field_identity := - mulmod( - addmod(addmod(non_native_field_gate_1, non_native_field_gate_2, p), non_native_field_gate_3, p), - mload(Q2_EVAL_LOC), - p - ) - - mstore(AUX_NON_NATIVE_FIELD_EVALUATION, non_native_field_identity) - } - - { - /** - * limb_accumulator_1 = w_2_omega; - * limb_accumulator_1 *= SUBLIMB_SHIFT; - * limb_accumulator_1 += w_1_omega; - * limb_accumulator_1 *= SUBLIMB_SHIFT; - * limb_accumulator_1 += w_3; - * limb_accumulator_1 *= SUBLIMB_SHIFT; - * limb_accumulator_1 += w_2; - * limb_accumulator_1 *= SUBLIMB_SHIFT; - * limb_accumulator_1 += w_1; - * limb_accumulator_1 -= w_4; - * limb_accumulator_1 *= q_4; - */ - let limb_accumulator_1 := mulmod(mload(W2_OMEGA_EVAL_LOC), SUBLIMB_SHIFT, p) - limb_accumulator_1 := addmod(limb_accumulator_1, mload(W1_OMEGA_EVAL_LOC), p) - limb_accumulator_1 := mulmod(limb_accumulator_1, SUBLIMB_SHIFT, p) - limb_accumulator_1 := addmod(limb_accumulator_1, mload(W3_EVAL_LOC), p) - limb_accumulator_1 := mulmod(limb_accumulator_1, SUBLIMB_SHIFT, p) - limb_accumulator_1 := addmod(limb_accumulator_1, mload(W2_EVAL_LOC), p) - limb_accumulator_1 := mulmod(limb_accumulator_1, SUBLIMB_SHIFT, p) - limb_accumulator_1 := addmod(limb_accumulator_1, mload(W1_EVAL_LOC), p) - limb_accumulator_1 := addmod(limb_accumulator_1, sub(p, mload(W4_EVAL_LOC)), p) - limb_accumulator_1 := mulmod(limb_accumulator_1, mload(Q4_EVAL_LOC), p) - - /** - * limb_accumulator_2 = w_3_omega; - * limb_accumulator_2 *= SUBLIMB_SHIFT; - * limb_accumulator_2 += w_2_omega; - * limb_accumulator_2 *= SUBLIMB_SHIFT; - * limb_accumulator_2 += w_1_omega; - * limb_accumulator_2 *= SUBLIMB_SHIFT; - * limb_accumulator_2 += w_4; - * limb_accumulator_2 *= SUBLIMB_SHIFT; - * limb_accumulator_2 += w_3; - * limb_accumulator_2 -= w_4_omega; - * limb_accumulator_2 *= q_m; - */ - let limb_accumulator_2 := mulmod(mload(W3_OMEGA_EVAL_LOC), SUBLIMB_SHIFT, p) - limb_accumulator_2 := addmod(limb_accumulator_2, mload(W2_OMEGA_EVAL_LOC), p) - limb_accumulator_2 := mulmod(limb_accumulator_2, SUBLIMB_SHIFT, p) - limb_accumulator_2 := addmod(limb_accumulator_2, mload(W1_OMEGA_EVAL_LOC), p) - limb_accumulator_2 := mulmod(limb_accumulator_2, SUBLIMB_SHIFT, p) - limb_accumulator_2 := addmod(limb_accumulator_2, mload(W4_EVAL_LOC), p) - limb_accumulator_2 := mulmod(limb_accumulator_2, SUBLIMB_SHIFT, p) - limb_accumulator_2 := addmod(limb_accumulator_2, mload(W3_EVAL_LOC), p) - limb_accumulator_2 := addmod(limb_accumulator_2, sub(p, mload(W4_OMEGA_EVAL_LOC)), p) - limb_accumulator_2 := mulmod(limb_accumulator_2, mload(QM_EVAL_LOC), p) - - mstore( - AUX_LIMB_ACCUMULATOR_EVALUATION, - mulmod(addmod(limb_accumulator_1, limb_accumulator_2, p), mload(Q3_EVAL_LOC), p) - ) - } - - { - /** - * memory_record_check = w_3; - * memory_record_check *= eta; - * memory_record_check += w_2; - * memory_record_check *= eta; - * memory_record_check += w_1; - * memory_record_check *= eta; - * memory_record_check += q_c; - * - * partial_record_check = memory_record_check; - * - * memory_record_check -= w_4; - */ - - let memory_record_check := mulmod(mload(W3_EVAL_LOC), mload(C_ETA_LOC), p) - memory_record_check := addmod(memory_record_check, mload(W2_EVAL_LOC), p) - memory_record_check := mulmod(memory_record_check, mload(C_ETA_LOC), p) - memory_record_check := addmod(memory_record_check, mload(W1_EVAL_LOC), p) - memory_record_check := mulmod(memory_record_check, mload(C_ETA_LOC), p) - memory_record_check := addmod(memory_record_check, mload(QC_EVAL_LOC), p) - - let partial_record_check := memory_record_check - memory_record_check := addmod(memory_record_check, sub(p, mload(W4_EVAL_LOC)), p) - - mstore(AUX_MEMORY_EVALUATION, memory_record_check) - - // index_delta = w_1_omega - w_1 - let index_delta := addmod(mload(W1_OMEGA_EVAL_LOC), sub(p, mload(W1_EVAL_LOC)), p) - // record_delta = w_4_omega - w_4 - let record_delta := addmod(mload(W4_OMEGA_EVAL_LOC), sub(p, mload(W4_EVAL_LOC)), p) - // index_is_monotonically_increasing = index_delta * (index_delta - 1) - let index_is_monotonically_increasing := mulmod(index_delta, addmod(index_delta, sub(p, 1), p), p) - - // adjacent_values_match_if_adjacent_indices_match = record_delta * (1 - index_delta) - let adjacent_values_match_if_adjacent_indices_match := - mulmod(record_delta, addmod(1, sub(p, index_delta), p), p) - - // AUX_ROM_CONSISTENCY_EVALUATION = ((adjacent_values_match_if_adjacent_indices_match * alpha) + index_is_monotonically_increasing) * alpha + partial_record_check - mstore( - AUX_ROM_CONSISTENCY_EVALUATION, - addmod( - mulmod( - addmod( - mulmod(adjacent_values_match_if_adjacent_indices_match, mload(C_ALPHA_LOC), p), - index_is_monotonically_increasing, - p - ), - mload(C_ALPHA_LOC), - p - ), - memory_record_check, - p - ) - ) - - { - /** - * next_gate_access_type = w_3_omega; - * next_gate_access_type *= eta; - * next_gate_access_type += w_2_omega; - * next_gate_access_type *= eta; - * next_gate_access_type += w_1_omega; - * next_gate_access_type *= eta; - * next_gate_access_type = w_4_omega - next_gate_access_type; - */ - let next_gate_access_type := mulmod(mload(W3_OMEGA_EVAL_LOC), mload(C_ETA_LOC), p) - next_gate_access_type := addmod(next_gate_access_type, mload(W2_OMEGA_EVAL_LOC), p) - next_gate_access_type := mulmod(next_gate_access_type, mload(C_ETA_LOC), p) - next_gate_access_type := addmod(next_gate_access_type, mload(W1_OMEGA_EVAL_LOC), p) - next_gate_access_type := mulmod(next_gate_access_type, mload(C_ETA_LOC), p) - next_gate_access_type := addmod(mload(W4_OMEGA_EVAL_LOC), sub(p, next_gate_access_type), p) - - // value_delta = w_3_omega - w_3 - let value_delta := addmod(mload(W3_OMEGA_EVAL_LOC), sub(p, mload(W3_EVAL_LOC)), p) - // adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation = (1 - index_delta) * value_delta * (1 - next_gate_access_type); - - let adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation := - mulmod( - addmod(1, sub(p, index_delta), p), - mulmod(value_delta, addmod(1, sub(p, next_gate_access_type), p), p), - p - ) - - // AUX_RAM_CONSISTENCY_EVALUATION - - /** - * access_type = w_4 - partial_record_check - * access_check = access_type^2 - access_type - * next_gate_access_type_is_boolean = next_gate_access_type^2 - next_gate_access_type - * RAM_consistency_check_identity = adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation; - * RAM_consistency_check_identity *= alpha; - * RAM_consistency_check_identity += index_is_monotonically_increasing; - * RAM_consistency_check_identity *= alpha; - * RAM_consistency_check_identity += next_gate_access_type_is_boolean; - * RAM_consistency_check_identity *= alpha; - * RAM_consistency_check_identity += access_check; - */ - - let access_type := addmod(mload(W4_EVAL_LOC), sub(p, partial_record_check), p) - let access_check := mulmod(access_type, addmod(access_type, sub(p, 1), p), p) - let next_gate_access_type_is_boolean := - mulmod(next_gate_access_type, addmod(next_gate_access_type, sub(p, 1), p), p) - let RAM_cci := - mulmod( - adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation, - mload(C_ALPHA_LOC), - p - ) - RAM_cci := addmod(RAM_cci, index_is_monotonically_increasing, p) - RAM_cci := mulmod(RAM_cci, mload(C_ALPHA_LOC), p) - RAM_cci := addmod(RAM_cci, next_gate_access_type_is_boolean, p) - RAM_cci := mulmod(RAM_cci, mload(C_ALPHA_LOC), p) - RAM_cci := addmod(RAM_cci, access_check, p) - - mstore(AUX_RAM_CONSISTENCY_EVALUATION, RAM_cci) - } - - { - // timestamp_delta = w_2_omega - w_2 - let timestamp_delta := addmod(mload(W2_OMEGA_EVAL_LOC), sub(p, mload(W2_EVAL_LOC)), p) - - // RAM_timestamp_check_identity = (1 - index_delta) * timestamp_delta - w_3 - let RAM_timestamp_check_identity := - addmod( - mulmod(timestamp_delta, addmod(1, sub(p, index_delta), p), p), sub(p, mload(W3_EVAL_LOC)), p - ) - - /** - * memory_identity = ROM_consistency_check_identity * q_2; - * memory_identity += RAM_timestamp_check_identity * q_4; - * memory_identity += memory_record_check * q_m; - * memory_identity *= q_1; - * memory_identity += (RAM_consistency_check_identity * q_arith); - * - * auxiliary_identity = memory_identity + non_native_field_identity + limb_accumulator_identity; - * auxiliary_identity *= q_aux; - * auxiliary_identity *= alpha_base; - */ - let memory_identity := mulmod(mload(AUX_ROM_CONSISTENCY_EVALUATION), mload(Q2_EVAL_LOC), p) - memory_identity := - addmod(memory_identity, mulmod(RAM_timestamp_check_identity, mload(Q4_EVAL_LOC), p), p) - memory_identity := - addmod(memory_identity, mulmod(mload(AUX_MEMORY_EVALUATION), mload(QM_EVAL_LOC), p), p) - memory_identity := mulmod(memory_identity, mload(Q1_EVAL_LOC), p) - memory_identity := - addmod( - memory_identity, mulmod(mload(AUX_RAM_CONSISTENCY_EVALUATION), mload(QARITH_EVAL_LOC), p), p - ) - - let auxiliary_identity := addmod(memory_identity, mload(AUX_NON_NATIVE_FIELD_EVALUATION), p) - auxiliary_identity := addmod(auxiliary_identity, mload(AUX_LIMB_ACCUMULATOR_EVALUATION), p) - auxiliary_identity := mulmod(auxiliary_identity, mload(QAUX_EVAL_LOC), p) - auxiliary_identity := mulmod(auxiliary_identity, mload(C_ALPHA_BASE_LOC), p) - - mstore(AUX_IDENTITY, auxiliary_identity) - - // update alpha - mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_CUBE_LOC), p)) - } - } - } - - { - /** - * quotient = ARITHMETIC_IDENTITY - * quotient += PERMUTATION_IDENTITY - * quotient += PLOOKUP_IDENTITY - * quotient += SORT_IDENTITY - * quotient += ELLIPTIC_IDENTITY - * quotient += AUX_IDENTITY - * quotient *= ZERO_POLY_INVERSE - */ - mstore( - QUOTIENT_EVAL_LOC, - mulmod( - addmod( - addmod( - addmod( - addmod( - addmod(mload(PERMUTATION_IDENTITY), mload(PLOOKUP_IDENTITY), p), - mload(ARITHMETIC_IDENTITY), - p - ), - mload(SORT_IDENTITY), - p - ), - mload(ELLIPTIC_IDENTITY), - p - ), - mload(AUX_IDENTITY), - p - ), - mload(ZERO_POLY_INVERSE_LOC), - p - ) - ) - } - - /** - * GENERATE NU AND SEPARATOR CHALLENGES - */ - { - let current_challenge := mload(C_CURRENT_LOC) - // get a calldata pointer that points to the start of the data we want to copy - let calldata_ptr := add(calldataload(0x04), 0x24) - - calldata_ptr := add(calldata_ptr, NU_CALLDATA_SKIP_LENGTH) - - mstore(NU_CHALLENGE_INPUT_LOC_A, current_challenge) - mstore(NU_CHALLENGE_INPUT_LOC_B, mload(QUOTIENT_EVAL_LOC)) - calldatacopy(NU_CHALLENGE_INPUT_LOC_C, calldata_ptr, NU_INPUT_LENGTH) - - // hash length = (0x20 + num field elements), we include the previous challenge in the hash - let challenge := keccak256(NU_CHALLENGE_INPUT_LOC_A, add(NU_INPUT_LENGTH, 0x40)) - - mstore(C_V0_LOC, mod(challenge, p)) - // We need THIRTY-ONE independent nu challenges! - mstore(0x00, challenge) - mstore8(0x20, 0x01) - mstore(C_V1_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x02) - mstore(C_V2_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x03) - mstore(C_V3_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x04) - mstore(C_V4_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x05) - mstore(C_V5_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x06) - mstore(C_V6_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x07) - mstore(C_V7_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x08) - mstore(C_V8_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x09) - mstore(C_V9_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x0a) - mstore(C_V10_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x0b) - mstore(C_V11_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x0c) - mstore(C_V12_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x0d) - mstore(C_V13_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x0e) - mstore(C_V14_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x0f) - mstore(C_V15_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x10) - mstore(C_V16_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x11) - mstore(C_V17_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x12) - mstore(C_V18_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x13) - mstore(C_V19_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x14) - mstore(C_V20_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x15) - mstore(C_V21_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x16) - mstore(C_V22_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x17) - mstore(C_V23_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x18) - mstore(C_V24_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x19) - mstore(C_V25_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x1a) - mstore(C_V26_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x1b) - mstore(C_V27_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x1c) - mstore(C_V28_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x1d) - mstore(C_V29_LOC, mod(keccak256(0x00, 0x21), p)) - - // @follow-up - Why are both v29 and v30 using appending 0x1d to the prior challenge and hashing, should it not change? - mstore8(0x20, 0x1d) - challenge := keccak256(0x00, 0x21) - mstore(C_V30_LOC, mod(challenge, p)) - - // separator - mstore(0x00, challenge) - mstore(0x20, mload(PI_Z_Y_LOC)) - mstore(0x40, mload(PI_Z_X_LOC)) - mstore(0x60, mload(PI_Z_OMEGA_Y_LOC)) - mstore(0x80, mload(PI_Z_OMEGA_X_LOC)) - - mstore(C_U_LOC, mod(keccak256(0x00, 0xa0), p)) - } - - let success := 0 - // VALIDATE T1 - { - let x := mload(T1_X_LOC) - let y := mload(T1_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(ACCUMULATOR_X_LOC, x) - mstore(add(ACCUMULATOR_X_LOC, 0x20), y) - } - // VALIDATE T2 - { - let x := mload(T2_X_LOC) // 0x1400 - let y := mload(T2_Y_LOC) // 0x1420 - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(ZETA_POW_N_LOC)) - // accumulator_2 = [T2].zeta^n - success := staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40) - // accumulator = [T1] + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE T3 - { - let x := mload(T3_X_LOC) - let y := mload(T3_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(mload(ZETA_POW_N_LOC), mload(ZETA_POW_N_LOC), p)) - // accumulator_2 = [T3].zeta^{2n} - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE T4 - { - let x := mload(T4_X_LOC) - let y := mload(T4_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(mulmod(mload(ZETA_POW_N_LOC), mload(ZETA_POW_N_LOC), p), mload(ZETA_POW_N_LOC), p)) - // accumulator_2 = [T4].zeta^{3n} - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE W1 - { - let x := mload(W1_X_LOC) - let y := mload(W1_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V0_LOC), p)) - // accumulator_2 = v0.(u + 1).[W1] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE W2 - { - let x := mload(W2_X_LOC) - let y := mload(W2_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V1_LOC), p)) - // accumulator_2 = v1.(u + 1).[W2] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE W3 - { - let x := mload(W3_X_LOC) - let y := mload(W3_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V2_LOC), p)) - // accumulator_2 = v2.(u + 1).[W3] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE W4 - { - let x := mload(W4_X_LOC) - let y := mload(W4_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V3_LOC), p)) - // accumulator_2 = v3.(u + 1).[W4] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE S - { - let x := mload(S_X_LOC) - let y := mload(S_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V4_LOC), p)) - // accumulator_2 = v4.(u + 1).[S] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE Z - { - let x := mload(Z_X_LOC) - let y := mload(Z_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V5_LOC), p)) - // accumulator_2 = v5.(u + 1).[Z] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE Z_LOOKUP - { - let x := mload(Z_LOOKUP_X_LOC) - let y := mload(Z_LOOKUP_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V6_LOC), p)) - // accumulator_2 = v6.(u + 1).[Z_LOOKUP] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE Q1 - { - let x := mload(Q1_X_LOC) - let y := mload(Q1_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V7_LOC)) - // accumulator_2 = v7.[Q1] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE Q2 - { - let x := mload(Q2_X_LOC) - let y := mload(Q2_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V8_LOC)) - // accumulator_2 = v8.[Q2] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE Q3 - { - let x := mload(Q3_X_LOC) - let y := mload(Q3_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V9_LOC)) - // accumulator_2 = v9.[Q3] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE Q4 - { - let x := mload(Q4_X_LOC) - let y := mload(Q4_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V10_LOC)) - // accumulator_2 = v10.[Q4] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE QM - { - let x := mload(QM_X_LOC) - let y := mload(QM_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V11_LOC)) - // accumulator_2 = v11.[Q;] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE QC - { - let x := mload(QC_X_LOC) - let y := mload(QC_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V12_LOC)) - // accumulator_2 = v12.[QC] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE QARITH - { - let x := mload(QARITH_X_LOC) - let y := mload(QARITH_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V13_LOC)) - // accumulator_2 = v13.[QARITH] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE QSORT - { - let x := mload(QSORT_X_LOC) - let y := mload(QSORT_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V14_LOC)) - // accumulator_2 = v14.[QSORT] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE QELLIPTIC - { - let x := mload(QELLIPTIC_X_LOC) - let y := mload(QELLIPTIC_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V15_LOC)) - // accumulator_2 = v15.[QELLIPTIC] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE QAUX - { - let x := mload(QAUX_X_LOC) - let y := mload(QAUX_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V16_LOC)) - // accumulator_2 = v15.[Q_AUX] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE SIGMA1 - { - let x := mload(SIGMA1_X_LOC) - let y := mload(SIGMA1_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V17_LOC)) - // accumulator_2 = v17.[sigma1] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE SIGMA2 - { - let x := mload(SIGMA2_X_LOC) - let y := mload(SIGMA2_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V18_LOC)) - // accumulator_2 = v18.[sigma2] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE SIGMA3 - { - let x := mload(SIGMA3_X_LOC) - let y := mload(SIGMA3_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V19_LOC)) - // accumulator_2 = v19.[sigma3] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE SIGMA4 - { - let x := mload(SIGMA4_X_LOC) - let y := mload(SIGMA4_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V20_LOC)) - // accumulator_2 = v20.[sigma4] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE TABLE1 - { - let x := mload(TABLE1_X_LOC) - let y := mload(TABLE1_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V21_LOC), p)) - // accumulator_2 = u.[table1] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE TABLE2 - { - let x := mload(TABLE2_X_LOC) - let y := mload(TABLE2_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V22_LOC), p)) - // accumulator_2 = u.[table2] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE TABLE3 - { - let x := mload(TABLE3_X_LOC) - let y := mload(TABLE3_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V23_LOC), p)) - // accumulator_2 = u.[table3] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE TABLE4 - { - let x := mload(TABLE4_X_LOC) - let y := mload(TABLE4_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V24_LOC), p)) - // accumulator_2 = u.[table4] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE TABLE_TYPE - { - let x := mload(TABLE_TYPE_X_LOC) - let y := mload(TABLE_TYPE_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V25_LOC)) - // accumulator_2 = v25.[TableType] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE ID1 - { - let x := mload(ID1_X_LOC) - let y := mload(ID1_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V26_LOC)) - // accumulator_2 = v26.[ID1] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE ID2 - { - let x := mload(ID2_X_LOC) - let y := mload(ID2_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V27_LOC)) - // accumulator_2 = v27.[ID2] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE ID3 - { - let x := mload(ID3_X_LOC) - let y := mload(ID3_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V28_LOC)) - // accumulator_2 = v28.[ID3] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE ID4 - { - let x := mload(ID4_X_LOC) - let y := mload(ID4_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V29_LOC)) - // accumulator_2 = v29.[ID4] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - /** - * COMPUTE BATCH EVALUATION SCALAR MULTIPLIER - */ - { - /** - * batch_evaluation = v0 * (w_1_omega * u + w_1_eval) - * batch_evaluation += v1 * (w_2_omega * u + w_2_eval) - * batch_evaluation += v2 * (w_3_omega * u + w_3_eval) - * batch_evaluation += v3 * (w_4_omega * u + w_4_eval) - * batch_evaluation += v4 * (s_omega_eval * u + s_eval) - * batch_evaluation += v5 * (z_omega_eval * u + z_eval) - * batch_evaluation += v6 * (z_lookup_omega_eval * u + z_lookup_eval) - */ - let batch_evaluation := - mulmod( - mload(C_V0_LOC), - addmod(mulmod(mload(W1_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W1_EVAL_LOC), p), - p - ) - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V1_LOC), - addmod(mulmod(mload(W2_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W2_EVAL_LOC), p), - p - ), - p - ) - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V2_LOC), - addmod(mulmod(mload(W3_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W3_EVAL_LOC), p), - p - ), - p - ) - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V3_LOC), - addmod(mulmod(mload(W4_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W4_EVAL_LOC), p), - p - ), - p - ) - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V4_LOC), - addmod(mulmod(mload(S_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(S_EVAL_LOC), p), - p - ), - p - ) - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V5_LOC), - addmod(mulmod(mload(Z_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(Z_EVAL_LOC), p), - p - ), - p - ) - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V6_LOC), - addmod(mulmod(mload(Z_LOOKUP_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(Z_LOOKUP_EVAL_LOC), p), - p - ), - p - ) - - /** - * batch_evaluation += v7 * Q1_EVAL - * batch_evaluation += v8 * Q2_EVAL - * batch_evaluation += v9 * Q3_EVAL - * batch_evaluation += v10 * Q4_EVAL - * batch_evaluation += v11 * QM_EVAL - * batch_evaluation += v12 * QC_EVAL - * batch_evaluation += v13 * QARITH_EVAL - * batch_evaluation += v14 * QSORT_EVAL_LOC - * batch_evaluation += v15 * QELLIPTIC_EVAL_LOC - * batch_evaluation += v16 * QAUX_EVAL_LOC - * batch_evaluation += v17 * SIGMA1_EVAL_LOC - * batch_evaluation += v18 * SIGMA2_EVAL_LOC - * batch_evaluation += v19 * SIGMA3_EVAL_LOC - * batch_evaluation += v20 * SIGMA4_EVAL_LOC - */ - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V7_LOC), mload(Q1_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V8_LOC), mload(Q2_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V9_LOC), mload(Q3_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V10_LOC), mload(Q4_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V11_LOC), mload(QM_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V12_LOC), mload(QC_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V13_LOC), mload(QARITH_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V14_LOC), mload(QSORT_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V15_LOC), mload(QELLIPTIC_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V16_LOC), mload(QAUX_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V17_LOC), mload(SIGMA1_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V18_LOC), mload(SIGMA2_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V19_LOC), mload(SIGMA3_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V20_LOC), mload(SIGMA4_EVAL_LOC), p), p) - - /** - * batch_evaluation += v21 * (table1(zw) * u + table1(z)) - * batch_evaluation += v22 * (table2(zw) * u + table2(z)) - * batch_evaluation += v23 * (table3(zw) * u + table3(z)) - * batch_evaluation += v24 * (table4(zw) * u + table4(z)) - * batch_evaluation += v25 * table_type_eval - * batch_evaluation += v26 * id1_eval - * batch_evaluation += v27 * id2_eval - * batch_evaluation += v28 * id3_eval - * batch_evaluation += v29 * id4_eval - * batch_evaluation += quotient_eval - */ - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V21_LOC), - addmod(mulmod(mload(TABLE1_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE1_EVAL_LOC), p), - p - ), - p - ) - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V22_LOC), - addmod(mulmod(mload(TABLE2_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE2_EVAL_LOC), p), - p - ), - p - ) - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V23_LOC), - addmod(mulmod(mload(TABLE3_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE3_EVAL_LOC), p), - p - ), - p - ) - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V24_LOC), - addmod(mulmod(mload(TABLE4_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE4_EVAL_LOC), p), - p - ), - p - ) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V25_LOC), mload(TABLE_TYPE_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V26_LOC), mload(ID1_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V27_LOC), mload(ID2_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V28_LOC), mload(ID3_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V29_LOC), mload(ID4_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mload(QUOTIENT_EVAL_LOC), p) - - mstore(0x00, 0x01) // [1].x - mstore(0x20, 0x02) // [1].y - mstore(0x40, sub(p, batch_evaluation)) - // accumulator_2 = -[1].(batch_evaluation) - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - if iszero(success) { - mstore(0x0, OPENING_COMMITMENT_FAILED_SELECTOR) - revert(0x00, 0x04) - } - } - - /** - * PERFORM PAIRING PREAMBLE - */ - { - let u := mload(C_U_LOC) - let zeta := mload(C_ZETA_LOC) - // VALIDATE PI_Z - { - let x := mload(PI_Z_X_LOC) - let y := mload(PI_Z_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - // compute zeta.[PI_Z] and add into accumulator - mstore(0x40, zeta) - success := staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE PI_Z_OMEGA - { - let x := mload(PI_Z_OMEGA_X_LOC) - let y := mload(PI_Z_OMEGA_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(mulmod(u, zeta, p), mload(OMEGA_LOC), p)) - // accumulator_2 = u.zeta.omega.[PI_Z_OMEGA] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // PAIRING_RHS = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, PAIRING_RHS_X_LOC, 0x40)) - - mstore(0x00, mload(PI_Z_X_LOC)) - mstore(0x20, mload(PI_Z_Y_LOC)) - mstore(0x40, mload(PI_Z_OMEGA_X_LOC)) - mstore(0x60, mload(PI_Z_OMEGA_Y_LOC)) - mstore(0x80, u) - success := and(success, staticcall(gas(), 7, 0x40, 0x60, 0x40, 0x40)) - // PAIRING_LHS = [PI_Z] + [PI_Z_OMEGA] * u - success := and(success, staticcall(gas(), 6, 0x00, 0x80, PAIRING_LHS_X_LOC, 0x40)) - // negate lhs y-coordinate - mstore(PAIRING_LHS_Y_LOC, sub(q, mload(PAIRING_LHS_Y_LOC))) - - if mload(CONTAINS_RECURSIVE_PROOF_LOC) { - // VALIDATE RECURSIVE P1 - { - let x := mload(RECURSIVE_P1_X_LOC) - let y := mload(RECURSIVE_P1_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - - // compute u.u.[recursive_p1] and write into 0x60 - mstore(0x40, mulmod(u, u, p)) - success := and(success, staticcall(gas(), 7, 0x00, 0x60, 0x60, 0x40)) - // VALIDATE RECURSIVE P2 - { - let x := mload(RECURSIVE_P2_X_LOC) - let y := mload(RECURSIVE_P2_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - // compute u.u.[recursive_p2] and write into 0x00 - // 0x40 still contains u*u - success := and(success, staticcall(gas(), 7, 0x00, 0x60, 0x00, 0x40)) - - // compute u.u.[recursiveP1] + rhs and write into rhs - mstore(0xa0, mload(PAIRING_RHS_X_LOC)) - mstore(0xc0, mload(PAIRING_RHS_Y_LOC)) - success := and(success, staticcall(gas(), 6, 0x60, 0x80, PAIRING_RHS_X_LOC, 0x40)) - - // compute u.u.[recursiveP2] + lhs and write into lhs - mstore(0x40, mload(PAIRING_LHS_X_LOC)) - mstore(0x60, mload(PAIRING_LHS_Y_LOC)) - success := and(success, staticcall(gas(), 6, 0x00, 0x80, PAIRING_LHS_X_LOC, 0x40)) - } - - if iszero(success) { - mstore(0x0, PAIRING_PREAMBLE_FAILED_SELECTOR) - revert(0x00, 0x04) - } - } - - /** - * PERFORM PAIRING - */ - { - // rhs paired with [1]_2 - // lhs paired with [x]_2 - - mstore(0x00, mload(PAIRING_RHS_X_LOC)) - mstore(0x20, mload(PAIRING_RHS_Y_LOC)) - mstore(0x40, 0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2) // this is [1]_2 - mstore(0x60, 0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed) - mstore(0x80, 0x090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b) - mstore(0xa0, 0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa) - - mstore(0xc0, mload(PAIRING_LHS_X_LOC)) - mstore(0xe0, mload(PAIRING_LHS_Y_LOC)) - mstore(0x100, mload(G2X_X0_LOC)) - mstore(0x120, mload(G2X_X1_LOC)) - mstore(0x140, mload(G2X_Y0_LOC)) - mstore(0x160, mload(G2X_Y1_LOC)) - - success := staticcall(gas(), 8, 0x00, 0x180, 0x00, 0x20) - if iszero(and(success, mload(0x00))) { - mstore(0x0, PAIRING_FAILED_SELECTOR) - revert(0x00, 0x04) - } - } - - { - mstore(0x00, 0x01) - return(0x00, 0x20) // Proof succeeded! - } - } - } -} - -contract UltraVerifier is BaseUltraVerifier { - function getVerificationKeyHash() public pure override(BaseUltraVerifier) returns (bytes32) { - return UltraVerificationKey.verificationKeyHash(); - } - - function loadVerificationKey(uint256 vk, uint256 _omegaInverseLoc) internal pure virtual override(BaseUltraVerifier) { - UltraVerificationKey.loadVerificationKey(vk, _omegaInverseLoc); - } -} diff --git a/noir/noir-repo/compiler/integration-tests/contracts/recursion.sol b/noir/noir-repo/compiler/integration-tests/contracts/recursion.sol deleted file mode 100644 index abb5529f12ed..000000000000 --- a/noir/noir-repo/compiler/integration-tests/contracts/recursion.sol +++ /dev/null @@ -1,2869 +0,0 @@ -// Verification Key Hash: e0328cb05dead618095601e226cdeb6dbc39366658b78fabcb8b4d79b64150fe -// SPDX-License-Identifier: Apache-2.0 -// Copyright 2022 Aztec -pragma solidity >=0.8.4; - -library UltraVerificationKey { - function verificationKeyHash() internal pure returns(bytes32) { - return 0xe0328cb05dead618095601e226cdeb6dbc39366658b78fabcb8b4d79b64150fe; - } - - function loadVerificationKey(uint256 _vk, uint256 _omegaInverseLoc) internal pure { - assembly { - mstore(add(_vk, 0x00), 0x0000000000000000000000000000000000000000000000000000000000040000) // vk.circuit_size - mstore(add(_vk, 0x20), 0x0000000000000000000000000000000000000000000000000000000000000010) // vk.num_inputs - mstore(add(_vk, 0x40), 0x19ddbcaf3a8d46c15c0176fbb5b95e4dc57088ff13f4d1bd84c6bfa57dcdc0e0) // vk.work_root - mstore(add(_vk, 0x60), 0x30644259cd94e7dd5045d7a27013b7fcd21c9e3b7fa75222e7bda49b729b0401) // vk.domain_inverse - mstore(add(_vk, 0x80), 0x296cf46c4f739702b3432a7e00d817fd408d994c86c7b2a3d111e60216220ff4) // vk.Q1.x - mstore(add(_vk, 0xa0), 0x23eb5e8befe06db56c45cacc7f6ebe1c5a6d564eacd9ce398f5512f78716db2f) // vk.Q1.y - mstore(add(_vk, 0xc0), 0x1343a11edd4c8f943d25b149f25ce46f3f3d778986116e54e46f19ecea6f222c) // vk.Q2.x - mstore(add(_vk, 0xe0), 0x21465130765a50d22ae703a7f04f1c56d702a1fd8e60ef7ab8643e7d65400d4a) // vk.Q2.y - mstore(add(_vk, 0x100), 0x14ca6d2277d046bfec277680aaef68c036229345162dc5898d4c59c48af3050c) // vk.Q3.x - mstore(add(_vk, 0x120), 0x0193076249ef903f84326def1f71f3e0f8964d6ad9b8169b10373534c5d8ce3a) // vk.Q3.y - mstore(add(_vk, 0x140), 0x19b321f51f228bda6233253f630bd7a4ef8886b0b0b04b8aa5dae7de26262741) // vk.Q4.x - mstore(add(_vk, 0x160), 0x29e642b2b28bb28117bf91a05f4072be4aa7b9e461a30a8b512c9ce550b8bd11) // vk.Q4.y - mstore(add(_vk, 0x180), 0x135c2b4ca117cad1e6de43b35922898f10a215ca4bd212fb235b11f749747a40) // vk.Q_M.x - mstore(add(_vk, 0x1a0), 0x1b5898cbfad83193f396baa1b97d270788e813afeb2a55342f4e01118d7c8d52) // vk.Q_M.y - mstore(add(_vk, 0x1c0), 0x22b15c7b21212709f0670cb679b2f9983b0624880388177e34194a86a8beeec4) // vk.Q_C.x - mstore(add(_vk, 0x1e0), 0x23abf1bb3ae5b994d972821a588c2a181d6f73b19cd63eb97ba3d279280c8d89) // vk.Q_C.y - mstore(add(_vk, 0x200), 0x113b6d3105a628cbad57a3e0d3af01035264182e3730b1e09ec465456c93e237) // vk.Q_ARITHMETIC.x - mstore(add(_vk, 0x220), 0x144c2223ed41c781c7e91e392a785122901565726d0733d1f85d715cf72f46c7) // vk.Q_ARITHMETIC.y - mstore(add(_vk, 0x240), 0x2ef5ddac9f6900407cb286d52468a09ed415e365b5086f5c9b74b4f281c61054) // vk.QSORT.x - mstore(add(_vk, 0x260), 0x010674e24f29b69a54da15ac59911e89cf3fa787ed2cad6a44daa63c67d00fd7) // vk.QSORT.y - mstore(add(_vk, 0x280), 0x26ba1f4d0e050a78621b511228a9c6983f7868dde8d03a3206ba8ecb4745228c) // vk.Q_ELLIPTIC.x - mstore(add(_vk, 0x2a0), 0x00e496fbcd18c30efca8bbab288382270e7c1ca730a6de1c97f1fdb8e8cbb8ae) // vk.Q_ELLIPTIC.y - mstore(add(_vk, 0x2c0), 0x12f33eb7f1ef14f7b9c5eef6fda9e8b915b1505a9fc4fddbe85273bab940215d) // vk.Q_AUX.x - mstore(add(_vk, 0x2e0), 0x0243ce5ba21f31b237dca7bb13bb6552da8e193324813b7269b144f5fc4bb571) // vk.Q_AUX.y - mstore(add(_vk, 0x300), 0x08ba0b0a65af34cf8d99b68d5a1f8ff614a3d2f2b79feeb798b1167cc9a38cc9) // vk.SIGMA1.x - mstore(add(_vk, 0x320), 0x150a1dbd173563cdd0503776c3d59e91d6e78c1f1e6d23785f9da5843b27fc60) // vk.SIGMA1.y - mstore(add(_vk, 0x340), 0x2495d18a5ab5b8e3a2f6f9888d92d349362dde30734049dccc6fa6e07d903231) // vk.SIGMA2.x - mstore(add(_vk, 0x360), 0x0823530dc06e55a763f9a51db768d4bc53ebec26334b3e9d248235e7972624c6) // vk.SIGMA2.y - mstore(add(_vk, 0x380), 0x15b6c07df0304bc78711f6f924f040f63c0a1e6174d1bc4bb20c5cf93444d239) // vk.SIGMA3.x - mstore(add(_vk, 0x3a0), 0x1c7932ed2c40d035d67e80599df3f127fd408c30af2f5dd14805dd5816715881) // vk.SIGMA3.y - mstore(add(_vk, 0x3c0), 0x2644c0b211b5bc8160034e9b4948392266e615c101df2306a82bc2f99ceb2357) // vk.SIGMA4.x - mstore(add(_vk, 0x3e0), 0x245551ceeed8c044a968549997e4d89071e9d65cd887afe82835c4b05394c8dd) // vk.SIGMA4.y - mstore(add(_vk, 0x400), 0x09796190fd3ba909c6530c89811df9b5b4f5f2fe6501ec21dd864b20673fc02c) // vk.TABLE1.x - mstore(add(_vk, 0x420), 0x00b9c2423e310caa43e1eb83b55f53977fccbed85422df8935635d77d146bf39) // vk.TABLE1.y - mstore(add(_vk, 0x440), 0x217dad26ccc0c543ec5750513e9365a5cae8164b08d364efcf4b5890ff05f334) // vk.TABLE2.x - mstore(add(_vk, 0x460), 0x1db28433f6bde424423f3587787f81c48101d2dc6e54b431332cb275f8518c62) // vk.TABLE2.y - mstore(add(_vk, 0x480), 0x2cc2d90f2da7f4ec16b7fe61babd4fb9b580ecff03c471764dd67a8c433afab5) // vk.TABLE3.x - mstore(add(_vk, 0x4a0), 0x3032b9ff096a43ce326cc63ffc6a86dcb913fb1f7700939f5304f6c6beb24574) // vk.TABLE3.y - mstore(add(_vk, 0x4c0), 0x1f4c58502ca713ed0bffb4ff31ed55e557e83a37d31b8e703aa9219d6158e2d2) // vk.TABLE4.x - mstore(add(_vk, 0x4e0), 0x0b0d5ed5432c5e7b56344c1d26ce0d9f632e8f8aa52505d6c89f6da89f357fa8) // vk.TABLE4.y - mstore(add(_vk, 0x500), 0x18f58f41d54253e53e11e950a30712a53ac21c410a53424cf08b5c866aa18ef7) // vk.TABLE_TYPE.x - mstore(add(_vk, 0x520), 0x085b844a9b90e6d79f01271644b9cbc23f81cccb1679ddb7c4cf28f525ff41ad) // vk.TABLE_TYPE.y - mstore(add(_vk, 0x540), 0x1409fc0d97f2c216efc3538236ffa767e74c140c918e041cd17029a30a4a9d44) // vk.ID1.x - mstore(add(_vk, 0x560), 0x26c5c627007675f6a57449fe0df318783b14e9abcf70ff93026059d76f6b9cd7) // vk.ID1.y - mstore(add(_vk, 0x580), 0x2c14b2eb3d66e1ad2ab2f3f572c788cc7fc3c5de27f10dc4b03fb8d24d99a100) // vk.ID2.x - mstore(add(_vk, 0x5a0), 0x12fb35d49297144b9c18d4fedadb24ecaf825a0b16f15429880254c021b848d3) // vk.ID2.y - mstore(add(_vk, 0x5c0), 0x09cd56d13b51b36941752c549fcbf0f91175759cd433aa663380ff74eea969bb) // vk.ID3.x - mstore(add(_vk, 0x5e0), 0x0a8120bced78e668891c2b79e4098b73357660d7ac5d18c38692b82fae92ceae) // vk.ID3.y - mstore(add(_vk, 0x600), 0x23a22f97c87c77b7ec20064f688ad1d82994517560d78cc0366cbaa3ad0fe931) // vk.ID4.x - mstore(add(_vk, 0x620), 0x08d8108812baa0e234edc5109ec726f19dc6efd247eea7d61930f0857844dba1) // vk.ID4.y - mstore(add(_vk, 0x640), 0x01) // vk.contains_recursive_proof - mstore(add(_vk, 0x660), 0) // vk.recursive_proof_public_input_indices - mstore(add(_vk, 0x680), 0x260e01b251f6f1c7e7ff4e580791dee8ea51d87a358e038b4efe30fac09383c1) // vk.g2_x.X.c1 - mstore(add(_vk, 0x6a0), 0x0118c4d5b837bcc2bc89b5b398b5974e9f5944073b32078b7e231fec938883b0) // vk.g2_x.X.c0 - mstore(add(_vk, 0x6c0), 0x04fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe4) // vk.g2_x.Y.c1 - mstore(add(_vk, 0x6e0), 0x22febda3c0c0632a56475b4214e5615e11e6dd3f96e6cea2854a87d4dacc5e55) // vk.g2_x.Y.c0 - mstore(_omegaInverseLoc, 0x036853f083780e87f8d7c71d111119c57dbe118c22d5ad707a82317466c5174c) // vk.work_root_inverse - } - } -} - -/** - * @title Ultra Plonk proof verification contract - * @dev Top level Plonk proof verification contract, which allows Plonk proof to be verified - */ -abstract contract BaseUltraVerifier { - // VERIFICATION KEY MEMORY LOCATIONS - uint256 internal constant N_LOC = 0x380; - uint256 internal constant NUM_INPUTS_LOC = 0x3a0; - uint256 internal constant OMEGA_LOC = 0x3c0; - uint256 internal constant DOMAIN_INVERSE_LOC = 0x3e0; - uint256 internal constant Q1_X_LOC = 0x400; - uint256 internal constant Q1_Y_LOC = 0x420; - uint256 internal constant Q2_X_LOC = 0x440; - uint256 internal constant Q2_Y_LOC = 0x460; - uint256 internal constant Q3_X_LOC = 0x480; - uint256 internal constant Q3_Y_LOC = 0x4a0; - uint256 internal constant Q4_X_LOC = 0x4c0; - uint256 internal constant Q4_Y_LOC = 0x4e0; - uint256 internal constant QM_X_LOC = 0x500; - uint256 internal constant QM_Y_LOC = 0x520; - uint256 internal constant QC_X_LOC = 0x540; - uint256 internal constant QC_Y_LOC = 0x560; - uint256 internal constant QARITH_X_LOC = 0x580; - uint256 internal constant QARITH_Y_LOC = 0x5a0; - uint256 internal constant QSORT_X_LOC = 0x5c0; - uint256 internal constant QSORT_Y_LOC = 0x5e0; - uint256 internal constant QELLIPTIC_X_LOC = 0x600; - uint256 internal constant QELLIPTIC_Y_LOC = 0x620; - uint256 internal constant QAUX_X_LOC = 0x640; - uint256 internal constant QAUX_Y_LOC = 0x660; - uint256 internal constant SIGMA1_X_LOC = 0x680; - uint256 internal constant SIGMA1_Y_LOC = 0x6a0; - uint256 internal constant SIGMA2_X_LOC = 0x6c0; - uint256 internal constant SIGMA2_Y_LOC = 0x6e0; - uint256 internal constant SIGMA3_X_LOC = 0x700; - uint256 internal constant SIGMA3_Y_LOC = 0x720; - uint256 internal constant SIGMA4_X_LOC = 0x740; - uint256 internal constant SIGMA4_Y_LOC = 0x760; - uint256 internal constant TABLE1_X_LOC = 0x780; - uint256 internal constant TABLE1_Y_LOC = 0x7a0; - uint256 internal constant TABLE2_X_LOC = 0x7c0; - uint256 internal constant TABLE2_Y_LOC = 0x7e0; - uint256 internal constant TABLE3_X_LOC = 0x800; - uint256 internal constant TABLE3_Y_LOC = 0x820; - uint256 internal constant TABLE4_X_LOC = 0x840; - uint256 internal constant TABLE4_Y_LOC = 0x860; - uint256 internal constant TABLE_TYPE_X_LOC = 0x880; - uint256 internal constant TABLE_TYPE_Y_LOC = 0x8a0; - uint256 internal constant ID1_X_LOC = 0x8c0; - uint256 internal constant ID1_Y_LOC = 0x8e0; - uint256 internal constant ID2_X_LOC = 0x900; - uint256 internal constant ID2_Y_LOC = 0x920; - uint256 internal constant ID3_X_LOC = 0x940; - uint256 internal constant ID3_Y_LOC = 0x960; - uint256 internal constant ID4_X_LOC = 0x980; - uint256 internal constant ID4_Y_LOC = 0x9a0; - uint256 internal constant CONTAINS_RECURSIVE_PROOF_LOC = 0x9c0; - uint256 internal constant RECURSIVE_PROOF_PUBLIC_INPUT_INDICES_LOC = 0x9e0; - uint256 internal constant G2X_X0_LOC = 0xa00; - uint256 internal constant G2X_X1_LOC = 0xa20; - uint256 internal constant G2X_Y0_LOC = 0xa40; - uint256 internal constant G2X_Y1_LOC = 0xa60; - - // ### PROOF DATA MEMORY LOCATIONS - uint256 internal constant W1_X_LOC = 0x1200; - uint256 internal constant W1_Y_LOC = 0x1220; - uint256 internal constant W2_X_LOC = 0x1240; - uint256 internal constant W2_Y_LOC = 0x1260; - uint256 internal constant W3_X_LOC = 0x1280; - uint256 internal constant W3_Y_LOC = 0x12a0; - uint256 internal constant W4_X_LOC = 0x12c0; - uint256 internal constant W4_Y_LOC = 0x12e0; - uint256 internal constant S_X_LOC = 0x1300; - uint256 internal constant S_Y_LOC = 0x1320; - uint256 internal constant Z_X_LOC = 0x1340; - uint256 internal constant Z_Y_LOC = 0x1360; - uint256 internal constant Z_LOOKUP_X_LOC = 0x1380; - uint256 internal constant Z_LOOKUP_Y_LOC = 0x13a0; - uint256 internal constant T1_X_LOC = 0x13c0; - uint256 internal constant T1_Y_LOC = 0x13e0; - uint256 internal constant T2_X_LOC = 0x1400; - uint256 internal constant T2_Y_LOC = 0x1420; - uint256 internal constant T3_X_LOC = 0x1440; - uint256 internal constant T3_Y_LOC = 0x1460; - uint256 internal constant T4_X_LOC = 0x1480; - uint256 internal constant T4_Y_LOC = 0x14a0; - - uint256 internal constant W1_EVAL_LOC = 0x1600; - uint256 internal constant W2_EVAL_LOC = 0x1620; - uint256 internal constant W3_EVAL_LOC = 0x1640; - uint256 internal constant W4_EVAL_LOC = 0x1660; - uint256 internal constant S_EVAL_LOC = 0x1680; - uint256 internal constant Z_EVAL_LOC = 0x16a0; - uint256 internal constant Z_LOOKUP_EVAL_LOC = 0x16c0; - uint256 internal constant Q1_EVAL_LOC = 0x16e0; - uint256 internal constant Q2_EVAL_LOC = 0x1700; - uint256 internal constant Q3_EVAL_LOC = 0x1720; - uint256 internal constant Q4_EVAL_LOC = 0x1740; - uint256 internal constant QM_EVAL_LOC = 0x1760; - uint256 internal constant QC_EVAL_LOC = 0x1780; - uint256 internal constant QARITH_EVAL_LOC = 0x17a0; - uint256 internal constant QSORT_EVAL_LOC = 0x17c0; - uint256 internal constant QELLIPTIC_EVAL_LOC = 0x17e0; - uint256 internal constant QAUX_EVAL_LOC = 0x1800; - uint256 internal constant TABLE1_EVAL_LOC = 0x1840; - uint256 internal constant TABLE2_EVAL_LOC = 0x1860; - uint256 internal constant TABLE3_EVAL_LOC = 0x1880; - uint256 internal constant TABLE4_EVAL_LOC = 0x18a0; - uint256 internal constant TABLE_TYPE_EVAL_LOC = 0x18c0; - uint256 internal constant ID1_EVAL_LOC = 0x18e0; - uint256 internal constant ID2_EVAL_LOC = 0x1900; - uint256 internal constant ID3_EVAL_LOC = 0x1920; - uint256 internal constant ID4_EVAL_LOC = 0x1940; - uint256 internal constant SIGMA1_EVAL_LOC = 0x1960; - uint256 internal constant SIGMA2_EVAL_LOC = 0x1980; - uint256 internal constant SIGMA3_EVAL_LOC = 0x19a0; - uint256 internal constant SIGMA4_EVAL_LOC = 0x19c0; - uint256 internal constant W1_OMEGA_EVAL_LOC = 0x19e0; - uint256 internal constant W2_OMEGA_EVAL_LOC = 0x2000; - uint256 internal constant W3_OMEGA_EVAL_LOC = 0x2020; - uint256 internal constant W4_OMEGA_EVAL_LOC = 0x2040; - uint256 internal constant S_OMEGA_EVAL_LOC = 0x2060; - uint256 internal constant Z_OMEGA_EVAL_LOC = 0x2080; - uint256 internal constant Z_LOOKUP_OMEGA_EVAL_LOC = 0x20a0; - uint256 internal constant TABLE1_OMEGA_EVAL_LOC = 0x20c0; - uint256 internal constant TABLE2_OMEGA_EVAL_LOC = 0x20e0; - uint256 internal constant TABLE3_OMEGA_EVAL_LOC = 0x2100; - uint256 internal constant TABLE4_OMEGA_EVAL_LOC = 0x2120; - - uint256 internal constant PI_Z_X_LOC = 0x2300; - uint256 internal constant PI_Z_Y_LOC = 0x2320; - uint256 internal constant PI_Z_OMEGA_X_LOC = 0x2340; - uint256 internal constant PI_Z_OMEGA_Y_LOC = 0x2360; - - // Used for elliptic widget. These are alias names for wire + shifted wire evaluations - uint256 internal constant X1_EVAL_LOC = W2_EVAL_LOC; - uint256 internal constant X2_EVAL_LOC = W1_OMEGA_EVAL_LOC; - uint256 internal constant X3_EVAL_LOC = W2_OMEGA_EVAL_LOC; - uint256 internal constant Y1_EVAL_LOC = W3_EVAL_LOC; - uint256 internal constant Y2_EVAL_LOC = W4_OMEGA_EVAL_LOC; - uint256 internal constant Y3_EVAL_LOC = W3_OMEGA_EVAL_LOC; - uint256 internal constant QBETA_LOC = Q3_EVAL_LOC; - uint256 internal constant QBETA_SQR_LOC = Q4_EVAL_LOC; - uint256 internal constant QSIGN_LOC = Q1_EVAL_LOC; - - // ### CHALLENGES MEMORY OFFSETS - - uint256 internal constant C_BETA_LOC = 0x2600; - uint256 internal constant C_GAMMA_LOC = 0x2620; - uint256 internal constant C_ALPHA_LOC = 0x2640; - uint256 internal constant C_ETA_LOC = 0x2660; - uint256 internal constant C_ETA_SQR_LOC = 0x2680; - uint256 internal constant C_ETA_CUBE_LOC = 0x26a0; - - uint256 internal constant C_ZETA_LOC = 0x26c0; - uint256 internal constant C_CURRENT_LOC = 0x26e0; - uint256 internal constant C_V0_LOC = 0x2700; - uint256 internal constant C_V1_LOC = 0x2720; - uint256 internal constant C_V2_LOC = 0x2740; - uint256 internal constant C_V3_LOC = 0x2760; - uint256 internal constant C_V4_LOC = 0x2780; - uint256 internal constant C_V5_LOC = 0x27a0; - uint256 internal constant C_V6_LOC = 0x27c0; - uint256 internal constant C_V7_LOC = 0x27e0; - uint256 internal constant C_V8_LOC = 0x2800; - uint256 internal constant C_V9_LOC = 0x2820; - uint256 internal constant C_V10_LOC = 0x2840; - uint256 internal constant C_V11_LOC = 0x2860; - uint256 internal constant C_V12_LOC = 0x2880; - uint256 internal constant C_V13_LOC = 0x28a0; - uint256 internal constant C_V14_LOC = 0x28c0; - uint256 internal constant C_V15_LOC = 0x28e0; - uint256 internal constant C_V16_LOC = 0x2900; - uint256 internal constant C_V17_LOC = 0x2920; - uint256 internal constant C_V18_LOC = 0x2940; - uint256 internal constant C_V19_LOC = 0x2960; - uint256 internal constant C_V20_LOC = 0x2980; - uint256 internal constant C_V21_LOC = 0x29a0; - uint256 internal constant C_V22_LOC = 0x29c0; - uint256 internal constant C_V23_LOC = 0x29e0; - uint256 internal constant C_V24_LOC = 0x2a00; - uint256 internal constant C_V25_LOC = 0x2a20; - uint256 internal constant C_V26_LOC = 0x2a40; - uint256 internal constant C_V27_LOC = 0x2a60; - uint256 internal constant C_V28_LOC = 0x2a80; - uint256 internal constant C_V29_LOC = 0x2aa0; - uint256 internal constant C_V30_LOC = 0x2ac0; - - uint256 internal constant C_U_LOC = 0x2b00; - - // ### LOCAL VARIABLES MEMORY OFFSETS - uint256 internal constant DELTA_NUMERATOR_LOC = 0x3000; - uint256 internal constant DELTA_DENOMINATOR_LOC = 0x3020; - uint256 internal constant ZETA_POW_N_LOC = 0x3040; - uint256 internal constant PUBLIC_INPUT_DELTA_LOC = 0x3060; - uint256 internal constant ZERO_POLY_LOC = 0x3080; - uint256 internal constant L_START_LOC = 0x30a0; - uint256 internal constant L_END_LOC = 0x30c0; - uint256 internal constant R_ZERO_EVAL_LOC = 0x30e0; - - uint256 internal constant PLOOKUP_DELTA_NUMERATOR_LOC = 0x3100; - uint256 internal constant PLOOKUP_DELTA_DENOMINATOR_LOC = 0x3120; - uint256 internal constant PLOOKUP_DELTA_LOC = 0x3140; - - uint256 internal constant ACCUMULATOR_X_LOC = 0x3160; - uint256 internal constant ACCUMULATOR_Y_LOC = 0x3180; - uint256 internal constant ACCUMULATOR2_X_LOC = 0x31a0; - uint256 internal constant ACCUMULATOR2_Y_LOC = 0x31c0; - uint256 internal constant PAIRING_LHS_X_LOC = 0x31e0; - uint256 internal constant PAIRING_LHS_Y_LOC = 0x3200; - uint256 internal constant PAIRING_RHS_X_LOC = 0x3220; - uint256 internal constant PAIRING_RHS_Y_LOC = 0x3240; - - // misc stuff - uint256 internal constant OMEGA_INVERSE_LOC = 0x3300; - uint256 internal constant C_ALPHA_SQR_LOC = 0x3320; - uint256 internal constant C_ALPHA_CUBE_LOC = 0x3340; - uint256 internal constant C_ALPHA_QUAD_LOC = 0x3360; - uint256 internal constant C_ALPHA_BASE_LOC = 0x3380; - - // ### RECURSION VARIABLE MEMORY LOCATIONS - uint256 internal constant RECURSIVE_P1_X_LOC = 0x3400; - uint256 internal constant RECURSIVE_P1_Y_LOC = 0x3420; - uint256 internal constant RECURSIVE_P2_X_LOC = 0x3440; - uint256 internal constant RECURSIVE_P2_Y_LOC = 0x3460; - uint256 internal constant PUBLIC_INPUTS_HASH_LOCATION = 0x3480; - - // sub-identity storage - uint256 internal constant PERMUTATION_IDENTITY = 0x3500; - uint256 internal constant PLOOKUP_IDENTITY = 0x3520; - uint256 internal constant ARITHMETIC_IDENTITY = 0x3540; - uint256 internal constant SORT_IDENTITY = 0x3560; - uint256 internal constant ELLIPTIC_IDENTITY = 0x3580; - uint256 internal constant AUX_IDENTITY = 0x35a0; - uint256 internal constant AUX_NON_NATIVE_FIELD_EVALUATION = 0x35c0; - uint256 internal constant AUX_LIMB_ACCUMULATOR_EVALUATION = 0x35e0; - uint256 internal constant AUX_RAM_CONSISTENCY_EVALUATION = 0x3600; - uint256 internal constant AUX_ROM_CONSISTENCY_EVALUATION = 0x3620; - uint256 internal constant AUX_MEMORY_EVALUATION = 0x3640; - - uint256 internal constant QUOTIENT_EVAL_LOC = 0x3660; - uint256 internal constant ZERO_POLY_INVERSE_LOC = 0x3680; - - // when hashing public inputs we use memory at NU_CHALLENGE_INPUT_LOC_A, as the hash input size is unknown at compile time - uint256 internal constant NU_CHALLENGE_INPUT_LOC_A = 0x36a0; - uint256 internal constant NU_CHALLENGE_INPUT_LOC_B = 0x36c0; - uint256 internal constant NU_CHALLENGE_INPUT_LOC_C = 0x36e0; - - bytes4 internal constant INVALID_VERIFICATION_KEY_SELECTOR = 0x7e5769bf; - bytes4 internal constant POINT_NOT_ON_CURVE_SELECTOR = 0xa3dad654; - bytes4 internal constant PUBLIC_INPUT_INVALID_BN128_G1_POINT_SELECTOR = 0xeba9f4a6; - bytes4 internal constant PUBLIC_INPUT_GE_P_SELECTOR = 0x374a972f; - bytes4 internal constant MOD_EXP_FAILURE_SELECTOR = 0xf894a7bc; - bytes4 internal constant PAIRING_PREAMBLE_FAILED_SELECTOR = 0x01882d81; - bytes4 internal constant OPENING_COMMITMENT_FAILED_SELECTOR = 0x4e719763; - bytes4 internal constant PAIRING_FAILED_SELECTOR = 0xd71fd263; - - uint256 internal constant ETA_INPUT_LENGTH = 0xc0; // W1, W2, W3 = 6 * 0x20 bytes - - // We need to hash 41 field elements when generating the NU challenge - // w1, w2, w3, w4, s, z, z_lookup, q1, q2, q3, q4, qm, qc, qarith (14) - // qsort, qelliptic, qaux, sigma1, sigma2, sigma, sigma4, (7) - // table1, table2, table3, table4, tabletype, id1, id2, id3, id4, (9) - // w1_omega, w2_omega, w3_omega, w4_omega, s_omega, z_omega, z_lookup_omega, (7) - // table1_omega, table2_omega, table3_omega, table4_omega (4) - uint256 internal constant NU_INPUT_LENGTH = 0x520; // 0x520 = 41 * 0x20 - - // There are ELEVEN G1 group elements added into the transcript in the `beta` round, that we need to skip over - // W1, W2, W3, W4, S, Z, Z_LOOKUP, T1, T2, T3, T4 - uint256 internal constant NU_CALLDATA_SKIP_LENGTH = 0x2c0; // 11 * 0x40 = 0x2c0 - - uint256 internal constant NEGATIVE_INVERSE_OF_2_MODULO_P = - 0x183227397098d014dc2822db40c0ac2e9419f4243cdcb848a1f0fac9f8000000; - uint256 internal constant LIMB_SIZE = 0x100000000000000000; // 2<<68 - uint256 internal constant SUBLIMB_SHIFT = 0x4000; // 2<<14 - - // y^2 = x^3 + ax + b - // for Grumpkin, a = 0 and b = -17. We use b in a custom gate relation that evaluates elliptic curve arithmetic - uint256 internal constant GRUMPKIN_CURVE_B_PARAMETER_NEGATED = 17; - - error INVALID_VERIFICATION_KEY(); - error POINT_NOT_ON_CURVE(); - error PUBLIC_INPUT_COUNT_INVALID(uint256 expected, uint256 actual); - error PUBLIC_INPUT_INVALID_BN128_G1_POINT(); - error PUBLIC_INPUT_GE_P(); - error MOD_EXP_FAILURE(); - error PAIRING_PREAMBLE_FAILED(); - error OPENING_COMMITMENT_FAILED(); - error PAIRING_FAILED(); - - function getVerificationKeyHash() public pure virtual returns (bytes32); - - /** - * @dev We assume that the verification key loaded by this function is constant as we only verify it on deployment - */ - function loadVerificationKey(uint256 _vk, uint256 _omegaInverseLoc) internal pure virtual; - - constructor() { - loadVerificationKey(N_LOC, OMEGA_INVERSE_LOC); - - // We verify that all of the EC points in the verification key lie on the bn128 curve. - assembly { - let q := 21888242871839275222246405745257275088696311157297823662689037894645226208583 // EC group order - - let success := 1 - - // VALIDATE Q1 - { - let x := mload(Q1_X_LOC) - let y := mload(Q1_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE Q2 - { - let x := mload(Q2_X_LOC) - let y := mload(Q2_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE Q3 - { - let x := mload(Q3_X_LOC) - let y := mload(Q3_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE Q4 - { - let x := mload(Q4_X_LOC) - let y := mload(Q4_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - mstore(0x00, x) - mstore(0x20, y) - } - // VALIDATE QM - { - let x := mload(QM_X_LOC) - let y := mload(QM_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE QC - { - let x := mload(QC_X_LOC) - let y := mload(QC_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE QARITH - { - let x := mload(QARITH_X_LOC) - let y := mload(QARITH_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE QSORT - { - let x := mload(QSORT_X_LOC) - let y := mload(QSORT_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE QELLIPTIC - { - let x := mload(QELLIPTIC_X_LOC) - let y := mload(QELLIPTIC_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE QAUX - { - let x := mload(QAUX_X_LOC) - let y := mload(QAUX_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE SIGMA1 - { - let x := mload(SIGMA1_X_LOC) - let y := mload(SIGMA1_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE SIGMA2 - { - let x := mload(SIGMA2_X_LOC) - let y := mload(SIGMA2_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE SIGMA3 - { - let x := mload(SIGMA3_X_LOC) - let y := mload(SIGMA3_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE SIGMA4 - { - let x := mload(SIGMA4_X_LOC) - let y := mload(SIGMA4_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE TABLE1 - { - let x := mload(TABLE1_X_LOC) - let y := mload(TABLE1_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE TABLE2 - { - let x := mload(TABLE2_X_LOC) - let y := mload(TABLE2_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE TABLE3 - { - let x := mload(TABLE3_X_LOC) - let y := mload(TABLE3_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE TABLE4 - { - let x := mload(TABLE4_X_LOC) - let y := mload(TABLE4_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE TABLE_TYPE - { - let x := mload(TABLE_TYPE_X_LOC) - let y := mload(TABLE_TYPE_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE ID1 - { - let x := mload(ID1_X_LOC) - let y := mload(ID1_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE ID2 - { - let x := mload(ID2_X_LOC) - let y := mload(ID2_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE ID3 - { - let x := mload(ID3_X_LOC) - let y := mload(ID3_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE ID4 - { - let x := mload(ID4_X_LOC) - let y := mload(ID4_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - - if iszero(success) { - mstore(0x0, INVALID_VERIFICATION_KEY_SELECTOR) - revert(0x00, 0x04) - } - } - } - - /** - * @notice Verify a Ultra Plonk proof - * @param _proof - The serialized proof - * @param _publicInputs - An array of the public inputs - * @return True if proof is valid, reverts otherwise - */ - function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool) { - loadVerificationKey(N_LOC, OMEGA_INVERSE_LOC); - - uint256 requiredPublicInputCount; - assembly { - requiredPublicInputCount := mload(NUM_INPUTS_LOC) - } - if (requiredPublicInputCount != _publicInputs.length) { - revert PUBLIC_INPUT_COUNT_INVALID(requiredPublicInputCount, _publicInputs.length); - } - - assembly { - let q := 21888242871839275222246405745257275088696311157297823662689037894645226208583 // EC group order - let p := 21888242871839275222246405745257275088548364400416034343698204186575808495617 // Prime field order - - /** - * LOAD PROOF FROM CALLDATA - */ - { - let data_ptr := add(calldataload(0x04), 0x24) - - mstore(W1_Y_LOC, mod(calldataload(data_ptr), q)) - mstore(W1_X_LOC, mod(calldataload(add(data_ptr, 0x20)), q)) - - mstore(W2_Y_LOC, mod(calldataload(add(data_ptr, 0x40)), q)) - mstore(W2_X_LOC, mod(calldataload(add(data_ptr, 0x60)), q)) - - mstore(W3_Y_LOC, mod(calldataload(add(data_ptr, 0x80)), q)) - mstore(W3_X_LOC, mod(calldataload(add(data_ptr, 0xa0)), q)) - - mstore(W4_Y_LOC, mod(calldataload(add(data_ptr, 0xc0)), q)) - mstore(W4_X_LOC, mod(calldataload(add(data_ptr, 0xe0)), q)) - - mstore(S_Y_LOC, mod(calldataload(add(data_ptr, 0x100)), q)) - mstore(S_X_LOC, mod(calldataload(add(data_ptr, 0x120)), q)) - mstore(Z_Y_LOC, mod(calldataload(add(data_ptr, 0x140)), q)) - mstore(Z_X_LOC, mod(calldataload(add(data_ptr, 0x160)), q)) - mstore(Z_LOOKUP_Y_LOC, mod(calldataload(add(data_ptr, 0x180)), q)) - mstore(Z_LOOKUP_X_LOC, mod(calldataload(add(data_ptr, 0x1a0)), q)) - mstore(T1_Y_LOC, mod(calldataload(add(data_ptr, 0x1c0)), q)) - mstore(T1_X_LOC, mod(calldataload(add(data_ptr, 0x1e0)), q)) - - mstore(T2_Y_LOC, mod(calldataload(add(data_ptr, 0x200)), q)) - mstore(T2_X_LOC, mod(calldataload(add(data_ptr, 0x220)), q)) - - mstore(T3_Y_LOC, mod(calldataload(add(data_ptr, 0x240)), q)) - mstore(T3_X_LOC, mod(calldataload(add(data_ptr, 0x260)), q)) - - mstore(T4_Y_LOC, mod(calldataload(add(data_ptr, 0x280)), q)) - mstore(T4_X_LOC, mod(calldataload(add(data_ptr, 0x2a0)), q)) - - mstore(W1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x2c0)), p)) - mstore(W2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x2e0)), p)) - mstore(W3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x300)), p)) - mstore(W4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x320)), p)) - mstore(S_EVAL_LOC, mod(calldataload(add(data_ptr, 0x340)), p)) - mstore(Z_EVAL_LOC, mod(calldataload(add(data_ptr, 0x360)), p)) - mstore(Z_LOOKUP_EVAL_LOC, mod(calldataload(add(data_ptr, 0x380)), p)) - mstore(Q1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x3a0)), p)) - mstore(Q2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x3c0)), p)) - mstore(Q3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x3e0)), p)) - mstore(Q4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x400)), p)) - mstore(QM_EVAL_LOC, mod(calldataload(add(data_ptr, 0x420)), p)) - mstore(QC_EVAL_LOC, mod(calldataload(add(data_ptr, 0x440)), p)) - mstore(QARITH_EVAL_LOC, mod(calldataload(add(data_ptr, 0x460)), p)) - mstore(QSORT_EVAL_LOC, mod(calldataload(add(data_ptr, 0x480)), p)) - mstore(QELLIPTIC_EVAL_LOC, mod(calldataload(add(data_ptr, 0x4a0)), p)) - mstore(QAUX_EVAL_LOC, mod(calldataload(add(data_ptr, 0x4c0)), p)) - - mstore(SIGMA1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x4e0)), p)) - mstore(SIGMA2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x500)), p)) - - mstore(SIGMA3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x520)), p)) - mstore(SIGMA4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x540)), p)) - - mstore(TABLE1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x560)), p)) - mstore(TABLE2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x580)), p)) - mstore(TABLE3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x5a0)), p)) - mstore(TABLE4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x5c0)), p)) - mstore(TABLE_TYPE_EVAL_LOC, mod(calldataload(add(data_ptr, 0x5e0)), p)) - - mstore(ID1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x600)), p)) - mstore(ID2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x620)), p)) - mstore(ID3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x640)), p)) - mstore(ID4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x660)), p)) - - mstore(W1_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x680)), p)) - mstore(W2_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x6a0)), p)) - mstore(W3_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x6c0)), p)) - mstore(W4_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x6e0)), p)) - mstore(S_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x700)), p)) - - mstore(Z_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x720)), p)) - - mstore(Z_LOOKUP_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x740)), p)) - mstore(TABLE1_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x760)), p)) - mstore(TABLE2_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x780)), p)) - mstore(TABLE3_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x7a0)), p)) - mstore(TABLE4_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x7c0)), p)) - - mstore(PI_Z_Y_LOC, mod(calldataload(add(data_ptr, 0x7e0)), q)) - mstore(PI_Z_X_LOC, mod(calldataload(add(data_ptr, 0x800)), q)) - - mstore(PI_Z_OMEGA_Y_LOC, mod(calldataload(add(data_ptr, 0x820)), q)) - mstore(PI_Z_OMEGA_X_LOC, mod(calldataload(add(data_ptr, 0x840)), q)) - } - - /** - * LOAD RECURSIVE PROOF INTO MEMORY - */ - { - if mload(CONTAINS_RECURSIVE_PROOF_LOC) { - let public_inputs_ptr := add(calldataload(0x24), 0x24) - let index_counter := add(shl(5, mload(RECURSIVE_PROOF_PUBLIC_INPUT_INDICES_LOC)), public_inputs_ptr) - - let x0 := calldataload(index_counter) - x0 := add(x0, shl(68, calldataload(add(index_counter, 0x20)))) - x0 := add(x0, shl(136, calldataload(add(index_counter, 0x40)))) - x0 := add(x0, shl(204, calldataload(add(index_counter, 0x60)))) - let y0 := calldataload(add(index_counter, 0x80)) - y0 := add(y0, shl(68, calldataload(add(index_counter, 0xa0)))) - y0 := add(y0, shl(136, calldataload(add(index_counter, 0xc0)))) - y0 := add(y0, shl(204, calldataload(add(index_counter, 0xe0)))) - let x1 := calldataload(add(index_counter, 0x100)) - x1 := add(x1, shl(68, calldataload(add(index_counter, 0x120)))) - x1 := add(x1, shl(136, calldataload(add(index_counter, 0x140)))) - x1 := add(x1, shl(204, calldataload(add(index_counter, 0x160)))) - let y1 := calldataload(add(index_counter, 0x180)) - y1 := add(y1, shl(68, calldataload(add(index_counter, 0x1a0)))) - y1 := add(y1, shl(136, calldataload(add(index_counter, 0x1c0)))) - y1 := add(y1, shl(204, calldataload(add(index_counter, 0x1e0)))) - mstore(RECURSIVE_P1_X_LOC, x0) - mstore(RECURSIVE_P1_Y_LOC, y0) - mstore(RECURSIVE_P2_X_LOC, x1) - mstore(RECURSIVE_P2_Y_LOC, y1) - - // validate these are valid bn128 G1 points - if iszero(and(and(lt(x0, q), lt(x1, q)), and(lt(y0, q), lt(y1, q)))) { - mstore(0x00, PUBLIC_INPUT_INVALID_BN128_G1_POINT_SELECTOR) - revert(0x00, 0x04) - } - } - } - - { - /** - * Generate initial challenge - */ - mstore(0x00, shl(224, mload(N_LOC))) - mstore(0x04, shl(224, mload(NUM_INPUTS_LOC))) - let challenge := keccak256(0x00, 0x08) - - /** - * Generate eta challenge - */ - mstore(PUBLIC_INPUTS_HASH_LOCATION, challenge) - // The public input location is stored at 0x24, we then add 0x24 to skip selector and the length of public inputs - let public_inputs_start := add(calldataload(0x24), 0x24) - // copy the public inputs over - let public_input_size := mul(mload(NUM_INPUTS_LOC), 0x20) - calldatacopy(add(PUBLIC_INPUTS_HASH_LOCATION, 0x20), public_inputs_start, public_input_size) - - // copy W1, W2, W3 into challenge. Each point is 0x40 bytes, so load 0xc0 = 3 * 0x40 bytes (ETA input length) - let w_start := add(calldataload(0x04), 0x24) - calldatacopy(add(add(PUBLIC_INPUTS_HASH_LOCATION, 0x20), public_input_size), w_start, ETA_INPUT_LENGTH) - - // Challenge is the old challenge + public inputs + W1, W2, W3 (0x20 + public_input_size + 0xc0) - let challenge_bytes_size := add(0x20, add(public_input_size, ETA_INPUT_LENGTH)) - - challenge := keccak256(PUBLIC_INPUTS_HASH_LOCATION, challenge_bytes_size) - { - let eta := mod(challenge, p) - mstore(C_ETA_LOC, eta) - mstore(C_ETA_SQR_LOC, mulmod(eta, eta, p)) - mstore(C_ETA_CUBE_LOC, mulmod(mload(C_ETA_SQR_LOC), eta, p)) - } - - /** - * Generate beta challenge - */ - mstore(0x00, challenge) - mstore(0x20, mload(W4_Y_LOC)) - mstore(0x40, mload(W4_X_LOC)) - mstore(0x60, mload(S_Y_LOC)) - mstore(0x80, mload(S_X_LOC)) - challenge := keccak256(0x00, 0xa0) - mstore(C_BETA_LOC, mod(challenge, p)) - - /** - * Generate gamma challenge - */ - mstore(0x00, challenge) - mstore8(0x20, 0x01) - challenge := keccak256(0x00, 0x21) - mstore(C_GAMMA_LOC, mod(challenge, p)) - - /** - * Generate alpha challenge - */ - mstore(0x00, challenge) - mstore(0x20, mload(Z_Y_LOC)) - mstore(0x40, mload(Z_X_LOC)) - mstore(0x60, mload(Z_LOOKUP_Y_LOC)) - mstore(0x80, mload(Z_LOOKUP_X_LOC)) - challenge := keccak256(0x00, 0xa0) - mstore(C_ALPHA_LOC, mod(challenge, p)) - - /** - * Compute and store some powers of alpha for future computations - */ - let alpha := mload(C_ALPHA_LOC) - mstore(C_ALPHA_SQR_LOC, mulmod(alpha, alpha, p)) - mstore(C_ALPHA_CUBE_LOC, mulmod(mload(C_ALPHA_SQR_LOC), alpha, p)) - mstore(C_ALPHA_QUAD_LOC, mulmod(mload(C_ALPHA_CUBE_LOC), alpha, p)) - mstore(C_ALPHA_BASE_LOC, alpha) - - /** - * Generate zeta challenge - */ - mstore(0x00, challenge) - mstore(0x20, mload(T1_Y_LOC)) - mstore(0x40, mload(T1_X_LOC)) - mstore(0x60, mload(T2_Y_LOC)) - mstore(0x80, mload(T2_X_LOC)) - mstore(0xa0, mload(T3_Y_LOC)) - mstore(0xc0, mload(T3_X_LOC)) - mstore(0xe0, mload(T4_Y_LOC)) - mstore(0x100, mload(T4_X_LOC)) - - challenge := keccak256(0x00, 0x120) - - mstore(C_ZETA_LOC, mod(challenge, p)) - mstore(C_CURRENT_LOC, challenge) - } - - /** - * EVALUATE FIELD OPERATIONS - */ - - /** - * COMPUTE PUBLIC INPUT DELTA - * ΔPI = ∏ᵢ∈ℓ(wᵢ + β σ(i) + γ) / ∏ᵢ∈ℓ(wᵢ + β σ'(i) + γ) - */ - { - let beta := mload(C_BETA_LOC) // β - let gamma := mload(C_GAMMA_LOC) // γ - let work_root := mload(OMEGA_LOC) // ω - let numerator_value := 1 - let denominator_value := 1 - - let p_clone := p // move p to the front of the stack - let valid_inputs := true - - // Load the starting point of the public inputs (jump over the selector and the length of public inputs [0x24]) - let public_inputs_ptr := add(calldataload(0x24), 0x24) - - // endpoint_ptr = public_inputs_ptr + num_inputs * 0x20. // every public input is 0x20 bytes - let endpoint_ptr := add(public_inputs_ptr, mul(mload(NUM_INPUTS_LOC), 0x20)) - - // root_1 = β * 0x05 - let root_1 := mulmod(beta, 0x05, p_clone) // k1.β - // root_2 = β * 0x0c - let root_2 := mulmod(beta, 0x0c, p_clone) - // @note 0x05 + 0x07 == 0x0c == external coset generator - - for {} lt(public_inputs_ptr, endpoint_ptr) { public_inputs_ptr := add(public_inputs_ptr, 0x20) } { - /** - * input = public_input[i] - * valid_inputs &= input < p - * temp = input + gamma - * numerator_value *= (β.σ(i) + wᵢ + γ) // σ(i) = 0x05.ωⁱ - * denominator_value *= (β.σ'(i) + wᵢ + γ) // σ'(i) = 0x0c.ωⁱ - * root_1 *= ω - * root_2 *= ω - */ - - let input := calldataload(public_inputs_ptr) - valid_inputs := and(valid_inputs, lt(input, p_clone)) - let temp := addmod(input, gamma, p_clone) - - numerator_value := mulmod(numerator_value, add(root_1, temp), p_clone) - denominator_value := mulmod(denominator_value, add(root_2, temp), p_clone) - - root_1 := mulmod(root_1, work_root, p_clone) - root_2 := mulmod(root_2, work_root, p_clone) - } - - // Revert if not all public inputs are field elements (i.e. < p) - if iszero(valid_inputs) { - mstore(0x00, PUBLIC_INPUT_GE_P_SELECTOR) - revert(0x00, 0x04) - } - - mstore(DELTA_NUMERATOR_LOC, numerator_value) - mstore(DELTA_DENOMINATOR_LOC, denominator_value) - } - - /** - * Compute Plookup delta factor [γ(1 + β)]^{n-k} - * k = num roots cut out of Z_H = 4 - */ - { - let delta_base := mulmod(mload(C_GAMMA_LOC), addmod(mload(C_BETA_LOC), 1, p), p) - let delta_numerator := delta_base - { - let exponent := mload(N_LOC) - let count := 1 - for {} lt(count, exponent) { count := add(count, count) } { - delta_numerator := mulmod(delta_numerator, delta_numerator, p) - } - } - mstore(PLOOKUP_DELTA_NUMERATOR_LOC, delta_numerator) - - let delta_denominator := mulmod(delta_base, delta_base, p) - delta_denominator := mulmod(delta_denominator, delta_denominator, p) - mstore(PLOOKUP_DELTA_DENOMINATOR_LOC, delta_denominator) - } - /** - * Compute lagrange poly and vanishing poly fractions - */ - { - /** - * vanishing_numerator = zeta - * ZETA_POW_N = zeta^n - * vanishing_numerator -= 1 - * accumulating_root = omega_inverse - * work_root = p - accumulating_root - * domain_inverse = domain_inverse - * vanishing_denominator = zeta + work_root - * work_root *= accumulating_root - * vanishing_denominator *= (zeta + work_root) - * work_root *= accumulating_root - * vanishing_denominator *= (zeta + work_root) - * vanishing_denominator *= (zeta + (zeta + accumulating_root)) - * work_root = omega - * lagrange_numerator = vanishing_numerator * domain_inverse - * l_start_denominator = zeta - 1 - * accumulating_root = work_root^2 - * l_end_denominator = accumulating_root^2 * work_root * zeta - 1 - * Note: l_end_denominator term contains a term \omega^5 to cut out 5 roots of unity from vanishing poly - */ - - let zeta := mload(C_ZETA_LOC) - - // compute zeta^n, where n is a power of 2 - let vanishing_numerator := zeta - { - // pow_small - let exponent := mload(N_LOC) - let count := 1 - for {} lt(count, exponent) { count := add(count, count) } { - vanishing_numerator := mulmod(vanishing_numerator, vanishing_numerator, p) - } - } - mstore(ZETA_POW_N_LOC, vanishing_numerator) - vanishing_numerator := addmod(vanishing_numerator, sub(p, 1), p) - - let accumulating_root := mload(OMEGA_INVERSE_LOC) - let work_root := sub(p, accumulating_root) - let domain_inverse := mload(DOMAIN_INVERSE_LOC) - - let vanishing_denominator := addmod(zeta, work_root, p) - work_root := mulmod(work_root, accumulating_root, p) - vanishing_denominator := mulmod(vanishing_denominator, addmod(zeta, work_root, p), p) - work_root := mulmod(work_root, accumulating_root, p) - vanishing_denominator := mulmod(vanishing_denominator, addmod(zeta, work_root, p), p) - vanishing_denominator := - mulmod(vanishing_denominator, addmod(zeta, mulmod(work_root, accumulating_root, p), p), p) - - work_root := mload(OMEGA_LOC) - - let lagrange_numerator := mulmod(vanishing_numerator, domain_inverse, p) - let l_start_denominator := addmod(zeta, sub(p, 1), p) - - accumulating_root := mulmod(work_root, work_root, p) - - let l_end_denominator := - addmod( - mulmod(mulmod(mulmod(accumulating_root, accumulating_root, p), work_root, p), zeta, p), sub(p, 1), p - ) - - /** - * Compute inversions using Montgomery's batch inversion trick - */ - let accumulator := mload(DELTA_DENOMINATOR_LOC) - let t0 := accumulator - accumulator := mulmod(accumulator, vanishing_denominator, p) - let t1 := accumulator - accumulator := mulmod(accumulator, vanishing_numerator, p) - let t2 := accumulator - accumulator := mulmod(accumulator, l_start_denominator, p) - let t3 := accumulator - accumulator := mulmod(accumulator, mload(PLOOKUP_DELTA_DENOMINATOR_LOC), p) - let t4 := accumulator - { - mstore(0, 0x20) - mstore(0x20, 0x20) - mstore(0x40, 0x20) - mstore(0x60, mulmod(accumulator, l_end_denominator, p)) - mstore(0x80, sub(p, 2)) - mstore(0xa0, p) - if iszero(staticcall(gas(), 0x05, 0x00, 0xc0, 0x00, 0x20)) { - mstore(0x0, MOD_EXP_FAILURE_SELECTOR) - revert(0x00, 0x04) - } - accumulator := mload(0x00) - } - - t4 := mulmod(accumulator, t4, p) - accumulator := mulmod(accumulator, l_end_denominator, p) - - t3 := mulmod(accumulator, t3, p) - accumulator := mulmod(accumulator, mload(PLOOKUP_DELTA_DENOMINATOR_LOC), p) - - t2 := mulmod(accumulator, t2, p) - accumulator := mulmod(accumulator, l_start_denominator, p) - - t1 := mulmod(accumulator, t1, p) - accumulator := mulmod(accumulator, vanishing_numerator, p) - - t0 := mulmod(accumulator, t0, p) - accumulator := mulmod(accumulator, vanishing_denominator, p) - - accumulator := mulmod(mulmod(accumulator, accumulator, p), mload(DELTA_DENOMINATOR_LOC), p) - - mstore(PUBLIC_INPUT_DELTA_LOC, mulmod(mload(DELTA_NUMERATOR_LOC), accumulator, p)) - mstore(ZERO_POLY_LOC, mulmod(vanishing_numerator, t0, p)) - mstore(ZERO_POLY_INVERSE_LOC, mulmod(vanishing_denominator, t1, p)) - mstore(L_START_LOC, mulmod(lagrange_numerator, t2, p)) - mstore(PLOOKUP_DELTA_LOC, mulmod(mload(PLOOKUP_DELTA_NUMERATOR_LOC), t3, p)) - mstore(L_END_LOC, mulmod(lagrange_numerator, t4, p)) - } - - /** - * UltraPlonk Widget Ordering: - * - * 1. Permutation widget - * 2. Plookup widget - * 3. Arithmetic widget - * 4. Fixed base widget (?) - * 5. GenPermSort widget - * 6. Elliptic widget - * 7. Auxiliary widget - */ - - /** - * COMPUTE PERMUTATION WIDGET EVALUATION - */ - { - let alpha := mload(C_ALPHA_LOC) - let beta := mload(C_BETA_LOC) - let gamma := mload(C_GAMMA_LOC) - - /** - * t1 = (W1 + gamma + beta * ID1) * (W2 + gamma + beta * ID2) - * t2 = (W3 + gamma + beta * ID3) * (W4 + gamma + beta * ID4) - * result = alpha_base * z_eval * t1 * t2 - * t1 = (W1 + gamma + beta * sigma_1_eval) * (W2 + gamma + beta * sigma_2_eval) - * t2 = (W2 + gamma + beta * sigma_3_eval) * (W3 + gamma + beta * sigma_4_eval) - * result -= (alpha_base * z_omega_eval * t1 * t2) - */ - let t1 := - mulmod( - add(add(mload(W1_EVAL_LOC), gamma), mulmod(beta, mload(ID1_EVAL_LOC), p)), - add(add(mload(W2_EVAL_LOC), gamma), mulmod(beta, mload(ID2_EVAL_LOC), p)), - p - ) - let t2 := - mulmod( - add(add(mload(W3_EVAL_LOC), gamma), mulmod(beta, mload(ID3_EVAL_LOC), p)), - add(add(mload(W4_EVAL_LOC), gamma), mulmod(beta, mload(ID4_EVAL_LOC), p)), - p - ) - let result := mulmod(mload(C_ALPHA_BASE_LOC), mulmod(mload(Z_EVAL_LOC), mulmod(t1, t2, p), p), p) - t1 := - mulmod( - add(add(mload(W1_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA1_EVAL_LOC), p)), - add(add(mload(W2_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA2_EVAL_LOC), p)), - p - ) - t2 := - mulmod( - add(add(mload(W3_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA3_EVAL_LOC), p)), - add(add(mload(W4_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA4_EVAL_LOC), p)), - p - ) - result := - addmod( - result, - sub(p, mulmod(mload(C_ALPHA_BASE_LOC), mulmod(mload(Z_OMEGA_EVAL_LOC), mulmod(t1, t2, p), p), p)), - p - ) - - /** - * alpha_base *= alpha - * result += alpha_base . (L_{n-k}(ʓ) . (z(ʓ.ω) - ∆_{PI})) - * alpha_base *= alpha - * result += alpha_base . (L_1(ʓ)(Z(ʓ) - 1)) - * alpha_Base *= alpha - */ - mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p)) - result := - addmod( - result, - mulmod( - mload(C_ALPHA_BASE_LOC), - mulmod( - mload(L_END_LOC), - addmod(mload(Z_OMEGA_EVAL_LOC), sub(p, mload(PUBLIC_INPUT_DELTA_LOC)), p), - p - ), - p - ), - p - ) - mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p)) - mstore( - PERMUTATION_IDENTITY, - addmod( - result, - mulmod( - mload(C_ALPHA_BASE_LOC), - mulmod(mload(L_START_LOC), addmod(mload(Z_EVAL_LOC), sub(p, 1), p), p), - p - ), - p - ) - ) - mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p)) - } - - /** - * COMPUTE PLOOKUP WIDGET EVALUATION - */ - { - /** - * Goal: f = (w1(z) + q2.w1(zω)) + η(w2(z) + qm.w2(zω)) + η²(w3(z) + qc.w_3(zω)) + q3(z).η³ - * f = η.q3(z) - * f += (w3(z) + qc.w_3(zω)) - * f *= η - * f += (w2(z) + qm.w2(zω)) - * f *= η - * f += (w1(z) + q2.w1(zω)) - */ - let f := mulmod(mload(C_ETA_LOC), mload(Q3_EVAL_LOC), p) - f := - addmod(f, addmod(mload(W3_EVAL_LOC), mulmod(mload(QC_EVAL_LOC), mload(W3_OMEGA_EVAL_LOC), p), p), p) - f := mulmod(f, mload(C_ETA_LOC), p) - f := - addmod(f, addmod(mload(W2_EVAL_LOC), mulmod(mload(QM_EVAL_LOC), mload(W2_OMEGA_EVAL_LOC), p), p), p) - f := mulmod(f, mload(C_ETA_LOC), p) - f := - addmod(f, addmod(mload(W1_EVAL_LOC), mulmod(mload(Q2_EVAL_LOC), mload(W1_OMEGA_EVAL_LOC), p), p), p) - - // t(z) = table4(z).η³ + table3(z).η² + table2(z).η + table1(z) - let t := - addmod( - addmod( - addmod( - mulmod(mload(TABLE4_EVAL_LOC), mload(C_ETA_CUBE_LOC), p), - mulmod(mload(TABLE3_EVAL_LOC), mload(C_ETA_SQR_LOC), p), - p - ), - mulmod(mload(TABLE2_EVAL_LOC), mload(C_ETA_LOC), p), - p - ), - mload(TABLE1_EVAL_LOC), - p - ) - - // t(zw) = table4(zw).η³ + table3(zw).η² + table2(zw).η + table1(zw) - let t_omega := - addmod( - addmod( - addmod( - mulmod(mload(TABLE4_OMEGA_EVAL_LOC), mload(C_ETA_CUBE_LOC), p), - mulmod(mload(TABLE3_OMEGA_EVAL_LOC), mload(C_ETA_SQR_LOC), p), - p - ), - mulmod(mload(TABLE2_OMEGA_EVAL_LOC), mload(C_ETA_LOC), p), - p - ), - mload(TABLE1_OMEGA_EVAL_LOC), - p - ) - - /** - * Goal: numerator = (TABLE_TYPE_EVAL * f(z) + γ) * (t(z) + βt(zω) + γ(β + 1)) * (β + 1) - * gamma_beta_constant = γ(β + 1) - * numerator = f * TABLE_TYPE_EVAL + gamma - * temp0 = t(z) + t(zω) * β + gamma_beta_constant - * numerator *= temp0 - * numerator *= (β + 1) - * temp0 = alpha * l_1 - * numerator += temp0 - * numerator *= z_lookup(z) - * numerator -= temp0 - */ - let gamma_beta_constant := mulmod(mload(C_GAMMA_LOC), addmod(mload(C_BETA_LOC), 1, p), p) - let numerator := addmod(mulmod(f, mload(TABLE_TYPE_EVAL_LOC), p), mload(C_GAMMA_LOC), p) - let temp0 := addmod(addmod(t, mulmod(t_omega, mload(C_BETA_LOC), p), p), gamma_beta_constant, p) - numerator := mulmod(numerator, temp0, p) - numerator := mulmod(numerator, addmod(mload(C_BETA_LOC), 1, p), p) - temp0 := mulmod(mload(C_ALPHA_LOC), mload(L_START_LOC), p) - numerator := addmod(numerator, temp0, p) - numerator := mulmod(numerator, mload(Z_LOOKUP_EVAL_LOC), p) - numerator := addmod(numerator, sub(p, temp0), p) - - /** - * Goal: denominator = z_lookup(zω)*[s(z) + βs(zω) + γ(1 + β)] - [z_lookup(zω) - [γ(1 + β)]^{n-k}]*α²L_end(z) - * note: delta_factor = [γ(1 + β)]^{n-k} - * denominator = s(z) + βs(zω) + γ(β + 1) - * temp1 = α²L_end(z) - * denominator -= temp1 - * denominator *= z_lookup(zω) - * denominator += temp1 * delta_factor - * PLOOKUP_IDENTITY = (numerator - denominator).alpha_base - * alpha_base *= alpha^3 - */ - let denominator := - addmod( - addmod(mload(S_EVAL_LOC), mulmod(mload(S_OMEGA_EVAL_LOC), mload(C_BETA_LOC), p), p), - gamma_beta_constant, - p - ) - let temp1 := mulmod(mload(C_ALPHA_SQR_LOC), mload(L_END_LOC), p) - denominator := addmod(denominator, sub(p, temp1), p) - denominator := mulmod(denominator, mload(Z_LOOKUP_OMEGA_EVAL_LOC), p) - denominator := addmod(denominator, mulmod(temp1, mload(PLOOKUP_DELTA_LOC), p), p) - - mstore(PLOOKUP_IDENTITY, mulmod(addmod(numerator, sub(p, denominator), p), mload(C_ALPHA_BASE_LOC), p)) - - // update alpha - mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_CUBE_LOC), p)) - } - - /** - * COMPUTE ARITHMETIC WIDGET EVALUATION - */ - { - /** - * The basic arithmetic gate identity in standard plonk is as follows. - * (w_1 . w_2 . q_m) + (w_1 . q_1) + (w_2 . q_2) + (w_3 . q_3) + (w_4 . q_4) + q_c = 0 - * However, for Ultraplonk, we extend this to support "passing" wires between rows (shown without alpha scaling below): - * q_arith * ( ( (-1/2) * (q_arith - 3) * q_m * w_1 * w_2 + q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c ) + - * (q_arith - 1)*( α * (q_arith - 2) * (w_1 + w_4 - w_1_omega + q_m) + w_4_omega) ) = 0 - * - * This formula results in several cases depending on q_arith: - * 1. q_arith == 0: Arithmetic gate is completely disabled - * - * 2. q_arith == 1: Everything in the minigate on the right is disabled. The equation is just a standard plonk equation - * with extra wires: q_m * w_1 * w_2 + q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c = 0 - * - * 3. q_arith == 2: The (w_1 + w_4 - ...) term is disabled. THe equation is: - * (1/2) * q_m * w_1 * w_2 + q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c + w_4_omega = 0 - * It allows defining w_4 at next index (w_4_omega) in terms of current wire values - * - * 4. q_arith == 3: The product of w_1 and w_2 is disabled, but a mini addition gate is enabled. α allows us to split - * the equation into two: - * - * q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c + 2 * w_4_omega = 0 - * and - * w_1 + w_4 - w_1_omega + q_m = 0 (we are reusing q_m here) - * - * 5. q_arith > 3: The product of w_1 and w_2 is scaled by (q_arith - 3), while the w_4_omega term is scaled by (q_arith - 1). - * The equation can be split into two: - * - * (q_arith - 3)* q_m * w_1 * w_ 2 + q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c + (q_arith - 1) * w_4_omega = 0 - * and - * w_1 + w_4 - w_1_omega + q_m = 0 - * - * The problem that q_m is used both in both equations can be dealt with by appropriately changing selector values at - * the next gate. Then we can treat (q_arith - 1) as a simulated q_6 selector and scale q_m to handle (q_arith - 3) at - * product. - */ - - let w1q1 := mulmod(mload(W1_EVAL_LOC), mload(Q1_EVAL_LOC), p) - let w2q2 := mulmod(mload(W2_EVAL_LOC), mload(Q2_EVAL_LOC), p) - let w3q3 := mulmod(mload(W3_EVAL_LOC), mload(Q3_EVAL_LOC), p) - let w4q3 := mulmod(mload(W4_EVAL_LOC), mload(Q4_EVAL_LOC), p) - - // @todo - Add a explicit test that hits QARITH == 3 - // w1w2qm := (w_1 . w_2 . q_m . (QARITH_EVAL_LOC - 3)) / 2 - let w1w2qm := - mulmod( - mulmod( - mulmod(mulmod(mload(W1_EVAL_LOC), mload(W2_EVAL_LOC), p), mload(QM_EVAL_LOC), p), - addmod(mload(QARITH_EVAL_LOC), sub(p, 3), p), - p - ), - NEGATIVE_INVERSE_OF_2_MODULO_P, - p - ) - - // (w_1 . w_2 . q_m . (q_arith - 3)) / -2) + (w_1 . q_1) + (w_2 . q_2) + (w_3 . q_3) + (w_4 . q_4) + q_c - let identity := - addmod( - mload(QC_EVAL_LOC), addmod(w4q3, addmod(w3q3, addmod(w2q2, addmod(w1q1, w1w2qm, p), p), p), p), p - ) - - // if q_arith == 3 we evaluate an additional mini addition gate (on top of the regular one), where: - // w_1 + w_4 - w_1_omega + q_m = 0 - // we use this gate to save an addition gate when adding or subtracting non-native field elements - // α * (q_arith - 2) * (w_1 + w_4 - w_1_omega + q_m) - let extra_small_addition_gate_identity := - mulmod( - mload(C_ALPHA_LOC), - mulmod( - addmod(mload(QARITH_EVAL_LOC), sub(p, 2), p), - addmod( - mload(QM_EVAL_LOC), - addmod( - sub(p, mload(W1_OMEGA_EVAL_LOC)), addmod(mload(W1_EVAL_LOC), mload(W4_EVAL_LOC), p), p - ), - p - ), - p - ), - p - ) - - // if q_arith == 2 OR q_arith == 3 we add the 4th wire of the NEXT gate into the arithmetic identity - // N.B. if q_arith > 2, this wire value will be scaled by (q_arith - 1) relative to the other gate wires! - // alpha_base * q_arith * (identity + (q_arith - 1) * (w_4_omega + extra_small_addition_gate_identity)) - mstore( - ARITHMETIC_IDENTITY, - mulmod( - mload(C_ALPHA_BASE_LOC), - mulmod( - mload(QARITH_EVAL_LOC), - addmod( - identity, - mulmod( - addmod(mload(QARITH_EVAL_LOC), sub(p, 1), p), - addmod(mload(W4_OMEGA_EVAL_LOC), extra_small_addition_gate_identity, p), - p - ), - p - ), - p - ), - p - ) - ) - - // update alpha - mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_SQR_LOC), p)) - } - - /** - * COMPUTE GENPERMSORT WIDGET EVALUATION - */ - { - /** - * D1 = (w2 - w1) - * D2 = (w3 - w2) - * D3 = (w4 - w3) - * D4 = (w1_omega - w4) - * - * α_a = alpha_base - * α_b = alpha_base * α - * α_c = alpha_base * α^2 - * α_d = alpha_base * α^3 - * - * range_accumulator = ( - * D1(D1 - 1)(D1 - 2)(D1 - 3).α_a + - * D2(D2 - 1)(D2 - 2)(D2 - 3).α_b + - * D3(D3 - 1)(D3 - 2)(D3 - 3).α_c + - * D4(D4 - 1)(D4 - 2)(D4 - 3).α_d + - * ) . q_sort - */ - let minus_two := sub(p, 2) - let minus_three := sub(p, 3) - let d1 := addmod(mload(W2_EVAL_LOC), sub(p, mload(W1_EVAL_LOC)), p) - let d2 := addmod(mload(W3_EVAL_LOC), sub(p, mload(W2_EVAL_LOC)), p) - let d3 := addmod(mload(W4_EVAL_LOC), sub(p, mload(W3_EVAL_LOC)), p) - let d4 := addmod(mload(W1_OMEGA_EVAL_LOC), sub(p, mload(W4_EVAL_LOC)), p) - - let range_accumulator := - mulmod( - mulmod( - mulmod(addmod(mulmod(d1, d1, p), sub(p, d1), p), addmod(d1, minus_two, p), p), - addmod(d1, minus_three, p), - p - ), - mload(C_ALPHA_BASE_LOC), - p - ) - range_accumulator := - addmod( - range_accumulator, - mulmod( - mulmod( - mulmod(addmod(mulmod(d2, d2, p), sub(p, d2), p), addmod(d2, minus_two, p), p), - addmod(d2, minus_three, p), - p - ), - mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p), - p - ), - p - ) - range_accumulator := - addmod( - range_accumulator, - mulmod( - mulmod( - mulmod(addmod(mulmod(d3, d3, p), sub(p, d3), p), addmod(d3, minus_two, p), p), - addmod(d3, minus_three, p), - p - ), - mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_SQR_LOC), p), - p - ), - p - ) - range_accumulator := - addmod( - range_accumulator, - mulmod( - mulmod( - mulmod(addmod(mulmod(d4, d4, p), sub(p, d4), p), addmod(d4, minus_two, p), p), - addmod(d4, minus_three, p), - p - ), - mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_CUBE_LOC), p), - p - ), - p - ) - range_accumulator := mulmod(range_accumulator, mload(QSORT_EVAL_LOC), p) - - mstore(SORT_IDENTITY, range_accumulator) - - // update alpha - mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_QUAD_LOC), p)) - } - - /** - * COMPUTE ELLIPTIC WIDGET EVALUATION - */ - { - /** - * endo_term = (-x_2) * x_1 * (x_3 * 2 + x_1) * q_beta - * endo_sqr_term = x_2^2 - * endo_sqr_term *= (x_3 - x_1) - * endo_sqr_term *= q_beta^2 - * leftovers = x_2^2 - * leftovers *= x_2 - * leftovers += x_1^2 * (x_3 + x_1) @follow-up Invalid comment in BB widget - * leftovers -= (y_2^2 + y_1^2) - * sign_term = y_2 * y_1 - * sign_term += sign_term - * sign_term *= q_sign - */ - // q_elliptic * (x3 + x2 + x1)(x2 - x1)(x2 - x1) - y2^2 - y1^2 + 2(y2y1)*q_sign = 0 - let x_diff := addmod(mload(X2_EVAL_LOC), sub(p, mload(X1_EVAL_LOC)), p) - let y2_sqr := mulmod(mload(Y2_EVAL_LOC), mload(Y2_EVAL_LOC), p) - let y1_sqr := mulmod(mload(Y1_EVAL_LOC), mload(Y1_EVAL_LOC), p) - let y1y2 := mulmod(mulmod(mload(Y1_EVAL_LOC), mload(Y2_EVAL_LOC), p), mload(QSIGN_LOC), p) - - let x_add_identity := - addmod( - mulmod( - addmod(mload(X3_EVAL_LOC), addmod(mload(X2_EVAL_LOC), mload(X1_EVAL_LOC), p), p), - mulmod(x_diff, x_diff, p), - p - ), - addmod( - sub( - p, - addmod(y2_sqr, y1_sqr, p) - ), - addmod(y1y2, y1y2, p), - p - ), - p - ) - x_add_identity := - mulmod( - mulmod( - x_add_identity, - addmod( - 1, - sub(p, mload(QM_EVAL_LOC)), - p - ), - p - ), - mload(C_ALPHA_BASE_LOC), - p - ) - - // q_elliptic * (x3 + x2 + x1)(x2 - x1)(x2 - x1) - y2^2 - y1^2 + 2(y2y1)*q_sign = 0 - let y1_plus_y3 := addmod( - mload(Y1_EVAL_LOC), - mload(Y3_EVAL_LOC), - p - ) - let y_diff := addmod(mulmod(mload(Y2_EVAL_LOC), mload(QSIGN_LOC), p), sub(p, mload(Y1_EVAL_LOC)), p) - let y_add_identity := - addmod( - mulmod(y1_plus_y3, x_diff, p), - mulmod(addmod(mload(X3_EVAL_LOC), sub(p, mload(X1_EVAL_LOC)), p), y_diff, p), - p - ) - y_add_identity := - mulmod( - mulmod(y_add_identity, addmod(1, sub(p, mload(QM_EVAL_LOC)), p), p), - mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p), - p - ) - - // ELLIPTIC_IDENTITY = (x_identity + y_identity) * Q_ELLIPTIC_EVAL - mstore( - ELLIPTIC_IDENTITY, mulmod(addmod(x_add_identity, y_add_identity, p), mload(QELLIPTIC_EVAL_LOC), p) - ) - } - { - /** - * x_pow_4 = (y_1_sqr - curve_b) * x_1; - * y_1_sqr_mul_4 = y_1_sqr + y_1_sqr; - * y_1_sqr_mul_4 += y_1_sqr_mul_4; - * x_1_pow_4_mul_9 = x_pow_4; - * x_1_pow_4_mul_9 += x_1_pow_4_mul_9; - * x_1_pow_4_mul_9 += x_1_pow_4_mul_9; - * x_1_pow_4_mul_9 += x_1_pow_4_mul_9; - * x_1_pow_4_mul_9 += x_pow_4; - * x_1_sqr_mul_3 = x_1_sqr + x_1_sqr + x_1_sqr; - * x_double_identity = (x_3 + x_1 + x_1) * y_1_sqr_mul_4 - x_1_pow_4_mul_9; - * y_double_identity = x_1_sqr_mul_3 * (x_1 - x_3) - (y_1 + y_1) * (y_1 + y_3); - */ - // (x3 + x1 + x1) (4y1*y1) - 9 * x1 * x1 * x1 * x1 = 0 - let x1_sqr := mulmod(mload(X1_EVAL_LOC), mload(X1_EVAL_LOC), p) - let y1_sqr := mulmod(mload(Y1_EVAL_LOC), mload(Y1_EVAL_LOC), p) - let x_pow_4 := mulmod(addmod(y1_sqr, GRUMPKIN_CURVE_B_PARAMETER_NEGATED, p), mload(X1_EVAL_LOC), p) - let y1_sqr_mul_4 := mulmod(y1_sqr, 4, p) - let x1_pow_4_mul_9 := mulmod(x_pow_4, 9, p) - let x1_sqr_mul_3 := mulmod(x1_sqr, 3, p) - let x_double_identity := - addmod( - mulmod( - addmod(mload(X3_EVAL_LOC), addmod(mload(X1_EVAL_LOC), mload(X1_EVAL_LOC), p), p), - y1_sqr_mul_4, - p - ), - sub(p, x1_pow_4_mul_9), - p - ) - // (y1 + y1) (2y1) - (3 * x1 * x1)(x1 - x3) = 0 - let y_double_identity := - addmod( - mulmod(x1_sqr_mul_3, addmod(mload(X1_EVAL_LOC), sub(p, mload(X3_EVAL_LOC)), p), p), - sub( - p, - mulmod( - addmod(mload(Y1_EVAL_LOC), mload(Y1_EVAL_LOC), p), - addmod(mload(Y1_EVAL_LOC), mload(Y3_EVAL_LOC), p), - p - ) - ), - p - ) - x_double_identity := mulmod(x_double_identity, mload(C_ALPHA_BASE_LOC), p) - y_double_identity := - mulmod(y_double_identity, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p), p) - x_double_identity := mulmod(x_double_identity, mload(QM_EVAL_LOC), p) - y_double_identity := mulmod(y_double_identity, mload(QM_EVAL_LOC), p) - // ELLIPTIC_IDENTITY += (x_double_identity + y_double_identity) * Q_DOUBLE_EVAL - mstore( - ELLIPTIC_IDENTITY, - addmod( - mload(ELLIPTIC_IDENTITY), - mulmod(addmod(x_double_identity, y_double_identity, p), mload(QELLIPTIC_EVAL_LOC), p), - p - ) - ) - - // update alpha - mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_QUAD_LOC), p)) - } - - /** - * COMPUTE AUXILIARY WIDGET EVALUATION - */ - { - { - /** - * Non native field arithmetic gate 2 - * _ _ - * / _ _ _ 14 \ - * q_2 . q_4 | (w_1 . w_2) + (w_1 . w_2) + (w_1 . w_4 + w_2 . w_3 - w_3) . 2 - w_3 - w_4 | - * \_ _/ - * - * limb_subproduct = w_1 . w_2_omega + w_1_omega . w_2 - * non_native_field_gate_2 = w_1 * w_4 + w_4 * w_3 - w_3_omega - * non_native_field_gate_2 = non_native_field_gate_2 * limb_size - * non_native_field_gate_2 -= w_4_omega - * non_native_field_gate_2 += limb_subproduct - * non_native_field_gate_2 *= q_4 - * limb_subproduct *= limb_size - * limb_subproduct += w_1_omega * w_2_omega - * non_native_field_gate_1 = (limb_subproduct + w_3 + w_4) * q_3 - * non_native_field_gate_3 = (limb_subproduct + w_4 - (w_3_omega + w_4_omega)) * q_m - * non_native_field_identity = (non_native_field_gate_1 + non_native_field_gate_2 + non_native_field_gate_3) * q_2 - */ - - let limb_subproduct := - addmod( - mulmod(mload(W1_EVAL_LOC), mload(W2_OMEGA_EVAL_LOC), p), - mulmod(mload(W1_OMEGA_EVAL_LOC), mload(W2_EVAL_LOC), p), - p - ) - - let non_native_field_gate_2 := - addmod( - addmod( - mulmod(mload(W1_EVAL_LOC), mload(W4_EVAL_LOC), p), - mulmod(mload(W2_EVAL_LOC), mload(W3_EVAL_LOC), p), - p - ), - sub(p, mload(W3_OMEGA_EVAL_LOC)), - p - ) - non_native_field_gate_2 := mulmod(non_native_field_gate_2, LIMB_SIZE, p) - non_native_field_gate_2 := addmod(non_native_field_gate_2, sub(p, mload(W4_OMEGA_EVAL_LOC)), p) - non_native_field_gate_2 := addmod(non_native_field_gate_2, limb_subproduct, p) - non_native_field_gate_2 := mulmod(non_native_field_gate_2, mload(Q4_EVAL_LOC), p) - limb_subproduct := mulmod(limb_subproduct, LIMB_SIZE, p) - limb_subproduct := - addmod(limb_subproduct, mulmod(mload(W1_OMEGA_EVAL_LOC), mload(W2_OMEGA_EVAL_LOC), p), p) - let non_native_field_gate_1 := - mulmod( - addmod(limb_subproduct, sub(p, addmod(mload(W3_EVAL_LOC), mload(W4_EVAL_LOC), p)), p), - mload(Q3_EVAL_LOC), - p - ) - let non_native_field_gate_3 := - mulmod( - addmod( - addmod(limb_subproduct, mload(W4_EVAL_LOC), p), - sub(p, addmod(mload(W3_OMEGA_EVAL_LOC), mload(W4_OMEGA_EVAL_LOC), p)), - p - ), - mload(QM_EVAL_LOC), - p - ) - let non_native_field_identity := - mulmod( - addmod(addmod(non_native_field_gate_1, non_native_field_gate_2, p), non_native_field_gate_3, p), - mload(Q2_EVAL_LOC), - p - ) - - mstore(AUX_NON_NATIVE_FIELD_EVALUATION, non_native_field_identity) - } - - { - /** - * limb_accumulator_1 = w_2_omega; - * limb_accumulator_1 *= SUBLIMB_SHIFT; - * limb_accumulator_1 += w_1_omega; - * limb_accumulator_1 *= SUBLIMB_SHIFT; - * limb_accumulator_1 += w_3; - * limb_accumulator_1 *= SUBLIMB_SHIFT; - * limb_accumulator_1 += w_2; - * limb_accumulator_1 *= SUBLIMB_SHIFT; - * limb_accumulator_1 += w_1; - * limb_accumulator_1 -= w_4; - * limb_accumulator_1 *= q_4; - */ - let limb_accumulator_1 := mulmod(mload(W2_OMEGA_EVAL_LOC), SUBLIMB_SHIFT, p) - limb_accumulator_1 := addmod(limb_accumulator_1, mload(W1_OMEGA_EVAL_LOC), p) - limb_accumulator_1 := mulmod(limb_accumulator_1, SUBLIMB_SHIFT, p) - limb_accumulator_1 := addmod(limb_accumulator_1, mload(W3_EVAL_LOC), p) - limb_accumulator_1 := mulmod(limb_accumulator_1, SUBLIMB_SHIFT, p) - limb_accumulator_1 := addmod(limb_accumulator_1, mload(W2_EVAL_LOC), p) - limb_accumulator_1 := mulmod(limb_accumulator_1, SUBLIMB_SHIFT, p) - limb_accumulator_1 := addmod(limb_accumulator_1, mload(W1_EVAL_LOC), p) - limb_accumulator_1 := addmod(limb_accumulator_1, sub(p, mload(W4_EVAL_LOC)), p) - limb_accumulator_1 := mulmod(limb_accumulator_1, mload(Q4_EVAL_LOC), p) - - /** - * limb_accumulator_2 = w_3_omega; - * limb_accumulator_2 *= SUBLIMB_SHIFT; - * limb_accumulator_2 += w_2_omega; - * limb_accumulator_2 *= SUBLIMB_SHIFT; - * limb_accumulator_2 += w_1_omega; - * limb_accumulator_2 *= SUBLIMB_SHIFT; - * limb_accumulator_2 += w_4; - * limb_accumulator_2 *= SUBLIMB_SHIFT; - * limb_accumulator_2 += w_3; - * limb_accumulator_2 -= w_4_omega; - * limb_accumulator_2 *= q_m; - */ - let limb_accumulator_2 := mulmod(mload(W3_OMEGA_EVAL_LOC), SUBLIMB_SHIFT, p) - limb_accumulator_2 := addmod(limb_accumulator_2, mload(W2_OMEGA_EVAL_LOC), p) - limb_accumulator_2 := mulmod(limb_accumulator_2, SUBLIMB_SHIFT, p) - limb_accumulator_2 := addmod(limb_accumulator_2, mload(W1_OMEGA_EVAL_LOC), p) - limb_accumulator_2 := mulmod(limb_accumulator_2, SUBLIMB_SHIFT, p) - limb_accumulator_2 := addmod(limb_accumulator_2, mload(W4_EVAL_LOC), p) - limb_accumulator_2 := mulmod(limb_accumulator_2, SUBLIMB_SHIFT, p) - limb_accumulator_2 := addmod(limb_accumulator_2, mload(W3_EVAL_LOC), p) - limb_accumulator_2 := addmod(limb_accumulator_2, sub(p, mload(W4_OMEGA_EVAL_LOC)), p) - limb_accumulator_2 := mulmod(limb_accumulator_2, mload(QM_EVAL_LOC), p) - - mstore( - AUX_LIMB_ACCUMULATOR_EVALUATION, - mulmod(addmod(limb_accumulator_1, limb_accumulator_2, p), mload(Q3_EVAL_LOC), p) - ) - } - - { - /** - * memory_record_check = w_3; - * memory_record_check *= eta; - * memory_record_check += w_2; - * memory_record_check *= eta; - * memory_record_check += w_1; - * memory_record_check *= eta; - * memory_record_check += q_c; - * - * partial_record_check = memory_record_check; - * - * memory_record_check -= w_4; - */ - - let memory_record_check := mulmod(mload(W3_EVAL_LOC), mload(C_ETA_LOC), p) - memory_record_check := addmod(memory_record_check, mload(W2_EVAL_LOC), p) - memory_record_check := mulmod(memory_record_check, mload(C_ETA_LOC), p) - memory_record_check := addmod(memory_record_check, mload(W1_EVAL_LOC), p) - memory_record_check := mulmod(memory_record_check, mload(C_ETA_LOC), p) - memory_record_check := addmod(memory_record_check, mload(QC_EVAL_LOC), p) - - let partial_record_check := memory_record_check - memory_record_check := addmod(memory_record_check, sub(p, mload(W4_EVAL_LOC)), p) - - mstore(AUX_MEMORY_EVALUATION, memory_record_check) - - // index_delta = w_1_omega - w_1 - let index_delta := addmod(mload(W1_OMEGA_EVAL_LOC), sub(p, mload(W1_EVAL_LOC)), p) - // record_delta = w_4_omega - w_4 - let record_delta := addmod(mload(W4_OMEGA_EVAL_LOC), sub(p, mload(W4_EVAL_LOC)), p) - // index_is_monotonically_increasing = index_delta * (index_delta - 1) - let index_is_monotonically_increasing := mulmod(index_delta, addmod(index_delta, sub(p, 1), p), p) - - // adjacent_values_match_if_adjacent_indices_match = record_delta * (1 - index_delta) - let adjacent_values_match_if_adjacent_indices_match := - mulmod(record_delta, addmod(1, sub(p, index_delta), p), p) - - // AUX_ROM_CONSISTENCY_EVALUATION = ((adjacent_values_match_if_adjacent_indices_match * alpha) + index_is_monotonically_increasing) * alpha + partial_record_check - mstore( - AUX_ROM_CONSISTENCY_EVALUATION, - addmod( - mulmod( - addmod( - mulmod(adjacent_values_match_if_adjacent_indices_match, mload(C_ALPHA_LOC), p), - index_is_monotonically_increasing, - p - ), - mload(C_ALPHA_LOC), - p - ), - memory_record_check, - p - ) - ) - - { - /** - * next_gate_access_type = w_3_omega; - * next_gate_access_type *= eta; - * next_gate_access_type += w_2_omega; - * next_gate_access_type *= eta; - * next_gate_access_type += w_1_omega; - * next_gate_access_type *= eta; - * next_gate_access_type = w_4_omega - next_gate_access_type; - */ - let next_gate_access_type := mulmod(mload(W3_OMEGA_EVAL_LOC), mload(C_ETA_LOC), p) - next_gate_access_type := addmod(next_gate_access_type, mload(W2_OMEGA_EVAL_LOC), p) - next_gate_access_type := mulmod(next_gate_access_type, mload(C_ETA_LOC), p) - next_gate_access_type := addmod(next_gate_access_type, mload(W1_OMEGA_EVAL_LOC), p) - next_gate_access_type := mulmod(next_gate_access_type, mload(C_ETA_LOC), p) - next_gate_access_type := addmod(mload(W4_OMEGA_EVAL_LOC), sub(p, next_gate_access_type), p) - - // value_delta = w_3_omega - w_3 - let value_delta := addmod(mload(W3_OMEGA_EVAL_LOC), sub(p, mload(W3_EVAL_LOC)), p) - // adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation = (1 - index_delta) * value_delta * (1 - next_gate_access_type); - - let adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation := - mulmod( - addmod(1, sub(p, index_delta), p), - mulmod(value_delta, addmod(1, sub(p, next_gate_access_type), p), p), - p - ) - - // AUX_RAM_CONSISTENCY_EVALUATION - - /** - * access_type = w_4 - partial_record_check - * access_check = access_type^2 - access_type - * next_gate_access_type_is_boolean = next_gate_access_type^2 - next_gate_access_type - * RAM_consistency_check_identity = adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation; - * RAM_consistency_check_identity *= alpha; - * RAM_consistency_check_identity += index_is_monotonically_increasing; - * RAM_consistency_check_identity *= alpha; - * RAM_consistency_check_identity += next_gate_access_type_is_boolean; - * RAM_consistency_check_identity *= alpha; - * RAM_consistency_check_identity += access_check; - */ - - let access_type := addmod(mload(W4_EVAL_LOC), sub(p, partial_record_check), p) - let access_check := mulmod(access_type, addmod(access_type, sub(p, 1), p), p) - let next_gate_access_type_is_boolean := - mulmod(next_gate_access_type, addmod(next_gate_access_type, sub(p, 1), p), p) - let RAM_cci := - mulmod( - adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation, - mload(C_ALPHA_LOC), - p - ) - RAM_cci := addmod(RAM_cci, index_is_monotonically_increasing, p) - RAM_cci := mulmod(RAM_cci, mload(C_ALPHA_LOC), p) - RAM_cci := addmod(RAM_cci, next_gate_access_type_is_boolean, p) - RAM_cci := mulmod(RAM_cci, mload(C_ALPHA_LOC), p) - RAM_cci := addmod(RAM_cci, access_check, p) - - mstore(AUX_RAM_CONSISTENCY_EVALUATION, RAM_cci) - } - - { - // timestamp_delta = w_2_omega - w_2 - let timestamp_delta := addmod(mload(W2_OMEGA_EVAL_LOC), sub(p, mload(W2_EVAL_LOC)), p) - - // RAM_timestamp_check_identity = (1 - index_delta) * timestamp_delta - w_3 - let RAM_timestamp_check_identity := - addmod( - mulmod(timestamp_delta, addmod(1, sub(p, index_delta), p), p), sub(p, mload(W3_EVAL_LOC)), p - ) - - /** - * memory_identity = ROM_consistency_check_identity * q_2; - * memory_identity += RAM_timestamp_check_identity * q_4; - * memory_identity += memory_record_check * q_m; - * memory_identity *= q_1; - * memory_identity += (RAM_consistency_check_identity * q_arith); - * - * auxiliary_identity = memory_identity + non_native_field_identity + limb_accumulator_identity; - * auxiliary_identity *= q_aux; - * auxiliary_identity *= alpha_base; - */ - let memory_identity := mulmod(mload(AUX_ROM_CONSISTENCY_EVALUATION), mload(Q2_EVAL_LOC), p) - memory_identity := - addmod(memory_identity, mulmod(RAM_timestamp_check_identity, mload(Q4_EVAL_LOC), p), p) - memory_identity := - addmod(memory_identity, mulmod(mload(AUX_MEMORY_EVALUATION), mload(QM_EVAL_LOC), p), p) - memory_identity := mulmod(memory_identity, mload(Q1_EVAL_LOC), p) - memory_identity := - addmod( - memory_identity, mulmod(mload(AUX_RAM_CONSISTENCY_EVALUATION), mload(QARITH_EVAL_LOC), p), p - ) - - let auxiliary_identity := addmod(memory_identity, mload(AUX_NON_NATIVE_FIELD_EVALUATION), p) - auxiliary_identity := addmod(auxiliary_identity, mload(AUX_LIMB_ACCUMULATOR_EVALUATION), p) - auxiliary_identity := mulmod(auxiliary_identity, mload(QAUX_EVAL_LOC), p) - auxiliary_identity := mulmod(auxiliary_identity, mload(C_ALPHA_BASE_LOC), p) - - mstore(AUX_IDENTITY, auxiliary_identity) - - // update alpha - mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_CUBE_LOC), p)) - } - } - } - - { - /** - * quotient = ARITHMETIC_IDENTITY - * quotient += PERMUTATION_IDENTITY - * quotient += PLOOKUP_IDENTITY - * quotient += SORT_IDENTITY - * quotient += ELLIPTIC_IDENTITY - * quotient += AUX_IDENTITY - * quotient *= ZERO_POLY_INVERSE - */ - mstore( - QUOTIENT_EVAL_LOC, - mulmod( - addmod( - addmod( - addmod( - addmod( - addmod(mload(PERMUTATION_IDENTITY), mload(PLOOKUP_IDENTITY), p), - mload(ARITHMETIC_IDENTITY), - p - ), - mload(SORT_IDENTITY), - p - ), - mload(ELLIPTIC_IDENTITY), - p - ), - mload(AUX_IDENTITY), - p - ), - mload(ZERO_POLY_INVERSE_LOC), - p - ) - ) - } - - /** - * GENERATE NU AND SEPARATOR CHALLENGES - */ - { - let current_challenge := mload(C_CURRENT_LOC) - // get a calldata pointer that points to the start of the data we want to copy - let calldata_ptr := add(calldataload(0x04), 0x24) - - calldata_ptr := add(calldata_ptr, NU_CALLDATA_SKIP_LENGTH) - - mstore(NU_CHALLENGE_INPUT_LOC_A, current_challenge) - mstore(NU_CHALLENGE_INPUT_LOC_B, mload(QUOTIENT_EVAL_LOC)) - calldatacopy(NU_CHALLENGE_INPUT_LOC_C, calldata_ptr, NU_INPUT_LENGTH) - - // hash length = (0x20 + num field elements), we include the previous challenge in the hash - let challenge := keccak256(NU_CHALLENGE_INPUT_LOC_A, add(NU_INPUT_LENGTH, 0x40)) - - mstore(C_V0_LOC, mod(challenge, p)) - // We need THIRTY-ONE independent nu challenges! - mstore(0x00, challenge) - mstore8(0x20, 0x01) - mstore(C_V1_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x02) - mstore(C_V2_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x03) - mstore(C_V3_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x04) - mstore(C_V4_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x05) - mstore(C_V5_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x06) - mstore(C_V6_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x07) - mstore(C_V7_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x08) - mstore(C_V8_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x09) - mstore(C_V9_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x0a) - mstore(C_V10_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x0b) - mstore(C_V11_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x0c) - mstore(C_V12_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x0d) - mstore(C_V13_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x0e) - mstore(C_V14_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x0f) - mstore(C_V15_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x10) - mstore(C_V16_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x11) - mstore(C_V17_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x12) - mstore(C_V18_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x13) - mstore(C_V19_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x14) - mstore(C_V20_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x15) - mstore(C_V21_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x16) - mstore(C_V22_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x17) - mstore(C_V23_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x18) - mstore(C_V24_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x19) - mstore(C_V25_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x1a) - mstore(C_V26_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x1b) - mstore(C_V27_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x1c) - mstore(C_V28_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x1d) - mstore(C_V29_LOC, mod(keccak256(0x00, 0x21), p)) - - // @follow-up - Why are both v29 and v30 using appending 0x1d to the prior challenge and hashing, should it not change? - mstore8(0x20, 0x1d) - challenge := keccak256(0x00, 0x21) - mstore(C_V30_LOC, mod(challenge, p)) - - // separator - mstore(0x00, challenge) - mstore(0x20, mload(PI_Z_Y_LOC)) - mstore(0x40, mload(PI_Z_X_LOC)) - mstore(0x60, mload(PI_Z_OMEGA_Y_LOC)) - mstore(0x80, mload(PI_Z_OMEGA_X_LOC)) - - mstore(C_U_LOC, mod(keccak256(0x00, 0xa0), p)) - } - - let success := 0 - // VALIDATE T1 - { - let x := mload(T1_X_LOC) - let y := mload(T1_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(ACCUMULATOR_X_LOC, x) - mstore(add(ACCUMULATOR_X_LOC, 0x20), y) - } - // VALIDATE T2 - { - let x := mload(T2_X_LOC) // 0x1400 - let y := mload(T2_Y_LOC) // 0x1420 - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(ZETA_POW_N_LOC)) - // accumulator_2 = [T2].zeta^n - success := staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40) - // accumulator = [T1] + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE T3 - { - let x := mload(T3_X_LOC) - let y := mload(T3_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(mload(ZETA_POW_N_LOC), mload(ZETA_POW_N_LOC), p)) - // accumulator_2 = [T3].zeta^{2n} - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE T4 - { - let x := mload(T4_X_LOC) - let y := mload(T4_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(mulmod(mload(ZETA_POW_N_LOC), mload(ZETA_POW_N_LOC), p), mload(ZETA_POW_N_LOC), p)) - // accumulator_2 = [T4].zeta^{3n} - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE W1 - { - let x := mload(W1_X_LOC) - let y := mload(W1_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V0_LOC), p)) - // accumulator_2 = v0.(u + 1).[W1] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE W2 - { - let x := mload(W2_X_LOC) - let y := mload(W2_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V1_LOC), p)) - // accumulator_2 = v1.(u + 1).[W2] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE W3 - { - let x := mload(W3_X_LOC) - let y := mload(W3_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V2_LOC), p)) - // accumulator_2 = v2.(u + 1).[W3] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE W4 - { - let x := mload(W4_X_LOC) - let y := mload(W4_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V3_LOC), p)) - // accumulator_2 = v3.(u + 1).[W4] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE S - { - let x := mload(S_X_LOC) - let y := mload(S_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V4_LOC), p)) - // accumulator_2 = v4.(u + 1).[S] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE Z - { - let x := mload(Z_X_LOC) - let y := mload(Z_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V5_LOC), p)) - // accumulator_2 = v5.(u + 1).[Z] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE Z_LOOKUP - { - let x := mload(Z_LOOKUP_X_LOC) - let y := mload(Z_LOOKUP_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V6_LOC), p)) - // accumulator_2 = v6.(u + 1).[Z_LOOKUP] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE Q1 - { - let x := mload(Q1_X_LOC) - let y := mload(Q1_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V7_LOC)) - // accumulator_2 = v7.[Q1] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE Q2 - { - let x := mload(Q2_X_LOC) - let y := mload(Q2_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V8_LOC)) - // accumulator_2 = v8.[Q2] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE Q3 - { - let x := mload(Q3_X_LOC) - let y := mload(Q3_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V9_LOC)) - // accumulator_2 = v9.[Q3] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE Q4 - { - let x := mload(Q4_X_LOC) - let y := mload(Q4_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V10_LOC)) - // accumulator_2 = v10.[Q4] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE QM - { - let x := mload(QM_X_LOC) - let y := mload(QM_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V11_LOC)) - // accumulator_2 = v11.[Q;] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE QC - { - let x := mload(QC_X_LOC) - let y := mload(QC_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V12_LOC)) - // accumulator_2 = v12.[QC] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE QARITH - { - let x := mload(QARITH_X_LOC) - let y := mload(QARITH_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V13_LOC)) - // accumulator_2 = v13.[QARITH] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE QSORT - { - let x := mload(QSORT_X_LOC) - let y := mload(QSORT_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V14_LOC)) - // accumulator_2 = v14.[QSORT] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE QELLIPTIC - { - let x := mload(QELLIPTIC_X_LOC) - let y := mload(QELLIPTIC_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V15_LOC)) - // accumulator_2 = v15.[QELLIPTIC] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE QAUX - { - let x := mload(QAUX_X_LOC) - let y := mload(QAUX_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V16_LOC)) - // accumulator_2 = v15.[Q_AUX] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE SIGMA1 - { - let x := mload(SIGMA1_X_LOC) - let y := mload(SIGMA1_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V17_LOC)) - // accumulator_2 = v17.[sigma1] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE SIGMA2 - { - let x := mload(SIGMA2_X_LOC) - let y := mload(SIGMA2_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V18_LOC)) - // accumulator_2 = v18.[sigma2] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE SIGMA3 - { - let x := mload(SIGMA3_X_LOC) - let y := mload(SIGMA3_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V19_LOC)) - // accumulator_2 = v19.[sigma3] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE SIGMA4 - { - let x := mload(SIGMA4_X_LOC) - let y := mload(SIGMA4_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V20_LOC)) - // accumulator_2 = v20.[sigma4] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE TABLE1 - { - let x := mload(TABLE1_X_LOC) - let y := mload(TABLE1_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V21_LOC), p)) - // accumulator_2 = u.[table1] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE TABLE2 - { - let x := mload(TABLE2_X_LOC) - let y := mload(TABLE2_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V22_LOC), p)) - // accumulator_2 = u.[table2] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE TABLE3 - { - let x := mload(TABLE3_X_LOC) - let y := mload(TABLE3_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V23_LOC), p)) - // accumulator_2 = u.[table3] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE TABLE4 - { - let x := mload(TABLE4_X_LOC) - let y := mload(TABLE4_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V24_LOC), p)) - // accumulator_2 = u.[table4] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE TABLE_TYPE - { - let x := mload(TABLE_TYPE_X_LOC) - let y := mload(TABLE_TYPE_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V25_LOC)) - // accumulator_2 = v25.[TableType] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE ID1 - { - let x := mload(ID1_X_LOC) - let y := mload(ID1_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V26_LOC)) - // accumulator_2 = v26.[ID1] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE ID2 - { - let x := mload(ID2_X_LOC) - let y := mload(ID2_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V27_LOC)) - // accumulator_2 = v27.[ID2] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE ID3 - { - let x := mload(ID3_X_LOC) - let y := mload(ID3_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V28_LOC)) - // accumulator_2 = v28.[ID3] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE ID4 - { - let x := mload(ID4_X_LOC) - let y := mload(ID4_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V29_LOC)) - // accumulator_2 = v29.[ID4] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - /** - * COMPUTE BATCH EVALUATION SCALAR MULTIPLIER - */ - { - /** - * batch_evaluation = v0 * (w_1_omega * u + w_1_eval) - * batch_evaluation += v1 * (w_2_omega * u + w_2_eval) - * batch_evaluation += v2 * (w_3_omega * u + w_3_eval) - * batch_evaluation += v3 * (w_4_omega * u + w_4_eval) - * batch_evaluation += v4 * (s_omega_eval * u + s_eval) - * batch_evaluation += v5 * (z_omega_eval * u + z_eval) - * batch_evaluation += v6 * (z_lookup_omega_eval * u + z_lookup_eval) - */ - let batch_evaluation := - mulmod( - mload(C_V0_LOC), - addmod(mulmod(mload(W1_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W1_EVAL_LOC), p), - p - ) - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V1_LOC), - addmod(mulmod(mload(W2_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W2_EVAL_LOC), p), - p - ), - p - ) - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V2_LOC), - addmod(mulmod(mload(W3_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W3_EVAL_LOC), p), - p - ), - p - ) - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V3_LOC), - addmod(mulmod(mload(W4_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W4_EVAL_LOC), p), - p - ), - p - ) - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V4_LOC), - addmod(mulmod(mload(S_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(S_EVAL_LOC), p), - p - ), - p - ) - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V5_LOC), - addmod(mulmod(mload(Z_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(Z_EVAL_LOC), p), - p - ), - p - ) - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V6_LOC), - addmod(mulmod(mload(Z_LOOKUP_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(Z_LOOKUP_EVAL_LOC), p), - p - ), - p - ) - - /** - * batch_evaluation += v7 * Q1_EVAL - * batch_evaluation += v8 * Q2_EVAL - * batch_evaluation += v9 * Q3_EVAL - * batch_evaluation += v10 * Q4_EVAL - * batch_evaluation += v11 * QM_EVAL - * batch_evaluation += v12 * QC_EVAL - * batch_evaluation += v13 * QARITH_EVAL - * batch_evaluation += v14 * QSORT_EVAL_LOC - * batch_evaluation += v15 * QELLIPTIC_EVAL_LOC - * batch_evaluation += v16 * QAUX_EVAL_LOC - * batch_evaluation += v17 * SIGMA1_EVAL_LOC - * batch_evaluation += v18 * SIGMA2_EVAL_LOC - * batch_evaluation += v19 * SIGMA3_EVAL_LOC - * batch_evaluation += v20 * SIGMA4_EVAL_LOC - */ - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V7_LOC), mload(Q1_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V8_LOC), mload(Q2_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V9_LOC), mload(Q3_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V10_LOC), mload(Q4_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V11_LOC), mload(QM_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V12_LOC), mload(QC_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V13_LOC), mload(QARITH_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V14_LOC), mload(QSORT_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V15_LOC), mload(QELLIPTIC_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V16_LOC), mload(QAUX_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V17_LOC), mload(SIGMA1_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V18_LOC), mload(SIGMA2_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V19_LOC), mload(SIGMA3_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V20_LOC), mload(SIGMA4_EVAL_LOC), p), p) - - /** - * batch_evaluation += v21 * (table1(zw) * u + table1(z)) - * batch_evaluation += v22 * (table2(zw) * u + table2(z)) - * batch_evaluation += v23 * (table3(zw) * u + table3(z)) - * batch_evaluation += v24 * (table4(zw) * u + table4(z)) - * batch_evaluation += v25 * table_type_eval - * batch_evaluation += v26 * id1_eval - * batch_evaluation += v27 * id2_eval - * batch_evaluation += v28 * id3_eval - * batch_evaluation += v29 * id4_eval - * batch_evaluation += quotient_eval - */ - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V21_LOC), - addmod(mulmod(mload(TABLE1_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE1_EVAL_LOC), p), - p - ), - p - ) - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V22_LOC), - addmod(mulmod(mload(TABLE2_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE2_EVAL_LOC), p), - p - ), - p - ) - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V23_LOC), - addmod(mulmod(mload(TABLE3_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE3_EVAL_LOC), p), - p - ), - p - ) - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V24_LOC), - addmod(mulmod(mload(TABLE4_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE4_EVAL_LOC), p), - p - ), - p - ) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V25_LOC), mload(TABLE_TYPE_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V26_LOC), mload(ID1_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V27_LOC), mload(ID2_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V28_LOC), mload(ID3_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V29_LOC), mload(ID4_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mload(QUOTIENT_EVAL_LOC), p) - - mstore(0x00, 0x01) // [1].x - mstore(0x20, 0x02) // [1].y - mstore(0x40, sub(p, batch_evaluation)) - // accumulator_2 = -[1].(batch_evaluation) - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - if iszero(success) { - mstore(0x0, OPENING_COMMITMENT_FAILED_SELECTOR) - revert(0x00, 0x04) - } - } - - /** - * PERFORM PAIRING PREAMBLE - */ - { - let u := mload(C_U_LOC) - let zeta := mload(C_ZETA_LOC) - // VALIDATE PI_Z - { - let x := mload(PI_Z_X_LOC) - let y := mload(PI_Z_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - // compute zeta.[PI_Z] and add into accumulator - mstore(0x40, zeta) - success := staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE PI_Z_OMEGA - { - let x := mload(PI_Z_OMEGA_X_LOC) - let y := mload(PI_Z_OMEGA_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(mulmod(u, zeta, p), mload(OMEGA_LOC), p)) - // accumulator_2 = u.zeta.omega.[PI_Z_OMEGA] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // PAIRING_RHS = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, PAIRING_RHS_X_LOC, 0x40)) - - mstore(0x00, mload(PI_Z_X_LOC)) - mstore(0x20, mload(PI_Z_Y_LOC)) - mstore(0x40, mload(PI_Z_OMEGA_X_LOC)) - mstore(0x60, mload(PI_Z_OMEGA_Y_LOC)) - mstore(0x80, u) - success := and(success, staticcall(gas(), 7, 0x40, 0x60, 0x40, 0x40)) - // PAIRING_LHS = [PI_Z] + [PI_Z_OMEGA] * u - success := and(success, staticcall(gas(), 6, 0x00, 0x80, PAIRING_LHS_X_LOC, 0x40)) - // negate lhs y-coordinate - mstore(PAIRING_LHS_Y_LOC, sub(q, mload(PAIRING_LHS_Y_LOC))) - - if mload(CONTAINS_RECURSIVE_PROOF_LOC) { - // VALIDATE RECURSIVE P1 - { - let x := mload(RECURSIVE_P1_X_LOC) - let y := mload(RECURSIVE_P1_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - - // compute u.u.[recursive_p1] and write into 0x60 - mstore(0x40, mulmod(u, u, p)) - success := and(success, staticcall(gas(), 7, 0x00, 0x60, 0x60, 0x40)) - // VALIDATE RECURSIVE P2 - { - let x := mload(RECURSIVE_P2_X_LOC) - let y := mload(RECURSIVE_P2_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - // compute u.u.[recursive_p2] and write into 0x00 - // 0x40 still contains u*u - success := and(success, staticcall(gas(), 7, 0x00, 0x60, 0x00, 0x40)) - - // compute u.u.[recursiveP1] + rhs and write into rhs - mstore(0xa0, mload(PAIRING_RHS_X_LOC)) - mstore(0xc0, mload(PAIRING_RHS_Y_LOC)) - success := and(success, staticcall(gas(), 6, 0x60, 0x80, PAIRING_RHS_X_LOC, 0x40)) - - // compute u.u.[recursiveP2] + lhs and write into lhs - mstore(0x40, mload(PAIRING_LHS_X_LOC)) - mstore(0x60, mload(PAIRING_LHS_Y_LOC)) - success := and(success, staticcall(gas(), 6, 0x00, 0x80, PAIRING_LHS_X_LOC, 0x40)) - } - - if iszero(success) { - mstore(0x0, PAIRING_PREAMBLE_FAILED_SELECTOR) - revert(0x00, 0x04) - } - } - - /** - * PERFORM PAIRING - */ - { - // rhs paired with [1]_2 - // lhs paired with [x]_2 - - mstore(0x00, mload(PAIRING_RHS_X_LOC)) - mstore(0x20, mload(PAIRING_RHS_Y_LOC)) - mstore(0x40, 0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2) // this is [1]_2 - mstore(0x60, 0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed) - mstore(0x80, 0x090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b) - mstore(0xa0, 0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa) - - mstore(0xc0, mload(PAIRING_LHS_X_LOC)) - mstore(0xe0, mload(PAIRING_LHS_Y_LOC)) - mstore(0x100, mload(G2X_X0_LOC)) - mstore(0x120, mload(G2X_X1_LOC)) - mstore(0x140, mload(G2X_Y0_LOC)) - mstore(0x160, mload(G2X_Y1_LOC)) - - success := staticcall(gas(), 8, 0x00, 0x180, 0x00, 0x20) - if iszero(and(success, mload(0x00))) { - mstore(0x0, PAIRING_FAILED_SELECTOR) - revert(0x00, 0x04) - } - } - - { - mstore(0x00, 0x01) - return(0x00, 0x20) // Proof succeeded! - } - } - } -} - -contract UltraVerifier is BaseUltraVerifier { - function getVerificationKeyHash() public pure override(BaseUltraVerifier) returns (bytes32) { - return UltraVerificationKey.verificationKeyHash(); - } - - function loadVerificationKey(uint256 vk, uint256 _omegaInverseLoc) internal pure virtual override(BaseUltraVerifier) { - UltraVerificationKey.loadVerificationKey(vk, _omegaInverseLoc); - } -} diff --git a/noir/noir-repo/compiler/integration-tests/package.json b/noir/noir-repo/compiler/integration-tests/package.json index 511df534110f..798b7c553123 100644 --- a/noir/noir-repo/compiler/integration-tests/package.json +++ b/noir/noir-repo/compiler/integration-tests/package.json @@ -6,7 +6,7 @@ "scripts": { "build": "echo Integration Test build step", "test": "yarn test:browser && yarn test:node", - "test:node": "hardhat test test/node/**/*", + "test:node": "bash ./scripts/codegen-verifiers.sh && hardhat test test/node/**/*", "test:browser": "web-test-runner", "test:integration:browser": "web-test-runner test/browser/**/*.test.ts", "test:integration:browser:watch": "web-test-runner test/browser/**/*.test.ts --watch", diff --git a/noir/noir-repo/compiler/noirc_driver/src/contract.rs b/noir/noir-repo/compiler/noirc_driver/src/contract.rs index 9a0e25a321bf..66e8dc0e7309 100644 --- a/noir/noir-repo/compiler/noirc_driver/src/contract.rs +++ b/noir/noir-repo/compiler/noirc_driver/src/contract.rs @@ -1,7 +1,7 @@ use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; -use acvm::acir::circuit::Program; +use acvm::acir::circuit::Circuit; use fm::FileId; use noirc_abi::{Abi, ContractEvent}; use noirc_errors::debug_info::DebugInfo; @@ -45,10 +45,10 @@ pub struct ContractFunction { pub abi: Abi, #[serde( - serialize_with = "Program::serialize_program_base64", - deserialize_with = "Program::deserialize_program_base64" + serialize_with = "Circuit::serialize_circuit_base64", + deserialize_with = "Circuit::deserialize_circuit_base64" )] - pub bytecode: Program, + pub bytecode: Circuit, pub debug: DebugInfo, } diff --git a/noir/noir-repo/compiler/noirc_driver/src/lib.rs b/noir/noir-repo/compiler/noirc_driver/src/lib.rs index fe4ecf14b70e..346eb5953894 100644 --- a/noir/noir-repo/compiler/noirc_driver/src/lib.rs +++ b/noir/noir-repo/compiler/noirc_driver/src/lib.rs @@ -3,7 +3,7 @@ #![warn(unreachable_pub)] #![warn(clippy::semicolon_if_nothing_returned)] -use acvm::acir::circuit::{ExpressionWidth, Program}; +use acvm::acir::circuit::ExpressionWidth; use clap::Args; use fm::{FileId, FileManager}; use iter_extended::vecmap; @@ -304,7 +304,7 @@ pub fn compile_main( if options.print_acir { println!("Compiled ACIR for main (unoptimized):"); - println!("{}", compiled_program.program); + println!("{}", compiled_program.circuit); } Ok((compiled_program, warnings)) @@ -420,7 +420,7 @@ fn compile_contract_inner( name, custom_attributes, abi: function.abi, - bytecode: function.program, + bytecode: function.circuit, debug: function.debug, is_unconstrained: modifiers.is_unconstrained, }); @@ -493,8 +493,7 @@ pub fn compile_no_check( Ok(CompiledProgram { hash, - // TODO(https://github.com/noir-lang/noir/issues/4428) - program: Program { functions: vec![circuit] }, + circuit, debug, abi, file_map, diff --git a/noir/noir-repo/compiler/noirc_driver/src/program.rs b/noir/noir-repo/compiler/noirc_driver/src/program.rs index 6f527297dcb4..8d509d3bf68e 100644 --- a/noir/noir-repo/compiler/noirc_driver/src/program.rs +++ b/noir/noir-repo/compiler/noirc_driver/src/program.rs @@ -1,6 +1,6 @@ use std::collections::BTreeMap; -use acvm::acir::circuit::Program; +use acvm::acir::circuit::Circuit; use fm::FileId; use noirc_errors::debug_info::DebugInfo; @@ -19,10 +19,10 @@ pub struct CompiledProgram { pub hash: u64, #[serde( - serialize_with = "Program::serialize_program_base64", - deserialize_with = "Program::deserialize_program_base64" + serialize_with = "Circuit::serialize_circuit_base64", + deserialize_with = "Circuit::deserialize_circuit_base64" )] - pub program: Program, + pub circuit: Circuit, pub abi: noirc_abi::Abi, pub debug: DebugInfo, pub file_map: BTreeMap, diff --git a/noir/noir-repo/test_programs/execution_success/recursion/Nargo.toml b/noir/noir-repo/test_programs/execution_success/recursion/Nargo.toml deleted file mode 100644 index fe1ba8b1ce62..000000000000 --- a/noir/noir-repo/test_programs/execution_success/recursion/Nargo.toml +++ /dev/null @@ -1,7 +0,0 @@ -[package] -name = "recursion" -type = "bin" -authors = [""] -compiler_version = ">=0.24.0" - -[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/execution_success/recursion/Prover.toml b/noir/noir-repo/test_programs/execution_success/recursion/Prover.toml deleted file mode 100644 index b00cd8661d8f..000000000000 --- a/noir/noir-repo/test_programs/execution_success/recursion/Prover.toml +++ /dev/null @@ -1,4 +0,0 @@ -key_hash = "0" -public_inputs = ["0"] -verification_key = ['0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'] -proof = ['0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/execution_success/recursion/src/main.nr b/noir/noir-repo/test_programs/execution_success/recursion/src/main.nr deleted file mode 100644 index f1b3875e1d4c..000000000000 --- a/noir/noir-repo/test_programs/execution_success/recursion/src/main.nr +++ /dev/null @@ -1,16 +0,0 @@ -use dep::std; - -// This test is used to generate artifacts for the compiler `integration-tests` -fn main( - verification_key: [Field; 114], - proof: [Field; 93], - public_inputs: [Field; 1], - key_hash: Field -) { - std::verify_proof( - verification_key.as_slice(), - proof.as_slice(), - public_inputs.as_slice(), - key_hash - ) -} diff --git a/noir/noir-repo/test_programs/execution_success/witness_compression/Nargo.toml b/noir/noir-repo/test_programs/execution_success/witness_compression/Nargo.toml deleted file mode 100644 index 7d6ba0c1938d..000000000000 --- a/noir/noir-repo/test_programs/execution_success/witness_compression/Nargo.toml +++ /dev/null @@ -1,7 +0,0 @@ -[package] -name = "witness_compression" -type = "bin" -authors = [""] -compiler_version = ">=0.24.0" - -[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/execution_success/witness_compression/Prover.toml b/noir/noir-repo/test_programs/execution_success/witness_compression/Prover.toml deleted file mode 100644 index 8c12ebba6cf7..000000000000 --- a/noir/noir-repo/test_programs/execution_success/witness_compression/Prover.toml +++ /dev/null @@ -1,2 +0,0 @@ -x = "1" -y = "2" diff --git a/noir/noir-repo/test_programs/execution_success/witness_compression/src/main.nr b/noir/noir-repo/test_programs/execution_success/witness_compression/src/main.nr deleted file mode 100644 index 803b72c64c55..000000000000 --- a/noir/noir-repo/test_programs/execution_success/witness_compression/src/main.nr +++ /dev/null @@ -1,4 +0,0 @@ -fn main(x : Field, y : pub Field) -> pub Field { - assert(x != y); - x + y -} diff --git a/noir/noir-repo/tooling/backend_interface/src/proof_system.rs b/noir/noir-repo/tooling/backend_interface/src/proof_system.rs index 83ee04f90428..485381006df7 100644 --- a/noir/noir-repo/tooling/backend_interface/src/proof_system.rs +++ b/noir/noir-repo/tooling/backend_interface/src/proof_system.rs @@ -3,7 +3,7 @@ use std::io::Write; use std::path::Path; use acvm::acir::{ - circuit::{Circuit, ExpressionWidth, Program}, + circuit::{Circuit, ExpressionWidth}, native_types::WitnessMap, }; use acvm::FieldElement; @@ -17,7 +17,7 @@ use crate::cli::{ use crate::{Backend, BackendError}; impl Backend { - pub fn get_exact_circuit_size(&self, program: &Program) -> Result { + pub fn get_exact_circuit_size(&self, circuit: &Circuit) -> Result { let binary_path = self.assert_binary_exists()?; self.assert_correct_version()?; @@ -26,8 +26,8 @@ impl Backend { // Create a temporary file for the circuit let circuit_path = temp_directory.join("circuit").with_extension("bytecode"); - let serialized_program = Program::serialize_program(program); - write_to_file(&serialized_program, &circuit_path); + let serialized_circuit = Circuit::serialize_circuit(circuit); + write_to_file(&serialized_circuit, &circuit_path); GatesCommand { crs_path: self.crs_directory(), bytecode_path: circuit_path } .run(binary_path) @@ -55,7 +55,7 @@ impl Backend { #[tracing::instrument(level = "trace", skip_all)] pub fn prove( &self, - program: &Program, + circuit: &Circuit, witness_values: WitnessMap, ) -> Result, BackendError> { let binary_path = self.assert_binary_exists()?; @@ -72,9 +72,9 @@ impl Backend { // Create a temporary file for the circuit // - let bytecode_path = temp_directory.join("program").with_extension("bytecode"); - let serialized_program = Program::serialize_program(program); - write_to_file(&serialized_program, &bytecode_path); + let bytecode_path = temp_directory.join("circuit").with_extension("bytecode"); + let serialized_circuit = Circuit::serialize_circuit(circuit); + write_to_file(&serialized_circuit, &bytecode_path); // Create proof and store it in the specified path let proof_with_public_inputs = @@ -82,8 +82,7 @@ impl Backend { .run(binary_path)?; let proof = bb_abstraction_leaks::remove_public_inputs( - // TODO(https://github.com/noir-lang/noir/issues/4428) - program.functions[0].public_inputs().0.len(), + circuit.public_inputs().0.len(), &proof_with_public_inputs, ); Ok(proof) @@ -94,7 +93,7 @@ impl Backend { &self, proof: &[u8], public_inputs: WitnessMap, - program: &Program, + circuit: &Circuit, ) -> Result { let binary_path = self.assert_binary_exists()?; self.assert_correct_version()?; @@ -109,9 +108,9 @@ impl Backend { write_to_file(&proof_with_public_inputs, &proof_path); // Create a temporary file for the circuit - let bytecode_path = temp_directory.join("program").with_extension("bytecode"); - let serialized_program = Program::serialize_program(program); - write_to_file(&serialized_program, &bytecode_path); + let bytecode_path = temp_directory.join("circuit").with_extension("bytecode"); + let serialized_circuit = Circuit::serialize_circuit(circuit); + write_to_file(&serialized_circuit, &bytecode_path); // Create the verification key and write it to the specified path let vk_path = temp_directory.join("vk"); diff --git a/noir/noir-repo/tooling/backend_interface/src/smart_contract.rs b/noir/noir-repo/tooling/backend_interface/src/smart_contract.rs index e2addeb66dff..5af75e48389a 100644 --- a/noir/noir-repo/tooling/backend_interface/src/smart_contract.rs +++ b/noir/noir-repo/tooling/backend_interface/src/smart_contract.rs @@ -3,11 +3,11 @@ use crate::{ cli::{ContractCommand, WriteVkCommand}, Backend, BackendError, }; -use acvm::acir::circuit::{Circuit, Program}; +use acvm::acir::circuit::Circuit; use tempfile::tempdir; impl Backend { - pub fn eth_contract(&self, program: &Program) -> Result { + pub fn eth_contract(&self, circuit: &Circuit) -> Result { let binary_path = self.assert_binary_exists()?; self.assert_correct_version()?; @@ -15,10 +15,9 @@ impl Backend { let temp_directory_path = temp_directory.path().to_path_buf(); // Create a temporary file for the circuit - let bytecode_path = temp_directory_path.join("program").with_extension("bytecode"); - let serialized_program = Program::serialize_program(program); - // let serialized_program = Circuit::serialize_circuit(&program.functions[0]); - write_to_file(&serialized_program, &bytecode_path); + let bytecode_path = temp_directory_path.join("circuit").with_extension("bytecode"); + let serialized_circuit = Circuit::serialize_circuit(circuit); + write_to_file(&serialized_circuit, &bytecode_path); // Create the verification key and write it to the specified path let vk_path = temp_directory_path.join("vk"); @@ -39,7 +38,7 @@ mod tests { use std::collections::BTreeSet; use acvm::acir::{ - circuit::{Circuit, ExpressionWidth, Opcode, Program, PublicInputs}, + circuit::{Circuit, ExpressionWidth, Opcode, PublicInputs}, native_types::{Expression, Witness}, }; @@ -60,9 +59,8 @@ mod tests { assert_messages: Default::default(), recursive: false, }; - let program = Program { functions: vec![circuit] }; - let contract = get_mock_backend()?.eth_contract(&program)?; + let contract = get_mock_backend()?.eth_contract(&circuit)?; assert!(contract.contains("contract VerifierContract")); diff --git a/noir/noir-repo/tooling/debugger/src/dap.rs b/noir/noir-repo/tooling/debugger/src/dap.rs index fdc56c29b08c..7e67a26b257f 100644 --- a/noir/noir-repo/tooling/debugger/src/dap.rs +++ b/noir/noir-repo/tooling/debugger/src/dap.rs @@ -668,13 +668,8 @@ pub fn run_session( file_map: program.file_map, warnings: program.warnings, }; - let mut session = DapSession::new( - server, - solver, - &program.program.functions[0], - &debug_artifact, - initial_witness, - ); + let mut session = + DapSession::new(server, solver, &program.circuit, &debug_artifact, initial_witness); session.run_loop() } diff --git a/noir/noir-repo/tooling/nargo/src/artifacts/contract.rs b/noir/noir-repo/tooling/nargo/src/artifacts/contract.rs index c0316a6d1a2e..020ce49662f2 100644 --- a/noir/noir-repo/tooling/nargo/src/artifacts/contract.rs +++ b/noir/noir-repo/tooling/nargo/src/artifacts/contract.rs @@ -1,4 +1,4 @@ -use acvm::acir::circuit::Program; +use acvm::acir::circuit::Circuit; use noirc_abi::{Abi, ContractEvent}; use noirc_driver::{CompiledContract, ContractFunction}; use serde::{Deserialize, Serialize}; @@ -50,10 +50,10 @@ pub struct ContractFunctionArtifact { pub abi: Abi, #[serde( - serialize_with = "Program::serialize_program_base64", - deserialize_with = "Program::deserialize_program_base64" + serialize_with = "Circuit::serialize_circuit_base64", + deserialize_with = "Circuit::deserialize_circuit_base64" )] - pub bytecode: Program, + pub bytecode: Circuit, #[serde( serialize_with = "DebugInfo::serialize_compressed_base64_json", diff --git a/noir/noir-repo/tooling/nargo/src/artifacts/program.rs b/noir/noir-repo/tooling/nargo/src/artifacts/program.rs index 046db1cd8faa..d8dc42ec2141 100644 --- a/noir/noir-repo/tooling/nargo/src/artifacts/program.rs +++ b/noir/noir-repo/tooling/nargo/src/artifacts/program.rs @@ -1,6 +1,6 @@ use std::collections::BTreeMap; -use acvm::acir::circuit::Program; +use acvm::acir::circuit::Circuit; use fm::FileId; use noirc_abi::Abi; use noirc_driver::CompiledProgram; @@ -21,10 +21,10 @@ pub struct ProgramArtifact { pub abi: Abi, #[serde( - serialize_with = "Program::serialize_program_base64", - deserialize_with = "Program::deserialize_program_base64" + serialize_with = "Circuit::serialize_circuit_base64", + deserialize_with = "Circuit::deserialize_circuit_base64" )] - pub bytecode: Program, + pub bytecode: Circuit, #[serde( serialize_with = "DebugInfo::serialize_compressed_base64_json", @@ -37,14 +37,14 @@ pub struct ProgramArtifact { } impl From for ProgramArtifact { - fn from(compiled_program: CompiledProgram) -> Self { + fn from(program: CompiledProgram) -> Self { ProgramArtifact { - hash: compiled_program.hash, - abi: compiled_program.abi, - noir_version: compiled_program.noir_version, - bytecode: compiled_program.program, - debug_symbols: compiled_program.debug, - file_map: compiled_program.file_map, + hash: program.hash, + abi: program.abi, + noir_version: program.noir_version, + bytecode: program.circuit, + debug_symbols: program.debug, + file_map: program.file_map, } } } @@ -55,7 +55,7 @@ impl From for CompiledProgram { hash: program.hash, abi: program.abi, noir_version: program.noir_version, - program: program.bytecode, + circuit: program.bytecode, debug: program.debug_symbols, file_map: program.file_map, warnings: vec![], diff --git a/noir/noir-repo/tooling/nargo/src/ops/optimize.rs b/noir/noir-repo/tooling/nargo/src/ops/optimize.rs index 250c070fe879..2d0c4c43d256 100644 --- a/noir/noir-repo/tooling/nargo/src/ops/optimize.rs +++ b/noir/noir-repo/tooling/nargo/src/ops/optimize.rs @@ -1,23 +1,17 @@ use iter_extended::vecmap; use noirc_driver::{CompiledContract, CompiledProgram}; -/// TODO(https://github.com/noir-lang/noir/issues/4428): Need to update how these passes are run to account for -/// multiple ACIR functions - -pub fn optimize_program(mut compiled_program: CompiledProgram) -> CompiledProgram { - // TODO: Work to get rid of these clones by borrowing `Circuit` in the acvm compiler or by accepted a `Program` - let (optimized_circuit, location_map) = - acvm::compiler::optimize(compiled_program.program.functions[0].clone()); - compiled_program.program.functions[0] = optimized_circuit; - compiled_program.debug.update_acir(location_map); - compiled_program +pub fn optimize_program(mut program: CompiledProgram) -> CompiledProgram { + let (optimized_circuit, location_map) = acvm::compiler::optimize(program.circuit); + program.circuit = optimized_circuit; + program.debug.update_acir(location_map); + program } pub fn optimize_contract(contract: CompiledContract) -> CompiledContract { let functions = vecmap(contract.functions, |mut func| { - let (optimized_bytecode, location_map) = - acvm::compiler::optimize(func.bytecode.functions[0].clone()); - func.bytecode.functions[0] = optimized_bytecode; + let (optimized_bytecode, location_map) = acvm::compiler::optimize(func.bytecode); + func.bytecode = optimized_bytecode; func.debug.update_acir(location_map); func }); diff --git a/noir/noir-repo/tooling/nargo/src/ops/test.rs b/noir/noir-repo/tooling/nargo/src/ops/test.rs index 929216bbae9f..92c09ec889e6 100644 --- a/noir/noir-repo/tooling/nargo/src/ops/test.rs +++ b/noir/noir-repo/tooling/nargo/src/ops/test.rs @@ -22,23 +22,18 @@ pub fn run_test( foreign_call_resolver_url: Option<&str>, config: &CompileOptions, ) -> TestStatus { - let compiled_program = compile_no_check(context, config, test_function.get_id(), None, false); - match compiled_program { - Ok(compiled_program) => { + let program = compile_no_check(context, config, test_function.get_id(), None, false); + match program { + Ok(program) => { // Run the backend to ensure the PWG evaluates functions like std::hash::pedersen, // otherwise constraints involving these expressions will not error. let circuit_execution = execute_circuit( - // TODO(https://github.com/noir-lang/noir/issues/4428) - &compiled_program.program.functions[0], + &program.circuit, WitnessMap::new(), blackbox_solver, &mut DefaultForeignCallExecutor::new(show_output, foreign_call_resolver_url), ); - test_status_program_compile_pass( - test_function, - compiled_program.debug, - circuit_execution, - ) + test_status_program_compile_pass(test_function, program.debug, circuit_execution) } Err(err) => test_status_program_compile_fail(err, test_function), } diff --git a/noir/noir-repo/tooling/nargo/src/ops/transform.rs b/noir/noir-repo/tooling/nargo/src/ops/transform.rs index c32ca2f482f4..9267ed7e0459 100644 --- a/noir/noir-repo/tooling/nargo/src/ops/transform.rs +++ b/noir/noir-repo/tooling/nargo/src/ops/transform.rs @@ -2,20 +2,16 @@ use acvm::acir::circuit::ExpressionWidth; use iter_extended::vecmap; use noirc_driver::{CompiledContract, CompiledProgram}; -/// TODO(https://github.com/noir-lang/noir/issues/4428): Need to update how these passes are run to account for -/// multiple ACIR functions - pub fn transform_program( - mut compiled_program: CompiledProgram, + mut program: CompiledProgram, expression_width: ExpressionWidth, ) -> CompiledProgram { - // TODO: Work to get rid of these clones by borrowing `Circuit` in the acvm compiler or by accepted a `Program` let (optimized_circuit, location_map) = - acvm::compiler::compile(compiled_program.program.functions[0].clone(), expression_width); + acvm::compiler::compile(program.circuit, expression_width); - compiled_program.program.functions[0] = optimized_circuit; - compiled_program.debug.update_acir(location_map); - compiled_program + program.circuit = optimized_circuit; + program.debug.update_acir(location_map); + program } pub fn transform_contract( @@ -24,8 +20,8 @@ pub fn transform_contract( ) -> CompiledContract { let functions = vecmap(contract.functions, |mut func| { let (optimized_bytecode, location_map) = - acvm::compiler::compile(func.bytecode.functions[0].clone(), expression_width); - func.bytecode.functions[0] = optimized_bytecode; + acvm::compiler::compile(func.bytecode, expression_width); + func.bytecode = optimized_bytecode; func.debug.update_acir(location_map); func }); diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/codegen_verifier_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/codegen_verifier_cmd.rs index 259e209b65a3..f0fe2e0ea781 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/codegen_verifier_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/codegen_verifier_cmd.rs @@ -64,13 +64,7 @@ pub(crate) fn run( let program = nargo::ops::transform_program(program, expression_width); - // TODO(https://github.com/noir-lang/noir/issues/4428): - // We do not expect to have a smart contract verifier for a foldable program with multiple circuits. - // However, in the future we can expect to possibly have non-inlined ACIR functions during compilation - // that will be inlined at a later step such as by the ACVM compiler or by the backend. - // Add appropriate handling here once the compiler enables multiple ACIR functions. - assert_eq!(program.program.functions.len(), 1); - let smart_contract_string = backend.eth_contract(&program.program)?; + let smart_contract_string = backend.eth_contract(&program.circuit)?; let contract_dir = workspace.contracts_directory_path(package); create_named_dir(&contract_dir, "contract"); diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/compile_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/compile_cmd.rs index 619ce93d6099..4309f0db3ea0 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/compile_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/compile_cmd.rs @@ -151,10 +151,10 @@ pub(super) fn save_program( circuit_dir: &Path, only_acir_opt: bool, ) { + let program_artifact = ProgramArtifact::from(program.clone()); if only_acir_opt { - only_acir(program.program, circuit_dir); + only_acir(&program_artifact, circuit_dir); } else { - let program_artifact = ProgramArtifact::from(program.clone()); save_program_to_file(&program_artifact, &package.name, circuit_dir); } } diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/debug_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/debug_cmd.rs index 1f448105ee25..2c4937b6f16c 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/debug_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/debug_cmd.rs @@ -235,7 +235,7 @@ pub(crate) fn debug_program( noir_debugger::debug_circuit( &blackbox_solver, - &compiled_program.program.functions[0], + &compiled_program.circuit, debug_artifact, initial_witness, ) diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/execute_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/execute_cmd.rs index 37489a069ce8..85c0a4160a72 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/execute_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/execute_cmd.rs @@ -135,9 +135,8 @@ pub(crate) fn execute_program( let initial_witness = compiled_program.abi.encode(inputs_map, None)?; - // TODO(https://github.com/noir-lang/noir/issues/4428) let solved_witness_err = nargo::ops::execute_circuit( - &compiled_program.program.functions[0], + &compiled_program.circuit, initial_witness, &blackbox_solver, &mut DefaultForeignCallExecutor::new(true, foreign_call_resolver_url), diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/fs/program.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/fs/program.rs index 77005e8d5af5..1fb57ae66851 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/fs/program.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/fs/program.rs @@ -1,6 +1,6 @@ use std::path::{Path, PathBuf}; -use acvm::acir::circuit::Program; +use acvm::acir::circuit::Circuit; use nargo::artifacts::{contract::ContractArtifact, program::ProgramArtifact}; use noirc_frontend::graph::CrateName; @@ -18,10 +18,13 @@ pub(crate) fn save_program_to_file>( } /// Writes the bytecode as acir.gz -pub(crate) fn only_acir>(program: Program, circuit_dir: P) -> PathBuf { +pub(crate) fn only_acir>( + program_artifact: &ProgramArtifact, + circuit_dir: P, +) -> PathBuf { create_named_dir(circuit_dir.as_ref(), "target"); let circuit_path = circuit_dir.as_ref().join("acir").with_extension("gz"); - let bytes = Program::serialize_program(&program); + let bytes = Circuit::serialize_circuit(&program_artifact.bytecode); write_to_file(&bytes, &circuit_path); circuit_path diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/fs/witness.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/fs/witness.rs index 52b5c385e5df..1a2cf88f4a16 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/fs/witness.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/fs/witness.rs @@ -1,6 +1,6 @@ use std::path::{Path, PathBuf}; -use acvm::acir::native_types::{WitnessMap, WitnessStack}; +use acvm::acir::native_types::WitnessMap; use nargo::constants::WITNESS_EXT; use super::{create_named_dir, write_to_file}; @@ -14,9 +14,7 @@ pub(crate) fn save_witness_to_dir>( create_named_dir(witness_dir.as_ref(), "witness"); let witness_path = witness_dir.as_ref().join(witness_name).with_extension(WITNESS_EXT); - // TODO(https://github.com/noir-lang/noir/issues/4428) - let witness_stack: WitnessStack = witnesses.into(); - let buf: Vec = witness_stack.try_into()?; + let buf: Vec = witnesses.try_into()?; write_to_file(buf.as_slice(), &witness_path); diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/info_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/info_cmd.rs index 850d5cf6974a..300e1a35be22 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/info_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/info_cmd.rs @@ -275,9 +275,8 @@ fn count_opcodes_and_gates_in_program( Ok(ProgramInfo { name: package.name.to_string(), expression_width, - // TODO(https://github.com/noir-lang/noir/issues/4428) - acir_opcodes: compiled_program.program.functions[0].opcodes.len(), - circuit_size: backend.get_exact_circuit_size(&compiled_program.program)?, + acir_opcodes: compiled_program.circuit.opcodes.len(), + circuit_size: backend.get_exact_circuit_size(&compiled_program.circuit)?, }) } @@ -292,8 +291,7 @@ fn count_opcodes_and_gates_in_contract( .map(|function| -> Result<_, BackendError> { Ok(FunctionInfo { name: function.name, - // TODO(https://github.com/noir-lang/noir/issues/4428) - acir_opcodes: function.bytecode.functions[0].opcodes.len(), + acir_opcodes: function.bytecode.opcodes.len(), circuit_size: backend.get_exact_circuit_size(&function.bytecode)?, }) }) diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/prove_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/prove_cmd.rs index 160b47a26ca3..f0a9b3185b98 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/prove_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/prove_cmd.rs @@ -137,11 +137,11 @@ pub(crate) fn prove_package( Format::Toml, )?; - let proof = backend.prove(&compiled_program.program, solved_witness)?; + let proof = backend.prove(&compiled_program.circuit, solved_witness)?; if check_proof { let public_inputs = public_abi.encode(&public_inputs, return_value)?; - let valid_proof = backend.verify(&proof, public_inputs, &compiled_program.program)?; + let valid_proof = backend.verify(&proof, public_inputs, &compiled_program.circuit)?; if !valid_proof { return Err(CliError::InvalidProof("".into())); diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/verify_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/verify_cmd.rs index 8aae3f983540..1063b50ab6c1 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/verify_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/verify_cmd.rs @@ -101,7 +101,7 @@ fn verify_package( let proof = load_hex_data(&proof_path)?; - let valid_proof = backend.verify(&proof, public_inputs, &compiled_program.program)?; + let valid_proof = backend.verify(&proof, public_inputs, &compiled_program.circuit)?; if valid_proof { Ok(()) diff --git a/noir/noir-repo/tooling/nargo_cli/src/errors.rs b/noir/noir-repo/tooling/nargo_cli/src/errors.rs index 40fb7886405a..c2996f53420a 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/errors.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/errors.rs @@ -1,4 +1,4 @@ -use acvm::acir::native_types::WitnessStackError; +use acvm::acir::native_types::WitnessMapError; use hex::FromHexError; use nargo::{errors::CompileError, NargoError}; use nargo_toml::ManifestError; @@ -22,9 +22,9 @@ pub(crate) enum FilesystemError { #[error(transparent)] InputParserError(#[from] InputParserError), - /// WitnessStack serialization error + /// WitnessMap serialization error #[error(transparent)] - WitnessStackSerialization(#[from] WitnessStackError), + WitnessMapSerialization(#[from] WitnessMapError), #[error("Error: could not deserialize build program: {0}")] ProgramSerializationError(String), diff --git a/noir/noir-repo/tooling/noir_js/test/node/e2e.test.ts b/noir/noir-repo/tooling/noir_js/test/node/e2e.test.ts index 0319a7c83187..8921314e8ea3 100644 --- a/noir/noir-repo/tooling/noir_js/test/node/e2e.test.ts +++ b/noir/noir-repo/tooling/noir_js/test/node/e2e.test.ts @@ -91,39 +91,39 @@ it('end-to-end proving and verification with different instances', async () => { expect(proof_is_valid).to.be.true; }); -// // This bug occurs when we use the same backend to create an inner proof and then an outer proof -// // and then try to verify either one of them. -// // -// // The panic occurs when we try to verify the outer/inner proof that was created. -// // If we only create one type of proof, then this works as expected. -// // -// // If we do not create an inner proof, then this will work as expected. -// it('[BUG] -- bb.js null function or function signature mismatch (outer-inner) ', async () => { -// // Noir.Js part -// const inputs = { -// x: '2', -// y: '3', -// }; - -// const program = new Noir(assert_lt_program); - -// const { witness } = await program.execute(inputs); - -// // bb.js part -// // -// // Proof creation -// // -// const prover = new Backend(assert_lt_program); -// // Create a proof using both proving systems, the majority of the time -// // one would only use outer proofs. -// const proofOuter = await prover.generateProof(witness); -// const _proofInner = await prover.generateProof(witness); - -// // Proof verification -// // -// const isValidOuter = await prover.verifyProof(proofOuter); -// expect(isValidOuter).to.be.true; -// // We can also try verifying an inner proof and it will fail. -// const isValidInner = await prover.verifyProof(_proofInner); -// expect(isValidInner).to.be.true; -// }); +// This bug occurs when we use the same backend to create an inner proof and then an outer proof +// and then try to verify either one of them. +// +// The panic occurs when we try to verify the outer/inner proof that was created. +// If we only create one type of proof, then this works as expected. +// +// If we do not create an inner proof, then this will work as expected. +it('[BUG] -- bb.js null function or function signature mismatch (outer-inner) ', async () => { + // Noir.Js part + const inputs = { + x: '2', + y: '3', + }; + + const program = new Noir(assert_lt_program); + + const { witness } = await program.execute(inputs); + + // bb.js part + // + // Proof creation + // + const prover = new Backend(assert_lt_program); + // Create a proof using both proving systems, the majority of the time + // one would only use outer proofs. + const proofOuter = await prover.generateProof(witness); + const _proofInner = await prover.generateProof(witness); + + // Proof verification + // + const isValidOuter = await prover.verifyProof(proofOuter); + expect(isValidOuter).to.be.true; + // We can also try verifying an inner proof and it will fail. + const isValidInner = await prover.verifyProof(_proofInner); + expect(isValidInner).to.be.true; +}); diff --git a/noir/noir-repo/tooling/noir_js_backend_barretenberg/package.json b/noir/noir-repo/tooling/noir_js_backend_barretenberg/package.json index 97b412cc9459..28c3609fd142 100644 --- a/noir/noir-repo/tooling/noir_js_backend_barretenberg/package.json +++ b/noir/noir-repo/tooling/noir_js_backend_barretenberg/package.json @@ -42,7 +42,7 @@ "lint": "NODE_NO_WARNINGS=1 eslint . --ext .ts --ignore-path ./.eslintignore --max-warnings 0" }, "dependencies": { - "@aztec/bb.js": "portal:../../../../barretenberg/ts", + "@aztec/bb.js": "0.24.0", "@noir-lang/types": "workspace:*", "fflate": "^0.8.0" }, diff --git a/noir/noir-repo/tooling/noir_js_backend_barretenberg/src/index.ts b/noir/noir-repo/tooling/noir_js_backend_barretenberg/src/index.ts index bfdf1005a939..af03743eb2f2 100644 --- a/noir/noir-repo/tooling/noir_js_backend_barretenberg/src/index.ts +++ b/noir/noir-repo/tooling/noir_js_backend_barretenberg/src/index.ts @@ -45,6 +45,7 @@ export class BarretenbergBackend implements Backend { } const { Barretenberg, RawBuffer, Crs } = await import('@aztec/bb.js'); const api = await Barretenberg.new(this.options); + const [_exact, _total, subgroupSize] = await api.acirGetCircuitSizes(this.acirUncompressedBytecode); const crs = await Crs.new(subgroupSize + 1); await api.commonInitSlabAllocator(subgroupSize); diff --git a/noir/noir-repo/yarn.lock b/noir/noir-repo/yarn.lock index ad12edebc854..f5f3a29f08a6 100644 --- a/noir/noir-repo/yarn.lock +++ b/noir/noir-repo/yarn.lock @@ -221,18 +221,19 @@ __metadata: languageName: node linkType: hard -"@aztec/bb.js@portal:../../../../barretenberg/ts::locator=%40noir-lang%2Fbackend_barretenberg%40workspace%3Atooling%2Fnoir_js_backend_barretenberg": - version: 0.0.0-use.local - resolution: "@aztec/bb.js@portal:../../../../barretenberg/ts::locator=%40noir-lang%2Fbackend_barretenberg%40workspace%3Atooling%2Fnoir_js_backend_barretenberg" +"@aztec/bb.js@npm:0.24.0": + version: 0.24.0 + resolution: "@aztec/bb.js@npm:0.24.0" dependencies: comlink: ^4.4.1 commander: ^10.0.1 debug: ^4.3.4 tslib: ^2.4.0 bin: - bb.js: ./dest/node/main.js + bb.js: dest/node/main.js + checksum: a086dabf30084cfa526e512148b9c02f0a0770dcc19b7dca4af9a3e98612b716acc7eaac6b52c0f12d985932e866d1cb9e534ded6ac9d747f3dd021afe25de27 languageName: node - linkType: soft + linkType: hard "@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.10.4, @babel/code-frame@npm:^7.12.11, @babel/code-frame@npm:^7.16.0, @babel/code-frame@npm:^7.22.13, @babel/code-frame@npm:^7.23.5, @babel/code-frame@npm:^7.8.3": version: 7.23.5 @@ -4395,7 +4396,7 @@ __metadata: version: 0.0.0-use.local resolution: "@noir-lang/backend_barretenberg@workspace:tooling/noir_js_backend_barretenberg" dependencies: - "@aztec/bb.js": "portal:../../../../barretenberg/ts" + "@aztec/bb.js": 0.24.0 "@noir-lang/types": "workspace:*" "@types/node": ^20.6.2 "@types/prettier": ^3 diff --git a/noir/scripts/test_native.sh b/noir/scripts/test_native.sh index 5b1bb1b180ae..e8c3f27b4b79 100755 --- a/noir/scripts/test_native.sh +++ b/noir/scripts/test_native.sh @@ -14,4 +14,4 @@ RUSTFLAGS=-Dwarnings cargo clippy --workspace --locked --release ./.github/scripts/cargo-binstall-install.sh cargo-binstall cargo-nextest --version 0.9.67 -y --secure -cargo nextest run --locked --release -E '!test(hello_world_example) & !test(simple_verifier_codegen)' +cargo nextest run --locked --release -E '!test(hello_world_example)' From 7748098beef755c30bf1d1b2f4f63606e0068e38 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Tue, 12 Mar 2024 03:55:47 +0000 Subject: [PATCH 036/139] Reapply "merge conflicts w/ master" This reverts commit d6707ca6545bddfe5e76154ef49c9a54cb7dfb40. --- .circleci/config.yml | 214 +- .vscode/settings.json | 1 + avm-transpiler/src/transpile_contract.rs | 13 +- .../acir_tests/flows/write_contract.sh | 7 + barretenberg/acir_tests/run_acir_tests.sh | 2 +- .../acir_format/acir_to_constraint_buf.hpp | 82 +- .../dsl/acir_format/serde/acir.hpp | 1797 ++++++----- .../dsl/acir_format/serde/index.hpp | 4 +- .../dsl/acir_format/serde/witness_map.hpp | 123 - .../dsl/acir_format/serde/witness_stack.hpp | 247 ++ build_manifest.yml | 3 + noir/Dockerfile.packages | 6 + noir/Dockerfile.packages-test | 6 + .../noir-repo/acvm-repo/acir/codegen/acir.cpp | 1712 +++++----- .../acvm-repo/acir/codegen/witness.cpp | 130 +- .../acvm-repo/acir/src/circuit/mod.rs | 74 + noir/noir-repo/acvm-repo/acir/src/lib.rs | 10 +- .../acvm-repo/acir/src/native_types/mod.rs | 4 +- .../acir/src/native_types/witness_stack.rs | 64 + .../acir/tests/test_program_serialization.rs | 119 +- .../acvm-repo/acvm_js/src/compression.rs | 15 +- .../acvm-repo/acvm_js/src/execute.rs | 8 +- .../acvm-repo/acvm_js/src/public_witness.rs | 29 +- .../acvm-repo/acvm_js/test/shared/addition.ts | 11 +- .../test/shared/complex_foreign_call.ts | 16 +- .../test/shared/fixed_base_scalar_mul.ts | 6 +- .../acvm_js/test/shared/foreign_call.ts | 9 +- .../acvm_js/test/shared/memory_op.ts | 9 +- .../acvm-repo/acvm_js/test/shared/pedersen.ts | 5 +- .../acvm_js/test/shared/schnorr_verify.ts | 28 +- .../test/shared/witness_compression.ts | 23 +- .../compiler/integration-tests/.gitignore | 1 - .../integration-tests/contracts/1_mul.sol | 2869 +++++++++++++++++ .../contracts/assert_statement.sol | 2869 +++++++++++++++++ .../integration-tests/contracts/recursion.sol | 2869 +++++++++++++++++ .../compiler/integration-tests/package.json | 2 +- .../compiler/noirc_driver/src/contract.rs | 8 +- .../compiler/noirc_driver/src/lib.rs | 9 +- .../compiler/noirc_driver/src/program.rs | 8 +- .../execution_success/recursion/Nargo.toml | 7 + .../execution_success/recursion/Prover.toml | 4 + .../execution_success/recursion/src/main.nr | 16 + .../witness_compression/Nargo.toml | 7 + .../witness_compression/Prover.toml | 2 + .../witness_compression/src/main.nr | 4 + .../backend_interface/src/proof_system.rs | 27 +- .../backend_interface/src/smart_contract.rs | 16 +- noir/noir-repo/tooling/debugger/src/dap.rs | 9 +- .../tooling/nargo/src/artifacts/contract.rs | 8 +- .../tooling/nargo/src/artifacts/program.rs | 24 +- .../tooling/nargo/src/ops/optimize.rs | 20 +- noir/noir-repo/tooling/nargo/src/ops/test.rs | 15 +- .../tooling/nargo/src/ops/transform.rs | 18 +- .../nargo_cli/src/cli/codegen_verifier_cmd.rs | 8 +- .../tooling/nargo_cli/src/cli/compile_cmd.rs | 4 +- .../tooling/nargo_cli/src/cli/debug_cmd.rs | 2 +- .../tooling/nargo_cli/src/cli/execute_cmd.rs | 3 +- .../tooling/nargo_cli/src/cli/fs/program.rs | 9 +- .../tooling/nargo_cli/src/cli/fs/witness.rs | 6 +- .../tooling/nargo_cli/src/cli/info_cmd.rs | 8 +- .../tooling/nargo_cli/src/cli/prove_cmd.rs | 4 +- .../tooling/nargo_cli/src/cli/verify_cmd.rs | 2 +- .../noir-repo/tooling/nargo_cli/src/errors.rs | 6 +- .../tooling/noir_js/test/node/e2e.test.ts | 72 +- .../noir_js_backend_barretenberg/package.json | 2 +- .../noir_js_backend_barretenberg/src/index.ts | 1 - noir/noir-repo/yarn.lock | 13 +- noir/scripts/test_native.sh | 2 +- 68 files changed, 11481 insertions(+), 2250 deletions(-) create mode 100755 barretenberg/acir_tests/flows/write_contract.sh delete mode 100644 barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/witness_map.hpp create mode 100644 barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/witness_stack.hpp create mode 100644 noir/noir-repo/acvm-repo/acir/src/native_types/witness_stack.rs create mode 100644 noir/noir-repo/compiler/integration-tests/contracts/1_mul.sol create mode 100644 noir/noir-repo/compiler/integration-tests/contracts/assert_statement.sol create mode 100644 noir/noir-repo/compiler/integration-tests/contracts/recursion.sol create mode 100644 noir/noir-repo/test_programs/execution_success/recursion/Nargo.toml create mode 100644 noir/noir-repo/test_programs/execution_success/recursion/Prover.toml create mode 100644 noir/noir-repo/test_programs/execution_success/recursion/src/main.nr create mode 100644 noir/noir-repo/test_programs/execution_success/witness_compression/Nargo.toml create mode 100644 noir/noir-repo/test_programs/execution_success/witness_compression/Prover.toml create mode 100644 noir/noir-repo/test_programs/execution_success/witness_compression/src/main.nr diff --git a/.circleci/config.yml b/.circleci/config.yml index 3579c1e18e5f..d30da596fb5b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -92,103 +92,6 @@ jobs: - continuation/continue: configuration_path: .circleci/generated_config.yml - # Noir - noir-x86_64: - docker: - - image: aztecprotocol/alpine-build-image - resource_class: small - steps: - - *checkout - - *setup_env - - run: - name: "Build" - command: cond_spot_run_build noir 32 - aztec_manifest_key: noir - - noir-arm64: - docker: - - image: aztecprotocol/alpine-build-image - resource_class: small - steps: - - *checkout - - *setup_env - - run: - name: "Build" - command: cond_spot_run_build noir 32 arm64 - aztec_manifest_key: noir - - noir-ecr-manifest: - machine: - image: default - resource_class: medium - steps: - - *checkout - - *setup_env - - run: - name: "Create ECR manifest" - command: create_ecr_manifest noir x86_64,arm64 - aztec_manifest_key: noir - - noir-tests: - docker: - - image: aztecprotocol/alpine-build-image - resource_class: small - steps: - - *checkout - - *setup_env - - run: - name: "Build" - command: cond_spot_run_build noir-tests 32 - aztec_manifest_key: noir-tests - - noir-packages: - docker: - - image: aztecprotocol/alpine-build-image - resource_class: small - steps: - - *checkout - - *setup_env - - run: - name: "Build" - command: cond_spot_run_build noir-packages 32 - aztec_manifest_key: noir-packages - - noir-packages-tests: - docker: - - image: aztecprotocol/alpine-build-image - resource_class: small - steps: - - *checkout - - *setup_env - - run: - name: "Build" - command: cond_spot_run_build noir-packages-tests 32 - aztec_manifest_key: noir-packages-tests - - noir-compile-acir-tests: - docker: - - image: aztecprotocol/alpine-build-image - resource_class: small - steps: - - *checkout - - *setup_env - - run: - name: "Build" - command: cond_spot_run_build noir-compile-acir-tests 32 - aztec_manifest_key: noir-compile-acir-tests - - avm-transpiler: - docker: - - image: aztecprotocol/alpine-build-image - resource_class: small - steps: - - *checkout - - *setup_env - - run: - name: "Build" - command: cond_spot_run_build avm-transpiler 32 - aztec_manifest_key: avm-transpiler - # Barretenberg barretenberg-wasm-linux-clang: docker: @@ -356,7 +259,7 @@ jobs: command: cond_spot_run_test barretenberg-x86_64-linux-clang-assert 32 ./scripts/run_tests 3 stdlib_recursion_tests --gtest_filter=-*turbo* aztec_manifest_key: barretenberg-x86_64-linux-clang-assert - barretenberg-acir-tests-bb: + barretenberg-join-split-tests: docker: - image: aztecprotocol/alpine-build-image resource_class: small @@ -364,9 +267,9 @@ jobs: - *checkout - *setup_env - run: - name: "Build and test" - command: cond_spot_run_build barretenberg-acir-tests-bb 32 - aztec_manifest_key: barretenberg-acir-tests-bb + name: "Test" + command: cond_spot_run_test barretenberg-x86_64-linux-clang-assert 32 ./scripts/run_tests 3 join_split_example_proofs_join_split_tests --gtest_filter=-*full_proof* + aztec_manifest_key: barretenberg-x86_64-linux-clang-assert barretenberg-acir-tests-bb-sol: docker: @@ -403,6 +306,115 @@ jobs: name: "Build and test" command: cond_spot_run_test bb.js 32 ./scripts/run_tests aztec_manifest_key: bb.js + + # Noir + noir-x86_64: + docker: + - image: aztecprotocol/alpine-build-image + resource_class: small + steps: + - *checkout + - *setup_env + - run: + name: "Build" + command: cond_spot_run_build noir 32 + aztec_manifest_key: noir + + noir-arm64: + docker: + - image: aztecprotocol/alpine-build-image + resource_class: small + steps: + - *checkout + - *setup_env + - run: + name: "Build" + command: cond_spot_run_build noir 32 arm64 + aztec_manifest_key: noir + + noir-ecr-manifest: + machine: + image: default + resource_class: medium + steps: + - *checkout + - *setup_env + - run: + name: "Create ECR manifest" + command: create_ecr_manifest noir x86_64,arm64 + aztec_manifest_key: noir + + noir-tests: + docker: + - image: aztecprotocol/alpine-build-image + resource_class: small + steps: + - *checkout + - *setup_env + - run: + name: "Build" + command: cond_spot_run_build noir-tests 32 + aztec_manifest_key: noir-tests + + noir-packages: + docker: + - image: aztecprotocol/alpine-build-image + resource_class: small + steps: + - *checkout + - *setup_env + - run: + name: "Build" + command: cond_spot_run_build noir-packages 32 + aztec_manifest_key: noir-packages + + noir-packages-tests: + docker: + - image: aztecprotocol/alpine-build-image + resource_class: small + steps: + - *checkout + - *setup_env + - run: + name: "Build" + command: cond_spot_run_build noir-packages-tests 32 + aztec_manifest_key: noir-packages-tests + + noir-compile-acir-tests: + docker: + - image: aztecprotocol/alpine-build-image + resource_class: small + steps: + - *checkout + - *setup_env + - run: + name: "Build" + command: cond_spot_run_build noir-compile-acir-tests 32 + aztec_manifest_key: noir-compile-acir-tests + + avm-transpiler: + docker: + - image: aztecprotocol/alpine-build-image + resource_class: small + steps: + - *checkout + - *setup_env + - run: + name: "Build" + command: cond_spot_run_build avm-transpiler 32 + aztec_manifest_key: avm-transpiler + + barretenberg-acir-tests-bb: + docker: + - image: aztecprotocol/alpine-build-image + resource_class: small + steps: + - *checkout + - *setup_env + - run: + name: "Build and test" + command: cond_spot_run_build barretenberg-acir-tests-bb 32 + aztec_manifest_key: barretenberg-acir-tests-bb bb-js-acir-tests: docker: diff --git a/.vscode/settings.json b/.vscode/settings.json index 2e610b828f9d..98b15088b502 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -158,6 +158,7 @@ "C_Cpp.default.includePath": ["barretenberg/cpp/src"], "rust-analyzer.linkedProjects": [ "noir/noir-repo/Cargo.toml", + "noir/noir-repo/acvm-repo/acvm_js/Cargo.toml", "avm-transpiler/Cargo.toml" ] } diff --git a/avm-transpiler/src/transpile_contract.rs b/avm-transpiler/src/transpile_contract.rs index 77528a460571..dc3453bf8b5c 100644 --- a/avm-transpiler/src/transpile_contract.rs +++ b/avm-transpiler/src/transpile_contract.rs @@ -3,7 +3,8 @@ use log::info; use regex::Regex; use serde::{Deserialize, Serialize}; -use acvm::acir::circuit::Circuit; +use acvm::acir::circuit::Program; +use noirc_driver::ContractFunctionType; use crate::transpile::brillig_to_avm; use crate::utils::extract_brillig_from_acir; @@ -55,10 +56,10 @@ pub struct AcirContractFunction { pub custom_attributes: Vec, pub abi: serde_json::Value, #[serde( - serialize_with = "Circuit::serialize_circuit_base64", - deserialize_with = "Circuit::deserialize_circuit_base64" + serialize_with = "Program::serialize_program_base64", + deserialize_with = "Program::deserialize_program_base64" )] - pub bytecode: Circuit, + pub bytecode: Program, pub debug_symbols: serde_json::Value, } @@ -91,8 +92,8 @@ impl From for TranspiledContract { function.name, contract.name ); // Extract Brillig Opcodes from acir - let acir_circuit = function.bytecode.clone(); - let brillig = extract_brillig_from_acir(&acir_circuit.opcodes); + let acir_program = function.bytecode; + let brillig = extract_brillig_from_acir(&acir_program.functions[0].opcodes); // Transpile to AVM let avm_bytecode = brillig_to_avm(brillig); diff --git a/barretenberg/acir_tests/flows/write_contract.sh b/barretenberg/acir_tests/flows/write_contract.sh new file mode 100755 index 000000000000..4f483395c58d --- /dev/null +++ b/barretenberg/acir_tests/flows/write_contract.sh @@ -0,0 +1,7 @@ +#!/bin/sh +set -eu + +export TEST_NAME=$(basename $(pwd)) + +$BIN write_vk -o vk +$BIN contract -k vk -c $CRS_PATH -b ./target/acir.gz -o $TEST_NAME.sol diff --git a/barretenberg/acir_tests/run_acir_tests.sh b/barretenberg/acir_tests/run_acir_tests.sh index 88189a434380..4203d9448f91 100755 --- a/barretenberg/acir_tests/run_acir_tests.sh +++ b/barretenberg/acir_tests/run_acir_tests.sh @@ -35,7 +35,7 @@ export BIN CRS_PATH VERBOSE BRANCH cd acir_tests # Convert them to array -SKIP_ARRAY=(diamond_deps_0 workspace workspace_default_member) +SKIP_ARRAY=(diamond_deps_0 workspace workspace_default_member recursion) function test() { cd $1 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 f7a5cbcf44d1..58d036f4e165 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 @@ -26,10 +26,10 @@ namespace acir_format { * * @param arg acir representation of an 3-wire arithmetic operation * @return poly_triple - * @note In principle Circuit::Expression can accommodate arbitrarily many quadratic and linear terms but in practice + * @note In principle Program::Expression can accommodate arbitrarily many quadratic and linear terms but in practice * the ones processed here have a max of 1 and 3 respectively, in accordance with the standard width-3 arithmetic gate. */ -poly_triple serialize_arithmetic_gate(Circuit::Expression const& arg) +poly_triple serialize_arithmetic_gate(Program::Expression const& arg) { // TODO(https://github.com/AztecProtocol/barretenberg/issues/816): The initialization of the witness indices a,b,c // to 0 is implicitly assuming that (builder.zero_idx == 0) which is no longer the case. Now, witness idx 0 in @@ -98,17 +98,17 @@ poly_triple serialize_arithmetic_gate(Circuit::Expression const& arg) return pt; } -void handle_arithmetic(Circuit::Opcode::AssertZero const& arg, AcirFormat& af) +void handle_arithmetic(Program::Opcode::AssertZero const& arg, AcirFormat& af) { af.constraints.push_back(serialize_arithmetic_gate(arg.value)); } -void handle_blackbox_func_call(Circuit::Opcode::BlackBoxFuncCall const& arg, AcirFormat& af) +void handle_blackbox_func_call(Program::Opcode::BlackBoxFuncCall const& arg, AcirFormat& af) { std::visit( [&](auto&& arg) { using T = std::decay_t; - if constexpr (std::is_same_v) { + if constexpr (std::is_same_v) { af.logic_constraints.push_back(LogicConstraint{ .a = arg.lhs.witness.value, .b = arg.rhs.witness.value, @@ -116,7 +116,7 @@ void handle_blackbox_func_call(Circuit::Opcode::BlackBoxFuncCall const& arg, Aci .num_bits = arg.lhs.num_bits, .is_xor_gate = false, }); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { af.logic_constraints.push_back(LogicConstraint{ .a = arg.lhs.witness.value, .b = arg.rhs.witness.value, @@ -124,12 +124,12 @@ void handle_blackbox_func_call(Circuit::Opcode::BlackBoxFuncCall const& arg, Aci .num_bits = arg.lhs.num_bits, .is_xor_gate = true, }); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { af.range_constraints.push_back(RangeConstraint{ .witness = arg.input.witness.value, .num_bits = arg.input.num_bits, }); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { af.sha256_constraints.push_back(Sha256Constraint{ .inputs = map(arg.inputs, [](auto& e) { @@ -140,7 +140,7 @@ void handle_blackbox_func_call(Circuit::Opcode::BlackBoxFuncCall const& arg, Aci }), .result = map(arg.outputs, [](auto& e) { return e.value; }), }); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { af.sha256_compression.push_back(Sha256Compression{ .inputs = map(arg.inputs, [](auto& e) { @@ -158,7 +158,7 @@ void handle_blackbox_func_call(Circuit::Opcode::BlackBoxFuncCall const& arg, Aci }), .result = map(arg.outputs, [](auto& e) { return e.value; }), }); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { af.blake2s_constraints.push_back(Blake2sConstraint{ .inputs = map(arg.inputs, [](auto& e) { @@ -169,7 +169,7 @@ void handle_blackbox_func_call(Circuit::Opcode::BlackBoxFuncCall const& arg, Aci }), .result = map(arg.outputs, [](auto& e) { return e.value; }), }); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { af.blake3_constraints.push_back(Blake3Constraint{ .inputs = map(arg.inputs, [](auto& e) { @@ -180,7 +180,7 @@ void handle_blackbox_func_call(Circuit::Opcode::BlackBoxFuncCall const& arg, Aci }), .result = map(arg.outputs, [](auto& e) { return e.value; }), }); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { af.schnorr_constraints.push_back(SchnorrConstraint{ .message = map(arg.message, [](auto& e) { return e.witness.value; }), .public_key_x = arg.public_key_x.witness.value, @@ -188,20 +188,20 @@ void handle_blackbox_func_call(Circuit::Opcode::BlackBoxFuncCall const& arg, Aci .result = arg.output.value, .signature = map(arg.signature, [](auto& e) { return e.witness.value; }), }); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { af.pedersen_constraints.push_back(PedersenConstraint{ .scalars = map(arg.inputs, [](auto& e) { return e.witness.value; }), .hash_index = arg.domain_separator, .result_x = arg.outputs[0].value, .result_y = arg.outputs[1].value, }); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { af.pedersen_hash_constraints.push_back(PedersenHashConstraint{ .scalars = map(arg.inputs, [](auto& e) { return e.witness.value; }), .hash_index = arg.domain_separator, .result = arg.output.value, }); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { af.ecdsa_k1_constraints.push_back(EcdsaSecp256k1Constraint{ .hashed_message = map(arg.hashed_message, [](auto& e) { return e.witness.value; }), .signature = map(arg.signature, [](auto& e) { return e.witness.value; }), @@ -209,7 +209,7 @@ void handle_blackbox_func_call(Circuit::Opcode::BlackBoxFuncCall const& arg, Aci .pub_y_indices = map(arg.public_key_y, [](auto& e) { return e.witness.value; }), .result = arg.output.value, }); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { af.ecdsa_r1_constraints.push_back(EcdsaSecp256r1Constraint{ .hashed_message = map(arg.hashed_message, [](auto& e) { return e.witness.value; }), .pub_x_indices = map(arg.public_key_x, [](auto& e) { return e.witness.value; }), @@ -217,14 +217,14 @@ void handle_blackbox_func_call(Circuit::Opcode::BlackBoxFuncCall const& arg, Aci .result = arg.output.value, .signature = map(arg.signature, [](auto& e) { return e.witness.value; }), }); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { af.fixed_base_scalar_mul_constraints.push_back(FixedBaseScalarMul{ .low = arg.low.witness.value, .high = arg.high.witness.value, .pub_key_x = arg.outputs[0].value, .pub_key_y = arg.outputs[1].value, }); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { af.ec_add_constraints.push_back(EcAdd{ .input1_x = arg.input1_x.witness.value, .input1_y = arg.input1_y.witness.value, @@ -233,7 +233,7 @@ void handle_blackbox_func_call(Circuit::Opcode::BlackBoxFuncCall const& arg, Aci .result_x = arg.outputs[0].value, .result_y = arg.outputs[1].value, }); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { af.keccak_constraints.push_back(KeccakConstraint{ .inputs = map(arg.inputs, [](auto& e) { @@ -244,7 +244,7 @@ void handle_blackbox_func_call(Circuit::Opcode::BlackBoxFuncCall const& arg, Aci }), .result = map(arg.outputs, [](auto& e) { return e.value; }), }); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { af.keccak_var_constraints.push_back(KeccakVarConstraint{ .inputs = map(arg.inputs, [](auto& e) { @@ -256,12 +256,12 @@ void handle_blackbox_func_call(Circuit::Opcode::BlackBoxFuncCall const& arg, Aci .result = map(arg.outputs, [](auto& e) { return e.value; }), .var_message_size = arg.var_message_size.witness.value, }); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { af.keccak_permutations.push_back(Keccakf1600{ .state = map(arg.inputs, [](auto& e) { return e.witness.value; }), .result = map(arg.outputs, [](auto& e) { return e.value; }), }); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { auto c = RecursionConstraint{ .key = map(arg.verification_key, [](auto& e) { return e.witness.value; }), .proof = map(arg.proof, [](auto& e) { return e.witness.value; }), @@ -269,46 +269,46 @@ 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) { + } 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) { + } else if constexpr (std::is_same_v) { af.bigint_to_le_bytes_constraints.push_back(BigIntToLeBytes{ .input = arg.input, .result = map(arg.outputs, [](auto& e) { return e.value; }), }); - } else if constexpr (std::is_same_v) { + } 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) { + } else if constexpr (std::is_same_v) { af.bigint_operations.push_back(BigIntOperation{ .lhs = arg.lhs, .rhs = arg.rhs, .result = arg.output, .opcode = BigIntOperationType::Sub, }); - } else if constexpr (std::is_same_v) { + } 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) { + } 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, }); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { af.poseidon2_constraints.push_back(Poseidon2Constraint{ .state = map(arg.inputs, [](auto& e) { return e.witness.value; }), .result = map(arg.outputs, [](auto& e) { return e.value; }), @@ -319,7 +319,7 @@ void handle_blackbox_func_call(Circuit::Opcode::BlackBoxFuncCall const& arg, Aci arg.value.value); } -BlockConstraint handle_memory_init(Circuit::Opcode::MemoryInit const& mem_init) +BlockConstraint handle_memory_init(Program::Opcode::MemoryInit const& mem_init) { BlockConstraint block{ .init = {}, .trace = {}, .type = BlockType::ROM }; std::vector init; @@ -341,13 +341,13 @@ BlockConstraint handle_memory_init(Circuit::Opcode::MemoryInit const& mem_init) return block; } -bool is_rom(Circuit::MemOp const& mem_op) +bool is_rom(Program::MemOp const& mem_op) { return mem_op.operation.mul_terms.size() == 0 && mem_op.operation.linear_combinations.size() == 0 && uint256_t(mem_op.operation.q_c) == 0; } -void handle_memory_op(Circuit::Opcode::MemoryOp const& mem_op, BlockConstraint& block) +void handle_memory_op(Program::Opcode::MemoryOp const& mem_op, BlockConstraint& block) { uint8_t access_type = 1; if (is_rom(mem_op.op)) { @@ -365,7 +365,9 @@ void handle_memory_op(Circuit::Opcode::MemoryOp const& mem_op, BlockConstraint& AcirFormat circuit_buf_to_acir_format(std::vector const& buf) { - auto circuit = Circuit::Circuit::bincodeDeserialize(buf); + // TODO(maxim): Handle the new `Program` structure once ACVM supports a function call stack. + // For now we expect a single ACIR function + auto circuit = Program::Program::bincodeDeserialize(buf).functions[0]; AcirFormat af; // `varnum` is the true number of variables, thus we add one to the index which starts at zero @@ -378,15 +380,15 @@ AcirFormat circuit_buf_to_acir_format(std::vector const& buf) std::visit( [&](auto&& arg) { using T = std::decay_t; - if constexpr (std::is_same_v) { + if constexpr (std::is_same_v) { handle_arithmetic(arg, af); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { handle_blackbox_func_call(arg, af); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { auto block = handle_memory_init(arg); uint32_t block_id = arg.block_id.value; block_id_to_block_constraint[block_id] = block; - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { auto block = block_id_to_block_constraint.find(arg.block_id.value); if (block == block_id_to_block_constraint.end()) { throw_or_abort("unitialized MemoryOp"); @@ -414,7 +416,11 @@ AcirFormat circuit_buf_to_acir_format(std::vector const& buf) */ WitnessVector witness_buf_to_witness_data(std::vector const& buf) { - auto w = WitnessMap::WitnessMap::bincodeDeserialize(buf); + // TODO(maxim): Handle the new `WitnessStack` structure once ACVM supports a function call stack + // A `StackItem` contains an index to an ACIR circuit and its respective ACIR-native `WitnessMap`. + // For now we expect the `WitnessStack` to contain a single witness. + auto w = WitnessStack::WitnessStack::bincodeDeserialize(buf).stack[0].witness; + WitnessVector wv; size_t index = 0; for (auto& e : w.value) { 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 0170896c722f..82b105315afe 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/acir.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/acir.hpp @@ -3,7 +3,7 @@ #include "bincode.hpp" #include "serde.hpp" -namespace Circuit { +namespace Program { struct BinaryFieldOp { @@ -140,7 +140,7 @@ struct MemoryAddress { }; struct HeapArray { - Circuit::MemoryAddress pointer; + Program::MemoryAddress pointer; uint64_t size; friend bool operator==(const HeapArray&, const HeapArray&); @@ -149,8 +149,8 @@ struct HeapArray { }; struct HeapVector { - Circuit::MemoryAddress pointer; - Circuit::MemoryAddress size; + Program::MemoryAddress pointer; + Program::MemoryAddress size; friend bool operator==(const HeapVector&, const HeapVector&); std::vector bincodeSerialize() const; @@ -160,8 +160,8 @@ struct HeapVector { struct BlackBoxOp { struct Sha256 { - Circuit::HeapVector message; - Circuit::HeapArray output; + Program::HeapVector message; + Program::HeapArray output; friend bool operator==(const Sha256&, const Sha256&); std::vector bincodeSerialize() const; @@ -169,8 +169,8 @@ struct BlackBoxOp { }; struct Blake2s { - Circuit::HeapVector message; - Circuit::HeapArray output; + Program::HeapVector message; + Program::HeapArray output; friend bool operator==(const Blake2s&, const Blake2s&); std::vector bincodeSerialize() const; @@ -178,8 +178,8 @@ struct BlackBoxOp { }; struct Blake3 { - Circuit::HeapVector message; - Circuit::HeapArray output; + Program::HeapVector message; + Program::HeapArray output; friend bool operator==(const Blake3&, const Blake3&); std::vector bincodeSerialize() const; @@ -187,8 +187,8 @@ struct BlackBoxOp { }; struct Keccak256 { - Circuit::HeapVector message; - Circuit::HeapArray output; + Program::HeapVector message; + Program::HeapArray output; friend bool operator==(const Keccak256&, const Keccak256&); std::vector bincodeSerialize() const; @@ -196,8 +196,8 @@ struct BlackBoxOp { }; struct Keccakf1600 { - Circuit::HeapVector message; - Circuit::HeapArray output; + Program::HeapVector message; + Program::HeapArray output; friend bool operator==(const Keccakf1600&, const Keccakf1600&); std::vector bincodeSerialize() const; @@ -205,11 +205,11 @@ struct BlackBoxOp { }; struct EcdsaSecp256k1 { - Circuit::HeapVector hashed_msg; - Circuit::HeapArray public_key_x; - Circuit::HeapArray public_key_y; - Circuit::HeapArray signature; - Circuit::MemoryAddress result; + Program::HeapVector hashed_msg; + Program::HeapArray public_key_x; + Program::HeapArray public_key_y; + Program::HeapArray signature; + Program::MemoryAddress result; friend bool operator==(const EcdsaSecp256k1&, const EcdsaSecp256k1&); std::vector bincodeSerialize() const; @@ -217,11 +217,11 @@ struct BlackBoxOp { }; struct EcdsaSecp256r1 { - Circuit::HeapVector hashed_msg; - Circuit::HeapArray public_key_x; - Circuit::HeapArray public_key_y; - Circuit::HeapArray signature; - Circuit::MemoryAddress result; + Program::HeapVector hashed_msg; + Program::HeapArray public_key_x; + Program::HeapArray public_key_y; + Program::HeapArray signature; + Program::MemoryAddress result; friend bool operator==(const EcdsaSecp256r1&, const EcdsaSecp256r1&); std::vector bincodeSerialize() const; @@ -229,11 +229,11 @@ struct BlackBoxOp { }; struct SchnorrVerify { - Circuit::MemoryAddress public_key_x; - Circuit::MemoryAddress public_key_y; - Circuit::HeapVector message; - Circuit::HeapVector signature; - Circuit::MemoryAddress result; + Program::MemoryAddress public_key_x; + Program::MemoryAddress public_key_y; + Program::HeapVector message; + Program::HeapVector signature; + Program::MemoryAddress result; friend bool operator==(const SchnorrVerify&, const SchnorrVerify&); std::vector bincodeSerialize() const; @@ -241,9 +241,9 @@ struct BlackBoxOp { }; struct PedersenCommitment { - Circuit::HeapVector inputs; - Circuit::MemoryAddress domain_separator; - Circuit::HeapArray output; + Program::HeapVector inputs; + Program::MemoryAddress domain_separator; + Program::HeapArray output; friend bool operator==(const PedersenCommitment&, const PedersenCommitment&); std::vector bincodeSerialize() const; @@ -251,9 +251,9 @@ struct BlackBoxOp { }; struct PedersenHash { - Circuit::HeapVector inputs; - Circuit::MemoryAddress domain_separator; - Circuit::MemoryAddress output; + Program::HeapVector inputs; + Program::MemoryAddress domain_separator; + Program::MemoryAddress output; friend bool operator==(const PedersenHash&, const PedersenHash&); std::vector bincodeSerialize() const; @@ -261,9 +261,9 @@ struct BlackBoxOp { }; struct FixedBaseScalarMul { - Circuit::MemoryAddress low; - Circuit::MemoryAddress high; - Circuit::HeapArray result; + Program::MemoryAddress low; + Program::MemoryAddress high; + Program::HeapArray result; friend bool operator==(const FixedBaseScalarMul&, const FixedBaseScalarMul&); std::vector bincodeSerialize() const; @@ -271,11 +271,11 @@ struct BlackBoxOp { }; struct EmbeddedCurveAdd { - Circuit::MemoryAddress input1_x; - Circuit::MemoryAddress input1_y; - Circuit::MemoryAddress input2_x; - Circuit::MemoryAddress input2_y; - Circuit::HeapArray result; + Program::MemoryAddress input1_x; + Program::MemoryAddress input1_y; + Program::MemoryAddress input2_x; + Program::MemoryAddress input2_y; + Program::HeapArray result; friend bool operator==(const EmbeddedCurveAdd&, const EmbeddedCurveAdd&); std::vector bincodeSerialize() const; @@ -283,9 +283,9 @@ struct BlackBoxOp { }; struct BigIntAdd { - Circuit::MemoryAddress lhs; - Circuit::MemoryAddress rhs; - Circuit::MemoryAddress output; + Program::MemoryAddress lhs; + Program::MemoryAddress rhs; + Program::MemoryAddress output; friend bool operator==(const BigIntAdd&, const BigIntAdd&); std::vector bincodeSerialize() const; @@ -293,9 +293,9 @@ struct BlackBoxOp { }; struct BigIntSub { - Circuit::MemoryAddress lhs; - Circuit::MemoryAddress rhs; - Circuit::MemoryAddress output; + Program::MemoryAddress lhs; + Program::MemoryAddress rhs; + Program::MemoryAddress output; friend bool operator==(const BigIntSub&, const BigIntSub&); std::vector bincodeSerialize() const; @@ -303,9 +303,9 @@ struct BlackBoxOp { }; struct BigIntMul { - Circuit::MemoryAddress lhs; - Circuit::MemoryAddress rhs; - Circuit::MemoryAddress output; + Program::MemoryAddress lhs; + Program::MemoryAddress rhs; + Program::MemoryAddress output; friend bool operator==(const BigIntMul&, const BigIntMul&); std::vector bincodeSerialize() const; @@ -313,9 +313,9 @@ struct BlackBoxOp { }; struct BigIntDiv { - Circuit::MemoryAddress lhs; - Circuit::MemoryAddress rhs; - Circuit::MemoryAddress output; + Program::MemoryAddress lhs; + Program::MemoryAddress rhs; + Program::MemoryAddress output; friend bool operator==(const BigIntDiv&, const BigIntDiv&); std::vector bincodeSerialize() const; @@ -323,9 +323,9 @@ struct BlackBoxOp { }; struct BigIntFromLeBytes { - Circuit::HeapVector inputs; - Circuit::HeapVector modulus; - Circuit::MemoryAddress output; + Program::HeapVector inputs; + Program::HeapVector modulus; + Program::MemoryAddress output; friend bool operator==(const BigIntFromLeBytes&, const BigIntFromLeBytes&); std::vector bincodeSerialize() const; @@ -333,8 +333,8 @@ struct BlackBoxOp { }; struct BigIntToLeBytes { - Circuit::MemoryAddress input; - Circuit::HeapVector output; + Program::MemoryAddress input; + Program::HeapVector output; friend bool operator==(const BigIntToLeBytes&, const BigIntToLeBytes&); std::vector bincodeSerialize() const; @@ -342,9 +342,9 @@ struct BlackBoxOp { }; struct Poseidon2Permutation { - Circuit::HeapVector message; - Circuit::HeapArray output; - Circuit::MemoryAddress len; + Program::HeapVector message; + Program::HeapArray output; + Program::MemoryAddress len; friend bool operator==(const Poseidon2Permutation&, const Poseidon2Permutation&); std::vector bincodeSerialize() const; @@ -352,9 +352,9 @@ struct BlackBoxOp { }; struct Sha256Compression { - Circuit::HeapVector input; - Circuit::HeapVector hash_values; - Circuit::HeapArray output; + Program::HeapVector input; + Program::HeapVector hash_values; + Program::HeapArray output; friend bool operator==(const Sha256Compression&, const Sha256Compression&); std::vector bincodeSerialize() const; @@ -399,7 +399,7 @@ struct HeapValueType { }; struct Array { - std::vector value_types; + std::vector value_types; uint64_t size; friend bool operator==(const Array&, const Array&); @@ -408,7 +408,7 @@ struct HeapValueType { }; struct Vector { - std::vector value_types; + std::vector value_types; friend bool operator==(const Vector&, const Vector&); std::vector bincodeSerialize() const; @@ -433,7 +433,7 @@ struct Value { struct ValueOrArray { struct MemoryAddress { - Circuit::MemoryAddress value; + Program::MemoryAddress value; friend bool operator==(const MemoryAddress&, const MemoryAddress&); std::vector bincodeSerialize() const; @@ -441,7 +441,7 @@ struct ValueOrArray { }; struct HeapArray { - Circuit::HeapArray value; + Program::HeapArray value; friend bool operator==(const HeapArray&, const HeapArray&); std::vector bincodeSerialize() const; @@ -449,7 +449,7 @@ struct ValueOrArray { }; struct HeapVector { - Circuit::HeapVector value; + Program::HeapVector value; friend bool operator==(const HeapVector&, const HeapVector&); std::vector bincodeSerialize() const; @@ -466,10 +466,10 @@ struct ValueOrArray { struct BrilligOpcode { struct BinaryFieldOp { - Circuit::MemoryAddress destination; - Circuit::BinaryFieldOp op; - Circuit::MemoryAddress lhs; - Circuit::MemoryAddress rhs; + Program::MemoryAddress destination; + Program::BinaryFieldOp op; + Program::MemoryAddress lhs; + Program::MemoryAddress rhs; friend bool operator==(const BinaryFieldOp&, const BinaryFieldOp&); std::vector bincodeSerialize() const; @@ -477,11 +477,11 @@ struct BrilligOpcode { }; struct BinaryIntOp { - Circuit::MemoryAddress destination; - Circuit::BinaryIntOp op; + Program::MemoryAddress destination; + Program::BinaryIntOp op; uint32_t bit_size; - Circuit::MemoryAddress lhs; - Circuit::MemoryAddress rhs; + Program::MemoryAddress lhs; + Program::MemoryAddress rhs; friend bool operator==(const BinaryIntOp&, const BinaryIntOp&); std::vector bincodeSerialize() const; @@ -489,8 +489,8 @@ struct BrilligOpcode { }; struct Cast { - Circuit::MemoryAddress destination; - Circuit::MemoryAddress source; + Program::MemoryAddress destination; + Program::MemoryAddress source; uint32_t bit_size; friend bool operator==(const Cast&, const Cast&); @@ -499,7 +499,7 @@ struct BrilligOpcode { }; struct JumpIfNot { - Circuit::MemoryAddress condition; + Program::MemoryAddress condition; uint64_t location; friend bool operator==(const JumpIfNot&, const JumpIfNot&); @@ -508,7 +508,7 @@ struct BrilligOpcode { }; struct JumpIf { - Circuit::MemoryAddress condition; + Program::MemoryAddress condition; uint64_t location; friend bool operator==(const JumpIf&, const JumpIf&); @@ -525,7 +525,7 @@ struct BrilligOpcode { }; struct CalldataCopy { - Circuit::MemoryAddress destination_address; + Program::MemoryAddress destination_address; uint64_t size; uint64_t offset; @@ -543,9 +543,9 @@ struct BrilligOpcode { }; struct Const { - Circuit::MemoryAddress destination; + Program::MemoryAddress destination; uint32_t bit_size; - Circuit::Value value; + Program::Value value; friend bool operator==(const Const&, const Const&); std::vector bincodeSerialize() const; @@ -560,10 +560,10 @@ struct BrilligOpcode { struct ForeignCall { std::string function; - std::vector destinations; - std::vector destination_value_types; - std::vector inputs; - std::vector input_value_types; + std::vector destinations; + std::vector destination_value_types; + std::vector inputs; + std::vector input_value_types; friend bool operator==(const ForeignCall&, const ForeignCall&); std::vector bincodeSerialize() const; @@ -571,8 +571,8 @@ struct BrilligOpcode { }; struct Mov { - Circuit::MemoryAddress destination; - Circuit::MemoryAddress source; + Program::MemoryAddress destination; + Program::MemoryAddress source; friend bool operator==(const Mov&, const Mov&); std::vector bincodeSerialize() const; @@ -580,8 +580,8 @@ struct BrilligOpcode { }; struct Load { - Circuit::MemoryAddress destination; - Circuit::MemoryAddress source_pointer; + Program::MemoryAddress destination; + Program::MemoryAddress source_pointer; friend bool operator==(const Load&, const Load&); std::vector bincodeSerialize() const; @@ -589,8 +589,8 @@ struct BrilligOpcode { }; struct Store { - Circuit::MemoryAddress destination_pointer; - Circuit::MemoryAddress source; + Program::MemoryAddress destination_pointer; + Program::MemoryAddress source; friend bool operator==(const Store&, const Store&); std::vector bincodeSerialize() const; @@ -598,7 +598,7 @@ struct BrilligOpcode { }; struct BlackBox { - Circuit::BlackBoxOp value; + Program::BlackBoxOp value; friend bool operator==(const BlackBox&, const BlackBox&); std::vector bincodeSerialize() const; @@ -653,7 +653,7 @@ struct Witness { }; struct FunctionInput { - Circuit::Witness witness; + Program::Witness witness; uint32_t num_bits; friend bool operator==(const FunctionInput&, const FunctionInput&); @@ -664,9 +664,9 @@ struct FunctionInput { struct BlackBoxFuncCall { struct AND { - Circuit::FunctionInput lhs; - Circuit::FunctionInput rhs; - Circuit::Witness output; + Program::FunctionInput lhs; + Program::FunctionInput rhs; + Program::Witness output; friend bool operator==(const AND&, const AND&); std::vector bincodeSerialize() const; @@ -674,9 +674,9 @@ struct BlackBoxFuncCall { }; struct XOR { - Circuit::FunctionInput lhs; - Circuit::FunctionInput rhs; - Circuit::Witness output; + Program::FunctionInput lhs; + Program::FunctionInput rhs; + Program::Witness output; friend bool operator==(const XOR&, const XOR&); std::vector bincodeSerialize() const; @@ -684,7 +684,7 @@ struct BlackBoxFuncCall { }; struct RANGE { - Circuit::FunctionInput input; + Program::FunctionInput input; friend bool operator==(const RANGE&, const RANGE&); std::vector bincodeSerialize() const; @@ -692,8 +692,8 @@ struct BlackBoxFuncCall { }; struct SHA256 { - std::vector inputs; - std::vector outputs; + std::vector inputs; + std::vector outputs; friend bool operator==(const SHA256&, const SHA256&); std::vector bincodeSerialize() const; @@ -701,8 +701,8 @@ struct BlackBoxFuncCall { }; struct Blake2s { - std::vector inputs; - std::vector outputs; + std::vector inputs; + std::vector outputs; friend bool operator==(const Blake2s&, const Blake2s&); std::vector bincodeSerialize() const; @@ -710,8 +710,8 @@ struct BlackBoxFuncCall { }; struct Blake3 { - std::vector inputs; - std::vector outputs; + std::vector inputs; + std::vector outputs; friend bool operator==(const Blake3&, const Blake3&); std::vector bincodeSerialize() const; @@ -719,11 +719,11 @@ struct BlackBoxFuncCall { }; struct SchnorrVerify { - Circuit::FunctionInput public_key_x; - Circuit::FunctionInput public_key_y; - std::vector signature; - std::vector message; - Circuit::Witness output; + Program::FunctionInput public_key_x; + Program::FunctionInput public_key_y; + std::vector signature; + std::vector message; + Program::Witness output; friend bool operator==(const SchnorrVerify&, const SchnorrVerify&); std::vector bincodeSerialize() const; @@ -731,9 +731,9 @@ struct BlackBoxFuncCall { }; struct PedersenCommitment { - std::vector inputs; + std::vector inputs; uint32_t domain_separator; - std::array outputs; + std::array outputs; friend bool operator==(const PedersenCommitment&, const PedersenCommitment&); std::vector bincodeSerialize() const; @@ -741,9 +741,9 @@ struct BlackBoxFuncCall { }; struct PedersenHash { - std::vector inputs; + std::vector inputs; uint32_t domain_separator; - Circuit::Witness output; + Program::Witness output; friend bool operator==(const PedersenHash&, const PedersenHash&); std::vector bincodeSerialize() const; @@ -751,11 +751,11 @@ struct BlackBoxFuncCall { }; struct EcdsaSecp256k1 { - std::vector public_key_x; - std::vector public_key_y; - std::vector signature; - std::vector hashed_message; - Circuit::Witness output; + std::vector public_key_x; + std::vector public_key_y; + std::vector signature; + std::vector hashed_message; + Program::Witness output; friend bool operator==(const EcdsaSecp256k1&, const EcdsaSecp256k1&); std::vector bincodeSerialize() const; @@ -763,11 +763,11 @@ struct BlackBoxFuncCall { }; struct EcdsaSecp256r1 { - std::vector public_key_x; - std::vector public_key_y; - std::vector signature; - std::vector hashed_message; - Circuit::Witness output; + std::vector public_key_x; + std::vector public_key_y; + std::vector signature; + std::vector hashed_message; + Program::Witness output; friend bool operator==(const EcdsaSecp256r1&, const EcdsaSecp256r1&); std::vector bincodeSerialize() const; @@ -775,9 +775,9 @@ struct BlackBoxFuncCall { }; struct FixedBaseScalarMul { - Circuit::FunctionInput low; - Circuit::FunctionInput high; - std::array outputs; + Program::FunctionInput low; + Program::FunctionInput high; + std::array outputs; friend bool operator==(const FixedBaseScalarMul&, const FixedBaseScalarMul&); std::vector bincodeSerialize() const; @@ -785,11 +785,11 @@ struct BlackBoxFuncCall { }; struct EmbeddedCurveAdd { - Circuit::FunctionInput input1_x; - Circuit::FunctionInput input1_y; - Circuit::FunctionInput input2_x; - Circuit::FunctionInput input2_y; - std::array outputs; + Program::FunctionInput input1_x; + Program::FunctionInput input1_y; + Program::FunctionInput input2_x; + Program::FunctionInput input2_y; + std::array outputs; friend bool operator==(const EmbeddedCurveAdd&, const EmbeddedCurveAdd&); std::vector bincodeSerialize() const; @@ -797,8 +797,8 @@ struct BlackBoxFuncCall { }; struct Keccak256 { - std::vector inputs; - std::vector outputs; + std::vector inputs; + std::vector outputs; friend bool operator==(const Keccak256&, const Keccak256&); std::vector bincodeSerialize() const; @@ -806,9 +806,9 @@ struct BlackBoxFuncCall { }; struct Keccak256VariableLength { - std::vector inputs; - Circuit::FunctionInput var_message_size; - std::vector outputs; + std::vector inputs; + Program::FunctionInput var_message_size; + std::vector outputs; friend bool operator==(const Keccak256VariableLength&, const Keccak256VariableLength&); std::vector bincodeSerialize() const; @@ -816,8 +816,8 @@ struct BlackBoxFuncCall { }; struct Keccakf1600 { - std::vector inputs; - std::vector outputs; + std::vector inputs; + std::vector outputs; friend bool operator==(const Keccakf1600&, const Keccakf1600&); std::vector bincodeSerialize() const; @@ -825,10 +825,10 @@ struct BlackBoxFuncCall { }; struct RecursiveAggregation { - std::vector verification_key; - std::vector proof; - std::vector public_inputs; - Circuit::FunctionInput key_hash; + std::vector verification_key; + std::vector proof; + std::vector public_inputs; + Program::FunctionInput key_hash; friend bool operator==(const RecursiveAggregation&, const RecursiveAggregation&); std::vector bincodeSerialize() const; @@ -876,7 +876,7 @@ struct BlackBoxFuncCall { }; struct BigIntFromLeBytes { - std::vector inputs; + std::vector inputs; std::vector modulus; uint32_t output; @@ -887,7 +887,7 @@ struct BlackBoxFuncCall { struct BigIntToLeBytes { uint32_t input; - std::vector outputs; + std::vector outputs; friend bool operator==(const BigIntToLeBytes&, const BigIntToLeBytes&); std::vector bincodeSerialize() const; @@ -895,8 +895,8 @@ struct BlackBoxFuncCall { }; struct Poseidon2Permutation { - std::vector inputs; - std::vector outputs; + std::vector inputs; + std::vector outputs; uint32_t len; friend bool operator==(const Poseidon2Permutation&, const Poseidon2Permutation&); @@ -905,9 +905,9 @@ struct BlackBoxFuncCall { }; struct Sha256Compression { - std::vector inputs; - std::vector hash_values; - std::vector outputs; + std::vector inputs; + std::vector hash_values; + std::vector outputs; friend bool operator==(const Sha256Compression&, const Sha256Compression&); std::vector bincodeSerialize() const; @@ -955,8 +955,8 @@ struct BlockId { }; struct Expression { - std::vector> mul_terms; - std::vector> linear_combinations; + std::vector> mul_terms; + std::vector> linear_combinations; std::string q_c; friend bool operator==(const Expression&, const Expression&); @@ -967,7 +967,7 @@ struct Expression { struct BrilligInputs { struct Single { - Circuit::Expression value; + Program::Expression value; friend bool operator==(const Single&, const Single&); std::vector bincodeSerialize() const; @@ -975,7 +975,7 @@ struct BrilligInputs { }; struct Array { - std::vector value; + std::vector value; friend bool operator==(const Array&, const Array&); std::vector bincodeSerialize() const; @@ -983,7 +983,7 @@ struct BrilligInputs { }; struct MemoryArray { - Circuit::BlockId value; + Program::BlockId value; friend bool operator==(const MemoryArray&, const MemoryArray&); std::vector bincodeSerialize() const; @@ -1000,7 +1000,7 @@ struct BrilligInputs { struct BrilligOutputs { struct Simple { - Circuit::Witness value; + Program::Witness value; friend bool operator==(const Simple&, const Simple&); std::vector bincodeSerialize() const; @@ -1008,7 +1008,7 @@ struct BrilligOutputs { }; struct Array { - std::vector value; + std::vector value; friend bool operator==(const Array&, const Array&); std::vector bincodeSerialize() const; @@ -1023,10 +1023,10 @@ struct BrilligOutputs { }; struct Brillig { - std::vector inputs; - std::vector outputs; - std::vector bytecode; - std::optional predicate; + std::vector inputs; + std::vector outputs; + std::vector bytecode; + std::optional predicate; friend bool operator==(const Brillig&, const Brillig&); std::vector bincodeSerialize() const; @@ -1036,8 +1036,8 @@ struct Brillig { struct Directive { struct ToLeRadix { - Circuit::Expression a; - std::vector b; + Program::Expression a; + std::vector b; uint32_t radix; friend bool operator==(const ToLeRadix&, const ToLeRadix&); @@ -1053,9 +1053,9 @@ struct Directive { }; struct MemOp { - Circuit::Expression operation; - Circuit::Expression index; - Circuit::Expression value; + Program::Expression operation; + Program::Expression index; + Program::Expression value; friend bool operator==(const MemOp&, const MemOp&); std::vector bincodeSerialize() const; @@ -1065,7 +1065,7 @@ struct MemOp { struct Opcode { struct AssertZero { - Circuit::Expression value; + Program::Expression value; friend bool operator==(const AssertZero&, const AssertZero&); std::vector bincodeSerialize() const; @@ -1073,7 +1073,7 @@ struct Opcode { }; struct BlackBoxFuncCall { - Circuit::BlackBoxFuncCall value; + Program::BlackBoxFuncCall value; friend bool operator==(const BlackBoxFuncCall&, const BlackBoxFuncCall&); std::vector bincodeSerialize() const; @@ -1081,7 +1081,7 @@ struct Opcode { }; struct Directive { - Circuit::Directive value; + Program::Directive value; friend bool operator==(const Directive&, const Directive&); std::vector bincodeSerialize() const; @@ -1089,7 +1089,7 @@ struct Opcode { }; struct Brillig { - Circuit::Brillig value; + Program::Brillig value; friend bool operator==(const Brillig&, const Brillig&); std::vector bincodeSerialize() const; @@ -1097,9 +1097,9 @@ struct Opcode { }; struct MemoryOp { - Circuit::BlockId block_id; - Circuit::MemOp op; - std::optional predicate; + Program::BlockId block_id; + Program::MemOp op; + std::optional predicate; friend bool operator==(const MemoryOp&, const MemoryOp&); std::vector bincodeSerialize() const; @@ -1107,8 +1107,8 @@ struct Opcode { }; struct MemoryInit { - Circuit::BlockId block_id; - std::vector init; + Program::BlockId block_id; + std::vector init; friend bool operator==(const MemoryInit&, const MemoryInit&); std::vector bincodeSerialize() const; @@ -1117,8 +1117,8 @@ struct Opcode { struct Call { uint32_t id; - std::vector inputs; - std::vector outputs; + std::vector inputs; + std::vector outputs; friend bool operator==(const Call&, const Call&); std::vector bincodeSerialize() const; @@ -1182,7 +1182,7 @@ struct OpcodeLocation { }; struct PublicInputs { - std::vector value; + std::vector value; friend bool operator==(const PublicInputs&, const PublicInputs&); std::vector bincodeSerialize() const; @@ -1191,12 +1191,12 @@ struct PublicInputs { struct Circuit { uint32_t current_witness_index; - std::vector opcodes; - ExpressionWidth expression_width; - std::vector private_parameters; - PublicInputs public_parameters; - PublicInputs return_values; - std::vector> assert_messages; + std::vector opcodes; + Program::ExpressionWidth expression_width; + std::vector private_parameters; + Program::PublicInputs public_parameters; + Program::PublicInputs return_values; + std::vector> assert_messages; bool recursive; friend bool operator==(const Circuit&, const Circuit&); @@ -1204,9 +1204,17 @@ struct Circuit { static Circuit bincodeDeserialize(std::vector); }; -} // end of namespace Circuit +struct Program { + std::vector functions; -namespace Circuit { + friend bool operator==(const Program&, const Program&); + std::vector bincodeSerialize() const; + static Program bincodeDeserialize(std::vector); +}; + +} // end of namespace Program + +namespace Program { inline bool operator==(const BinaryFieldOp& lhs, const BinaryFieldOp& rhs) { @@ -1233,11 +1241,11 @@ inline BinaryFieldOp BinaryFieldOp::bincodeDeserialize(std::vector inpu return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryFieldOp& obj, Serializer& serializer) +void serde::Serializable::serialize(const Program::BinaryFieldOp& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); @@ -1246,16 +1254,16 @@ void serde::Serializable::serialize(const Circuit::Binar template <> template -Circuit::BinaryFieldOp serde::Deserializable::deserialize(Deserializer& deserializer) +Program::BinaryFieldOp serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Circuit::BinaryFieldOp obj; + Program::BinaryFieldOp obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryFieldOp::Add& lhs, const BinaryFieldOp::Add& rhs) { @@ -1279,23 +1287,23 @@ inline BinaryFieldOp::Add BinaryFieldOp::Add::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Circuit::BinaryFieldOp::Add& obj, +void serde::Serializable::serialize(const Program::BinaryFieldOp::Add& obj, Serializer& serializer) {} template <> template -Circuit::BinaryFieldOp::Add serde::Deserializable::deserialize(Deserializer& deserializer) +Program::BinaryFieldOp::Add serde::Deserializable::deserialize(Deserializer& deserializer) { - Circuit::BinaryFieldOp::Add obj; + Program::BinaryFieldOp::Add obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryFieldOp::Sub& lhs, const BinaryFieldOp::Sub& rhs) { @@ -1319,23 +1327,23 @@ inline BinaryFieldOp::Sub BinaryFieldOp::Sub::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Circuit::BinaryFieldOp::Sub& obj, +void serde::Serializable::serialize(const Program::BinaryFieldOp::Sub& obj, Serializer& serializer) {} template <> template -Circuit::BinaryFieldOp::Sub serde::Deserializable::deserialize(Deserializer& deserializer) +Program::BinaryFieldOp::Sub serde::Deserializable::deserialize(Deserializer& deserializer) { - Circuit::BinaryFieldOp::Sub obj; + Program::BinaryFieldOp::Sub obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryFieldOp::Mul& lhs, const BinaryFieldOp::Mul& rhs) { @@ -1359,23 +1367,23 @@ inline BinaryFieldOp::Mul BinaryFieldOp::Mul::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Circuit::BinaryFieldOp::Mul& obj, +void serde::Serializable::serialize(const Program::BinaryFieldOp::Mul& obj, Serializer& serializer) {} template <> template -Circuit::BinaryFieldOp::Mul serde::Deserializable::deserialize(Deserializer& deserializer) +Program::BinaryFieldOp::Mul serde::Deserializable::deserialize(Deserializer& deserializer) { - Circuit::BinaryFieldOp::Mul obj; + Program::BinaryFieldOp::Mul obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryFieldOp::Div& lhs, const BinaryFieldOp::Div& rhs) { @@ -1399,23 +1407,23 @@ inline BinaryFieldOp::Div BinaryFieldOp::Div::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Circuit::BinaryFieldOp::Div& obj, +void serde::Serializable::serialize(const Program::BinaryFieldOp::Div& obj, Serializer& serializer) {} template <> template -Circuit::BinaryFieldOp::Div serde::Deserializable::deserialize(Deserializer& deserializer) +Program::BinaryFieldOp::Div serde::Deserializable::deserialize(Deserializer& deserializer) { - Circuit::BinaryFieldOp::Div obj; + Program::BinaryFieldOp::Div obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryFieldOp::Equals& lhs, const BinaryFieldOp::Equals& rhs) { @@ -1439,24 +1447,24 @@ inline BinaryFieldOp::Equals BinaryFieldOp::Equals::bincodeDeserialize(std::vect return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryFieldOp::Equals& obj, +void serde::Serializable::serialize(const Program::BinaryFieldOp::Equals& obj, Serializer& serializer) {} template <> template -Circuit::BinaryFieldOp::Equals serde::Deserializable::deserialize( +Program::BinaryFieldOp::Equals serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BinaryFieldOp::Equals obj; + Program::BinaryFieldOp::Equals obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp& lhs, const BinaryIntOp& rhs) { @@ -1483,11 +1491,11 @@ inline BinaryIntOp BinaryIntOp::bincodeDeserialize(std::vector input) return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryIntOp& obj, Serializer& serializer) +void serde::Serializable::serialize(const Program::BinaryIntOp& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); @@ -1496,16 +1504,16 @@ void serde::Serializable::serialize(const Circuit::BinaryI template <> template -Circuit::BinaryIntOp serde::Deserializable::deserialize(Deserializer& deserializer) +Program::BinaryIntOp serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Circuit::BinaryIntOp obj; + Program::BinaryIntOp obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp::Add& lhs, const BinaryIntOp::Add& rhs) { @@ -1529,23 +1537,23 @@ inline BinaryIntOp::Add BinaryIntOp::Add::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Circuit::BinaryIntOp::Add& obj, +void serde::Serializable::serialize(const Program::BinaryIntOp::Add& obj, Serializer& serializer) {} template <> template -Circuit::BinaryIntOp::Add serde::Deserializable::deserialize(Deserializer& deserializer) +Program::BinaryIntOp::Add serde::Deserializable::deserialize(Deserializer& deserializer) { - Circuit::BinaryIntOp::Add obj; + Program::BinaryIntOp::Add obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp::Sub& lhs, const BinaryIntOp::Sub& rhs) { @@ -1569,23 +1577,23 @@ inline BinaryIntOp::Sub BinaryIntOp::Sub::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Circuit::BinaryIntOp::Sub& obj, +void serde::Serializable::serialize(const Program::BinaryIntOp::Sub& obj, Serializer& serializer) {} template <> template -Circuit::BinaryIntOp::Sub serde::Deserializable::deserialize(Deserializer& deserializer) +Program::BinaryIntOp::Sub serde::Deserializable::deserialize(Deserializer& deserializer) { - Circuit::BinaryIntOp::Sub obj; + Program::BinaryIntOp::Sub obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp::Mul& lhs, const BinaryIntOp::Mul& rhs) { @@ -1609,23 +1617,23 @@ inline BinaryIntOp::Mul BinaryIntOp::Mul::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Circuit::BinaryIntOp::Mul& obj, +void serde::Serializable::serialize(const Program::BinaryIntOp::Mul& obj, Serializer& serializer) {} template <> template -Circuit::BinaryIntOp::Mul serde::Deserializable::deserialize(Deserializer& deserializer) +Program::BinaryIntOp::Mul serde::Deserializable::deserialize(Deserializer& deserializer) { - Circuit::BinaryIntOp::Mul obj; + Program::BinaryIntOp::Mul obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp::SignedDiv& lhs, const BinaryIntOp::SignedDiv& rhs) { @@ -1649,24 +1657,24 @@ inline BinaryIntOp::SignedDiv BinaryIntOp::SignedDiv::bincodeDeserialize(std::ve return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryIntOp::SignedDiv& obj, +void serde::Serializable::serialize(const Program::BinaryIntOp::SignedDiv& obj, Serializer& serializer) {} template <> template -Circuit::BinaryIntOp::SignedDiv serde::Deserializable::deserialize( +Program::BinaryIntOp::SignedDiv serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BinaryIntOp::SignedDiv obj; + Program::BinaryIntOp::SignedDiv obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp::UnsignedDiv& lhs, const BinaryIntOp::UnsignedDiv& rhs) { @@ -1690,24 +1698,24 @@ inline BinaryIntOp::UnsignedDiv BinaryIntOp::UnsignedDiv::bincodeDeserialize(std return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryIntOp::UnsignedDiv& obj, +void serde::Serializable::serialize(const Program::BinaryIntOp::UnsignedDiv& obj, Serializer& serializer) {} template <> template -Circuit::BinaryIntOp::UnsignedDiv serde::Deserializable::deserialize( +Program::BinaryIntOp::UnsignedDiv serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BinaryIntOp::UnsignedDiv obj; + Program::BinaryIntOp::UnsignedDiv obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp::Equals& lhs, const BinaryIntOp::Equals& rhs) { @@ -1731,24 +1739,24 @@ inline BinaryIntOp::Equals BinaryIntOp::Equals::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Circuit::BinaryIntOp::Equals& obj, +void serde::Serializable::serialize(const Program::BinaryIntOp::Equals& obj, Serializer& serializer) {} template <> template -Circuit::BinaryIntOp::Equals serde::Deserializable::deserialize( +Program::BinaryIntOp::Equals serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BinaryIntOp::Equals obj; + Program::BinaryIntOp::Equals obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp::LessThan& lhs, const BinaryIntOp::LessThan& rhs) { @@ -1772,24 +1780,24 @@ inline BinaryIntOp::LessThan BinaryIntOp::LessThan::bincodeDeserialize(std::vect return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryIntOp::LessThan& obj, +void serde::Serializable::serialize(const Program::BinaryIntOp::LessThan& obj, Serializer& serializer) {} template <> template -Circuit::BinaryIntOp::LessThan serde::Deserializable::deserialize( +Program::BinaryIntOp::LessThan serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BinaryIntOp::LessThan obj; + Program::BinaryIntOp::LessThan obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp::LessThanEquals& lhs, const BinaryIntOp::LessThanEquals& rhs) { @@ -1813,24 +1821,24 @@ inline BinaryIntOp::LessThanEquals BinaryIntOp::LessThanEquals::bincodeDeseriali return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize( - const Circuit::BinaryIntOp::LessThanEquals& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Program::BinaryIntOp::LessThanEquals& obj, Serializer& serializer) {} template <> template -Circuit::BinaryIntOp::LessThanEquals serde::Deserializable::deserialize( +Program::BinaryIntOp::LessThanEquals serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BinaryIntOp::LessThanEquals obj; + Program::BinaryIntOp::LessThanEquals obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp::And& lhs, const BinaryIntOp::And& rhs) { @@ -1854,23 +1862,23 @@ inline BinaryIntOp::And BinaryIntOp::And::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Circuit::BinaryIntOp::And& obj, +void serde::Serializable::serialize(const Program::BinaryIntOp::And& obj, Serializer& serializer) {} template <> template -Circuit::BinaryIntOp::And serde::Deserializable::deserialize(Deserializer& deserializer) +Program::BinaryIntOp::And serde::Deserializable::deserialize(Deserializer& deserializer) { - Circuit::BinaryIntOp::And obj; + Program::BinaryIntOp::And obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp::Or& lhs, const BinaryIntOp::Or& rhs) { @@ -1894,23 +1902,23 @@ inline BinaryIntOp::Or BinaryIntOp::Or::bincodeDeserialize(std::vector return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryIntOp::Or& obj, +void serde::Serializable::serialize(const Program::BinaryIntOp::Or& obj, Serializer& serializer) {} template <> template -Circuit::BinaryIntOp::Or serde::Deserializable::deserialize(Deserializer& deserializer) +Program::BinaryIntOp::Or serde::Deserializable::deserialize(Deserializer& deserializer) { - Circuit::BinaryIntOp::Or obj; + Program::BinaryIntOp::Or obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp::Xor& lhs, const BinaryIntOp::Xor& rhs) { @@ -1934,23 +1942,23 @@ inline BinaryIntOp::Xor BinaryIntOp::Xor::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Circuit::BinaryIntOp::Xor& obj, +void serde::Serializable::serialize(const Program::BinaryIntOp::Xor& obj, Serializer& serializer) {} template <> template -Circuit::BinaryIntOp::Xor serde::Deserializable::deserialize(Deserializer& deserializer) +Program::BinaryIntOp::Xor serde::Deserializable::deserialize(Deserializer& deserializer) { - Circuit::BinaryIntOp::Xor obj; + Program::BinaryIntOp::Xor obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp::Shl& lhs, const BinaryIntOp::Shl& rhs) { @@ -1974,23 +1982,23 @@ inline BinaryIntOp::Shl BinaryIntOp::Shl::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Circuit::BinaryIntOp::Shl& obj, +void serde::Serializable::serialize(const Program::BinaryIntOp::Shl& obj, Serializer& serializer) {} template <> template -Circuit::BinaryIntOp::Shl serde::Deserializable::deserialize(Deserializer& deserializer) +Program::BinaryIntOp::Shl serde::Deserializable::deserialize(Deserializer& deserializer) { - Circuit::BinaryIntOp::Shl obj; + Program::BinaryIntOp::Shl obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp::Shr& lhs, const BinaryIntOp::Shr& rhs) { @@ -2014,23 +2022,23 @@ inline BinaryIntOp::Shr BinaryIntOp::Shr::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Circuit::BinaryIntOp::Shr& obj, +void serde::Serializable::serialize(const Program::BinaryIntOp::Shr& obj, Serializer& serializer) {} template <> template -Circuit::BinaryIntOp::Shr serde::Deserializable::deserialize(Deserializer& deserializer) +Program::BinaryIntOp::Shr serde::Deserializable::deserialize(Deserializer& deserializer) { - Circuit::BinaryIntOp::Shr obj; + Program::BinaryIntOp::Shr obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall& lhs, const BlackBoxFuncCall& rhs) { @@ -2057,11 +2065,11 @@ inline BlackBoxFuncCall BlackBoxFuncCall::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall& obj, +void serde::Serializable::serialize(const Program::BlackBoxFuncCall& obj, Serializer& serializer) { serializer.increase_container_depth(); @@ -2071,16 +2079,16 @@ void serde::Serializable::serialize(const Circuit::Bl template <> template -Circuit::BlackBoxFuncCall serde::Deserializable::deserialize(Deserializer& deserializer) +Program::BlackBoxFuncCall serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Circuit::BlackBoxFuncCall obj; + Program::BlackBoxFuncCall obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::AND& lhs, const BlackBoxFuncCall::AND& rhs) { @@ -2113,11 +2121,11 @@ inline BlackBoxFuncCall::AND BlackBoxFuncCall::AND::bincodeDeserialize(std::vect return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::AND& obj, +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::AND& obj, Serializer& serializer) { serde::Serializable::serialize(obj.lhs, serializer); @@ -2127,17 +2135,17 @@ void serde::Serializable::serialize(const Circui template <> template -Circuit::BlackBoxFuncCall::AND serde::Deserializable::deserialize( +Program::BlackBoxFuncCall::AND serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxFuncCall::AND obj; + Program::BlackBoxFuncCall::AND obj; obj.lhs = serde::Deserializable::deserialize(deserializer); obj.rhs = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::XOR& lhs, const BlackBoxFuncCall::XOR& rhs) { @@ -2170,11 +2178,11 @@ inline BlackBoxFuncCall::XOR BlackBoxFuncCall::XOR::bincodeDeserialize(std::vect return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::XOR& obj, +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::XOR& obj, Serializer& serializer) { serde::Serializable::serialize(obj.lhs, serializer); @@ -2184,17 +2192,17 @@ void serde::Serializable::serialize(const Circui template <> template -Circuit::BlackBoxFuncCall::XOR serde::Deserializable::deserialize( +Program::BlackBoxFuncCall::XOR serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxFuncCall::XOR obj; + Program::BlackBoxFuncCall::XOR obj; obj.lhs = serde::Deserializable::deserialize(deserializer); obj.rhs = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::RANGE& lhs, const BlackBoxFuncCall::RANGE& rhs) { @@ -2221,11 +2229,11 @@ inline BlackBoxFuncCall::RANGE BlackBoxFuncCall::RANGE::bincodeDeserialize(std:: return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::RANGE& obj, +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::RANGE& obj, Serializer& serializer) { serde::Serializable::serialize(obj.input, serializer); @@ -2233,15 +2241,15 @@ void serde::Serializable::serialize(const Circ template <> template -Circuit::BlackBoxFuncCall::RANGE serde::Deserializable::deserialize( +Program::BlackBoxFuncCall::RANGE serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxFuncCall::RANGE obj; + Program::BlackBoxFuncCall::RANGE obj; obj.input = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::SHA256& lhs, const BlackBoxFuncCall::SHA256& rhs) { @@ -2271,11 +2279,11 @@ inline BlackBoxFuncCall::SHA256 BlackBoxFuncCall::SHA256::bincodeDeserialize(std return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::SHA256& obj, +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::SHA256& obj, Serializer& serializer) { serde::Serializable::serialize(obj.inputs, serializer); @@ -2284,16 +2292,16 @@ void serde::Serializable::serialize(const Cir template <> template -Circuit::BlackBoxFuncCall::SHA256 serde::Deserializable::deserialize( +Program::BlackBoxFuncCall::SHA256 serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxFuncCall::SHA256 obj; + Program::BlackBoxFuncCall::SHA256 obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::Blake2s& lhs, const BlackBoxFuncCall::Blake2s& rhs) { @@ -2323,11 +2331,11 @@ inline BlackBoxFuncCall::Blake2s BlackBoxFuncCall::Blake2s::bincodeDeserialize(s return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::Blake2s& obj, +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::Blake2s& obj, Serializer& serializer) { serde::Serializable::serialize(obj.inputs, serializer); @@ -2336,16 +2344,16 @@ void serde::Serializable::serialize(const Ci template <> template -Circuit::BlackBoxFuncCall::Blake2s serde::Deserializable::deserialize( +Program::BlackBoxFuncCall::Blake2s serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxFuncCall::Blake2s obj; + Program::BlackBoxFuncCall::Blake2s obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::Blake3& lhs, const BlackBoxFuncCall::Blake3& rhs) { @@ -2375,11 +2383,11 @@ inline BlackBoxFuncCall::Blake3 BlackBoxFuncCall::Blake3::bincodeDeserialize(std return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::Blake3& obj, +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::Blake3& obj, Serializer& serializer) { serde::Serializable::serialize(obj.inputs, serializer); @@ -2388,16 +2396,16 @@ void serde::Serializable::serialize(const Cir template <> template -Circuit::BlackBoxFuncCall::Blake3 serde::Deserializable::deserialize( +Program::BlackBoxFuncCall::Blake3 serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxFuncCall::Blake3 obj; + Program::BlackBoxFuncCall::Blake3 obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::SchnorrVerify& lhs, const BlackBoxFuncCall::SchnorrVerify& rhs) { @@ -2436,12 +2444,12 @@ inline BlackBoxFuncCall::SchnorrVerify BlackBoxFuncCall::SchnorrVerify::bincodeD return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize( - const Circuit::BlackBoxFuncCall::SchnorrVerify& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Program::BlackBoxFuncCall::SchnorrVerify& obj, Serializer& serializer) { serde::Serializable::serialize(obj.public_key_x, serializer); serde::Serializable::serialize(obj.public_key_y, serializer); @@ -2452,10 +2460,10 @@ void serde::Serializable::serialize( template <> template -Circuit::BlackBoxFuncCall::SchnorrVerify serde::Deserializable::deserialize( +Program::BlackBoxFuncCall::SchnorrVerify serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxFuncCall::SchnorrVerify obj; + Program::BlackBoxFuncCall::SchnorrVerify obj; obj.public_key_x = serde::Deserializable::deserialize(deserializer); obj.public_key_y = serde::Deserializable::deserialize(deserializer); obj.signature = serde::Deserializable::deserialize(deserializer); @@ -2464,7 +2472,7 @@ Circuit::BlackBoxFuncCall::SchnorrVerify serde::Deserializable template -void serde::Serializable::serialize( - const Circuit::BlackBoxFuncCall::PedersenCommitment& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Program::BlackBoxFuncCall::PedersenCommitment& obj, Serializer& serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.domain_separator, serializer); @@ -2512,17 +2520,17 @@ void serde::Serializable::seriali template <> template -Circuit::BlackBoxFuncCall::PedersenCommitment serde::Deserializable< - Circuit::BlackBoxFuncCall::PedersenCommitment>::deserialize(Deserializer& deserializer) +Program::BlackBoxFuncCall::PedersenCommitment serde::Deserializable< + Program::BlackBoxFuncCall::PedersenCommitment>::deserialize(Deserializer& deserializer) { - Circuit::BlackBoxFuncCall::PedersenCommitment obj; + Program::BlackBoxFuncCall::PedersenCommitment obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.domain_separator = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::PedersenHash& lhs, const BlackBoxFuncCall::PedersenHash& rhs) { @@ -2555,12 +2563,12 @@ inline BlackBoxFuncCall::PedersenHash BlackBoxFuncCall::PedersenHash::bincodeDes return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize( - const Circuit::BlackBoxFuncCall::PedersenHash& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Program::BlackBoxFuncCall::PedersenHash& obj, Serializer& serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.domain_separator, serializer); @@ -2569,17 +2577,17 @@ void serde::Serializable::serialize( template <> template -Circuit::BlackBoxFuncCall::PedersenHash serde::Deserializable::deserialize( +Program::BlackBoxFuncCall::PedersenHash serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxFuncCall::PedersenHash obj; + Program::BlackBoxFuncCall::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 { +namespace Program { inline bool operator==(const BlackBoxFuncCall::EcdsaSecp256k1& lhs, const BlackBoxFuncCall::EcdsaSecp256k1& rhs) { @@ -2618,12 +2626,12 @@ inline BlackBoxFuncCall::EcdsaSecp256k1 BlackBoxFuncCall::EcdsaSecp256k1::bincod return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize( - const Circuit::BlackBoxFuncCall::EcdsaSecp256k1& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Program::BlackBoxFuncCall::EcdsaSecp256k1& obj, Serializer& serializer) { serde::Serializable::serialize(obj.public_key_x, serializer); serde::Serializable::serialize(obj.public_key_y, serializer); @@ -2634,10 +2642,10 @@ void serde::Serializable::serialize( template <> template -Circuit::BlackBoxFuncCall::EcdsaSecp256k1 serde::Deserializable::deserialize( +Program::BlackBoxFuncCall::EcdsaSecp256k1 serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxFuncCall::EcdsaSecp256k1 obj; + Program::BlackBoxFuncCall::EcdsaSecp256k1 obj; obj.public_key_x = serde::Deserializable::deserialize(deserializer); obj.public_key_y = serde::Deserializable::deserialize(deserializer); obj.signature = serde::Deserializable::deserialize(deserializer); @@ -2646,7 +2654,7 @@ Circuit::BlackBoxFuncCall::EcdsaSecp256k1 serde::Deserializable template -void serde::Serializable::serialize( - const Circuit::BlackBoxFuncCall::EcdsaSecp256r1& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Program::BlackBoxFuncCall::EcdsaSecp256r1& obj, Serializer& serializer) { serde::Serializable::serialize(obj.public_key_x, serializer); serde::Serializable::serialize(obj.public_key_y, serializer); @@ -2701,10 +2709,10 @@ void serde::Serializable::serialize( template <> template -Circuit::BlackBoxFuncCall::EcdsaSecp256r1 serde::Deserializable::deserialize( +Program::BlackBoxFuncCall::EcdsaSecp256r1 serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxFuncCall::EcdsaSecp256r1 obj; + Program::BlackBoxFuncCall::EcdsaSecp256r1 obj; obj.public_key_x = serde::Deserializable::deserialize(deserializer); obj.public_key_y = serde::Deserializable::deserialize(deserializer); obj.signature = serde::Deserializable::deserialize(deserializer); @@ -2713,7 +2721,7 @@ Circuit::BlackBoxFuncCall::EcdsaSecp256r1 serde::Deserializable template -void serde::Serializable::serialize( - const Circuit::BlackBoxFuncCall::FixedBaseScalarMul& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Program::BlackBoxFuncCall::FixedBaseScalarMul& obj, Serializer& serializer) { serde::Serializable::serialize(obj.low, serializer); serde::Serializable::serialize(obj.high, serializer); @@ -2761,17 +2769,17 @@ void serde::Serializable::seriali template <> template -Circuit::BlackBoxFuncCall::FixedBaseScalarMul serde::Deserializable< - Circuit::BlackBoxFuncCall::FixedBaseScalarMul>::deserialize(Deserializer& deserializer) +Program::BlackBoxFuncCall::FixedBaseScalarMul serde::Deserializable< + Program::BlackBoxFuncCall::FixedBaseScalarMul>::deserialize(Deserializer& deserializer) { - Circuit::BlackBoxFuncCall::FixedBaseScalarMul obj; + Program::BlackBoxFuncCall::FixedBaseScalarMul obj; obj.low = serde::Deserializable::deserialize(deserializer); obj.high = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::EmbeddedCurveAdd& lhs, const BlackBoxFuncCall::EmbeddedCurveAdd& rhs) { @@ -2811,12 +2819,12 @@ inline BlackBoxFuncCall::EmbeddedCurveAdd BlackBoxFuncCall::EmbeddedCurveAdd::bi return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize( - const Circuit::BlackBoxFuncCall::EmbeddedCurveAdd& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Program::BlackBoxFuncCall::EmbeddedCurveAdd& obj, Serializer& serializer) { serde::Serializable::serialize(obj.input1_x, serializer); serde::Serializable::serialize(obj.input1_y, serializer); @@ -2827,10 +2835,10 @@ void serde::Serializable::serialize template <> template -Circuit::BlackBoxFuncCall::EmbeddedCurveAdd serde::Deserializable< - Circuit::BlackBoxFuncCall::EmbeddedCurveAdd>::deserialize(Deserializer& deserializer) +Program::BlackBoxFuncCall::EmbeddedCurveAdd serde::Deserializable< + Program::BlackBoxFuncCall::EmbeddedCurveAdd>::deserialize(Deserializer& deserializer) { - Circuit::BlackBoxFuncCall::EmbeddedCurveAdd obj; + Program::BlackBoxFuncCall::EmbeddedCurveAdd obj; obj.input1_x = serde::Deserializable::deserialize(deserializer); obj.input1_y = serde::Deserializable::deserialize(deserializer); obj.input2_x = serde::Deserializable::deserialize(deserializer); @@ -2839,7 +2847,7 @@ Circuit::BlackBoxFuncCall::EmbeddedCurveAdd serde::Deserializable< return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::Keccak256& lhs, const BlackBoxFuncCall::Keccak256& rhs) { @@ -2869,12 +2877,12 @@ inline BlackBoxFuncCall::Keccak256 BlackBoxFuncCall::Keccak256::bincodeDeseriali return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize( - const Circuit::BlackBoxFuncCall::Keccak256& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Program::BlackBoxFuncCall::Keccak256& obj, Serializer& serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.outputs, serializer); @@ -2882,16 +2890,16 @@ void serde::Serializable::serialize( template <> template -Circuit::BlackBoxFuncCall::Keccak256 serde::Deserializable::deserialize( +Program::BlackBoxFuncCall::Keccak256 serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxFuncCall::Keccak256 obj; + Program::BlackBoxFuncCall::Keccak256 obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::Keccak256VariableLength& lhs, const BlackBoxFuncCall::Keccak256VariableLength& rhs) @@ -2926,12 +2934,12 @@ inline BlackBoxFuncCall::Keccak256VariableLength BlackBoxFuncCall::Keccak256Vari return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize( - const Circuit::BlackBoxFuncCall::Keccak256VariableLength& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Program::BlackBoxFuncCall::Keccak256VariableLength& obj, Serializer& serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.var_message_size, serializer); @@ -2940,17 +2948,17 @@ void serde::Serializable::se template <> template -Circuit::BlackBoxFuncCall::Keccak256VariableLength serde::Deserializable< - Circuit::BlackBoxFuncCall::Keccak256VariableLength>::deserialize(Deserializer& deserializer) +Program::BlackBoxFuncCall::Keccak256VariableLength serde::Deserializable< + Program::BlackBoxFuncCall::Keccak256VariableLength>::deserialize(Deserializer& deserializer) { - Circuit::BlackBoxFuncCall::Keccak256VariableLength obj; + Program::BlackBoxFuncCall::Keccak256VariableLength obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.var_message_size = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::Keccakf1600& lhs, const BlackBoxFuncCall::Keccakf1600& rhs) { @@ -2980,12 +2988,12 @@ inline BlackBoxFuncCall::Keccakf1600 BlackBoxFuncCall::Keccakf1600::bincodeDeser return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize( - const Circuit::BlackBoxFuncCall::Keccakf1600& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Program::BlackBoxFuncCall::Keccakf1600& obj, Serializer& serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.outputs, serializer); @@ -2993,16 +3001,16 @@ void serde::Serializable::serialize( template <> template -Circuit::BlackBoxFuncCall::Keccakf1600 serde::Deserializable::deserialize( +Program::BlackBoxFuncCall::Keccakf1600 serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxFuncCall::Keccakf1600 obj; + Program::BlackBoxFuncCall::Keccakf1600 obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::RecursiveAggregation& lhs, const BlackBoxFuncCall::RecursiveAggregation& rhs) @@ -3040,12 +3048,12 @@ inline BlackBoxFuncCall::RecursiveAggregation BlackBoxFuncCall::RecursiveAggrega return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize( - const Circuit::BlackBoxFuncCall::RecursiveAggregation& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Program::BlackBoxFuncCall::RecursiveAggregation& obj, Serializer& serializer) { serde::Serializable::serialize(obj.verification_key, serializer); serde::Serializable::serialize(obj.proof, serializer); @@ -3055,10 +3063,10 @@ void serde::Serializable::seria template <> template -Circuit::BlackBoxFuncCall::RecursiveAggregation serde::Deserializable< - Circuit::BlackBoxFuncCall::RecursiveAggregation>::deserialize(Deserializer& deserializer) +Program::BlackBoxFuncCall::RecursiveAggregation serde::Deserializable< + Program::BlackBoxFuncCall::RecursiveAggregation>::deserialize(Deserializer& deserializer) { - Circuit::BlackBoxFuncCall::RecursiveAggregation obj; + Program::BlackBoxFuncCall::RecursiveAggregation obj; obj.verification_key = serde::Deserializable::deserialize(deserializer); obj.proof = serde::Deserializable::deserialize(deserializer); obj.public_inputs = serde::Deserializable::deserialize(deserializer); @@ -3066,7 +3074,7 @@ Circuit::BlackBoxFuncCall::RecursiveAggregation serde::Deserializable< return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::BigIntAdd& lhs, const BlackBoxFuncCall::BigIntAdd& rhs) { @@ -3099,12 +3107,12 @@ inline BlackBoxFuncCall::BigIntAdd BlackBoxFuncCall::BigIntAdd::bincodeDeseriali return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize( - const Circuit::BlackBoxFuncCall::BigIntAdd& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Program::BlackBoxFuncCall::BigIntAdd& obj, Serializer& serializer) { serde::Serializable::serialize(obj.lhs, serializer); serde::Serializable::serialize(obj.rhs, serializer); @@ -3113,17 +3121,17 @@ void serde::Serializable::serialize( template <> template -Circuit::BlackBoxFuncCall::BigIntAdd serde::Deserializable::deserialize( +Program::BlackBoxFuncCall::BigIntAdd serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxFuncCall::BigIntAdd obj; + Program::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 { +namespace Program { inline bool operator==(const BlackBoxFuncCall::BigIntSub& lhs, const BlackBoxFuncCall::BigIntSub& rhs) { @@ -3156,12 +3164,12 @@ inline BlackBoxFuncCall::BigIntSub BlackBoxFuncCall::BigIntSub::bincodeDeseriali return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize( - const Circuit::BlackBoxFuncCall::BigIntSub& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Program::BlackBoxFuncCall::BigIntSub& obj, Serializer& serializer) { serde::Serializable::serialize(obj.lhs, serializer); serde::Serializable::serialize(obj.rhs, serializer); @@ -3170,17 +3178,17 @@ void serde::Serializable::serialize( template <> template -Circuit::BlackBoxFuncCall::BigIntSub serde::Deserializable::deserialize( +Program::BlackBoxFuncCall::BigIntSub serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxFuncCall::BigIntSub obj; + Program::BlackBoxFuncCall::BigIntSub obj; obj.lhs = serde::Deserializable::deserialize(deserializer); obj.rhs = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::BigIntMul& lhs, const BlackBoxFuncCall::BigIntMul& rhs) { @@ -3213,12 +3221,12 @@ inline BlackBoxFuncCall::BigIntMul BlackBoxFuncCall::BigIntMul::bincodeDeseriali return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize( - const Circuit::BlackBoxFuncCall::BigIntMul& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Program::BlackBoxFuncCall::BigIntMul& obj, Serializer& serializer) { serde::Serializable::serialize(obj.lhs, serializer); serde::Serializable::serialize(obj.rhs, serializer); @@ -3227,17 +3235,17 @@ void serde::Serializable::serialize( template <> template -Circuit::BlackBoxFuncCall::BigIntMul serde::Deserializable::deserialize( +Program::BlackBoxFuncCall::BigIntMul serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxFuncCall::BigIntMul obj; + Program::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 { +namespace Program { inline bool operator==(const BlackBoxFuncCall::BigIntDiv& lhs, const BlackBoxFuncCall::BigIntDiv& rhs) { @@ -3270,12 +3278,12 @@ inline BlackBoxFuncCall::BigIntDiv BlackBoxFuncCall::BigIntDiv::bincodeDeseriali return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize( - const Circuit::BlackBoxFuncCall::BigIntDiv& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Program::BlackBoxFuncCall::BigIntDiv& obj, Serializer& serializer) { serde::Serializable::serialize(obj.lhs, serializer); serde::Serializable::serialize(obj.rhs, serializer); @@ -3284,17 +3292,17 @@ void serde::Serializable::serialize( template <> template -Circuit::BlackBoxFuncCall::BigIntDiv serde::Deserializable::deserialize( +Program::BlackBoxFuncCall::BigIntDiv serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxFuncCall::BigIntDiv obj; + Program::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 { +namespace Program { inline bool operator==(const BlackBoxFuncCall::BigIntFromLeBytes& lhs, const BlackBoxFuncCall::BigIntFromLeBytes& rhs) { @@ -3328,12 +3336,12 @@ inline BlackBoxFuncCall::BigIntFromLeBytes BlackBoxFuncCall::BigIntFromLeBytes:: return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize( - const Circuit::BlackBoxFuncCall::BigIntFromLeBytes& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Program::BlackBoxFuncCall::BigIntFromLeBytes& obj, Serializer& serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.modulus, serializer); @@ -3342,17 +3350,17 @@ void serde::Serializable::serializ template <> template -Circuit::BlackBoxFuncCall::BigIntFromLeBytes serde::Deserializable< - Circuit::BlackBoxFuncCall::BigIntFromLeBytes>::deserialize(Deserializer& deserializer) +Program::BlackBoxFuncCall::BigIntFromLeBytes serde::Deserializable< + Program::BlackBoxFuncCall::BigIntFromLeBytes>::deserialize(Deserializer& deserializer) { - Circuit::BlackBoxFuncCall::BigIntFromLeBytes obj; + Program::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 { +namespace Program { inline bool operator==(const BlackBoxFuncCall::BigIntToLeBytes& lhs, const BlackBoxFuncCall::BigIntToLeBytes& rhs) { @@ -3383,12 +3391,12 @@ inline BlackBoxFuncCall::BigIntToLeBytes BlackBoxFuncCall::BigIntToLeBytes::binc return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize( - const Circuit::BlackBoxFuncCall::BigIntToLeBytes& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Program::BlackBoxFuncCall::BigIntToLeBytes& obj, Serializer& serializer) { serde::Serializable::serialize(obj.input, serializer); serde::Serializable::serialize(obj.outputs, serializer); @@ -3396,16 +3404,16 @@ void serde::Serializable::serialize( template <> template -Circuit::BlackBoxFuncCall::BigIntToLeBytes serde::Deserializable< - Circuit::BlackBoxFuncCall::BigIntToLeBytes>::deserialize(Deserializer& deserializer) +Program::BlackBoxFuncCall::BigIntToLeBytes serde::Deserializable< + Program::BlackBoxFuncCall::BigIntToLeBytes>::deserialize(Deserializer& deserializer) { - Circuit::BlackBoxFuncCall::BigIntToLeBytes obj; + Program::BlackBoxFuncCall::BigIntToLeBytes obj; obj.input = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::Poseidon2Permutation& lhs, const BlackBoxFuncCall::Poseidon2Permutation& rhs) @@ -3440,12 +3448,12 @@ inline BlackBoxFuncCall::Poseidon2Permutation BlackBoxFuncCall::Poseidon2Permuta return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize( - const Circuit::BlackBoxFuncCall::Poseidon2Permutation& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Program::BlackBoxFuncCall::Poseidon2Permutation& obj, Serializer& serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.outputs, serializer); @@ -3454,17 +3462,17 @@ void serde::Serializable::seria template <> template -Circuit::BlackBoxFuncCall::Poseidon2Permutation serde::Deserializable< - Circuit::BlackBoxFuncCall::Poseidon2Permutation>::deserialize(Deserializer& deserializer) +Program::BlackBoxFuncCall::Poseidon2Permutation serde::Deserializable< + Program::BlackBoxFuncCall::Poseidon2Permutation>::deserialize(Deserializer& deserializer) { - Circuit::BlackBoxFuncCall::Poseidon2Permutation obj; + Program::BlackBoxFuncCall::Poseidon2Permutation obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); obj.len = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::Sha256Compression& lhs, const BlackBoxFuncCall::Sha256Compression& rhs) { @@ -3498,12 +3506,12 @@ inline BlackBoxFuncCall::Sha256Compression BlackBoxFuncCall::Sha256Compression:: return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize( - const Circuit::BlackBoxFuncCall::Sha256Compression& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Program::BlackBoxFuncCall::Sha256Compression& obj, Serializer& serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.hash_values, serializer); @@ -3512,17 +3520,17 @@ void serde::Serializable::serializ template <> template -Circuit::BlackBoxFuncCall::Sha256Compression serde::Deserializable< - Circuit::BlackBoxFuncCall::Sha256Compression>::deserialize(Deserializer& deserializer) +Program::BlackBoxFuncCall::Sha256Compression serde::Deserializable< + Program::BlackBoxFuncCall::Sha256Compression>::deserialize(Deserializer& deserializer) { - Circuit::BlackBoxFuncCall::Sha256Compression obj; + Program::BlackBoxFuncCall::Sha256Compression obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.hash_values = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxOp& lhs, const BlackBoxOp& rhs) { @@ -3549,11 +3557,11 @@ inline BlackBoxOp BlackBoxOp::bincodeDeserialize(std::vector input) return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp& obj, Serializer& serializer) +void serde::Serializable::serialize(const Program::BlackBoxOp& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); @@ -3562,16 +3570,16 @@ void serde::Serializable::serialize(const Circuit::BlackBox template <> template -Circuit::BlackBoxOp serde::Deserializable::deserialize(Deserializer& deserializer) +Program::BlackBoxOp serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Circuit::BlackBoxOp obj; + Program::BlackBoxOp obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxOp::Sha256& lhs, const BlackBoxOp::Sha256& rhs) { @@ -3601,11 +3609,11 @@ inline BlackBoxOp::Sha256 BlackBoxOp::Sha256::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::Sha256& obj, +void serde::Serializable::serialize(const Program::BlackBoxOp::Sha256& obj, Serializer& serializer) { serde::Serializable::serialize(obj.message, serializer); @@ -3614,15 +3622,15 @@ void serde::Serializable::serialize(const Circuit:: template <> template -Circuit::BlackBoxOp::Sha256 serde::Deserializable::deserialize(Deserializer& deserializer) +Program::BlackBoxOp::Sha256 serde::Deserializable::deserialize(Deserializer& deserializer) { - Circuit::BlackBoxOp::Sha256 obj; + Program::BlackBoxOp::Sha256 obj; obj.message = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxOp::Blake2s& lhs, const BlackBoxOp::Blake2s& rhs) { @@ -3652,11 +3660,11 @@ inline BlackBoxOp::Blake2s BlackBoxOp::Blake2s::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::Blake2s& obj, +void serde::Serializable::serialize(const Program::BlackBoxOp::Blake2s& obj, Serializer& serializer) { serde::Serializable::serialize(obj.message, serializer); @@ -3665,16 +3673,16 @@ void serde::Serializable::serialize(const Circuit: template <> template -Circuit::BlackBoxOp::Blake2s serde::Deserializable::deserialize( +Program::BlackBoxOp::Blake2s serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxOp::Blake2s obj; + Program::BlackBoxOp::Blake2s obj; obj.message = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxOp::Blake3& lhs, const BlackBoxOp::Blake3& rhs) { @@ -3704,11 +3712,11 @@ inline BlackBoxOp::Blake3 BlackBoxOp::Blake3::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::Blake3& obj, +void serde::Serializable::serialize(const Program::BlackBoxOp::Blake3& obj, Serializer& serializer) { serde::Serializable::serialize(obj.message, serializer); @@ -3717,15 +3725,15 @@ void serde::Serializable::serialize(const Circuit:: template <> template -Circuit::BlackBoxOp::Blake3 serde::Deserializable::deserialize(Deserializer& deserializer) +Program::BlackBoxOp::Blake3 serde::Deserializable::deserialize(Deserializer& deserializer) { - Circuit::BlackBoxOp::Blake3 obj; + Program::BlackBoxOp::Blake3 obj; obj.message = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxOp::Keccak256& lhs, const BlackBoxOp::Keccak256& rhs) { @@ -3755,11 +3763,11 @@ inline BlackBoxOp::Keccak256 BlackBoxOp::Keccak256::bincodeDeserialize(std::vect return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::Keccak256& obj, +void serde::Serializable::serialize(const Program::BlackBoxOp::Keccak256& obj, Serializer& serializer) { serde::Serializable::serialize(obj.message, serializer); @@ -3768,16 +3776,16 @@ void serde::Serializable::serialize(const Circui template <> template -Circuit::BlackBoxOp::Keccak256 serde::Deserializable::deserialize( +Program::BlackBoxOp::Keccak256 serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxOp::Keccak256 obj; + Program::BlackBoxOp::Keccak256 obj; obj.message = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxOp::Keccakf1600& lhs, const BlackBoxOp::Keccakf1600& rhs) { @@ -3807,11 +3815,11 @@ inline BlackBoxOp::Keccakf1600 BlackBoxOp::Keccakf1600::bincodeDeserialize(std:: return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::Keccakf1600& obj, +void serde::Serializable::serialize(const Program::BlackBoxOp::Keccakf1600& obj, Serializer& serializer) { serde::Serializable::serialize(obj.message, serializer); @@ -3820,16 +3828,16 @@ void serde::Serializable::serialize(const Circ template <> template -Circuit::BlackBoxOp::Keccakf1600 serde::Deserializable::deserialize( +Program::BlackBoxOp::Keccakf1600 serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxOp::Keccakf1600 obj; + Program::BlackBoxOp::Keccakf1600 obj; obj.message = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxOp::EcdsaSecp256k1& lhs, const BlackBoxOp::EcdsaSecp256k1& rhs) { @@ -3868,11 +3876,11 @@ inline BlackBoxOp::EcdsaSecp256k1 BlackBoxOp::EcdsaSecp256k1::bincodeDeserialize return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::EcdsaSecp256k1& obj, +void serde::Serializable::serialize(const Program::BlackBoxOp::EcdsaSecp256k1& obj, Serializer& serializer) { serde::Serializable::serialize(obj.hashed_msg, serializer); @@ -3884,10 +3892,10 @@ void serde::Serializable::serialize(const C template <> template -Circuit::BlackBoxOp::EcdsaSecp256k1 serde::Deserializable::deserialize( +Program::BlackBoxOp::EcdsaSecp256k1 serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxOp::EcdsaSecp256k1 obj; + Program::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); @@ -3896,7 +3904,7 @@ Circuit::BlackBoxOp::EcdsaSecp256k1 serde::Deserializable template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::EcdsaSecp256r1& obj, +void serde::Serializable::serialize(const Program::BlackBoxOp::EcdsaSecp256r1& obj, Serializer& serializer) { serde::Serializable::serialize(obj.hashed_msg, serializer); @@ -3951,10 +3959,10 @@ void serde::Serializable::serialize(const C template <> template -Circuit::BlackBoxOp::EcdsaSecp256r1 serde::Deserializable::deserialize( +Program::BlackBoxOp::EcdsaSecp256r1 serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxOp::EcdsaSecp256r1 obj; + Program::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); @@ -3963,7 +3971,7 @@ Circuit::BlackBoxOp::EcdsaSecp256r1 serde::Deserializable template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::SchnorrVerify& obj, +void serde::Serializable::serialize(const Program::BlackBoxOp::SchnorrVerify& obj, Serializer& serializer) { serde::Serializable::serialize(obj.public_key_x, serializer); @@ -4018,10 +4026,10 @@ void serde::Serializable::serialize(const Ci template <> template -Circuit::BlackBoxOp::SchnorrVerify serde::Deserializable::deserialize( +Program::BlackBoxOp::SchnorrVerify serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxOp::SchnorrVerify obj; + Program::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); @@ -4030,7 +4038,7 @@ Circuit::BlackBoxOp::SchnorrVerify serde::Deserializable template -void serde::Serializable::serialize( - const Circuit::BlackBoxOp::PedersenCommitment& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Program::BlackBoxOp::PedersenCommitment& obj, Serializer& serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.domain_separator, serializer); @@ -4077,17 +4085,17 @@ void serde::Serializable::serialize( template <> template -Circuit::BlackBoxOp::PedersenCommitment serde::Deserializable::deserialize( +Program::BlackBoxOp::PedersenCommitment serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxOp::PedersenCommitment obj; + Program::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 { +namespace Program { inline bool operator==(const BlackBoxOp::PedersenHash& lhs, const BlackBoxOp::PedersenHash& rhs) { @@ -4120,11 +4128,11 @@ inline BlackBoxOp::PedersenHash BlackBoxOp::PedersenHash::bincodeDeserialize(std return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::PedersenHash& obj, +void serde::Serializable::serialize(const Program::BlackBoxOp::PedersenHash& obj, Serializer& serializer) { serde::Serializable::serialize(obj.inputs, serializer); @@ -4134,17 +4142,17 @@ void serde::Serializable::serialize(const Cir template <> template -Circuit::BlackBoxOp::PedersenHash serde::Deserializable::deserialize( +Program::BlackBoxOp::PedersenHash serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxOp::PedersenHash obj; + Program::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 { +namespace Program { inline bool operator==(const BlackBoxOp::FixedBaseScalarMul& lhs, const BlackBoxOp::FixedBaseScalarMul& rhs) { @@ -4177,12 +4185,12 @@ inline BlackBoxOp::FixedBaseScalarMul BlackBoxOp::FixedBaseScalarMul::bincodeDes return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize( - const Circuit::BlackBoxOp::FixedBaseScalarMul& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Program::BlackBoxOp::FixedBaseScalarMul& obj, Serializer& serializer) { serde::Serializable::serialize(obj.low, serializer); serde::Serializable::serialize(obj.high, serializer); @@ -4191,17 +4199,17 @@ void serde::Serializable::serialize( template <> template -Circuit::BlackBoxOp::FixedBaseScalarMul serde::Deserializable::deserialize( +Program::BlackBoxOp::FixedBaseScalarMul serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxOp::FixedBaseScalarMul obj; + Program::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 { +namespace Program { inline bool operator==(const BlackBoxOp::EmbeddedCurveAdd& lhs, const BlackBoxOp::EmbeddedCurveAdd& rhs) { @@ -4240,12 +4248,12 @@ inline BlackBoxOp::EmbeddedCurveAdd BlackBoxOp::EmbeddedCurveAdd::bincodeDeseria return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize( - const Circuit::BlackBoxOp::EmbeddedCurveAdd& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Program::BlackBoxOp::EmbeddedCurveAdd& obj, Serializer& serializer) { serde::Serializable::serialize(obj.input1_x, serializer); serde::Serializable::serialize(obj.input1_y, serializer); @@ -4256,10 +4264,10 @@ void serde::Serializable::serialize( template <> template -Circuit::BlackBoxOp::EmbeddedCurveAdd serde::Deserializable::deserialize( +Program::BlackBoxOp::EmbeddedCurveAdd serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxOp::EmbeddedCurveAdd obj; + Program::BlackBoxOp::EmbeddedCurveAdd obj; obj.input1_x = serde::Deserializable::deserialize(deserializer); obj.input1_y = serde::Deserializable::deserialize(deserializer); obj.input2_x = serde::Deserializable::deserialize(deserializer); @@ -4268,7 +4276,7 @@ Circuit::BlackBoxOp::EmbeddedCurveAdd serde::Deserializable template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::BigIntAdd& obj, +void serde::Serializable::serialize(const Program::BlackBoxOp::BigIntAdd& obj, Serializer& serializer) { serde::Serializable::serialize(obj.lhs, serializer); @@ -4315,17 +4323,17 @@ void serde::Serializable::serialize(const Circui template <> template -Circuit::BlackBoxOp::BigIntAdd serde::Deserializable::deserialize( +Program::BlackBoxOp::BigIntAdd serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxOp::BigIntAdd obj; + Program::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 { +namespace Program { inline bool operator==(const BlackBoxOp::BigIntSub& lhs, const BlackBoxOp::BigIntSub& rhs) { @@ -4358,11 +4366,11 @@ inline BlackBoxOp::BigIntSub BlackBoxOp::BigIntSub::bincodeDeserialize(std::vect return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::BigIntSub& obj, +void serde::Serializable::serialize(const Program::BlackBoxOp::BigIntSub& obj, Serializer& serializer) { serde::Serializable::serialize(obj.lhs, serializer); @@ -4372,17 +4380,17 @@ void serde::Serializable::serialize(const Circui template <> template -Circuit::BlackBoxOp::BigIntSub serde::Deserializable::deserialize( +Program::BlackBoxOp::BigIntSub serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxOp::BigIntSub obj; + Program::BlackBoxOp::BigIntSub obj; obj.lhs = serde::Deserializable::deserialize(deserializer); obj.rhs = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxOp::BigIntMul& lhs, const BlackBoxOp::BigIntMul& rhs) { @@ -4415,11 +4423,11 @@ inline BlackBoxOp::BigIntMul BlackBoxOp::BigIntMul::bincodeDeserialize(std::vect return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::BigIntMul& obj, +void serde::Serializable::serialize(const Program::BlackBoxOp::BigIntMul& obj, Serializer& serializer) { serde::Serializable::serialize(obj.lhs, serializer); @@ -4429,17 +4437,17 @@ void serde::Serializable::serialize(const Circui template <> template -Circuit::BlackBoxOp::BigIntMul serde::Deserializable::deserialize( +Program::BlackBoxOp::BigIntMul serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxOp::BigIntMul obj; + Program::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 { +namespace Program { inline bool operator==(const BlackBoxOp::BigIntDiv& lhs, const BlackBoxOp::BigIntDiv& rhs) { @@ -4472,11 +4480,11 @@ inline BlackBoxOp::BigIntDiv BlackBoxOp::BigIntDiv::bincodeDeserialize(std::vect return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::BigIntDiv& obj, +void serde::Serializable::serialize(const Program::BlackBoxOp::BigIntDiv& obj, Serializer& serializer) { serde::Serializable::serialize(obj.lhs, serializer); @@ -4486,17 +4494,17 @@ void serde::Serializable::serialize(const Circui template <> template -Circuit::BlackBoxOp::BigIntDiv serde::Deserializable::deserialize( +Program::BlackBoxOp::BigIntDiv serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxOp::BigIntDiv obj; + Program::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 { +namespace Program { inline bool operator==(const BlackBoxOp::BigIntFromLeBytes& lhs, const BlackBoxOp::BigIntFromLeBytes& rhs) { @@ -4529,12 +4537,12 @@ inline BlackBoxOp::BigIntFromLeBytes BlackBoxOp::BigIntFromLeBytes::bincodeDeser return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize( - const Circuit::BlackBoxOp::BigIntFromLeBytes& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Program::BlackBoxOp::BigIntFromLeBytes& obj, Serializer& serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.modulus, serializer); @@ -4543,17 +4551,17 @@ void serde::Serializable::serialize( template <> template -Circuit::BlackBoxOp::BigIntFromLeBytes serde::Deserializable::deserialize( +Program::BlackBoxOp::BigIntFromLeBytes serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxOp::BigIntFromLeBytes obj; + Program::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 { +namespace Program { inline bool operator==(const BlackBoxOp::BigIntToLeBytes& lhs, const BlackBoxOp::BigIntToLeBytes& rhs) { @@ -4583,12 +4591,12 @@ inline BlackBoxOp::BigIntToLeBytes BlackBoxOp::BigIntToLeBytes::bincodeDeseriali return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize( - const Circuit::BlackBoxOp::BigIntToLeBytes& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Program::BlackBoxOp::BigIntToLeBytes& obj, Serializer& serializer) { serde::Serializable::serialize(obj.input, serializer); serde::Serializable::serialize(obj.output, serializer); @@ -4596,16 +4604,16 @@ void serde::Serializable::serialize( template <> template -Circuit::BlackBoxOp::BigIntToLeBytes serde::Deserializable::deserialize( +Program::BlackBoxOp::BigIntToLeBytes serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxOp::BigIntToLeBytes obj; + Program::BlackBoxOp::BigIntToLeBytes obj; obj.input = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxOp::Poseidon2Permutation& lhs, const BlackBoxOp::Poseidon2Permutation& rhs) { @@ -4638,12 +4646,12 @@ inline BlackBoxOp::Poseidon2Permutation BlackBoxOp::Poseidon2Permutation::bincod return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize( - const Circuit::BlackBoxOp::Poseidon2Permutation& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Program::BlackBoxOp::Poseidon2Permutation& obj, Serializer& serializer) { serde::Serializable::serialize(obj.message, serializer); serde::Serializable::serialize(obj.output, serializer); @@ -4652,17 +4660,17 @@ void serde::Serializable::serialize( template <> template -Circuit::BlackBoxOp::Poseidon2Permutation serde::Deserializable::deserialize( +Program::BlackBoxOp::Poseidon2Permutation serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxOp::Poseidon2Permutation obj; + Program::BlackBoxOp::Poseidon2Permutation obj; obj.message = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); obj.len = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxOp::Sha256Compression& lhs, const BlackBoxOp::Sha256Compression& rhs) { @@ -4695,12 +4703,12 @@ inline BlackBoxOp::Sha256Compression BlackBoxOp::Sha256Compression::bincodeDeser return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize( - const Circuit::BlackBoxOp::Sha256Compression& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Program::BlackBoxOp::Sha256Compression& obj, Serializer& serializer) { serde::Serializable::serialize(obj.input, serializer); serde::Serializable::serialize(obj.hash_values, serializer); @@ -4709,17 +4717,17 @@ void serde::Serializable::serialize( template <> template -Circuit::BlackBoxOp::Sha256Compression serde::Deserializable::deserialize( +Program::BlackBoxOp::Sha256Compression serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BlackBoxOp::Sha256Compression obj; + Program::BlackBoxOp::Sha256Compression obj; obj.input = serde::Deserializable::deserialize(deserializer); obj.hash_values = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlockId& lhs, const BlockId& rhs) { @@ -4746,11 +4754,11 @@ inline BlockId BlockId::bincodeDeserialize(std::vector input) return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlockId& obj, Serializer& serializer) +void serde::Serializable::serialize(const Program::BlockId& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); @@ -4759,16 +4767,16 @@ void serde::Serializable::serialize(const Circuit::BlockId& ob template <> template -Circuit::BlockId serde::Deserializable::deserialize(Deserializer& deserializer) +Program::BlockId serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Circuit::BlockId obj; + Program::BlockId obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Brillig& lhs, const Brillig& rhs) { @@ -4804,11 +4812,11 @@ inline Brillig Brillig::bincodeDeserialize(std::vector input) return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Brillig& obj, Serializer& serializer) +void serde::Serializable::serialize(const Program::Brillig& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.inputs, serializer); @@ -4820,10 +4828,10 @@ void serde::Serializable::serialize(const Circuit::Brillig& ob template <> template -Circuit::Brillig serde::Deserializable::deserialize(Deserializer& deserializer) +Program::Brillig serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Circuit::Brillig obj; + Program::Brillig obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); obj.bytecode = serde::Deserializable::deserialize(deserializer); @@ -4832,7 +4840,7 @@ Circuit::Brillig serde::Deserializable::deserialize(Deserializ return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligInputs& lhs, const BrilligInputs& rhs) { @@ -4859,11 +4867,11 @@ inline BrilligInputs BrilligInputs::bincodeDeserialize(std::vector inpu return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligInputs& obj, Serializer& serializer) +void serde::Serializable::serialize(const Program::BrilligInputs& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); @@ -4872,16 +4880,16 @@ void serde::Serializable::serialize(const Circuit::Brill template <> template -Circuit::BrilligInputs serde::Deserializable::deserialize(Deserializer& deserializer) +Program::BrilligInputs serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Circuit::BrilligInputs obj; + Program::BrilligInputs obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligInputs::Single& lhs, const BrilligInputs::Single& rhs) { @@ -4908,11 +4916,11 @@ inline BrilligInputs::Single BrilligInputs::Single::bincodeDeserialize(std::vect return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligInputs::Single& obj, +void serde::Serializable::serialize(const Program::BrilligInputs::Single& obj, Serializer& serializer) { serde::Serializable::serialize(obj.value, serializer); @@ -4920,15 +4928,15 @@ void serde::Serializable::serialize(const Circui template <> template -Circuit::BrilligInputs::Single serde::Deserializable::deserialize( +Program::BrilligInputs::Single serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BrilligInputs::Single obj; + Program::BrilligInputs::Single obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligInputs::Array& lhs, const BrilligInputs::Array& rhs) { @@ -4955,11 +4963,11 @@ inline BrilligInputs::Array BrilligInputs::Array::bincodeDeserialize(std::vector return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligInputs::Array& obj, +void serde::Serializable::serialize(const Program::BrilligInputs::Array& obj, Serializer& serializer) { serde::Serializable::serialize(obj.value, serializer); @@ -4967,15 +4975,15 @@ void serde::Serializable::serialize(const Circuit template <> template -Circuit::BrilligInputs::Array serde::Deserializable::deserialize( +Program::BrilligInputs::Array serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BrilligInputs::Array obj; + Program::BrilligInputs::Array obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligInputs::MemoryArray& lhs, const BrilligInputs::MemoryArray& rhs) { @@ -5002,11 +5010,11 @@ inline BrilligInputs::MemoryArray BrilligInputs::MemoryArray::bincodeDeserialize return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligInputs::MemoryArray& obj, +void serde::Serializable::serialize(const Program::BrilligInputs::MemoryArray& obj, Serializer& serializer) { serde::Serializable::serialize(obj.value, serializer); @@ -5014,15 +5022,15 @@ void serde::Serializable::serialize(const C template <> template -Circuit::BrilligInputs::MemoryArray serde::Deserializable::deserialize( +Program::BrilligInputs::MemoryArray serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BrilligInputs::MemoryArray obj; + Program::BrilligInputs::MemoryArray obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode& lhs, const BrilligOpcode& rhs) { @@ -5049,11 +5057,11 @@ inline BrilligOpcode BrilligOpcode::bincodeDeserialize(std::vector inpu return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOpcode& obj, Serializer& serializer) +void serde::Serializable::serialize(const Program::BrilligOpcode& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); @@ -5062,16 +5070,16 @@ void serde::Serializable::serialize(const Circuit::Brill template <> template -Circuit::BrilligOpcode serde::Deserializable::deserialize(Deserializer& deserializer) +Program::BrilligOpcode serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Circuit::BrilligOpcode obj; + Program::BrilligOpcode obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::BinaryFieldOp& lhs, const BrilligOpcode::BinaryFieldOp& rhs) { @@ -5107,12 +5115,12 @@ inline BrilligOpcode::BinaryFieldOp BrilligOpcode::BinaryFieldOp::bincodeDeseria return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize( - const Circuit::BrilligOpcode::BinaryFieldOp& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Program::BrilligOpcode::BinaryFieldOp& obj, Serializer& serializer) { serde::Serializable::serialize(obj.destination, serializer); serde::Serializable::serialize(obj.op, serializer); @@ -5122,10 +5130,10 @@ void serde::Serializable::serialize( template <> template -Circuit::BrilligOpcode::BinaryFieldOp serde::Deserializable::deserialize( +Program::BrilligOpcode::BinaryFieldOp serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BrilligOpcode::BinaryFieldOp obj; + Program::BrilligOpcode::BinaryFieldOp obj; obj.destination = serde::Deserializable::deserialize(deserializer); obj.op = serde::Deserializable::deserialize(deserializer); obj.lhs = serde::Deserializable::deserialize(deserializer); @@ -5133,7 +5141,7 @@ Circuit::BrilligOpcode::BinaryFieldOp serde::Deserializable template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::BinaryIntOp& obj, +void serde::Serializable::serialize(const Program::BrilligOpcode::BinaryIntOp& obj, Serializer& serializer) { serde::Serializable::serialize(obj.destination, serializer); @@ -5188,10 +5196,10 @@ void serde::Serializable::serialize(const C template <> template -Circuit::BrilligOpcode::BinaryIntOp serde::Deserializable::deserialize( +Program::BrilligOpcode::BinaryIntOp serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BrilligOpcode::BinaryIntOp obj; + Program::BrilligOpcode::BinaryIntOp obj; obj.destination = serde::Deserializable::deserialize(deserializer); obj.op = serde::Deserializable::deserialize(deserializer); obj.bit_size = serde::Deserializable::deserialize(deserializer); @@ -5200,7 +5208,7 @@ Circuit::BrilligOpcode::BinaryIntOp serde::Deserializable template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::Cast& obj, +void serde::Serializable::serialize(const Program::BrilligOpcode::Cast& obj, Serializer& serializer) { serde::Serializable::serialize(obj.destination, serializer); @@ -5247,17 +5255,17 @@ void serde::Serializable::serialize(const Circuit: template <> template -Circuit::BrilligOpcode::Cast serde::Deserializable::deserialize( +Program::BrilligOpcode::Cast serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BrilligOpcode::Cast obj; + Program::BrilligOpcode::Cast obj; obj.destination = serde::Deserializable::deserialize(deserializer); obj.source = serde::Deserializable::deserialize(deserializer); obj.bit_size = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::JumpIfNot& lhs, const BrilligOpcode::JumpIfNot& rhs) { @@ -5287,11 +5295,11 @@ inline BrilligOpcode::JumpIfNot BrilligOpcode::JumpIfNot::bincodeDeserialize(std return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::JumpIfNot& obj, +void serde::Serializable::serialize(const Program::BrilligOpcode::JumpIfNot& obj, Serializer& serializer) { serde::Serializable::serialize(obj.condition, serializer); @@ -5300,16 +5308,16 @@ void serde::Serializable::serialize(const Cir template <> template -Circuit::BrilligOpcode::JumpIfNot serde::Deserializable::deserialize( +Program::BrilligOpcode::JumpIfNot serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BrilligOpcode::JumpIfNot obj; + Program::BrilligOpcode::JumpIfNot obj; obj.condition = serde::Deserializable::deserialize(deserializer); obj.location = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::JumpIf& lhs, const BrilligOpcode::JumpIf& rhs) { @@ -5339,11 +5347,11 @@ inline BrilligOpcode::JumpIf BrilligOpcode::JumpIf::bincodeDeserialize(std::vect return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::JumpIf& obj, +void serde::Serializable::serialize(const Program::BrilligOpcode::JumpIf& obj, Serializer& serializer) { serde::Serializable::serialize(obj.condition, serializer); @@ -5352,16 +5360,16 @@ void serde::Serializable::serialize(const Circui template <> template -Circuit::BrilligOpcode::JumpIf serde::Deserializable::deserialize( +Program::BrilligOpcode::JumpIf serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BrilligOpcode::JumpIf obj; + Program::BrilligOpcode::JumpIf obj; obj.condition = serde::Deserializable::deserialize(deserializer); obj.location = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::Jump& lhs, const BrilligOpcode::Jump& rhs) { @@ -5388,11 +5396,11 @@ inline BrilligOpcode::Jump BrilligOpcode::Jump::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::Jump& obj, +void serde::Serializable::serialize(const Program::BrilligOpcode::Jump& obj, Serializer& serializer) { serde::Serializable::serialize(obj.location, serializer); @@ -5400,15 +5408,15 @@ void serde::Serializable::serialize(const Circuit: template <> template -Circuit::BrilligOpcode::Jump serde::Deserializable::deserialize( +Program::BrilligOpcode::Jump serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BrilligOpcode::Jump obj; + Program::BrilligOpcode::Jump obj; obj.location = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::CalldataCopy& lhs, const BrilligOpcode::CalldataCopy& rhs) { @@ -5441,12 +5449,12 @@ inline BrilligOpcode::CalldataCopy BrilligOpcode::CalldataCopy::bincodeDeseriali return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize( - const Circuit::BrilligOpcode::CalldataCopy& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Program::BrilligOpcode::CalldataCopy& obj, Serializer& serializer) { serde::Serializable::serialize(obj.destination_address, serializer); serde::Serializable::serialize(obj.size, serializer); @@ -5455,17 +5463,17 @@ void serde::Serializable::serialize( template <> template -Circuit::BrilligOpcode::CalldataCopy serde::Deserializable::deserialize( +Program::BrilligOpcode::CalldataCopy serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BrilligOpcode::CalldataCopy obj; + Program::BrilligOpcode::CalldataCopy obj; obj.destination_address = serde::Deserializable::deserialize(deserializer); obj.size = serde::Deserializable::deserialize(deserializer); obj.offset = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::Call& lhs, const BrilligOpcode::Call& rhs) { @@ -5492,11 +5500,11 @@ inline BrilligOpcode::Call BrilligOpcode::Call::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::Call& obj, +void serde::Serializable::serialize(const Program::BrilligOpcode::Call& obj, Serializer& serializer) { serde::Serializable::serialize(obj.location, serializer); @@ -5504,15 +5512,15 @@ void serde::Serializable::serialize(const Circuit: template <> template -Circuit::BrilligOpcode::Call serde::Deserializable::deserialize( +Program::BrilligOpcode::Call serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BrilligOpcode::Call obj; + Program::BrilligOpcode::Call obj; obj.location = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::Const& lhs, const BrilligOpcode::Const& rhs) { @@ -5545,11 +5553,11 @@ inline BrilligOpcode::Const BrilligOpcode::Const::bincodeDeserialize(std::vector return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::Const& obj, +void serde::Serializable::serialize(const Program::BrilligOpcode::Const& obj, Serializer& serializer) { serde::Serializable::serialize(obj.destination, serializer); @@ -5559,17 +5567,17 @@ void serde::Serializable::serialize(const Circuit template <> template -Circuit::BrilligOpcode::Const serde::Deserializable::deserialize( +Program::BrilligOpcode::Const serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BrilligOpcode::Const obj; + Program::BrilligOpcode::Const obj; obj.destination = serde::Deserializable::deserialize(deserializer); obj.bit_size = serde::Deserializable::deserialize(deserializer); obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::Return& lhs, const BrilligOpcode::Return& rhs) { @@ -5593,24 +5601,24 @@ inline BrilligOpcode::Return BrilligOpcode::Return::bincodeDeserialize(std::vect return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::Return& obj, +void serde::Serializable::serialize(const Program::BrilligOpcode::Return& obj, Serializer& serializer) {} template <> template -Circuit::BrilligOpcode::Return serde::Deserializable::deserialize( +Program::BrilligOpcode::Return serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BrilligOpcode::Return obj; + Program::BrilligOpcode::Return obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::ForeignCall& lhs, const BrilligOpcode::ForeignCall& rhs) { @@ -5649,11 +5657,11 @@ inline BrilligOpcode::ForeignCall BrilligOpcode::ForeignCall::bincodeDeserialize return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::ForeignCall& obj, +void serde::Serializable::serialize(const Program::BrilligOpcode::ForeignCall& obj, Serializer& serializer) { serde::Serializable::serialize(obj.function, serializer); @@ -5665,10 +5673,10 @@ void serde::Serializable::serialize(const C template <> template -Circuit::BrilligOpcode::ForeignCall serde::Deserializable::deserialize( +Program::BrilligOpcode::ForeignCall serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BrilligOpcode::ForeignCall obj; + Program::BrilligOpcode::ForeignCall obj; obj.function = serde::Deserializable::deserialize(deserializer); obj.destinations = serde::Deserializable::deserialize(deserializer); obj.destination_value_types = @@ -5678,7 +5686,7 @@ Circuit::BrilligOpcode::ForeignCall serde::Deserializable template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::Mov& obj, +void serde::Serializable::serialize(const Program::BrilligOpcode::Mov& obj, Serializer& serializer) { serde::Serializable::serialize(obj.destination, serializer); @@ -5721,15 +5729,15 @@ void serde::Serializable::serialize(const Circuit:: template <> template -Circuit::BrilligOpcode::Mov serde::Deserializable::deserialize(Deserializer& deserializer) +Program::BrilligOpcode::Mov serde::Deserializable::deserialize(Deserializer& deserializer) { - Circuit::BrilligOpcode::Mov obj; + Program::BrilligOpcode::Mov obj; obj.destination = serde::Deserializable::deserialize(deserializer); obj.source = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::Load& lhs, const BrilligOpcode::Load& rhs) { @@ -5759,11 +5767,11 @@ inline BrilligOpcode::Load BrilligOpcode::Load::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::Load& obj, +void serde::Serializable::serialize(const Program::BrilligOpcode::Load& obj, Serializer& serializer) { serde::Serializable::serialize(obj.destination, serializer); @@ -5772,16 +5780,16 @@ void serde::Serializable::serialize(const Circuit: template <> template -Circuit::BrilligOpcode::Load serde::Deserializable::deserialize( +Program::BrilligOpcode::Load serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BrilligOpcode::Load obj; + Program::BrilligOpcode::Load obj; obj.destination = serde::Deserializable::deserialize(deserializer); obj.source_pointer = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::Store& lhs, const BrilligOpcode::Store& rhs) { @@ -5811,11 +5819,11 @@ inline BrilligOpcode::Store BrilligOpcode::Store::bincodeDeserialize(std::vector return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::Store& obj, +void serde::Serializable::serialize(const Program::BrilligOpcode::Store& obj, Serializer& serializer) { serde::Serializable::serialize(obj.destination_pointer, serializer); @@ -5824,16 +5832,16 @@ void serde::Serializable::serialize(const Circuit template <> template -Circuit::BrilligOpcode::Store serde::Deserializable::deserialize( +Program::BrilligOpcode::Store serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BrilligOpcode::Store obj; + Program::BrilligOpcode::Store obj; obj.destination_pointer = serde::Deserializable::deserialize(deserializer); obj.source = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::BlackBox& lhs, const BrilligOpcode::BlackBox& rhs) { @@ -5860,11 +5868,11 @@ inline BrilligOpcode::BlackBox BrilligOpcode::BlackBox::bincodeDeserialize(std:: return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::BlackBox& obj, +void serde::Serializable::serialize(const Program::BrilligOpcode::BlackBox& obj, Serializer& serializer) { serde::Serializable::serialize(obj.value, serializer); @@ -5872,15 +5880,15 @@ void serde::Serializable::serialize(const Circ template <> template -Circuit::BrilligOpcode::BlackBox serde::Deserializable::deserialize( +Program::BrilligOpcode::BlackBox serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BrilligOpcode::BlackBox obj; + Program::BrilligOpcode::BlackBox obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::Trap& lhs, const BrilligOpcode::Trap& rhs) { @@ -5904,24 +5912,24 @@ inline BrilligOpcode::Trap BrilligOpcode::Trap::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::Trap& obj, +void serde::Serializable::serialize(const Program::BrilligOpcode::Trap& obj, Serializer& serializer) {} template <> template -Circuit::BrilligOpcode::Trap serde::Deserializable::deserialize( +Program::BrilligOpcode::Trap serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BrilligOpcode::Trap obj; + Program::BrilligOpcode::Trap obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::Stop& lhs, const BrilligOpcode::Stop& rhs) { @@ -5951,11 +5959,11 @@ inline BrilligOpcode::Stop BrilligOpcode::Stop::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::Stop& obj, +void serde::Serializable::serialize(const Program::BrilligOpcode::Stop& obj, Serializer& serializer) { serde::Serializable::serialize(obj.return_data_offset, serializer); @@ -5964,16 +5972,16 @@ void serde::Serializable::serialize(const Circuit: template <> template -Circuit::BrilligOpcode::Stop serde::Deserializable::deserialize( +Program::BrilligOpcode::Stop serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BrilligOpcode::Stop obj; + Program::BrilligOpcode::Stop obj; obj.return_data_offset = serde::Deserializable::deserialize(deserializer); obj.return_data_size = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOutputs& lhs, const BrilligOutputs& rhs) { @@ -6000,11 +6008,11 @@ inline BrilligOutputs BrilligOutputs::bincodeDeserialize(std::vector in return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOutputs& obj, Serializer& serializer) +void serde::Serializable::serialize(const Program::BrilligOutputs& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); @@ -6013,16 +6021,16 @@ void serde::Serializable::serialize(const Circuit::Bril template <> template -Circuit::BrilligOutputs serde::Deserializable::deserialize(Deserializer& deserializer) +Program::BrilligOutputs serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Circuit::BrilligOutputs obj; + Program::BrilligOutputs obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOutputs::Simple& lhs, const BrilligOutputs::Simple& rhs) { @@ -6049,11 +6057,11 @@ inline BrilligOutputs::Simple BrilligOutputs::Simple::bincodeDeserialize(std::ve return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOutputs::Simple& obj, +void serde::Serializable::serialize(const Program::BrilligOutputs::Simple& obj, Serializer& serializer) { serde::Serializable::serialize(obj.value, serializer); @@ -6061,15 +6069,15 @@ void serde::Serializable::serialize(const Circu template <> template -Circuit::BrilligOutputs::Simple serde::Deserializable::deserialize( +Program::BrilligOutputs::Simple serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BrilligOutputs::Simple obj; + Program::BrilligOutputs::Simple obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOutputs::Array& lhs, const BrilligOutputs::Array& rhs) { @@ -6096,11 +6104,11 @@ inline BrilligOutputs::Array BrilligOutputs::Array::bincodeDeserialize(std::vect return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOutputs::Array& obj, +void serde::Serializable::serialize(const Program::BrilligOutputs::Array& obj, Serializer& serializer) { serde::Serializable::serialize(obj.value, serializer); @@ -6108,15 +6116,15 @@ void serde::Serializable::serialize(const Circui template <> template -Circuit::BrilligOutputs::Array serde::Deserializable::deserialize( +Program::BrilligOutputs::Array serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BrilligOutputs::Array obj; + Program::BrilligOutputs::Array obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Circuit& lhs, const Circuit& rhs) { @@ -6164,11 +6172,11 @@ inline Circuit Circuit::bincodeDeserialize(std::vector input) return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Circuit& obj, Serializer& serializer) +void serde::Serializable::serialize(const Program::Circuit& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.current_witness_index, serializer); @@ -6184,10 +6192,10 @@ void serde::Serializable::serialize(const Circuit::Circuit& ob template <> template -Circuit::Circuit serde::Deserializable::deserialize(Deserializer& deserializer) +Program::Circuit serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Circuit::Circuit obj; + Program::Circuit obj; obj.current_witness_index = serde::Deserializable::deserialize(deserializer); obj.opcodes = serde::Deserializable::deserialize(deserializer); obj.expression_width = serde::Deserializable::deserialize(deserializer); @@ -6200,7 +6208,7 @@ Circuit::Circuit serde::Deserializable::deserialize(Deserializ return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Directive& lhs, const Directive& rhs) { @@ -6227,11 +6235,11 @@ inline Directive Directive::bincodeDeserialize(std::vector input) return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Directive& obj, Serializer& serializer) +void serde::Serializable::serialize(const Program::Directive& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); @@ -6240,16 +6248,16 @@ void serde::Serializable::serialize(const Circuit::Directive template <> template -Circuit::Directive serde::Deserializable::deserialize(Deserializer& deserializer) +Program::Directive serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Circuit::Directive obj; + Program::Directive obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Directive::ToLeRadix& lhs, const Directive::ToLeRadix& rhs) { @@ -6282,11 +6290,11 @@ inline Directive::ToLeRadix Directive::ToLeRadix::bincodeDeserialize(std::vector return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Directive::ToLeRadix& obj, +void serde::Serializable::serialize(const Program::Directive::ToLeRadix& obj, Serializer& serializer) { serde::Serializable::serialize(obj.a, serializer); @@ -6296,17 +6304,17 @@ void serde::Serializable::serialize(const Circuit template <> template -Circuit::Directive::ToLeRadix serde::Deserializable::deserialize( +Program::Directive::ToLeRadix serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::Directive::ToLeRadix obj; + Program::Directive::ToLeRadix obj; obj.a = serde::Deserializable::deserialize(deserializer); obj.b = serde::Deserializable::deserialize(deserializer); obj.radix = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Expression& lhs, const Expression& rhs) { @@ -6339,11 +6347,11 @@ inline Expression Expression::bincodeDeserialize(std::vector input) return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Expression& obj, Serializer& serializer) +void serde::Serializable::serialize(const Program::Expression& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.mul_terms, serializer); @@ -6354,10 +6362,10 @@ void serde::Serializable::serialize(const Circuit::Expressi template <> template -Circuit::Expression serde::Deserializable::deserialize(Deserializer& deserializer) +Program::Expression serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Circuit::Expression obj; + Program::Expression obj; obj.mul_terms = serde::Deserializable::deserialize(deserializer); obj.linear_combinations = serde::Deserializable::deserialize(deserializer); obj.q_c = serde::Deserializable::deserialize(deserializer); @@ -6365,7 +6373,7 @@ Circuit::Expression serde::Deserializable::deserialize(Dese return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const ExpressionWidth& lhs, const ExpressionWidth& rhs) { @@ -6392,11 +6400,11 @@ inline ExpressionWidth ExpressionWidth::bincodeDeserialize(std::vector return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::ExpressionWidth& obj, +void serde::Serializable::serialize(const Program::ExpressionWidth& obj, Serializer& serializer) { serializer.increase_container_depth(); @@ -6406,16 +6414,16 @@ void serde::Serializable::serialize(const Circuit::Exp template <> template -Circuit::ExpressionWidth serde::Deserializable::deserialize(Deserializer& deserializer) +Program::ExpressionWidth serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Circuit::ExpressionWidth obj; + Program::ExpressionWidth obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const ExpressionWidth::Unbounded& lhs, const ExpressionWidth::Unbounded& rhs) { @@ -6439,24 +6447,24 @@ inline ExpressionWidth::Unbounded ExpressionWidth::Unbounded::bincodeDeserialize return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::ExpressionWidth::Unbounded& obj, +void serde::Serializable::serialize(const Program::ExpressionWidth::Unbounded& obj, Serializer& serializer) {} template <> template -Circuit::ExpressionWidth::Unbounded serde::Deserializable::deserialize( +Program::ExpressionWidth::Unbounded serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::ExpressionWidth::Unbounded obj; + Program::ExpressionWidth::Unbounded obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const ExpressionWidth::Bounded& lhs, const ExpressionWidth::Bounded& rhs) { @@ -6483,11 +6491,11 @@ inline ExpressionWidth::Bounded ExpressionWidth::Bounded::bincodeDeserialize(std return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::ExpressionWidth::Bounded& obj, +void serde::Serializable::serialize(const Program::ExpressionWidth::Bounded& obj, Serializer& serializer) { serde::Serializable::serialize(obj.width, serializer); @@ -6495,15 +6503,15 @@ void serde::Serializable::serialize(const Cir template <> template -Circuit::ExpressionWidth::Bounded serde::Deserializable::deserialize( +Program::ExpressionWidth::Bounded serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::ExpressionWidth::Bounded obj; + Program::ExpressionWidth::Bounded obj; obj.width = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const FunctionInput& lhs, const FunctionInput& rhs) { @@ -6533,11 +6541,11 @@ inline FunctionInput FunctionInput::bincodeDeserialize(std::vector inpu return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::FunctionInput& obj, Serializer& serializer) +void serde::Serializable::serialize(const Program::FunctionInput& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.witness, serializer); @@ -6547,17 +6555,17 @@ void serde::Serializable::serialize(const Circuit::Funct template <> template -Circuit::FunctionInput serde::Deserializable::deserialize(Deserializer& deserializer) +Program::FunctionInput serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Circuit::FunctionInput obj; + Program::FunctionInput obj; obj.witness = serde::Deserializable::deserialize(deserializer); obj.num_bits = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const HeapArray& lhs, const HeapArray& rhs) { @@ -6587,11 +6595,11 @@ inline HeapArray HeapArray::bincodeDeserialize(std::vector input) return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::HeapArray& obj, Serializer& serializer) +void serde::Serializable::serialize(const Program::HeapArray& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.pointer, serializer); @@ -6601,17 +6609,17 @@ void serde::Serializable::serialize(const Circuit::HeapArray template <> template -Circuit::HeapArray serde::Deserializable::deserialize(Deserializer& deserializer) +Program::HeapArray serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Circuit::HeapArray obj; + Program::HeapArray obj; obj.pointer = serde::Deserializable::deserialize(deserializer); obj.size = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const HeapValueType& lhs, const HeapValueType& rhs) { @@ -6638,11 +6646,11 @@ inline HeapValueType HeapValueType::bincodeDeserialize(std::vector inpu return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::HeapValueType& obj, Serializer& serializer) +void serde::Serializable::serialize(const Program::HeapValueType& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); @@ -6651,16 +6659,16 @@ void serde::Serializable::serialize(const Circuit::HeapV template <> template -Circuit::HeapValueType serde::Deserializable::deserialize(Deserializer& deserializer) +Program::HeapValueType serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Circuit::HeapValueType obj; + Program::HeapValueType obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const HeapValueType::Simple& lhs, const HeapValueType::Simple& rhs) { @@ -6684,24 +6692,24 @@ inline HeapValueType::Simple HeapValueType::Simple::bincodeDeserialize(std::vect return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::HeapValueType::Simple& obj, +void serde::Serializable::serialize(const Program::HeapValueType::Simple& obj, Serializer& serializer) {} template <> template -Circuit::HeapValueType::Simple serde::Deserializable::deserialize( +Program::HeapValueType::Simple serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::HeapValueType::Simple obj; + Program::HeapValueType::Simple obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const HeapValueType::Array& lhs, const HeapValueType::Array& rhs) { @@ -6731,11 +6739,11 @@ inline HeapValueType::Array HeapValueType::Array::bincodeDeserialize(std::vector return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::HeapValueType::Array& obj, +void serde::Serializable::serialize(const Program::HeapValueType::Array& obj, Serializer& serializer) { serde::Serializable::serialize(obj.value_types, serializer); @@ -6744,16 +6752,16 @@ void serde::Serializable::serialize(const Circuit template <> template -Circuit::HeapValueType::Array serde::Deserializable::deserialize( +Program::HeapValueType::Array serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::HeapValueType::Array obj; + Program::HeapValueType::Array obj; obj.value_types = serde::Deserializable::deserialize(deserializer); obj.size = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const HeapValueType::Vector& lhs, const HeapValueType::Vector& rhs) { @@ -6780,11 +6788,11 @@ inline HeapValueType::Vector HeapValueType::Vector::bincodeDeserialize(std::vect return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::HeapValueType::Vector& obj, +void serde::Serializable::serialize(const Program::HeapValueType::Vector& obj, Serializer& serializer) { serde::Serializable::serialize(obj.value_types, serializer); @@ -6792,15 +6800,15 @@ void serde::Serializable::serialize(const Circui template <> template -Circuit::HeapValueType::Vector serde::Deserializable::deserialize( +Program::HeapValueType::Vector serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::HeapValueType::Vector obj; + Program::HeapValueType::Vector obj; obj.value_types = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const HeapVector& lhs, const HeapVector& rhs) { @@ -6830,11 +6838,11 @@ inline HeapVector HeapVector::bincodeDeserialize(std::vector input) return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::HeapVector& obj, Serializer& serializer) +void serde::Serializable::serialize(const Program::HeapVector& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.pointer, serializer); @@ -6844,17 +6852,17 @@ void serde::Serializable::serialize(const Circuit::HeapVect template <> template -Circuit::HeapVector serde::Deserializable::deserialize(Deserializer& deserializer) +Program::HeapVector serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Circuit::HeapVector obj; + Program::HeapVector obj; obj.pointer = serde::Deserializable::deserialize(deserializer); obj.size = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const MemOp& lhs, const MemOp& rhs) { @@ -6887,11 +6895,11 @@ inline MemOp MemOp::bincodeDeserialize(std::vector input) return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::MemOp& obj, Serializer& serializer) +void serde::Serializable::serialize(const Program::MemOp& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.operation, serializer); @@ -6902,10 +6910,10 @@ void serde::Serializable::serialize(const Circuit::MemOp& obj, S template <> template -Circuit::MemOp serde::Deserializable::deserialize(Deserializer& deserializer) +Program::MemOp serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Circuit::MemOp obj; + Program::MemOp obj; obj.operation = serde::Deserializable::deserialize(deserializer); obj.index = serde::Deserializable::deserialize(deserializer); obj.value = serde::Deserializable::deserialize(deserializer); @@ -6913,7 +6921,7 @@ Circuit::MemOp serde::Deserializable::deserialize(Deserializer& return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const MemoryAddress& lhs, const MemoryAddress& rhs) { @@ -6940,11 +6948,11 @@ inline MemoryAddress MemoryAddress::bincodeDeserialize(std::vector inpu return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::MemoryAddress& obj, Serializer& serializer) +void serde::Serializable::serialize(const Program::MemoryAddress& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); @@ -6953,16 +6961,16 @@ void serde::Serializable::serialize(const Circuit::Memor template <> template -Circuit::MemoryAddress serde::Deserializable::deserialize(Deserializer& deserializer) +Program::MemoryAddress serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Circuit::MemoryAddress obj; + Program::MemoryAddress obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Opcode& lhs, const Opcode& rhs) { @@ -6989,11 +6997,11 @@ inline Opcode Opcode::bincodeDeserialize(std::vector input) return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Opcode& obj, Serializer& serializer) +void serde::Serializable::serialize(const Program::Opcode& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); @@ -7002,16 +7010,16 @@ void serde::Serializable::serialize(const Circuit::Opcode& obj, template <> template -Circuit::Opcode serde::Deserializable::deserialize(Deserializer& deserializer) +Program::Opcode serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Circuit::Opcode obj; + Program::Opcode obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Opcode::AssertZero& lhs, const Opcode::AssertZero& rhs) { @@ -7038,11 +7046,11 @@ inline Opcode::AssertZero Opcode::AssertZero::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Circuit::Opcode::AssertZero& obj, +void serde::Serializable::serialize(const Program::Opcode::AssertZero& obj, Serializer& serializer) { serde::Serializable::serialize(obj.value, serializer); @@ -7050,14 +7058,14 @@ void serde::Serializable::serialize(const Circuit:: template <> template -Circuit::Opcode::AssertZero serde::Deserializable::deserialize(Deserializer& deserializer) +Program::Opcode::AssertZero serde::Deserializable::deserialize(Deserializer& deserializer) { - Circuit::Opcode::AssertZero obj; + Program::Opcode::AssertZero obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Opcode::BlackBoxFuncCall& lhs, const Opcode::BlackBoxFuncCall& rhs) { @@ -7084,11 +7092,11 @@ inline Opcode::BlackBoxFuncCall Opcode::BlackBoxFuncCall::bincodeDeserialize(std return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Opcode::BlackBoxFuncCall& obj, +void serde::Serializable::serialize(const Program::Opcode::BlackBoxFuncCall& obj, Serializer& serializer) { serde::Serializable::serialize(obj.value, serializer); @@ -7096,15 +7104,15 @@ void serde::Serializable::serialize(const Cir template <> template -Circuit::Opcode::BlackBoxFuncCall serde::Deserializable::deserialize( +Program::Opcode::BlackBoxFuncCall serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::Opcode::BlackBoxFuncCall obj; + Program::Opcode::BlackBoxFuncCall obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Opcode::Directive& lhs, const Opcode::Directive& rhs) { @@ -7131,11 +7139,11 @@ inline Opcode::Directive Opcode::Directive::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Circuit::Opcode::Directive& obj, +void serde::Serializable::serialize(const Program::Opcode::Directive& obj, Serializer& serializer) { serde::Serializable::serialize(obj.value, serializer); @@ -7143,14 +7151,14 @@ void serde::Serializable::serialize(const Circuit::O template <> template -Circuit::Opcode::Directive serde::Deserializable::deserialize(Deserializer& deserializer) +Program::Opcode::Directive serde::Deserializable::deserialize(Deserializer& deserializer) { - Circuit::Opcode::Directive obj; + Program::Opcode::Directive obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Opcode::Brillig& lhs, const Opcode::Brillig& rhs) { @@ -7177,11 +7185,11 @@ inline Opcode::Brillig Opcode::Brillig::bincodeDeserialize(std::vector return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Opcode::Brillig& obj, +void serde::Serializable::serialize(const Program::Opcode::Brillig& obj, Serializer& serializer) { serde::Serializable::serialize(obj.value, serializer); @@ -7189,14 +7197,14 @@ void serde::Serializable::serialize(const Circuit::Opc template <> template -Circuit::Opcode::Brillig serde::Deserializable::deserialize(Deserializer& deserializer) +Program::Opcode::Brillig serde::Deserializable::deserialize(Deserializer& deserializer) { - Circuit::Opcode::Brillig obj; + Program::Opcode::Brillig obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Opcode::MemoryOp& lhs, const Opcode::MemoryOp& rhs) { @@ -7229,11 +7237,11 @@ inline Opcode::MemoryOp Opcode::MemoryOp::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Circuit::Opcode::MemoryOp& obj, +void serde::Serializable::serialize(const Program::Opcode::MemoryOp& obj, Serializer& serializer) { serde::Serializable::serialize(obj.block_id, serializer); @@ -7243,16 +7251,16 @@ void serde::Serializable::serialize(const Circuit::Op template <> template -Circuit::Opcode::MemoryOp serde::Deserializable::deserialize(Deserializer& deserializer) +Program::Opcode::MemoryOp serde::Deserializable::deserialize(Deserializer& deserializer) { - Circuit::Opcode::MemoryOp obj; + Program::Opcode::MemoryOp obj; obj.block_id = serde::Deserializable::deserialize(deserializer); obj.op = serde::Deserializable::deserialize(deserializer); obj.predicate = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Opcode::MemoryInit& lhs, const Opcode::MemoryInit& rhs) { @@ -7282,11 +7290,11 @@ inline Opcode::MemoryInit Opcode::MemoryInit::bincodeDeserialize(std::vector template -void serde::Serializable::serialize(const Circuit::Opcode::MemoryInit& obj, +void serde::Serializable::serialize(const Program::Opcode::MemoryInit& obj, Serializer& serializer) { serde::Serializable::serialize(obj.block_id, serializer); @@ -7295,15 +7303,15 @@ void serde::Serializable::serialize(const Circuit:: template <> template -Circuit::Opcode::MemoryInit serde::Deserializable::deserialize(Deserializer& deserializer) +Program::Opcode::MemoryInit serde::Deserializable::deserialize(Deserializer& deserializer) { - Circuit::Opcode::MemoryInit obj; + Program::Opcode::MemoryInit obj; obj.block_id = serde::Deserializable::deserialize(deserializer); obj.init = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Opcode::Call& lhs, const Opcode::Call& rhs) { @@ -7336,11 +7344,11 @@ inline Opcode::Call Opcode::Call::bincodeDeserialize(std::vector input) return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Opcode::Call& obj, Serializer& serializer) +void serde::Serializable::serialize(const Program::Opcode::Call& obj, Serializer& serializer) { serde::Serializable::serialize(obj.id, serializer); serde::Serializable::serialize(obj.inputs, serializer); @@ -7349,16 +7357,16 @@ void serde::Serializable::serialize(const Circuit::Opcode template <> template -Circuit::Opcode::Call serde::Deserializable::deserialize(Deserializer& deserializer) +Program::Opcode::Call serde::Deserializable::deserialize(Deserializer& deserializer) { - Circuit::Opcode::Call obj; + Program::Opcode::Call obj; obj.id = serde::Deserializable::deserialize(deserializer); obj.inputs = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const OpcodeLocation& lhs, const OpcodeLocation& rhs) { @@ -7385,11 +7393,11 @@ inline OpcodeLocation OpcodeLocation::bincodeDeserialize(std::vector in return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::OpcodeLocation& obj, Serializer& serializer) +void serde::Serializable::serialize(const Program::OpcodeLocation& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); @@ -7398,16 +7406,16 @@ void serde::Serializable::serialize(const Circuit::Opco template <> template -Circuit::OpcodeLocation serde::Deserializable::deserialize(Deserializer& deserializer) +Program::OpcodeLocation serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Circuit::OpcodeLocation obj; + Program::OpcodeLocation obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const OpcodeLocation::Acir& lhs, const OpcodeLocation::Acir& rhs) { @@ -7434,11 +7442,11 @@ inline OpcodeLocation::Acir OpcodeLocation::Acir::bincodeDeserialize(std::vector return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::OpcodeLocation::Acir& obj, +void serde::Serializable::serialize(const Program::OpcodeLocation::Acir& obj, Serializer& serializer) { serde::Serializable::serialize(obj.value, serializer); @@ -7446,15 +7454,15 @@ void serde::Serializable::serialize(const Circuit template <> template -Circuit::OpcodeLocation::Acir serde::Deserializable::deserialize( +Program::OpcodeLocation::Acir serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::OpcodeLocation::Acir obj; + Program::OpcodeLocation::Acir obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const OpcodeLocation::Brillig& lhs, const OpcodeLocation::Brillig& rhs) { @@ -7484,11 +7492,11 @@ inline OpcodeLocation::Brillig OpcodeLocation::Brillig::bincodeDeserialize(std:: return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::OpcodeLocation::Brillig& obj, +void serde::Serializable::serialize(const Program::OpcodeLocation::Brillig& obj, Serializer& serializer) { serde::Serializable::serialize(obj.acir_index, serializer); @@ -7497,16 +7505,65 @@ void serde::Serializable::serialize(const Circ template <> template -Circuit::OpcodeLocation::Brillig serde::Deserializable::deserialize( +Program::OpcodeLocation::Brillig serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::OpcodeLocation::Brillig obj; + Program::OpcodeLocation::Brillig obj; obj.acir_index = serde::Deserializable::deserialize(deserializer); obj.brillig_index = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { + +inline bool operator==(const Program& lhs, const Program& rhs) +{ + if (!(lhs.functions == rhs.functions)) { + return false; + } + return true; +} + +inline std::vector Program::bincodeSerialize() const +{ + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); +} + +inline Program Program::bincodeDeserialize(std::vector input) +{ + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw_or_abort("Some input bytes were not read"); + } + return value; +} + +} // end of namespace Program + +template <> +template +void serde::Serializable::serialize(const Program::Program& obj, Serializer& serializer) +{ + serializer.increase_container_depth(); + serde::Serializable::serialize(obj.functions, serializer); + serializer.decrease_container_depth(); +} + +template <> +template +Program::Program serde::Deserializable::deserialize(Deserializer& deserializer) +{ + deserializer.increase_container_depth(); + Program::Program obj; + obj.functions = serde::Deserializable::deserialize(deserializer); + deserializer.decrease_container_depth(); + return obj; +} + +namespace Program { inline bool operator==(const PublicInputs& lhs, const PublicInputs& rhs) { @@ -7533,11 +7590,11 @@ inline PublicInputs PublicInputs::bincodeDeserialize(std::vector input) return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::PublicInputs& obj, Serializer& serializer) +void serde::Serializable::serialize(const Program::PublicInputs& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); @@ -7546,16 +7603,16 @@ void serde::Serializable::serialize(const Circuit::Public template <> template -Circuit::PublicInputs serde::Deserializable::deserialize(Deserializer& deserializer) +Program::PublicInputs serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Circuit::PublicInputs obj; + Program::PublicInputs obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Value& lhs, const Value& rhs) { @@ -7582,11 +7639,11 @@ inline Value Value::bincodeDeserialize(std::vector input) return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Value& obj, Serializer& serializer) +void serde::Serializable::serialize(const Program::Value& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.inner, serializer); @@ -7595,16 +7652,16 @@ void serde::Serializable::serialize(const Circuit::Value& obj, S template <> template -Circuit::Value serde::Deserializable::deserialize(Deserializer& deserializer) +Program::Value serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Circuit::Value obj; + Program::Value obj; obj.inner = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const ValueOrArray& lhs, const ValueOrArray& rhs) { @@ -7631,11 +7688,11 @@ inline ValueOrArray ValueOrArray::bincodeDeserialize(std::vector input) return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::ValueOrArray& obj, Serializer& serializer) +void serde::Serializable::serialize(const Program::ValueOrArray& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); @@ -7644,16 +7701,16 @@ void serde::Serializable::serialize(const Circuit::ValueO template <> template -Circuit::ValueOrArray serde::Deserializable::deserialize(Deserializer& deserializer) +Program::ValueOrArray serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Circuit::ValueOrArray obj; + Program::ValueOrArray obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const ValueOrArray::MemoryAddress& lhs, const ValueOrArray::MemoryAddress& rhs) { @@ -7680,27 +7737,27 @@ inline ValueOrArray::MemoryAddress ValueOrArray::MemoryAddress::bincodeDeseriali return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize( - const Circuit::ValueOrArray::MemoryAddress& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Program::ValueOrArray::MemoryAddress& obj, Serializer& serializer) { serde::Serializable::serialize(obj.value, serializer); } template <> template -Circuit::ValueOrArray::MemoryAddress serde::Deserializable::deserialize( +Program::ValueOrArray::MemoryAddress serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::ValueOrArray::MemoryAddress obj; + Program::ValueOrArray::MemoryAddress obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const ValueOrArray::HeapArray& lhs, const ValueOrArray::HeapArray& rhs) { @@ -7727,11 +7784,11 @@ inline ValueOrArray::HeapArray ValueOrArray::HeapArray::bincodeDeserialize(std:: return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::ValueOrArray::HeapArray& obj, +void serde::Serializable::serialize(const Program::ValueOrArray::HeapArray& obj, Serializer& serializer) { serde::Serializable::serialize(obj.value, serializer); @@ -7739,15 +7796,15 @@ void serde::Serializable::serialize(const Circ template <> template -Circuit::ValueOrArray::HeapArray serde::Deserializable::deserialize( +Program::ValueOrArray::HeapArray serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::ValueOrArray::HeapArray obj; + Program::ValueOrArray::HeapArray obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const ValueOrArray::HeapVector& lhs, const ValueOrArray::HeapVector& rhs) { @@ -7774,11 +7831,11 @@ inline ValueOrArray::HeapVector ValueOrArray::HeapVector::bincodeDeserialize(std return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::ValueOrArray::HeapVector& obj, +void serde::Serializable::serialize(const Program::ValueOrArray::HeapVector& obj, Serializer& serializer) { serde::Serializable::serialize(obj.value, serializer); @@ -7786,15 +7843,15 @@ void serde::Serializable::serialize(const Cir template <> template -Circuit::ValueOrArray::HeapVector serde::Deserializable::deserialize( +Program::ValueOrArray::HeapVector serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::ValueOrArray::HeapVector obj; + Program::ValueOrArray::HeapVector obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Witness& lhs, const Witness& rhs) { @@ -7821,11 +7878,11 @@ inline Witness Witness::bincodeDeserialize(std::vector input) return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Witness& obj, Serializer& serializer) +void serde::Serializable::serialize(const Program::Witness& obj, Serializer& serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); @@ -7834,10 +7891,10 @@ void serde::Serializable::serialize(const Circuit::Witness& ob template <> template -Circuit::Witness serde::Deserializable::deserialize(Deserializer& deserializer) +Program::Witness serde::Deserializable::deserialize(Deserializer& deserializer) { deserializer.increase_container_depth(); - Circuit::Witness obj; + Program::Witness obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/index.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/index.hpp index 82716cef883c..da0e55ad1c55 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/index.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/index.hpp @@ -6,7 +6,7 @@ #pragma clang diagnostic ignored "-Wshorten-64-to-32" #pragma clang diagnostic ignored "-Wunused-parameter" #include "acir.hpp" -#include "witness_map.hpp" +#include "witness_stack.hpp" #pragma clang diagnostic pop #else #pragma GCC diagnostic push @@ -16,6 +16,6 @@ #pragma GCC diagnostic ignored "-Wsign-conversion" #pragma GCC diagnostic ignored "-Wconversion" #include "acir.hpp" -#include "witness_map.hpp" +#include "witness_stack.hpp" #pragma GCC diagnostic pop #endif \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/witness_map.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/witness_map.hpp deleted file mode 100644 index de4523e7020a..000000000000 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/witness_map.hpp +++ /dev/null @@ -1,123 +0,0 @@ -#pragma once - -#include "bincode.hpp" -#include "serde.hpp" - -namespace WitnessMap { - -struct Witness { - uint32_t value; - - friend bool operator==(const Witness&, const Witness&); - bool operator<(Witness const& rhs) const { return value < rhs.value; } - std::vector bincodeSerialize() const; - static Witness bincodeDeserialize(std::vector); -}; - -struct WitnessMap { - std::map value; - - friend bool operator==(const WitnessMap&, const WitnessMap&); - std::vector bincodeSerialize() const; - static WitnessMap bincodeDeserialize(std::vector); -}; - -} // end of namespace WitnessMap - -namespace WitnessMap { - -inline bool operator==(const Witness& lhs, const Witness& rhs) -{ - if (!(lhs.value == rhs.value)) { - return false; - } - return true; -} - -inline std::vector Witness::bincodeSerialize() const -{ - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} - -inline Witness Witness::bincodeDeserialize(std::vector input) -{ - auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); - if (deserializer.get_buffer_offset() < input.size()) { - throw_or_abort("Some input bytes were not read"); - } - return value; -} - -} // end of namespace WitnessMap - -template <> -template -void serde::Serializable::serialize(const WitnessMap::Witness& obj, Serializer& serializer) -{ - serializer.increase_container_depth(); - serde::Serializable::serialize(obj.value, serializer); - serializer.decrease_container_depth(); -} - -template <> -template -WitnessMap::Witness serde::Deserializable::deserialize(Deserializer& deserializer) -{ - deserializer.increase_container_depth(); - WitnessMap::Witness obj; - obj.value = serde::Deserializable::deserialize(deserializer); - deserializer.decrease_container_depth(); - return obj; -} - -namespace WitnessMap { - -inline bool operator==(const WitnessMap& lhs, const WitnessMap& rhs) -{ - if (!(lhs.value == rhs.value)) { - return false; - } - return true; -} - -inline std::vector WitnessMap::bincodeSerialize() const -{ - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} - -inline WitnessMap WitnessMap::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 WitnessMap - -template <> -template -void serde::Serializable::serialize(const WitnessMap::WitnessMap& obj, Serializer& serializer) -{ - serializer.increase_container_depth(); - serde::Serializable::serialize(obj.value, serializer); - serializer.decrease_container_depth(); -} - -template <> -template -WitnessMap::WitnessMap serde::Deserializable::deserialize(Deserializer& deserializer) -{ - deserializer.increase_container_depth(); - WitnessMap::WitnessMap obj; - obj.value = serde::Deserializable::deserialize(deserializer); - deserializer.decrease_container_depth(); - return obj; -} \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/witness_stack.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/witness_stack.hpp new file mode 100644 index 000000000000..67ef655babfd --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/witness_stack.hpp @@ -0,0 +1,247 @@ +#pragma once + +#include "bincode.hpp" +#include "serde.hpp" + +namespace WitnessStack { + +struct Witness { + uint32_t value; + + friend bool operator==(const Witness&, const Witness&); + + bool operator<(Witness const& rhs) const { return value < rhs.value; } + + std::vector bincodeSerialize() const; + static Witness bincodeDeserialize(std::vector); +}; + +struct WitnessMap { + std::map value; + + friend bool operator==(const WitnessMap&, const WitnessMap&); + std::vector bincodeSerialize() const; + static WitnessMap bincodeDeserialize(std::vector); +}; + +struct StackItem { + uint32_t index; + WitnessStack::WitnessMap witness; + + friend bool operator==(const StackItem&, const StackItem&); + std::vector bincodeSerialize() const; + static StackItem bincodeDeserialize(std::vector); +}; + +struct WitnessStack { + std::vector stack; + + friend bool operator==(const WitnessStack&, const WitnessStack&); + std::vector bincodeSerialize() const; + static WitnessStack bincodeDeserialize(std::vector); +}; + +} // end of namespace WitnessStack + +namespace WitnessStack { + +inline bool operator==(const StackItem& lhs, const StackItem& rhs) +{ + if (!(lhs.index == rhs.index)) { + return false; + } + if (!(lhs.witness == rhs.witness)) { + return false; + } + return true; +} + +inline std::vector StackItem::bincodeSerialize() const +{ + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); +} + +inline StackItem StackItem::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 WitnessStack + +template <> +template +void serde::Serializable::serialize(const WitnessStack::StackItem& obj, Serializer& serializer) +{ + serializer.increase_container_depth(); + serde::Serializable::serialize(obj.index, serializer); + serde::Serializable::serialize(obj.witness, serializer); + serializer.decrease_container_depth(); +} + +template <> +template +WitnessStack::StackItem serde::Deserializable::deserialize(Deserializer& deserializer) +{ + deserializer.increase_container_depth(); + WitnessStack::StackItem obj; + obj.index = serde::Deserializable::deserialize(deserializer); + obj.witness = serde::Deserializable::deserialize(deserializer); + deserializer.decrease_container_depth(); + return obj; +} + +namespace WitnessStack { + +inline bool operator==(const Witness& lhs, const Witness& rhs) +{ + if (!(lhs.value == rhs.value)) { + return false; + } + return true; +} + +inline std::vector Witness::bincodeSerialize() const +{ + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); +} + +inline Witness Witness::bincodeDeserialize(std::vector input) +{ + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw_or_abort("Some input bytes were not read"); + } + return value; +} + +} // end of namespace WitnessStack + +template <> +template +void serde::Serializable::serialize(const WitnessStack::Witness& obj, Serializer& serializer) +{ + serializer.increase_container_depth(); + serde::Serializable::serialize(obj.value, serializer); + serializer.decrease_container_depth(); +} + +template <> +template +WitnessStack::Witness serde::Deserializable::deserialize(Deserializer& deserializer) +{ + deserializer.increase_container_depth(); + WitnessStack::Witness obj; + obj.value = serde::Deserializable::deserialize(deserializer); + deserializer.decrease_container_depth(); + return obj; +} + +namespace WitnessStack { + +inline bool operator==(const WitnessMap& lhs, const WitnessMap& rhs) +{ + if (!(lhs.value == rhs.value)) { + return false; + } + return true; +} + +inline std::vector WitnessMap::bincodeSerialize() const +{ + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); +} + +inline WitnessMap WitnessMap::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 WitnessStack + +template <> +template +void serde::Serializable::serialize(const WitnessStack::WitnessMap& obj, + Serializer& serializer) +{ + serializer.increase_container_depth(); + serde::Serializable::serialize(obj.value, serializer); + serializer.decrease_container_depth(); +} + +template <> +template +WitnessStack::WitnessMap serde::Deserializable::deserialize(Deserializer& deserializer) +{ + deserializer.increase_container_depth(); + WitnessStack::WitnessMap obj; + obj.value = serde::Deserializable::deserialize(deserializer); + deserializer.decrease_container_depth(); + return obj; +} + +namespace WitnessStack { + +inline bool operator==(const WitnessStack& lhs, const WitnessStack& rhs) +{ + if (!(lhs.stack == rhs.stack)) { + return false; + } + return true; +} + +inline std::vector WitnessStack::bincodeSerialize() const +{ + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); +} + +inline WitnessStack WitnessStack::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 WitnessStack + +template <> +template +void serde::Serializable::serialize(const WitnessStack::WitnessStack& obj, + Serializer& serializer) +{ + serializer.increase_container_depth(); + serde::Serializable::serialize(obj.stack, serializer); + serializer.decrease_container_depth(); +} + +template <> +template +WitnessStack::WitnessStack serde::Deserializable::deserialize(Deserializer& deserializer) +{ + deserializer.increase_container_depth(); + WitnessStack::WitnessStack obj; + obj.stack = serde::Deserializable::deserialize(deserializer); + deserializer.decrease_container_depth(); + return obj; +} diff --git a/build_manifest.yml b/build_manifest.yml index c07877468bc0..9ae9eea56d6b 100644 --- a/build_manifest.yml +++ b/build_manifest.yml @@ -28,6 +28,8 @@ noir-packages: buildDir: noir dockerfile: Dockerfile.packages rebuildPatterns: .rebuild_patterns_packages + dependencies: + - bb.js # Builds and runs *all* noir package tests. noir-packages-tests: @@ -36,6 +38,7 @@ noir-packages-tests: rebuildPatterns: .rebuild_patterns_packages dependencies: - noir + - bb.js # Builds the brillig to avm transpiler. avm-transpiler: diff --git a/noir/Dockerfile.packages b/noir/Dockerfile.packages index c45260afaf4d..f6bf8ad67568 100644 --- a/noir/Dockerfile.packages +++ b/noir/Dockerfile.packages @@ -1,4 +1,10 @@ +FROM --platform=linux/amd64 aztecprotocol/bb.js as bb.js + FROM node:20 AS builder + +# Copy in portalled packages. +COPY --from=bb.js /usr/src/barretenberg/ts /usr/src/barretenberg/ts + ENV PATH=${PATH}:/usr/src/noir/noir-repo/target/release RUN curl https://sh.rustup.rs -sSf | bash -s -- -y RUN echo 'source $HOME/.cargo/env' >> $HOME/.bashrc diff --git a/noir/Dockerfile.packages-test b/noir/Dockerfile.packages-test index 33fac5120fb4..6c9c7c9ac48a 100644 --- a/noir/Dockerfile.packages-test +++ b/noir/Dockerfile.packages-test @@ -1,6 +1,12 @@ FROM aztecprotocol/noir AS noir +FROM --platform=linux/amd64 aztecprotocol/bb.js as bb.js FROM node:20 AS builder +COPY --from=bb.js /usr/src/barretenberg/ts /usr/src/barretenberg/ts + +WORKDIR /usr/src/barretenberg/ts +RUN yarn --immutable + COPY --from=noir /usr/src/noir/noir-repo/target/release /usr/src/noir/noir-repo/target/release ENV PATH=${PATH}:/usr/src/noir/noir-repo/target/release RUN curl https://sh.rustup.rs -sSf | bash -s -- -y diff --git a/noir/noir-repo/acvm-repo/acir/codegen/acir.cpp b/noir/noir-repo/acvm-repo/acir/codegen/acir.cpp index 46809727000a..2fd8180b5b7f 100644 --- a/noir/noir-repo/acvm-repo/acir/codegen/acir.cpp +++ b/noir/noir-repo/acvm-repo/acir/codegen/acir.cpp @@ -3,7 +3,7 @@ #include "serde.hpp" #include "bincode.hpp" -namespace Circuit { +namespace Program { struct BinaryFieldOp { @@ -140,7 +140,7 @@ namespace Circuit { }; struct HeapArray { - Circuit::MemoryAddress pointer; + Program::MemoryAddress pointer; uint64_t size; friend bool operator==(const HeapArray&, const HeapArray&); @@ -149,8 +149,8 @@ namespace Circuit { }; struct HeapVector { - Circuit::MemoryAddress pointer; - Circuit::MemoryAddress size; + Program::MemoryAddress pointer; + Program::MemoryAddress size; friend bool operator==(const HeapVector&, const HeapVector&); std::vector bincodeSerialize() const; @@ -160,8 +160,8 @@ namespace Circuit { struct BlackBoxOp { struct Sha256 { - Circuit::HeapVector message; - Circuit::HeapArray output; + Program::HeapVector message; + Program::HeapArray output; friend bool operator==(const Sha256&, const Sha256&); std::vector bincodeSerialize() const; @@ -169,8 +169,8 @@ namespace Circuit { }; struct Blake2s { - Circuit::HeapVector message; - Circuit::HeapArray output; + Program::HeapVector message; + Program::HeapArray output; friend bool operator==(const Blake2s&, const Blake2s&); std::vector bincodeSerialize() const; @@ -178,8 +178,8 @@ namespace Circuit { }; struct Blake3 { - Circuit::HeapVector message; - Circuit::HeapArray output; + Program::HeapVector message; + Program::HeapArray output; friend bool operator==(const Blake3&, const Blake3&); std::vector bincodeSerialize() const; @@ -187,8 +187,8 @@ namespace Circuit { }; struct Keccak256 { - Circuit::HeapVector message; - Circuit::HeapArray output; + Program::HeapVector message; + Program::HeapArray output; friend bool operator==(const Keccak256&, const Keccak256&); std::vector bincodeSerialize() const; @@ -196,8 +196,8 @@ namespace Circuit { }; struct Keccakf1600 { - Circuit::HeapVector message; - Circuit::HeapArray output; + Program::HeapVector message; + Program::HeapArray output; friend bool operator==(const Keccakf1600&, const Keccakf1600&); std::vector bincodeSerialize() const; @@ -205,11 +205,11 @@ namespace Circuit { }; struct EcdsaSecp256k1 { - Circuit::HeapVector hashed_msg; - Circuit::HeapArray public_key_x; - Circuit::HeapArray public_key_y; - Circuit::HeapArray signature; - Circuit::MemoryAddress result; + Program::HeapVector hashed_msg; + Program::HeapArray public_key_x; + Program::HeapArray public_key_y; + Program::HeapArray signature; + Program::MemoryAddress result; friend bool operator==(const EcdsaSecp256k1&, const EcdsaSecp256k1&); std::vector bincodeSerialize() const; @@ -217,11 +217,11 @@ namespace Circuit { }; struct EcdsaSecp256r1 { - Circuit::HeapVector hashed_msg; - Circuit::HeapArray public_key_x; - Circuit::HeapArray public_key_y; - Circuit::HeapArray signature; - Circuit::MemoryAddress result; + Program::HeapVector hashed_msg; + Program::HeapArray public_key_x; + Program::HeapArray public_key_y; + Program::HeapArray signature; + Program::MemoryAddress result; friend bool operator==(const EcdsaSecp256r1&, const EcdsaSecp256r1&); std::vector bincodeSerialize() const; @@ -229,11 +229,11 @@ namespace Circuit { }; struct SchnorrVerify { - Circuit::MemoryAddress public_key_x; - Circuit::MemoryAddress public_key_y; - Circuit::HeapVector message; - Circuit::HeapVector signature; - Circuit::MemoryAddress result; + Program::MemoryAddress public_key_x; + Program::MemoryAddress public_key_y; + Program::HeapVector message; + Program::HeapVector signature; + Program::MemoryAddress result; friend bool operator==(const SchnorrVerify&, const SchnorrVerify&); std::vector bincodeSerialize() const; @@ -241,9 +241,9 @@ namespace Circuit { }; struct PedersenCommitment { - Circuit::HeapVector inputs; - Circuit::MemoryAddress domain_separator; - Circuit::HeapArray output; + Program::HeapVector inputs; + Program::MemoryAddress domain_separator; + Program::HeapArray output; friend bool operator==(const PedersenCommitment&, const PedersenCommitment&); std::vector bincodeSerialize() const; @@ -251,9 +251,9 @@ namespace Circuit { }; struct PedersenHash { - Circuit::HeapVector inputs; - Circuit::MemoryAddress domain_separator; - Circuit::MemoryAddress output; + Program::HeapVector inputs; + Program::MemoryAddress domain_separator; + Program::MemoryAddress output; friend bool operator==(const PedersenHash&, const PedersenHash&); std::vector bincodeSerialize() const; @@ -261,9 +261,9 @@ namespace Circuit { }; struct FixedBaseScalarMul { - Circuit::MemoryAddress low; - Circuit::MemoryAddress high; - Circuit::HeapArray result; + Program::MemoryAddress low; + Program::MemoryAddress high; + Program::HeapArray result; friend bool operator==(const FixedBaseScalarMul&, const FixedBaseScalarMul&); std::vector bincodeSerialize() const; @@ -271,11 +271,11 @@ namespace Circuit { }; struct EmbeddedCurveAdd { - Circuit::MemoryAddress input1_x; - Circuit::MemoryAddress input1_y; - Circuit::MemoryAddress input2_x; - Circuit::MemoryAddress input2_y; - Circuit::HeapArray result; + Program::MemoryAddress input1_x; + Program::MemoryAddress input1_y; + Program::MemoryAddress input2_x; + Program::MemoryAddress input2_y; + Program::HeapArray result; friend bool operator==(const EmbeddedCurveAdd&, const EmbeddedCurveAdd&); std::vector bincodeSerialize() const; @@ -283,9 +283,9 @@ namespace Circuit { }; struct BigIntAdd { - Circuit::MemoryAddress lhs; - Circuit::MemoryAddress rhs; - Circuit::MemoryAddress output; + Program::MemoryAddress lhs; + Program::MemoryAddress rhs; + Program::MemoryAddress output; friend bool operator==(const BigIntAdd&, const BigIntAdd&); std::vector bincodeSerialize() const; @@ -293,9 +293,9 @@ namespace Circuit { }; struct BigIntSub { - Circuit::MemoryAddress lhs; - Circuit::MemoryAddress rhs; - Circuit::MemoryAddress output; + Program::MemoryAddress lhs; + Program::MemoryAddress rhs; + Program::MemoryAddress output; friend bool operator==(const BigIntSub&, const BigIntSub&); std::vector bincodeSerialize() const; @@ -303,9 +303,9 @@ namespace Circuit { }; struct BigIntMul { - Circuit::MemoryAddress lhs; - Circuit::MemoryAddress rhs; - Circuit::MemoryAddress output; + Program::MemoryAddress lhs; + Program::MemoryAddress rhs; + Program::MemoryAddress output; friend bool operator==(const BigIntMul&, const BigIntMul&); std::vector bincodeSerialize() const; @@ -313,9 +313,9 @@ namespace Circuit { }; struct BigIntDiv { - Circuit::MemoryAddress lhs; - Circuit::MemoryAddress rhs; - Circuit::MemoryAddress output; + Program::MemoryAddress lhs; + Program::MemoryAddress rhs; + Program::MemoryAddress output; friend bool operator==(const BigIntDiv&, const BigIntDiv&); std::vector bincodeSerialize() const; @@ -323,9 +323,9 @@ namespace Circuit { }; struct BigIntFromLeBytes { - Circuit::HeapVector inputs; - Circuit::HeapVector modulus; - Circuit::MemoryAddress output; + Program::HeapVector inputs; + Program::HeapVector modulus; + Program::MemoryAddress output; friend bool operator==(const BigIntFromLeBytes&, const BigIntFromLeBytes&); std::vector bincodeSerialize() const; @@ -333,8 +333,8 @@ namespace Circuit { }; struct BigIntToLeBytes { - Circuit::MemoryAddress input; - Circuit::HeapVector output; + Program::MemoryAddress input; + Program::HeapVector output; friend bool operator==(const BigIntToLeBytes&, const BigIntToLeBytes&); std::vector bincodeSerialize() const; @@ -342,9 +342,9 @@ namespace Circuit { }; struct Poseidon2Permutation { - Circuit::HeapVector message; - Circuit::HeapArray output; - Circuit::MemoryAddress len; + Program::HeapVector message; + Program::HeapArray output; + Program::MemoryAddress len; friend bool operator==(const Poseidon2Permutation&, const Poseidon2Permutation&); std::vector bincodeSerialize() const; @@ -352,9 +352,9 @@ namespace Circuit { }; struct Sha256Compression { - Circuit::HeapVector input; - Circuit::HeapVector hash_values; - Circuit::HeapArray output; + Program::HeapVector input; + Program::HeapVector hash_values; + Program::HeapArray output; friend bool operator==(const Sha256Compression&, const Sha256Compression&); std::vector bincodeSerialize() const; @@ -379,7 +379,7 @@ namespace Circuit { }; struct Array { - std::vector value_types; + std::vector value_types; uint64_t size; friend bool operator==(const Array&, const Array&); @@ -388,7 +388,7 @@ namespace Circuit { }; struct Vector { - std::vector value_types; + std::vector value_types; friend bool operator==(const Vector&, const Vector&); std::vector bincodeSerialize() const; @@ -413,7 +413,7 @@ namespace Circuit { struct ValueOrArray { struct MemoryAddress { - Circuit::MemoryAddress value; + Program::MemoryAddress value; friend bool operator==(const MemoryAddress&, const MemoryAddress&); std::vector bincodeSerialize() const; @@ -421,7 +421,7 @@ namespace Circuit { }; struct HeapArray { - Circuit::HeapArray value; + Program::HeapArray value; friend bool operator==(const HeapArray&, const HeapArray&); std::vector bincodeSerialize() const; @@ -429,7 +429,7 @@ namespace Circuit { }; struct HeapVector { - Circuit::HeapVector value; + Program::HeapVector value; friend bool operator==(const HeapVector&, const HeapVector&); std::vector bincodeSerialize() const; @@ -446,10 +446,10 @@ namespace Circuit { struct BrilligOpcode { struct BinaryFieldOp { - Circuit::MemoryAddress destination; - Circuit::BinaryFieldOp op; - Circuit::MemoryAddress lhs; - Circuit::MemoryAddress rhs; + Program::MemoryAddress destination; + Program::BinaryFieldOp op; + Program::MemoryAddress lhs; + Program::MemoryAddress rhs; friend bool operator==(const BinaryFieldOp&, const BinaryFieldOp&); std::vector bincodeSerialize() const; @@ -457,11 +457,11 @@ namespace Circuit { }; struct BinaryIntOp { - Circuit::MemoryAddress destination; - Circuit::BinaryIntOp op; + Program::MemoryAddress destination; + Program::BinaryIntOp op; uint32_t bit_size; - Circuit::MemoryAddress lhs; - Circuit::MemoryAddress rhs; + Program::MemoryAddress lhs; + Program::MemoryAddress rhs; friend bool operator==(const BinaryIntOp&, const BinaryIntOp&); std::vector bincodeSerialize() const; @@ -469,8 +469,8 @@ namespace Circuit { }; struct Cast { - Circuit::MemoryAddress destination; - Circuit::MemoryAddress source; + Program::MemoryAddress destination; + Program::MemoryAddress source; uint32_t bit_size; friend bool operator==(const Cast&, const Cast&); @@ -479,7 +479,7 @@ namespace Circuit { }; struct JumpIfNot { - Circuit::MemoryAddress condition; + Program::MemoryAddress condition; uint64_t location; friend bool operator==(const JumpIfNot&, const JumpIfNot&); @@ -488,7 +488,7 @@ namespace Circuit { }; struct JumpIf { - Circuit::MemoryAddress condition; + Program::MemoryAddress condition; uint64_t location; friend bool operator==(const JumpIf&, const JumpIf&); @@ -505,7 +505,7 @@ namespace Circuit { }; struct CalldataCopy { - Circuit::MemoryAddress destination_address; + Program::MemoryAddress destination_address; uint64_t size; uint64_t offset; @@ -523,9 +523,9 @@ namespace Circuit { }; struct Const { - Circuit::MemoryAddress destination; + Program::MemoryAddress destination; uint32_t bit_size; - Circuit::Value value; + Program::Value value; friend bool operator==(const Const&, const Const&); std::vector bincodeSerialize() const; @@ -540,10 +540,10 @@ namespace Circuit { struct ForeignCall { std::string function; - std::vector destinations; - std::vector destination_value_types; - std::vector inputs; - std::vector input_value_types; + std::vector destinations; + std::vector destination_value_types; + std::vector inputs; + std::vector input_value_types; friend bool operator==(const ForeignCall&, const ForeignCall&); std::vector bincodeSerialize() const; @@ -551,8 +551,8 @@ namespace Circuit { }; struct Mov { - Circuit::MemoryAddress destination; - Circuit::MemoryAddress source; + Program::MemoryAddress destination; + Program::MemoryAddress source; friend bool operator==(const Mov&, const Mov&); std::vector bincodeSerialize() const; @@ -560,8 +560,8 @@ namespace Circuit { }; struct Load { - Circuit::MemoryAddress destination; - Circuit::MemoryAddress source_pointer; + Program::MemoryAddress destination; + Program::MemoryAddress source_pointer; friend bool operator==(const Load&, const Load&); std::vector bincodeSerialize() const; @@ -569,8 +569,8 @@ namespace Circuit { }; struct Store { - Circuit::MemoryAddress destination_pointer; - Circuit::MemoryAddress source; + Program::MemoryAddress destination_pointer; + Program::MemoryAddress source; friend bool operator==(const Store&, const Store&); std::vector bincodeSerialize() const; @@ -578,7 +578,7 @@ namespace Circuit { }; struct BlackBox { - Circuit::BlackBoxOp value; + Program::BlackBoxOp value; friend bool operator==(const BlackBox&, const BlackBox&); std::vector bincodeSerialize() const; @@ -616,7 +616,7 @@ namespace Circuit { }; struct FunctionInput { - Circuit::Witness witness; + Program::Witness witness; uint32_t num_bits; friend bool operator==(const FunctionInput&, const FunctionInput&); @@ -627,9 +627,9 @@ namespace Circuit { struct BlackBoxFuncCall { struct AND { - Circuit::FunctionInput lhs; - Circuit::FunctionInput rhs; - Circuit::Witness output; + Program::FunctionInput lhs; + Program::FunctionInput rhs; + Program::Witness output; friend bool operator==(const AND&, const AND&); std::vector bincodeSerialize() const; @@ -637,9 +637,9 @@ namespace Circuit { }; struct XOR { - Circuit::FunctionInput lhs; - Circuit::FunctionInput rhs; - Circuit::Witness output; + Program::FunctionInput lhs; + Program::FunctionInput rhs; + Program::Witness output; friend bool operator==(const XOR&, const XOR&); std::vector bincodeSerialize() const; @@ -647,7 +647,7 @@ namespace Circuit { }; struct RANGE { - Circuit::FunctionInput input; + Program::FunctionInput input; friend bool operator==(const RANGE&, const RANGE&); std::vector bincodeSerialize() const; @@ -655,8 +655,8 @@ namespace Circuit { }; struct SHA256 { - std::vector inputs; - std::vector outputs; + std::vector inputs; + std::vector outputs; friend bool operator==(const SHA256&, const SHA256&); std::vector bincodeSerialize() const; @@ -664,8 +664,8 @@ namespace Circuit { }; struct Blake2s { - std::vector inputs; - std::vector outputs; + std::vector inputs; + std::vector outputs; friend bool operator==(const Blake2s&, const Blake2s&); std::vector bincodeSerialize() const; @@ -673,8 +673,8 @@ namespace Circuit { }; struct Blake3 { - std::vector inputs; - std::vector outputs; + std::vector inputs; + std::vector outputs; friend bool operator==(const Blake3&, const Blake3&); std::vector bincodeSerialize() const; @@ -682,11 +682,11 @@ namespace Circuit { }; struct SchnorrVerify { - Circuit::FunctionInput public_key_x; - Circuit::FunctionInput public_key_y; - std::vector signature; - std::vector message; - Circuit::Witness output; + Program::FunctionInput public_key_x; + Program::FunctionInput public_key_y; + std::vector signature; + std::vector message; + Program::Witness output; friend bool operator==(const SchnorrVerify&, const SchnorrVerify&); std::vector bincodeSerialize() const; @@ -694,9 +694,9 @@ namespace Circuit { }; struct PedersenCommitment { - std::vector inputs; + std::vector inputs; uint32_t domain_separator; - std::array outputs; + std::array outputs; friend bool operator==(const PedersenCommitment&, const PedersenCommitment&); std::vector bincodeSerialize() const; @@ -704,9 +704,9 @@ namespace Circuit { }; struct PedersenHash { - std::vector inputs; + std::vector inputs; uint32_t domain_separator; - Circuit::Witness output; + Program::Witness output; friend bool operator==(const PedersenHash&, const PedersenHash&); std::vector bincodeSerialize() const; @@ -714,11 +714,11 @@ namespace Circuit { }; struct EcdsaSecp256k1 { - std::vector public_key_x; - std::vector public_key_y; - std::vector signature; - std::vector hashed_message; - Circuit::Witness output; + std::vector public_key_x; + std::vector public_key_y; + std::vector signature; + std::vector hashed_message; + Program::Witness output; friend bool operator==(const EcdsaSecp256k1&, const EcdsaSecp256k1&); std::vector bincodeSerialize() const; @@ -726,11 +726,11 @@ namespace Circuit { }; struct EcdsaSecp256r1 { - std::vector public_key_x; - std::vector public_key_y; - std::vector signature; - std::vector hashed_message; - Circuit::Witness output; + std::vector public_key_x; + std::vector public_key_y; + std::vector signature; + std::vector hashed_message; + Program::Witness output; friend bool operator==(const EcdsaSecp256r1&, const EcdsaSecp256r1&); std::vector bincodeSerialize() const; @@ -738,9 +738,9 @@ namespace Circuit { }; struct FixedBaseScalarMul { - Circuit::FunctionInput low; - Circuit::FunctionInput high; - std::array outputs; + Program::FunctionInput low; + Program::FunctionInput high; + std::array outputs; friend bool operator==(const FixedBaseScalarMul&, const FixedBaseScalarMul&); std::vector bincodeSerialize() const; @@ -748,11 +748,11 @@ namespace Circuit { }; struct EmbeddedCurveAdd { - Circuit::FunctionInput input1_x; - Circuit::FunctionInput input1_y; - Circuit::FunctionInput input2_x; - Circuit::FunctionInput input2_y; - std::array outputs; + Program::FunctionInput input1_x; + Program::FunctionInput input1_y; + Program::FunctionInput input2_x; + Program::FunctionInput input2_y; + std::array outputs; friend bool operator==(const EmbeddedCurveAdd&, const EmbeddedCurveAdd&); std::vector bincodeSerialize() const; @@ -760,8 +760,8 @@ namespace Circuit { }; struct Keccak256 { - std::vector inputs; - std::vector outputs; + std::vector inputs; + std::vector outputs; friend bool operator==(const Keccak256&, const Keccak256&); std::vector bincodeSerialize() const; @@ -769,9 +769,9 @@ namespace Circuit { }; struct Keccak256VariableLength { - std::vector inputs; - Circuit::FunctionInput var_message_size; - std::vector outputs; + std::vector inputs; + Program::FunctionInput var_message_size; + std::vector outputs; friend bool operator==(const Keccak256VariableLength&, const Keccak256VariableLength&); std::vector bincodeSerialize() const; @@ -779,8 +779,8 @@ namespace Circuit { }; struct Keccakf1600 { - std::vector inputs; - std::vector outputs; + std::vector inputs; + std::vector outputs; friend bool operator==(const Keccakf1600&, const Keccakf1600&); std::vector bincodeSerialize() const; @@ -788,10 +788,10 @@ namespace Circuit { }; struct RecursiveAggregation { - std::vector verification_key; - std::vector proof; - std::vector public_inputs; - Circuit::FunctionInput key_hash; + std::vector verification_key; + std::vector proof; + std::vector public_inputs; + Program::FunctionInput key_hash; friend bool operator==(const RecursiveAggregation&, const RecursiveAggregation&); std::vector bincodeSerialize() const; @@ -839,7 +839,7 @@ namespace Circuit { }; struct BigIntFromLeBytes { - std::vector inputs; + std::vector inputs; std::vector modulus; uint32_t output; @@ -850,7 +850,7 @@ namespace Circuit { struct BigIntToLeBytes { uint32_t input; - std::vector outputs; + std::vector outputs; friend bool operator==(const BigIntToLeBytes&, const BigIntToLeBytes&); std::vector bincodeSerialize() const; @@ -858,8 +858,8 @@ namespace Circuit { }; struct Poseidon2Permutation { - std::vector inputs; - std::vector outputs; + std::vector inputs; + std::vector outputs; uint32_t len; friend bool operator==(const Poseidon2Permutation&, const Poseidon2Permutation&); @@ -868,9 +868,9 @@ namespace Circuit { }; struct Sha256Compression { - std::vector inputs; - std::vector hash_values; - std::vector outputs; + std::vector inputs; + std::vector hash_values; + std::vector outputs; friend bool operator==(const Sha256Compression&, const Sha256Compression&); std::vector bincodeSerialize() const; @@ -893,8 +893,8 @@ namespace Circuit { }; struct Expression { - std::vector> mul_terms; - std::vector> linear_combinations; + std::vector> mul_terms; + std::vector> linear_combinations; std::string q_c; friend bool operator==(const Expression&, const Expression&); @@ -905,7 +905,7 @@ namespace Circuit { struct BrilligInputs { struct Single { - Circuit::Expression value; + Program::Expression value; friend bool operator==(const Single&, const Single&); std::vector bincodeSerialize() const; @@ -913,7 +913,7 @@ namespace Circuit { }; struct Array { - std::vector value; + std::vector value; friend bool operator==(const Array&, const Array&); std::vector bincodeSerialize() const; @@ -921,7 +921,7 @@ namespace Circuit { }; struct MemoryArray { - Circuit::BlockId value; + Program::BlockId value; friend bool operator==(const MemoryArray&, const MemoryArray&); std::vector bincodeSerialize() const; @@ -938,7 +938,7 @@ namespace Circuit { struct BrilligOutputs { struct Simple { - Circuit::Witness value; + Program::Witness value; friend bool operator==(const Simple&, const Simple&); std::vector bincodeSerialize() const; @@ -946,7 +946,7 @@ namespace Circuit { }; struct Array { - std::vector value; + std::vector value; friend bool operator==(const Array&, const Array&); std::vector bincodeSerialize() const; @@ -961,10 +961,10 @@ namespace Circuit { }; struct Brillig { - std::vector inputs; - std::vector outputs; - std::vector bytecode; - std::optional predicate; + std::vector inputs; + std::vector outputs; + std::vector bytecode; + std::optional predicate; friend bool operator==(const Brillig&, const Brillig&); std::vector bincodeSerialize() const; @@ -974,8 +974,8 @@ namespace Circuit { struct Directive { struct ToLeRadix { - Circuit::Expression a; - std::vector b; + Program::Expression a; + std::vector b; uint32_t radix; friend bool operator==(const ToLeRadix&, const ToLeRadix&); @@ -991,9 +991,9 @@ namespace Circuit { }; struct MemOp { - Circuit::Expression operation; - Circuit::Expression index; - Circuit::Expression value; + Program::Expression operation; + Program::Expression index; + Program::Expression value; friend bool operator==(const MemOp&, const MemOp&); std::vector bincodeSerialize() const; @@ -1003,7 +1003,7 @@ namespace Circuit { struct Opcode { struct AssertZero { - Circuit::Expression value; + Program::Expression value; friend bool operator==(const AssertZero&, const AssertZero&); std::vector bincodeSerialize() const; @@ -1011,7 +1011,7 @@ namespace Circuit { }; struct BlackBoxFuncCall { - Circuit::BlackBoxFuncCall value; + Program::BlackBoxFuncCall value; friend bool operator==(const BlackBoxFuncCall&, const BlackBoxFuncCall&); std::vector bincodeSerialize() const; @@ -1019,7 +1019,7 @@ namespace Circuit { }; struct Directive { - Circuit::Directive value; + Program::Directive value; friend bool operator==(const Directive&, const Directive&); std::vector bincodeSerialize() const; @@ -1027,7 +1027,7 @@ namespace Circuit { }; struct Brillig { - Circuit::Brillig value; + Program::Brillig value; friend bool operator==(const Brillig&, const Brillig&); std::vector bincodeSerialize() const; @@ -1035,9 +1035,9 @@ namespace Circuit { }; struct MemoryOp { - Circuit::BlockId block_id; - Circuit::MemOp op; - std::optional predicate; + Program::BlockId block_id; + Program::MemOp op; + std::optional predicate; friend bool operator==(const MemoryOp&, const MemoryOp&); std::vector bincodeSerialize() const; @@ -1045,8 +1045,8 @@ namespace Circuit { }; struct MemoryInit { - Circuit::BlockId block_id; - std::vector init; + Program::BlockId block_id; + std::vector init; friend bool operator==(const MemoryInit&, const MemoryInit&); std::vector bincodeSerialize() const; @@ -1055,8 +1055,8 @@ namespace Circuit { struct Call { uint32_t id; - std::vector inputs; - std::vector outputs; + std::vector inputs; + std::vector outputs; friend bool operator==(const Call&, const Call&); std::vector bincodeSerialize() const; @@ -1120,7 +1120,7 @@ namespace Circuit { }; struct PublicInputs { - std::vector value; + std::vector value; friend bool operator==(const PublicInputs&, const PublicInputs&); std::vector bincodeSerialize() const; @@ -1129,12 +1129,12 @@ namespace Circuit { struct Circuit { uint32_t current_witness_index; - std::vector opcodes; - Circuit::ExpressionWidth expression_width; - std::vector private_parameters; - Circuit::PublicInputs public_parameters; - Circuit::PublicInputs return_values; - std::vector> assert_messages; + std::vector opcodes; + Program::ExpressionWidth expression_width; + std::vector private_parameters; + Program::PublicInputs public_parameters; + Program::PublicInputs return_values; + std::vector> assert_messages; bool recursive; friend bool operator==(const Circuit&, const Circuit&); @@ -1142,10 +1142,18 @@ namespace Circuit { static Circuit bincodeDeserialize(std::vector); }; -} // end of namespace Circuit + struct Program { + std::vector functions; + friend bool operator==(const Program&, const Program&); + std::vector bincodeSerialize() const; + static Program bincodeDeserialize(std::vector); + }; + +} // end of namespace Program -namespace Circuit { + +namespace Program { inline bool operator==(const BinaryFieldOp &lhs, const BinaryFieldOp &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -1167,11 +1175,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryFieldOp &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BinaryFieldOp &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -1179,15 +1187,15 @@ void serde::Serializable::serialize(const Circuit::Binar template <> template -Circuit::BinaryFieldOp serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::BinaryFieldOp serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::BinaryFieldOp obj; + Program::BinaryFieldOp obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryFieldOp::Add &lhs, const BinaryFieldOp::Add &rhs) { return true; @@ -1208,21 +1216,21 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryFieldOp::Add &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BinaryFieldOp::Add &obj, Serializer &serializer) { } template <> template -Circuit::BinaryFieldOp::Add serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BinaryFieldOp::Add obj; +Program::BinaryFieldOp::Add serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryFieldOp::Add obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryFieldOp::Sub &lhs, const BinaryFieldOp::Sub &rhs) { return true; @@ -1243,21 +1251,21 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryFieldOp::Sub &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BinaryFieldOp::Sub &obj, Serializer &serializer) { } template <> template -Circuit::BinaryFieldOp::Sub serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BinaryFieldOp::Sub obj; +Program::BinaryFieldOp::Sub serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryFieldOp::Sub obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryFieldOp::Mul &lhs, const BinaryFieldOp::Mul &rhs) { return true; @@ -1278,21 +1286,21 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryFieldOp::Mul &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BinaryFieldOp::Mul &obj, Serializer &serializer) { } template <> template -Circuit::BinaryFieldOp::Mul serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BinaryFieldOp::Mul obj; +Program::BinaryFieldOp::Mul serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryFieldOp::Mul obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryFieldOp::Div &lhs, const BinaryFieldOp::Div &rhs) { return true; @@ -1313,21 +1321,21 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryFieldOp::Div &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BinaryFieldOp::Div &obj, Serializer &serializer) { } template <> template -Circuit::BinaryFieldOp::Div serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BinaryFieldOp::Div obj; +Program::BinaryFieldOp::Div serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryFieldOp::Div obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryFieldOp::Equals &lhs, const BinaryFieldOp::Equals &rhs) { return true; @@ -1348,21 +1356,21 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryFieldOp::Equals &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BinaryFieldOp::Equals &obj, Serializer &serializer) { } template <> template -Circuit::BinaryFieldOp::Equals serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BinaryFieldOp::Equals obj; +Program::BinaryFieldOp::Equals serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryFieldOp::Equals obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp &lhs, const BinaryIntOp &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -1384,11 +1392,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryIntOp &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BinaryIntOp &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -1396,15 +1404,15 @@ void serde::Serializable::serialize(const Circuit::BinaryI template <> template -Circuit::BinaryIntOp serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::BinaryIntOp serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::BinaryIntOp obj; + Program::BinaryIntOp obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp::Add &lhs, const BinaryIntOp::Add &rhs) { return true; @@ -1425,21 +1433,21 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryIntOp::Add &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BinaryIntOp::Add &obj, Serializer &serializer) { } template <> template -Circuit::BinaryIntOp::Add serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BinaryIntOp::Add obj; +Program::BinaryIntOp::Add serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryIntOp::Add obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp::Sub &lhs, const BinaryIntOp::Sub &rhs) { return true; @@ -1460,21 +1468,21 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryIntOp::Sub &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BinaryIntOp::Sub &obj, Serializer &serializer) { } template <> template -Circuit::BinaryIntOp::Sub serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BinaryIntOp::Sub obj; +Program::BinaryIntOp::Sub serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryIntOp::Sub obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp::Mul &lhs, const BinaryIntOp::Mul &rhs) { return true; @@ -1495,21 +1503,21 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryIntOp::Mul &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BinaryIntOp::Mul &obj, Serializer &serializer) { } template <> template -Circuit::BinaryIntOp::Mul serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BinaryIntOp::Mul obj; +Program::BinaryIntOp::Mul serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryIntOp::Mul obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp::SignedDiv &lhs, const BinaryIntOp::SignedDiv &rhs) { return true; @@ -1530,21 +1538,21 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryIntOp::SignedDiv &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BinaryIntOp::SignedDiv &obj, Serializer &serializer) { } template <> template -Circuit::BinaryIntOp::SignedDiv serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BinaryIntOp::SignedDiv obj; +Program::BinaryIntOp::SignedDiv serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryIntOp::SignedDiv obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp::UnsignedDiv &lhs, const BinaryIntOp::UnsignedDiv &rhs) { return true; @@ -1565,21 +1573,21 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryIntOp::UnsignedDiv &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BinaryIntOp::UnsignedDiv &obj, Serializer &serializer) { } template <> template -Circuit::BinaryIntOp::UnsignedDiv serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BinaryIntOp::UnsignedDiv obj; +Program::BinaryIntOp::UnsignedDiv serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryIntOp::UnsignedDiv obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp::Equals &lhs, const BinaryIntOp::Equals &rhs) { return true; @@ -1600,21 +1608,21 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryIntOp::Equals &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BinaryIntOp::Equals &obj, Serializer &serializer) { } template <> template -Circuit::BinaryIntOp::Equals serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BinaryIntOp::Equals obj; +Program::BinaryIntOp::Equals serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryIntOp::Equals obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp::LessThan &lhs, const BinaryIntOp::LessThan &rhs) { return true; @@ -1635,21 +1643,21 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryIntOp::LessThan &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BinaryIntOp::LessThan &obj, Serializer &serializer) { } template <> template -Circuit::BinaryIntOp::LessThan serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BinaryIntOp::LessThan obj; +Program::BinaryIntOp::LessThan serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryIntOp::LessThan obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp::LessThanEquals &lhs, const BinaryIntOp::LessThanEquals &rhs) { return true; @@ -1670,21 +1678,21 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryIntOp::LessThanEquals &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BinaryIntOp::LessThanEquals &obj, Serializer &serializer) { } template <> template -Circuit::BinaryIntOp::LessThanEquals serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BinaryIntOp::LessThanEquals obj; +Program::BinaryIntOp::LessThanEquals serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryIntOp::LessThanEquals obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp::And &lhs, const BinaryIntOp::And &rhs) { return true; @@ -1705,21 +1713,21 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryIntOp::And &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BinaryIntOp::And &obj, Serializer &serializer) { } template <> template -Circuit::BinaryIntOp::And serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BinaryIntOp::And obj; +Program::BinaryIntOp::And serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryIntOp::And obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp::Or &lhs, const BinaryIntOp::Or &rhs) { return true; @@ -1740,21 +1748,21 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryIntOp::Or &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BinaryIntOp::Or &obj, Serializer &serializer) { } template <> template -Circuit::BinaryIntOp::Or serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BinaryIntOp::Or obj; +Program::BinaryIntOp::Or serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryIntOp::Or obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp::Xor &lhs, const BinaryIntOp::Xor &rhs) { return true; @@ -1775,21 +1783,21 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryIntOp::Xor &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BinaryIntOp::Xor &obj, Serializer &serializer) { } template <> template -Circuit::BinaryIntOp::Xor serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BinaryIntOp::Xor obj; +Program::BinaryIntOp::Xor serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryIntOp::Xor obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp::Shl &lhs, const BinaryIntOp::Shl &rhs) { return true; @@ -1810,21 +1818,21 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryIntOp::Shl &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BinaryIntOp::Shl &obj, Serializer &serializer) { } template <> template -Circuit::BinaryIntOp::Shl serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BinaryIntOp::Shl obj; +Program::BinaryIntOp::Shl serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryIntOp::Shl obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp::Shr &lhs, const BinaryIntOp::Shr &rhs) { return true; @@ -1845,21 +1853,21 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryIntOp::Shr &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BinaryIntOp::Shr &obj, Serializer &serializer) { } template <> template -Circuit::BinaryIntOp::Shr serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BinaryIntOp::Shr obj; +Program::BinaryIntOp::Shr serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryIntOp::Shr obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall &lhs, const BlackBoxFuncCall &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -1881,11 +1889,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -1893,15 +1901,15 @@ void serde::Serializable::serialize(const Circuit::Bl template <> template -Circuit::BlackBoxFuncCall serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::BlackBoxFuncCall serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::BlackBoxFuncCall obj; + Program::BlackBoxFuncCall obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::AND &lhs, const BlackBoxFuncCall::AND &rhs) { if (!(lhs.lhs == rhs.lhs)) { return false; } @@ -1925,11 +1933,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::AND &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::AND &obj, Serializer &serializer) { serde::Serializable::serialize(obj.lhs, serializer); serde::Serializable::serialize(obj.rhs, serializer); serde::Serializable::serialize(obj.output, serializer); @@ -1937,15 +1945,15 @@ void serde::Serializable::serialize(const Circui template <> template -Circuit::BlackBoxFuncCall::AND serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::AND obj; +Program::BlackBoxFuncCall::AND serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::AND obj; obj.lhs = serde::Deserializable::deserialize(deserializer); obj.rhs = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::XOR &lhs, const BlackBoxFuncCall::XOR &rhs) { if (!(lhs.lhs == rhs.lhs)) { return false; } @@ -1969,11 +1977,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::XOR &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::XOR &obj, Serializer &serializer) { serde::Serializable::serialize(obj.lhs, serializer); serde::Serializable::serialize(obj.rhs, serializer); serde::Serializable::serialize(obj.output, serializer); @@ -1981,15 +1989,15 @@ void serde::Serializable::serialize(const Circui template <> template -Circuit::BlackBoxFuncCall::XOR serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::XOR obj; +Program::BlackBoxFuncCall::XOR serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::XOR obj; obj.lhs = serde::Deserializable::deserialize(deserializer); obj.rhs = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::RANGE &lhs, const BlackBoxFuncCall::RANGE &rhs) { if (!(lhs.input == rhs.input)) { return false; } @@ -2011,23 +2019,23 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::RANGE &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::RANGE &obj, Serializer &serializer) { serde::Serializable::serialize(obj.input, serializer); } template <> template -Circuit::BlackBoxFuncCall::RANGE serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::RANGE obj; +Program::BlackBoxFuncCall::RANGE serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::RANGE obj; obj.input = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::SHA256 &lhs, const BlackBoxFuncCall::SHA256 &rhs) { if (!(lhs.inputs == rhs.inputs)) { return false; } @@ -2050,25 +2058,25 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::SHA256 &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::SHA256 &obj, Serializer &serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.outputs, serializer); } template <> template -Circuit::BlackBoxFuncCall::SHA256 serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::SHA256 obj; +Program::BlackBoxFuncCall::SHA256 serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::SHA256 obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::Blake2s &lhs, const BlackBoxFuncCall::Blake2s &rhs) { if (!(lhs.inputs == rhs.inputs)) { return false; } @@ -2091,25 +2099,25 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::Blake2s &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::Blake2s &obj, Serializer &serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.outputs, serializer); } template <> template -Circuit::BlackBoxFuncCall::Blake2s serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::Blake2s obj; +Program::BlackBoxFuncCall::Blake2s serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::Blake2s obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::Blake3 &lhs, const BlackBoxFuncCall::Blake3 &rhs) { if (!(lhs.inputs == rhs.inputs)) { return false; } @@ -2132,25 +2140,25 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::Blake3 &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::Blake3 &obj, Serializer &serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.outputs, serializer); } template <> template -Circuit::BlackBoxFuncCall::Blake3 serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::Blake3 obj; +Program::BlackBoxFuncCall::Blake3 serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::Blake3 obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::SchnorrVerify &lhs, const BlackBoxFuncCall::SchnorrVerify &rhs) { if (!(lhs.public_key_x == rhs.public_key_x)) { return false; } @@ -2176,11 +2184,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::SchnorrVerify &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::SchnorrVerify &obj, Serializer &serializer) { serde::Serializable::serialize(obj.public_key_x, serializer); serde::Serializable::serialize(obj.public_key_y, serializer); serde::Serializable::serialize(obj.signature, serializer); @@ -2190,8 +2198,8 @@ void serde::Serializable::serialize(co template <> template -Circuit::BlackBoxFuncCall::SchnorrVerify serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::SchnorrVerify obj; +Program::BlackBoxFuncCall::SchnorrVerify serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::SchnorrVerify obj; obj.public_key_x = serde::Deserializable::deserialize(deserializer); obj.public_key_y = serde::Deserializable::deserialize(deserializer); obj.signature = serde::Deserializable::deserialize(deserializer); @@ -2200,7 +2208,7 @@ Circuit::BlackBoxFuncCall::SchnorrVerify serde::Deserializable template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::PedersenCommitment &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::PedersenCommitment &obj, Serializer &serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.domain_separator, serializer); serde::Serializable::serialize(obj.outputs, serializer); @@ -2236,15 +2244,15 @@ void serde::Serializable::seriali template <> template -Circuit::BlackBoxFuncCall::PedersenCommitment serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::PedersenCommitment obj; +Program::BlackBoxFuncCall::PedersenCommitment serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::PedersenCommitment obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.domain_separator = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::PedersenHash &lhs, const BlackBoxFuncCall::PedersenHash &rhs) { if (!(lhs.inputs == rhs.inputs)) { return false; } @@ -2268,11 +2276,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::PedersenHash &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::PedersenHash &obj, Serializer &serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.domain_separator, serializer); serde::Serializable::serialize(obj.output, serializer); @@ -2280,15 +2288,15 @@ void serde::Serializable::serialize(con template <> template -Circuit::BlackBoxFuncCall::PedersenHash serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::PedersenHash obj; +Program::BlackBoxFuncCall::PedersenHash serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::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 { +namespace Program { inline bool operator==(const BlackBoxFuncCall::EcdsaSecp256k1 &lhs, const BlackBoxFuncCall::EcdsaSecp256k1 &rhs) { if (!(lhs.public_key_x == rhs.public_key_x)) { return false; } @@ -2314,11 +2322,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::EcdsaSecp256k1 &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::EcdsaSecp256k1 &obj, Serializer &serializer) { serde::Serializable::serialize(obj.public_key_x, serializer); serde::Serializable::serialize(obj.public_key_y, serializer); serde::Serializable::serialize(obj.signature, serializer); @@ -2328,8 +2336,8 @@ void serde::Serializable::serialize(c template <> template -Circuit::BlackBoxFuncCall::EcdsaSecp256k1 serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::EcdsaSecp256k1 obj; +Program::BlackBoxFuncCall::EcdsaSecp256k1 serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::EcdsaSecp256k1 obj; obj.public_key_x = serde::Deserializable::deserialize(deserializer); obj.public_key_y = serde::Deserializable::deserialize(deserializer); obj.signature = serde::Deserializable::deserialize(deserializer); @@ -2338,7 +2346,7 @@ Circuit::BlackBoxFuncCall::EcdsaSecp256k1 serde::Deserializable template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::EcdsaSecp256r1 &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::EcdsaSecp256r1 &obj, Serializer &serializer) { serde::Serializable::serialize(obj.public_key_x, serializer); serde::Serializable::serialize(obj.public_key_y, serializer); serde::Serializable::serialize(obj.signature, serializer); @@ -2378,8 +2386,8 @@ void serde::Serializable::serialize(c template <> template -Circuit::BlackBoxFuncCall::EcdsaSecp256r1 serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::EcdsaSecp256r1 obj; +Program::BlackBoxFuncCall::EcdsaSecp256r1 serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::EcdsaSecp256r1 obj; obj.public_key_x = serde::Deserializable::deserialize(deserializer); obj.public_key_y = serde::Deserializable::deserialize(deserializer); obj.signature = serde::Deserializable::deserialize(deserializer); @@ -2388,7 +2396,7 @@ Circuit::BlackBoxFuncCall::EcdsaSecp256r1 serde::Deserializable template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::FixedBaseScalarMul &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::FixedBaseScalarMul &obj, Serializer &serializer) { serde::Serializable::serialize(obj.low, serializer); serde::Serializable::serialize(obj.high, serializer); serde::Serializable::serialize(obj.outputs, serializer); @@ -2424,15 +2432,15 @@ void serde::Serializable::seriali template <> template -Circuit::BlackBoxFuncCall::FixedBaseScalarMul serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::FixedBaseScalarMul obj; +Program::BlackBoxFuncCall::FixedBaseScalarMul serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::FixedBaseScalarMul obj; obj.low = serde::Deserializable::deserialize(deserializer); obj.high = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::EmbeddedCurveAdd &lhs, const BlackBoxFuncCall::EmbeddedCurveAdd &rhs) { if (!(lhs.input1_x == rhs.input1_x)) { return false; } @@ -2458,11 +2466,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::EmbeddedCurveAdd &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::EmbeddedCurveAdd &obj, Serializer &serializer) { serde::Serializable::serialize(obj.input1_x, serializer); serde::Serializable::serialize(obj.input1_y, serializer); serde::Serializable::serialize(obj.input2_x, serializer); @@ -2472,8 +2480,8 @@ void serde::Serializable::serialize template <> template -Circuit::BlackBoxFuncCall::EmbeddedCurveAdd serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::EmbeddedCurveAdd obj; +Program::BlackBoxFuncCall::EmbeddedCurveAdd serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::EmbeddedCurveAdd obj; obj.input1_x = serde::Deserializable::deserialize(deserializer); obj.input1_y = serde::Deserializable::deserialize(deserializer); obj.input2_x = serde::Deserializable::deserialize(deserializer); @@ -2482,7 +2490,7 @@ Circuit::BlackBoxFuncCall::EmbeddedCurveAdd serde::Deserializable template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::Keccak256 &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::Keccak256 &obj, Serializer &serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.outputs, serializer); } template <> template -Circuit::BlackBoxFuncCall::Keccak256 serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::Keccak256 obj; +Program::BlackBoxFuncCall::Keccak256 serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::Keccak256 obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::Keccak256VariableLength &lhs, const BlackBoxFuncCall::Keccak256VariableLength &rhs) { if (!(lhs.inputs == rhs.inputs)) { return false; } @@ -2547,11 +2555,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::Keccak256VariableLength &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::Keccak256VariableLength &obj, Serializer &serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.var_message_size, serializer); serde::Serializable::serialize(obj.outputs, serializer); @@ -2559,15 +2567,15 @@ void serde::Serializable::se template <> template -Circuit::BlackBoxFuncCall::Keccak256VariableLength serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::Keccak256VariableLength obj; +Program::BlackBoxFuncCall::Keccak256VariableLength serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::Keccak256VariableLength obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.var_message_size = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::Keccakf1600 &lhs, const BlackBoxFuncCall::Keccakf1600 &rhs) { if (!(lhs.inputs == rhs.inputs)) { return false; } @@ -2590,25 +2598,25 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::Keccakf1600 &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::Keccakf1600 &obj, Serializer &serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.outputs, serializer); } template <> template -Circuit::BlackBoxFuncCall::Keccakf1600 serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::Keccakf1600 obj; +Program::BlackBoxFuncCall::Keccakf1600 serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::Keccakf1600 obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::RecursiveAggregation &lhs, const BlackBoxFuncCall::RecursiveAggregation &rhs) { if (!(lhs.verification_key == rhs.verification_key)) { return false; } @@ -2633,11 +2641,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::RecursiveAggregation &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::RecursiveAggregation &obj, Serializer &serializer) { serde::Serializable::serialize(obj.verification_key, serializer); serde::Serializable::serialize(obj.proof, serializer); serde::Serializable::serialize(obj.public_inputs, serializer); @@ -2646,8 +2654,8 @@ void serde::Serializable::seria template <> template -Circuit::BlackBoxFuncCall::RecursiveAggregation serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::RecursiveAggregation obj; +Program::BlackBoxFuncCall::RecursiveAggregation serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::RecursiveAggregation obj; obj.verification_key = serde::Deserializable::deserialize(deserializer); obj.proof = serde::Deserializable::deserialize(deserializer); obj.public_inputs = serde::Deserializable::deserialize(deserializer); @@ -2655,7 +2663,7 @@ Circuit::BlackBoxFuncCall::RecursiveAggregation serde::Deserializable template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::BigIntAdd &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::BigIntAdd &obj, Serializer &serializer) { serde::Serializable::serialize(obj.lhs, serializer); serde::Serializable::serialize(obj.rhs, serializer); serde::Serializable::serialize(obj.output, serializer); @@ -2691,15 +2699,15 @@ void serde::Serializable::serialize(const template <> template -Circuit::BlackBoxFuncCall::BigIntAdd serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::BigIntAdd obj; +Program::BlackBoxFuncCall::BigIntAdd serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::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 { +namespace Program { inline bool operator==(const BlackBoxFuncCall::BigIntSub &lhs, const BlackBoxFuncCall::BigIntSub &rhs) { if (!(lhs.lhs == rhs.lhs)) { return false; } @@ -2723,11 +2731,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::BigIntSub &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::BigIntSub &obj, Serializer &serializer) { serde::Serializable::serialize(obj.lhs, serializer); serde::Serializable::serialize(obj.rhs, serializer); serde::Serializable::serialize(obj.output, serializer); @@ -2735,15 +2743,15 @@ void serde::Serializable::serialize(const template <> template -Circuit::BlackBoxFuncCall::BigIntSub serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::BigIntSub obj; +Program::BlackBoxFuncCall::BigIntSub serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::BigIntSub obj; obj.lhs = serde::Deserializable::deserialize(deserializer); obj.rhs = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::BigIntMul &lhs, const BlackBoxFuncCall::BigIntMul &rhs) { if (!(lhs.lhs == rhs.lhs)) { return false; } @@ -2767,11 +2775,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::BigIntMul &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::BigIntMul &obj, Serializer &serializer) { serde::Serializable::serialize(obj.lhs, serializer); serde::Serializable::serialize(obj.rhs, serializer); serde::Serializable::serialize(obj.output, serializer); @@ -2779,15 +2787,15 @@ void serde::Serializable::serialize(const template <> template -Circuit::BlackBoxFuncCall::BigIntMul serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::BigIntMul obj; +Program::BlackBoxFuncCall::BigIntMul serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::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 { +namespace Program { inline bool operator==(const BlackBoxFuncCall::BigIntDiv &lhs, const BlackBoxFuncCall::BigIntDiv &rhs) { if (!(lhs.lhs == rhs.lhs)) { return false; } @@ -2811,11 +2819,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::BigIntDiv &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::BigIntDiv &obj, Serializer &serializer) { serde::Serializable::serialize(obj.lhs, serializer); serde::Serializable::serialize(obj.rhs, serializer); serde::Serializable::serialize(obj.output, serializer); @@ -2823,15 +2831,15 @@ void serde::Serializable::serialize(const template <> template -Circuit::BlackBoxFuncCall::BigIntDiv serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::BigIntDiv obj; +Program::BlackBoxFuncCall::BigIntDiv serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::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 { +namespace Program { inline bool operator==(const BlackBoxFuncCall::BigIntFromLeBytes &lhs, const BlackBoxFuncCall::BigIntFromLeBytes &rhs) { if (!(lhs.inputs == rhs.inputs)) { return false; } @@ -2855,11 +2863,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::BigIntFromLeBytes &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::BigIntFromLeBytes &obj, Serializer &serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.modulus, serializer); serde::Serializable::serialize(obj.output, serializer); @@ -2867,15 +2875,15 @@ void serde::Serializable::serializ template <> template -Circuit::BlackBoxFuncCall::BigIntFromLeBytes serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::BigIntFromLeBytes obj; +Program::BlackBoxFuncCall::BigIntFromLeBytes serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::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 { +namespace Program { inline bool operator==(const BlackBoxFuncCall::BigIntToLeBytes &lhs, const BlackBoxFuncCall::BigIntToLeBytes &rhs) { if (!(lhs.input == rhs.input)) { return false; } @@ -2898,25 +2906,25 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::BigIntToLeBytes &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::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; +Program::BlackBoxFuncCall::BigIntToLeBytes serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::BigIntToLeBytes obj; obj.input = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::Poseidon2Permutation &lhs, const BlackBoxFuncCall::Poseidon2Permutation &rhs) { if (!(lhs.inputs == rhs.inputs)) { return false; } @@ -2940,11 +2948,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::Poseidon2Permutation &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::Poseidon2Permutation &obj, Serializer &serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.outputs, serializer); serde::Serializable::serialize(obj.len, serializer); @@ -2952,15 +2960,15 @@ void serde::Serializable::seria template <> template -Circuit::BlackBoxFuncCall::Poseidon2Permutation serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::Poseidon2Permutation obj; +Program::BlackBoxFuncCall::Poseidon2Permutation serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::Poseidon2Permutation obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); obj.len = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxFuncCall::Sha256Compression &lhs, const BlackBoxFuncCall::Sha256Compression &rhs) { if (!(lhs.inputs == rhs.inputs)) { return false; } @@ -2984,11 +2992,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxFuncCall::Sha256Compression &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::Sha256Compression &obj, Serializer &serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.hash_values, serializer); serde::Serializable::serialize(obj.outputs, serializer); @@ -2996,15 +3004,15 @@ void serde::Serializable::serializ template <> template -Circuit::BlackBoxFuncCall::Sha256Compression serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxFuncCall::Sha256Compression obj; +Program::BlackBoxFuncCall::Sha256Compression serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::Sha256Compression obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.hash_values = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxOp &lhs, const BlackBoxOp &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -3026,11 +3034,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxOp &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -3038,15 +3046,15 @@ void serde::Serializable::serialize(const Circuit::BlackBox template <> template -Circuit::BlackBoxOp serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::BlackBoxOp serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::BlackBoxOp obj; + Program::BlackBoxOp obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxOp::Sha256 &lhs, const BlackBoxOp::Sha256 &rhs) { if (!(lhs.message == rhs.message)) { return false; } @@ -3069,25 +3077,25 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::Sha256 &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::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; +Program::BlackBoxOp::Sha256 serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxOp::Sha256 obj; obj.message = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxOp::Blake2s &lhs, const BlackBoxOp::Blake2s &rhs) { if (!(lhs.message == rhs.message)) { return false; } @@ -3110,25 +3118,25 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::Blake2s &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::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; +Program::BlackBoxOp::Blake2s serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxOp::Blake2s obj; obj.message = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxOp::Blake3 &lhs, const BlackBoxOp::Blake3 &rhs) { if (!(lhs.message == rhs.message)) { return false; } @@ -3151,25 +3159,25 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::Blake3 &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::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; +Program::BlackBoxOp::Blake3 serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxOp::Blake3 obj; obj.message = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxOp::Keccak256 &lhs, const BlackBoxOp::Keccak256 &rhs) { if (!(lhs.message == rhs.message)) { return false; } @@ -3192,25 +3200,25 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::Keccak256 &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::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; +Program::BlackBoxOp::Keccak256 serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxOp::Keccak256 obj; obj.message = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxOp::Keccakf1600 &lhs, const BlackBoxOp::Keccakf1600 &rhs) { if (!(lhs.message == rhs.message)) { return false; } @@ -3233,25 +3241,25 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::Keccakf1600 &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::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; +Program::BlackBoxOp::Keccakf1600 serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxOp::Keccakf1600 obj; obj.message = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxOp::EcdsaSecp256k1 &lhs, const BlackBoxOp::EcdsaSecp256k1 &rhs) { if (!(lhs.hashed_msg == rhs.hashed_msg)) { return false; } @@ -3277,11 +3285,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::EcdsaSecp256k1 &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::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); @@ -3291,8 +3299,8 @@ void serde::Serializable::serialize(const C template <> template -Circuit::BlackBoxOp::EcdsaSecp256k1 serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxOp::EcdsaSecp256k1 obj; +Program::BlackBoxOp::EcdsaSecp256k1 serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::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); @@ -3301,7 +3309,7 @@ Circuit::BlackBoxOp::EcdsaSecp256k1 serde::Deserializable template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::EcdsaSecp256r1 &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::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); @@ -3341,8 +3349,8 @@ void serde::Serializable::serialize(const C template <> template -Circuit::BlackBoxOp::EcdsaSecp256r1 serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxOp::EcdsaSecp256r1 obj; +Program::BlackBoxOp::EcdsaSecp256r1 serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::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); @@ -3351,7 +3359,7 @@ Circuit::BlackBoxOp::EcdsaSecp256r1 serde::Deserializable template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::SchnorrVerify &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::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); @@ -3391,8 +3399,8 @@ void serde::Serializable::serialize(const Ci template <> template -Circuit::BlackBoxOp::SchnorrVerify serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxOp::SchnorrVerify obj; +Program::BlackBoxOp::SchnorrVerify serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::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); @@ -3401,7 +3409,7 @@ Circuit::BlackBoxOp::SchnorrVerify serde::Deserializable template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::PedersenCommitment &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxOp::PedersenCommitment &obj, Serializer &serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.domain_separator, serializer); serde::Serializable::serialize(obj.output, serializer); @@ -3437,15 +3445,15 @@ void serde::Serializable::serialize(con template <> template -Circuit::BlackBoxOp::PedersenCommitment serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxOp::PedersenCommitment obj; +Program::BlackBoxOp::PedersenCommitment serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::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 { +namespace Program { inline bool operator==(const BlackBoxOp::PedersenHash &lhs, const BlackBoxOp::PedersenHash &rhs) { if (!(lhs.inputs == rhs.inputs)) { return false; } @@ -3469,11 +3477,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::PedersenHash &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxOp::PedersenHash &obj, Serializer &serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.domain_separator, serializer); serde::Serializable::serialize(obj.output, serializer); @@ -3481,15 +3489,15 @@ void serde::Serializable::serialize(const Cir template <> template -Circuit::BlackBoxOp::PedersenHash serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxOp::PedersenHash obj; +Program::BlackBoxOp::PedersenHash serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::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 { +namespace Program { inline bool operator==(const BlackBoxOp::FixedBaseScalarMul &lhs, const BlackBoxOp::FixedBaseScalarMul &rhs) { if (!(lhs.low == rhs.low)) { return false; } @@ -3513,11 +3521,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::FixedBaseScalarMul &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxOp::FixedBaseScalarMul &obj, Serializer &serializer) { serde::Serializable::serialize(obj.low, serializer); serde::Serializable::serialize(obj.high, serializer); serde::Serializable::serialize(obj.result, serializer); @@ -3525,15 +3533,15 @@ void serde::Serializable::serialize(con template <> template -Circuit::BlackBoxOp::FixedBaseScalarMul serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxOp::FixedBaseScalarMul obj; +Program::BlackBoxOp::FixedBaseScalarMul serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::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 { +namespace Program { inline bool operator==(const BlackBoxOp::EmbeddedCurveAdd &lhs, const BlackBoxOp::EmbeddedCurveAdd &rhs) { if (!(lhs.input1_x == rhs.input1_x)) { return false; } @@ -3559,11 +3567,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::EmbeddedCurveAdd &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxOp::EmbeddedCurveAdd &obj, Serializer &serializer) { serde::Serializable::serialize(obj.input1_x, serializer); serde::Serializable::serialize(obj.input1_y, serializer); serde::Serializable::serialize(obj.input2_x, serializer); @@ -3573,8 +3581,8 @@ void serde::Serializable::serialize(const template <> template -Circuit::BlackBoxOp::EmbeddedCurveAdd serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxOp::EmbeddedCurveAdd obj; +Program::BlackBoxOp::EmbeddedCurveAdd serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxOp::EmbeddedCurveAdd obj; obj.input1_x = serde::Deserializable::deserialize(deserializer); obj.input1_y = serde::Deserializable::deserialize(deserializer); obj.input2_x = serde::Deserializable::deserialize(deserializer); @@ -3583,7 +3591,7 @@ Circuit::BlackBoxOp::EmbeddedCurveAdd serde::Deserializable template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::BigIntAdd &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxOp::BigIntAdd &obj, Serializer &serializer) { serde::Serializable::serialize(obj.lhs, serializer); serde::Serializable::serialize(obj.rhs, serializer); serde::Serializable::serialize(obj.output, serializer); @@ -3619,15 +3627,15 @@ void serde::Serializable::serialize(const Circui template <> template -Circuit::BlackBoxOp::BigIntAdd serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxOp::BigIntAdd obj; +Program::BlackBoxOp::BigIntAdd serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::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 { +namespace Program { inline bool operator==(const BlackBoxOp::BigIntSub &lhs, const BlackBoxOp::BigIntSub &rhs) { if (!(lhs.lhs == rhs.lhs)) { return false; } @@ -3651,11 +3659,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::BigIntSub &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxOp::BigIntSub &obj, Serializer &serializer) { serde::Serializable::serialize(obj.lhs, serializer); serde::Serializable::serialize(obj.rhs, serializer); serde::Serializable::serialize(obj.output, serializer); @@ -3663,15 +3671,15 @@ void serde::Serializable::serialize(const Circui template <> template -Circuit::BlackBoxOp::BigIntSub serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxOp::BigIntSub obj; +Program::BlackBoxOp::BigIntSub serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxOp::BigIntSub obj; obj.lhs = serde::Deserializable::deserialize(deserializer); obj.rhs = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxOp::BigIntMul &lhs, const BlackBoxOp::BigIntMul &rhs) { if (!(lhs.lhs == rhs.lhs)) { return false; } @@ -3695,11 +3703,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::BigIntMul &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxOp::BigIntMul &obj, Serializer &serializer) { serde::Serializable::serialize(obj.lhs, serializer); serde::Serializable::serialize(obj.rhs, serializer); serde::Serializable::serialize(obj.output, serializer); @@ -3707,15 +3715,15 @@ void serde::Serializable::serialize(const Circui template <> template -Circuit::BlackBoxOp::BigIntMul serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxOp::BigIntMul obj; +Program::BlackBoxOp::BigIntMul serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::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 { +namespace Program { inline bool operator==(const BlackBoxOp::BigIntDiv &lhs, const BlackBoxOp::BigIntDiv &rhs) { if (!(lhs.lhs == rhs.lhs)) { return false; } @@ -3739,11 +3747,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::BigIntDiv &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxOp::BigIntDiv &obj, Serializer &serializer) { serde::Serializable::serialize(obj.lhs, serializer); serde::Serializable::serialize(obj.rhs, serializer); serde::Serializable::serialize(obj.output, serializer); @@ -3751,15 +3759,15 @@ void serde::Serializable::serialize(const Circui template <> template -Circuit::BlackBoxOp::BigIntDiv serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxOp::BigIntDiv obj; +Program::BlackBoxOp::BigIntDiv serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::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 { +namespace Program { inline bool operator==(const BlackBoxOp::BigIntFromLeBytes &lhs, const BlackBoxOp::BigIntFromLeBytes &rhs) { if (!(lhs.inputs == rhs.inputs)) { return false; } @@ -3783,11 +3791,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::BigIntFromLeBytes &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxOp::BigIntFromLeBytes &obj, Serializer &serializer) { serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.modulus, serializer); serde::Serializable::serialize(obj.output, serializer); @@ -3795,15 +3803,15 @@ void serde::Serializable::serialize(cons template <> template -Circuit::BlackBoxOp::BigIntFromLeBytes serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxOp::BigIntFromLeBytes obj; +Program::BlackBoxOp::BigIntFromLeBytes serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::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 { +namespace Program { inline bool operator==(const BlackBoxOp::BigIntToLeBytes &lhs, const BlackBoxOp::BigIntToLeBytes &rhs) { if (!(lhs.input == rhs.input)) { return false; } @@ -3826,25 +3834,25 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::BigIntToLeBytes &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::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; +Program::BlackBoxOp::BigIntToLeBytes serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxOp::BigIntToLeBytes obj; obj.input = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxOp::Poseidon2Permutation &lhs, const BlackBoxOp::Poseidon2Permutation &rhs) { if (!(lhs.message == rhs.message)) { return false; } @@ -3868,11 +3876,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::Poseidon2Permutation &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxOp::Poseidon2Permutation &obj, Serializer &serializer) { serde::Serializable::serialize(obj.message, serializer); serde::Serializable::serialize(obj.output, serializer); serde::Serializable::serialize(obj.len, serializer); @@ -3880,15 +3888,15 @@ void serde::Serializable::serialize(c template <> template -Circuit::BlackBoxOp::Poseidon2Permutation serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxOp::Poseidon2Permutation obj; +Program::BlackBoxOp::Poseidon2Permutation serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxOp::Poseidon2Permutation obj; obj.message = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); obj.len = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlackBoxOp::Sha256Compression &lhs, const BlackBoxOp::Sha256Compression &rhs) { if (!(lhs.input == rhs.input)) { return false; } @@ -3912,11 +3920,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlackBoxOp::Sha256Compression &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlackBoxOp::Sha256Compression &obj, Serializer &serializer) { serde::Serializable::serialize(obj.input, serializer); serde::Serializable::serialize(obj.hash_values, serializer); serde::Serializable::serialize(obj.output, serializer); @@ -3924,15 +3932,15 @@ void serde::Serializable::serialize(cons template <> template -Circuit::BlackBoxOp::Sha256Compression serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BlackBoxOp::Sha256Compression obj; +Program::BlackBoxOp::Sha256Compression serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxOp::Sha256Compression obj; obj.input = serde::Deserializable::deserialize(deserializer); obj.hash_values = serde::Deserializable::deserialize(deserializer); obj.output = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BlockId &lhs, const BlockId &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -3954,11 +3962,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BlockId &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BlockId &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -3966,15 +3974,15 @@ void serde::Serializable::serialize(const Circuit::BlockId &ob template <> template -Circuit::BlockId serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::BlockId serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::BlockId obj; + Program::BlockId obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Brillig &lhs, const Brillig &rhs) { if (!(lhs.inputs == rhs.inputs)) { return false; } @@ -3999,11 +4007,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Brillig &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::Brillig &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.outputs, serializer); @@ -4014,9 +4022,9 @@ void serde::Serializable::serialize(const Circuit::Brillig &ob template <> template -Circuit::Brillig serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::Brillig serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::Brillig obj; + Program::Brillig obj; obj.inputs = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); obj.bytecode = serde::Deserializable::deserialize(deserializer); @@ -4025,7 +4033,7 @@ Circuit::Brillig serde::Deserializable::deserialize(Deserializ return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligInputs &lhs, const BrilligInputs &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -4047,11 +4055,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligInputs &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligInputs &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -4059,15 +4067,15 @@ void serde::Serializable::serialize(const Circuit::Brill template <> template -Circuit::BrilligInputs serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::BrilligInputs serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::BrilligInputs obj; + Program::BrilligInputs obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligInputs::Single &lhs, const BrilligInputs::Single &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -4089,23 +4097,23 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligInputs::Single &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligInputs::Single &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value, serializer); } template <> template -Circuit::BrilligInputs::Single serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligInputs::Single obj; +Program::BrilligInputs::Single serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligInputs::Single obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligInputs::Array &lhs, const BrilligInputs::Array &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -4127,23 +4135,23 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligInputs::Array &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligInputs::Array &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value, serializer); } template <> template -Circuit::BrilligInputs::Array serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligInputs::Array obj; +Program::BrilligInputs::Array serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligInputs::Array obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligInputs::MemoryArray &lhs, const BrilligInputs::MemoryArray &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -4165,23 +4173,23 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligInputs::MemoryArray &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligInputs::MemoryArray &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value, serializer); } template <> template -Circuit::BrilligInputs::MemoryArray serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligInputs::MemoryArray obj; +Program::BrilligInputs::MemoryArray serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligInputs::MemoryArray obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode &lhs, const BrilligOpcode &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -4203,11 +4211,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOpcode &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligOpcode &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -4215,15 +4223,15 @@ void serde::Serializable::serialize(const Circuit::Brill template <> template -Circuit::BrilligOpcode serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::BrilligOpcode serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::BrilligOpcode obj; + Program::BrilligOpcode obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::BinaryFieldOp &lhs, const BrilligOpcode::BinaryFieldOp &rhs) { if (!(lhs.destination == rhs.destination)) { return false; } @@ -4248,11 +4256,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::BinaryFieldOp &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligOpcode::BinaryFieldOp &obj, Serializer &serializer) { serde::Serializable::serialize(obj.destination, serializer); serde::Serializable::serialize(obj.op, serializer); serde::Serializable::serialize(obj.lhs, serializer); @@ -4261,8 +4269,8 @@ void serde::Serializable::serialize(const template <> template -Circuit::BrilligOpcode::BinaryFieldOp serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligOpcode::BinaryFieldOp obj; +Program::BrilligOpcode::BinaryFieldOp serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::BinaryFieldOp obj; obj.destination = serde::Deserializable::deserialize(deserializer); obj.op = serde::Deserializable::deserialize(deserializer); obj.lhs = serde::Deserializable::deserialize(deserializer); @@ -4270,7 +4278,7 @@ Circuit::BrilligOpcode::BinaryFieldOp serde::Deserializable template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::BinaryIntOp &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligOpcode::BinaryIntOp &obj, Serializer &serializer) { serde::Serializable::serialize(obj.destination, serializer); serde::Serializable::serialize(obj.op, serializer); serde::Serializable::serialize(obj.bit_size, serializer); @@ -4310,8 +4318,8 @@ void serde::Serializable::serialize(const C template <> template -Circuit::BrilligOpcode::BinaryIntOp serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligOpcode::BinaryIntOp obj; +Program::BrilligOpcode::BinaryIntOp serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::BinaryIntOp obj; obj.destination = serde::Deserializable::deserialize(deserializer); obj.op = serde::Deserializable::deserialize(deserializer); obj.bit_size = serde::Deserializable::deserialize(deserializer); @@ -4320,7 +4328,7 @@ Circuit::BrilligOpcode::BinaryIntOp serde::Deserializable template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::Cast &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligOpcode::Cast &obj, Serializer &serializer) { serde::Serializable::serialize(obj.destination, serializer); serde::Serializable::serialize(obj.source, serializer); serde::Serializable::serialize(obj.bit_size, serializer); @@ -4356,15 +4364,15 @@ void serde::Serializable::serialize(const Circuit: template <> template -Circuit::BrilligOpcode::Cast serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligOpcode::Cast obj; +Program::BrilligOpcode::Cast serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::Cast obj; obj.destination = serde::Deserializable::deserialize(deserializer); obj.source = serde::Deserializable::deserialize(deserializer); obj.bit_size = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::JumpIfNot &lhs, const BrilligOpcode::JumpIfNot &rhs) { if (!(lhs.condition == rhs.condition)) { return false; } @@ -4387,25 +4395,25 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::JumpIfNot &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligOpcode::JumpIfNot &obj, Serializer &serializer) { serde::Serializable::serialize(obj.condition, serializer); serde::Serializable::serialize(obj.location, serializer); } template <> template -Circuit::BrilligOpcode::JumpIfNot serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligOpcode::JumpIfNot obj; +Program::BrilligOpcode::JumpIfNot serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::JumpIfNot obj; obj.condition = serde::Deserializable::deserialize(deserializer); obj.location = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::JumpIf &lhs, const BrilligOpcode::JumpIf &rhs) { if (!(lhs.condition == rhs.condition)) { return false; } @@ -4428,25 +4436,25 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::JumpIf &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligOpcode::JumpIf &obj, Serializer &serializer) { serde::Serializable::serialize(obj.condition, serializer); serde::Serializable::serialize(obj.location, serializer); } template <> template -Circuit::BrilligOpcode::JumpIf serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligOpcode::JumpIf obj; +Program::BrilligOpcode::JumpIf serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::JumpIf obj; obj.condition = serde::Deserializable::deserialize(deserializer); obj.location = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::Jump &lhs, const BrilligOpcode::Jump &rhs) { if (!(lhs.location == rhs.location)) { return false; } @@ -4468,23 +4476,23 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::Jump &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligOpcode::Jump &obj, Serializer &serializer) { serde::Serializable::serialize(obj.location, serializer); } template <> template -Circuit::BrilligOpcode::Jump serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligOpcode::Jump obj; +Program::BrilligOpcode::Jump serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::Jump obj; obj.location = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::CalldataCopy &lhs, const BrilligOpcode::CalldataCopy &rhs) { if (!(lhs.destination_address == rhs.destination_address)) { return false; } @@ -4508,11 +4516,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::CalldataCopy &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligOpcode::CalldataCopy &obj, Serializer &serializer) { serde::Serializable::serialize(obj.destination_address, serializer); serde::Serializable::serialize(obj.size, serializer); serde::Serializable::serialize(obj.offset, serializer); @@ -4520,15 +4528,15 @@ void serde::Serializable::serialize(const template <> template -Circuit::BrilligOpcode::CalldataCopy serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligOpcode::CalldataCopy obj; +Program::BrilligOpcode::CalldataCopy serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::CalldataCopy obj; obj.destination_address = serde::Deserializable::deserialize(deserializer); obj.size = serde::Deserializable::deserialize(deserializer); obj.offset = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::Call &lhs, const BrilligOpcode::Call &rhs) { if (!(lhs.location == rhs.location)) { return false; } @@ -4550,23 +4558,23 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::Call &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligOpcode::Call &obj, Serializer &serializer) { serde::Serializable::serialize(obj.location, serializer); } template <> template -Circuit::BrilligOpcode::Call serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligOpcode::Call obj; +Program::BrilligOpcode::Call serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::Call obj; obj.location = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::Const &lhs, const BrilligOpcode::Const &rhs) { if (!(lhs.destination == rhs.destination)) { return false; } @@ -4590,11 +4598,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::Const &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligOpcode::Const &obj, Serializer &serializer) { serde::Serializable::serialize(obj.destination, serializer); serde::Serializable::serialize(obj.bit_size, serializer); serde::Serializable::serialize(obj.value, serializer); @@ -4602,15 +4610,15 @@ void serde::Serializable::serialize(const Circuit template <> template -Circuit::BrilligOpcode::Const serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligOpcode::Const obj; +Program::BrilligOpcode::Const serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::Const obj; obj.destination = serde::Deserializable::deserialize(deserializer); obj.bit_size = serde::Deserializable::deserialize(deserializer); obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::Return &lhs, const BrilligOpcode::Return &rhs) { return true; @@ -4631,21 +4639,21 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::Return &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligOpcode::Return &obj, Serializer &serializer) { } template <> template -Circuit::BrilligOpcode::Return serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligOpcode::Return obj; +Program::BrilligOpcode::Return serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::Return obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::ForeignCall &lhs, const BrilligOpcode::ForeignCall &rhs) { if (!(lhs.function == rhs.function)) { return false; } @@ -4671,11 +4679,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::ForeignCall &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligOpcode::ForeignCall &obj, Serializer &serializer) { serde::Serializable::serialize(obj.function, serializer); serde::Serializable::serialize(obj.destinations, serializer); serde::Serializable::serialize(obj.destination_value_types, serializer); @@ -4685,8 +4693,8 @@ void serde::Serializable::serialize(const C template <> template -Circuit::BrilligOpcode::ForeignCall serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligOpcode::ForeignCall obj; +Program::BrilligOpcode::ForeignCall serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::ForeignCall obj; obj.function = serde::Deserializable::deserialize(deserializer); obj.destinations = serde::Deserializable::deserialize(deserializer); obj.destination_value_types = serde::Deserializable::deserialize(deserializer); @@ -4695,7 +4703,7 @@ Circuit::BrilligOpcode::ForeignCall serde::Deserializable template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::Mov &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligOpcode::Mov &obj, Serializer &serializer) { serde::Serializable::serialize(obj.destination, serializer); serde::Serializable::serialize(obj.source, serializer); } template <> template -Circuit::BrilligOpcode::Mov serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligOpcode::Mov obj; +Program::BrilligOpcode::Mov serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::Mov obj; obj.destination = serde::Deserializable::deserialize(deserializer); obj.source = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::Load &lhs, const BrilligOpcode::Load &rhs) { if (!(lhs.destination == rhs.destination)) { return false; } @@ -4759,25 +4767,25 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::Load &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligOpcode::Load &obj, Serializer &serializer) { serde::Serializable::serialize(obj.destination, serializer); serde::Serializable::serialize(obj.source_pointer, serializer); } template <> template -Circuit::BrilligOpcode::Load serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligOpcode::Load obj; +Program::BrilligOpcode::Load serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::Load obj; obj.destination = serde::Deserializable::deserialize(deserializer); obj.source_pointer = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::Store &lhs, const BrilligOpcode::Store &rhs) { if (!(lhs.destination_pointer == rhs.destination_pointer)) { return false; } @@ -4800,25 +4808,25 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::Store &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligOpcode::Store &obj, Serializer &serializer) { serde::Serializable::serialize(obj.destination_pointer, serializer); serde::Serializable::serialize(obj.source, serializer); } template <> template -Circuit::BrilligOpcode::Store serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligOpcode::Store obj; +Program::BrilligOpcode::Store serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::Store obj; obj.destination_pointer = serde::Deserializable::deserialize(deserializer); obj.source = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::BlackBox &lhs, const BrilligOpcode::BlackBox &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -4840,23 +4848,23 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::BlackBox &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligOpcode::BlackBox &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value, serializer); } template <> template -Circuit::BrilligOpcode::BlackBox serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligOpcode::BlackBox obj; +Program::BrilligOpcode::BlackBox serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::BlackBox obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::Trap &lhs, const BrilligOpcode::Trap &rhs) { return true; @@ -4877,21 +4885,21 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::Trap &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligOpcode::Trap &obj, Serializer &serializer) { } template <> template -Circuit::BrilligOpcode::Trap serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligOpcode::Trap obj; +Program::BrilligOpcode::Trap serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::Trap obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOpcode::Stop &lhs, const BrilligOpcode::Stop &rhs) { if (!(lhs.return_data_offset == rhs.return_data_offset)) { return false; } @@ -4914,25 +4922,25 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOpcode::Stop &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligOpcode::Stop &obj, Serializer &serializer) { serde::Serializable::serialize(obj.return_data_offset, serializer); serde::Serializable::serialize(obj.return_data_size, serializer); } template <> template -Circuit::BrilligOpcode::Stop serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligOpcode::Stop obj; +Program::BrilligOpcode::Stop serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::Stop obj; obj.return_data_offset = serde::Deserializable::deserialize(deserializer); obj.return_data_size = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOutputs &lhs, const BrilligOutputs &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -4954,11 +4962,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOutputs &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligOutputs &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -4966,15 +4974,15 @@ void serde::Serializable::serialize(const Circuit::Bril template <> template -Circuit::BrilligOutputs serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::BrilligOutputs serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::BrilligOutputs obj; + Program::BrilligOutputs obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOutputs::Simple &lhs, const BrilligOutputs::Simple &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -4996,23 +5004,23 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOutputs::Simple &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligOutputs::Simple &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value, serializer); } template <> template -Circuit::BrilligOutputs::Simple serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligOutputs::Simple obj; +Program::BrilligOutputs::Simple serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOutputs::Simple obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BrilligOutputs::Array &lhs, const BrilligOutputs::Array &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -5034,23 +5042,23 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BrilligOutputs::Array &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BrilligOutputs::Array &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value, serializer); } template <> template -Circuit::BrilligOutputs::Array serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BrilligOutputs::Array obj; +Program::BrilligOutputs::Array serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOutputs::Array obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Circuit &lhs, const Circuit &rhs) { if (!(lhs.current_witness_index == rhs.current_witness_index)) { return false; } @@ -5079,11 +5087,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Circuit &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::Circuit &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.current_witness_index, serializer); serde::Serializable::serialize(obj.opcodes, serializer); @@ -5098,9 +5106,9 @@ void serde::Serializable::serialize(const Circuit::Circuit &ob template <> template -Circuit::Circuit serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::Circuit serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::Circuit obj; + Program::Circuit obj; obj.current_witness_index = serde::Deserializable::deserialize(deserializer); obj.opcodes = serde::Deserializable::deserialize(deserializer); obj.expression_width = serde::Deserializable::deserialize(deserializer); @@ -5113,7 +5121,7 @@ Circuit::Circuit serde::Deserializable::deserialize(Deserializ return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Directive &lhs, const Directive &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -5135,11 +5143,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Directive &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::Directive &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -5147,15 +5155,15 @@ void serde::Serializable::serialize(const Circuit::Directive template <> template -Circuit::Directive serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::Directive serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::Directive obj; + Program::Directive obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Directive::ToLeRadix &lhs, const Directive::ToLeRadix &rhs) { if (!(lhs.a == rhs.a)) { return false; } @@ -5179,11 +5187,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Directive::ToLeRadix &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::Directive::ToLeRadix &obj, Serializer &serializer) { serde::Serializable::serialize(obj.a, serializer); serde::Serializable::serialize(obj.b, serializer); serde::Serializable::serialize(obj.radix, serializer); @@ -5191,15 +5199,15 @@ void serde::Serializable::serialize(const Circuit template <> template -Circuit::Directive::ToLeRadix serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::Directive::ToLeRadix obj; +Program::Directive::ToLeRadix serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::Directive::ToLeRadix obj; obj.a = serde::Deserializable::deserialize(deserializer); obj.b = serde::Deserializable::deserialize(deserializer); obj.radix = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Expression &lhs, const Expression &rhs) { if (!(lhs.mul_terms == rhs.mul_terms)) { return false; } @@ -5223,11 +5231,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Expression &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::Expression &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.mul_terms, serializer); serde::Serializable::serialize(obj.linear_combinations, serializer); @@ -5237,9 +5245,9 @@ void serde::Serializable::serialize(const Circuit::Expressi template <> template -Circuit::Expression serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::Expression serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::Expression obj; + Program::Expression obj; obj.mul_terms = serde::Deserializable::deserialize(deserializer); obj.linear_combinations = serde::Deserializable::deserialize(deserializer); obj.q_c = serde::Deserializable::deserialize(deserializer); @@ -5247,7 +5255,7 @@ Circuit::Expression serde::Deserializable::deserialize(Dese return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const ExpressionWidth &lhs, const ExpressionWidth &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -5269,11 +5277,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::ExpressionWidth &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::ExpressionWidth &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -5281,15 +5289,15 @@ void serde::Serializable::serialize(const Circuit::Exp template <> template -Circuit::ExpressionWidth serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::ExpressionWidth serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::ExpressionWidth obj; + Program::ExpressionWidth obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const ExpressionWidth::Unbounded &lhs, const ExpressionWidth::Unbounded &rhs) { return true; @@ -5310,21 +5318,21 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::ExpressionWidth::Unbounded &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::ExpressionWidth::Unbounded &obj, Serializer &serializer) { } template <> template -Circuit::ExpressionWidth::Unbounded serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::ExpressionWidth::Unbounded obj; +Program::ExpressionWidth::Unbounded serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::ExpressionWidth::Unbounded obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const ExpressionWidth::Bounded &lhs, const ExpressionWidth::Bounded &rhs) { if (!(lhs.width == rhs.width)) { return false; } @@ -5346,23 +5354,23 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::ExpressionWidth::Bounded &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::ExpressionWidth::Bounded &obj, Serializer &serializer) { serde::Serializable::serialize(obj.width, serializer); } template <> template -Circuit::ExpressionWidth::Bounded serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::ExpressionWidth::Bounded obj; +Program::ExpressionWidth::Bounded serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::ExpressionWidth::Bounded obj; obj.width = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const FunctionInput &lhs, const FunctionInput &rhs) { if (!(lhs.witness == rhs.witness)) { return false; } @@ -5385,11 +5393,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::FunctionInput &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::FunctionInput &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.witness, serializer); serde::Serializable::serialize(obj.num_bits, serializer); @@ -5398,16 +5406,16 @@ void serde::Serializable::serialize(const Circuit::Funct template <> template -Circuit::FunctionInput serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::FunctionInput serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::FunctionInput obj; + Program::FunctionInput obj; obj.witness = serde::Deserializable::deserialize(deserializer); obj.num_bits = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const HeapArray &lhs, const HeapArray &rhs) { if (!(lhs.pointer == rhs.pointer)) { return false; } @@ -5430,11 +5438,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::HeapArray &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::HeapArray &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.pointer, serializer); serde::Serializable::serialize(obj.size, serializer); @@ -5443,16 +5451,16 @@ void serde::Serializable::serialize(const Circuit::HeapArray template <> template -Circuit::HeapArray serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::HeapArray serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::HeapArray obj; + Program::HeapArray obj; obj.pointer = serde::Deserializable::deserialize(deserializer); obj.size = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const HeapValueType &lhs, const HeapValueType &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -5474,11 +5482,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::HeapValueType &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::HeapValueType &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -5486,15 +5494,15 @@ void serde::Serializable::serialize(const Circuit::HeapV template <> template -Circuit::HeapValueType serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::HeapValueType serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::HeapValueType obj; + Program::HeapValueType obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const HeapValueType::Simple &lhs, const HeapValueType::Simple &rhs) { return true; @@ -5515,21 +5523,21 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::HeapValueType::Simple &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::HeapValueType::Simple &obj, Serializer &serializer) { } template <> template -Circuit::HeapValueType::Simple serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::HeapValueType::Simple obj; +Program::HeapValueType::Simple serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::HeapValueType::Simple obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const HeapValueType::Array &lhs, const HeapValueType::Array &rhs) { if (!(lhs.value_types == rhs.value_types)) { return false; } @@ -5552,25 +5560,25 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::HeapValueType::Array &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::HeapValueType::Array &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value_types, serializer); serde::Serializable::serialize(obj.size, serializer); } template <> template -Circuit::HeapValueType::Array serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::HeapValueType::Array obj; +Program::HeapValueType::Array serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::HeapValueType::Array obj; obj.value_types = serde::Deserializable::deserialize(deserializer); obj.size = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const HeapValueType::Vector &lhs, const HeapValueType::Vector &rhs) { if (!(lhs.value_types == rhs.value_types)) { return false; } @@ -5592,23 +5600,23 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::HeapValueType::Vector &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::HeapValueType::Vector &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value_types, serializer); } template <> template -Circuit::HeapValueType::Vector serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::HeapValueType::Vector obj; +Program::HeapValueType::Vector serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::HeapValueType::Vector obj; obj.value_types = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const HeapVector &lhs, const HeapVector &rhs) { if (!(lhs.pointer == rhs.pointer)) { return false; } @@ -5631,11 +5639,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::HeapVector &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::HeapVector &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.pointer, serializer); serde::Serializable::serialize(obj.size, serializer); @@ -5644,16 +5652,16 @@ void serde::Serializable::serialize(const Circuit::HeapVect template <> template -Circuit::HeapVector serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::HeapVector serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::HeapVector obj; + Program::HeapVector obj; obj.pointer = serde::Deserializable::deserialize(deserializer); obj.size = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const MemOp &lhs, const MemOp &rhs) { if (!(lhs.operation == rhs.operation)) { return false; } @@ -5677,11 +5685,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::MemOp &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::MemOp &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.operation, serializer); serde::Serializable::serialize(obj.index, serializer); @@ -5691,9 +5699,9 @@ void serde::Serializable::serialize(const Circuit::MemOp &obj, S template <> template -Circuit::MemOp serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::MemOp serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::MemOp obj; + Program::MemOp obj; obj.operation = serde::Deserializable::deserialize(deserializer); obj.index = serde::Deserializable::deserialize(deserializer); obj.value = serde::Deserializable::deserialize(deserializer); @@ -5701,7 +5709,7 @@ Circuit::MemOp serde::Deserializable::deserialize(Deserializer & return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const MemoryAddress &lhs, const MemoryAddress &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -5723,11 +5731,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::MemoryAddress &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::MemoryAddress &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -5735,15 +5743,15 @@ void serde::Serializable::serialize(const Circuit::Memor template <> template -Circuit::MemoryAddress serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::MemoryAddress serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::MemoryAddress obj; + Program::MemoryAddress obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Opcode &lhs, const Opcode &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -5765,11 +5773,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Opcode &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::Opcode &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -5777,15 +5785,15 @@ void serde::Serializable::serialize(const Circuit::Opcode &obj, template <> template -Circuit::Opcode serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::Opcode serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::Opcode obj; + Program::Opcode obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Opcode::AssertZero &lhs, const Opcode::AssertZero &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -5807,23 +5815,23 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Opcode::AssertZero &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::Opcode::AssertZero &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value, serializer); } template <> template -Circuit::Opcode::AssertZero serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::Opcode::AssertZero obj; +Program::Opcode::AssertZero serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::Opcode::AssertZero obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Opcode::BlackBoxFuncCall &lhs, const Opcode::BlackBoxFuncCall &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -5845,23 +5853,23 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Opcode::BlackBoxFuncCall &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::Opcode::BlackBoxFuncCall &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value, serializer); } template <> template -Circuit::Opcode::BlackBoxFuncCall serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::Opcode::BlackBoxFuncCall obj; +Program::Opcode::BlackBoxFuncCall serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::Opcode::BlackBoxFuncCall obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Opcode::Directive &lhs, const Opcode::Directive &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -5883,23 +5891,23 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Opcode::Directive &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::Opcode::Directive &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value, serializer); } template <> template -Circuit::Opcode::Directive serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::Opcode::Directive obj; +Program::Opcode::Directive serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::Opcode::Directive obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Opcode::Brillig &lhs, const Opcode::Brillig &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -5921,23 +5929,23 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Opcode::Brillig &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::Opcode::Brillig &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value, serializer); } template <> template -Circuit::Opcode::Brillig serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::Opcode::Brillig obj; +Program::Opcode::Brillig serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::Opcode::Brillig obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Opcode::MemoryOp &lhs, const Opcode::MemoryOp &rhs) { if (!(lhs.block_id == rhs.block_id)) { return false; } @@ -5961,11 +5969,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Opcode::MemoryOp &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::Opcode::MemoryOp &obj, Serializer &serializer) { serde::Serializable::serialize(obj.block_id, serializer); serde::Serializable::serialize(obj.op, serializer); serde::Serializable::serialize(obj.predicate, serializer); @@ -5973,15 +5981,15 @@ void serde::Serializable::serialize(const Circuit::Op template <> template -Circuit::Opcode::MemoryOp serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::Opcode::MemoryOp obj; +Program::Opcode::MemoryOp serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::Opcode::MemoryOp obj; obj.block_id = serde::Deserializable::deserialize(deserializer); obj.op = serde::Deserializable::deserialize(deserializer); obj.predicate = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Opcode::MemoryInit &lhs, const Opcode::MemoryInit &rhs) { if (!(lhs.block_id == rhs.block_id)) { return false; } @@ -6004,25 +6012,25 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Opcode::MemoryInit &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::Opcode::MemoryInit &obj, Serializer &serializer) { serde::Serializable::serialize(obj.block_id, serializer); serde::Serializable::serialize(obj.init, serializer); } template <> template -Circuit::Opcode::MemoryInit serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::Opcode::MemoryInit obj; +Program::Opcode::MemoryInit serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::Opcode::MemoryInit obj; obj.block_id = serde::Deserializable::deserialize(deserializer); obj.init = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Opcode::Call &lhs, const Opcode::Call &rhs) { if (!(lhs.id == rhs.id)) { return false; } @@ -6046,11 +6054,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Opcode::Call &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::Opcode::Call &obj, Serializer &serializer) { serde::Serializable::serialize(obj.id, serializer); serde::Serializable::serialize(obj.inputs, serializer); serde::Serializable::serialize(obj.outputs, serializer); @@ -6058,15 +6066,15 @@ void serde::Serializable::serialize(const Circuit::Opcode template <> template -Circuit::Opcode::Call serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::Opcode::Call obj; +Program::Opcode::Call serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::Opcode::Call obj; obj.id = serde::Deserializable::deserialize(deserializer); obj.inputs = serde::Deserializable::deserialize(deserializer); obj.outputs = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const OpcodeLocation &lhs, const OpcodeLocation &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -6088,11 +6096,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::OpcodeLocation &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::OpcodeLocation &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -6100,15 +6108,15 @@ void serde::Serializable::serialize(const Circuit::Opco template <> template -Circuit::OpcodeLocation serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::OpcodeLocation serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::OpcodeLocation obj; + Program::OpcodeLocation obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const OpcodeLocation::Acir &lhs, const OpcodeLocation::Acir &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -6130,23 +6138,23 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::OpcodeLocation::Acir &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::OpcodeLocation::Acir &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value, serializer); } template <> template -Circuit::OpcodeLocation::Acir serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::OpcodeLocation::Acir obj; +Program::OpcodeLocation::Acir serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::OpcodeLocation::Acir obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const OpcodeLocation::Brillig &lhs, const OpcodeLocation::Brillig &rhs) { if (!(lhs.acir_index == rhs.acir_index)) { return false; } @@ -6169,25 +6177,67 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::OpcodeLocation::Brillig &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::OpcodeLocation::Brillig &obj, Serializer &serializer) { serde::Serializable::serialize(obj.acir_index, serializer); serde::Serializable::serialize(obj.brillig_index, serializer); } template <> template -Circuit::OpcodeLocation::Brillig serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::OpcodeLocation::Brillig obj; +Program::OpcodeLocation::Brillig serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::OpcodeLocation::Brillig obj; obj.acir_index = serde::Deserializable::deserialize(deserializer); obj.brillig_index = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { + + inline bool operator==(const Program &lhs, const Program &rhs) { + if (!(lhs.functions == rhs.functions)) { return false; } + return true; + } + + inline std::vector Program::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } + + inline Program Program::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } + +} // end of namespace Program + +template <> +template +void serde::Serializable::serialize(const Program::Program &obj, Serializer &serializer) { + serializer.increase_container_depth(); + serde::Serializable::serialize(obj.functions, serializer); + serializer.decrease_container_depth(); +} + +template <> +template +Program::Program serde::Deserializable::deserialize(Deserializer &deserializer) { + deserializer.increase_container_depth(); + Program::Program obj; + obj.functions = serde::Deserializable::deserialize(deserializer); + deserializer.decrease_container_depth(); + return obj; +} + +namespace Program { inline bool operator==(const PublicInputs &lhs, const PublicInputs &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -6209,11 +6259,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::PublicInputs &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::PublicInputs &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -6221,15 +6271,15 @@ void serde::Serializable::serialize(const Circuit::Public template <> template -Circuit::PublicInputs serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::PublicInputs serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::PublicInputs obj; + Program::PublicInputs obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Value &lhs, const Value &rhs) { if (!(lhs.inner == rhs.inner)) { return false; } @@ -6251,11 +6301,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Value &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::Value &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.inner, serializer); serializer.decrease_container_depth(); @@ -6263,15 +6313,15 @@ void serde::Serializable::serialize(const Circuit::Value &obj, S template <> template -Circuit::Value serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::Value serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::Value obj; + Program::Value obj; obj.inner = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const ValueOrArray &lhs, const ValueOrArray &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -6293,11 +6343,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::ValueOrArray &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::ValueOrArray &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -6305,15 +6355,15 @@ void serde::Serializable::serialize(const Circuit::ValueO template <> template -Circuit::ValueOrArray serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::ValueOrArray serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::ValueOrArray obj; + Program::ValueOrArray obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const ValueOrArray::MemoryAddress &lhs, const ValueOrArray::MemoryAddress &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -6335,23 +6385,23 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::ValueOrArray::MemoryAddress &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::ValueOrArray::MemoryAddress &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value, serializer); } template <> template -Circuit::ValueOrArray::MemoryAddress serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::ValueOrArray::MemoryAddress obj; +Program::ValueOrArray::MemoryAddress serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::ValueOrArray::MemoryAddress obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const ValueOrArray::HeapArray &lhs, const ValueOrArray::HeapArray &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -6373,23 +6423,23 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::ValueOrArray::HeapArray &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::ValueOrArray::HeapArray &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value, serializer); } template <> template -Circuit::ValueOrArray::HeapArray serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::ValueOrArray::HeapArray obj; +Program::ValueOrArray::HeapArray serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::ValueOrArray::HeapArray obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const ValueOrArray::HeapVector &lhs, const ValueOrArray::HeapVector &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -6411,23 +6461,23 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::ValueOrArray::HeapVector &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::ValueOrArray::HeapVector &obj, Serializer &serializer) { serde::Serializable::serialize(obj.value, serializer); } template <> template -Circuit::ValueOrArray::HeapVector serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::ValueOrArray::HeapVector obj; +Program::ValueOrArray::HeapVector serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::ValueOrArray::HeapVector obj; obj.value = serde::Deserializable::deserialize(deserializer); return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const Witness &lhs, const Witness &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -6449,11 +6499,11 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::Witness &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::Witness &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -6461,9 +6511,9 @@ void serde::Serializable::serialize(const Circuit::Witness &ob template <> template -Circuit::Witness serde::Deserializable::deserialize(Deserializer &deserializer) { +Program::Witness serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - Circuit::Witness obj; + Program::Witness obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; diff --git a/noir/noir-repo/acvm-repo/acir/codegen/witness.cpp b/noir/noir-repo/acvm-repo/acir/codegen/witness.cpp index 118d4ca7ac5b..ad2b0550db2e 100644 --- a/noir/noir-repo/acvm-repo/acir/codegen/witness.cpp +++ b/noir/noir-repo/acvm-repo/acir/codegen/witness.cpp @@ -3,7 +3,7 @@ #include "serde.hpp" #include "bincode.hpp" -namespace WitnessMap { +namespace WitnessStack { struct Witness { uint32_t value; @@ -14,17 +14,79 @@ namespace WitnessMap { }; struct WitnessMap { - std::map value; + std::map value; friend bool operator==(const WitnessMap&, const WitnessMap&); std::vector bincodeSerialize() const; static WitnessMap bincodeDeserialize(std::vector); }; -} // end of namespace WitnessMap + struct StackItem { + uint32_t index; + WitnessStack::WitnessMap witness; + friend bool operator==(const StackItem&, const StackItem&); + std::vector bincodeSerialize() const; + static StackItem bincodeDeserialize(std::vector); + }; + + struct WitnessStack { + std::vector stack; + + friend bool operator==(const WitnessStack&, const WitnessStack&); + std::vector bincodeSerialize() const; + static WitnessStack bincodeDeserialize(std::vector); + }; + +} // end of namespace WitnessStack + + +namespace WitnessStack { + + inline bool operator==(const StackItem &lhs, const StackItem &rhs) { + if (!(lhs.index == rhs.index)) { return false; } + if (!(lhs.witness == rhs.witness)) { return false; } + return true; + } + + inline std::vector StackItem::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } + + inline StackItem StackItem::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 WitnessStack + +template <> +template +void serde::Serializable::serialize(const WitnessStack::StackItem &obj, Serializer &serializer) { + serializer.increase_container_depth(); + serde::Serializable::serialize(obj.index, serializer); + serde::Serializable::serialize(obj.witness, serializer); + serializer.decrease_container_depth(); +} + +template <> +template +WitnessStack::StackItem serde::Deserializable::deserialize(Deserializer &deserializer) { + deserializer.increase_container_depth(); + WitnessStack::StackItem obj; + obj.index = serde::Deserializable::deserialize(deserializer); + obj.witness = serde::Deserializable::deserialize(deserializer); + deserializer.decrease_container_depth(); + return obj; +} -namespace WitnessMap { +namespace WitnessStack { inline bool operator==(const Witness &lhs, const Witness &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -46,11 +108,11 @@ namespace WitnessMap { return value; } -} // end of namespace WitnessMap +} // end of namespace WitnessStack template <> template -void serde::Serializable::serialize(const WitnessMap::Witness &obj, Serializer &serializer) { +void serde::Serializable::serialize(const WitnessStack::Witness &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -58,15 +120,15 @@ void serde::Serializable::serialize(const WitnessMap::Witne template <> template -WitnessMap::Witness serde::Deserializable::deserialize(Deserializer &deserializer) { +WitnessStack::Witness serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - WitnessMap::Witness obj; + WitnessStack::Witness obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } -namespace WitnessMap { +namespace WitnessStack { inline bool operator==(const WitnessMap &lhs, const WitnessMap &rhs) { if (!(lhs.value == rhs.value)) { return false; } @@ -88,11 +150,11 @@ namespace WitnessMap { return value; } -} // end of namespace WitnessMap +} // end of namespace WitnessStack template <> template -void serde::Serializable::serialize(const WitnessMap::WitnessMap &obj, Serializer &serializer) { +void serde::Serializable::serialize(const WitnessStack::WitnessMap &obj, Serializer &serializer) { serializer.increase_container_depth(); serde::Serializable::serialize(obj.value, serializer); serializer.decrease_container_depth(); @@ -100,10 +162,52 @@ void serde::Serializable::serialize(const WitnessMap::Wi template <> template -WitnessMap::WitnessMap serde::Deserializable::deserialize(Deserializer &deserializer) { +WitnessStack::WitnessMap serde::Deserializable::deserialize(Deserializer &deserializer) { deserializer.increase_container_depth(); - WitnessMap::WitnessMap obj; + WitnessStack::WitnessMap obj; obj.value = serde::Deserializable::deserialize(deserializer); deserializer.decrease_container_depth(); return obj; } + +namespace WitnessStack { + + inline bool operator==(const WitnessStack &lhs, const WitnessStack &rhs) { + if (!(lhs.stack == rhs.stack)) { return false; } + return true; + } + + inline std::vector WitnessStack::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } + + inline WitnessStack WitnessStack::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 WitnessStack + +template <> +template +void serde::Serializable::serialize(const WitnessStack::WitnessStack &obj, Serializer &serializer) { + serializer.increase_container_depth(); + serde::Serializable::serialize(obj.stack, serializer); + serializer.decrease_container_depth(); +} + +template <> +template +WitnessStack::WitnessStack serde::Deserializable::deserialize(Deserializer &deserializer) { + deserializer.increase_container_depth(); + WitnessStack::WitnessStack obj; + obj.stack = serde::Deserializable::deserialize(deserializer); + deserializer.decrease_container_depth(); + return obj; +} diff --git a/noir/noir-repo/acvm-repo/acir/src/circuit/mod.rs b/noir/noir-repo/acvm-repo/acir/src/circuit/mod.rs index 7e6cbf238039..3d4d62969815 100644 --- a/noir/noir-repo/acvm-repo/acir/src/circuit/mod.rs +++ b/noir/noir-repo/acvm-repo/acir/src/circuit/mod.rs @@ -32,6 +32,13 @@ pub enum ExpressionWidth { }, } +/// A program represented by multiple ACIR circuits. The execution trace of these +/// circuits is dictated by construction of the [crate::native_types::WitnessStack]. +#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Default)] +pub struct Program { + pub functions: Vec, +} + #[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Default)] pub struct Circuit { // current_witness_index is the highest witness index in the circuit. The next witness to be added to this circuit @@ -203,6 +210,57 @@ impl Circuit { } } +impl Program { + fn write(&self, writer: W) -> std::io::Result<()> { + let buf = bincode::serialize(self).unwrap(); + let mut encoder = flate2::write::GzEncoder::new(writer, Compression::default()); + encoder.write_all(&buf)?; + encoder.finish()?; + Ok(()) + } + + fn read(reader: R) -> std::io::Result { + let mut gz_decoder = flate2::read::GzDecoder::new(reader); + let mut buf_d = Vec::new(); + gz_decoder.read_to_end(&mut buf_d)?; + bincode::deserialize(&buf_d) + .map_err(|err| std::io::Error::new(std::io::ErrorKind::InvalidInput, err)) + } + + pub fn serialize_program(program: &Program) -> Vec { + let mut program_bytes: Vec = Vec::new(); + program.write(&mut program_bytes).expect("expected circuit to be serializable"); + program_bytes + } + + pub fn deserialize_program(serialized_circuit: &[u8]) -> std::io::Result { + Program::read(serialized_circuit) + } + + // Serialize and base64 encode program + pub fn serialize_program_base64(program: &Program, s: S) -> Result + where + S: Serializer, + { + let program_bytes = Program::serialize_program(program); + let encoded_b64 = base64::engine::general_purpose::STANDARD.encode(program_bytes); + s.serialize_str(&encoded_b64) + } + + // Deserialize and base64 decode program + pub fn deserialize_program_base64<'de, D>(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let bytecode_b64: String = serde::Deserialize::deserialize(deserializer)?; + let program_bytes = base64::engine::general_purpose::STANDARD + .decode(bytecode_b64) + .map_err(D::Error::custom)?; + let circuit = Self::deserialize_program(&program_bytes).map_err(D::Error::custom)?; + Ok(circuit) + } +} + impl std::fmt::Display for Circuit { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { writeln!(f, "current witness index : {}", self.current_witness_index)?; @@ -240,6 +298,22 @@ impl std::fmt::Debug for Circuit { } } +impl std::fmt::Display for Program { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + for (func_index, function) in self.functions.iter().enumerate() { + writeln!(f, "func {}", func_index)?; + writeln!(f, "{}", function)?; + } + Ok(()) + } +} + +impl std::fmt::Debug for Program { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self, f) + } +} + #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Default)] pub struct PublicInputs(pub BTreeSet); diff --git a/noir/noir-repo/acvm-repo/acir/src/lib.rs b/noir/noir-repo/acvm-repo/acir/src/lib.rs index c7be50268502..d14159f34a16 100644 --- a/noir/noir-repo/acvm-repo/acir/src/lib.rs +++ b/noir/noir-repo/acvm-repo/acir/src/lib.rs @@ -42,9 +42,9 @@ mod reflection { brillig::{BrilligInputs, BrilligOutputs}, directives::Directive, opcodes::BlackBoxFuncCall, - Circuit, ExpressionWidth, Opcode, OpcodeLocation, + Circuit, ExpressionWidth, Opcode, OpcodeLocation, Program, }, - native_types::{Witness, WitnessMap}, + native_types::{Witness, WitnessMap, WitnessStack}, }; #[test] @@ -59,6 +59,7 @@ mod reflection { }; let mut tracer = Tracer::new(TracerConfig::default()); + tracer.trace_simple_type::().unwrap(); tracer.trace_simple_type::().unwrap(); tracer.trace_simple_type::().unwrap(); tracer.trace_simple_type::().unwrap(); @@ -78,7 +79,7 @@ mod reflection { // Create C++ class definitions. let mut source = Vec::new(); - let config = serde_generate::CodeGeneratorConfig::new("Circuit".to_string()) + let config = serde_generate::CodeGeneratorConfig::new("Program".to_string()) .with_encodings(vec![serde_generate::Encoding::Bincode]); let generator = serde_generate::cpp::CodeGenerator::new(&config); generator.output(&mut source, ®istry).unwrap(); @@ -106,12 +107,13 @@ mod reflection { let mut tracer = Tracer::new(TracerConfig::default()); tracer.trace_simple_type::().unwrap(); tracer.trace_simple_type::().unwrap(); + tracer.trace_simple_type::().unwrap(); let registry = tracer.registry().unwrap(); // Create C++ class definitions. let mut source = Vec::new(); - let config = serde_generate::CodeGeneratorConfig::new("WitnessMap".to_string()) + let config = serde_generate::CodeGeneratorConfig::new("WitnessStack".to_string()) .with_encodings(vec![serde_generate::Encoding::Bincode]); let generator = serde_generate::cpp::CodeGenerator::new(&config); generator.output(&mut source, ®istry).unwrap(); diff --git a/noir/noir-repo/acvm-repo/acir/src/native_types/mod.rs b/noir/noir-repo/acvm-repo/acir/src/native_types/mod.rs index 66c822bfff87..eb9d1f6fd038 100644 --- a/noir/noir-repo/acvm-repo/acir/src/native_types/mod.rs +++ b/noir/noir-repo/acvm-repo/acir/src/native_types/mod.rs @@ -1,8 +1,10 @@ mod expression; mod witness; mod witness_map; +mod witness_stack; pub use expression::Expression; pub use witness::Witness; pub use witness_map::WitnessMap; -pub use witness_map::WitnessMapError; +pub use witness_stack::WitnessStack; +pub use witness_stack::WitnessStackError; diff --git a/noir/noir-repo/acvm-repo/acir/src/native_types/witness_stack.rs b/noir/noir-repo/acvm-repo/acir/src/native_types/witness_stack.rs new file mode 100644 index 000000000000..9592d90b014b --- /dev/null +++ b/noir/noir-repo/acvm-repo/acir/src/native_types/witness_stack.rs @@ -0,0 +1,64 @@ +use std::io::Read; + +use flate2::bufread::GzDecoder; +use flate2::bufread::GzEncoder; +use flate2::Compression; +use serde::{Deserialize, Serialize}; +use thiserror::Error; + +use super::WitnessMap; + +#[derive(Debug, Error)] +enum SerializationError { + #[error(transparent)] + Deflate(#[from] std::io::Error), +} + +#[derive(Debug, Error)] +#[error(transparent)] +pub struct WitnessStackError(#[from] SerializationError); + +/// An ordered set of witness maps for separate circuits +#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Default, Serialize, Deserialize)] +pub struct WitnessStack { + pub stack: Vec, +} + +#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Default, Serialize, Deserialize)] +pub struct StackItem { + /// Index into a [crate::circuit::Program] function list for which we have an associated witness + pub index: u32, + /// A full witness for the respective constraint system specified by the index + pub witness: WitnessMap, +} + +impl From for WitnessStack { + fn from(witness: WitnessMap) -> Self { + let stack = vec![StackItem { index: 0, witness }]; + Self { stack } + } +} + +impl TryFrom for Vec { + type Error = WitnessStackError; + + fn try_from(val: WitnessStack) -> Result { + let buf = bincode::serialize(&val).unwrap(); + let mut deflater = GzEncoder::new(buf.as_slice(), Compression::best()); + let mut buf_c = Vec::new(); + deflater.read_to_end(&mut buf_c).map_err(|err| WitnessStackError(err.into()))?; + Ok(buf_c) + } +} + +impl TryFrom<&[u8]> for WitnessStack { + type Error = WitnessStackError; + + fn try_from(bytes: &[u8]) -> Result { + let mut deflater = GzDecoder::new(bytes); + let mut buf_d = Vec::new(); + deflater.read_to_end(&mut buf_d).map_err(|err| WitnessStackError(err.into()))?; + let witness_stack = bincode::deserialize(&buf_d).unwrap(); + Ok(witness_stack) + } +} diff --git a/noir/noir-repo/acvm-repo/acir/tests/test_program_serialization.rs b/noir/noir-repo/acvm-repo/acir/tests/test_program_serialization.rs index 2c8ad2b99868..238f51b1e280 100644 --- a/noir/noir-repo/acvm-repo/acir/tests/test_program_serialization.rs +++ b/noir/noir-repo/acvm-repo/acir/tests/test_program_serialization.rs @@ -1,13 +1,13 @@ //! This integration test defines a set of circuits which are used in order to test the acvm_js package. //! -//! The acvm_js test suite contains serialized [circuits][`Circuit`] which must be kept in sync with the format +//! The acvm_js test suite contains serialized program [circuits][`Program`] which must be kept in sync with the format //! outputted from the [ACIR crate][acir]. //! Breaking changes to the serialization format then require refreshing acvm_js's test suite. //! This file contains Rust definitions of these circuits and outputs the updated serialized format. //! //! These tests also check this circuit serialization against an expected value, erroring if the serialization changes. //! Generally in this situation we just need to refresh the `expected_serialization` variables to match the -//! actual output, **HOWEVER** note that this results in a breaking change to the ACIR format. +//! actual output, **HOWEVER** note that this results in a breaking change to the backend ACIR format. use std::collections::BTreeSet; @@ -15,7 +15,7 @@ use acir::{ circuit::{ brillig::{Brillig, BrilligInputs, BrilligOutputs}, opcodes::{BlackBoxFuncCall, BlockId, FunctionInput, MemOp}, - Circuit, Opcode, PublicInputs, + Circuit, Opcode, Program, PublicInputs, }, native_types::{Expression, Witness}, }; @@ -41,16 +41,17 @@ fn addition_circuit() { return_values: PublicInputs([Witness(3)].into()), ..Circuit::default() }; + let program = Program { functions: vec![circuit] }; - let bytes = Circuit::serialize_circuit(&circuit); + let bytes = Program::serialize_program(&program); let expected_serialization: Vec = vec![ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 208, 49, 14, 192, 32, 8, 5, 80, 212, 30, 8, 4, 20, - 182, 94, 165, 166, 122, 255, 35, 52, 77, 28, 76, 58, 214, 191, 124, 166, 23, 242, 15, 0, 8, - 240, 77, 154, 125, 206, 198, 127, 161, 176, 209, 138, 139, 197, 88, 68, 122, 205, 157, 152, - 46, 204, 222, 76, 81, 180, 21, 35, 35, 53, 189, 179, 49, 119, 19, 171, 222, 188, 162, 147, - 112, 167, 161, 206, 99, 98, 105, 223, 95, 248, 26, 113, 90, 97, 185, 97, 217, 56, 173, 35, - 63, 243, 81, 87, 163, 125, 1, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 144, 75, 14, 128, 32, 12, 68, 249, 120, 160, 150, + 182, 208, 238, 188, 138, 68, 184, 255, 17, 212, 200, 130, 196, 165, 188, 164, 153, 174, 94, + 38, 227, 221, 203, 118, 159, 119, 95, 226, 200, 125, 36, 252, 3, 253, 66, 87, 152, 92, 4, + 153, 185, 149, 212, 144, 240, 128, 100, 85, 5, 88, 106, 86, 84, 20, 149, 51, 41, 81, 83, + 214, 98, 213, 10, 24, 50, 53, 236, 98, 212, 135, 44, 174, 235, 5, 143, 35, 12, 151, 159, + 126, 55, 109, 28, 231, 145, 47, 245, 105, 191, 143, 133, 1, 0, 0, ]; assert_eq!(bytes, expected_serialization) @@ -71,13 +72,14 @@ fn fixed_base_scalar_mul_circuit() { return_values: PublicInputs(BTreeSet::from_iter(vec![Witness(3), Witness(4)])), ..Circuit::default() }; + let program = Program { functions: vec![circuit] }; - let bytes = Circuit::serialize_circuit(&circuit); + let bytes = Program::serialize_program(&program); let expected_serialization: Vec = vec![ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 77, 138, 91, 10, 0, 32, 16, 2, 109, 171, 175, 46, 221, - 209, 247, 229, 130, 130, 140, 200, 92, 0, 11, 157, 228, 35, 127, 212, 200, 29, 61, 116, 76, - 220, 217, 250, 171, 91, 113, 160, 66, 104, 242, 97, 0, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 77, 138, 81, 10, 0, 48, 8, 66, 87, 219, 190, 118, 233, + 29, 61, 43, 3, 5, 121, 34, 207, 86, 231, 162, 198, 157, 124, 228, 71, 157, 220, 232, 161, + 227, 226, 206, 214, 95, 221, 74, 0, 116, 58, 13, 182, 105, 0, 0, 0, ]; assert_eq!(bytes, expected_serialization) @@ -98,13 +100,14 @@ fn pedersen_circuit() { return_values: PublicInputs(BTreeSet::from_iter(vec![Witness(2), Witness(3)])), ..Circuit::default() }; + let program = Program { functions: vec![circuit] }; - let bytes = Circuit::serialize_circuit(&circuit); + let bytes = Program::serialize_program(&program); let expected_serialization: Vec = vec![ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 93, 74, 135, 9, 0, 48, 8, 75, 171, 224, 255, 15, 139, - 27, 196, 64, 200, 100, 0, 15, 133, 80, 57, 89, 219, 127, 39, 173, 126, 235, 236, 247, 151, - 48, 224, 71, 90, 33, 97, 0, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 93, 74, 7, 6, 0, 0, 8, 108, 209, 255, 63, 156, 54, 233, + 56, 55, 17, 26, 18, 196, 241, 169, 250, 178, 141, 167, 32, 159, 254, 234, 238, 255, 87, + 112, 52, 63, 63, 101, 105, 0, 0, 0, ]; assert_eq!(bytes, expected_serialization) @@ -139,26 +142,27 @@ fn schnorr_verify_circuit() { return_values: PublicInputs(BTreeSet::from([output])), ..Circuit::default() }; + let program = Program { functions: vec![circuit] }; - let bytes = Circuit::serialize_circuit(&circuit); + let bytes = Program::serialize_program(&program); let expected_serialization: Vec = vec![ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 77, 210, 7, 74, 3, 1, 20, 69, 209, 177, 247, 222, 123, - 239, 189, 119, 141, 93, 99, 220, 133, 251, 95, 130, 152, 103, 78, 32, 3, 195, 33, 4, 66, - 248, 239, 254, 20, 69, 209, 84, 212, 158, 216, 206, 223, 234, 219, 204, 146, 239, 91, 170, - 111, 103, 245, 109, 101, 27, 219, 217, 193, 250, 219, 197, 110, 246, 176, 151, 125, 236, - 231, 0, 7, 57, 196, 97, 142, 112, 148, 99, 28, 231, 4, 39, 57, 197, 105, 206, 112, 150, - 115, 156, 231, 2, 23, 185, 196, 101, 174, 112, 149, 107, 92, 231, 6, 55, 185, 197, 109, - 238, 112, 151, 123, 220, 231, 1, 15, 121, 196, 99, 158, 240, 148, 103, 60, 231, 5, 47, 121, - 197, 107, 222, 240, 150, 119, 188, 231, 3, 75, 124, 228, 83, 195, 142, 121, 158, 125, 126, - 225, 43, 223, 248, 206, 15, 126, 178, 204, 47, 86, 248, 237, 119, 43, 76, 127, 105, 47, - 189, 165, 181, 116, 150, 198, 234, 125, 117, 249, 47, 233, 41, 45, 165, 163, 52, 148, 126, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 77, 210, 7, 78, 2, 1, 20, 69, 81, 236, 189, 247, 222, + 123, 239, 93, 177, 33, 34, 238, 194, 253, 47, 193, 200, 147, 67, 194, 36, 147, 163, 33, 33, + 228, 191, 219, 82, 168, 63, 63, 181, 183, 197, 223, 177, 147, 191, 181, 183, 149, 69, 159, + 183, 213, 222, 238, 218, 219, 206, 14, 118, 178, 139, 141, 183, 135, 189, 236, 99, 63, 7, + 56, 200, 33, 14, 115, 132, 163, 28, 227, 56, 39, 56, 201, 41, 78, 115, 134, 179, 156, 227, + 60, 23, 184, 200, 37, 46, 115, 133, 171, 92, 227, 58, 55, 184, 201, 45, 110, 115, 135, 187, + 220, 227, 62, 15, 120, 200, 35, 30, 243, 132, 167, 60, 227, 57, 47, 120, 201, 43, 94, 243, + 134, 183, 188, 227, 61, 31, 248, 200, 39, 22, 249, 204, 151, 166, 29, 243, 188, 250, 255, + 141, 239, 44, 241, 131, 101, 126, 178, 194, 47, 86, 249, 237, 123, 171, 76, 127, 105, 47, + 189, 165, 181, 116, 150, 198, 26, 125, 245, 248, 45, 233, 41, 45, 165, 163, 52, 148, 126, 210, 78, 186, 73, 51, 233, 37, 173, 164, 147, 52, 146, 62, 210, 70, 186, 72, 19, 233, 33, - 45, 164, 131, 52, 144, 253, 23, 139, 218, 238, 217, 60, 123, 103, 235, 236, 156, 141, 179, - 239, 166, 93, 183, 237, 185, 107, 199, 125, 251, 29, 218, 237, 216, 94, 167, 118, 58, 183, - 207, 165, 93, 174, 237, 113, 107, 135, 123, 247, 47, 185, 251, 147, 59, 191, 184, 239, 155, - 187, 126, 184, 103, 217, 29, 235, 55, 171, 223, 173, 104, 184, 231, 255, 243, 7, 236, 52, - 239, 128, 225, 3, 0, 0, + 45, 164, 131, 52, 144, 253, 151, 11, 245, 221, 179, 121, 246, 206, 214, 217, 57, 27, 103, + 223, 109, 187, 238, 218, 115, 223, 142, 135, 246, 59, 182, 219, 169, 189, 206, 237, 116, + 105, 159, 107, 187, 220, 218, 227, 222, 14, 143, 238, 95, 116, 247, 23, 119, 126, 115, 223, + 146, 187, 150, 221, 179, 226, 142, 141, 155, 53, 238, 86, 104, 186, 231, 255, 243, 7, 100, + 141, 232, 192, 233, 3, 0, 0, ]; assert_eq!(bytes, expected_serialization) @@ -202,15 +206,16 @@ fn simple_brillig_foreign_call() { private_parameters: BTreeSet::from([Witness(1), Witness(2)]), ..Circuit::default() }; + let program = Program { functions: vec![circuit] }; - let bytes = Circuit::serialize_circuit(&circuit); + let bytes = Program::serialize_program(&program); let expected_serialization: Vec = vec![ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 143, 177, 10, 192, 32, 16, 67, 227, 21, 74, 233, - 212, 79, 177, 127, 208, 159, 233, 224, 226, 32, 226, 247, 139, 168, 16, 68, 93, 244, 45, - 119, 228, 142, 144, 92, 0, 20, 50, 7, 237, 76, 213, 190, 50, 245, 26, 175, 218, 231, 165, - 57, 175, 148, 14, 137, 179, 147, 191, 114, 211, 221, 216, 240, 59, 63, 107, 221, 115, 104, - 181, 103, 244, 43, 36, 10, 38, 68, 108, 25, 253, 238, 136, 1, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 143, 65, 10, 192, 32, 12, 4, 77, 10, 165, 244, 212, + 167, 216, 31, 244, 51, 61, 120, 241, 32, 226, 251, 85, 140, 176, 136, 122, 209, 129, 144, + 176, 9, 97, 151, 84, 225, 74, 69, 50, 31, 48, 35, 85, 251, 164, 235, 53, 94, 218, 247, 75, + 163, 95, 150, 12, 153, 179, 227, 191, 114, 195, 222, 216, 240, 59, 63, 75, 221, 251, 208, + 106, 207, 232, 150, 65, 100, 53, 33, 2, 9, 69, 91, 82, 144, 1, 0, 0, ]; assert_eq!(bytes, expected_serialization) @@ -301,19 +306,20 @@ fn complex_brillig_foreign_call() { private_parameters: BTreeSet::from([Witness(1), Witness(2), Witness(3)]), ..Circuit::default() }; + let program = Program { functions: vec![circuit] }; - let bytes = Circuit::serialize_circuit(&circuit); + let bytes = Program::serialize_program(&program); let expected_serialization: Vec = vec![ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 84, 75, 10, 132, 48, 12, 125, 177, 163, 35, 179, - 154, 35, 8, 51, 7, 232, 204, 9, 188, 139, 184, 83, 116, 233, 241, 173, 152, 98, 12, 213, - 141, 21, 244, 65, 232, 39, 175, 233, 35, 73, 155, 3, 32, 204, 48, 206, 18, 158, 19, 175, - 37, 60, 175, 228, 209, 30, 195, 143, 226, 197, 178, 103, 105, 76, 110, 160, 209, 156, 160, - 209, 247, 195, 69, 235, 29, 179, 46, 81, 243, 103, 2, 239, 231, 225, 44, 117, 150, 241, - 250, 201, 99, 206, 251, 96, 95, 161, 242, 14, 193, 243, 40, 162, 105, 253, 219, 12, 75, 47, - 146, 186, 251, 37, 116, 86, 93, 219, 55, 245, 96, 20, 85, 75, 253, 136, 249, 87, 249, 105, - 231, 220, 4, 249, 237, 132, 56, 20, 224, 109, 113, 223, 88, 82, 153, 34, 64, 34, 14, 164, - 69, 172, 48, 2, 23, 243, 6, 31, 25, 5, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 84, 65, 14, 132, 32, 12, 108, 101, 117, 205, 158, + 246, 9, 38, 187, 15, 96, 247, 5, 254, 197, 120, 211, 232, 209, 231, 139, 113, 136, 181, 65, + 47, 98, 162, 147, 52, 20, 24, 202, 164, 45, 48, 205, 200, 157, 49, 124, 227, 44, 129, 207, + 152, 75, 120, 94, 137, 209, 30, 195, 143, 227, 197, 178, 103, 105, 76, 110, 160, 209, 156, + 160, 209, 247, 195, 69, 235, 29, 179, 46, 81, 243, 103, 2, 239, 231, 225, 44, 117, 150, 97, + 254, 196, 152, 99, 157, 176, 87, 168, 188, 147, 224, 121, 20, 209, 180, 254, 109, 70, 75, + 47, 178, 186, 251, 37, 116, 86, 93, 219, 55, 245, 96, 20, 85, 75, 253, 8, 255, 171, 246, + 121, 231, 220, 4, 249, 237, 132, 56, 28, 224, 109, 113, 223, 180, 164, 50, 165, 0, 137, 17, + 72, 139, 88, 97, 4, 198, 90, 226, 196, 33, 5, 0, 0, ]; assert_eq!(bytes, expected_serialization) @@ -342,13 +348,16 @@ fn memory_op_circuit() { return_values: PublicInputs([Witness(4)].into()), ..Circuit::default() }; - let bytes = Circuit::serialize_circuit(&circuit); + let program = Program { functions: vec![circuit] }; + + let bytes = Program::serialize_program(&program); let expected_serialization: Vec = vec![ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 145, 187, 17, 0, 32, 8, 67, 195, 111, 31, 220, 192, - 253, 167, 178, 144, 2, 239, 236, 132, 194, 52, 129, 230, 93, 8, 6, 64, 176, 101, 225, 28, - 78, 49, 43, 238, 154, 225, 254, 166, 209, 205, 165, 98, 174, 212, 177, 188, 187, 92, 255, - 173, 92, 173, 190, 93, 82, 80, 78, 123, 14, 127, 60, 97, 1, 210, 144, 46, 242, 19, 3, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 81, 201, 13, 0, 32, 8, 147, 195, 125, 112, 3, 247, + 159, 74, 141, 60, 106, 226, 79, 120, 216, 132, 180, 124, 154, 82, 168, 108, 212, 57, 2, + 122, 129, 157, 201, 181, 150, 59, 186, 179, 189, 161, 101, 251, 82, 176, 175, 196, 121, 89, + 118, 185, 246, 91, 185, 26, 125, 187, 64, 80, 134, 29, 195, 31, 79, 24, 2, 250, 167, 252, + 27, 3, 0, 0, ]; assert_eq!(bytes, expected_serialization) diff --git a/noir/noir-repo/acvm-repo/acvm_js/src/compression.rs b/noir/noir-repo/acvm-repo/acvm_js/src/compression.rs index fedaa514bf06..73bcd02ecd1b 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/src/compression.rs +++ b/noir/noir-repo/acvm-repo/acvm_js/src/compression.rs @@ -1,4 +1,4 @@ -use acvm::acir::native_types::WitnessMap; +use acvm::acir::native_types::{WitnessMap, WitnessStack}; use js_sys::JsString; use wasm_bindgen::prelude::wasm_bindgen; @@ -13,10 +13,11 @@ pub fn compress_witness(witness_map: JsWitnessMap) -> Result, JsString> console_error_panic_hook::set_once(); let witness_map = WitnessMap::from(witness_map); - let compressed_witness_map: Vec = - Vec::::try_from(witness_map).map_err(|err| err.to_string())?; + let witness_stack: WitnessStack = witness_map.into(); + let compressed_witness_stack: Vec = + Vec::::try_from(witness_stack).map_err(|err| err.to_string())?; - Ok(compressed_witness_map) + Ok(compressed_witness_stack) } /// Decompresses a compressed witness as outputted by Nargo into a `WitnessMap`. @@ -27,8 +28,8 @@ pub fn compress_witness(witness_map: JsWitnessMap) -> Result, JsString> pub fn decompress_witness(compressed_witness: Vec) -> Result { console_error_panic_hook::set_once(); - let witness_map = - WitnessMap::try_from(compressed_witness.as_slice()).map_err(|err| err.to_string())?; + let witness_stack = + WitnessStack::try_from(compressed_witness.as_slice()).map_err(|err| err.to_string())?; - Ok(witness_map.into()) + Ok(witness_stack.stack[0].witness.clone().into()) } diff --git a/noir/noir-repo/acvm-repo/acvm_js/src/execute.rs b/noir/noir-repo/acvm-repo/acvm_js/src/execute.rs index 3f691e1abf29..6985183a8a07 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/src/execute.rs +++ b/noir/noir-repo/acvm-repo/acvm_js/src/execute.rs @@ -1,5 +1,5 @@ use acvm::{ - acir::circuit::Circuit, + acir::circuit::Program, pwg::{ACVMStatus, ErrorLocation, OpcodeResolutionError, ACVM}, }; use bn254_blackbox_solver::Bn254BlackBoxSolver; @@ -56,13 +56,17 @@ pub async fn execute_circuit( #[wasm_bindgen(js_name = executeCircuitWithBlackBoxSolver, skip_jsdoc)] pub async fn execute_circuit_with_black_box_solver( solver: &WasmBlackBoxFunctionSolver, + // TODO(https://github.com/noir-lang/noir/issues/4428): These need to be updated to match the same interfaces + // as the native ACVM executor. Right now native execution still only handles one circuit so I do not feel the need + // to break the JS interface just yet. circuit: Vec, initial_witness: JsWitnessMap, foreign_call_handler: ForeignCallHandler, ) -> Result { console_error_panic_hook::set_once(); - let circuit: Circuit = Circuit::deserialize_circuit(&circuit) + let program: Program = Program::deserialize_program(&circuit) .map_err(|_| JsExecutionError::new("Failed to deserialize circuit. This is likely due to differing serialization formats between ACVM_JS and your compiler".to_string(), None))?; + let circuit = &program.functions[0]; let mut acvm = ACVM::new(&solver.0, &circuit.opcodes, initial_witness.into()); diff --git a/noir/noir-repo/acvm-repo/acvm_js/src/public_witness.rs b/noir/noir-repo/acvm-repo/acvm_js/src/public_witness.rs index 8dc66c435b3c..2ae90b79a6a5 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/src/public_witness.rs +++ b/noir/noir-repo/acvm-repo/acvm_js/src/public_witness.rs @@ -1,5 +1,5 @@ use acvm::acir::{ - circuit::Circuit, + circuit::Program, native_types::{Witness, WitnessMap}, }; use js_sys::JsString; @@ -26,16 +26,21 @@ fn extract_indices(witness_map: &WitnessMap, indices: Vec) -> Result, witness_map: JsWitnessMap, ) -> Result { console_error_panic_hook::set_once(); - let circuit: Circuit = - Circuit::deserialize_circuit(&circuit).expect("Failed to deserialize circuit"); + let program: Program = + Program::deserialize_program(&circuit).expect("Failed to deserialize circuit"); + let circuit = &program.functions[0]; + let witness_map = WitnessMap::from(witness_map); let return_witness = - extract_indices(&witness_map, circuit.return_values.0.into_iter().collect())?; + extract_indices(&witness_map, circuit.return_values.0.clone().into_iter().collect())?; Ok(JsWitnessMap::from(return_witness)) } @@ -51,12 +56,14 @@ pub fn get_public_parameters_witness( solved_witness: JsWitnessMap, ) -> Result { console_error_panic_hook::set_once(); - let circuit: Circuit = - Circuit::deserialize_circuit(&circuit).expect("Failed to deserialize circuit"); + let program: Program = + Program::deserialize_program(&circuit).expect("Failed to deserialize circuit"); + let circuit = &program.functions[0]; + let witness_map = WitnessMap::from(solved_witness); let public_params_witness = - extract_indices(&witness_map, circuit.public_parameters.0.into_iter().collect())?; + extract_indices(&witness_map, circuit.public_parameters.0.clone().into_iter().collect())?; Ok(JsWitnessMap::from(public_params_witness)) } @@ -72,12 +79,14 @@ pub fn get_public_witness( solved_witness: JsWitnessMap, ) -> Result { console_error_panic_hook::set_once(); - let circuit: Circuit = - Circuit::deserialize_circuit(&circuit).expect("Failed to deserialize circuit"); + let program: Program = + Program::deserialize_program(&circuit).expect("Failed to deserialize circuit"); + let circuit = &program.functions[0]; + let witness_map = WitnessMap::from(solved_witness); let public_witness = - extract_indices(&witness_map, circuit.public_inputs().0.into_iter().collect())?; + extract_indices(&witness_map, circuit.public_inputs().0.clone().into_iter().collect())?; Ok(JsWitnessMap::from(public_witness)) } diff --git a/noir/noir-repo/acvm-repo/acvm_js/test/shared/addition.ts b/noir/noir-repo/acvm-repo/acvm_js/test/shared/addition.ts index 217902bdea61..f5b0bda2d07a 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/test/shared/addition.ts +++ b/noir/noir-repo/acvm-repo/acvm_js/test/shared/addition.ts @@ -2,11 +2,12 @@ import { WitnessMap } from '@noir-lang/acvm_js'; // See `addition_circuit` integration test in `acir/tests/test_program_serialization.rs`. export const bytecode = Uint8Array.from([ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 208, 49, 14, 192, 32, 8, 5, 80, 212, 30, 8, 4, 20, 182, 94, 165, 166, 122, - 255, 35, 52, 77, 28, 76, 58, 214, 191, 124, 166, 23, 242, 15, 0, 8, 240, 77, 154, 125, 206, 198, 127, 161, 176, 209, - 138, 139, 197, 88, 68, 122, 205, 157, 152, 46, 204, 222, 76, 81, 180, 21, 35, 35, 53, 189, 179, 49, 119, 19, 171, 222, - 188, 162, 147, 112, 167, 161, 206, 99, 98, 105, 223, 95, 248, 26, 113, 90, 97, 185, 97, 217, 56, 173, 35, 63, 243, 81, - 87, 163, 125, 1, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 144, 75, 14, 128, 32, 12, 68, 249, 120, 160, 150, + 182, 208, 238, 188, 138, 68, 184, 255, 17, 212, 200, 130, 196, 165, 188, 164, 153, 174, 94, + 38, 227, 221, 203, 118, 159, 119, 95, 226, 200, 125, 36, 252, 3, 253, 66, 87, 152, 92, 4, + 153, 185, 149, 212, 144, 240, 128, 100, 85, 5, 88, 106, 86, 84, 20, 149, 51, 41, 81, 83, + 214, 98, 213, 10, 24, 50, 53, 236, 98, 212, 135, 44, 174, 235, 5, 143, 35, 12, 151, 159, + 126, 55, 109, 28, 231, 145, 47, 245, 105, 191, 143, 133, 1, 0, 0, ]); export const initialWitnessMap: WitnessMap = new Map([ diff --git a/noir/noir-repo/acvm-repo/acvm_js/test/shared/complex_foreign_call.ts b/noir/noir-repo/acvm-repo/acvm_js/test/shared/complex_foreign_call.ts index 27abd72305f0..c75a59643473 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/test/shared/complex_foreign_call.ts +++ b/noir/noir-repo/acvm-repo/acvm_js/test/shared/complex_foreign_call.ts @@ -2,13 +2,15 @@ import { WitnessMap } from '@noir-lang/acvm_js'; // See `complex_brillig_foreign_call` integration test in `acir/tests/test_program_serialization.rs`. export const bytecode = Uint8Array.from([ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 84, 75, 10, 132, 48, 12, 125, 177, 163, 35, 179, 154, 35, 8, 51, 7, 232, 204, - 9, 188, 139, 184, 83, 116, 233, 241, 173, 152, 98, 12, 213, 141, 21, 244, 65, 232, 39, 175, 233, 35, 73, 155, 3, 32, - 204, 48, 206, 18, 158, 19, 175, 37, 60, 175, 228, 209, 30, 195, 143, 226, 197, 178, 103, 105, 76, 110, 160, 209, 156, - 160, 209, 247, 195, 69, 235, 29, 179, 46, 81, 243, 103, 2, 239, 231, 225, 44, 117, 150, 241, 250, 201, 99, 206, 251, - 96, 95, 161, 242, 14, 193, 243, 40, 162, 105, 253, 219, 12, 75, 47, 146, 186, 251, 37, 116, 86, 93, 219, 55, 245, 96, - 20, 85, 75, 253, 136, 249, 87, 249, 105, 231, 220, 4, 249, 237, 132, 56, 20, 224, 109, 113, 223, 88, 82, 153, 34, 64, - 34, 14, 164, 69, 172, 48, 2, 23, 243, 6, 31, 25, 5, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 84, 65, 14, 132, 32, 12, 108, 101, 117, 205, 158, + 246, 9, 38, 187, 15, 96, 247, 5, 254, 197, 120, 211, 232, 209, 231, 139, 113, 136, 181, 65, + 47, 98, 162, 147, 52, 20, 24, 202, 164, 45, 48, 205, 200, 157, 49, 124, 227, 44, 129, 207, + 152, 75, 120, 94, 137, 209, 30, 195, 143, 227, 197, 178, 103, 105, 76, 110, 160, 209, 156, + 160, 209, 247, 195, 69, 235, 29, 179, 46, 81, 243, 103, 2, 239, 231, 225, 44, 117, 150, 97, + 254, 196, 152, 99, 157, 176, 87, 168, 188, 147, 224, 121, 20, 209, 180, 254, 109, 70, 75, + 47, 178, 186, 251, 37, 116, 86, 93, 219, 55, 245, 96, 20, 85, 75, 253, 8, 255, 171, 246, + 121, 231, 220, 4, 249, 237, 132, 56, 28, 224, 109, 113, 223, 180, 164, 50, 165, 0, 137, 17, + 72, 139, 88, 97, 4, 198, 90, 226, 196, 33, 5, 0, 0, ]); export const initialWitnessMap: WitnessMap = new Map([ [1, '0x0000000000000000000000000000000000000000000000000000000000000001'], diff --git a/noir/noir-repo/acvm-repo/acvm_js/test/shared/fixed_base_scalar_mul.ts b/noir/noir-repo/acvm-repo/acvm_js/test/shared/fixed_base_scalar_mul.ts index c0859f50135b..46e1f66fb211 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/test/shared/fixed_base_scalar_mul.ts +++ b/noir/noir-repo/acvm-repo/acvm_js/test/shared/fixed_base_scalar_mul.ts @@ -1,8 +1,8 @@ // See `fixed_base_scalar_mul_circuit` integration test in `acir/tests/test_program_serialization.rs`. export const bytecode = Uint8Array.from([ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 77, 138, 91, 10, 0, 32, 16, 2, 109, 171, 175, 46, 221, 209, 247, 229, 130, 130, - 140, 200, 92, 0, 11, 157, 228, 35, 127, 212, 200, 29, 61, 116, 76, 220, 217, 250, 171, 91, 113, 160, 66, 104, 242, 97, - 0, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 77, 138, 81, 10, 0, 48, 8, 66, 87, 219, 190, 118, 233, + 29, 61, 43, 3, 5, 121, 34, 207, 86, 231, 162, 198, 157, 124, 228, 71, 157, 220, 232, 161, + 227, 226, 206, 214, 95, 221, 74, 0, 116, 58, 13, 182, 105, 0, 0, 0, ]); export const initialWitnessMap = new Map([ [1, '0x0000000000000000000000000000000000000000000000000000000000000001'], diff --git a/noir/noir-repo/acvm-repo/acvm_js/test/shared/foreign_call.ts b/noir/noir-repo/acvm-repo/acvm_js/test/shared/foreign_call.ts index 0be8937b57d3..527f26b4ae39 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/test/shared/foreign_call.ts +++ b/noir/noir-repo/acvm-repo/acvm_js/test/shared/foreign_call.ts @@ -2,10 +2,11 @@ import { WitnessMap } from '@noir-lang/acvm_js'; // See `simple_brillig_foreign_call` integration test in `acir/tests/test_program_serialization.rs`. export const bytecode = Uint8Array.from([ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 143, 177, 10, 192, 32, 16, 67, 227, 21, 74, 233, 212, 79, 177, 127, 208, 159, - 233, 224, 226, 32, 226, 247, 139, 168, 16, 68, 93, 244, 45, 119, 228, 142, 144, 92, 0, 20, 50, 7, 237, 76, 213, 190, - 50, 245, 26, 175, 218, 231, 165, 57, 175, 148, 14, 137, 179, 147, 191, 114, 211, 221, 216, 240, 59, 63, 107, 221, 115, - 104, 181, 103, 244, 43, 36, 10, 38, 68, 108, 25, 253, 238, 136, 1, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 143, 65, 10, 192, 32, 12, 4, 77, 10, 165, 244, 212, + 167, 216, 31, 244, 51, 61, 120, 241, 32, 226, 251, 85, 140, 176, 136, 122, 209, 129, 144, + 176, 9, 97, 151, 84, 225, 74, 69, 50, 31, 48, 35, 85, 251, 164, 235, 53, 94, 218, 247, 75, + 163, 95, 150, 12, 153, 179, 227, 191, 114, 195, 222, 216, 240, 59, 63, 75, 221, 251, 208, + 106, 207, 232, 150, 65, 100, 53, 33, 2, 9, 69, 91, 82, 144, 1, 0, 0, ]); export const initialWitnessMap: WitnessMap = new Map([ [1, '0x0000000000000000000000000000000000000000000000000000000000000005'], diff --git a/noir/noir-repo/acvm-repo/acvm_js/test/shared/memory_op.ts b/noir/noir-repo/acvm-repo/acvm_js/test/shared/memory_op.ts index b5ab64b3447e..f2e5ab4af491 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/test/shared/memory_op.ts +++ b/noir/noir-repo/acvm-repo/acvm_js/test/shared/memory_op.ts @@ -1,9 +1,10 @@ // See `memory_op_circuit` integration test in `acir/tests/test_program_serialization.rs`. export const bytecode = Uint8Array.from([ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 145, 187, 17, 0, 32, 8, 67, 195, 111, 31, 220, 192, 253, 167, 178, 144, 2, - 239, 236, 132, 194, 52, 129, 230, 93, 8, 6, 64, 176, 101, 225, 28, 78, 49, 43, 238, 154, 225, 254, 166, 209, 205, 165, - 98, 174, 212, 177, 188, 187, 92, 255, 173, 92, 173, 190, 93, 82, 80, 78, 123, 14, 127, 60, 97, 1, 210, 144, 46, 242, - 19, 3, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 81, 201, 13, 0, 32, 8, 147, 195, 125, 112, 3, 247, + 159, 74, 141, 60, 106, 226, 79, 120, 216, 132, 180, 124, 154, 82, 168, 108, 212, 57, 2, + 122, 129, 157, 201, 181, 150, 59, 186, 179, 189, 161, 101, 251, 82, 176, 175, 196, 121, 89, + 118, 185, 246, 91, 185, 26, 125, 187, 64, 80, 134, 29, 195, 31, 79, 24, 2, 250, 167, 252, + 27, 3, 0, 0, ]); export const initialWitnessMap = new Map([ diff --git a/noir/noir-repo/acvm-repo/acvm_js/test/shared/pedersen.ts b/noir/noir-repo/acvm-repo/acvm_js/test/shared/pedersen.ts index 5150d24131c4..0882874136ee 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/test/shared/pedersen.ts +++ b/noir/noir-repo/acvm-repo/acvm_js/test/shared/pedersen.ts @@ -1,7 +1,8 @@ // See `pedersen_circuit` integration test in `acir/tests/test_program_serialization.rs`. export const bytecode = Uint8Array.from([ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 93, 74, 135, 9, 0, 48, 8, 75, 171, 224, 255, 15, 139, 27, 196, 64, 200, 100, 0, 15, - 133, 80, 57, 89, 219, 127, 39, 173, 126, 235, 236, 247, 151, 48, 224, 71, 90, 33, 97, 0, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 93, 74, 7, 6, 0, 0, 8, 108, 209, 255, 63, 156, 54, 233, + 56, 55, 17, 26, 18, 196, 241, 169, 250, 178, 141, 167, 32, 159, 254, 234, 238, 255, 87, + 112, 52, 63, 63, 101, 105, 0, 0, 0, ]); export const initialWitnessMap = new Map([[1, '0x0000000000000000000000000000000000000000000000000000000000000001']]); diff --git a/noir/noir-repo/acvm-repo/acvm_js/test/shared/schnorr_verify.ts b/noir/noir-repo/acvm-repo/acvm_js/test/shared/schnorr_verify.ts index 2127de66f694..8f5667bd8883 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/test/shared/schnorr_verify.ts +++ b/noir/noir-repo/acvm-repo/acvm_js/test/shared/schnorr_verify.ts @@ -1,17 +1,21 @@ // See `schnorr_verify_circuit` integration test in `acir/tests/test_program_serialization.rs`. export const bytecode = Uint8Array.from([ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 77, 210, 7, 74, 3, 1, 20, 69, 209, 177, 247, 222, 123, 239, 189, 119, 141, 93, 99, - 220, 133, 251, 95, 130, 152, 103, 78, 32, 3, 195, 33, 4, 66, 248, 239, 254, 20, 69, 209, 84, 212, 158, 216, 206, 223, - 234, 219, 204, 146, 239, 91, 170, 111, 103, 245, 109, 101, 27, 219, 217, 193, 250, 219, 197, 110, 246, 176, 151, 125, - 236, 231, 0, 7, 57, 196, 97, 142, 112, 148, 99, 28, 231, 4, 39, 57, 197, 105, 206, 112, 150, 115, 156, 231, 2, 23, - 185, 196, 101, 174, 112, 149, 107, 92, 231, 6, 55, 185, 197, 109, 238, 112, 151, 123, 220, 231, 1, 15, 121, 196, 99, - 158, 240, 148, 103, 60, 231, 5, 47, 121, 197, 107, 222, 240, 150, 119, 188, 231, 3, 75, 124, 228, 83, 195, 142, 121, - 158, 125, 126, 225, 43, 223, 248, 206, 15, 126, 178, 204, 47, 86, 248, 237, 119, 43, 76, 127, 105, 47, 189, 165, 181, - 116, 150, 198, 234, 125, 117, 249, 47, 233, 41, 45, 165, 163, 52, 148, 126, 210, 78, 186, 73, 51, 233, 37, 173, 164, - 147, 52, 146, 62, 210, 70, 186, 72, 19, 233, 33, 45, 164, 131, 52, 144, 253, 23, 139, 218, 238, 217, 60, 123, 103, - 235, 236, 156, 141, 179, 239, 166, 93, 183, 237, 185, 107, 199, 125, 251, 29, 218, 237, 216, 94, 167, 118, 58, 183, - 207, 165, 93, 174, 237, 113, 107, 135, 123, 247, 47, 185, 251, 147, 59, 191, 184, 239, 155, 187, 126, 184, 103, 217, - 29, 235, 55, 171, 223, 173, 104, 184, 231, 255, 243, 7, 236, 52, 239, 128, 225, 3, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 77, 210, 7, 78, 2, 1, 20, 69, 81, 236, 189, 247, 222, + 123, 239, 93, 177, 33, 34, 238, 194, 253, 47, 193, 200, 147, 67, 194, 36, 147, 163, 33, 33, + 228, 191, 219, 82, 168, 63, 63, 181, 183, 197, 223, 177, 147, 191, 181, 183, 149, 69, 159, + 183, 213, 222, 238, 218, 219, 206, 14, 118, 178, 139, 141, 183, 135, 189, 236, 99, 63, 7, + 56, 200, 33, 14, 115, 132, 163, 28, 227, 56, 39, 56, 201, 41, 78, 115, 134, 179, 156, 227, + 60, 23, 184, 200, 37, 46, 115, 133, 171, 92, 227, 58, 55, 184, 201, 45, 110, 115, 135, 187, + 220, 227, 62, 15, 120, 200, 35, 30, 243, 132, 167, 60, 227, 57, 47, 120, 201, 43, 94, 243, + 134, 183, 188, 227, 61, 31, 248, 200, 39, 22, 249, 204, 151, 166, 29, 243, 188, 250, 255, + 141, 239, 44, 241, 131, 101, 126, 178, 194, 47, 86, 249, 237, 123, 171, 76, 127, 105, 47, + 189, 165, 181, 116, 150, 198, 26, 125, 245, 248, 45, 233, 41, 45, 165, 163, 52, 148, 126, + 210, 78, 186, 73, 51, 233, 37, 173, 164, 147, 52, 146, 62, 210, 70, 186, 72, 19, 233, 33, + 45, 164, 131, 52, 144, 253, 151, 11, 245, 221, 179, 121, 246, 206, 214, 217, 57, 27, 103, + 223, 109, 187, 238, 218, 115, 223, 142, 135, 246, 59, 182, 219, 169, 189, 206, 237, 116, + 105, 159, 107, 187, 220, 218, 227, 222, 14, 143, 238, 95, 116, 247, 23, 119, 126, 115, 223, + 146, 187, 150, 221, 179, 226, 142, 141, 155, 53, 238, 86, 104, 186, 231, 255, 243, 7, 100, + 141, 232, 192, 233, 3, 0, 0, ]); export const initialWitnessMap = new Map([ diff --git a/noir/noir-repo/acvm-repo/acvm_js/test/shared/witness_compression.ts b/noir/noir-repo/acvm-repo/acvm_js/test/shared/witness_compression.ts index 36b9a0284af6..f9d66c2c8d0e 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/test/shared/witness_compression.ts +++ b/noir/noir-repo/acvm-repo/acvm_js/test/shared/witness_compression.ts @@ -4,19 +4,22 @@ // assert(x != y); // x + y // } +// +// Regenerate this byte array by going to the Noir integration tests and running `/test_programs/execution_success/witness_compression` +// after recompiling Noir to print the witness byte array to be written to file after execution export const expectedCompressedWitnessMap = Uint8Array.from([ - 31, 139, 8, 0, 0, 0, 0, 0, 2, 255, 173, 208, 187, 13, 128, 48, 12, 4, 80, 190, 153, 199, 142, 237, 196, 238, 88, 133, - 8, 103, 255, 17, 64, 34, 5, 61, 62, 233, 164, 171, 94, 113, 105, 122, 51, 63, 61, 198, 134, 127, 193, 37, 206, 202, - 235, 199, 34, 40, 204, 94, 179, 35, 225, 9, 217, 154, 10, 176, 180, 162, 168, 40, 42, 87, 86, 34, 87, 214, 106, 205, - 42, 24, 50, 57, 118, 49, 234, 3, 219, 2, 173, 61, 240, 175, 20, 103, 209, 13, 151, 252, 77, 33, 208, 1, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 2, 255, 173, 206, 185, 13, 0, 48, 8, 67, 209, 144, 107, 30, 146, + 44, 144, 253, 167, 162, 65, 130, 158, 239, 198, 174, 158, 44, 45, 178, 211, 254, 222, 90, + 203, 17, 206, 186, 29, 252, 53, 64, 107, 114, 150, 46, 206, 122, 6, 24, 73, 44, 193, 220, + 1, 0, 0, ]); export const expectedWitnessMap = new Map([ - [1, '0x0000000000000000000000000000000000000000000000000000000000000001'], - [2, '0x0000000000000000000000000000000000000000000000000000000000000002'], - [3, '0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000'], - [4, '0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000'], - [5, '0x0000000000000000000000000000000000000000000000000000000000000001'], - [6, '0x0000000000000000000000000000000000000000000000000000000000000003'], + [0, '0x0000000000000000000000000000000000000000000000000000000000000001'], + [1, '0x0000000000000000000000000000000000000000000000000000000000000002'], + [2, '0x0000000000000000000000000000000000000000000000000000000000000001'], + [3, '0x0000000000000000000000000000000000000000000000000000000000000001'], + [4, '0x0000000000000000000000000000000000000000000000000000000000000000'], + [5, '0x0000000000000000000000000000000000000000000000000000000000000003'], ]); diff --git a/noir/noir-repo/compiler/integration-tests/.gitignore b/noir/noir-repo/compiler/integration-tests/.gitignore index 40571b83650d..d27cc5f16183 100644 --- a/noir/noir-repo/compiler/integration-tests/.gitignore +++ b/noir/noir-repo/compiler/integration-tests/.gitignore @@ -1,4 +1,3 @@ -contracts crs node_modules diff --git a/noir/noir-repo/compiler/integration-tests/contracts/1_mul.sol b/noir/noir-repo/compiler/integration-tests/contracts/1_mul.sol new file mode 100644 index 000000000000..ff8f36385337 --- /dev/null +++ b/noir/noir-repo/compiler/integration-tests/contracts/1_mul.sol @@ -0,0 +1,2869 @@ +// Verification Key Hash: 81dab81c9312ecc480984185bcdeabfb118f294791980be42c247006c29b27de +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2022 Aztec +pragma solidity >=0.8.4; + +library UltraVerificationKey { + function verificationKeyHash() internal pure returns(bytes32) { + return 0x81dab81c9312ecc480984185bcdeabfb118f294791980be42c247006c29b27de; + } + + function loadVerificationKey(uint256 _vk, uint256 _omegaInverseLoc) internal pure { + assembly { + mstore(add(_vk, 0x00), 0x0000000000000000000000000000000000000000000000000000000000001000) // vk.circuit_size + mstore(add(_vk, 0x20), 0x0000000000000000000000000000000000000000000000000000000000000000) // vk.num_inputs + mstore(add(_vk, 0x40), 0x0931d596de2fd10f01ddd073fd5a90a976f169c76f039bb91c4775720042d43a) // vk.work_root + mstore(add(_vk, 0x60), 0x3061482dfa038d0fb5b4c0b226194047a2616509f531d4fa3acdb77496c10001) // vk.domain_inverse + mstore(add(_vk, 0x80), 0x26dff731489360cd9d88e52bad2198f84d36c1439b77c54f95d6eaf0cef94b8f) // vk.Q1.x + mstore(add(_vk, 0xa0), 0x02acb21f0f38895956e06930708b45106e016ebefc0d24dcdb8c7f959967a90c) // vk.Q1.y + mstore(add(_vk, 0xc0), 0x24ef08dff23f2729f6cd70ed8305655ccec1dfb5e70d8e8a2d4190ce1a1d7e81) // vk.Q2.x + mstore(add(_vk, 0xe0), 0x16ae4c218a37acdb580a2f2c2033d4c93ee06633febe6c96d6bc845b1fbbf7db) // vk.Q2.y + mstore(add(_vk, 0x100), 0x02be54ccdfcf358d15e469f7a7a79d4851996cb90ff7e6ae89734c53b5db89b2) // vk.Q3.x + mstore(add(_vk, 0x120), 0x292fefb96ebc59f41b06421baa766e8949eab20ba1ddbe3cdc0d4a130bdc9dac) // vk.Q3.y + mstore(add(_vk, 0x140), 0x019d7129fa4f0cc04801bd9b9065a25c61b3400244190698a17d73f550c3ad01) // vk.Q4.x + mstore(add(_vk, 0x160), 0x106810b16c402a25c417c5603b70b3ee6b41316be80ba38bb2276f8e9427d8b9) // vk.Q4.y + mstore(add(_vk, 0x180), 0x0efb192384fe64f333475e3c441dcb9d8933a2b4a4179d43b66ee1966199de66) // vk.Q_M.x + mstore(add(_vk, 0x1a0), 0x2a56cfd4a9b725326de5171dd6ec6cba64945cde70652768e4aeecb4a92f193a) // vk.Q_M.y + mstore(add(_vk, 0x1c0), 0x24e321e4d1e65f3c26b32903a432217b5d1c03cf5ac13fa055b5d38216bac3f1) // vk.Q_C.x + mstore(add(_vk, 0x1e0), 0x304c9ace458fbf93f3e9d07fea2b48edc40e9d248862871437a044d557b89085) // vk.Q_C.y + mstore(add(_vk, 0x200), 0x040f659b07806f721e8eeb17773c70a7351a0e59a15027c7f87343d5bd2cac01) // vk.Q_ARITHMETIC.x + mstore(add(_vk, 0x220), 0x215a63918831655a2020158099ebd13bbab94febef4febe815bbca0ac5b0b303) // vk.Q_ARITHMETIC.y + mstore(add(_vk, 0x240), 0x0348ad0a2d9d9a94c78f6c20d7ed0ee0a018bc5a3e51a3453f4256430b0d526c) // vk.QSORT.x + mstore(add(_vk, 0x260), 0x0b711c4268e26d19a11f7560fc53828b7d9e6f920ccb8a0129f8d515c66d99ac) // vk.QSORT.y + mstore(add(_vk, 0x280), 0x13982fd0cf8da5082a77561113bb5ee51e2e82380da3da5ad0f24e49e5f32208) // vk.Q_ELLIPTIC.x + mstore(add(_vk, 0x2a0), 0x1aa5ffd5aa4c16d1c66e18c4574a3ab0b25e9b4e4e04ad1280d1a264237717e0) // vk.Q_ELLIPTIC.y + mstore(add(_vk, 0x2c0), 0x1750f44d3f9dfad78a1e2127ef91051ce018f20536fe45ca28dcc7b248389fc0) // vk.Q_AUX.x + mstore(add(_vk, 0x2e0), 0x1a05418f502a965c39994cd3f83e39164b49c0f27d4f5ac4550751cc0a24bb58) // vk.Q_AUX.y + mstore(add(_vk, 0x300), 0x0e79dad980ecbcba02fa09399f492293608ea5ec55655f381851ab2a7fd9d3e4) // vk.SIGMA1.x + mstore(add(_vk, 0x320), 0x20dcf4e6e84362a1fbb32928b49070375f866ce7334fe5d96572d6a885879066) // vk.SIGMA1.y + mstore(add(_vk, 0x340), 0x04700138101e581226ac624463c28d886eedc87159a518f9c59e117b30dd9fc6) // vk.SIGMA2.x + mstore(add(_vk, 0x360), 0x0766d9586e6192576f6eddb0e2c023f9a574f4d736c9480820431f434b235344) // vk.SIGMA2.y + mstore(add(_vk, 0x380), 0x196fd832eb6b30543b949cd2a124bd2d1504133b34fe6b6346f30cc7a3ed2a75) // vk.SIGMA3.x + mstore(add(_vk, 0x3a0), 0x14bfde5cb996c75c818cdf88d9234ccc0e905f27af5503f42a8f38c2892d6e1c) // vk.SIGMA3.y + mstore(add(_vk, 0x3c0), 0x03c8a1592fca76a3959266b015c120e99a764029d1373ce0a9329d8b441f841a) // vk.SIGMA4.x + mstore(add(_vk, 0x3e0), 0x2239ff07c67a2a59139ef012e667a5fb08293af4abc6dc70e1297e45e744355c) // vk.SIGMA4.y + mstore(add(_vk, 0x400), 0x259f452dc7fd2dda4013dba2196852bcf43c285b1d1f7f85341f3615d25fe97b) // vk.TABLE1.x + mstore(add(_vk, 0x420), 0x117500555dd886209c0b10ee8cd10e711e890a1c99a8f689419da8c52d2e8e9d) // vk.TABLE1.y + mstore(add(_vk, 0x440), 0x2577f542178a07dac262fdabad6f55a84fca32b13b92e520bb91a7455f78ccf1) // vk.TABLE2.x + mstore(add(_vk, 0x460), 0x0fc87ae27122e60eaacc070bd59aafe12644a82ee1345497f8c0302e92925c68) // vk.TABLE2.y + mstore(add(_vk, 0x480), 0x1612f501335a4b72ac55dbe2fd1a75e5fe2c041687603b6577581d673d13be50) // vk.TABLE3.x + mstore(add(_vk, 0x4a0), 0x160e8ef7ff5315cb640ec82e965db270846e904bb7d1c7ff02f32823de6c1c71) // vk.TABLE3.y + mstore(add(_vk, 0x4c0), 0x2d540ff1653b38acbcb9cda315442364007633f529476b2f169a0ff131bfb319) // vk.TABLE4.x + mstore(add(_vk, 0x4e0), 0x2198b9feb61f8160e357b8bb7ca329713898655cc94a0ac2d84944c737cf57e5) // vk.TABLE4.y + mstore(add(_vk, 0x500), 0x11c8df52c3ef754f80d11792cea4b7ad74612e486596cbe7f7d6a05f19c69444) // vk.TABLE_TYPE.x + mstore(add(_vk, 0x520), 0x10c8a36cbb2fd9ed8875b5106a37162ac2932f3bd1b6942b132546d2110a63e2) // vk.TABLE_TYPE.y + mstore(add(_vk, 0x540), 0x122470dc810ee1029ff28334364b1b3dd18193defaf51bb09296275700ee6dd0) // vk.ID1.x + mstore(add(_vk, 0x560), 0x018b2c609f8013a95b1e7c3346e2d3febea6791d393777bfc213831f687070b9) // vk.ID1.y + mstore(add(_vk, 0x580), 0x2fd86e853b82a697cfcd347bad53b66a655813df12ba231808bf65f6561e923c) // vk.ID2.x + mstore(add(_vk, 0x5a0), 0x12b82a7864a782e5afc7f9c85f01ee1b233d94da8bcd1fac485cfdd481db8086) // vk.ID2.y + mstore(add(_vk, 0x5c0), 0x23afba4022c9e1a3eb7ab039a120c48ee661a8e06751225fb989b53f0bfe0b34) // vk.ID3.x + mstore(add(_vk, 0x5e0), 0x04f7c94dc819346aae8a76a89d7d1792c1806ed2e76828e60ee05241952773ec) // vk.ID3.y + mstore(add(_vk, 0x600), 0x282ed40f6896050dc339a08a220ddfb4d33a7c766684e2dde14ca6f452da84b0) // vk.ID4.x + mstore(add(_vk, 0x620), 0x2dadeff4061603c87f4dce0e42c6e145f590062d9bf6e6642f997275bb05b6af) // vk.ID4.y + mstore(add(_vk, 0x640), 0x00) // vk.contains_recursive_proof + mstore(add(_vk, 0x660), 0) // vk.recursive_proof_public_input_indices + mstore(add(_vk, 0x680), 0x260e01b251f6f1c7e7ff4e580791dee8ea51d87a358e038b4efe30fac09383c1) // vk.g2_x.X.c1 + mstore(add(_vk, 0x6a0), 0x0118c4d5b837bcc2bc89b5b398b5974e9f5944073b32078b7e231fec938883b0) // vk.g2_x.X.c0 + mstore(add(_vk, 0x6c0), 0x04fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe4) // vk.g2_x.Y.c1 + mstore(add(_vk, 0x6e0), 0x22febda3c0c0632a56475b4214e5615e11e6dd3f96e6cea2854a87d4dacc5e55) // vk.g2_x.Y.c0 + mstore(_omegaInverseLoc, 0x1af864d211b88d9ccf2e371c2ba088d9269d3fdea04e05acb6f70f8dc79e0e57) // vk.work_root_inverse + } + } +} + +/** + * @title Ultra Plonk proof verification contract + * @dev Top level Plonk proof verification contract, which allows Plonk proof to be verified + */ +abstract contract BaseUltraVerifier { + // VERIFICATION KEY MEMORY LOCATIONS + uint256 internal constant N_LOC = 0x380; + uint256 internal constant NUM_INPUTS_LOC = 0x3a0; + uint256 internal constant OMEGA_LOC = 0x3c0; + uint256 internal constant DOMAIN_INVERSE_LOC = 0x3e0; + uint256 internal constant Q1_X_LOC = 0x400; + uint256 internal constant Q1_Y_LOC = 0x420; + uint256 internal constant Q2_X_LOC = 0x440; + uint256 internal constant Q2_Y_LOC = 0x460; + uint256 internal constant Q3_X_LOC = 0x480; + uint256 internal constant Q3_Y_LOC = 0x4a0; + uint256 internal constant Q4_X_LOC = 0x4c0; + uint256 internal constant Q4_Y_LOC = 0x4e0; + uint256 internal constant QM_X_LOC = 0x500; + uint256 internal constant QM_Y_LOC = 0x520; + uint256 internal constant QC_X_LOC = 0x540; + uint256 internal constant QC_Y_LOC = 0x560; + uint256 internal constant QARITH_X_LOC = 0x580; + uint256 internal constant QARITH_Y_LOC = 0x5a0; + uint256 internal constant QSORT_X_LOC = 0x5c0; + uint256 internal constant QSORT_Y_LOC = 0x5e0; + uint256 internal constant QELLIPTIC_X_LOC = 0x600; + uint256 internal constant QELLIPTIC_Y_LOC = 0x620; + uint256 internal constant QAUX_X_LOC = 0x640; + uint256 internal constant QAUX_Y_LOC = 0x660; + uint256 internal constant SIGMA1_X_LOC = 0x680; + uint256 internal constant SIGMA1_Y_LOC = 0x6a0; + uint256 internal constant SIGMA2_X_LOC = 0x6c0; + uint256 internal constant SIGMA2_Y_LOC = 0x6e0; + uint256 internal constant SIGMA3_X_LOC = 0x700; + uint256 internal constant SIGMA3_Y_LOC = 0x720; + uint256 internal constant SIGMA4_X_LOC = 0x740; + uint256 internal constant SIGMA4_Y_LOC = 0x760; + uint256 internal constant TABLE1_X_LOC = 0x780; + uint256 internal constant TABLE1_Y_LOC = 0x7a0; + uint256 internal constant TABLE2_X_LOC = 0x7c0; + uint256 internal constant TABLE2_Y_LOC = 0x7e0; + uint256 internal constant TABLE3_X_LOC = 0x800; + uint256 internal constant TABLE3_Y_LOC = 0x820; + uint256 internal constant TABLE4_X_LOC = 0x840; + uint256 internal constant TABLE4_Y_LOC = 0x860; + uint256 internal constant TABLE_TYPE_X_LOC = 0x880; + uint256 internal constant TABLE_TYPE_Y_LOC = 0x8a0; + uint256 internal constant ID1_X_LOC = 0x8c0; + uint256 internal constant ID1_Y_LOC = 0x8e0; + uint256 internal constant ID2_X_LOC = 0x900; + uint256 internal constant ID2_Y_LOC = 0x920; + uint256 internal constant ID3_X_LOC = 0x940; + uint256 internal constant ID3_Y_LOC = 0x960; + uint256 internal constant ID4_X_LOC = 0x980; + uint256 internal constant ID4_Y_LOC = 0x9a0; + uint256 internal constant CONTAINS_RECURSIVE_PROOF_LOC = 0x9c0; + uint256 internal constant RECURSIVE_PROOF_PUBLIC_INPUT_INDICES_LOC = 0x9e0; + uint256 internal constant G2X_X0_LOC = 0xa00; + uint256 internal constant G2X_X1_LOC = 0xa20; + uint256 internal constant G2X_Y0_LOC = 0xa40; + uint256 internal constant G2X_Y1_LOC = 0xa60; + + // ### PROOF DATA MEMORY LOCATIONS + uint256 internal constant W1_X_LOC = 0x1200; + uint256 internal constant W1_Y_LOC = 0x1220; + uint256 internal constant W2_X_LOC = 0x1240; + uint256 internal constant W2_Y_LOC = 0x1260; + uint256 internal constant W3_X_LOC = 0x1280; + uint256 internal constant W3_Y_LOC = 0x12a0; + uint256 internal constant W4_X_LOC = 0x12c0; + uint256 internal constant W4_Y_LOC = 0x12e0; + uint256 internal constant S_X_LOC = 0x1300; + uint256 internal constant S_Y_LOC = 0x1320; + uint256 internal constant Z_X_LOC = 0x1340; + uint256 internal constant Z_Y_LOC = 0x1360; + uint256 internal constant Z_LOOKUP_X_LOC = 0x1380; + uint256 internal constant Z_LOOKUP_Y_LOC = 0x13a0; + uint256 internal constant T1_X_LOC = 0x13c0; + uint256 internal constant T1_Y_LOC = 0x13e0; + uint256 internal constant T2_X_LOC = 0x1400; + uint256 internal constant T2_Y_LOC = 0x1420; + uint256 internal constant T3_X_LOC = 0x1440; + uint256 internal constant T3_Y_LOC = 0x1460; + uint256 internal constant T4_X_LOC = 0x1480; + uint256 internal constant T4_Y_LOC = 0x14a0; + + uint256 internal constant W1_EVAL_LOC = 0x1600; + uint256 internal constant W2_EVAL_LOC = 0x1620; + uint256 internal constant W3_EVAL_LOC = 0x1640; + uint256 internal constant W4_EVAL_LOC = 0x1660; + uint256 internal constant S_EVAL_LOC = 0x1680; + uint256 internal constant Z_EVAL_LOC = 0x16a0; + uint256 internal constant Z_LOOKUP_EVAL_LOC = 0x16c0; + uint256 internal constant Q1_EVAL_LOC = 0x16e0; + uint256 internal constant Q2_EVAL_LOC = 0x1700; + uint256 internal constant Q3_EVAL_LOC = 0x1720; + uint256 internal constant Q4_EVAL_LOC = 0x1740; + uint256 internal constant QM_EVAL_LOC = 0x1760; + uint256 internal constant QC_EVAL_LOC = 0x1780; + uint256 internal constant QARITH_EVAL_LOC = 0x17a0; + uint256 internal constant QSORT_EVAL_LOC = 0x17c0; + uint256 internal constant QELLIPTIC_EVAL_LOC = 0x17e0; + uint256 internal constant QAUX_EVAL_LOC = 0x1800; + uint256 internal constant TABLE1_EVAL_LOC = 0x1840; + uint256 internal constant TABLE2_EVAL_LOC = 0x1860; + uint256 internal constant TABLE3_EVAL_LOC = 0x1880; + uint256 internal constant TABLE4_EVAL_LOC = 0x18a0; + uint256 internal constant TABLE_TYPE_EVAL_LOC = 0x18c0; + uint256 internal constant ID1_EVAL_LOC = 0x18e0; + uint256 internal constant ID2_EVAL_LOC = 0x1900; + uint256 internal constant ID3_EVAL_LOC = 0x1920; + uint256 internal constant ID4_EVAL_LOC = 0x1940; + uint256 internal constant SIGMA1_EVAL_LOC = 0x1960; + uint256 internal constant SIGMA2_EVAL_LOC = 0x1980; + uint256 internal constant SIGMA3_EVAL_LOC = 0x19a0; + uint256 internal constant SIGMA4_EVAL_LOC = 0x19c0; + uint256 internal constant W1_OMEGA_EVAL_LOC = 0x19e0; + uint256 internal constant W2_OMEGA_EVAL_LOC = 0x2000; + uint256 internal constant W3_OMEGA_EVAL_LOC = 0x2020; + uint256 internal constant W4_OMEGA_EVAL_LOC = 0x2040; + uint256 internal constant S_OMEGA_EVAL_LOC = 0x2060; + uint256 internal constant Z_OMEGA_EVAL_LOC = 0x2080; + uint256 internal constant Z_LOOKUP_OMEGA_EVAL_LOC = 0x20a0; + uint256 internal constant TABLE1_OMEGA_EVAL_LOC = 0x20c0; + uint256 internal constant TABLE2_OMEGA_EVAL_LOC = 0x20e0; + uint256 internal constant TABLE3_OMEGA_EVAL_LOC = 0x2100; + uint256 internal constant TABLE4_OMEGA_EVAL_LOC = 0x2120; + + uint256 internal constant PI_Z_X_LOC = 0x2300; + uint256 internal constant PI_Z_Y_LOC = 0x2320; + uint256 internal constant PI_Z_OMEGA_X_LOC = 0x2340; + uint256 internal constant PI_Z_OMEGA_Y_LOC = 0x2360; + + // Used for elliptic widget. These are alias names for wire + shifted wire evaluations + uint256 internal constant X1_EVAL_LOC = W2_EVAL_LOC; + uint256 internal constant X2_EVAL_LOC = W1_OMEGA_EVAL_LOC; + uint256 internal constant X3_EVAL_LOC = W2_OMEGA_EVAL_LOC; + uint256 internal constant Y1_EVAL_LOC = W3_EVAL_LOC; + uint256 internal constant Y2_EVAL_LOC = W4_OMEGA_EVAL_LOC; + uint256 internal constant Y3_EVAL_LOC = W3_OMEGA_EVAL_LOC; + uint256 internal constant QBETA_LOC = Q3_EVAL_LOC; + uint256 internal constant QBETA_SQR_LOC = Q4_EVAL_LOC; + uint256 internal constant QSIGN_LOC = Q1_EVAL_LOC; + + // ### CHALLENGES MEMORY OFFSETS + + uint256 internal constant C_BETA_LOC = 0x2600; + uint256 internal constant C_GAMMA_LOC = 0x2620; + uint256 internal constant C_ALPHA_LOC = 0x2640; + uint256 internal constant C_ETA_LOC = 0x2660; + uint256 internal constant C_ETA_SQR_LOC = 0x2680; + uint256 internal constant C_ETA_CUBE_LOC = 0x26a0; + + uint256 internal constant C_ZETA_LOC = 0x26c0; + uint256 internal constant C_CURRENT_LOC = 0x26e0; + uint256 internal constant C_V0_LOC = 0x2700; + uint256 internal constant C_V1_LOC = 0x2720; + uint256 internal constant C_V2_LOC = 0x2740; + uint256 internal constant C_V3_LOC = 0x2760; + uint256 internal constant C_V4_LOC = 0x2780; + uint256 internal constant C_V5_LOC = 0x27a0; + uint256 internal constant C_V6_LOC = 0x27c0; + uint256 internal constant C_V7_LOC = 0x27e0; + uint256 internal constant C_V8_LOC = 0x2800; + uint256 internal constant C_V9_LOC = 0x2820; + uint256 internal constant C_V10_LOC = 0x2840; + uint256 internal constant C_V11_LOC = 0x2860; + uint256 internal constant C_V12_LOC = 0x2880; + uint256 internal constant C_V13_LOC = 0x28a0; + uint256 internal constant C_V14_LOC = 0x28c0; + uint256 internal constant C_V15_LOC = 0x28e0; + uint256 internal constant C_V16_LOC = 0x2900; + uint256 internal constant C_V17_LOC = 0x2920; + uint256 internal constant C_V18_LOC = 0x2940; + uint256 internal constant C_V19_LOC = 0x2960; + uint256 internal constant C_V20_LOC = 0x2980; + uint256 internal constant C_V21_LOC = 0x29a0; + uint256 internal constant C_V22_LOC = 0x29c0; + uint256 internal constant C_V23_LOC = 0x29e0; + uint256 internal constant C_V24_LOC = 0x2a00; + uint256 internal constant C_V25_LOC = 0x2a20; + uint256 internal constant C_V26_LOC = 0x2a40; + uint256 internal constant C_V27_LOC = 0x2a60; + uint256 internal constant C_V28_LOC = 0x2a80; + uint256 internal constant C_V29_LOC = 0x2aa0; + uint256 internal constant C_V30_LOC = 0x2ac0; + + uint256 internal constant C_U_LOC = 0x2b00; + + // ### LOCAL VARIABLES MEMORY OFFSETS + uint256 internal constant DELTA_NUMERATOR_LOC = 0x3000; + uint256 internal constant DELTA_DENOMINATOR_LOC = 0x3020; + uint256 internal constant ZETA_POW_N_LOC = 0x3040; + uint256 internal constant PUBLIC_INPUT_DELTA_LOC = 0x3060; + uint256 internal constant ZERO_POLY_LOC = 0x3080; + uint256 internal constant L_START_LOC = 0x30a0; + uint256 internal constant L_END_LOC = 0x30c0; + uint256 internal constant R_ZERO_EVAL_LOC = 0x30e0; + + uint256 internal constant PLOOKUP_DELTA_NUMERATOR_LOC = 0x3100; + uint256 internal constant PLOOKUP_DELTA_DENOMINATOR_LOC = 0x3120; + uint256 internal constant PLOOKUP_DELTA_LOC = 0x3140; + + uint256 internal constant ACCUMULATOR_X_LOC = 0x3160; + uint256 internal constant ACCUMULATOR_Y_LOC = 0x3180; + uint256 internal constant ACCUMULATOR2_X_LOC = 0x31a0; + uint256 internal constant ACCUMULATOR2_Y_LOC = 0x31c0; + uint256 internal constant PAIRING_LHS_X_LOC = 0x31e0; + uint256 internal constant PAIRING_LHS_Y_LOC = 0x3200; + uint256 internal constant PAIRING_RHS_X_LOC = 0x3220; + uint256 internal constant PAIRING_RHS_Y_LOC = 0x3240; + + // misc stuff + uint256 internal constant OMEGA_INVERSE_LOC = 0x3300; + uint256 internal constant C_ALPHA_SQR_LOC = 0x3320; + uint256 internal constant C_ALPHA_CUBE_LOC = 0x3340; + uint256 internal constant C_ALPHA_QUAD_LOC = 0x3360; + uint256 internal constant C_ALPHA_BASE_LOC = 0x3380; + + // ### RECURSION VARIABLE MEMORY LOCATIONS + uint256 internal constant RECURSIVE_P1_X_LOC = 0x3400; + uint256 internal constant RECURSIVE_P1_Y_LOC = 0x3420; + uint256 internal constant RECURSIVE_P2_X_LOC = 0x3440; + uint256 internal constant RECURSIVE_P2_Y_LOC = 0x3460; + uint256 internal constant PUBLIC_INPUTS_HASH_LOCATION = 0x3480; + + // sub-identity storage + uint256 internal constant PERMUTATION_IDENTITY = 0x3500; + uint256 internal constant PLOOKUP_IDENTITY = 0x3520; + uint256 internal constant ARITHMETIC_IDENTITY = 0x3540; + uint256 internal constant SORT_IDENTITY = 0x3560; + uint256 internal constant ELLIPTIC_IDENTITY = 0x3580; + uint256 internal constant AUX_IDENTITY = 0x35a0; + uint256 internal constant AUX_NON_NATIVE_FIELD_EVALUATION = 0x35c0; + uint256 internal constant AUX_LIMB_ACCUMULATOR_EVALUATION = 0x35e0; + uint256 internal constant AUX_RAM_CONSISTENCY_EVALUATION = 0x3600; + uint256 internal constant AUX_ROM_CONSISTENCY_EVALUATION = 0x3620; + uint256 internal constant AUX_MEMORY_EVALUATION = 0x3640; + + uint256 internal constant QUOTIENT_EVAL_LOC = 0x3660; + uint256 internal constant ZERO_POLY_INVERSE_LOC = 0x3680; + + // when hashing public inputs we use memory at NU_CHALLENGE_INPUT_LOC_A, as the hash input size is unknown at compile time + uint256 internal constant NU_CHALLENGE_INPUT_LOC_A = 0x36a0; + uint256 internal constant NU_CHALLENGE_INPUT_LOC_B = 0x36c0; + uint256 internal constant NU_CHALLENGE_INPUT_LOC_C = 0x36e0; + + bytes4 internal constant INVALID_VERIFICATION_KEY_SELECTOR = 0x7e5769bf; + bytes4 internal constant POINT_NOT_ON_CURVE_SELECTOR = 0xa3dad654; + bytes4 internal constant PUBLIC_INPUT_INVALID_BN128_G1_POINT_SELECTOR = 0xeba9f4a6; + bytes4 internal constant PUBLIC_INPUT_GE_P_SELECTOR = 0x374a972f; + bytes4 internal constant MOD_EXP_FAILURE_SELECTOR = 0xf894a7bc; + bytes4 internal constant PAIRING_PREAMBLE_FAILED_SELECTOR = 0x01882d81; + bytes4 internal constant OPENING_COMMITMENT_FAILED_SELECTOR = 0x4e719763; + bytes4 internal constant PAIRING_FAILED_SELECTOR = 0xd71fd263; + + uint256 internal constant ETA_INPUT_LENGTH = 0xc0; // W1, W2, W3 = 6 * 0x20 bytes + + // We need to hash 41 field elements when generating the NU challenge + // w1, w2, w3, w4, s, z, z_lookup, q1, q2, q3, q4, qm, qc, qarith (14) + // qsort, qelliptic, qaux, sigma1, sigma2, sigma, sigma4, (7) + // table1, table2, table3, table4, tabletype, id1, id2, id3, id4, (9) + // w1_omega, w2_omega, w3_omega, w4_omega, s_omega, z_omega, z_lookup_omega, (7) + // table1_omega, table2_omega, table3_omega, table4_omega (4) + uint256 internal constant NU_INPUT_LENGTH = 0x520; // 0x520 = 41 * 0x20 + + // There are ELEVEN G1 group elements added into the transcript in the `beta` round, that we need to skip over + // W1, W2, W3, W4, S, Z, Z_LOOKUP, T1, T2, T3, T4 + uint256 internal constant NU_CALLDATA_SKIP_LENGTH = 0x2c0; // 11 * 0x40 = 0x2c0 + + uint256 internal constant NEGATIVE_INVERSE_OF_2_MODULO_P = + 0x183227397098d014dc2822db40c0ac2e9419f4243cdcb848a1f0fac9f8000000; + uint256 internal constant LIMB_SIZE = 0x100000000000000000; // 2<<68 + uint256 internal constant SUBLIMB_SHIFT = 0x4000; // 2<<14 + + // y^2 = x^3 + ax + b + // for Grumpkin, a = 0 and b = -17. We use b in a custom gate relation that evaluates elliptic curve arithmetic + uint256 internal constant GRUMPKIN_CURVE_B_PARAMETER_NEGATED = 17; + + error INVALID_VERIFICATION_KEY(); + error POINT_NOT_ON_CURVE(); + error PUBLIC_INPUT_COUNT_INVALID(uint256 expected, uint256 actual); + error PUBLIC_INPUT_INVALID_BN128_G1_POINT(); + error PUBLIC_INPUT_GE_P(); + error MOD_EXP_FAILURE(); + error PAIRING_PREAMBLE_FAILED(); + error OPENING_COMMITMENT_FAILED(); + error PAIRING_FAILED(); + + function getVerificationKeyHash() public pure virtual returns (bytes32); + + /** + * @dev We assume that the verification key loaded by this function is constant as we only verify it on deployment + */ + function loadVerificationKey(uint256 _vk, uint256 _omegaInverseLoc) internal pure virtual; + + constructor() { + loadVerificationKey(N_LOC, OMEGA_INVERSE_LOC); + + // We verify that all of the EC points in the verification key lie on the bn128 curve. + assembly { + let q := 21888242871839275222246405745257275088696311157297823662689037894645226208583 // EC group order + + let success := 1 + + // VALIDATE Q1 + { + let x := mload(Q1_X_LOC) + let y := mload(Q1_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE Q2 + { + let x := mload(Q2_X_LOC) + let y := mload(Q2_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE Q3 + { + let x := mload(Q3_X_LOC) + let y := mload(Q3_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE Q4 + { + let x := mload(Q4_X_LOC) + let y := mload(Q4_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + mstore(0x00, x) + mstore(0x20, y) + } + // VALIDATE QM + { + let x := mload(QM_X_LOC) + let y := mload(QM_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE QC + { + let x := mload(QC_X_LOC) + let y := mload(QC_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE QARITH + { + let x := mload(QARITH_X_LOC) + let y := mload(QARITH_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE QSORT + { + let x := mload(QSORT_X_LOC) + let y := mload(QSORT_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE QELLIPTIC + { + let x := mload(QELLIPTIC_X_LOC) + let y := mload(QELLIPTIC_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE QAUX + { + let x := mload(QAUX_X_LOC) + let y := mload(QAUX_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE SIGMA1 + { + let x := mload(SIGMA1_X_LOC) + let y := mload(SIGMA1_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE SIGMA2 + { + let x := mload(SIGMA2_X_LOC) + let y := mload(SIGMA2_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE SIGMA3 + { + let x := mload(SIGMA3_X_LOC) + let y := mload(SIGMA3_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE SIGMA4 + { + let x := mload(SIGMA4_X_LOC) + let y := mload(SIGMA4_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE TABLE1 + { + let x := mload(TABLE1_X_LOC) + let y := mload(TABLE1_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE TABLE2 + { + let x := mload(TABLE2_X_LOC) + let y := mload(TABLE2_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE TABLE3 + { + let x := mload(TABLE3_X_LOC) + let y := mload(TABLE3_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE TABLE4 + { + let x := mload(TABLE4_X_LOC) + let y := mload(TABLE4_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE TABLE_TYPE + { + let x := mload(TABLE_TYPE_X_LOC) + let y := mload(TABLE_TYPE_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE ID1 + { + let x := mload(ID1_X_LOC) + let y := mload(ID1_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE ID2 + { + let x := mload(ID2_X_LOC) + let y := mload(ID2_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE ID3 + { + let x := mload(ID3_X_LOC) + let y := mload(ID3_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE ID4 + { + let x := mload(ID4_X_LOC) + let y := mload(ID4_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + + if iszero(success) { + mstore(0x0, INVALID_VERIFICATION_KEY_SELECTOR) + revert(0x00, 0x04) + } + } + } + + /** + * @notice Verify a Ultra Plonk proof + * @param _proof - The serialized proof + * @param _publicInputs - An array of the public inputs + * @return True if proof is valid, reverts otherwise + */ + function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool) { + loadVerificationKey(N_LOC, OMEGA_INVERSE_LOC); + + uint256 requiredPublicInputCount; + assembly { + requiredPublicInputCount := mload(NUM_INPUTS_LOC) + } + if (requiredPublicInputCount != _publicInputs.length) { + revert PUBLIC_INPUT_COUNT_INVALID(requiredPublicInputCount, _publicInputs.length); + } + + assembly { + let q := 21888242871839275222246405745257275088696311157297823662689037894645226208583 // EC group order + let p := 21888242871839275222246405745257275088548364400416034343698204186575808495617 // Prime field order + + /** + * LOAD PROOF FROM CALLDATA + */ + { + let data_ptr := add(calldataload(0x04), 0x24) + + mstore(W1_Y_LOC, mod(calldataload(data_ptr), q)) + mstore(W1_X_LOC, mod(calldataload(add(data_ptr, 0x20)), q)) + + mstore(W2_Y_LOC, mod(calldataload(add(data_ptr, 0x40)), q)) + mstore(W2_X_LOC, mod(calldataload(add(data_ptr, 0x60)), q)) + + mstore(W3_Y_LOC, mod(calldataload(add(data_ptr, 0x80)), q)) + mstore(W3_X_LOC, mod(calldataload(add(data_ptr, 0xa0)), q)) + + mstore(W4_Y_LOC, mod(calldataload(add(data_ptr, 0xc0)), q)) + mstore(W4_X_LOC, mod(calldataload(add(data_ptr, 0xe0)), q)) + + mstore(S_Y_LOC, mod(calldataload(add(data_ptr, 0x100)), q)) + mstore(S_X_LOC, mod(calldataload(add(data_ptr, 0x120)), q)) + mstore(Z_Y_LOC, mod(calldataload(add(data_ptr, 0x140)), q)) + mstore(Z_X_LOC, mod(calldataload(add(data_ptr, 0x160)), q)) + mstore(Z_LOOKUP_Y_LOC, mod(calldataload(add(data_ptr, 0x180)), q)) + mstore(Z_LOOKUP_X_LOC, mod(calldataload(add(data_ptr, 0x1a0)), q)) + mstore(T1_Y_LOC, mod(calldataload(add(data_ptr, 0x1c0)), q)) + mstore(T1_X_LOC, mod(calldataload(add(data_ptr, 0x1e0)), q)) + + mstore(T2_Y_LOC, mod(calldataload(add(data_ptr, 0x200)), q)) + mstore(T2_X_LOC, mod(calldataload(add(data_ptr, 0x220)), q)) + + mstore(T3_Y_LOC, mod(calldataload(add(data_ptr, 0x240)), q)) + mstore(T3_X_LOC, mod(calldataload(add(data_ptr, 0x260)), q)) + + mstore(T4_Y_LOC, mod(calldataload(add(data_ptr, 0x280)), q)) + mstore(T4_X_LOC, mod(calldataload(add(data_ptr, 0x2a0)), q)) + + mstore(W1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x2c0)), p)) + mstore(W2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x2e0)), p)) + mstore(W3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x300)), p)) + mstore(W4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x320)), p)) + mstore(S_EVAL_LOC, mod(calldataload(add(data_ptr, 0x340)), p)) + mstore(Z_EVAL_LOC, mod(calldataload(add(data_ptr, 0x360)), p)) + mstore(Z_LOOKUP_EVAL_LOC, mod(calldataload(add(data_ptr, 0x380)), p)) + mstore(Q1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x3a0)), p)) + mstore(Q2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x3c0)), p)) + mstore(Q3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x3e0)), p)) + mstore(Q4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x400)), p)) + mstore(QM_EVAL_LOC, mod(calldataload(add(data_ptr, 0x420)), p)) + mstore(QC_EVAL_LOC, mod(calldataload(add(data_ptr, 0x440)), p)) + mstore(QARITH_EVAL_LOC, mod(calldataload(add(data_ptr, 0x460)), p)) + mstore(QSORT_EVAL_LOC, mod(calldataload(add(data_ptr, 0x480)), p)) + mstore(QELLIPTIC_EVAL_LOC, mod(calldataload(add(data_ptr, 0x4a0)), p)) + mstore(QAUX_EVAL_LOC, mod(calldataload(add(data_ptr, 0x4c0)), p)) + + mstore(SIGMA1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x4e0)), p)) + mstore(SIGMA2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x500)), p)) + + mstore(SIGMA3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x520)), p)) + mstore(SIGMA4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x540)), p)) + + mstore(TABLE1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x560)), p)) + mstore(TABLE2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x580)), p)) + mstore(TABLE3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x5a0)), p)) + mstore(TABLE4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x5c0)), p)) + mstore(TABLE_TYPE_EVAL_LOC, mod(calldataload(add(data_ptr, 0x5e0)), p)) + + mstore(ID1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x600)), p)) + mstore(ID2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x620)), p)) + mstore(ID3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x640)), p)) + mstore(ID4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x660)), p)) + + mstore(W1_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x680)), p)) + mstore(W2_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x6a0)), p)) + mstore(W3_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x6c0)), p)) + mstore(W4_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x6e0)), p)) + mstore(S_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x700)), p)) + + mstore(Z_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x720)), p)) + + mstore(Z_LOOKUP_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x740)), p)) + mstore(TABLE1_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x760)), p)) + mstore(TABLE2_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x780)), p)) + mstore(TABLE3_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x7a0)), p)) + mstore(TABLE4_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x7c0)), p)) + + mstore(PI_Z_Y_LOC, mod(calldataload(add(data_ptr, 0x7e0)), q)) + mstore(PI_Z_X_LOC, mod(calldataload(add(data_ptr, 0x800)), q)) + + mstore(PI_Z_OMEGA_Y_LOC, mod(calldataload(add(data_ptr, 0x820)), q)) + mstore(PI_Z_OMEGA_X_LOC, mod(calldataload(add(data_ptr, 0x840)), q)) + } + + /** + * LOAD RECURSIVE PROOF INTO MEMORY + */ + { + if mload(CONTAINS_RECURSIVE_PROOF_LOC) { + let public_inputs_ptr := add(calldataload(0x24), 0x24) + let index_counter := add(shl(5, mload(RECURSIVE_PROOF_PUBLIC_INPUT_INDICES_LOC)), public_inputs_ptr) + + let x0 := calldataload(index_counter) + x0 := add(x0, shl(68, calldataload(add(index_counter, 0x20)))) + x0 := add(x0, shl(136, calldataload(add(index_counter, 0x40)))) + x0 := add(x0, shl(204, calldataload(add(index_counter, 0x60)))) + let y0 := calldataload(add(index_counter, 0x80)) + y0 := add(y0, shl(68, calldataload(add(index_counter, 0xa0)))) + y0 := add(y0, shl(136, calldataload(add(index_counter, 0xc0)))) + y0 := add(y0, shl(204, calldataload(add(index_counter, 0xe0)))) + let x1 := calldataload(add(index_counter, 0x100)) + x1 := add(x1, shl(68, calldataload(add(index_counter, 0x120)))) + x1 := add(x1, shl(136, calldataload(add(index_counter, 0x140)))) + x1 := add(x1, shl(204, calldataload(add(index_counter, 0x160)))) + let y1 := calldataload(add(index_counter, 0x180)) + y1 := add(y1, shl(68, calldataload(add(index_counter, 0x1a0)))) + y1 := add(y1, shl(136, calldataload(add(index_counter, 0x1c0)))) + y1 := add(y1, shl(204, calldataload(add(index_counter, 0x1e0)))) + mstore(RECURSIVE_P1_X_LOC, x0) + mstore(RECURSIVE_P1_Y_LOC, y0) + mstore(RECURSIVE_P2_X_LOC, x1) + mstore(RECURSIVE_P2_Y_LOC, y1) + + // validate these are valid bn128 G1 points + if iszero(and(and(lt(x0, q), lt(x1, q)), and(lt(y0, q), lt(y1, q)))) { + mstore(0x00, PUBLIC_INPUT_INVALID_BN128_G1_POINT_SELECTOR) + revert(0x00, 0x04) + } + } + } + + { + /** + * Generate initial challenge + */ + mstore(0x00, shl(224, mload(N_LOC))) + mstore(0x04, shl(224, mload(NUM_INPUTS_LOC))) + let challenge := keccak256(0x00, 0x08) + + /** + * Generate eta challenge + */ + mstore(PUBLIC_INPUTS_HASH_LOCATION, challenge) + // The public input location is stored at 0x24, we then add 0x24 to skip selector and the length of public inputs + let public_inputs_start := add(calldataload(0x24), 0x24) + // copy the public inputs over + let public_input_size := mul(mload(NUM_INPUTS_LOC), 0x20) + calldatacopy(add(PUBLIC_INPUTS_HASH_LOCATION, 0x20), public_inputs_start, public_input_size) + + // copy W1, W2, W3 into challenge. Each point is 0x40 bytes, so load 0xc0 = 3 * 0x40 bytes (ETA input length) + let w_start := add(calldataload(0x04), 0x24) + calldatacopy(add(add(PUBLIC_INPUTS_HASH_LOCATION, 0x20), public_input_size), w_start, ETA_INPUT_LENGTH) + + // Challenge is the old challenge + public inputs + W1, W2, W3 (0x20 + public_input_size + 0xc0) + let challenge_bytes_size := add(0x20, add(public_input_size, ETA_INPUT_LENGTH)) + + challenge := keccak256(PUBLIC_INPUTS_HASH_LOCATION, challenge_bytes_size) + { + let eta := mod(challenge, p) + mstore(C_ETA_LOC, eta) + mstore(C_ETA_SQR_LOC, mulmod(eta, eta, p)) + mstore(C_ETA_CUBE_LOC, mulmod(mload(C_ETA_SQR_LOC), eta, p)) + } + + /** + * Generate beta challenge + */ + mstore(0x00, challenge) + mstore(0x20, mload(W4_Y_LOC)) + mstore(0x40, mload(W4_X_LOC)) + mstore(0x60, mload(S_Y_LOC)) + mstore(0x80, mload(S_X_LOC)) + challenge := keccak256(0x00, 0xa0) + mstore(C_BETA_LOC, mod(challenge, p)) + + /** + * Generate gamma challenge + */ + mstore(0x00, challenge) + mstore8(0x20, 0x01) + challenge := keccak256(0x00, 0x21) + mstore(C_GAMMA_LOC, mod(challenge, p)) + + /** + * Generate alpha challenge + */ + mstore(0x00, challenge) + mstore(0x20, mload(Z_Y_LOC)) + mstore(0x40, mload(Z_X_LOC)) + mstore(0x60, mload(Z_LOOKUP_Y_LOC)) + mstore(0x80, mload(Z_LOOKUP_X_LOC)) + challenge := keccak256(0x00, 0xa0) + mstore(C_ALPHA_LOC, mod(challenge, p)) + + /** + * Compute and store some powers of alpha for future computations + */ + let alpha := mload(C_ALPHA_LOC) + mstore(C_ALPHA_SQR_LOC, mulmod(alpha, alpha, p)) + mstore(C_ALPHA_CUBE_LOC, mulmod(mload(C_ALPHA_SQR_LOC), alpha, p)) + mstore(C_ALPHA_QUAD_LOC, mulmod(mload(C_ALPHA_CUBE_LOC), alpha, p)) + mstore(C_ALPHA_BASE_LOC, alpha) + + /** + * Generate zeta challenge + */ + mstore(0x00, challenge) + mstore(0x20, mload(T1_Y_LOC)) + mstore(0x40, mload(T1_X_LOC)) + mstore(0x60, mload(T2_Y_LOC)) + mstore(0x80, mload(T2_X_LOC)) + mstore(0xa0, mload(T3_Y_LOC)) + mstore(0xc0, mload(T3_X_LOC)) + mstore(0xe0, mload(T4_Y_LOC)) + mstore(0x100, mload(T4_X_LOC)) + + challenge := keccak256(0x00, 0x120) + + mstore(C_ZETA_LOC, mod(challenge, p)) + mstore(C_CURRENT_LOC, challenge) + } + + /** + * EVALUATE FIELD OPERATIONS + */ + + /** + * COMPUTE PUBLIC INPUT DELTA + * ΔPI = ∏ᵢ∈ℓ(wᵢ + β σ(i) + γ) / ∏ᵢ∈ℓ(wᵢ + β σ'(i) + γ) + */ + { + let beta := mload(C_BETA_LOC) // β + let gamma := mload(C_GAMMA_LOC) // γ + let work_root := mload(OMEGA_LOC) // ω + let numerator_value := 1 + let denominator_value := 1 + + let p_clone := p // move p to the front of the stack + let valid_inputs := true + + // Load the starting point of the public inputs (jump over the selector and the length of public inputs [0x24]) + let public_inputs_ptr := add(calldataload(0x24), 0x24) + + // endpoint_ptr = public_inputs_ptr + num_inputs * 0x20. // every public input is 0x20 bytes + let endpoint_ptr := add(public_inputs_ptr, mul(mload(NUM_INPUTS_LOC), 0x20)) + + // root_1 = β * 0x05 + let root_1 := mulmod(beta, 0x05, p_clone) // k1.β + // root_2 = β * 0x0c + let root_2 := mulmod(beta, 0x0c, p_clone) + // @note 0x05 + 0x07 == 0x0c == external coset generator + + for {} lt(public_inputs_ptr, endpoint_ptr) { public_inputs_ptr := add(public_inputs_ptr, 0x20) } { + /** + * input = public_input[i] + * valid_inputs &= input < p + * temp = input + gamma + * numerator_value *= (β.σ(i) + wᵢ + γ) // σ(i) = 0x05.ωⁱ + * denominator_value *= (β.σ'(i) + wᵢ + γ) // σ'(i) = 0x0c.ωⁱ + * root_1 *= ω + * root_2 *= ω + */ + + let input := calldataload(public_inputs_ptr) + valid_inputs := and(valid_inputs, lt(input, p_clone)) + let temp := addmod(input, gamma, p_clone) + + numerator_value := mulmod(numerator_value, add(root_1, temp), p_clone) + denominator_value := mulmod(denominator_value, add(root_2, temp), p_clone) + + root_1 := mulmod(root_1, work_root, p_clone) + root_2 := mulmod(root_2, work_root, p_clone) + } + + // Revert if not all public inputs are field elements (i.e. < p) + if iszero(valid_inputs) { + mstore(0x00, PUBLIC_INPUT_GE_P_SELECTOR) + revert(0x00, 0x04) + } + + mstore(DELTA_NUMERATOR_LOC, numerator_value) + mstore(DELTA_DENOMINATOR_LOC, denominator_value) + } + + /** + * Compute Plookup delta factor [γ(1 + β)]^{n-k} + * k = num roots cut out of Z_H = 4 + */ + { + let delta_base := mulmod(mload(C_GAMMA_LOC), addmod(mload(C_BETA_LOC), 1, p), p) + let delta_numerator := delta_base + { + let exponent := mload(N_LOC) + let count := 1 + for {} lt(count, exponent) { count := add(count, count) } { + delta_numerator := mulmod(delta_numerator, delta_numerator, p) + } + } + mstore(PLOOKUP_DELTA_NUMERATOR_LOC, delta_numerator) + + let delta_denominator := mulmod(delta_base, delta_base, p) + delta_denominator := mulmod(delta_denominator, delta_denominator, p) + mstore(PLOOKUP_DELTA_DENOMINATOR_LOC, delta_denominator) + } + /** + * Compute lagrange poly and vanishing poly fractions + */ + { + /** + * vanishing_numerator = zeta + * ZETA_POW_N = zeta^n + * vanishing_numerator -= 1 + * accumulating_root = omega_inverse + * work_root = p - accumulating_root + * domain_inverse = domain_inverse + * vanishing_denominator = zeta + work_root + * work_root *= accumulating_root + * vanishing_denominator *= (zeta + work_root) + * work_root *= accumulating_root + * vanishing_denominator *= (zeta + work_root) + * vanishing_denominator *= (zeta + (zeta + accumulating_root)) + * work_root = omega + * lagrange_numerator = vanishing_numerator * domain_inverse + * l_start_denominator = zeta - 1 + * accumulating_root = work_root^2 + * l_end_denominator = accumulating_root^2 * work_root * zeta - 1 + * Note: l_end_denominator term contains a term \omega^5 to cut out 5 roots of unity from vanishing poly + */ + + let zeta := mload(C_ZETA_LOC) + + // compute zeta^n, where n is a power of 2 + let vanishing_numerator := zeta + { + // pow_small + let exponent := mload(N_LOC) + let count := 1 + for {} lt(count, exponent) { count := add(count, count) } { + vanishing_numerator := mulmod(vanishing_numerator, vanishing_numerator, p) + } + } + mstore(ZETA_POW_N_LOC, vanishing_numerator) + vanishing_numerator := addmod(vanishing_numerator, sub(p, 1), p) + + let accumulating_root := mload(OMEGA_INVERSE_LOC) + let work_root := sub(p, accumulating_root) + let domain_inverse := mload(DOMAIN_INVERSE_LOC) + + let vanishing_denominator := addmod(zeta, work_root, p) + work_root := mulmod(work_root, accumulating_root, p) + vanishing_denominator := mulmod(vanishing_denominator, addmod(zeta, work_root, p), p) + work_root := mulmod(work_root, accumulating_root, p) + vanishing_denominator := mulmod(vanishing_denominator, addmod(zeta, work_root, p), p) + vanishing_denominator := + mulmod(vanishing_denominator, addmod(zeta, mulmod(work_root, accumulating_root, p), p), p) + + work_root := mload(OMEGA_LOC) + + let lagrange_numerator := mulmod(vanishing_numerator, domain_inverse, p) + let l_start_denominator := addmod(zeta, sub(p, 1), p) + + accumulating_root := mulmod(work_root, work_root, p) + + let l_end_denominator := + addmod( + mulmod(mulmod(mulmod(accumulating_root, accumulating_root, p), work_root, p), zeta, p), sub(p, 1), p + ) + + /** + * Compute inversions using Montgomery's batch inversion trick + */ + let accumulator := mload(DELTA_DENOMINATOR_LOC) + let t0 := accumulator + accumulator := mulmod(accumulator, vanishing_denominator, p) + let t1 := accumulator + accumulator := mulmod(accumulator, vanishing_numerator, p) + let t2 := accumulator + accumulator := mulmod(accumulator, l_start_denominator, p) + let t3 := accumulator + accumulator := mulmod(accumulator, mload(PLOOKUP_DELTA_DENOMINATOR_LOC), p) + let t4 := accumulator + { + mstore(0, 0x20) + mstore(0x20, 0x20) + mstore(0x40, 0x20) + mstore(0x60, mulmod(accumulator, l_end_denominator, p)) + mstore(0x80, sub(p, 2)) + mstore(0xa0, p) + if iszero(staticcall(gas(), 0x05, 0x00, 0xc0, 0x00, 0x20)) { + mstore(0x0, MOD_EXP_FAILURE_SELECTOR) + revert(0x00, 0x04) + } + accumulator := mload(0x00) + } + + t4 := mulmod(accumulator, t4, p) + accumulator := mulmod(accumulator, l_end_denominator, p) + + t3 := mulmod(accumulator, t3, p) + accumulator := mulmod(accumulator, mload(PLOOKUP_DELTA_DENOMINATOR_LOC), p) + + t2 := mulmod(accumulator, t2, p) + accumulator := mulmod(accumulator, l_start_denominator, p) + + t1 := mulmod(accumulator, t1, p) + accumulator := mulmod(accumulator, vanishing_numerator, p) + + t0 := mulmod(accumulator, t0, p) + accumulator := mulmod(accumulator, vanishing_denominator, p) + + accumulator := mulmod(mulmod(accumulator, accumulator, p), mload(DELTA_DENOMINATOR_LOC), p) + + mstore(PUBLIC_INPUT_DELTA_LOC, mulmod(mload(DELTA_NUMERATOR_LOC), accumulator, p)) + mstore(ZERO_POLY_LOC, mulmod(vanishing_numerator, t0, p)) + mstore(ZERO_POLY_INVERSE_LOC, mulmod(vanishing_denominator, t1, p)) + mstore(L_START_LOC, mulmod(lagrange_numerator, t2, p)) + mstore(PLOOKUP_DELTA_LOC, mulmod(mload(PLOOKUP_DELTA_NUMERATOR_LOC), t3, p)) + mstore(L_END_LOC, mulmod(lagrange_numerator, t4, p)) + } + + /** + * UltraPlonk Widget Ordering: + * + * 1. Permutation widget + * 2. Plookup widget + * 3. Arithmetic widget + * 4. Fixed base widget (?) + * 5. GenPermSort widget + * 6. Elliptic widget + * 7. Auxiliary widget + */ + + /** + * COMPUTE PERMUTATION WIDGET EVALUATION + */ + { + let alpha := mload(C_ALPHA_LOC) + let beta := mload(C_BETA_LOC) + let gamma := mload(C_GAMMA_LOC) + + /** + * t1 = (W1 + gamma + beta * ID1) * (W2 + gamma + beta * ID2) + * t2 = (W3 + gamma + beta * ID3) * (W4 + gamma + beta * ID4) + * result = alpha_base * z_eval * t1 * t2 + * t1 = (W1 + gamma + beta * sigma_1_eval) * (W2 + gamma + beta * sigma_2_eval) + * t2 = (W2 + gamma + beta * sigma_3_eval) * (W3 + gamma + beta * sigma_4_eval) + * result -= (alpha_base * z_omega_eval * t1 * t2) + */ + let t1 := + mulmod( + add(add(mload(W1_EVAL_LOC), gamma), mulmod(beta, mload(ID1_EVAL_LOC), p)), + add(add(mload(W2_EVAL_LOC), gamma), mulmod(beta, mload(ID2_EVAL_LOC), p)), + p + ) + let t2 := + mulmod( + add(add(mload(W3_EVAL_LOC), gamma), mulmod(beta, mload(ID3_EVAL_LOC), p)), + add(add(mload(W4_EVAL_LOC), gamma), mulmod(beta, mload(ID4_EVAL_LOC), p)), + p + ) + let result := mulmod(mload(C_ALPHA_BASE_LOC), mulmod(mload(Z_EVAL_LOC), mulmod(t1, t2, p), p), p) + t1 := + mulmod( + add(add(mload(W1_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA1_EVAL_LOC), p)), + add(add(mload(W2_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA2_EVAL_LOC), p)), + p + ) + t2 := + mulmod( + add(add(mload(W3_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA3_EVAL_LOC), p)), + add(add(mload(W4_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA4_EVAL_LOC), p)), + p + ) + result := + addmod( + result, + sub(p, mulmod(mload(C_ALPHA_BASE_LOC), mulmod(mload(Z_OMEGA_EVAL_LOC), mulmod(t1, t2, p), p), p)), + p + ) + + /** + * alpha_base *= alpha + * result += alpha_base . (L_{n-k}(ʓ) . (z(ʓ.ω) - ∆_{PI})) + * alpha_base *= alpha + * result += alpha_base . (L_1(ʓ)(Z(ʓ) - 1)) + * alpha_Base *= alpha + */ + mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p)) + result := + addmod( + result, + mulmod( + mload(C_ALPHA_BASE_LOC), + mulmod( + mload(L_END_LOC), + addmod(mload(Z_OMEGA_EVAL_LOC), sub(p, mload(PUBLIC_INPUT_DELTA_LOC)), p), + p + ), + p + ), + p + ) + mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p)) + mstore( + PERMUTATION_IDENTITY, + addmod( + result, + mulmod( + mload(C_ALPHA_BASE_LOC), + mulmod(mload(L_START_LOC), addmod(mload(Z_EVAL_LOC), sub(p, 1), p), p), + p + ), + p + ) + ) + mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p)) + } + + /** + * COMPUTE PLOOKUP WIDGET EVALUATION + */ + { + /** + * Goal: f = (w1(z) + q2.w1(zω)) + η(w2(z) + qm.w2(zω)) + η²(w3(z) + qc.w_3(zω)) + q3(z).η³ + * f = η.q3(z) + * f += (w3(z) + qc.w_3(zω)) + * f *= η + * f += (w2(z) + qm.w2(zω)) + * f *= η + * f += (w1(z) + q2.w1(zω)) + */ + let f := mulmod(mload(C_ETA_LOC), mload(Q3_EVAL_LOC), p) + f := + addmod(f, addmod(mload(W3_EVAL_LOC), mulmod(mload(QC_EVAL_LOC), mload(W3_OMEGA_EVAL_LOC), p), p), p) + f := mulmod(f, mload(C_ETA_LOC), p) + f := + addmod(f, addmod(mload(W2_EVAL_LOC), mulmod(mload(QM_EVAL_LOC), mload(W2_OMEGA_EVAL_LOC), p), p), p) + f := mulmod(f, mload(C_ETA_LOC), p) + f := + addmod(f, addmod(mload(W1_EVAL_LOC), mulmod(mload(Q2_EVAL_LOC), mload(W1_OMEGA_EVAL_LOC), p), p), p) + + // t(z) = table4(z).η³ + table3(z).η² + table2(z).η + table1(z) + let t := + addmod( + addmod( + addmod( + mulmod(mload(TABLE4_EVAL_LOC), mload(C_ETA_CUBE_LOC), p), + mulmod(mload(TABLE3_EVAL_LOC), mload(C_ETA_SQR_LOC), p), + p + ), + mulmod(mload(TABLE2_EVAL_LOC), mload(C_ETA_LOC), p), + p + ), + mload(TABLE1_EVAL_LOC), + p + ) + + // t(zw) = table4(zw).η³ + table3(zw).η² + table2(zw).η + table1(zw) + let t_omega := + addmod( + addmod( + addmod( + mulmod(mload(TABLE4_OMEGA_EVAL_LOC), mload(C_ETA_CUBE_LOC), p), + mulmod(mload(TABLE3_OMEGA_EVAL_LOC), mload(C_ETA_SQR_LOC), p), + p + ), + mulmod(mload(TABLE2_OMEGA_EVAL_LOC), mload(C_ETA_LOC), p), + p + ), + mload(TABLE1_OMEGA_EVAL_LOC), + p + ) + + /** + * Goal: numerator = (TABLE_TYPE_EVAL * f(z) + γ) * (t(z) + βt(zω) + γ(β + 1)) * (β + 1) + * gamma_beta_constant = γ(β + 1) + * numerator = f * TABLE_TYPE_EVAL + gamma + * temp0 = t(z) + t(zω) * β + gamma_beta_constant + * numerator *= temp0 + * numerator *= (β + 1) + * temp0 = alpha * l_1 + * numerator += temp0 + * numerator *= z_lookup(z) + * numerator -= temp0 + */ + let gamma_beta_constant := mulmod(mload(C_GAMMA_LOC), addmod(mload(C_BETA_LOC), 1, p), p) + let numerator := addmod(mulmod(f, mload(TABLE_TYPE_EVAL_LOC), p), mload(C_GAMMA_LOC), p) + let temp0 := addmod(addmod(t, mulmod(t_omega, mload(C_BETA_LOC), p), p), gamma_beta_constant, p) + numerator := mulmod(numerator, temp0, p) + numerator := mulmod(numerator, addmod(mload(C_BETA_LOC), 1, p), p) + temp0 := mulmod(mload(C_ALPHA_LOC), mload(L_START_LOC), p) + numerator := addmod(numerator, temp0, p) + numerator := mulmod(numerator, mload(Z_LOOKUP_EVAL_LOC), p) + numerator := addmod(numerator, sub(p, temp0), p) + + /** + * Goal: denominator = z_lookup(zω)*[s(z) + βs(zω) + γ(1 + β)] - [z_lookup(zω) - [γ(1 + β)]^{n-k}]*α²L_end(z) + * note: delta_factor = [γ(1 + β)]^{n-k} + * denominator = s(z) + βs(zω) + γ(β + 1) + * temp1 = α²L_end(z) + * denominator -= temp1 + * denominator *= z_lookup(zω) + * denominator += temp1 * delta_factor + * PLOOKUP_IDENTITY = (numerator - denominator).alpha_base + * alpha_base *= alpha^3 + */ + let denominator := + addmod( + addmod(mload(S_EVAL_LOC), mulmod(mload(S_OMEGA_EVAL_LOC), mload(C_BETA_LOC), p), p), + gamma_beta_constant, + p + ) + let temp1 := mulmod(mload(C_ALPHA_SQR_LOC), mload(L_END_LOC), p) + denominator := addmod(denominator, sub(p, temp1), p) + denominator := mulmod(denominator, mload(Z_LOOKUP_OMEGA_EVAL_LOC), p) + denominator := addmod(denominator, mulmod(temp1, mload(PLOOKUP_DELTA_LOC), p), p) + + mstore(PLOOKUP_IDENTITY, mulmod(addmod(numerator, sub(p, denominator), p), mload(C_ALPHA_BASE_LOC), p)) + + // update alpha + mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_CUBE_LOC), p)) + } + + /** + * COMPUTE ARITHMETIC WIDGET EVALUATION + */ + { + /** + * The basic arithmetic gate identity in standard plonk is as follows. + * (w_1 . w_2 . q_m) + (w_1 . q_1) + (w_2 . q_2) + (w_3 . q_3) + (w_4 . q_4) + q_c = 0 + * However, for Ultraplonk, we extend this to support "passing" wires between rows (shown without alpha scaling below): + * q_arith * ( ( (-1/2) * (q_arith - 3) * q_m * w_1 * w_2 + q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c ) + + * (q_arith - 1)*( α * (q_arith - 2) * (w_1 + w_4 - w_1_omega + q_m) + w_4_omega) ) = 0 + * + * This formula results in several cases depending on q_arith: + * 1. q_arith == 0: Arithmetic gate is completely disabled + * + * 2. q_arith == 1: Everything in the minigate on the right is disabled. The equation is just a standard plonk equation + * with extra wires: q_m * w_1 * w_2 + q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c = 0 + * + * 3. q_arith == 2: The (w_1 + w_4 - ...) term is disabled. THe equation is: + * (1/2) * q_m * w_1 * w_2 + q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c + w_4_omega = 0 + * It allows defining w_4 at next index (w_4_omega) in terms of current wire values + * + * 4. q_arith == 3: The product of w_1 and w_2 is disabled, but a mini addition gate is enabled. α allows us to split + * the equation into two: + * + * q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c + 2 * w_4_omega = 0 + * and + * w_1 + w_4 - w_1_omega + q_m = 0 (we are reusing q_m here) + * + * 5. q_arith > 3: The product of w_1 and w_2 is scaled by (q_arith - 3), while the w_4_omega term is scaled by (q_arith - 1). + * The equation can be split into two: + * + * (q_arith - 3)* q_m * w_1 * w_ 2 + q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c + (q_arith - 1) * w_4_omega = 0 + * and + * w_1 + w_4 - w_1_omega + q_m = 0 + * + * The problem that q_m is used both in both equations can be dealt with by appropriately changing selector values at + * the next gate. Then we can treat (q_arith - 1) as a simulated q_6 selector and scale q_m to handle (q_arith - 3) at + * product. + */ + + let w1q1 := mulmod(mload(W1_EVAL_LOC), mload(Q1_EVAL_LOC), p) + let w2q2 := mulmod(mload(W2_EVAL_LOC), mload(Q2_EVAL_LOC), p) + let w3q3 := mulmod(mload(W3_EVAL_LOC), mload(Q3_EVAL_LOC), p) + let w4q3 := mulmod(mload(W4_EVAL_LOC), mload(Q4_EVAL_LOC), p) + + // @todo - Add a explicit test that hits QARITH == 3 + // w1w2qm := (w_1 . w_2 . q_m . (QARITH_EVAL_LOC - 3)) / 2 + let w1w2qm := + mulmod( + mulmod( + mulmod(mulmod(mload(W1_EVAL_LOC), mload(W2_EVAL_LOC), p), mload(QM_EVAL_LOC), p), + addmod(mload(QARITH_EVAL_LOC), sub(p, 3), p), + p + ), + NEGATIVE_INVERSE_OF_2_MODULO_P, + p + ) + + // (w_1 . w_2 . q_m . (q_arith - 3)) / -2) + (w_1 . q_1) + (w_2 . q_2) + (w_3 . q_3) + (w_4 . q_4) + q_c + let identity := + addmod( + mload(QC_EVAL_LOC), addmod(w4q3, addmod(w3q3, addmod(w2q2, addmod(w1q1, w1w2qm, p), p), p), p), p + ) + + // if q_arith == 3 we evaluate an additional mini addition gate (on top of the regular one), where: + // w_1 + w_4 - w_1_omega + q_m = 0 + // we use this gate to save an addition gate when adding or subtracting non-native field elements + // α * (q_arith - 2) * (w_1 + w_4 - w_1_omega + q_m) + let extra_small_addition_gate_identity := + mulmod( + mload(C_ALPHA_LOC), + mulmod( + addmod(mload(QARITH_EVAL_LOC), sub(p, 2), p), + addmod( + mload(QM_EVAL_LOC), + addmod( + sub(p, mload(W1_OMEGA_EVAL_LOC)), addmod(mload(W1_EVAL_LOC), mload(W4_EVAL_LOC), p), p + ), + p + ), + p + ), + p + ) + + // if q_arith == 2 OR q_arith == 3 we add the 4th wire of the NEXT gate into the arithmetic identity + // N.B. if q_arith > 2, this wire value will be scaled by (q_arith - 1) relative to the other gate wires! + // alpha_base * q_arith * (identity + (q_arith - 1) * (w_4_omega + extra_small_addition_gate_identity)) + mstore( + ARITHMETIC_IDENTITY, + mulmod( + mload(C_ALPHA_BASE_LOC), + mulmod( + mload(QARITH_EVAL_LOC), + addmod( + identity, + mulmod( + addmod(mload(QARITH_EVAL_LOC), sub(p, 1), p), + addmod(mload(W4_OMEGA_EVAL_LOC), extra_small_addition_gate_identity, p), + p + ), + p + ), + p + ), + p + ) + ) + + // update alpha + mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_SQR_LOC), p)) + } + + /** + * COMPUTE GENPERMSORT WIDGET EVALUATION + */ + { + /** + * D1 = (w2 - w1) + * D2 = (w3 - w2) + * D3 = (w4 - w3) + * D4 = (w1_omega - w4) + * + * α_a = alpha_base + * α_b = alpha_base * α + * α_c = alpha_base * α^2 + * α_d = alpha_base * α^3 + * + * range_accumulator = ( + * D1(D1 - 1)(D1 - 2)(D1 - 3).α_a + + * D2(D2 - 1)(D2 - 2)(D2 - 3).α_b + + * D3(D3 - 1)(D3 - 2)(D3 - 3).α_c + + * D4(D4 - 1)(D4 - 2)(D4 - 3).α_d + + * ) . q_sort + */ + let minus_two := sub(p, 2) + let minus_three := sub(p, 3) + let d1 := addmod(mload(W2_EVAL_LOC), sub(p, mload(W1_EVAL_LOC)), p) + let d2 := addmod(mload(W3_EVAL_LOC), sub(p, mload(W2_EVAL_LOC)), p) + let d3 := addmod(mload(W4_EVAL_LOC), sub(p, mload(W3_EVAL_LOC)), p) + let d4 := addmod(mload(W1_OMEGA_EVAL_LOC), sub(p, mload(W4_EVAL_LOC)), p) + + let range_accumulator := + mulmod( + mulmod( + mulmod(addmod(mulmod(d1, d1, p), sub(p, d1), p), addmod(d1, minus_two, p), p), + addmod(d1, minus_three, p), + p + ), + mload(C_ALPHA_BASE_LOC), + p + ) + range_accumulator := + addmod( + range_accumulator, + mulmod( + mulmod( + mulmod(addmod(mulmod(d2, d2, p), sub(p, d2), p), addmod(d2, minus_two, p), p), + addmod(d2, minus_three, p), + p + ), + mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p), + p + ), + p + ) + range_accumulator := + addmod( + range_accumulator, + mulmod( + mulmod( + mulmod(addmod(mulmod(d3, d3, p), sub(p, d3), p), addmod(d3, minus_two, p), p), + addmod(d3, minus_three, p), + p + ), + mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_SQR_LOC), p), + p + ), + p + ) + range_accumulator := + addmod( + range_accumulator, + mulmod( + mulmod( + mulmod(addmod(mulmod(d4, d4, p), sub(p, d4), p), addmod(d4, minus_two, p), p), + addmod(d4, minus_three, p), + p + ), + mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_CUBE_LOC), p), + p + ), + p + ) + range_accumulator := mulmod(range_accumulator, mload(QSORT_EVAL_LOC), p) + + mstore(SORT_IDENTITY, range_accumulator) + + // update alpha + mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_QUAD_LOC), p)) + } + + /** + * COMPUTE ELLIPTIC WIDGET EVALUATION + */ + { + /** + * endo_term = (-x_2) * x_1 * (x_3 * 2 + x_1) * q_beta + * endo_sqr_term = x_2^2 + * endo_sqr_term *= (x_3 - x_1) + * endo_sqr_term *= q_beta^2 + * leftovers = x_2^2 + * leftovers *= x_2 + * leftovers += x_1^2 * (x_3 + x_1) @follow-up Invalid comment in BB widget + * leftovers -= (y_2^2 + y_1^2) + * sign_term = y_2 * y_1 + * sign_term += sign_term + * sign_term *= q_sign + */ + // q_elliptic * (x3 + x2 + x1)(x2 - x1)(x2 - x1) - y2^2 - y1^2 + 2(y2y1)*q_sign = 0 + let x_diff := addmod(mload(X2_EVAL_LOC), sub(p, mload(X1_EVAL_LOC)), p) + let y2_sqr := mulmod(mload(Y2_EVAL_LOC), mload(Y2_EVAL_LOC), p) + let y1_sqr := mulmod(mload(Y1_EVAL_LOC), mload(Y1_EVAL_LOC), p) + let y1y2 := mulmod(mulmod(mload(Y1_EVAL_LOC), mload(Y2_EVAL_LOC), p), mload(QSIGN_LOC), p) + + let x_add_identity := + addmod( + mulmod( + addmod(mload(X3_EVAL_LOC), addmod(mload(X2_EVAL_LOC), mload(X1_EVAL_LOC), p), p), + mulmod(x_diff, x_diff, p), + p + ), + addmod( + sub( + p, + addmod(y2_sqr, y1_sqr, p) + ), + addmod(y1y2, y1y2, p), + p + ), + p + ) + x_add_identity := + mulmod( + mulmod( + x_add_identity, + addmod( + 1, + sub(p, mload(QM_EVAL_LOC)), + p + ), + p + ), + mload(C_ALPHA_BASE_LOC), + p + ) + + // q_elliptic * (x3 + x2 + x1)(x2 - x1)(x2 - x1) - y2^2 - y1^2 + 2(y2y1)*q_sign = 0 + let y1_plus_y3 := addmod( + mload(Y1_EVAL_LOC), + mload(Y3_EVAL_LOC), + p + ) + let y_diff := addmod(mulmod(mload(Y2_EVAL_LOC), mload(QSIGN_LOC), p), sub(p, mload(Y1_EVAL_LOC)), p) + let y_add_identity := + addmod( + mulmod(y1_plus_y3, x_diff, p), + mulmod(addmod(mload(X3_EVAL_LOC), sub(p, mload(X1_EVAL_LOC)), p), y_diff, p), + p + ) + y_add_identity := + mulmod( + mulmod(y_add_identity, addmod(1, sub(p, mload(QM_EVAL_LOC)), p), p), + mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p), + p + ) + + // ELLIPTIC_IDENTITY = (x_identity + y_identity) * Q_ELLIPTIC_EVAL + mstore( + ELLIPTIC_IDENTITY, mulmod(addmod(x_add_identity, y_add_identity, p), mload(QELLIPTIC_EVAL_LOC), p) + ) + } + { + /** + * x_pow_4 = (y_1_sqr - curve_b) * x_1; + * y_1_sqr_mul_4 = y_1_sqr + y_1_sqr; + * y_1_sqr_mul_4 += y_1_sqr_mul_4; + * x_1_pow_4_mul_9 = x_pow_4; + * x_1_pow_4_mul_9 += x_1_pow_4_mul_9; + * x_1_pow_4_mul_9 += x_1_pow_4_mul_9; + * x_1_pow_4_mul_9 += x_1_pow_4_mul_9; + * x_1_pow_4_mul_9 += x_pow_4; + * x_1_sqr_mul_3 = x_1_sqr + x_1_sqr + x_1_sqr; + * x_double_identity = (x_3 + x_1 + x_1) * y_1_sqr_mul_4 - x_1_pow_4_mul_9; + * y_double_identity = x_1_sqr_mul_3 * (x_1 - x_3) - (y_1 + y_1) * (y_1 + y_3); + */ + // (x3 + x1 + x1) (4y1*y1) - 9 * x1 * x1 * x1 * x1 = 0 + let x1_sqr := mulmod(mload(X1_EVAL_LOC), mload(X1_EVAL_LOC), p) + let y1_sqr := mulmod(mload(Y1_EVAL_LOC), mload(Y1_EVAL_LOC), p) + let x_pow_4 := mulmod(addmod(y1_sqr, GRUMPKIN_CURVE_B_PARAMETER_NEGATED, p), mload(X1_EVAL_LOC), p) + let y1_sqr_mul_4 := mulmod(y1_sqr, 4, p) + let x1_pow_4_mul_9 := mulmod(x_pow_4, 9, p) + let x1_sqr_mul_3 := mulmod(x1_sqr, 3, p) + let x_double_identity := + addmod( + mulmod( + addmod(mload(X3_EVAL_LOC), addmod(mload(X1_EVAL_LOC), mload(X1_EVAL_LOC), p), p), + y1_sqr_mul_4, + p + ), + sub(p, x1_pow_4_mul_9), + p + ) + // (y1 + y1) (2y1) - (3 * x1 * x1)(x1 - x3) = 0 + let y_double_identity := + addmod( + mulmod(x1_sqr_mul_3, addmod(mload(X1_EVAL_LOC), sub(p, mload(X3_EVAL_LOC)), p), p), + sub( + p, + mulmod( + addmod(mload(Y1_EVAL_LOC), mload(Y1_EVAL_LOC), p), + addmod(mload(Y1_EVAL_LOC), mload(Y3_EVAL_LOC), p), + p + ) + ), + p + ) + x_double_identity := mulmod(x_double_identity, mload(C_ALPHA_BASE_LOC), p) + y_double_identity := + mulmod(y_double_identity, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p), p) + x_double_identity := mulmod(x_double_identity, mload(QM_EVAL_LOC), p) + y_double_identity := mulmod(y_double_identity, mload(QM_EVAL_LOC), p) + // ELLIPTIC_IDENTITY += (x_double_identity + y_double_identity) * Q_DOUBLE_EVAL + mstore( + ELLIPTIC_IDENTITY, + addmod( + mload(ELLIPTIC_IDENTITY), + mulmod(addmod(x_double_identity, y_double_identity, p), mload(QELLIPTIC_EVAL_LOC), p), + p + ) + ) + + // update alpha + mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_QUAD_LOC), p)) + } + + /** + * COMPUTE AUXILIARY WIDGET EVALUATION + */ + { + { + /** + * Non native field arithmetic gate 2 + * _ _ + * / _ _ _ 14 \ + * q_2 . q_4 | (w_1 . w_2) + (w_1 . w_2) + (w_1 . w_4 + w_2 . w_3 - w_3) . 2 - w_3 - w_4 | + * \_ _/ + * + * limb_subproduct = w_1 . w_2_omega + w_1_omega . w_2 + * non_native_field_gate_2 = w_1 * w_4 + w_4 * w_3 - w_3_omega + * non_native_field_gate_2 = non_native_field_gate_2 * limb_size + * non_native_field_gate_2 -= w_4_omega + * non_native_field_gate_2 += limb_subproduct + * non_native_field_gate_2 *= q_4 + * limb_subproduct *= limb_size + * limb_subproduct += w_1_omega * w_2_omega + * non_native_field_gate_1 = (limb_subproduct + w_3 + w_4) * q_3 + * non_native_field_gate_3 = (limb_subproduct + w_4 - (w_3_omega + w_4_omega)) * q_m + * non_native_field_identity = (non_native_field_gate_1 + non_native_field_gate_2 + non_native_field_gate_3) * q_2 + */ + + let limb_subproduct := + addmod( + mulmod(mload(W1_EVAL_LOC), mload(W2_OMEGA_EVAL_LOC), p), + mulmod(mload(W1_OMEGA_EVAL_LOC), mload(W2_EVAL_LOC), p), + p + ) + + let non_native_field_gate_2 := + addmod( + addmod( + mulmod(mload(W1_EVAL_LOC), mload(W4_EVAL_LOC), p), + mulmod(mload(W2_EVAL_LOC), mload(W3_EVAL_LOC), p), + p + ), + sub(p, mload(W3_OMEGA_EVAL_LOC)), + p + ) + non_native_field_gate_2 := mulmod(non_native_field_gate_2, LIMB_SIZE, p) + non_native_field_gate_2 := addmod(non_native_field_gate_2, sub(p, mload(W4_OMEGA_EVAL_LOC)), p) + non_native_field_gate_2 := addmod(non_native_field_gate_2, limb_subproduct, p) + non_native_field_gate_2 := mulmod(non_native_field_gate_2, mload(Q4_EVAL_LOC), p) + limb_subproduct := mulmod(limb_subproduct, LIMB_SIZE, p) + limb_subproduct := + addmod(limb_subproduct, mulmod(mload(W1_OMEGA_EVAL_LOC), mload(W2_OMEGA_EVAL_LOC), p), p) + let non_native_field_gate_1 := + mulmod( + addmod(limb_subproduct, sub(p, addmod(mload(W3_EVAL_LOC), mload(W4_EVAL_LOC), p)), p), + mload(Q3_EVAL_LOC), + p + ) + let non_native_field_gate_3 := + mulmod( + addmod( + addmod(limb_subproduct, mload(W4_EVAL_LOC), p), + sub(p, addmod(mload(W3_OMEGA_EVAL_LOC), mload(W4_OMEGA_EVAL_LOC), p)), + p + ), + mload(QM_EVAL_LOC), + p + ) + let non_native_field_identity := + mulmod( + addmod(addmod(non_native_field_gate_1, non_native_field_gate_2, p), non_native_field_gate_3, p), + mload(Q2_EVAL_LOC), + p + ) + + mstore(AUX_NON_NATIVE_FIELD_EVALUATION, non_native_field_identity) + } + + { + /** + * limb_accumulator_1 = w_2_omega; + * limb_accumulator_1 *= SUBLIMB_SHIFT; + * limb_accumulator_1 += w_1_omega; + * limb_accumulator_1 *= SUBLIMB_SHIFT; + * limb_accumulator_1 += w_3; + * limb_accumulator_1 *= SUBLIMB_SHIFT; + * limb_accumulator_1 += w_2; + * limb_accumulator_1 *= SUBLIMB_SHIFT; + * limb_accumulator_1 += w_1; + * limb_accumulator_1 -= w_4; + * limb_accumulator_1 *= q_4; + */ + let limb_accumulator_1 := mulmod(mload(W2_OMEGA_EVAL_LOC), SUBLIMB_SHIFT, p) + limb_accumulator_1 := addmod(limb_accumulator_1, mload(W1_OMEGA_EVAL_LOC), p) + limb_accumulator_1 := mulmod(limb_accumulator_1, SUBLIMB_SHIFT, p) + limb_accumulator_1 := addmod(limb_accumulator_1, mload(W3_EVAL_LOC), p) + limb_accumulator_1 := mulmod(limb_accumulator_1, SUBLIMB_SHIFT, p) + limb_accumulator_1 := addmod(limb_accumulator_1, mload(W2_EVAL_LOC), p) + limb_accumulator_1 := mulmod(limb_accumulator_1, SUBLIMB_SHIFT, p) + limb_accumulator_1 := addmod(limb_accumulator_1, mload(W1_EVAL_LOC), p) + limb_accumulator_1 := addmod(limb_accumulator_1, sub(p, mload(W4_EVAL_LOC)), p) + limb_accumulator_1 := mulmod(limb_accumulator_1, mload(Q4_EVAL_LOC), p) + + /** + * limb_accumulator_2 = w_3_omega; + * limb_accumulator_2 *= SUBLIMB_SHIFT; + * limb_accumulator_2 += w_2_omega; + * limb_accumulator_2 *= SUBLIMB_SHIFT; + * limb_accumulator_2 += w_1_omega; + * limb_accumulator_2 *= SUBLIMB_SHIFT; + * limb_accumulator_2 += w_4; + * limb_accumulator_2 *= SUBLIMB_SHIFT; + * limb_accumulator_2 += w_3; + * limb_accumulator_2 -= w_4_omega; + * limb_accumulator_2 *= q_m; + */ + let limb_accumulator_2 := mulmod(mload(W3_OMEGA_EVAL_LOC), SUBLIMB_SHIFT, p) + limb_accumulator_2 := addmod(limb_accumulator_2, mload(W2_OMEGA_EVAL_LOC), p) + limb_accumulator_2 := mulmod(limb_accumulator_2, SUBLIMB_SHIFT, p) + limb_accumulator_2 := addmod(limb_accumulator_2, mload(W1_OMEGA_EVAL_LOC), p) + limb_accumulator_2 := mulmod(limb_accumulator_2, SUBLIMB_SHIFT, p) + limb_accumulator_2 := addmod(limb_accumulator_2, mload(W4_EVAL_LOC), p) + limb_accumulator_2 := mulmod(limb_accumulator_2, SUBLIMB_SHIFT, p) + limb_accumulator_2 := addmod(limb_accumulator_2, mload(W3_EVAL_LOC), p) + limb_accumulator_2 := addmod(limb_accumulator_2, sub(p, mload(W4_OMEGA_EVAL_LOC)), p) + limb_accumulator_2 := mulmod(limb_accumulator_2, mload(QM_EVAL_LOC), p) + + mstore( + AUX_LIMB_ACCUMULATOR_EVALUATION, + mulmod(addmod(limb_accumulator_1, limb_accumulator_2, p), mload(Q3_EVAL_LOC), p) + ) + } + + { + /** + * memory_record_check = w_3; + * memory_record_check *= eta; + * memory_record_check += w_2; + * memory_record_check *= eta; + * memory_record_check += w_1; + * memory_record_check *= eta; + * memory_record_check += q_c; + * + * partial_record_check = memory_record_check; + * + * memory_record_check -= w_4; + */ + + let memory_record_check := mulmod(mload(W3_EVAL_LOC), mload(C_ETA_LOC), p) + memory_record_check := addmod(memory_record_check, mload(W2_EVAL_LOC), p) + memory_record_check := mulmod(memory_record_check, mload(C_ETA_LOC), p) + memory_record_check := addmod(memory_record_check, mload(W1_EVAL_LOC), p) + memory_record_check := mulmod(memory_record_check, mload(C_ETA_LOC), p) + memory_record_check := addmod(memory_record_check, mload(QC_EVAL_LOC), p) + + let partial_record_check := memory_record_check + memory_record_check := addmod(memory_record_check, sub(p, mload(W4_EVAL_LOC)), p) + + mstore(AUX_MEMORY_EVALUATION, memory_record_check) + + // index_delta = w_1_omega - w_1 + let index_delta := addmod(mload(W1_OMEGA_EVAL_LOC), sub(p, mload(W1_EVAL_LOC)), p) + // record_delta = w_4_omega - w_4 + let record_delta := addmod(mload(W4_OMEGA_EVAL_LOC), sub(p, mload(W4_EVAL_LOC)), p) + // index_is_monotonically_increasing = index_delta * (index_delta - 1) + let index_is_monotonically_increasing := mulmod(index_delta, addmod(index_delta, sub(p, 1), p), p) + + // adjacent_values_match_if_adjacent_indices_match = record_delta * (1 - index_delta) + let adjacent_values_match_if_adjacent_indices_match := + mulmod(record_delta, addmod(1, sub(p, index_delta), p), p) + + // AUX_ROM_CONSISTENCY_EVALUATION = ((adjacent_values_match_if_adjacent_indices_match * alpha) + index_is_monotonically_increasing) * alpha + partial_record_check + mstore( + AUX_ROM_CONSISTENCY_EVALUATION, + addmod( + mulmod( + addmod( + mulmod(adjacent_values_match_if_adjacent_indices_match, mload(C_ALPHA_LOC), p), + index_is_monotonically_increasing, + p + ), + mload(C_ALPHA_LOC), + p + ), + memory_record_check, + p + ) + ) + + { + /** + * next_gate_access_type = w_3_omega; + * next_gate_access_type *= eta; + * next_gate_access_type += w_2_omega; + * next_gate_access_type *= eta; + * next_gate_access_type += w_1_omega; + * next_gate_access_type *= eta; + * next_gate_access_type = w_4_omega - next_gate_access_type; + */ + let next_gate_access_type := mulmod(mload(W3_OMEGA_EVAL_LOC), mload(C_ETA_LOC), p) + next_gate_access_type := addmod(next_gate_access_type, mload(W2_OMEGA_EVAL_LOC), p) + next_gate_access_type := mulmod(next_gate_access_type, mload(C_ETA_LOC), p) + next_gate_access_type := addmod(next_gate_access_type, mload(W1_OMEGA_EVAL_LOC), p) + next_gate_access_type := mulmod(next_gate_access_type, mload(C_ETA_LOC), p) + next_gate_access_type := addmod(mload(W4_OMEGA_EVAL_LOC), sub(p, next_gate_access_type), p) + + // value_delta = w_3_omega - w_3 + let value_delta := addmod(mload(W3_OMEGA_EVAL_LOC), sub(p, mload(W3_EVAL_LOC)), p) + // adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation = (1 - index_delta) * value_delta * (1 - next_gate_access_type); + + let adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation := + mulmod( + addmod(1, sub(p, index_delta), p), + mulmod(value_delta, addmod(1, sub(p, next_gate_access_type), p), p), + p + ) + + // AUX_RAM_CONSISTENCY_EVALUATION + + /** + * access_type = w_4 - partial_record_check + * access_check = access_type^2 - access_type + * next_gate_access_type_is_boolean = next_gate_access_type^2 - next_gate_access_type + * RAM_consistency_check_identity = adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation; + * RAM_consistency_check_identity *= alpha; + * RAM_consistency_check_identity += index_is_monotonically_increasing; + * RAM_consistency_check_identity *= alpha; + * RAM_consistency_check_identity += next_gate_access_type_is_boolean; + * RAM_consistency_check_identity *= alpha; + * RAM_consistency_check_identity += access_check; + */ + + let access_type := addmod(mload(W4_EVAL_LOC), sub(p, partial_record_check), p) + let access_check := mulmod(access_type, addmod(access_type, sub(p, 1), p), p) + let next_gate_access_type_is_boolean := + mulmod(next_gate_access_type, addmod(next_gate_access_type, sub(p, 1), p), p) + let RAM_cci := + mulmod( + adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation, + mload(C_ALPHA_LOC), + p + ) + RAM_cci := addmod(RAM_cci, index_is_monotonically_increasing, p) + RAM_cci := mulmod(RAM_cci, mload(C_ALPHA_LOC), p) + RAM_cci := addmod(RAM_cci, next_gate_access_type_is_boolean, p) + RAM_cci := mulmod(RAM_cci, mload(C_ALPHA_LOC), p) + RAM_cci := addmod(RAM_cci, access_check, p) + + mstore(AUX_RAM_CONSISTENCY_EVALUATION, RAM_cci) + } + + { + // timestamp_delta = w_2_omega - w_2 + let timestamp_delta := addmod(mload(W2_OMEGA_EVAL_LOC), sub(p, mload(W2_EVAL_LOC)), p) + + // RAM_timestamp_check_identity = (1 - index_delta) * timestamp_delta - w_3 + let RAM_timestamp_check_identity := + addmod( + mulmod(timestamp_delta, addmod(1, sub(p, index_delta), p), p), sub(p, mload(W3_EVAL_LOC)), p + ) + + /** + * memory_identity = ROM_consistency_check_identity * q_2; + * memory_identity += RAM_timestamp_check_identity * q_4; + * memory_identity += memory_record_check * q_m; + * memory_identity *= q_1; + * memory_identity += (RAM_consistency_check_identity * q_arith); + * + * auxiliary_identity = memory_identity + non_native_field_identity + limb_accumulator_identity; + * auxiliary_identity *= q_aux; + * auxiliary_identity *= alpha_base; + */ + let memory_identity := mulmod(mload(AUX_ROM_CONSISTENCY_EVALUATION), mload(Q2_EVAL_LOC), p) + memory_identity := + addmod(memory_identity, mulmod(RAM_timestamp_check_identity, mload(Q4_EVAL_LOC), p), p) + memory_identity := + addmod(memory_identity, mulmod(mload(AUX_MEMORY_EVALUATION), mload(QM_EVAL_LOC), p), p) + memory_identity := mulmod(memory_identity, mload(Q1_EVAL_LOC), p) + memory_identity := + addmod( + memory_identity, mulmod(mload(AUX_RAM_CONSISTENCY_EVALUATION), mload(QARITH_EVAL_LOC), p), p + ) + + let auxiliary_identity := addmod(memory_identity, mload(AUX_NON_NATIVE_FIELD_EVALUATION), p) + auxiliary_identity := addmod(auxiliary_identity, mload(AUX_LIMB_ACCUMULATOR_EVALUATION), p) + auxiliary_identity := mulmod(auxiliary_identity, mload(QAUX_EVAL_LOC), p) + auxiliary_identity := mulmod(auxiliary_identity, mload(C_ALPHA_BASE_LOC), p) + + mstore(AUX_IDENTITY, auxiliary_identity) + + // update alpha + mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_CUBE_LOC), p)) + } + } + } + + { + /** + * quotient = ARITHMETIC_IDENTITY + * quotient += PERMUTATION_IDENTITY + * quotient += PLOOKUP_IDENTITY + * quotient += SORT_IDENTITY + * quotient += ELLIPTIC_IDENTITY + * quotient += AUX_IDENTITY + * quotient *= ZERO_POLY_INVERSE + */ + mstore( + QUOTIENT_EVAL_LOC, + mulmod( + addmod( + addmod( + addmod( + addmod( + addmod(mload(PERMUTATION_IDENTITY), mload(PLOOKUP_IDENTITY), p), + mload(ARITHMETIC_IDENTITY), + p + ), + mload(SORT_IDENTITY), + p + ), + mload(ELLIPTIC_IDENTITY), + p + ), + mload(AUX_IDENTITY), + p + ), + mload(ZERO_POLY_INVERSE_LOC), + p + ) + ) + } + + /** + * GENERATE NU AND SEPARATOR CHALLENGES + */ + { + let current_challenge := mload(C_CURRENT_LOC) + // get a calldata pointer that points to the start of the data we want to copy + let calldata_ptr := add(calldataload(0x04), 0x24) + + calldata_ptr := add(calldata_ptr, NU_CALLDATA_SKIP_LENGTH) + + mstore(NU_CHALLENGE_INPUT_LOC_A, current_challenge) + mstore(NU_CHALLENGE_INPUT_LOC_B, mload(QUOTIENT_EVAL_LOC)) + calldatacopy(NU_CHALLENGE_INPUT_LOC_C, calldata_ptr, NU_INPUT_LENGTH) + + // hash length = (0x20 + num field elements), we include the previous challenge in the hash + let challenge := keccak256(NU_CHALLENGE_INPUT_LOC_A, add(NU_INPUT_LENGTH, 0x40)) + + mstore(C_V0_LOC, mod(challenge, p)) + // We need THIRTY-ONE independent nu challenges! + mstore(0x00, challenge) + mstore8(0x20, 0x01) + mstore(C_V1_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x02) + mstore(C_V2_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x03) + mstore(C_V3_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x04) + mstore(C_V4_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x05) + mstore(C_V5_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x06) + mstore(C_V6_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x07) + mstore(C_V7_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x08) + mstore(C_V8_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x09) + mstore(C_V9_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x0a) + mstore(C_V10_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x0b) + mstore(C_V11_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x0c) + mstore(C_V12_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x0d) + mstore(C_V13_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x0e) + mstore(C_V14_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x0f) + mstore(C_V15_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x10) + mstore(C_V16_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x11) + mstore(C_V17_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x12) + mstore(C_V18_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x13) + mstore(C_V19_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x14) + mstore(C_V20_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x15) + mstore(C_V21_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x16) + mstore(C_V22_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x17) + mstore(C_V23_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x18) + mstore(C_V24_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x19) + mstore(C_V25_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x1a) + mstore(C_V26_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x1b) + mstore(C_V27_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x1c) + mstore(C_V28_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x1d) + mstore(C_V29_LOC, mod(keccak256(0x00, 0x21), p)) + + // @follow-up - Why are both v29 and v30 using appending 0x1d to the prior challenge and hashing, should it not change? + mstore8(0x20, 0x1d) + challenge := keccak256(0x00, 0x21) + mstore(C_V30_LOC, mod(challenge, p)) + + // separator + mstore(0x00, challenge) + mstore(0x20, mload(PI_Z_Y_LOC)) + mstore(0x40, mload(PI_Z_X_LOC)) + mstore(0x60, mload(PI_Z_OMEGA_Y_LOC)) + mstore(0x80, mload(PI_Z_OMEGA_X_LOC)) + + mstore(C_U_LOC, mod(keccak256(0x00, 0xa0), p)) + } + + let success := 0 + // VALIDATE T1 + { + let x := mload(T1_X_LOC) + let y := mload(T1_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(ACCUMULATOR_X_LOC, x) + mstore(add(ACCUMULATOR_X_LOC, 0x20), y) + } + // VALIDATE T2 + { + let x := mload(T2_X_LOC) // 0x1400 + let y := mload(T2_Y_LOC) // 0x1420 + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(ZETA_POW_N_LOC)) + // accumulator_2 = [T2].zeta^n + success := staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40) + // accumulator = [T1] + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE T3 + { + let x := mload(T3_X_LOC) + let y := mload(T3_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(mload(ZETA_POW_N_LOC), mload(ZETA_POW_N_LOC), p)) + // accumulator_2 = [T3].zeta^{2n} + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE T4 + { + let x := mload(T4_X_LOC) + let y := mload(T4_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(mulmod(mload(ZETA_POW_N_LOC), mload(ZETA_POW_N_LOC), p), mload(ZETA_POW_N_LOC), p)) + // accumulator_2 = [T4].zeta^{3n} + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE W1 + { + let x := mload(W1_X_LOC) + let y := mload(W1_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V0_LOC), p)) + // accumulator_2 = v0.(u + 1).[W1] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE W2 + { + let x := mload(W2_X_LOC) + let y := mload(W2_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V1_LOC), p)) + // accumulator_2 = v1.(u + 1).[W2] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE W3 + { + let x := mload(W3_X_LOC) + let y := mload(W3_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V2_LOC), p)) + // accumulator_2 = v2.(u + 1).[W3] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE W4 + { + let x := mload(W4_X_LOC) + let y := mload(W4_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V3_LOC), p)) + // accumulator_2 = v3.(u + 1).[W4] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE S + { + let x := mload(S_X_LOC) + let y := mload(S_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V4_LOC), p)) + // accumulator_2 = v4.(u + 1).[S] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE Z + { + let x := mload(Z_X_LOC) + let y := mload(Z_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V5_LOC), p)) + // accumulator_2 = v5.(u + 1).[Z] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE Z_LOOKUP + { + let x := mload(Z_LOOKUP_X_LOC) + let y := mload(Z_LOOKUP_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V6_LOC), p)) + // accumulator_2 = v6.(u + 1).[Z_LOOKUP] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE Q1 + { + let x := mload(Q1_X_LOC) + let y := mload(Q1_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V7_LOC)) + // accumulator_2 = v7.[Q1] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE Q2 + { + let x := mload(Q2_X_LOC) + let y := mload(Q2_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V8_LOC)) + // accumulator_2 = v8.[Q2] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE Q3 + { + let x := mload(Q3_X_LOC) + let y := mload(Q3_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V9_LOC)) + // accumulator_2 = v9.[Q3] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE Q4 + { + let x := mload(Q4_X_LOC) + let y := mload(Q4_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V10_LOC)) + // accumulator_2 = v10.[Q4] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE QM + { + let x := mload(QM_X_LOC) + let y := mload(QM_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V11_LOC)) + // accumulator_2 = v11.[Q;] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE QC + { + let x := mload(QC_X_LOC) + let y := mload(QC_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V12_LOC)) + // accumulator_2 = v12.[QC] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE QARITH + { + let x := mload(QARITH_X_LOC) + let y := mload(QARITH_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V13_LOC)) + // accumulator_2 = v13.[QARITH] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE QSORT + { + let x := mload(QSORT_X_LOC) + let y := mload(QSORT_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V14_LOC)) + // accumulator_2 = v14.[QSORT] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE QELLIPTIC + { + let x := mload(QELLIPTIC_X_LOC) + let y := mload(QELLIPTIC_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V15_LOC)) + // accumulator_2 = v15.[QELLIPTIC] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE QAUX + { + let x := mload(QAUX_X_LOC) + let y := mload(QAUX_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V16_LOC)) + // accumulator_2 = v15.[Q_AUX] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE SIGMA1 + { + let x := mload(SIGMA1_X_LOC) + let y := mload(SIGMA1_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V17_LOC)) + // accumulator_2 = v17.[sigma1] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE SIGMA2 + { + let x := mload(SIGMA2_X_LOC) + let y := mload(SIGMA2_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V18_LOC)) + // accumulator_2 = v18.[sigma2] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE SIGMA3 + { + let x := mload(SIGMA3_X_LOC) + let y := mload(SIGMA3_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V19_LOC)) + // accumulator_2 = v19.[sigma3] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE SIGMA4 + { + let x := mload(SIGMA4_X_LOC) + let y := mload(SIGMA4_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V20_LOC)) + // accumulator_2 = v20.[sigma4] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE TABLE1 + { + let x := mload(TABLE1_X_LOC) + let y := mload(TABLE1_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V21_LOC), p)) + // accumulator_2 = u.[table1] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE TABLE2 + { + let x := mload(TABLE2_X_LOC) + let y := mload(TABLE2_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V22_LOC), p)) + // accumulator_2 = u.[table2] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE TABLE3 + { + let x := mload(TABLE3_X_LOC) + let y := mload(TABLE3_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V23_LOC), p)) + // accumulator_2 = u.[table3] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE TABLE4 + { + let x := mload(TABLE4_X_LOC) + let y := mload(TABLE4_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V24_LOC), p)) + // accumulator_2 = u.[table4] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE TABLE_TYPE + { + let x := mload(TABLE_TYPE_X_LOC) + let y := mload(TABLE_TYPE_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V25_LOC)) + // accumulator_2 = v25.[TableType] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE ID1 + { + let x := mload(ID1_X_LOC) + let y := mload(ID1_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V26_LOC)) + // accumulator_2 = v26.[ID1] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE ID2 + { + let x := mload(ID2_X_LOC) + let y := mload(ID2_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V27_LOC)) + // accumulator_2 = v27.[ID2] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE ID3 + { + let x := mload(ID3_X_LOC) + let y := mload(ID3_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V28_LOC)) + // accumulator_2 = v28.[ID3] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE ID4 + { + let x := mload(ID4_X_LOC) + let y := mload(ID4_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V29_LOC)) + // accumulator_2 = v29.[ID4] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + /** + * COMPUTE BATCH EVALUATION SCALAR MULTIPLIER + */ + { + /** + * batch_evaluation = v0 * (w_1_omega * u + w_1_eval) + * batch_evaluation += v1 * (w_2_omega * u + w_2_eval) + * batch_evaluation += v2 * (w_3_omega * u + w_3_eval) + * batch_evaluation += v3 * (w_4_omega * u + w_4_eval) + * batch_evaluation += v4 * (s_omega_eval * u + s_eval) + * batch_evaluation += v5 * (z_omega_eval * u + z_eval) + * batch_evaluation += v6 * (z_lookup_omega_eval * u + z_lookup_eval) + */ + let batch_evaluation := + mulmod( + mload(C_V0_LOC), + addmod(mulmod(mload(W1_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W1_EVAL_LOC), p), + p + ) + batch_evaluation := + addmod( + batch_evaluation, + mulmod( + mload(C_V1_LOC), + addmod(mulmod(mload(W2_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W2_EVAL_LOC), p), + p + ), + p + ) + batch_evaluation := + addmod( + batch_evaluation, + mulmod( + mload(C_V2_LOC), + addmod(mulmod(mload(W3_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W3_EVAL_LOC), p), + p + ), + p + ) + batch_evaluation := + addmod( + batch_evaluation, + mulmod( + mload(C_V3_LOC), + addmod(mulmod(mload(W4_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W4_EVAL_LOC), p), + p + ), + p + ) + batch_evaluation := + addmod( + batch_evaluation, + mulmod( + mload(C_V4_LOC), + addmod(mulmod(mload(S_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(S_EVAL_LOC), p), + p + ), + p + ) + batch_evaluation := + addmod( + batch_evaluation, + mulmod( + mload(C_V5_LOC), + addmod(mulmod(mload(Z_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(Z_EVAL_LOC), p), + p + ), + p + ) + batch_evaluation := + addmod( + batch_evaluation, + mulmod( + mload(C_V6_LOC), + addmod(mulmod(mload(Z_LOOKUP_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(Z_LOOKUP_EVAL_LOC), p), + p + ), + p + ) + + /** + * batch_evaluation += v7 * Q1_EVAL + * batch_evaluation += v8 * Q2_EVAL + * batch_evaluation += v9 * Q3_EVAL + * batch_evaluation += v10 * Q4_EVAL + * batch_evaluation += v11 * QM_EVAL + * batch_evaluation += v12 * QC_EVAL + * batch_evaluation += v13 * QARITH_EVAL + * batch_evaluation += v14 * QSORT_EVAL_LOC + * batch_evaluation += v15 * QELLIPTIC_EVAL_LOC + * batch_evaluation += v16 * QAUX_EVAL_LOC + * batch_evaluation += v17 * SIGMA1_EVAL_LOC + * batch_evaluation += v18 * SIGMA2_EVAL_LOC + * batch_evaluation += v19 * SIGMA3_EVAL_LOC + * batch_evaluation += v20 * SIGMA4_EVAL_LOC + */ + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V7_LOC), mload(Q1_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V8_LOC), mload(Q2_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V9_LOC), mload(Q3_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V10_LOC), mload(Q4_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V11_LOC), mload(QM_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V12_LOC), mload(QC_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V13_LOC), mload(QARITH_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V14_LOC), mload(QSORT_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V15_LOC), mload(QELLIPTIC_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V16_LOC), mload(QAUX_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V17_LOC), mload(SIGMA1_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V18_LOC), mload(SIGMA2_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V19_LOC), mload(SIGMA3_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V20_LOC), mload(SIGMA4_EVAL_LOC), p), p) + + /** + * batch_evaluation += v21 * (table1(zw) * u + table1(z)) + * batch_evaluation += v22 * (table2(zw) * u + table2(z)) + * batch_evaluation += v23 * (table3(zw) * u + table3(z)) + * batch_evaluation += v24 * (table4(zw) * u + table4(z)) + * batch_evaluation += v25 * table_type_eval + * batch_evaluation += v26 * id1_eval + * batch_evaluation += v27 * id2_eval + * batch_evaluation += v28 * id3_eval + * batch_evaluation += v29 * id4_eval + * batch_evaluation += quotient_eval + */ + batch_evaluation := + addmod( + batch_evaluation, + mulmod( + mload(C_V21_LOC), + addmod(mulmod(mload(TABLE1_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE1_EVAL_LOC), p), + p + ), + p + ) + batch_evaluation := + addmod( + batch_evaluation, + mulmod( + mload(C_V22_LOC), + addmod(mulmod(mload(TABLE2_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE2_EVAL_LOC), p), + p + ), + p + ) + batch_evaluation := + addmod( + batch_evaluation, + mulmod( + mload(C_V23_LOC), + addmod(mulmod(mload(TABLE3_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE3_EVAL_LOC), p), + p + ), + p + ) + batch_evaluation := + addmod( + batch_evaluation, + mulmod( + mload(C_V24_LOC), + addmod(mulmod(mload(TABLE4_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE4_EVAL_LOC), p), + p + ), + p + ) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V25_LOC), mload(TABLE_TYPE_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V26_LOC), mload(ID1_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V27_LOC), mload(ID2_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V28_LOC), mload(ID3_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V29_LOC), mload(ID4_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mload(QUOTIENT_EVAL_LOC), p) + + mstore(0x00, 0x01) // [1].x + mstore(0x20, 0x02) // [1].y + mstore(0x40, sub(p, batch_evaluation)) + // accumulator_2 = -[1].(batch_evaluation) + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + if iszero(success) { + mstore(0x0, OPENING_COMMITMENT_FAILED_SELECTOR) + revert(0x00, 0x04) + } + } + + /** + * PERFORM PAIRING PREAMBLE + */ + { + let u := mload(C_U_LOC) + let zeta := mload(C_ZETA_LOC) + // VALIDATE PI_Z + { + let x := mload(PI_Z_X_LOC) + let y := mload(PI_Z_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + // compute zeta.[PI_Z] and add into accumulator + mstore(0x40, zeta) + success := staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE PI_Z_OMEGA + { + let x := mload(PI_Z_OMEGA_X_LOC) + let y := mload(PI_Z_OMEGA_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(mulmod(u, zeta, p), mload(OMEGA_LOC), p)) + // accumulator_2 = u.zeta.omega.[PI_Z_OMEGA] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // PAIRING_RHS = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, PAIRING_RHS_X_LOC, 0x40)) + + mstore(0x00, mload(PI_Z_X_LOC)) + mstore(0x20, mload(PI_Z_Y_LOC)) + mstore(0x40, mload(PI_Z_OMEGA_X_LOC)) + mstore(0x60, mload(PI_Z_OMEGA_Y_LOC)) + mstore(0x80, u) + success := and(success, staticcall(gas(), 7, 0x40, 0x60, 0x40, 0x40)) + // PAIRING_LHS = [PI_Z] + [PI_Z_OMEGA] * u + success := and(success, staticcall(gas(), 6, 0x00, 0x80, PAIRING_LHS_X_LOC, 0x40)) + // negate lhs y-coordinate + mstore(PAIRING_LHS_Y_LOC, sub(q, mload(PAIRING_LHS_Y_LOC))) + + if mload(CONTAINS_RECURSIVE_PROOF_LOC) { + // VALIDATE RECURSIVE P1 + { + let x := mload(RECURSIVE_P1_X_LOC) + let y := mload(RECURSIVE_P1_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + + // compute u.u.[recursive_p1] and write into 0x60 + mstore(0x40, mulmod(u, u, p)) + success := and(success, staticcall(gas(), 7, 0x00, 0x60, 0x60, 0x40)) + // VALIDATE RECURSIVE P2 + { + let x := mload(RECURSIVE_P2_X_LOC) + let y := mload(RECURSIVE_P2_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + // compute u.u.[recursive_p2] and write into 0x00 + // 0x40 still contains u*u + success := and(success, staticcall(gas(), 7, 0x00, 0x60, 0x00, 0x40)) + + // compute u.u.[recursiveP1] + rhs and write into rhs + mstore(0xa0, mload(PAIRING_RHS_X_LOC)) + mstore(0xc0, mload(PAIRING_RHS_Y_LOC)) + success := and(success, staticcall(gas(), 6, 0x60, 0x80, PAIRING_RHS_X_LOC, 0x40)) + + // compute u.u.[recursiveP2] + lhs and write into lhs + mstore(0x40, mload(PAIRING_LHS_X_LOC)) + mstore(0x60, mload(PAIRING_LHS_Y_LOC)) + success := and(success, staticcall(gas(), 6, 0x00, 0x80, PAIRING_LHS_X_LOC, 0x40)) + } + + if iszero(success) { + mstore(0x0, PAIRING_PREAMBLE_FAILED_SELECTOR) + revert(0x00, 0x04) + } + } + + /** + * PERFORM PAIRING + */ + { + // rhs paired with [1]_2 + // lhs paired with [x]_2 + + mstore(0x00, mload(PAIRING_RHS_X_LOC)) + mstore(0x20, mload(PAIRING_RHS_Y_LOC)) + mstore(0x40, 0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2) // this is [1]_2 + mstore(0x60, 0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed) + mstore(0x80, 0x090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b) + mstore(0xa0, 0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa) + + mstore(0xc0, mload(PAIRING_LHS_X_LOC)) + mstore(0xe0, mload(PAIRING_LHS_Y_LOC)) + mstore(0x100, mload(G2X_X0_LOC)) + mstore(0x120, mload(G2X_X1_LOC)) + mstore(0x140, mload(G2X_Y0_LOC)) + mstore(0x160, mload(G2X_Y1_LOC)) + + success := staticcall(gas(), 8, 0x00, 0x180, 0x00, 0x20) + if iszero(and(success, mload(0x00))) { + mstore(0x0, PAIRING_FAILED_SELECTOR) + revert(0x00, 0x04) + } + } + + { + mstore(0x00, 0x01) + return(0x00, 0x20) // Proof succeeded! + } + } + } +} + +contract UltraVerifier is BaseUltraVerifier { + function getVerificationKeyHash() public pure override(BaseUltraVerifier) returns (bytes32) { + return UltraVerificationKey.verificationKeyHash(); + } + + function loadVerificationKey(uint256 vk, uint256 _omegaInverseLoc) internal pure virtual override(BaseUltraVerifier) { + UltraVerificationKey.loadVerificationKey(vk, _omegaInverseLoc); + } +} diff --git a/noir/noir-repo/compiler/integration-tests/contracts/assert_statement.sol b/noir/noir-repo/compiler/integration-tests/contracts/assert_statement.sol new file mode 100644 index 000000000000..6946be8ee4be --- /dev/null +++ b/noir/noir-repo/compiler/integration-tests/contracts/assert_statement.sol @@ -0,0 +1,2869 @@ +// Verification Key Hash: 203c988709ced4125d5c6138661ba4d16a71092c5f4189d2b3baf2596a93311b +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2022 Aztec +pragma solidity >=0.8.4; + +library UltraVerificationKey { + function verificationKeyHash() internal pure returns(bytes32) { + return 0x203c988709ced4125d5c6138661ba4d16a71092c5f4189d2b3baf2596a93311b; + } + + function loadVerificationKey(uint256 _vk, uint256 _omegaInverseLoc) internal pure { + assembly { + mstore(add(_vk, 0x00), 0x0000000000000000000000000000000000000000000000000000000000000008) // vk.circuit_size + mstore(add(_vk, 0x20), 0x0000000000000000000000000000000000000000000000000000000000000001) // vk.num_inputs + mstore(add(_vk, 0x40), 0x2b337de1c8c14f22ec9b9e2f96afef3652627366f8170a0a948dad4ac1bd5e80) // vk.work_root + mstore(add(_vk, 0x60), 0x2a57c4a4850b6c2481463cffb1512d51832d6b3f6a82427f1b65b6e172000001) // vk.domain_inverse + mstore(add(_vk, 0x80), 0x0160ce4e279582f91bde4f03f5e9a292139c61bae1a44f0fc7689507414be688) // vk.Q1.x + mstore(add(_vk, 0xa0), 0x07e3e8a5d98a1177ec85bf88f163a55dc2d37f658c3b2d60f24740eb13b65d79) // vk.Q1.y + mstore(add(_vk, 0xc0), 0x23d08e2817ac16990004ed11d8fc66dc3035fbd7ff16412a8fd7da587a935298) // vk.Q2.x + mstore(add(_vk, 0xe0), 0x0708529196af3c8e16ffa580c26182356a5ad59c646c746a8d09f5d154e47c4f) // vk.Q2.y + mstore(add(_vk, 0x100), 0x13757e15a0905f298303784a161b212ddfe70eb7a1280596e8e4a804f118a6dd) // vk.Q3.x + mstore(add(_vk, 0x120), 0x05775b6c146c4a59856e869fe5a70ea23a729df796935c7824e3a26be794829b) // vk.Q3.y + mstore(add(_vk, 0x140), 0x1d539ccbfc556d0ad59307a218de65eef0c9e088fd2d45aa40311082d1f2809b) // vk.Q4.x + mstore(add(_vk, 0x160), 0x177004deeb1f9d401fd7b1af1a5ac8a2c848beceb6ab7806fd3b88037b8410fc) // vk.Q4.y + mstore(add(_vk, 0x180), 0x0d82d51f2f75d806285fd248c819b82508eb63672a733f20de1a97644be4f540) // vk.Q_M.x + mstore(add(_vk, 0x1a0), 0x06cd3b0e3460533b9e5ea2cdc0fcbbd002f9100cbba8a29f13b11513c53c59d0) // vk.Q_M.y + mstore(add(_vk, 0x1c0), 0x21791de65f9a28ec7024b1a87ab4f3f45ea38a93b2f810c5633ddb54927c1c96) // vk.Q_C.x + mstore(add(_vk, 0x1e0), 0x29fa14a969c5d81ed3abbbfb11220a926511a0439502c86885a8c6f0327aa7ad) // vk.Q_C.y + mstore(add(_vk, 0x200), 0x2a910445cd8fc895e5d235cd8ea185b84c3258e8206f560e5b5b18cbeafef87e) // vk.Q_ARITHMETIC.x + mstore(add(_vk, 0x220), 0x14dc6643d801c3ef27c2066b6e2bb4887e67f15e84bcb8507a5064a363f6043b) // vk.Q_ARITHMETIC.y + mstore(add(_vk, 0x240), 0x20690fd4869db418306046b38161dce38e900b42c314ba803088e8fbf125203f) // vk.QSORT.x + mstore(add(_vk, 0x260), 0x048a85e0bbac7c60ad3d78f601f63c1e2fa856bf7951b8292b1e88185993629c) // vk.QSORT.y + mstore(add(_vk, 0x280), 0x2623ad892dc62b1fa7d0a650f0d4706f457719495073d3666d77a625aeab0c51) // vk.Q_ELLIPTIC.x + mstore(add(_vk, 0x2a0), 0x295f6f10976c37bd9c6f96bb7187d5dbfcc8a467e021c03b13f74a9f79c3a10c) // vk.Q_ELLIPTIC.y + mstore(add(_vk, 0x2c0), 0x03560a3b334e887532f605c9cb7628c13ef9a937cc12420fb38d9ab8e848e85e) // vk.Q_AUX.x + mstore(add(_vk, 0x2e0), 0x15adc8bb1e01c835f48959d1237bd69bcebf08a4599cdda0fb96312d4dc0c7a9) // vk.Q_AUX.y + mstore(add(_vk, 0x300), 0x24e3690cd89b1f74c96a6b0e03032344488741fb4b129e9cbcb31de91fd06ad8) // vk.SIGMA1.x + mstore(add(_vk, 0x320), 0x2c3b3b2783935f54e840bb7502b0ec734cb8ac2419c90514d0d015a974a9b52b) // vk.SIGMA1.y + mstore(add(_vk, 0x340), 0x060d8aa43fdc434d1942263f364d95ab17c6189d67d3bf5dd2f3885de0151b6f) // vk.SIGMA2.x + mstore(add(_vk, 0x360), 0x1a1018a66221883639f2898a66f3455d292333b3adb497f00b4bc32d45229060) // vk.SIGMA2.y + mstore(add(_vk, 0x380), 0x27730cec8ee6eafbd0e5ccffeab20dbd1c781a61196943647af68c4e39985fdc) // vk.SIGMA3.x + mstore(add(_vk, 0x3a0), 0x0766d1f3a85c923ee23cb3fcd89886f19af23a34217779c58eaeceb38cfdf1eb) // vk.SIGMA3.y + mstore(add(_vk, 0x3c0), 0x09ae6c317ff52520ae05150d89a4678f6f5839296a91685a8f562ca95fa36822) // vk.SIGMA4.x + mstore(add(_vk, 0x3e0), 0x0832680695476b91062cfd71c4663f5bd579304b4448ce5ae6eaa6620db20ab1) // vk.SIGMA4.y + mstore(add(_vk, 0x400), 0x1f54baa07558e5fb055bd9ba49c0679c5d6e08a6605ab4513748ac0fa017dd1c) // vk.TABLE1.x + mstore(add(_vk, 0x420), 0x24aec62a9d9763499267dc98c334281e1ee7ee29bbb5e4b080c6091c1433ce62) // vk.TABLE1.y + mstore(add(_vk, 0x440), 0x28cf3e22bcd53782ebc3e0490e27e51a96755946ff16f0d6632365f0eb0ab4d4) // vk.TABLE2.x + mstore(add(_vk, 0x460), 0x234ce541f1f5117dd404cfaf01a22943148d7d8c9ba43f2133fab4201435a364) // vk.TABLE2.y + mstore(add(_vk, 0x480), 0x3016955028b6390f446c3fd0c5b424a7fb95ffb461d9514a1070e2d2403982ef) // vk.TABLE3.x + mstore(add(_vk, 0x4a0), 0x13ef666111b0be56a235983d397d2a08863c3b7cd7cddc20ba79ce915051c56e) // vk.TABLE3.y + mstore(add(_vk, 0x4c0), 0x217f7c4235161e9a3c16c45b6ca499e3993f465fc9f56e93ac769e597b752c1c) // vk.TABLE4.x + mstore(add(_vk, 0x4e0), 0x256467bfcb63d9fdcb5dde397757ad8ffa4cd96bc67b0b7df5678271e1114075) // vk.TABLE4.y + mstore(add(_vk, 0x500), 0x0e52d1bd75812c33c6f3d79ee4b94c54e5eb270bb64bde6e6ececadfd8c3236c) // vk.TABLE_TYPE.x + mstore(add(_vk, 0x520), 0x0ff417d256be43e73c8b1aa85bdda3484a2c641dce55bc2dd64ef0cd790a7fea) // vk.TABLE_TYPE.y + mstore(add(_vk, 0x540), 0x2914765365b4bb5f48a424db02b30c158b9ace6a8786bf33f65c33e87249f995) // vk.ID1.x + mstore(add(_vk, 0x560), 0x2e606ebd09b7686801932b72c9dbe83a6b1ae341f8cb6d52a568b693630f4643) // vk.ID1.y + mstore(add(_vk, 0x580), 0x1b0d1316756ddd16982a7e98b868244fff53c5d4bdc2b70e371c0d08e994cfd5) // vk.ID2.x + mstore(add(_vk, 0x5a0), 0x27f94b1ce85bf25b95857aaa3b82f6a3706170d67e53462bc635491ec3a29f98) // vk.ID2.y + mstore(add(_vk, 0x5c0), 0x26c5c0971d041a6777e4896896f674670e17bb68e92cbb11e605d2d74c077f66) // vk.ID3.x + mstore(add(_vk, 0x5e0), 0x15d5a580649417ff6523c7ec8e2fce5f1f22fef5be2a9fb4fd3004d9c6562efe) // vk.ID3.y + mstore(add(_vk, 0x600), 0x2eea648c8732596b1314fe2a4d2f05363f0c994e91cecad25835338edee2294f) // vk.ID4.x + mstore(add(_vk, 0x620), 0x0ab49886c2b94bd0bd3f6ed1dbbe2cb2671d2ae51d31c1210433c3972bb64578) // vk.ID4.y + mstore(add(_vk, 0x640), 0x00) // vk.contains_recursive_proof + mstore(add(_vk, 0x660), 0) // vk.recursive_proof_public_input_indices + mstore(add(_vk, 0x680), 0x260e01b251f6f1c7e7ff4e580791dee8ea51d87a358e038b4efe30fac09383c1) // vk.g2_x.X.c1 + mstore(add(_vk, 0x6a0), 0x0118c4d5b837bcc2bc89b5b398b5974e9f5944073b32078b7e231fec938883b0) // vk.g2_x.X.c0 + mstore(add(_vk, 0x6c0), 0x04fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe4) // vk.g2_x.Y.c1 + mstore(add(_vk, 0x6e0), 0x22febda3c0c0632a56475b4214e5615e11e6dd3f96e6cea2854a87d4dacc5e55) // vk.g2_x.Y.c0 + mstore(_omegaInverseLoc, 0x130b17119778465cfb3acaee30f81dee20710ead41671f568b11d9ab07b95a9b) // vk.work_root_inverse + } + } +} + +/** + * @title Ultra Plonk proof verification contract + * @dev Top level Plonk proof verification contract, which allows Plonk proof to be verified + */ +abstract contract BaseUltraVerifier { + // VERIFICATION KEY MEMORY LOCATIONS + uint256 internal constant N_LOC = 0x380; + uint256 internal constant NUM_INPUTS_LOC = 0x3a0; + uint256 internal constant OMEGA_LOC = 0x3c0; + uint256 internal constant DOMAIN_INVERSE_LOC = 0x3e0; + uint256 internal constant Q1_X_LOC = 0x400; + uint256 internal constant Q1_Y_LOC = 0x420; + uint256 internal constant Q2_X_LOC = 0x440; + uint256 internal constant Q2_Y_LOC = 0x460; + uint256 internal constant Q3_X_LOC = 0x480; + uint256 internal constant Q3_Y_LOC = 0x4a0; + uint256 internal constant Q4_X_LOC = 0x4c0; + uint256 internal constant Q4_Y_LOC = 0x4e0; + uint256 internal constant QM_X_LOC = 0x500; + uint256 internal constant QM_Y_LOC = 0x520; + uint256 internal constant QC_X_LOC = 0x540; + uint256 internal constant QC_Y_LOC = 0x560; + uint256 internal constant QARITH_X_LOC = 0x580; + uint256 internal constant QARITH_Y_LOC = 0x5a0; + uint256 internal constant QSORT_X_LOC = 0x5c0; + uint256 internal constant QSORT_Y_LOC = 0x5e0; + uint256 internal constant QELLIPTIC_X_LOC = 0x600; + uint256 internal constant QELLIPTIC_Y_LOC = 0x620; + uint256 internal constant QAUX_X_LOC = 0x640; + uint256 internal constant QAUX_Y_LOC = 0x660; + uint256 internal constant SIGMA1_X_LOC = 0x680; + uint256 internal constant SIGMA1_Y_LOC = 0x6a0; + uint256 internal constant SIGMA2_X_LOC = 0x6c0; + uint256 internal constant SIGMA2_Y_LOC = 0x6e0; + uint256 internal constant SIGMA3_X_LOC = 0x700; + uint256 internal constant SIGMA3_Y_LOC = 0x720; + uint256 internal constant SIGMA4_X_LOC = 0x740; + uint256 internal constant SIGMA4_Y_LOC = 0x760; + uint256 internal constant TABLE1_X_LOC = 0x780; + uint256 internal constant TABLE1_Y_LOC = 0x7a0; + uint256 internal constant TABLE2_X_LOC = 0x7c0; + uint256 internal constant TABLE2_Y_LOC = 0x7e0; + uint256 internal constant TABLE3_X_LOC = 0x800; + uint256 internal constant TABLE3_Y_LOC = 0x820; + uint256 internal constant TABLE4_X_LOC = 0x840; + uint256 internal constant TABLE4_Y_LOC = 0x860; + uint256 internal constant TABLE_TYPE_X_LOC = 0x880; + uint256 internal constant TABLE_TYPE_Y_LOC = 0x8a0; + uint256 internal constant ID1_X_LOC = 0x8c0; + uint256 internal constant ID1_Y_LOC = 0x8e0; + uint256 internal constant ID2_X_LOC = 0x900; + uint256 internal constant ID2_Y_LOC = 0x920; + uint256 internal constant ID3_X_LOC = 0x940; + uint256 internal constant ID3_Y_LOC = 0x960; + uint256 internal constant ID4_X_LOC = 0x980; + uint256 internal constant ID4_Y_LOC = 0x9a0; + uint256 internal constant CONTAINS_RECURSIVE_PROOF_LOC = 0x9c0; + uint256 internal constant RECURSIVE_PROOF_PUBLIC_INPUT_INDICES_LOC = 0x9e0; + uint256 internal constant G2X_X0_LOC = 0xa00; + uint256 internal constant G2X_X1_LOC = 0xa20; + uint256 internal constant G2X_Y0_LOC = 0xa40; + uint256 internal constant G2X_Y1_LOC = 0xa60; + + // ### PROOF DATA MEMORY LOCATIONS + uint256 internal constant W1_X_LOC = 0x1200; + uint256 internal constant W1_Y_LOC = 0x1220; + uint256 internal constant W2_X_LOC = 0x1240; + uint256 internal constant W2_Y_LOC = 0x1260; + uint256 internal constant W3_X_LOC = 0x1280; + uint256 internal constant W3_Y_LOC = 0x12a0; + uint256 internal constant W4_X_LOC = 0x12c0; + uint256 internal constant W4_Y_LOC = 0x12e0; + uint256 internal constant S_X_LOC = 0x1300; + uint256 internal constant S_Y_LOC = 0x1320; + uint256 internal constant Z_X_LOC = 0x1340; + uint256 internal constant Z_Y_LOC = 0x1360; + uint256 internal constant Z_LOOKUP_X_LOC = 0x1380; + uint256 internal constant Z_LOOKUP_Y_LOC = 0x13a0; + uint256 internal constant T1_X_LOC = 0x13c0; + uint256 internal constant T1_Y_LOC = 0x13e0; + uint256 internal constant T2_X_LOC = 0x1400; + uint256 internal constant T2_Y_LOC = 0x1420; + uint256 internal constant T3_X_LOC = 0x1440; + uint256 internal constant T3_Y_LOC = 0x1460; + uint256 internal constant T4_X_LOC = 0x1480; + uint256 internal constant T4_Y_LOC = 0x14a0; + + uint256 internal constant W1_EVAL_LOC = 0x1600; + uint256 internal constant W2_EVAL_LOC = 0x1620; + uint256 internal constant W3_EVAL_LOC = 0x1640; + uint256 internal constant W4_EVAL_LOC = 0x1660; + uint256 internal constant S_EVAL_LOC = 0x1680; + uint256 internal constant Z_EVAL_LOC = 0x16a0; + uint256 internal constant Z_LOOKUP_EVAL_LOC = 0x16c0; + uint256 internal constant Q1_EVAL_LOC = 0x16e0; + uint256 internal constant Q2_EVAL_LOC = 0x1700; + uint256 internal constant Q3_EVAL_LOC = 0x1720; + uint256 internal constant Q4_EVAL_LOC = 0x1740; + uint256 internal constant QM_EVAL_LOC = 0x1760; + uint256 internal constant QC_EVAL_LOC = 0x1780; + uint256 internal constant QARITH_EVAL_LOC = 0x17a0; + uint256 internal constant QSORT_EVAL_LOC = 0x17c0; + uint256 internal constant QELLIPTIC_EVAL_LOC = 0x17e0; + uint256 internal constant QAUX_EVAL_LOC = 0x1800; + uint256 internal constant TABLE1_EVAL_LOC = 0x1840; + uint256 internal constant TABLE2_EVAL_LOC = 0x1860; + uint256 internal constant TABLE3_EVAL_LOC = 0x1880; + uint256 internal constant TABLE4_EVAL_LOC = 0x18a0; + uint256 internal constant TABLE_TYPE_EVAL_LOC = 0x18c0; + uint256 internal constant ID1_EVAL_LOC = 0x18e0; + uint256 internal constant ID2_EVAL_LOC = 0x1900; + uint256 internal constant ID3_EVAL_LOC = 0x1920; + uint256 internal constant ID4_EVAL_LOC = 0x1940; + uint256 internal constant SIGMA1_EVAL_LOC = 0x1960; + uint256 internal constant SIGMA2_EVAL_LOC = 0x1980; + uint256 internal constant SIGMA3_EVAL_LOC = 0x19a0; + uint256 internal constant SIGMA4_EVAL_LOC = 0x19c0; + uint256 internal constant W1_OMEGA_EVAL_LOC = 0x19e0; + uint256 internal constant W2_OMEGA_EVAL_LOC = 0x2000; + uint256 internal constant W3_OMEGA_EVAL_LOC = 0x2020; + uint256 internal constant W4_OMEGA_EVAL_LOC = 0x2040; + uint256 internal constant S_OMEGA_EVAL_LOC = 0x2060; + uint256 internal constant Z_OMEGA_EVAL_LOC = 0x2080; + uint256 internal constant Z_LOOKUP_OMEGA_EVAL_LOC = 0x20a0; + uint256 internal constant TABLE1_OMEGA_EVAL_LOC = 0x20c0; + uint256 internal constant TABLE2_OMEGA_EVAL_LOC = 0x20e0; + uint256 internal constant TABLE3_OMEGA_EVAL_LOC = 0x2100; + uint256 internal constant TABLE4_OMEGA_EVAL_LOC = 0x2120; + + uint256 internal constant PI_Z_X_LOC = 0x2300; + uint256 internal constant PI_Z_Y_LOC = 0x2320; + uint256 internal constant PI_Z_OMEGA_X_LOC = 0x2340; + uint256 internal constant PI_Z_OMEGA_Y_LOC = 0x2360; + + // Used for elliptic widget. These are alias names for wire + shifted wire evaluations + uint256 internal constant X1_EVAL_LOC = W2_EVAL_LOC; + uint256 internal constant X2_EVAL_LOC = W1_OMEGA_EVAL_LOC; + uint256 internal constant X3_EVAL_LOC = W2_OMEGA_EVAL_LOC; + uint256 internal constant Y1_EVAL_LOC = W3_EVAL_LOC; + uint256 internal constant Y2_EVAL_LOC = W4_OMEGA_EVAL_LOC; + uint256 internal constant Y3_EVAL_LOC = W3_OMEGA_EVAL_LOC; + uint256 internal constant QBETA_LOC = Q3_EVAL_LOC; + uint256 internal constant QBETA_SQR_LOC = Q4_EVAL_LOC; + uint256 internal constant QSIGN_LOC = Q1_EVAL_LOC; + + // ### CHALLENGES MEMORY OFFSETS + + uint256 internal constant C_BETA_LOC = 0x2600; + uint256 internal constant C_GAMMA_LOC = 0x2620; + uint256 internal constant C_ALPHA_LOC = 0x2640; + uint256 internal constant C_ETA_LOC = 0x2660; + uint256 internal constant C_ETA_SQR_LOC = 0x2680; + uint256 internal constant C_ETA_CUBE_LOC = 0x26a0; + + uint256 internal constant C_ZETA_LOC = 0x26c0; + uint256 internal constant C_CURRENT_LOC = 0x26e0; + uint256 internal constant C_V0_LOC = 0x2700; + uint256 internal constant C_V1_LOC = 0x2720; + uint256 internal constant C_V2_LOC = 0x2740; + uint256 internal constant C_V3_LOC = 0x2760; + uint256 internal constant C_V4_LOC = 0x2780; + uint256 internal constant C_V5_LOC = 0x27a0; + uint256 internal constant C_V6_LOC = 0x27c0; + uint256 internal constant C_V7_LOC = 0x27e0; + uint256 internal constant C_V8_LOC = 0x2800; + uint256 internal constant C_V9_LOC = 0x2820; + uint256 internal constant C_V10_LOC = 0x2840; + uint256 internal constant C_V11_LOC = 0x2860; + uint256 internal constant C_V12_LOC = 0x2880; + uint256 internal constant C_V13_LOC = 0x28a0; + uint256 internal constant C_V14_LOC = 0x28c0; + uint256 internal constant C_V15_LOC = 0x28e0; + uint256 internal constant C_V16_LOC = 0x2900; + uint256 internal constant C_V17_LOC = 0x2920; + uint256 internal constant C_V18_LOC = 0x2940; + uint256 internal constant C_V19_LOC = 0x2960; + uint256 internal constant C_V20_LOC = 0x2980; + uint256 internal constant C_V21_LOC = 0x29a0; + uint256 internal constant C_V22_LOC = 0x29c0; + uint256 internal constant C_V23_LOC = 0x29e0; + uint256 internal constant C_V24_LOC = 0x2a00; + uint256 internal constant C_V25_LOC = 0x2a20; + uint256 internal constant C_V26_LOC = 0x2a40; + uint256 internal constant C_V27_LOC = 0x2a60; + uint256 internal constant C_V28_LOC = 0x2a80; + uint256 internal constant C_V29_LOC = 0x2aa0; + uint256 internal constant C_V30_LOC = 0x2ac0; + + uint256 internal constant C_U_LOC = 0x2b00; + + // ### LOCAL VARIABLES MEMORY OFFSETS + uint256 internal constant DELTA_NUMERATOR_LOC = 0x3000; + uint256 internal constant DELTA_DENOMINATOR_LOC = 0x3020; + uint256 internal constant ZETA_POW_N_LOC = 0x3040; + uint256 internal constant PUBLIC_INPUT_DELTA_LOC = 0x3060; + uint256 internal constant ZERO_POLY_LOC = 0x3080; + uint256 internal constant L_START_LOC = 0x30a0; + uint256 internal constant L_END_LOC = 0x30c0; + uint256 internal constant R_ZERO_EVAL_LOC = 0x30e0; + + uint256 internal constant PLOOKUP_DELTA_NUMERATOR_LOC = 0x3100; + uint256 internal constant PLOOKUP_DELTA_DENOMINATOR_LOC = 0x3120; + uint256 internal constant PLOOKUP_DELTA_LOC = 0x3140; + + uint256 internal constant ACCUMULATOR_X_LOC = 0x3160; + uint256 internal constant ACCUMULATOR_Y_LOC = 0x3180; + uint256 internal constant ACCUMULATOR2_X_LOC = 0x31a0; + uint256 internal constant ACCUMULATOR2_Y_LOC = 0x31c0; + uint256 internal constant PAIRING_LHS_X_LOC = 0x31e0; + uint256 internal constant PAIRING_LHS_Y_LOC = 0x3200; + uint256 internal constant PAIRING_RHS_X_LOC = 0x3220; + uint256 internal constant PAIRING_RHS_Y_LOC = 0x3240; + + // misc stuff + uint256 internal constant OMEGA_INVERSE_LOC = 0x3300; + uint256 internal constant C_ALPHA_SQR_LOC = 0x3320; + uint256 internal constant C_ALPHA_CUBE_LOC = 0x3340; + uint256 internal constant C_ALPHA_QUAD_LOC = 0x3360; + uint256 internal constant C_ALPHA_BASE_LOC = 0x3380; + + // ### RECURSION VARIABLE MEMORY LOCATIONS + uint256 internal constant RECURSIVE_P1_X_LOC = 0x3400; + uint256 internal constant RECURSIVE_P1_Y_LOC = 0x3420; + uint256 internal constant RECURSIVE_P2_X_LOC = 0x3440; + uint256 internal constant RECURSIVE_P2_Y_LOC = 0x3460; + uint256 internal constant PUBLIC_INPUTS_HASH_LOCATION = 0x3480; + + // sub-identity storage + uint256 internal constant PERMUTATION_IDENTITY = 0x3500; + uint256 internal constant PLOOKUP_IDENTITY = 0x3520; + uint256 internal constant ARITHMETIC_IDENTITY = 0x3540; + uint256 internal constant SORT_IDENTITY = 0x3560; + uint256 internal constant ELLIPTIC_IDENTITY = 0x3580; + uint256 internal constant AUX_IDENTITY = 0x35a0; + uint256 internal constant AUX_NON_NATIVE_FIELD_EVALUATION = 0x35c0; + uint256 internal constant AUX_LIMB_ACCUMULATOR_EVALUATION = 0x35e0; + uint256 internal constant AUX_RAM_CONSISTENCY_EVALUATION = 0x3600; + uint256 internal constant AUX_ROM_CONSISTENCY_EVALUATION = 0x3620; + uint256 internal constant AUX_MEMORY_EVALUATION = 0x3640; + + uint256 internal constant QUOTIENT_EVAL_LOC = 0x3660; + uint256 internal constant ZERO_POLY_INVERSE_LOC = 0x3680; + + // when hashing public inputs we use memory at NU_CHALLENGE_INPUT_LOC_A, as the hash input size is unknown at compile time + uint256 internal constant NU_CHALLENGE_INPUT_LOC_A = 0x36a0; + uint256 internal constant NU_CHALLENGE_INPUT_LOC_B = 0x36c0; + uint256 internal constant NU_CHALLENGE_INPUT_LOC_C = 0x36e0; + + bytes4 internal constant INVALID_VERIFICATION_KEY_SELECTOR = 0x7e5769bf; + bytes4 internal constant POINT_NOT_ON_CURVE_SELECTOR = 0xa3dad654; + bytes4 internal constant PUBLIC_INPUT_INVALID_BN128_G1_POINT_SELECTOR = 0xeba9f4a6; + bytes4 internal constant PUBLIC_INPUT_GE_P_SELECTOR = 0x374a972f; + bytes4 internal constant MOD_EXP_FAILURE_SELECTOR = 0xf894a7bc; + bytes4 internal constant PAIRING_PREAMBLE_FAILED_SELECTOR = 0x01882d81; + bytes4 internal constant OPENING_COMMITMENT_FAILED_SELECTOR = 0x4e719763; + bytes4 internal constant PAIRING_FAILED_SELECTOR = 0xd71fd263; + + uint256 internal constant ETA_INPUT_LENGTH = 0xc0; // W1, W2, W3 = 6 * 0x20 bytes + + // We need to hash 41 field elements when generating the NU challenge + // w1, w2, w3, w4, s, z, z_lookup, q1, q2, q3, q4, qm, qc, qarith (14) + // qsort, qelliptic, qaux, sigma1, sigma2, sigma, sigma4, (7) + // table1, table2, table3, table4, tabletype, id1, id2, id3, id4, (9) + // w1_omega, w2_omega, w3_omega, w4_omega, s_omega, z_omega, z_lookup_omega, (7) + // table1_omega, table2_omega, table3_omega, table4_omega (4) + uint256 internal constant NU_INPUT_LENGTH = 0x520; // 0x520 = 41 * 0x20 + + // There are ELEVEN G1 group elements added into the transcript in the `beta` round, that we need to skip over + // W1, W2, W3, W4, S, Z, Z_LOOKUP, T1, T2, T3, T4 + uint256 internal constant NU_CALLDATA_SKIP_LENGTH = 0x2c0; // 11 * 0x40 = 0x2c0 + + uint256 internal constant NEGATIVE_INVERSE_OF_2_MODULO_P = + 0x183227397098d014dc2822db40c0ac2e9419f4243cdcb848a1f0fac9f8000000; + uint256 internal constant LIMB_SIZE = 0x100000000000000000; // 2<<68 + uint256 internal constant SUBLIMB_SHIFT = 0x4000; // 2<<14 + + // y^2 = x^3 + ax + b + // for Grumpkin, a = 0 and b = -17. We use b in a custom gate relation that evaluates elliptic curve arithmetic + uint256 internal constant GRUMPKIN_CURVE_B_PARAMETER_NEGATED = 17; + + error INVALID_VERIFICATION_KEY(); + error POINT_NOT_ON_CURVE(); + error PUBLIC_INPUT_COUNT_INVALID(uint256 expected, uint256 actual); + error PUBLIC_INPUT_INVALID_BN128_G1_POINT(); + error PUBLIC_INPUT_GE_P(); + error MOD_EXP_FAILURE(); + error PAIRING_PREAMBLE_FAILED(); + error OPENING_COMMITMENT_FAILED(); + error PAIRING_FAILED(); + + function getVerificationKeyHash() public pure virtual returns (bytes32); + + /** + * @dev We assume that the verification key loaded by this function is constant as we only verify it on deployment + */ + function loadVerificationKey(uint256 _vk, uint256 _omegaInverseLoc) internal pure virtual; + + constructor() { + loadVerificationKey(N_LOC, OMEGA_INVERSE_LOC); + + // We verify that all of the EC points in the verification key lie on the bn128 curve. + assembly { + let q := 21888242871839275222246405745257275088696311157297823662689037894645226208583 // EC group order + + let success := 1 + + // VALIDATE Q1 + { + let x := mload(Q1_X_LOC) + let y := mload(Q1_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE Q2 + { + let x := mload(Q2_X_LOC) + let y := mload(Q2_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE Q3 + { + let x := mload(Q3_X_LOC) + let y := mload(Q3_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE Q4 + { + let x := mload(Q4_X_LOC) + let y := mload(Q4_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + mstore(0x00, x) + mstore(0x20, y) + } + // VALIDATE QM + { + let x := mload(QM_X_LOC) + let y := mload(QM_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE QC + { + let x := mload(QC_X_LOC) + let y := mload(QC_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE QARITH + { + let x := mload(QARITH_X_LOC) + let y := mload(QARITH_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE QSORT + { + let x := mload(QSORT_X_LOC) + let y := mload(QSORT_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE QELLIPTIC + { + let x := mload(QELLIPTIC_X_LOC) + let y := mload(QELLIPTIC_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE QAUX + { + let x := mload(QAUX_X_LOC) + let y := mload(QAUX_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE SIGMA1 + { + let x := mload(SIGMA1_X_LOC) + let y := mload(SIGMA1_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE SIGMA2 + { + let x := mload(SIGMA2_X_LOC) + let y := mload(SIGMA2_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE SIGMA3 + { + let x := mload(SIGMA3_X_LOC) + let y := mload(SIGMA3_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE SIGMA4 + { + let x := mload(SIGMA4_X_LOC) + let y := mload(SIGMA4_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE TABLE1 + { + let x := mload(TABLE1_X_LOC) + let y := mload(TABLE1_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE TABLE2 + { + let x := mload(TABLE2_X_LOC) + let y := mload(TABLE2_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE TABLE3 + { + let x := mload(TABLE3_X_LOC) + let y := mload(TABLE3_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE TABLE4 + { + let x := mload(TABLE4_X_LOC) + let y := mload(TABLE4_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE TABLE_TYPE + { + let x := mload(TABLE_TYPE_X_LOC) + let y := mload(TABLE_TYPE_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE ID1 + { + let x := mload(ID1_X_LOC) + let y := mload(ID1_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE ID2 + { + let x := mload(ID2_X_LOC) + let y := mload(ID2_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE ID3 + { + let x := mload(ID3_X_LOC) + let y := mload(ID3_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE ID4 + { + let x := mload(ID4_X_LOC) + let y := mload(ID4_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + + if iszero(success) { + mstore(0x0, INVALID_VERIFICATION_KEY_SELECTOR) + revert(0x00, 0x04) + } + } + } + + /** + * @notice Verify a Ultra Plonk proof + * @param _proof - The serialized proof + * @param _publicInputs - An array of the public inputs + * @return True if proof is valid, reverts otherwise + */ + function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool) { + loadVerificationKey(N_LOC, OMEGA_INVERSE_LOC); + + uint256 requiredPublicInputCount; + assembly { + requiredPublicInputCount := mload(NUM_INPUTS_LOC) + } + if (requiredPublicInputCount != _publicInputs.length) { + revert PUBLIC_INPUT_COUNT_INVALID(requiredPublicInputCount, _publicInputs.length); + } + + assembly { + let q := 21888242871839275222246405745257275088696311157297823662689037894645226208583 // EC group order + let p := 21888242871839275222246405745257275088548364400416034343698204186575808495617 // Prime field order + + /** + * LOAD PROOF FROM CALLDATA + */ + { + let data_ptr := add(calldataload(0x04), 0x24) + + mstore(W1_Y_LOC, mod(calldataload(data_ptr), q)) + mstore(W1_X_LOC, mod(calldataload(add(data_ptr, 0x20)), q)) + + mstore(W2_Y_LOC, mod(calldataload(add(data_ptr, 0x40)), q)) + mstore(W2_X_LOC, mod(calldataload(add(data_ptr, 0x60)), q)) + + mstore(W3_Y_LOC, mod(calldataload(add(data_ptr, 0x80)), q)) + mstore(W3_X_LOC, mod(calldataload(add(data_ptr, 0xa0)), q)) + + mstore(W4_Y_LOC, mod(calldataload(add(data_ptr, 0xc0)), q)) + mstore(W4_X_LOC, mod(calldataload(add(data_ptr, 0xe0)), q)) + + mstore(S_Y_LOC, mod(calldataload(add(data_ptr, 0x100)), q)) + mstore(S_X_LOC, mod(calldataload(add(data_ptr, 0x120)), q)) + mstore(Z_Y_LOC, mod(calldataload(add(data_ptr, 0x140)), q)) + mstore(Z_X_LOC, mod(calldataload(add(data_ptr, 0x160)), q)) + mstore(Z_LOOKUP_Y_LOC, mod(calldataload(add(data_ptr, 0x180)), q)) + mstore(Z_LOOKUP_X_LOC, mod(calldataload(add(data_ptr, 0x1a0)), q)) + mstore(T1_Y_LOC, mod(calldataload(add(data_ptr, 0x1c0)), q)) + mstore(T1_X_LOC, mod(calldataload(add(data_ptr, 0x1e0)), q)) + + mstore(T2_Y_LOC, mod(calldataload(add(data_ptr, 0x200)), q)) + mstore(T2_X_LOC, mod(calldataload(add(data_ptr, 0x220)), q)) + + mstore(T3_Y_LOC, mod(calldataload(add(data_ptr, 0x240)), q)) + mstore(T3_X_LOC, mod(calldataload(add(data_ptr, 0x260)), q)) + + mstore(T4_Y_LOC, mod(calldataload(add(data_ptr, 0x280)), q)) + mstore(T4_X_LOC, mod(calldataload(add(data_ptr, 0x2a0)), q)) + + mstore(W1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x2c0)), p)) + mstore(W2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x2e0)), p)) + mstore(W3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x300)), p)) + mstore(W4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x320)), p)) + mstore(S_EVAL_LOC, mod(calldataload(add(data_ptr, 0x340)), p)) + mstore(Z_EVAL_LOC, mod(calldataload(add(data_ptr, 0x360)), p)) + mstore(Z_LOOKUP_EVAL_LOC, mod(calldataload(add(data_ptr, 0x380)), p)) + mstore(Q1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x3a0)), p)) + mstore(Q2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x3c0)), p)) + mstore(Q3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x3e0)), p)) + mstore(Q4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x400)), p)) + mstore(QM_EVAL_LOC, mod(calldataload(add(data_ptr, 0x420)), p)) + mstore(QC_EVAL_LOC, mod(calldataload(add(data_ptr, 0x440)), p)) + mstore(QARITH_EVAL_LOC, mod(calldataload(add(data_ptr, 0x460)), p)) + mstore(QSORT_EVAL_LOC, mod(calldataload(add(data_ptr, 0x480)), p)) + mstore(QELLIPTIC_EVAL_LOC, mod(calldataload(add(data_ptr, 0x4a0)), p)) + mstore(QAUX_EVAL_LOC, mod(calldataload(add(data_ptr, 0x4c0)), p)) + + mstore(SIGMA1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x4e0)), p)) + mstore(SIGMA2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x500)), p)) + + mstore(SIGMA3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x520)), p)) + mstore(SIGMA4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x540)), p)) + + mstore(TABLE1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x560)), p)) + mstore(TABLE2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x580)), p)) + mstore(TABLE3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x5a0)), p)) + mstore(TABLE4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x5c0)), p)) + mstore(TABLE_TYPE_EVAL_LOC, mod(calldataload(add(data_ptr, 0x5e0)), p)) + + mstore(ID1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x600)), p)) + mstore(ID2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x620)), p)) + mstore(ID3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x640)), p)) + mstore(ID4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x660)), p)) + + mstore(W1_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x680)), p)) + mstore(W2_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x6a0)), p)) + mstore(W3_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x6c0)), p)) + mstore(W4_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x6e0)), p)) + mstore(S_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x700)), p)) + + mstore(Z_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x720)), p)) + + mstore(Z_LOOKUP_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x740)), p)) + mstore(TABLE1_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x760)), p)) + mstore(TABLE2_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x780)), p)) + mstore(TABLE3_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x7a0)), p)) + mstore(TABLE4_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x7c0)), p)) + + mstore(PI_Z_Y_LOC, mod(calldataload(add(data_ptr, 0x7e0)), q)) + mstore(PI_Z_X_LOC, mod(calldataload(add(data_ptr, 0x800)), q)) + + mstore(PI_Z_OMEGA_Y_LOC, mod(calldataload(add(data_ptr, 0x820)), q)) + mstore(PI_Z_OMEGA_X_LOC, mod(calldataload(add(data_ptr, 0x840)), q)) + } + + /** + * LOAD RECURSIVE PROOF INTO MEMORY + */ + { + if mload(CONTAINS_RECURSIVE_PROOF_LOC) { + let public_inputs_ptr := add(calldataload(0x24), 0x24) + let index_counter := add(shl(5, mload(RECURSIVE_PROOF_PUBLIC_INPUT_INDICES_LOC)), public_inputs_ptr) + + let x0 := calldataload(index_counter) + x0 := add(x0, shl(68, calldataload(add(index_counter, 0x20)))) + x0 := add(x0, shl(136, calldataload(add(index_counter, 0x40)))) + x0 := add(x0, shl(204, calldataload(add(index_counter, 0x60)))) + let y0 := calldataload(add(index_counter, 0x80)) + y0 := add(y0, shl(68, calldataload(add(index_counter, 0xa0)))) + y0 := add(y0, shl(136, calldataload(add(index_counter, 0xc0)))) + y0 := add(y0, shl(204, calldataload(add(index_counter, 0xe0)))) + let x1 := calldataload(add(index_counter, 0x100)) + x1 := add(x1, shl(68, calldataload(add(index_counter, 0x120)))) + x1 := add(x1, shl(136, calldataload(add(index_counter, 0x140)))) + x1 := add(x1, shl(204, calldataload(add(index_counter, 0x160)))) + let y1 := calldataload(add(index_counter, 0x180)) + y1 := add(y1, shl(68, calldataload(add(index_counter, 0x1a0)))) + y1 := add(y1, shl(136, calldataload(add(index_counter, 0x1c0)))) + y1 := add(y1, shl(204, calldataload(add(index_counter, 0x1e0)))) + mstore(RECURSIVE_P1_X_LOC, x0) + mstore(RECURSIVE_P1_Y_LOC, y0) + mstore(RECURSIVE_P2_X_LOC, x1) + mstore(RECURSIVE_P2_Y_LOC, y1) + + // validate these are valid bn128 G1 points + if iszero(and(and(lt(x0, q), lt(x1, q)), and(lt(y0, q), lt(y1, q)))) { + mstore(0x00, PUBLIC_INPUT_INVALID_BN128_G1_POINT_SELECTOR) + revert(0x00, 0x04) + } + } + } + + { + /** + * Generate initial challenge + */ + mstore(0x00, shl(224, mload(N_LOC))) + mstore(0x04, shl(224, mload(NUM_INPUTS_LOC))) + let challenge := keccak256(0x00, 0x08) + + /** + * Generate eta challenge + */ + mstore(PUBLIC_INPUTS_HASH_LOCATION, challenge) + // The public input location is stored at 0x24, we then add 0x24 to skip selector and the length of public inputs + let public_inputs_start := add(calldataload(0x24), 0x24) + // copy the public inputs over + let public_input_size := mul(mload(NUM_INPUTS_LOC), 0x20) + calldatacopy(add(PUBLIC_INPUTS_HASH_LOCATION, 0x20), public_inputs_start, public_input_size) + + // copy W1, W2, W3 into challenge. Each point is 0x40 bytes, so load 0xc0 = 3 * 0x40 bytes (ETA input length) + let w_start := add(calldataload(0x04), 0x24) + calldatacopy(add(add(PUBLIC_INPUTS_HASH_LOCATION, 0x20), public_input_size), w_start, ETA_INPUT_LENGTH) + + // Challenge is the old challenge + public inputs + W1, W2, W3 (0x20 + public_input_size + 0xc0) + let challenge_bytes_size := add(0x20, add(public_input_size, ETA_INPUT_LENGTH)) + + challenge := keccak256(PUBLIC_INPUTS_HASH_LOCATION, challenge_bytes_size) + { + let eta := mod(challenge, p) + mstore(C_ETA_LOC, eta) + mstore(C_ETA_SQR_LOC, mulmod(eta, eta, p)) + mstore(C_ETA_CUBE_LOC, mulmod(mload(C_ETA_SQR_LOC), eta, p)) + } + + /** + * Generate beta challenge + */ + mstore(0x00, challenge) + mstore(0x20, mload(W4_Y_LOC)) + mstore(0x40, mload(W4_X_LOC)) + mstore(0x60, mload(S_Y_LOC)) + mstore(0x80, mload(S_X_LOC)) + challenge := keccak256(0x00, 0xa0) + mstore(C_BETA_LOC, mod(challenge, p)) + + /** + * Generate gamma challenge + */ + mstore(0x00, challenge) + mstore8(0x20, 0x01) + challenge := keccak256(0x00, 0x21) + mstore(C_GAMMA_LOC, mod(challenge, p)) + + /** + * Generate alpha challenge + */ + mstore(0x00, challenge) + mstore(0x20, mload(Z_Y_LOC)) + mstore(0x40, mload(Z_X_LOC)) + mstore(0x60, mload(Z_LOOKUP_Y_LOC)) + mstore(0x80, mload(Z_LOOKUP_X_LOC)) + challenge := keccak256(0x00, 0xa0) + mstore(C_ALPHA_LOC, mod(challenge, p)) + + /** + * Compute and store some powers of alpha for future computations + */ + let alpha := mload(C_ALPHA_LOC) + mstore(C_ALPHA_SQR_LOC, mulmod(alpha, alpha, p)) + mstore(C_ALPHA_CUBE_LOC, mulmod(mload(C_ALPHA_SQR_LOC), alpha, p)) + mstore(C_ALPHA_QUAD_LOC, mulmod(mload(C_ALPHA_CUBE_LOC), alpha, p)) + mstore(C_ALPHA_BASE_LOC, alpha) + + /** + * Generate zeta challenge + */ + mstore(0x00, challenge) + mstore(0x20, mload(T1_Y_LOC)) + mstore(0x40, mload(T1_X_LOC)) + mstore(0x60, mload(T2_Y_LOC)) + mstore(0x80, mload(T2_X_LOC)) + mstore(0xa0, mload(T3_Y_LOC)) + mstore(0xc0, mload(T3_X_LOC)) + mstore(0xe0, mload(T4_Y_LOC)) + mstore(0x100, mload(T4_X_LOC)) + + challenge := keccak256(0x00, 0x120) + + mstore(C_ZETA_LOC, mod(challenge, p)) + mstore(C_CURRENT_LOC, challenge) + } + + /** + * EVALUATE FIELD OPERATIONS + */ + + /** + * COMPUTE PUBLIC INPUT DELTA + * ΔPI = ∏ᵢ∈ℓ(wᵢ + β σ(i) + γ) / ∏ᵢ∈ℓ(wᵢ + β σ'(i) + γ) + */ + { + let beta := mload(C_BETA_LOC) // β + let gamma := mload(C_GAMMA_LOC) // γ + let work_root := mload(OMEGA_LOC) // ω + let numerator_value := 1 + let denominator_value := 1 + + let p_clone := p // move p to the front of the stack + let valid_inputs := true + + // Load the starting point of the public inputs (jump over the selector and the length of public inputs [0x24]) + let public_inputs_ptr := add(calldataload(0x24), 0x24) + + // endpoint_ptr = public_inputs_ptr + num_inputs * 0x20. // every public input is 0x20 bytes + let endpoint_ptr := add(public_inputs_ptr, mul(mload(NUM_INPUTS_LOC), 0x20)) + + // root_1 = β * 0x05 + let root_1 := mulmod(beta, 0x05, p_clone) // k1.β + // root_2 = β * 0x0c + let root_2 := mulmod(beta, 0x0c, p_clone) + // @note 0x05 + 0x07 == 0x0c == external coset generator + + for {} lt(public_inputs_ptr, endpoint_ptr) { public_inputs_ptr := add(public_inputs_ptr, 0x20) } { + /** + * input = public_input[i] + * valid_inputs &= input < p + * temp = input + gamma + * numerator_value *= (β.σ(i) + wᵢ + γ) // σ(i) = 0x05.ωⁱ + * denominator_value *= (β.σ'(i) + wᵢ + γ) // σ'(i) = 0x0c.ωⁱ + * root_1 *= ω + * root_2 *= ω + */ + + let input := calldataload(public_inputs_ptr) + valid_inputs := and(valid_inputs, lt(input, p_clone)) + let temp := addmod(input, gamma, p_clone) + + numerator_value := mulmod(numerator_value, add(root_1, temp), p_clone) + denominator_value := mulmod(denominator_value, add(root_2, temp), p_clone) + + root_1 := mulmod(root_1, work_root, p_clone) + root_2 := mulmod(root_2, work_root, p_clone) + } + + // Revert if not all public inputs are field elements (i.e. < p) + if iszero(valid_inputs) { + mstore(0x00, PUBLIC_INPUT_GE_P_SELECTOR) + revert(0x00, 0x04) + } + + mstore(DELTA_NUMERATOR_LOC, numerator_value) + mstore(DELTA_DENOMINATOR_LOC, denominator_value) + } + + /** + * Compute Plookup delta factor [γ(1 + β)]^{n-k} + * k = num roots cut out of Z_H = 4 + */ + { + let delta_base := mulmod(mload(C_GAMMA_LOC), addmod(mload(C_BETA_LOC), 1, p), p) + let delta_numerator := delta_base + { + let exponent := mload(N_LOC) + let count := 1 + for {} lt(count, exponent) { count := add(count, count) } { + delta_numerator := mulmod(delta_numerator, delta_numerator, p) + } + } + mstore(PLOOKUP_DELTA_NUMERATOR_LOC, delta_numerator) + + let delta_denominator := mulmod(delta_base, delta_base, p) + delta_denominator := mulmod(delta_denominator, delta_denominator, p) + mstore(PLOOKUP_DELTA_DENOMINATOR_LOC, delta_denominator) + } + /** + * Compute lagrange poly and vanishing poly fractions + */ + { + /** + * vanishing_numerator = zeta + * ZETA_POW_N = zeta^n + * vanishing_numerator -= 1 + * accumulating_root = omega_inverse + * work_root = p - accumulating_root + * domain_inverse = domain_inverse + * vanishing_denominator = zeta + work_root + * work_root *= accumulating_root + * vanishing_denominator *= (zeta + work_root) + * work_root *= accumulating_root + * vanishing_denominator *= (zeta + work_root) + * vanishing_denominator *= (zeta + (zeta + accumulating_root)) + * work_root = omega + * lagrange_numerator = vanishing_numerator * domain_inverse + * l_start_denominator = zeta - 1 + * accumulating_root = work_root^2 + * l_end_denominator = accumulating_root^2 * work_root * zeta - 1 + * Note: l_end_denominator term contains a term \omega^5 to cut out 5 roots of unity from vanishing poly + */ + + let zeta := mload(C_ZETA_LOC) + + // compute zeta^n, where n is a power of 2 + let vanishing_numerator := zeta + { + // pow_small + let exponent := mload(N_LOC) + let count := 1 + for {} lt(count, exponent) { count := add(count, count) } { + vanishing_numerator := mulmod(vanishing_numerator, vanishing_numerator, p) + } + } + mstore(ZETA_POW_N_LOC, vanishing_numerator) + vanishing_numerator := addmod(vanishing_numerator, sub(p, 1), p) + + let accumulating_root := mload(OMEGA_INVERSE_LOC) + let work_root := sub(p, accumulating_root) + let domain_inverse := mload(DOMAIN_INVERSE_LOC) + + let vanishing_denominator := addmod(zeta, work_root, p) + work_root := mulmod(work_root, accumulating_root, p) + vanishing_denominator := mulmod(vanishing_denominator, addmod(zeta, work_root, p), p) + work_root := mulmod(work_root, accumulating_root, p) + vanishing_denominator := mulmod(vanishing_denominator, addmod(zeta, work_root, p), p) + vanishing_denominator := + mulmod(vanishing_denominator, addmod(zeta, mulmod(work_root, accumulating_root, p), p), p) + + work_root := mload(OMEGA_LOC) + + let lagrange_numerator := mulmod(vanishing_numerator, domain_inverse, p) + let l_start_denominator := addmod(zeta, sub(p, 1), p) + + accumulating_root := mulmod(work_root, work_root, p) + + let l_end_denominator := + addmod( + mulmod(mulmod(mulmod(accumulating_root, accumulating_root, p), work_root, p), zeta, p), sub(p, 1), p + ) + + /** + * Compute inversions using Montgomery's batch inversion trick + */ + let accumulator := mload(DELTA_DENOMINATOR_LOC) + let t0 := accumulator + accumulator := mulmod(accumulator, vanishing_denominator, p) + let t1 := accumulator + accumulator := mulmod(accumulator, vanishing_numerator, p) + let t2 := accumulator + accumulator := mulmod(accumulator, l_start_denominator, p) + let t3 := accumulator + accumulator := mulmod(accumulator, mload(PLOOKUP_DELTA_DENOMINATOR_LOC), p) + let t4 := accumulator + { + mstore(0, 0x20) + mstore(0x20, 0x20) + mstore(0x40, 0x20) + mstore(0x60, mulmod(accumulator, l_end_denominator, p)) + mstore(0x80, sub(p, 2)) + mstore(0xa0, p) + if iszero(staticcall(gas(), 0x05, 0x00, 0xc0, 0x00, 0x20)) { + mstore(0x0, MOD_EXP_FAILURE_SELECTOR) + revert(0x00, 0x04) + } + accumulator := mload(0x00) + } + + t4 := mulmod(accumulator, t4, p) + accumulator := mulmod(accumulator, l_end_denominator, p) + + t3 := mulmod(accumulator, t3, p) + accumulator := mulmod(accumulator, mload(PLOOKUP_DELTA_DENOMINATOR_LOC), p) + + t2 := mulmod(accumulator, t2, p) + accumulator := mulmod(accumulator, l_start_denominator, p) + + t1 := mulmod(accumulator, t1, p) + accumulator := mulmod(accumulator, vanishing_numerator, p) + + t0 := mulmod(accumulator, t0, p) + accumulator := mulmod(accumulator, vanishing_denominator, p) + + accumulator := mulmod(mulmod(accumulator, accumulator, p), mload(DELTA_DENOMINATOR_LOC), p) + + mstore(PUBLIC_INPUT_DELTA_LOC, mulmod(mload(DELTA_NUMERATOR_LOC), accumulator, p)) + mstore(ZERO_POLY_LOC, mulmod(vanishing_numerator, t0, p)) + mstore(ZERO_POLY_INVERSE_LOC, mulmod(vanishing_denominator, t1, p)) + mstore(L_START_LOC, mulmod(lagrange_numerator, t2, p)) + mstore(PLOOKUP_DELTA_LOC, mulmod(mload(PLOOKUP_DELTA_NUMERATOR_LOC), t3, p)) + mstore(L_END_LOC, mulmod(lagrange_numerator, t4, p)) + } + + /** + * UltraPlonk Widget Ordering: + * + * 1. Permutation widget + * 2. Plookup widget + * 3. Arithmetic widget + * 4. Fixed base widget (?) + * 5. GenPermSort widget + * 6. Elliptic widget + * 7. Auxiliary widget + */ + + /** + * COMPUTE PERMUTATION WIDGET EVALUATION + */ + { + let alpha := mload(C_ALPHA_LOC) + let beta := mload(C_BETA_LOC) + let gamma := mload(C_GAMMA_LOC) + + /** + * t1 = (W1 + gamma + beta * ID1) * (W2 + gamma + beta * ID2) + * t2 = (W3 + gamma + beta * ID3) * (W4 + gamma + beta * ID4) + * result = alpha_base * z_eval * t1 * t2 + * t1 = (W1 + gamma + beta * sigma_1_eval) * (W2 + gamma + beta * sigma_2_eval) + * t2 = (W2 + gamma + beta * sigma_3_eval) * (W3 + gamma + beta * sigma_4_eval) + * result -= (alpha_base * z_omega_eval * t1 * t2) + */ + let t1 := + mulmod( + add(add(mload(W1_EVAL_LOC), gamma), mulmod(beta, mload(ID1_EVAL_LOC), p)), + add(add(mload(W2_EVAL_LOC), gamma), mulmod(beta, mload(ID2_EVAL_LOC), p)), + p + ) + let t2 := + mulmod( + add(add(mload(W3_EVAL_LOC), gamma), mulmod(beta, mload(ID3_EVAL_LOC), p)), + add(add(mload(W4_EVAL_LOC), gamma), mulmod(beta, mload(ID4_EVAL_LOC), p)), + p + ) + let result := mulmod(mload(C_ALPHA_BASE_LOC), mulmod(mload(Z_EVAL_LOC), mulmod(t1, t2, p), p), p) + t1 := + mulmod( + add(add(mload(W1_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA1_EVAL_LOC), p)), + add(add(mload(W2_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA2_EVAL_LOC), p)), + p + ) + t2 := + mulmod( + add(add(mload(W3_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA3_EVAL_LOC), p)), + add(add(mload(W4_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA4_EVAL_LOC), p)), + p + ) + result := + addmod( + result, + sub(p, mulmod(mload(C_ALPHA_BASE_LOC), mulmod(mload(Z_OMEGA_EVAL_LOC), mulmod(t1, t2, p), p), p)), + p + ) + + /** + * alpha_base *= alpha + * result += alpha_base . (L_{n-k}(ʓ) . (z(ʓ.ω) - ∆_{PI})) + * alpha_base *= alpha + * result += alpha_base . (L_1(ʓ)(Z(ʓ) - 1)) + * alpha_Base *= alpha + */ + mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p)) + result := + addmod( + result, + mulmod( + mload(C_ALPHA_BASE_LOC), + mulmod( + mload(L_END_LOC), + addmod(mload(Z_OMEGA_EVAL_LOC), sub(p, mload(PUBLIC_INPUT_DELTA_LOC)), p), + p + ), + p + ), + p + ) + mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p)) + mstore( + PERMUTATION_IDENTITY, + addmod( + result, + mulmod( + mload(C_ALPHA_BASE_LOC), + mulmod(mload(L_START_LOC), addmod(mload(Z_EVAL_LOC), sub(p, 1), p), p), + p + ), + p + ) + ) + mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p)) + } + + /** + * COMPUTE PLOOKUP WIDGET EVALUATION + */ + { + /** + * Goal: f = (w1(z) + q2.w1(zω)) + η(w2(z) + qm.w2(zω)) + η²(w3(z) + qc.w_3(zω)) + q3(z).η³ + * f = η.q3(z) + * f += (w3(z) + qc.w_3(zω)) + * f *= η + * f += (w2(z) + qm.w2(zω)) + * f *= η + * f += (w1(z) + q2.w1(zω)) + */ + let f := mulmod(mload(C_ETA_LOC), mload(Q3_EVAL_LOC), p) + f := + addmod(f, addmod(mload(W3_EVAL_LOC), mulmod(mload(QC_EVAL_LOC), mload(W3_OMEGA_EVAL_LOC), p), p), p) + f := mulmod(f, mload(C_ETA_LOC), p) + f := + addmod(f, addmod(mload(W2_EVAL_LOC), mulmod(mload(QM_EVAL_LOC), mload(W2_OMEGA_EVAL_LOC), p), p), p) + f := mulmod(f, mload(C_ETA_LOC), p) + f := + addmod(f, addmod(mload(W1_EVAL_LOC), mulmod(mload(Q2_EVAL_LOC), mload(W1_OMEGA_EVAL_LOC), p), p), p) + + // t(z) = table4(z).η³ + table3(z).η² + table2(z).η + table1(z) + let t := + addmod( + addmod( + addmod( + mulmod(mload(TABLE4_EVAL_LOC), mload(C_ETA_CUBE_LOC), p), + mulmod(mload(TABLE3_EVAL_LOC), mload(C_ETA_SQR_LOC), p), + p + ), + mulmod(mload(TABLE2_EVAL_LOC), mload(C_ETA_LOC), p), + p + ), + mload(TABLE1_EVAL_LOC), + p + ) + + // t(zw) = table4(zw).η³ + table3(zw).η² + table2(zw).η + table1(zw) + let t_omega := + addmod( + addmod( + addmod( + mulmod(mload(TABLE4_OMEGA_EVAL_LOC), mload(C_ETA_CUBE_LOC), p), + mulmod(mload(TABLE3_OMEGA_EVAL_LOC), mload(C_ETA_SQR_LOC), p), + p + ), + mulmod(mload(TABLE2_OMEGA_EVAL_LOC), mload(C_ETA_LOC), p), + p + ), + mload(TABLE1_OMEGA_EVAL_LOC), + p + ) + + /** + * Goal: numerator = (TABLE_TYPE_EVAL * f(z) + γ) * (t(z) + βt(zω) + γ(β + 1)) * (β + 1) + * gamma_beta_constant = γ(β + 1) + * numerator = f * TABLE_TYPE_EVAL + gamma + * temp0 = t(z) + t(zω) * β + gamma_beta_constant + * numerator *= temp0 + * numerator *= (β + 1) + * temp0 = alpha * l_1 + * numerator += temp0 + * numerator *= z_lookup(z) + * numerator -= temp0 + */ + let gamma_beta_constant := mulmod(mload(C_GAMMA_LOC), addmod(mload(C_BETA_LOC), 1, p), p) + let numerator := addmod(mulmod(f, mload(TABLE_TYPE_EVAL_LOC), p), mload(C_GAMMA_LOC), p) + let temp0 := addmod(addmod(t, mulmod(t_omega, mload(C_BETA_LOC), p), p), gamma_beta_constant, p) + numerator := mulmod(numerator, temp0, p) + numerator := mulmod(numerator, addmod(mload(C_BETA_LOC), 1, p), p) + temp0 := mulmod(mload(C_ALPHA_LOC), mload(L_START_LOC), p) + numerator := addmod(numerator, temp0, p) + numerator := mulmod(numerator, mload(Z_LOOKUP_EVAL_LOC), p) + numerator := addmod(numerator, sub(p, temp0), p) + + /** + * Goal: denominator = z_lookup(zω)*[s(z) + βs(zω) + γ(1 + β)] - [z_lookup(zω) - [γ(1 + β)]^{n-k}]*α²L_end(z) + * note: delta_factor = [γ(1 + β)]^{n-k} + * denominator = s(z) + βs(zω) + γ(β + 1) + * temp1 = α²L_end(z) + * denominator -= temp1 + * denominator *= z_lookup(zω) + * denominator += temp1 * delta_factor + * PLOOKUP_IDENTITY = (numerator - denominator).alpha_base + * alpha_base *= alpha^3 + */ + let denominator := + addmod( + addmod(mload(S_EVAL_LOC), mulmod(mload(S_OMEGA_EVAL_LOC), mload(C_BETA_LOC), p), p), + gamma_beta_constant, + p + ) + let temp1 := mulmod(mload(C_ALPHA_SQR_LOC), mload(L_END_LOC), p) + denominator := addmod(denominator, sub(p, temp1), p) + denominator := mulmod(denominator, mload(Z_LOOKUP_OMEGA_EVAL_LOC), p) + denominator := addmod(denominator, mulmod(temp1, mload(PLOOKUP_DELTA_LOC), p), p) + + mstore(PLOOKUP_IDENTITY, mulmod(addmod(numerator, sub(p, denominator), p), mload(C_ALPHA_BASE_LOC), p)) + + // update alpha + mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_CUBE_LOC), p)) + } + + /** + * COMPUTE ARITHMETIC WIDGET EVALUATION + */ + { + /** + * The basic arithmetic gate identity in standard plonk is as follows. + * (w_1 . w_2 . q_m) + (w_1 . q_1) + (w_2 . q_2) + (w_3 . q_3) + (w_4 . q_4) + q_c = 0 + * However, for Ultraplonk, we extend this to support "passing" wires between rows (shown without alpha scaling below): + * q_arith * ( ( (-1/2) * (q_arith - 3) * q_m * w_1 * w_2 + q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c ) + + * (q_arith - 1)*( α * (q_arith - 2) * (w_1 + w_4 - w_1_omega + q_m) + w_4_omega) ) = 0 + * + * This formula results in several cases depending on q_arith: + * 1. q_arith == 0: Arithmetic gate is completely disabled + * + * 2. q_arith == 1: Everything in the minigate on the right is disabled. The equation is just a standard plonk equation + * with extra wires: q_m * w_1 * w_2 + q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c = 0 + * + * 3. q_arith == 2: The (w_1 + w_4 - ...) term is disabled. THe equation is: + * (1/2) * q_m * w_1 * w_2 + q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c + w_4_omega = 0 + * It allows defining w_4 at next index (w_4_omega) in terms of current wire values + * + * 4. q_arith == 3: The product of w_1 and w_2 is disabled, but a mini addition gate is enabled. α allows us to split + * the equation into two: + * + * q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c + 2 * w_4_omega = 0 + * and + * w_1 + w_4 - w_1_omega + q_m = 0 (we are reusing q_m here) + * + * 5. q_arith > 3: The product of w_1 and w_2 is scaled by (q_arith - 3), while the w_4_omega term is scaled by (q_arith - 1). + * The equation can be split into two: + * + * (q_arith - 3)* q_m * w_1 * w_ 2 + q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c + (q_arith - 1) * w_4_omega = 0 + * and + * w_1 + w_4 - w_1_omega + q_m = 0 + * + * The problem that q_m is used both in both equations can be dealt with by appropriately changing selector values at + * the next gate. Then we can treat (q_arith - 1) as a simulated q_6 selector and scale q_m to handle (q_arith - 3) at + * product. + */ + + let w1q1 := mulmod(mload(W1_EVAL_LOC), mload(Q1_EVAL_LOC), p) + let w2q2 := mulmod(mload(W2_EVAL_LOC), mload(Q2_EVAL_LOC), p) + let w3q3 := mulmod(mload(W3_EVAL_LOC), mload(Q3_EVAL_LOC), p) + let w4q3 := mulmod(mload(W4_EVAL_LOC), mload(Q4_EVAL_LOC), p) + + // @todo - Add a explicit test that hits QARITH == 3 + // w1w2qm := (w_1 . w_2 . q_m . (QARITH_EVAL_LOC - 3)) / 2 + let w1w2qm := + mulmod( + mulmod( + mulmod(mulmod(mload(W1_EVAL_LOC), mload(W2_EVAL_LOC), p), mload(QM_EVAL_LOC), p), + addmod(mload(QARITH_EVAL_LOC), sub(p, 3), p), + p + ), + NEGATIVE_INVERSE_OF_2_MODULO_P, + p + ) + + // (w_1 . w_2 . q_m . (q_arith - 3)) / -2) + (w_1 . q_1) + (w_2 . q_2) + (w_3 . q_3) + (w_4 . q_4) + q_c + let identity := + addmod( + mload(QC_EVAL_LOC), addmod(w4q3, addmod(w3q3, addmod(w2q2, addmod(w1q1, w1w2qm, p), p), p), p), p + ) + + // if q_arith == 3 we evaluate an additional mini addition gate (on top of the regular one), where: + // w_1 + w_4 - w_1_omega + q_m = 0 + // we use this gate to save an addition gate when adding or subtracting non-native field elements + // α * (q_arith - 2) * (w_1 + w_4 - w_1_omega + q_m) + let extra_small_addition_gate_identity := + mulmod( + mload(C_ALPHA_LOC), + mulmod( + addmod(mload(QARITH_EVAL_LOC), sub(p, 2), p), + addmod( + mload(QM_EVAL_LOC), + addmod( + sub(p, mload(W1_OMEGA_EVAL_LOC)), addmod(mload(W1_EVAL_LOC), mload(W4_EVAL_LOC), p), p + ), + p + ), + p + ), + p + ) + + // if q_arith == 2 OR q_arith == 3 we add the 4th wire of the NEXT gate into the arithmetic identity + // N.B. if q_arith > 2, this wire value will be scaled by (q_arith - 1) relative to the other gate wires! + // alpha_base * q_arith * (identity + (q_arith - 1) * (w_4_omega + extra_small_addition_gate_identity)) + mstore( + ARITHMETIC_IDENTITY, + mulmod( + mload(C_ALPHA_BASE_LOC), + mulmod( + mload(QARITH_EVAL_LOC), + addmod( + identity, + mulmod( + addmod(mload(QARITH_EVAL_LOC), sub(p, 1), p), + addmod(mload(W4_OMEGA_EVAL_LOC), extra_small_addition_gate_identity, p), + p + ), + p + ), + p + ), + p + ) + ) + + // update alpha + mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_SQR_LOC), p)) + } + + /** + * COMPUTE GENPERMSORT WIDGET EVALUATION + */ + { + /** + * D1 = (w2 - w1) + * D2 = (w3 - w2) + * D3 = (w4 - w3) + * D4 = (w1_omega - w4) + * + * α_a = alpha_base + * α_b = alpha_base * α + * α_c = alpha_base * α^2 + * α_d = alpha_base * α^3 + * + * range_accumulator = ( + * D1(D1 - 1)(D1 - 2)(D1 - 3).α_a + + * D2(D2 - 1)(D2 - 2)(D2 - 3).α_b + + * D3(D3 - 1)(D3 - 2)(D3 - 3).α_c + + * D4(D4 - 1)(D4 - 2)(D4 - 3).α_d + + * ) . q_sort + */ + let minus_two := sub(p, 2) + let minus_three := sub(p, 3) + let d1 := addmod(mload(W2_EVAL_LOC), sub(p, mload(W1_EVAL_LOC)), p) + let d2 := addmod(mload(W3_EVAL_LOC), sub(p, mload(W2_EVAL_LOC)), p) + let d3 := addmod(mload(W4_EVAL_LOC), sub(p, mload(W3_EVAL_LOC)), p) + let d4 := addmod(mload(W1_OMEGA_EVAL_LOC), sub(p, mload(W4_EVAL_LOC)), p) + + let range_accumulator := + mulmod( + mulmod( + mulmod(addmod(mulmod(d1, d1, p), sub(p, d1), p), addmod(d1, minus_two, p), p), + addmod(d1, minus_three, p), + p + ), + mload(C_ALPHA_BASE_LOC), + p + ) + range_accumulator := + addmod( + range_accumulator, + mulmod( + mulmod( + mulmod(addmod(mulmod(d2, d2, p), sub(p, d2), p), addmod(d2, minus_two, p), p), + addmod(d2, minus_three, p), + p + ), + mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p), + p + ), + p + ) + range_accumulator := + addmod( + range_accumulator, + mulmod( + mulmod( + mulmod(addmod(mulmod(d3, d3, p), sub(p, d3), p), addmod(d3, minus_two, p), p), + addmod(d3, minus_three, p), + p + ), + mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_SQR_LOC), p), + p + ), + p + ) + range_accumulator := + addmod( + range_accumulator, + mulmod( + mulmod( + mulmod(addmod(mulmod(d4, d4, p), sub(p, d4), p), addmod(d4, minus_two, p), p), + addmod(d4, minus_three, p), + p + ), + mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_CUBE_LOC), p), + p + ), + p + ) + range_accumulator := mulmod(range_accumulator, mload(QSORT_EVAL_LOC), p) + + mstore(SORT_IDENTITY, range_accumulator) + + // update alpha + mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_QUAD_LOC), p)) + } + + /** + * COMPUTE ELLIPTIC WIDGET EVALUATION + */ + { + /** + * endo_term = (-x_2) * x_1 * (x_3 * 2 + x_1) * q_beta + * endo_sqr_term = x_2^2 + * endo_sqr_term *= (x_3 - x_1) + * endo_sqr_term *= q_beta^2 + * leftovers = x_2^2 + * leftovers *= x_2 + * leftovers += x_1^2 * (x_3 + x_1) @follow-up Invalid comment in BB widget + * leftovers -= (y_2^2 + y_1^2) + * sign_term = y_2 * y_1 + * sign_term += sign_term + * sign_term *= q_sign + */ + // q_elliptic * (x3 + x2 + x1)(x2 - x1)(x2 - x1) - y2^2 - y1^2 + 2(y2y1)*q_sign = 0 + let x_diff := addmod(mload(X2_EVAL_LOC), sub(p, mload(X1_EVAL_LOC)), p) + let y2_sqr := mulmod(mload(Y2_EVAL_LOC), mload(Y2_EVAL_LOC), p) + let y1_sqr := mulmod(mload(Y1_EVAL_LOC), mload(Y1_EVAL_LOC), p) + let y1y2 := mulmod(mulmod(mload(Y1_EVAL_LOC), mload(Y2_EVAL_LOC), p), mload(QSIGN_LOC), p) + + let x_add_identity := + addmod( + mulmod( + addmod(mload(X3_EVAL_LOC), addmod(mload(X2_EVAL_LOC), mload(X1_EVAL_LOC), p), p), + mulmod(x_diff, x_diff, p), + p + ), + addmod( + sub( + p, + addmod(y2_sqr, y1_sqr, p) + ), + addmod(y1y2, y1y2, p), + p + ), + p + ) + x_add_identity := + mulmod( + mulmod( + x_add_identity, + addmod( + 1, + sub(p, mload(QM_EVAL_LOC)), + p + ), + p + ), + mload(C_ALPHA_BASE_LOC), + p + ) + + // q_elliptic * (x3 + x2 + x1)(x2 - x1)(x2 - x1) - y2^2 - y1^2 + 2(y2y1)*q_sign = 0 + let y1_plus_y3 := addmod( + mload(Y1_EVAL_LOC), + mload(Y3_EVAL_LOC), + p + ) + let y_diff := addmod(mulmod(mload(Y2_EVAL_LOC), mload(QSIGN_LOC), p), sub(p, mload(Y1_EVAL_LOC)), p) + let y_add_identity := + addmod( + mulmod(y1_plus_y3, x_diff, p), + mulmod(addmod(mload(X3_EVAL_LOC), sub(p, mload(X1_EVAL_LOC)), p), y_diff, p), + p + ) + y_add_identity := + mulmod( + mulmod(y_add_identity, addmod(1, sub(p, mload(QM_EVAL_LOC)), p), p), + mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p), + p + ) + + // ELLIPTIC_IDENTITY = (x_identity + y_identity) * Q_ELLIPTIC_EVAL + mstore( + ELLIPTIC_IDENTITY, mulmod(addmod(x_add_identity, y_add_identity, p), mload(QELLIPTIC_EVAL_LOC), p) + ) + } + { + /** + * x_pow_4 = (y_1_sqr - curve_b) * x_1; + * y_1_sqr_mul_4 = y_1_sqr + y_1_sqr; + * y_1_sqr_mul_4 += y_1_sqr_mul_4; + * x_1_pow_4_mul_9 = x_pow_4; + * x_1_pow_4_mul_9 += x_1_pow_4_mul_9; + * x_1_pow_4_mul_9 += x_1_pow_4_mul_9; + * x_1_pow_4_mul_9 += x_1_pow_4_mul_9; + * x_1_pow_4_mul_9 += x_pow_4; + * x_1_sqr_mul_3 = x_1_sqr + x_1_sqr + x_1_sqr; + * x_double_identity = (x_3 + x_1 + x_1) * y_1_sqr_mul_4 - x_1_pow_4_mul_9; + * y_double_identity = x_1_sqr_mul_3 * (x_1 - x_3) - (y_1 + y_1) * (y_1 + y_3); + */ + // (x3 + x1 + x1) (4y1*y1) - 9 * x1 * x1 * x1 * x1 = 0 + let x1_sqr := mulmod(mload(X1_EVAL_LOC), mload(X1_EVAL_LOC), p) + let y1_sqr := mulmod(mload(Y1_EVAL_LOC), mload(Y1_EVAL_LOC), p) + let x_pow_4 := mulmod(addmod(y1_sqr, GRUMPKIN_CURVE_B_PARAMETER_NEGATED, p), mload(X1_EVAL_LOC), p) + let y1_sqr_mul_4 := mulmod(y1_sqr, 4, p) + let x1_pow_4_mul_9 := mulmod(x_pow_4, 9, p) + let x1_sqr_mul_3 := mulmod(x1_sqr, 3, p) + let x_double_identity := + addmod( + mulmod( + addmod(mload(X3_EVAL_LOC), addmod(mload(X1_EVAL_LOC), mload(X1_EVAL_LOC), p), p), + y1_sqr_mul_4, + p + ), + sub(p, x1_pow_4_mul_9), + p + ) + // (y1 + y1) (2y1) - (3 * x1 * x1)(x1 - x3) = 0 + let y_double_identity := + addmod( + mulmod(x1_sqr_mul_3, addmod(mload(X1_EVAL_LOC), sub(p, mload(X3_EVAL_LOC)), p), p), + sub( + p, + mulmod( + addmod(mload(Y1_EVAL_LOC), mload(Y1_EVAL_LOC), p), + addmod(mload(Y1_EVAL_LOC), mload(Y3_EVAL_LOC), p), + p + ) + ), + p + ) + x_double_identity := mulmod(x_double_identity, mload(C_ALPHA_BASE_LOC), p) + y_double_identity := + mulmod(y_double_identity, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p), p) + x_double_identity := mulmod(x_double_identity, mload(QM_EVAL_LOC), p) + y_double_identity := mulmod(y_double_identity, mload(QM_EVAL_LOC), p) + // ELLIPTIC_IDENTITY += (x_double_identity + y_double_identity) * Q_DOUBLE_EVAL + mstore( + ELLIPTIC_IDENTITY, + addmod( + mload(ELLIPTIC_IDENTITY), + mulmod(addmod(x_double_identity, y_double_identity, p), mload(QELLIPTIC_EVAL_LOC), p), + p + ) + ) + + // update alpha + mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_QUAD_LOC), p)) + } + + /** + * COMPUTE AUXILIARY WIDGET EVALUATION + */ + { + { + /** + * Non native field arithmetic gate 2 + * _ _ + * / _ _ _ 14 \ + * q_2 . q_4 | (w_1 . w_2) + (w_1 . w_2) + (w_1 . w_4 + w_2 . w_3 - w_3) . 2 - w_3 - w_4 | + * \_ _/ + * + * limb_subproduct = w_1 . w_2_omega + w_1_omega . w_2 + * non_native_field_gate_2 = w_1 * w_4 + w_4 * w_3 - w_3_omega + * non_native_field_gate_2 = non_native_field_gate_2 * limb_size + * non_native_field_gate_2 -= w_4_omega + * non_native_field_gate_2 += limb_subproduct + * non_native_field_gate_2 *= q_4 + * limb_subproduct *= limb_size + * limb_subproduct += w_1_omega * w_2_omega + * non_native_field_gate_1 = (limb_subproduct + w_3 + w_4) * q_3 + * non_native_field_gate_3 = (limb_subproduct + w_4 - (w_3_omega + w_4_omega)) * q_m + * non_native_field_identity = (non_native_field_gate_1 + non_native_field_gate_2 + non_native_field_gate_3) * q_2 + */ + + let limb_subproduct := + addmod( + mulmod(mload(W1_EVAL_LOC), mload(W2_OMEGA_EVAL_LOC), p), + mulmod(mload(W1_OMEGA_EVAL_LOC), mload(W2_EVAL_LOC), p), + p + ) + + let non_native_field_gate_2 := + addmod( + addmod( + mulmod(mload(W1_EVAL_LOC), mload(W4_EVAL_LOC), p), + mulmod(mload(W2_EVAL_LOC), mload(W3_EVAL_LOC), p), + p + ), + sub(p, mload(W3_OMEGA_EVAL_LOC)), + p + ) + non_native_field_gate_2 := mulmod(non_native_field_gate_2, LIMB_SIZE, p) + non_native_field_gate_2 := addmod(non_native_field_gate_2, sub(p, mload(W4_OMEGA_EVAL_LOC)), p) + non_native_field_gate_2 := addmod(non_native_field_gate_2, limb_subproduct, p) + non_native_field_gate_2 := mulmod(non_native_field_gate_2, mload(Q4_EVAL_LOC), p) + limb_subproduct := mulmod(limb_subproduct, LIMB_SIZE, p) + limb_subproduct := + addmod(limb_subproduct, mulmod(mload(W1_OMEGA_EVAL_LOC), mload(W2_OMEGA_EVAL_LOC), p), p) + let non_native_field_gate_1 := + mulmod( + addmod(limb_subproduct, sub(p, addmod(mload(W3_EVAL_LOC), mload(W4_EVAL_LOC), p)), p), + mload(Q3_EVAL_LOC), + p + ) + let non_native_field_gate_3 := + mulmod( + addmod( + addmod(limb_subproduct, mload(W4_EVAL_LOC), p), + sub(p, addmod(mload(W3_OMEGA_EVAL_LOC), mload(W4_OMEGA_EVAL_LOC), p)), + p + ), + mload(QM_EVAL_LOC), + p + ) + let non_native_field_identity := + mulmod( + addmod(addmod(non_native_field_gate_1, non_native_field_gate_2, p), non_native_field_gate_3, p), + mload(Q2_EVAL_LOC), + p + ) + + mstore(AUX_NON_NATIVE_FIELD_EVALUATION, non_native_field_identity) + } + + { + /** + * limb_accumulator_1 = w_2_omega; + * limb_accumulator_1 *= SUBLIMB_SHIFT; + * limb_accumulator_1 += w_1_omega; + * limb_accumulator_1 *= SUBLIMB_SHIFT; + * limb_accumulator_1 += w_3; + * limb_accumulator_1 *= SUBLIMB_SHIFT; + * limb_accumulator_1 += w_2; + * limb_accumulator_1 *= SUBLIMB_SHIFT; + * limb_accumulator_1 += w_1; + * limb_accumulator_1 -= w_4; + * limb_accumulator_1 *= q_4; + */ + let limb_accumulator_1 := mulmod(mload(W2_OMEGA_EVAL_LOC), SUBLIMB_SHIFT, p) + limb_accumulator_1 := addmod(limb_accumulator_1, mload(W1_OMEGA_EVAL_LOC), p) + limb_accumulator_1 := mulmod(limb_accumulator_1, SUBLIMB_SHIFT, p) + limb_accumulator_1 := addmod(limb_accumulator_1, mload(W3_EVAL_LOC), p) + limb_accumulator_1 := mulmod(limb_accumulator_1, SUBLIMB_SHIFT, p) + limb_accumulator_1 := addmod(limb_accumulator_1, mload(W2_EVAL_LOC), p) + limb_accumulator_1 := mulmod(limb_accumulator_1, SUBLIMB_SHIFT, p) + limb_accumulator_1 := addmod(limb_accumulator_1, mload(W1_EVAL_LOC), p) + limb_accumulator_1 := addmod(limb_accumulator_1, sub(p, mload(W4_EVAL_LOC)), p) + limb_accumulator_1 := mulmod(limb_accumulator_1, mload(Q4_EVAL_LOC), p) + + /** + * limb_accumulator_2 = w_3_omega; + * limb_accumulator_2 *= SUBLIMB_SHIFT; + * limb_accumulator_2 += w_2_omega; + * limb_accumulator_2 *= SUBLIMB_SHIFT; + * limb_accumulator_2 += w_1_omega; + * limb_accumulator_2 *= SUBLIMB_SHIFT; + * limb_accumulator_2 += w_4; + * limb_accumulator_2 *= SUBLIMB_SHIFT; + * limb_accumulator_2 += w_3; + * limb_accumulator_2 -= w_4_omega; + * limb_accumulator_2 *= q_m; + */ + let limb_accumulator_2 := mulmod(mload(W3_OMEGA_EVAL_LOC), SUBLIMB_SHIFT, p) + limb_accumulator_2 := addmod(limb_accumulator_2, mload(W2_OMEGA_EVAL_LOC), p) + limb_accumulator_2 := mulmod(limb_accumulator_2, SUBLIMB_SHIFT, p) + limb_accumulator_2 := addmod(limb_accumulator_2, mload(W1_OMEGA_EVAL_LOC), p) + limb_accumulator_2 := mulmod(limb_accumulator_2, SUBLIMB_SHIFT, p) + limb_accumulator_2 := addmod(limb_accumulator_2, mload(W4_EVAL_LOC), p) + limb_accumulator_2 := mulmod(limb_accumulator_2, SUBLIMB_SHIFT, p) + limb_accumulator_2 := addmod(limb_accumulator_2, mload(W3_EVAL_LOC), p) + limb_accumulator_2 := addmod(limb_accumulator_2, sub(p, mload(W4_OMEGA_EVAL_LOC)), p) + limb_accumulator_2 := mulmod(limb_accumulator_2, mload(QM_EVAL_LOC), p) + + mstore( + AUX_LIMB_ACCUMULATOR_EVALUATION, + mulmod(addmod(limb_accumulator_1, limb_accumulator_2, p), mload(Q3_EVAL_LOC), p) + ) + } + + { + /** + * memory_record_check = w_3; + * memory_record_check *= eta; + * memory_record_check += w_2; + * memory_record_check *= eta; + * memory_record_check += w_1; + * memory_record_check *= eta; + * memory_record_check += q_c; + * + * partial_record_check = memory_record_check; + * + * memory_record_check -= w_4; + */ + + let memory_record_check := mulmod(mload(W3_EVAL_LOC), mload(C_ETA_LOC), p) + memory_record_check := addmod(memory_record_check, mload(W2_EVAL_LOC), p) + memory_record_check := mulmod(memory_record_check, mload(C_ETA_LOC), p) + memory_record_check := addmod(memory_record_check, mload(W1_EVAL_LOC), p) + memory_record_check := mulmod(memory_record_check, mload(C_ETA_LOC), p) + memory_record_check := addmod(memory_record_check, mload(QC_EVAL_LOC), p) + + let partial_record_check := memory_record_check + memory_record_check := addmod(memory_record_check, sub(p, mload(W4_EVAL_LOC)), p) + + mstore(AUX_MEMORY_EVALUATION, memory_record_check) + + // index_delta = w_1_omega - w_1 + let index_delta := addmod(mload(W1_OMEGA_EVAL_LOC), sub(p, mload(W1_EVAL_LOC)), p) + // record_delta = w_4_omega - w_4 + let record_delta := addmod(mload(W4_OMEGA_EVAL_LOC), sub(p, mload(W4_EVAL_LOC)), p) + // index_is_monotonically_increasing = index_delta * (index_delta - 1) + let index_is_monotonically_increasing := mulmod(index_delta, addmod(index_delta, sub(p, 1), p), p) + + // adjacent_values_match_if_adjacent_indices_match = record_delta * (1 - index_delta) + let adjacent_values_match_if_adjacent_indices_match := + mulmod(record_delta, addmod(1, sub(p, index_delta), p), p) + + // AUX_ROM_CONSISTENCY_EVALUATION = ((adjacent_values_match_if_adjacent_indices_match * alpha) + index_is_monotonically_increasing) * alpha + partial_record_check + mstore( + AUX_ROM_CONSISTENCY_EVALUATION, + addmod( + mulmod( + addmod( + mulmod(adjacent_values_match_if_adjacent_indices_match, mload(C_ALPHA_LOC), p), + index_is_monotonically_increasing, + p + ), + mload(C_ALPHA_LOC), + p + ), + memory_record_check, + p + ) + ) + + { + /** + * next_gate_access_type = w_3_omega; + * next_gate_access_type *= eta; + * next_gate_access_type += w_2_omega; + * next_gate_access_type *= eta; + * next_gate_access_type += w_1_omega; + * next_gate_access_type *= eta; + * next_gate_access_type = w_4_omega - next_gate_access_type; + */ + let next_gate_access_type := mulmod(mload(W3_OMEGA_EVAL_LOC), mload(C_ETA_LOC), p) + next_gate_access_type := addmod(next_gate_access_type, mload(W2_OMEGA_EVAL_LOC), p) + next_gate_access_type := mulmod(next_gate_access_type, mload(C_ETA_LOC), p) + next_gate_access_type := addmod(next_gate_access_type, mload(W1_OMEGA_EVAL_LOC), p) + next_gate_access_type := mulmod(next_gate_access_type, mload(C_ETA_LOC), p) + next_gate_access_type := addmod(mload(W4_OMEGA_EVAL_LOC), sub(p, next_gate_access_type), p) + + // value_delta = w_3_omega - w_3 + let value_delta := addmod(mload(W3_OMEGA_EVAL_LOC), sub(p, mload(W3_EVAL_LOC)), p) + // adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation = (1 - index_delta) * value_delta * (1 - next_gate_access_type); + + let adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation := + mulmod( + addmod(1, sub(p, index_delta), p), + mulmod(value_delta, addmod(1, sub(p, next_gate_access_type), p), p), + p + ) + + // AUX_RAM_CONSISTENCY_EVALUATION + + /** + * access_type = w_4 - partial_record_check + * access_check = access_type^2 - access_type + * next_gate_access_type_is_boolean = next_gate_access_type^2 - next_gate_access_type + * RAM_consistency_check_identity = adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation; + * RAM_consistency_check_identity *= alpha; + * RAM_consistency_check_identity += index_is_monotonically_increasing; + * RAM_consistency_check_identity *= alpha; + * RAM_consistency_check_identity += next_gate_access_type_is_boolean; + * RAM_consistency_check_identity *= alpha; + * RAM_consistency_check_identity += access_check; + */ + + let access_type := addmod(mload(W4_EVAL_LOC), sub(p, partial_record_check), p) + let access_check := mulmod(access_type, addmod(access_type, sub(p, 1), p), p) + let next_gate_access_type_is_boolean := + mulmod(next_gate_access_type, addmod(next_gate_access_type, sub(p, 1), p), p) + let RAM_cci := + mulmod( + adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation, + mload(C_ALPHA_LOC), + p + ) + RAM_cci := addmod(RAM_cci, index_is_monotonically_increasing, p) + RAM_cci := mulmod(RAM_cci, mload(C_ALPHA_LOC), p) + RAM_cci := addmod(RAM_cci, next_gate_access_type_is_boolean, p) + RAM_cci := mulmod(RAM_cci, mload(C_ALPHA_LOC), p) + RAM_cci := addmod(RAM_cci, access_check, p) + + mstore(AUX_RAM_CONSISTENCY_EVALUATION, RAM_cci) + } + + { + // timestamp_delta = w_2_omega - w_2 + let timestamp_delta := addmod(mload(W2_OMEGA_EVAL_LOC), sub(p, mload(W2_EVAL_LOC)), p) + + // RAM_timestamp_check_identity = (1 - index_delta) * timestamp_delta - w_3 + let RAM_timestamp_check_identity := + addmod( + mulmod(timestamp_delta, addmod(1, sub(p, index_delta), p), p), sub(p, mload(W3_EVAL_LOC)), p + ) + + /** + * memory_identity = ROM_consistency_check_identity * q_2; + * memory_identity += RAM_timestamp_check_identity * q_4; + * memory_identity += memory_record_check * q_m; + * memory_identity *= q_1; + * memory_identity += (RAM_consistency_check_identity * q_arith); + * + * auxiliary_identity = memory_identity + non_native_field_identity + limb_accumulator_identity; + * auxiliary_identity *= q_aux; + * auxiliary_identity *= alpha_base; + */ + let memory_identity := mulmod(mload(AUX_ROM_CONSISTENCY_EVALUATION), mload(Q2_EVAL_LOC), p) + memory_identity := + addmod(memory_identity, mulmod(RAM_timestamp_check_identity, mload(Q4_EVAL_LOC), p), p) + memory_identity := + addmod(memory_identity, mulmod(mload(AUX_MEMORY_EVALUATION), mload(QM_EVAL_LOC), p), p) + memory_identity := mulmod(memory_identity, mload(Q1_EVAL_LOC), p) + memory_identity := + addmod( + memory_identity, mulmod(mload(AUX_RAM_CONSISTENCY_EVALUATION), mload(QARITH_EVAL_LOC), p), p + ) + + let auxiliary_identity := addmod(memory_identity, mload(AUX_NON_NATIVE_FIELD_EVALUATION), p) + auxiliary_identity := addmod(auxiliary_identity, mload(AUX_LIMB_ACCUMULATOR_EVALUATION), p) + auxiliary_identity := mulmod(auxiliary_identity, mload(QAUX_EVAL_LOC), p) + auxiliary_identity := mulmod(auxiliary_identity, mload(C_ALPHA_BASE_LOC), p) + + mstore(AUX_IDENTITY, auxiliary_identity) + + // update alpha + mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_CUBE_LOC), p)) + } + } + } + + { + /** + * quotient = ARITHMETIC_IDENTITY + * quotient += PERMUTATION_IDENTITY + * quotient += PLOOKUP_IDENTITY + * quotient += SORT_IDENTITY + * quotient += ELLIPTIC_IDENTITY + * quotient += AUX_IDENTITY + * quotient *= ZERO_POLY_INVERSE + */ + mstore( + QUOTIENT_EVAL_LOC, + mulmod( + addmod( + addmod( + addmod( + addmod( + addmod(mload(PERMUTATION_IDENTITY), mload(PLOOKUP_IDENTITY), p), + mload(ARITHMETIC_IDENTITY), + p + ), + mload(SORT_IDENTITY), + p + ), + mload(ELLIPTIC_IDENTITY), + p + ), + mload(AUX_IDENTITY), + p + ), + mload(ZERO_POLY_INVERSE_LOC), + p + ) + ) + } + + /** + * GENERATE NU AND SEPARATOR CHALLENGES + */ + { + let current_challenge := mload(C_CURRENT_LOC) + // get a calldata pointer that points to the start of the data we want to copy + let calldata_ptr := add(calldataload(0x04), 0x24) + + calldata_ptr := add(calldata_ptr, NU_CALLDATA_SKIP_LENGTH) + + mstore(NU_CHALLENGE_INPUT_LOC_A, current_challenge) + mstore(NU_CHALLENGE_INPUT_LOC_B, mload(QUOTIENT_EVAL_LOC)) + calldatacopy(NU_CHALLENGE_INPUT_LOC_C, calldata_ptr, NU_INPUT_LENGTH) + + // hash length = (0x20 + num field elements), we include the previous challenge in the hash + let challenge := keccak256(NU_CHALLENGE_INPUT_LOC_A, add(NU_INPUT_LENGTH, 0x40)) + + mstore(C_V0_LOC, mod(challenge, p)) + // We need THIRTY-ONE independent nu challenges! + mstore(0x00, challenge) + mstore8(0x20, 0x01) + mstore(C_V1_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x02) + mstore(C_V2_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x03) + mstore(C_V3_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x04) + mstore(C_V4_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x05) + mstore(C_V5_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x06) + mstore(C_V6_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x07) + mstore(C_V7_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x08) + mstore(C_V8_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x09) + mstore(C_V9_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x0a) + mstore(C_V10_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x0b) + mstore(C_V11_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x0c) + mstore(C_V12_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x0d) + mstore(C_V13_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x0e) + mstore(C_V14_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x0f) + mstore(C_V15_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x10) + mstore(C_V16_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x11) + mstore(C_V17_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x12) + mstore(C_V18_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x13) + mstore(C_V19_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x14) + mstore(C_V20_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x15) + mstore(C_V21_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x16) + mstore(C_V22_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x17) + mstore(C_V23_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x18) + mstore(C_V24_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x19) + mstore(C_V25_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x1a) + mstore(C_V26_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x1b) + mstore(C_V27_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x1c) + mstore(C_V28_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x1d) + mstore(C_V29_LOC, mod(keccak256(0x00, 0x21), p)) + + // @follow-up - Why are both v29 and v30 using appending 0x1d to the prior challenge and hashing, should it not change? + mstore8(0x20, 0x1d) + challenge := keccak256(0x00, 0x21) + mstore(C_V30_LOC, mod(challenge, p)) + + // separator + mstore(0x00, challenge) + mstore(0x20, mload(PI_Z_Y_LOC)) + mstore(0x40, mload(PI_Z_X_LOC)) + mstore(0x60, mload(PI_Z_OMEGA_Y_LOC)) + mstore(0x80, mload(PI_Z_OMEGA_X_LOC)) + + mstore(C_U_LOC, mod(keccak256(0x00, 0xa0), p)) + } + + let success := 0 + // VALIDATE T1 + { + let x := mload(T1_X_LOC) + let y := mload(T1_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(ACCUMULATOR_X_LOC, x) + mstore(add(ACCUMULATOR_X_LOC, 0x20), y) + } + // VALIDATE T2 + { + let x := mload(T2_X_LOC) // 0x1400 + let y := mload(T2_Y_LOC) // 0x1420 + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(ZETA_POW_N_LOC)) + // accumulator_2 = [T2].zeta^n + success := staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40) + // accumulator = [T1] + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE T3 + { + let x := mload(T3_X_LOC) + let y := mload(T3_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(mload(ZETA_POW_N_LOC), mload(ZETA_POW_N_LOC), p)) + // accumulator_2 = [T3].zeta^{2n} + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE T4 + { + let x := mload(T4_X_LOC) + let y := mload(T4_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(mulmod(mload(ZETA_POW_N_LOC), mload(ZETA_POW_N_LOC), p), mload(ZETA_POW_N_LOC), p)) + // accumulator_2 = [T4].zeta^{3n} + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE W1 + { + let x := mload(W1_X_LOC) + let y := mload(W1_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V0_LOC), p)) + // accumulator_2 = v0.(u + 1).[W1] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE W2 + { + let x := mload(W2_X_LOC) + let y := mload(W2_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V1_LOC), p)) + // accumulator_2 = v1.(u + 1).[W2] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE W3 + { + let x := mload(W3_X_LOC) + let y := mload(W3_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V2_LOC), p)) + // accumulator_2 = v2.(u + 1).[W3] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE W4 + { + let x := mload(W4_X_LOC) + let y := mload(W4_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V3_LOC), p)) + // accumulator_2 = v3.(u + 1).[W4] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE S + { + let x := mload(S_X_LOC) + let y := mload(S_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V4_LOC), p)) + // accumulator_2 = v4.(u + 1).[S] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE Z + { + let x := mload(Z_X_LOC) + let y := mload(Z_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V5_LOC), p)) + // accumulator_2 = v5.(u + 1).[Z] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE Z_LOOKUP + { + let x := mload(Z_LOOKUP_X_LOC) + let y := mload(Z_LOOKUP_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V6_LOC), p)) + // accumulator_2 = v6.(u + 1).[Z_LOOKUP] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE Q1 + { + let x := mload(Q1_X_LOC) + let y := mload(Q1_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V7_LOC)) + // accumulator_2 = v7.[Q1] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE Q2 + { + let x := mload(Q2_X_LOC) + let y := mload(Q2_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V8_LOC)) + // accumulator_2 = v8.[Q2] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE Q3 + { + let x := mload(Q3_X_LOC) + let y := mload(Q3_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V9_LOC)) + // accumulator_2 = v9.[Q3] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE Q4 + { + let x := mload(Q4_X_LOC) + let y := mload(Q4_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V10_LOC)) + // accumulator_2 = v10.[Q4] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE QM + { + let x := mload(QM_X_LOC) + let y := mload(QM_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V11_LOC)) + // accumulator_2 = v11.[Q;] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE QC + { + let x := mload(QC_X_LOC) + let y := mload(QC_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V12_LOC)) + // accumulator_2 = v12.[QC] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE QARITH + { + let x := mload(QARITH_X_LOC) + let y := mload(QARITH_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V13_LOC)) + // accumulator_2 = v13.[QARITH] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE QSORT + { + let x := mload(QSORT_X_LOC) + let y := mload(QSORT_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V14_LOC)) + // accumulator_2 = v14.[QSORT] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE QELLIPTIC + { + let x := mload(QELLIPTIC_X_LOC) + let y := mload(QELLIPTIC_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V15_LOC)) + // accumulator_2 = v15.[QELLIPTIC] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE QAUX + { + let x := mload(QAUX_X_LOC) + let y := mload(QAUX_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V16_LOC)) + // accumulator_2 = v15.[Q_AUX] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE SIGMA1 + { + let x := mload(SIGMA1_X_LOC) + let y := mload(SIGMA1_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V17_LOC)) + // accumulator_2 = v17.[sigma1] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE SIGMA2 + { + let x := mload(SIGMA2_X_LOC) + let y := mload(SIGMA2_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V18_LOC)) + // accumulator_2 = v18.[sigma2] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE SIGMA3 + { + let x := mload(SIGMA3_X_LOC) + let y := mload(SIGMA3_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V19_LOC)) + // accumulator_2 = v19.[sigma3] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE SIGMA4 + { + let x := mload(SIGMA4_X_LOC) + let y := mload(SIGMA4_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V20_LOC)) + // accumulator_2 = v20.[sigma4] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE TABLE1 + { + let x := mload(TABLE1_X_LOC) + let y := mload(TABLE1_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V21_LOC), p)) + // accumulator_2 = u.[table1] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE TABLE2 + { + let x := mload(TABLE2_X_LOC) + let y := mload(TABLE2_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V22_LOC), p)) + // accumulator_2 = u.[table2] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE TABLE3 + { + let x := mload(TABLE3_X_LOC) + let y := mload(TABLE3_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V23_LOC), p)) + // accumulator_2 = u.[table3] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE TABLE4 + { + let x := mload(TABLE4_X_LOC) + let y := mload(TABLE4_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V24_LOC), p)) + // accumulator_2 = u.[table4] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE TABLE_TYPE + { + let x := mload(TABLE_TYPE_X_LOC) + let y := mload(TABLE_TYPE_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V25_LOC)) + // accumulator_2 = v25.[TableType] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE ID1 + { + let x := mload(ID1_X_LOC) + let y := mload(ID1_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V26_LOC)) + // accumulator_2 = v26.[ID1] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE ID2 + { + let x := mload(ID2_X_LOC) + let y := mload(ID2_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V27_LOC)) + // accumulator_2 = v27.[ID2] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE ID3 + { + let x := mload(ID3_X_LOC) + let y := mload(ID3_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V28_LOC)) + // accumulator_2 = v28.[ID3] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE ID4 + { + let x := mload(ID4_X_LOC) + let y := mload(ID4_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V29_LOC)) + // accumulator_2 = v29.[ID4] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + /** + * COMPUTE BATCH EVALUATION SCALAR MULTIPLIER + */ + { + /** + * batch_evaluation = v0 * (w_1_omega * u + w_1_eval) + * batch_evaluation += v1 * (w_2_omega * u + w_2_eval) + * batch_evaluation += v2 * (w_3_omega * u + w_3_eval) + * batch_evaluation += v3 * (w_4_omega * u + w_4_eval) + * batch_evaluation += v4 * (s_omega_eval * u + s_eval) + * batch_evaluation += v5 * (z_omega_eval * u + z_eval) + * batch_evaluation += v6 * (z_lookup_omega_eval * u + z_lookup_eval) + */ + let batch_evaluation := + mulmod( + mload(C_V0_LOC), + addmod(mulmod(mload(W1_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W1_EVAL_LOC), p), + p + ) + batch_evaluation := + addmod( + batch_evaluation, + mulmod( + mload(C_V1_LOC), + addmod(mulmod(mload(W2_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W2_EVAL_LOC), p), + p + ), + p + ) + batch_evaluation := + addmod( + batch_evaluation, + mulmod( + mload(C_V2_LOC), + addmod(mulmod(mload(W3_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W3_EVAL_LOC), p), + p + ), + p + ) + batch_evaluation := + addmod( + batch_evaluation, + mulmod( + mload(C_V3_LOC), + addmod(mulmod(mload(W4_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W4_EVAL_LOC), p), + p + ), + p + ) + batch_evaluation := + addmod( + batch_evaluation, + mulmod( + mload(C_V4_LOC), + addmod(mulmod(mload(S_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(S_EVAL_LOC), p), + p + ), + p + ) + batch_evaluation := + addmod( + batch_evaluation, + mulmod( + mload(C_V5_LOC), + addmod(mulmod(mload(Z_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(Z_EVAL_LOC), p), + p + ), + p + ) + batch_evaluation := + addmod( + batch_evaluation, + mulmod( + mload(C_V6_LOC), + addmod(mulmod(mload(Z_LOOKUP_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(Z_LOOKUP_EVAL_LOC), p), + p + ), + p + ) + + /** + * batch_evaluation += v7 * Q1_EVAL + * batch_evaluation += v8 * Q2_EVAL + * batch_evaluation += v9 * Q3_EVAL + * batch_evaluation += v10 * Q4_EVAL + * batch_evaluation += v11 * QM_EVAL + * batch_evaluation += v12 * QC_EVAL + * batch_evaluation += v13 * QARITH_EVAL + * batch_evaluation += v14 * QSORT_EVAL_LOC + * batch_evaluation += v15 * QELLIPTIC_EVAL_LOC + * batch_evaluation += v16 * QAUX_EVAL_LOC + * batch_evaluation += v17 * SIGMA1_EVAL_LOC + * batch_evaluation += v18 * SIGMA2_EVAL_LOC + * batch_evaluation += v19 * SIGMA3_EVAL_LOC + * batch_evaluation += v20 * SIGMA4_EVAL_LOC + */ + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V7_LOC), mload(Q1_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V8_LOC), mload(Q2_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V9_LOC), mload(Q3_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V10_LOC), mload(Q4_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V11_LOC), mload(QM_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V12_LOC), mload(QC_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V13_LOC), mload(QARITH_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V14_LOC), mload(QSORT_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V15_LOC), mload(QELLIPTIC_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V16_LOC), mload(QAUX_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V17_LOC), mload(SIGMA1_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V18_LOC), mload(SIGMA2_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V19_LOC), mload(SIGMA3_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V20_LOC), mload(SIGMA4_EVAL_LOC), p), p) + + /** + * batch_evaluation += v21 * (table1(zw) * u + table1(z)) + * batch_evaluation += v22 * (table2(zw) * u + table2(z)) + * batch_evaluation += v23 * (table3(zw) * u + table3(z)) + * batch_evaluation += v24 * (table4(zw) * u + table4(z)) + * batch_evaluation += v25 * table_type_eval + * batch_evaluation += v26 * id1_eval + * batch_evaluation += v27 * id2_eval + * batch_evaluation += v28 * id3_eval + * batch_evaluation += v29 * id4_eval + * batch_evaluation += quotient_eval + */ + batch_evaluation := + addmod( + batch_evaluation, + mulmod( + mload(C_V21_LOC), + addmod(mulmod(mload(TABLE1_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE1_EVAL_LOC), p), + p + ), + p + ) + batch_evaluation := + addmod( + batch_evaluation, + mulmod( + mload(C_V22_LOC), + addmod(mulmod(mload(TABLE2_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE2_EVAL_LOC), p), + p + ), + p + ) + batch_evaluation := + addmod( + batch_evaluation, + mulmod( + mload(C_V23_LOC), + addmod(mulmod(mload(TABLE3_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE3_EVAL_LOC), p), + p + ), + p + ) + batch_evaluation := + addmod( + batch_evaluation, + mulmod( + mload(C_V24_LOC), + addmod(mulmod(mload(TABLE4_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE4_EVAL_LOC), p), + p + ), + p + ) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V25_LOC), mload(TABLE_TYPE_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V26_LOC), mload(ID1_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V27_LOC), mload(ID2_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V28_LOC), mload(ID3_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V29_LOC), mload(ID4_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mload(QUOTIENT_EVAL_LOC), p) + + mstore(0x00, 0x01) // [1].x + mstore(0x20, 0x02) // [1].y + mstore(0x40, sub(p, batch_evaluation)) + // accumulator_2 = -[1].(batch_evaluation) + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + if iszero(success) { + mstore(0x0, OPENING_COMMITMENT_FAILED_SELECTOR) + revert(0x00, 0x04) + } + } + + /** + * PERFORM PAIRING PREAMBLE + */ + { + let u := mload(C_U_LOC) + let zeta := mload(C_ZETA_LOC) + // VALIDATE PI_Z + { + let x := mload(PI_Z_X_LOC) + let y := mload(PI_Z_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + // compute zeta.[PI_Z] and add into accumulator + mstore(0x40, zeta) + success := staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE PI_Z_OMEGA + { + let x := mload(PI_Z_OMEGA_X_LOC) + let y := mload(PI_Z_OMEGA_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(mulmod(u, zeta, p), mload(OMEGA_LOC), p)) + // accumulator_2 = u.zeta.omega.[PI_Z_OMEGA] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // PAIRING_RHS = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, PAIRING_RHS_X_LOC, 0x40)) + + mstore(0x00, mload(PI_Z_X_LOC)) + mstore(0x20, mload(PI_Z_Y_LOC)) + mstore(0x40, mload(PI_Z_OMEGA_X_LOC)) + mstore(0x60, mload(PI_Z_OMEGA_Y_LOC)) + mstore(0x80, u) + success := and(success, staticcall(gas(), 7, 0x40, 0x60, 0x40, 0x40)) + // PAIRING_LHS = [PI_Z] + [PI_Z_OMEGA] * u + success := and(success, staticcall(gas(), 6, 0x00, 0x80, PAIRING_LHS_X_LOC, 0x40)) + // negate lhs y-coordinate + mstore(PAIRING_LHS_Y_LOC, sub(q, mload(PAIRING_LHS_Y_LOC))) + + if mload(CONTAINS_RECURSIVE_PROOF_LOC) { + // VALIDATE RECURSIVE P1 + { + let x := mload(RECURSIVE_P1_X_LOC) + let y := mload(RECURSIVE_P1_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + + // compute u.u.[recursive_p1] and write into 0x60 + mstore(0x40, mulmod(u, u, p)) + success := and(success, staticcall(gas(), 7, 0x00, 0x60, 0x60, 0x40)) + // VALIDATE RECURSIVE P2 + { + let x := mload(RECURSIVE_P2_X_LOC) + let y := mload(RECURSIVE_P2_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + // compute u.u.[recursive_p2] and write into 0x00 + // 0x40 still contains u*u + success := and(success, staticcall(gas(), 7, 0x00, 0x60, 0x00, 0x40)) + + // compute u.u.[recursiveP1] + rhs and write into rhs + mstore(0xa0, mload(PAIRING_RHS_X_LOC)) + mstore(0xc0, mload(PAIRING_RHS_Y_LOC)) + success := and(success, staticcall(gas(), 6, 0x60, 0x80, PAIRING_RHS_X_LOC, 0x40)) + + // compute u.u.[recursiveP2] + lhs and write into lhs + mstore(0x40, mload(PAIRING_LHS_X_LOC)) + mstore(0x60, mload(PAIRING_LHS_Y_LOC)) + success := and(success, staticcall(gas(), 6, 0x00, 0x80, PAIRING_LHS_X_LOC, 0x40)) + } + + if iszero(success) { + mstore(0x0, PAIRING_PREAMBLE_FAILED_SELECTOR) + revert(0x00, 0x04) + } + } + + /** + * PERFORM PAIRING + */ + { + // rhs paired with [1]_2 + // lhs paired with [x]_2 + + mstore(0x00, mload(PAIRING_RHS_X_LOC)) + mstore(0x20, mload(PAIRING_RHS_Y_LOC)) + mstore(0x40, 0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2) // this is [1]_2 + mstore(0x60, 0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed) + mstore(0x80, 0x090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b) + mstore(0xa0, 0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa) + + mstore(0xc0, mload(PAIRING_LHS_X_LOC)) + mstore(0xe0, mload(PAIRING_LHS_Y_LOC)) + mstore(0x100, mload(G2X_X0_LOC)) + mstore(0x120, mload(G2X_X1_LOC)) + mstore(0x140, mload(G2X_Y0_LOC)) + mstore(0x160, mload(G2X_Y1_LOC)) + + success := staticcall(gas(), 8, 0x00, 0x180, 0x00, 0x20) + if iszero(and(success, mload(0x00))) { + mstore(0x0, PAIRING_FAILED_SELECTOR) + revert(0x00, 0x04) + } + } + + { + mstore(0x00, 0x01) + return(0x00, 0x20) // Proof succeeded! + } + } + } +} + +contract UltraVerifier is BaseUltraVerifier { + function getVerificationKeyHash() public pure override(BaseUltraVerifier) returns (bytes32) { + return UltraVerificationKey.verificationKeyHash(); + } + + function loadVerificationKey(uint256 vk, uint256 _omegaInverseLoc) internal pure virtual override(BaseUltraVerifier) { + UltraVerificationKey.loadVerificationKey(vk, _omegaInverseLoc); + } +} diff --git a/noir/noir-repo/compiler/integration-tests/contracts/recursion.sol b/noir/noir-repo/compiler/integration-tests/contracts/recursion.sol new file mode 100644 index 000000000000..abb5529f12ed --- /dev/null +++ b/noir/noir-repo/compiler/integration-tests/contracts/recursion.sol @@ -0,0 +1,2869 @@ +// Verification Key Hash: e0328cb05dead618095601e226cdeb6dbc39366658b78fabcb8b4d79b64150fe +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2022 Aztec +pragma solidity >=0.8.4; + +library UltraVerificationKey { + function verificationKeyHash() internal pure returns(bytes32) { + return 0xe0328cb05dead618095601e226cdeb6dbc39366658b78fabcb8b4d79b64150fe; + } + + function loadVerificationKey(uint256 _vk, uint256 _omegaInverseLoc) internal pure { + assembly { + mstore(add(_vk, 0x00), 0x0000000000000000000000000000000000000000000000000000000000040000) // vk.circuit_size + mstore(add(_vk, 0x20), 0x0000000000000000000000000000000000000000000000000000000000000010) // vk.num_inputs + mstore(add(_vk, 0x40), 0x19ddbcaf3a8d46c15c0176fbb5b95e4dc57088ff13f4d1bd84c6bfa57dcdc0e0) // vk.work_root + mstore(add(_vk, 0x60), 0x30644259cd94e7dd5045d7a27013b7fcd21c9e3b7fa75222e7bda49b729b0401) // vk.domain_inverse + mstore(add(_vk, 0x80), 0x296cf46c4f739702b3432a7e00d817fd408d994c86c7b2a3d111e60216220ff4) // vk.Q1.x + mstore(add(_vk, 0xa0), 0x23eb5e8befe06db56c45cacc7f6ebe1c5a6d564eacd9ce398f5512f78716db2f) // vk.Q1.y + mstore(add(_vk, 0xc0), 0x1343a11edd4c8f943d25b149f25ce46f3f3d778986116e54e46f19ecea6f222c) // vk.Q2.x + mstore(add(_vk, 0xe0), 0x21465130765a50d22ae703a7f04f1c56d702a1fd8e60ef7ab8643e7d65400d4a) // vk.Q2.y + mstore(add(_vk, 0x100), 0x14ca6d2277d046bfec277680aaef68c036229345162dc5898d4c59c48af3050c) // vk.Q3.x + mstore(add(_vk, 0x120), 0x0193076249ef903f84326def1f71f3e0f8964d6ad9b8169b10373534c5d8ce3a) // vk.Q3.y + mstore(add(_vk, 0x140), 0x19b321f51f228bda6233253f630bd7a4ef8886b0b0b04b8aa5dae7de26262741) // vk.Q4.x + mstore(add(_vk, 0x160), 0x29e642b2b28bb28117bf91a05f4072be4aa7b9e461a30a8b512c9ce550b8bd11) // vk.Q4.y + mstore(add(_vk, 0x180), 0x135c2b4ca117cad1e6de43b35922898f10a215ca4bd212fb235b11f749747a40) // vk.Q_M.x + mstore(add(_vk, 0x1a0), 0x1b5898cbfad83193f396baa1b97d270788e813afeb2a55342f4e01118d7c8d52) // vk.Q_M.y + mstore(add(_vk, 0x1c0), 0x22b15c7b21212709f0670cb679b2f9983b0624880388177e34194a86a8beeec4) // vk.Q_C.x + mstore(add(_vk, 0x1e0), 0x23abf1bb3ae5b994d972821a588c2a181d6f73b19cd63eb97ba3d279280c8d89) // vk.Q_C.y + mstore(add(_vk, 0x200), 0x113b6d3105a628cbad57a3e0d3af01035264182e3730b1e09ec465456c93e237) // vk.Q_ARITHMETIC.x + mstore(add(_vk, 0x220), 0x144c2223ed41c781c7e91e392a785122901565726d0733d1f85d715cf72f46c7) // vk.Q_ARITHMETIC.y + mstore(add(_vk, 0x240), 0x2ef5ddac9f6900407cb286d52468a09ed415e365b5086f5c9b74b4f281c61054) // vk.QSORT.x + mstore(add(_vk, 0x260), 0x010674e24f29b69a54da15ac59911e89cf3fa787ed2cad6a44daa63c67d00fd7) // vk.QSORT.y + mstore(add(_vk, 0x280), 0x26ba1f4d0e050a78621b511228a9c6983f7868dde8d03a3206ba8ecb4745228c) // vk.Q_ELLIPTIC.x + mstore(add(_vk, 0x2a0), 0x00e496fbcd18c30efca8bbab288382270e7c1ca730a6de1c97f1fdb8e8cbb8ae) // vk.Q_ELLIPTIC.y + mstore(add(_vk, 0x2c0), 0x12f33eb7f1ef14f7b9c5eef6fda9e8b915b1505a9fc4fddbe85273bab940215d) // vk.Q_AUX.x + mstore(add(_vk, 0x2e0), 0x0243ce5ba21f31b237dca7bb13bb6552da8e193324813b7269b144f5fc4bb571) // vk.Q_AUX.y + mstore(add(_vk, 0x300), 0x08ba0b0a65af34cf8d99b68d5a1f8ff614a3d2f2b79feeb798b1167cc9a38cc9) // vk.SIGMA1.x + mstore(add(_vk, 0x320), 0x150a1dbd173563cdd0503776c3d59e91d6e78c1f1e6d23785f9da5843b27fc60) // vk.SIGMA1.y + mstore(add(_vk, 0x340), 0x2495d18a5ab5b8e3a2f6f9888d92d349362dde30734049dccc6fa6e07d903231) // vk.SIGMA2.x + mstore(add(_vk, 0x360), 0x0823530dc06e55a763f9a51db768d4bc53ebec26334b3e9d248235e7972624c6) // vk.SIGMA2.y + mstore(add(_vk, 0x380), 0x15b6c07df0304bc78711f6f924f040f63c0a1e6174d1bc4bb20c5cf93444d239) // vk.SIGMA3.x + mstore(add(_vk, 0x3a0), 0x1c7932ed2c40d035d67e80599df3f127fd408c30af2f5dd14805dd5816715881) // vk.SIGMA3.y + mstore(add(_vk, 0x3c0), 0x2644c0b211b5bc8160034e9b4948392266e615c101df2306a82bc2f99ceb2357) // vk.SIGMA4.x + mstore(add(_vk, 0x3e0), 0x245551ceeed8c044a968549997e4d89071e9d65cd887afe82835c4b05394c8dd) // vk.SIGMA4.y + mstore(add(_vk, 0x400), 0x09796190fd3ba909c6530c89811df9b5b4f5f2fe6501ec21dd864b20673fc02c) // vk.TABLE1.x + mstore(add(_vk, 0x420), 0x00b9c2423e310caa43e1eb83b55f53977fccbed85422df8935635d77d146bf39) // vk.TABLE1.y + mstore(add(_vk, 0x440), 0x217dad26ccc0c543ec5750513e9365a5cae8164b08d364efcf4b5890ff05f334) // vk.TABLE2.x + mstore(add(_vk, 0x460), 0x1db28433f6bde424423f3587787f81c48101d2dc6e54b431332cb275f8518c62) // vk.TABLE2.y + mstore(add(_vk, 0x480), 0x2cc2d90f2da7f4ec16b7fe61babd4fb9b580ecff03c471764dd67a8c433afab5) // vk.TABLE3.x + mstore(add(_vk, 0x4a0), 0x3032b9ff096a43ce326cc63ffc6a86dcb913fb1f7700939f5304f6c6beb24574) // vk.TABLE3.y + mstore(add(_vk, 0x4c0), 0x1f4c58502ca713ed0bffb4ff31ed55e557e83a37d31b8e703aa9219d6158e2d2) // vk.TABLE4.x + mstore(add(_vk, 0x4e0), 0x0b0d5ed5432c5e7b56344c1d26ce0d9f632e8f8aa52505d6c89f6da89f357fa8) // vk.TABLE4.y + mstore(add(_vk, 0x500), 0x18f58f41d54253e53e11e950a30712a53ac21c410a53424cf08b5c866aa18ef7) // vk.TABLE_TYPE.x + mstore(add(_vk, 0x520), 0x085b844a9b90e6d79f01271644b9cbc23f81cccb1679ddb7c4cf28f525ff41ad) // vk.TABLE_TYPE.y + mstore(add(_vk, 0x540), 0x1409fc0d97f2c216efc3538236ffa767e74c140c918e041cd17029a30a4a9d44) // vk.ID1.x + mstore(add(_vk, 0x560), 0x26c5c627007675f6a57449fe0df318783b14e9abcf70ff93026059d76f6b9cd7) // vk.ID1.y + mstore(add(_vk, 0x580), 0x2c14b2eb3d66e1ad2ab2f3f572c788cc7fc3c5de27f10dc4b03fb8d24d99a100) // vk.ID2.x + mstore(add(_vk, 0x5a0), 0x12fb35d49297144b9c18d4fedadb24ecaf825a0b16f15429880254c021b848d3) // vk.ID2.y + mstore(add(_vk, 0x5c0), 0x09cd56d13b51b36941752c549fcbf0f91175759cd433aa663380ff74eea969bb) // vk.ID3.x + mstore(add(_vk, 0x5e0), 0x0a8120bced78e668891c2b79e4098b73357660d7ac5d18c38692b82fae92ceae) // vk.ID3.y + mstore(add(_vk, 0x600), 0x23a22f97c87c77b7ec20064f688ad1d82994517560d78cc0366cbaa3ad0fe931) // vk.ID4.x + mstore(add(_vk, 0x620), 0x08d8108812baa0e234edc5109ec726f19dc6efd247eea7d61930f0857844dba1) // vk.ID4.y + mstore(add(_vk, 0x640), 0x01) // vk.contains_recursive_proof + mstore(add(_vk, 0x660), 0) // vk.recursive_proof_public_input_indices + mstore(add(_vk, 0x680), 0x260e01b251f6f1c7e7ff4e580791dee8ea51d87a358e038b4efe30fac09383c1) // vk.g2_x.X.c1 + mstore(add(_vk, 0x6a0), 0x0118c4d5b837bcc2bc89b5b398b5974e9f5944073b32078b7e231fec938883b0) // vk.g2_x.X.c0 + mstore(add(_vk, 0x6c0), 0x04fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe4) // vk.g2_x.Y.c1 + mstore(add(_vk, 0x6e0), 0x22febda3c0c0632a56475b4214e5615e11e6dd3f96e6cea2854a87d4dacc5e55) // vk.g2_x.Y.c0 + mstore(_omegaInverseLoc, 0x036853f083780e87f8d7c71d111119c57dbe118c22d5ad707a82317466c5174c) // vk.work_root_inverse + } + } +} + +/** + * @title Ultra Plonk proof verification contract + * @dev Top level Plonk proof verification contract, which allows Plonk proof to be verified + */ +abstract contract BaseUltraVerifier { + // VERIFICATION KEY MEMORY LOCATIONS + uint256 internal constant N_LOC = 0x380; + uint256 internal constant NUM_INPUTS_LOC = 0x3a0; + uint256 internal constant OMEGA_LOC = 0x3c0; + uint256 internal constant DOMAIN_INVERSE_LOC = 0x3e0; + uint256 internal constant Q1_X_LOC = 0x400; + uint256 internal constant Q1_Y_LOC = 0x420; + uint256 internal constant Q2_X_LOC = 0x440; + uint256 internal constant Q2_Y_LOC = 0x460; + uint256 internal constant Q3_X_LOC = 0x480; + uint256 internal constant Q3_Y_LOC = 0x4a0; + uint256 internal constant Q4_X_LOC = 0x4c0; + uint256 internal constant Q4_Y_LOC = 0x4e0; + uint256 internal constant QM_X_LOC = 0x500; + uint256 internal constant QM_Y_LOC = 0x520; + uint256 internal constant QC_X_LOC = 0x540; + uint256 internal constant QC_Y_LOC = 0x560; + uint256 internal constant QARITH_X_LOC = 0x580; + uint256 internal constant QARITH_Y_LOC = 0x5a0; + uint256 internal constant QSORT_X_LOC = 0x5c0; + uint256 internal constant QSORT_Y_LOC = 0x5e0; + uint256 internal constant QELLIPTIC_X_LOC = 0x600; + uint256 internal constant QELLIPTIC_Y_LOC = 0x620; + uint256 internal constant QAUX_X_LOC = 0x640; + uint256 internal constant QAUX_Y_LOC = 0x660; + uint256 internal constant SIGMA1_X_LOC = 0x680; + uint256 internal constant SIGMA1_Y_LOC = 0x6a0; + uint256 internal constant SIGMA2_X_LOC = 0x6c0; + uint256 internal constant SIGMA2_Y_LOC = 0x6e0; + uint256 internal constant SIGMA3_X_LOC = 0x700; + uint256 internal constant SIGMA3_Y_LOC = 0x720; + uint256 internal constant SIGMA4_X_LOC = 0x740; + uint256 internal constant SIGMA4_Y_LOC = 0x760; + uint256 internal constant TABLE1_X_LOC = 0x780; + uint256 internal constant TABLE1_Y_LOC = 0x7a0; + uint256 internal constant TABLE2_X_LOC = 0x7c0; + uint256 internal constant TABLE2_Y_LOC = 0x7e0; + uint256 internal constant TABLE3_X_LOC = 0x800; + uint256 internal constant TABLE3_Y_LOC = 0x820; + uint256 internal constant TABLE4_X_LOC = 0x840; + uint256 internal constant TABLE4_Y_LOC = 0x860; + uint256 internal constant TABLE_TYPE_X_LOC = 0x880; + uint256 internal constant TABLE_TYPE_Y_LOC = 0x8a0; + uint256 internal constant ID1_X_LOC = 0x8c0; + uint256 internal constant ID1_Y_LOC = 0x8e0; + uint256 internal constant ID2_X_LOC = 0x900; + uint256 internal constant ID2_Y_LOC = 0x920; + uint256 internal constant ID3_X_LOC = 0x940; + uint256 internal constant ID3_Y_LOC = 0x960; + uint256 internal constant ID4_X_LOC = 0x980; + uint256 internal constant ID4_Y_LOC = 0x9a0; + uint256 internal constant CONTAINS_RECURSIVE_PROOF_LOC = 0x9c0; + uint256 internal constant RECURSIVE_PROOF_PUBLIC_INPUT_INDICES_LOC = 0x9e0; + uint256 internal constant G2X_X0_LOC = 0xa00; + uint256 internal constant G2X_X1_LOC = 0xa20; + uint256 internal constant G2X_Y0_LOC = 0xa40; + uint256 internal constant G2X_Y1_LOC = 0xa60; + + // ### PROOF DATA MEMORY LOCATIONS + uint256 internal constant W1_X_LOC = 0x1200; + uint256 internal constant W1_Y_LOC = 0x1220; + uint256 internal constant W2_X_LOC = 0x1240; + uint256 internal constant W2_Y_LOC = 0x1260; + uint256 internal constant W3_X_LOC = 0x1280; + uint256 internal constant W3_Y_LOC = 0x12a0; + uint256 internal constant W4_X_LOC = 0x12c0; + uint256 internal constant W4_Y_LOC = 0x12e0; + uint256 internal constant S_X_LOC = 0x1300; + uint256 internal constant S_Y_LOC = 0x1320; + uint256 internal constant Z_X_LOC = 0x1340; + uint256 internal constant Z_Y_LOC = 0x1360; + uint256 internal constant Z_LOOKUP_X_LOC = 0x1380; + uint256 internal constant Z_LOOKUP_Y_LOC = 0x13a0; + uint256 internal constant T1_X_LOC = 0x13c0; + uint256 internal constant T1_Y_LOC = 0x13e0; + uint256 internal constant T2_X_LOC = 0x1400; + uint256 internal constant T2_Y_LOC = 0x1420; + uint256 internal constant T3_X_LOC = 0x1440; + uint256 internal constant T3_Y_LOC = 0x1460; + uint256 internal constant T4_X_LOC = 0x1480; + uint256 internal constant T4_Y_LOC = 0x14a0; + + uint256 internal constant W1_EVAL_LOC = 0x1600; + uint256 internal constant W2_EVAL_LOC = 0x1620; + uint256 internal constant W3_EVAL_LOC = 0x1640; + uint256 internal constant W4_EVAL_LOC = 0x1660; + uint256 internal constant S_EVAL_LOC = 0x1680; + uint256 internal constant Z_EVAL_LOC = 0x16a0; + uint256 internal constant Z_LOOKUP_EVAL_LOC = 0x16c0; + uint256 internal constant Q1_EVAL_LOC = 0x16e0; + uint256 internal constant Q2_EVAL_LOC = 0x1700; + uint256 internal constant Q3_EVAL_LOC = 0x1720; + uint256 internal constant Q4_EVAL_LOC = 0x1740; + uint256 internal constant QM_EVAL_LOC = 0x1760; + uint256 internal constant QC_EVAL_LOC = 0x1780; + uint256 internal constant QARITH_EVAL_LOC = 0x17a0; + uint256 internal constant QSORT_EVAL_LOC = 0x17c0; + uint256 internal constant QELLIPTIC_EVAL_LOC = 0x17e0; + uint256 internal constant QAUX_EVAL_LOC = 0x1800; + uint256 internal constant TABLE1_EVAL_LOC = 0x1840; + uint256 internal constant TABLE2_EVAL_LOC = 0x1860; + uint256 internal constant TABLE3_EVAL_LOC = 0x1880; + uint256 internal constant TABLE4_EVAL_LOC = 0x18a0; + uint256 internal constant TABLE_TYPE_EVAL_LOC = 0x18c0; + uint256 internal constant ID1_EVAL_LOC = 0x18e0; + uint256 internal constant ID2_EVAL_LOC = 0x1900; + uint256 internal constant ID3_EVAL_LOC = 0x1920; + uint256 internal constant ID4_EVAL_LOC = 0x1940; + uint256 internal constant SIGMA1_EVAL_LOC = 0x1960; + uint256 internal constant SIGMA2_EVAL_LOC = 0x1980; + uint256 internal constant SIGMA3_EVAL_LOC = 0x19a0; + uint256 internal constant SIGMA4_EVAL_LOC = 0x19c0; + uint256 internal constant W1_OMEGA_EVAL_LOC = 0x19e0; + uint256 internal constant W2_OMEGA_EVAL_LOC = 0x2000; + uint256 internal constant W3_OMEGA_EVAL_LOC = 0x2020; + uint256 internal constant W4_OMEGA_EVAL_LOC = 0x2040; + uint256 internal constant S_OMEGA_EVAL_LOC = 0x2060; + uint256 internal constant Z_OMEGA_EVAL_LOC = 0x2080; + uint256 internal constant Z_LOOKUP_OMEGA_EVAL_LOC = 0x20a0; + uint256 internal constant TABLE1_OMEGA_EVAL_LOC = 0x20c0; + uint256 internal constant TABLE2_OMEGA_EVAL_LOC = 0x20e0; + uint256 internal constant TABLE3_OMEGA_EVAL_LOC = 0x2100; + uint256 internal constant TABLE4_OMEGA_EVAL_LOC = 0x2120; + + uint256 internal constant PI_Z_X_LOC = 0x2300; + uint256 internal constant PI_Z_Y_LOC = 0x2320; + uint256 internal constant PI_Z_OMEGA_X_LOC = 0x2340; + uint256 internal constant PI_Z_OMEGA_Y_LOC = 0x2360; + + // Used for elliptic widget. These are alias names for wire + shifted wire evaluations + uint256 internal constant X1_EVAL_LOC = W2_EVAL_LOC; + uint256 internal constant X2_EVAL_LOC = W1_OMEGA_EVAL_LOC; + uint256 internal constant X3_EVAL_LOC = W2_OMEGA_EVAL_LOC; + uint256 internal constant Y1_EVAL_LOC = W3_EVAL_LOC; + uint256 internal constant Y2_EVAL_LOC = W4_OMEGA_EVAL_LOC; + uint256 internal constant Y3_EVAL_LOC = W3_OMEGA_EVAL_LOC; + uint256 internal constant QBETA_LOC = Q3_EVAL_LOC; + uint256 internal constant QBETA_SQR_LOC = Q4_EVAL_LOC; + uint256 internal constant QSIGN_LOC = Q1_EVAL_LOC; + + // ### CHALLENGES MEMORY OFFSETS + + uint256 internal constant C_BETA_LOC = 0x2600; + uint256 internal constant C_GAMMA_LOC = 0x2620; + uint256 internal constant C_ALPHA_LOC = 0x2640; + uint256 internal constant C_ETA_LOC = 0x2660; + uint256 internal constant C_ETA_SQR_LOC = 0x2680; + uint256 internal constant C_ETA_CUBE_LOC = 0x26a0; + + uint256 internal constant C_ZETA_LOC = 0x26c0; + uint256 internal constant C_CURRENT_LOC = 0x26e0; + uint256 internal constant C_V0_LOC = 0x2700; + uint256 internal constant C_V1_LOC = 0x2720; + uint256 internal constant C_V2_LOC = 0x2740; + uint256 internal constant C_V3_LOC = 0x2760; + uint256 internal constant C_V4_LOC = 0x2780; + uint256 internal constant C_V5_LOC = 0x27a0; + uint256 internal constant C_V6_LOC = 0x27c0; + uint256 internal constant C_V7_LOC = 0x27e0; + uint256 internal constant C_V8_LOC = 0x2800; + uint256 internal constant C_V9_LOC = 0x2820; + uint256 internal constant C_V10_LOC = 0x2840; + uint256 internal constant C_V11_LOC = 0x2860; + uint256 internal constant C_V12_LOC = 0x2880; + uint256 internal constant C_V13_LOC = 0x28a0; + uint256 internal constant C_V14_LOC = 0x28c0; + uint256 internal constant C_V15_LOC = 0x28e0; + uint256 internal constant C_V16_LOC = 0x2900; + uint256 internal constant C_V17_LOC = 0x2920; + uint256 internal constant C_V18_LOC = 0x2940; + uint256 internal constant C_V19_LOC = 0x2960; + uint256 internal constant C_V20_LOC = 0x2980; + uint256 internal constant C_V21_LOC = 0x29a0; + uint256 internal constant C_V22_LOC = 0x29c0; + uint256 internal constant C_V23_LOC = 0x29e0; + uint256 internal constant C_V24_LOC = 0x2a00; + uint256 internal constant C_V25_LOC = 0x2a20; + uint256 internal constant C_V26_LOC = 0x2a40; + uint256 internal constant C_V27_LOC = 0x2a60; + uint256 internal constant C_V28_LOC = 0x2a80; + uint256 internal constant C_V29_LOC = 0x2aa0; + uint256 internal constant C_V30_LOC = 0x2ac0; + + uint256 internal constant C_U_LOC = 0x2b00; + + // ### LOCAL VARIABLES MEMORY OFFSETS + uint256 internal constant DELTA_NUMERATOR_LOC = 0x3000; + uint256 internal constant DELTA_DENOMINATOR_LOC = 0x3020; + uint256 internal constant ZETA_POW_N_LOC = 0x3040; + uint256 internal constant PUBLIC_INPUT_DELTA_LOC = 0x3060; + uint256 internal constant ZERO_POLY_LOC = 0x3080; + uint256 internal constant L_START_LOC = 0x30a0; + uint256 internal constant L_END_LOC = 0x30c0; + uint256 internal constant R_ZERO_EVAL_LOC = 0x30e0; + + uint256 internal constant PLOOKUP_DELTA_NUMERATOR_LOC = 0x3100; + uint256 internal constant PLOOKUP_DELTA_DENOMINATOR_LOC = 0x3120; + uint256 internal constant PLOOKUP_DELTA_LOC = 0x3140; + + uint256 internal constant ACCUMULATOR_X_LOC = 0x3160; + uint256 internal constant ACCUMULATOR_Y_LOC = 0x3180; + uint256 internal constant ACCUMULATOR2_X_LOC = 0x31a0; + uint256 internal constant ACCUMULATOR2_Y_LOC = 0x31c0; + uint256 internal constant PAIRING_LHS_X_LOC = 0x31e0; + uint256 internal constant PAIRING_LHS_Y_LOC = 0x3200; + uint256 internal constant PAIRING_RHS_X_LOC = 0x3220; + uint256 internal constant PAIRING_RHS_Y_LOC = 0x3240; + + // misc stuff + uint256 internal constant OMEGA_INVERSE_LOC = 0x3300; + uint256 internal constant C_ALPHA_SQR_LOC = 0x3320; + uint256 internal constant C_ALPHA_CUBE_LOC = 0x3340; + uint256 internal constant C_ALPHA_QUAD_LOC = 0x3360; + uint256 internal constant C_ALPHA_BASE_LOC = 0x3380; + + // ### RECURSION VARIABLE MEMORY LOCATIONS + uint256 internal constant RECURSIVE_P1_X_LOC = 0x3400; + uint256 internal constant RECURSIVE_P1_Y_LOC = 0x3420; + uint256 internal constant RECURSIVE_P2_X_LOC = 0x3440; + uint256 internal constant RECURSIVE_P2_Y_LOC = 0x3460; + uint256 internal constant PUBLIC_INPUTS_HASH_LOCATION = 0x3480; + + // sub-identity storage + uint256 internal constant PERMUTATION_IDENTITY = 0x3500; + uint256 internal constant PLOOKUP_IDENTITY = 0x3520; + uint256 internal constant ARITHMETIC_IDENTITY = 0x3540; + uint256 internal constant SORT_IDENTITY = 0x3560; + uint256 internal constant ELLIPTIC_IDENTITY = 0x3580; + uint256 internal constant AUX_IDENTITY = 0x35a0; + uint256 internal constant AUX_NON_NATIVE_FIELD_EVALUATION = 0x35c0; + uint256 internal constant AUX_LIMB_ACCUMULATOR_EVALUATION = 0x35e0; + uint256 internal constant AUX_RAM_CONSISTENCY_EVALUATION = 0x3600; + uint256 internal constant AUX_ROM_CONSISTENCY_EVALUATION = 0x3620; + uint256 internal constant AUX_MEMORY_EVALUATION = 0x3640; + + uint256 internal constant QUOTIENT_EVAL_LOC = 0x3660; + uint256 internal constant ZERO_POLY_INVERSE_LOC = 0x3680; + + // when hashing public inputs we use memory at NU_CHALLENGE_INPUT_LOC_A, as the hash input size is unknown at compile time + uint256 internal constant NU_CHALLENGE_INPUT_LOC_A = 0x36a0; + uint256 internal constant NU_CHALLENGE_INPUT_LOC_B = 0x36c0; + uint256 internal constant NU_CHALLENGE_INPUT_LOC_C = 0x36e0; + + bytes4 internal constant INVALID_VERIFICATION_KEY_SELECTOR = 0x7e5769bf; + bytes4 internal constant POINT_NOT_ON_CURVE_SELECTOR = 0xa3dad654; + bytes4 internal constant PUBLIC_INPUT_INVALID_BN128_G1_POINT_SELECTOR = 0xeba9f4a6; + bytes4 internal constant PUBLIC_INPUT_GE_P_SELECTOR = 0x374a972f; + bytes4 internal constant MOD_EXP_FAILURE_SELECTOR = 0xf894a7bc; + bytes4 internal constant PAIRING_PREAMBLE_FAILED_SELECTOR = 0x01882d81; + bytes4 internal constant OPENING_COMMITMENT_FAILED_SELECTOR = 0x4e719763; + bytes4 internal constant PAIRING_FAILED_SELECTOR = 0xd71fd263; + + uint256 internal constant ETA_INPUT_LENGTH = 0xc0; // W1, W2, W3 = 6 * 0x20 bytes + + // We need to hash 41 field elements when generating the NU challenge + // w1, w2, w3, w4, s, z, z_lookup, q1, q2, q3, q4, qm, qc, qarith (14) + // qsort, qelliptic, qaux, sigma1, sigma2, sigma, sigma4, (7) + // table1, table2, table3, table4, tabletype, id1, id2, id3, id4, (9) + // w1_omega, w2_omega, w3_omega, w4_omega, s_omega, z_omega, z_lookup_omega, (7) + // table1_omega, table2_omega, table3_omega, table4_omega (4) + uint256 internal constant NU_INPUT_LENGTH = 0x520; // 0x520 = 41 * 0x20 + + // There are ELEVEN G1 group elements added into the transcript in the `beta` round, that we need to skip over + // W1, W2, W3, W4, S, Z, Z_LOOKUP, T1, T2, T3, T4 + uint256 internal constant NU_CALLDATA_SKIP_LENGTH = 0x2c0; // 11 * 0x40 = 0x2c0 + + uint256 internal constant NEGATIVE_INVERSE_OF_2_MODULO_P = + 0x183227397098d014dc2822db40c0ac2e9419f4243cdcb848a1f0fac9f8000000; + uint256 internal constant LIMB_SIZE = 0x100000000000000000; // 2<<68 + uint256 internal constant SUBLIMB_SHIFT = 0x4000; // 2<<14 + + // y^2 = x^3 + ax + b + // for Grumpkin, a = 0 and b = -17. We use b in a custom gate relation that evaluates elliptic curve arithmetic + uint256 internal constant GRUMPKIN_CURVE_B_PARAMETER_NEGATED = 17; + + error INVALID_VERIFICATION_KEY(); + error POINT_NOT_ON_CURVE(); + error PUBLIC_INPUT_COUNT_INVALID(uint256 expected, uint256 actual); + error PUBLIC_INPUT_INVALID_BN128_G1_POINT(); + error PUBLIC_INPUT_GE_P(); + error MOD_EXP_FAILURE(); + error PAIRING_PREAMBLE_FAILED(); + error OPENING_COMMITMENT_FAILED(); + error PAIRING_FAILED(); + + function getVerificationKeyHash() public pure virtual returns (bytes32); + + /** + * @dev We assume that the verification key loaded by this function is constant as we only verify it on deployment + */ + function loadVerificationKey(uint256 _vk, uint256 _omegaInverseLoc) internal pure virtual; + + constructor() { + loadVerificationKey(N_LOC, OMEGA_INVERSE_LOC); + + // We verify that all of the EC points in the verification key lie on the bn128 curve. + assembly { + let q := 21888242871839275222246405745257275088696311157297823662689037894645226208583 // EC group order + + let success := 1 + + // VALIDATE Q1 + { + let x := mload(Q1_X_LOC) + let y := mload(Q1_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE Q2 + { + let x := mload(Q2_X_LOC) + let y := mload(Q2_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE Q3 + { + let x := mload(Q3_X_LOC) + let y := mload(Q3_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE Q4 + { + let x := mload(Q4_X_LOC) + let y := mload(Q4_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + mstore(0x00, x) + mstore(0x20, y) + } + // VALIDATE QM + { + let x := mload(QM_X_LOC) + let y := mload(QM_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE QC + { + let x := mload(QC_X_LOC) + let y := mload(QC_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE QARITH + { + let x := mload(QARITH_X_LOC) + let y := mload(QARITH_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE QSORT + { + let x := mload(QSORT_X_LOC) + let y := mload(QSORT_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE QELLIPTIC + { + let x := mload(QELLIPTIC_X_LOC) + let y := mload(QELLIPTIC_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE QAUX + { + let x := mload(QAUX_X_LOC) + let y := mload(QAUX_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE SIGMA1 + { + let x := mload(SIGMA1_X_LOC) + let y := mload(SIGMA1_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE SIGMA2 + { + let x := mload(SIGMA2_X_LOC) + let y := mload(SIGMA2_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE SIGMA3 + { + let x := mload(SIGMA3_X_LOC) + let y := mload(SIGMA3_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE SIGMA4 + { + let x := mload(SIGMA4_X_LOC) + let y := mload(SIGMA4_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE TABLE1 + { + let x := mload(TABLE1_X_LOC) + let y := mload(TABLE1_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE TABLE2 + { + let x := mload(TABLE2_X_LOC) + let y := mload(TABLE2_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE TABLE3 + { + let x := mload(TABLE3_X_LOC) + let y := mload(TABLE3_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE TABLE4 + { + let x := mload(TABLE4_X_LOC) + let y := mload(TABLE4_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE TABLE_TYPE + { + let x := mload(TABLE_TYPE_X_LOC) + let y := mload(TABLE_TYPE_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE ID1 + { + let x := mload(ID1_X_LOC) + let y := mload(ID1_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE ID2 + { + let x := mload(ID2_X_LOC) + let y := mload(ID2_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE ID3 + { + let x := mload(ID3_X_LOC) + let y := mload(ID3_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE ID4 + { + let x := mload(ID4_X_LOC) + let y := mload(ID4_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + + if iszero(success) { + mstore(0x0, INVALID_VERIFICATION_KEY_SELECTOR) + revert(0x00, 0x04) + } + } + } + + /** + * @notice Verify a Ultra Plonk proof + * @param _proof - The serialized proof + * @param _publicInputs - An array of the public inputs + * @return True if proof is valid, reverts otherwise + */ + function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool) { + loadVerificationKey(N_LOC, OMEGA_INVERSE_LOC); + + uint256 requiredPublicInputCount; + assembly { + requiredPublicInputCount := mload(NUM_INPUTS_LOC) + } + if (requiredPublicInputCount != _publicInputs.length) { + revert PUBLIC_INPUT_COUNT_INVALID(requiredPublicInputCount, _publicInputs.length); + } + + assembly { + let q := 21888242871839275222246405745257275088696311157297823662689037894645226208583 // EC group order + let p := 21888242871839275222246405745257275088548364400416034343698204186575808495617 // Prime field order + + /** + * LOAD PROOF FROM CALLDATA + */ + { + let data_ptr := add(calldataload(0x04), 0x24) + + mstore(W1_Y_LOC, mod(calldataload(data_ptr), q)) + mstore(W1_X_LOC, mod(calldataload(add(data_ptr, 0x20)), q)) + + mstore(W2_Y_LOC, mod(calldataload(add(data_ptr, 0x40)), q)) + mstore(W2_X_LOC, mod(calldataload(add(data_ptr, 0x60)), q)) + + mstore(W3_Y_LOC, mod(calldataload(add(data_ptr, 0x80)), q)) + mstore(W3_X_LOC, mod(calldataload(add(data_ptr, 0xa0)), q)) + + mstore(W4_Y_LOC, mod(calldataload(add(data_ptr, 0xc0)), q)) + mstore(W4_X_LOC, mod(calldataload(add(data_ptr, 0xe0)), q)) + + mstore(S_Y_LOC, mod(calldataload(add(data_ptr, 0x100)), q)) + mstore(S_X_LOC, mod(calldataload(add(data_ptr, 0x120)), q)) + mstore(Z_Y_LOC, mod(calldataload(add(data_ptr, 0x140)), q)) + mstore(Z_X_LOC, mod(calldataload(add(data_ptr, 0x160)), q)) + mstore(Z_LOOKUP_Y_LOC, mod(calldataload(add(data_ptr, 0x180)), q)) + mstore(Z_LOOKUP_X_LOC, mod(calldataload(add(data_ptr, 0x1a0)), q)) + mstore(T1_Y_LOC, mod(calldataload(add(data_ptr, 0x1c0)), q)) + mstore(T1_X_LOC, mod(calldataload(add(data_ptr, 0x1e0)), q)) + + mstore(T2_Y_LOC, mod(calldataload(add(data_ptr, 0x200)), q)) + mstore(T2_X_LOC, mod(calldataload(add(data_ptr, 0x220)), q)) + + mstore(T3_Y_LOC, mod(calldataload(add(data_ptr, 0x240)), q)) + mstore(T3_X_LOC, mod(calldataload(add(data_ptr, 0x260)), q)) + + mstore(T4_Y_LOC, mod(calldataload(add(data_ptr, 0x280)), q)) + mstore(T4_X_LOC, mod(calldataload(add(data_ptr, 0x2a0)), q)) + + mstore(W1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x2c0)), p)) + mstore(W2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x2e0)), p)) + mstore(W3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x300)), p)) + mstore(W4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x320)), p)) + mstore(S_EVAL_LOC, mod(calldataload(add(data_ptr, 0x340)), p)) + mstore(Z_EVAL_LOC, mod(calldataload(add(data_ptr, 0x360)), p)) + mstore(Z_LOOKUP_EVAL_LOC, mod(calldataload(add(data_ptr, 0x380)), p)) + mstore(Q1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x3a0)), p)) + mstore(Q2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x3c0)), p)) + mstore(Q3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x3e0)), p)) + mstore(Q4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x400)), p)) + mstore(QM_EVAL_LOC, mod(calldataload(add(data_ptr, 0x420)), p)) + mstore(QC_EVAL_LOC, mod(calldataload(add(data_ptr, 0x440)), p)) + mstore(QARITH_EVAL_LOC, mod(calldataload(add(data_ptr, 0x460)), p)) + mstore(QSORT_EVAL_LOC, mod(calldataload(add(data_ptr, 0x480)), p)) + mstore(QELLIPTIC_EVAL_LOC, mod(calldataload(add(data_ptr, 0x4a0)), p)) + mstore(QAUX_EVAL_LOC, mod(calldataload(add(data_ptr, 0x4c0)), p)) + + mstore(SIGMA1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x4e0)), p)) + mstore(SIGMA2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x500)), p)) + + mstore(SIGMA3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x520)), p)) + mstore(SIGMA4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x540)), p)) + + mstore(TABLE1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x560)), p)) + mstore(TABLE2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x580)), p)) + mstore(TABLE3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x5a0)), p)) + mstore(TABLE4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x5c0)), p)) + mstore(TABLE_TYPE_EVAL_LOC, mod(calldataload(add(data_ptr, 0x5e0)), p)) + + mstore(ID1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x600)), p)) + mstore(ID2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x620)), p)) + mstore(ID3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x640)), p)) + mstore(ID4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x660)), p)) + + mstore(W1_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x680)), p)) + mstore(W2_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x6a0)), p)) + mstore(W3_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x6c0)), p)) + mstore(W4_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x6e0)), p)) + mstore(S_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x700)), p)) + + mstore(Z_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x720)), p)) + + mstore(Z_LOOKUP_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x740)), p)) + mstore(TABLE1_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x760)), p)) + mstore(TABLE2_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x780)), p)) + mstore(TABLE3_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x7a0)), p)) + mstore(TABLE4_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x7c0)), p)) + + mstore(PI_Z_Y_LOC, mod(calldataload(add(data_ptr, 0x7e0)), q)) + mstore(PI_Z_X_LOC, mod(calldataload(add(data_ptr, 0x800)), q)) + + mstore(PI_Z_OMEGA_Y_LOC, mod(calldataload(add(data_ptr, 0x820)), q)) + mstore(PI_Z_OMEGA_X_LOC, mod(calldataload(add(data_ptr, 0x840)), q)) + } + + /** + * LOAD RECURSIVE PROOF INTO MEMORY + */ + { + if mload(CONTAINS_RECURSIVE_PROOF_LOC) { + let public_inputs_ptr := add(calldataload(0x24), 0x24) + let index_counter := add(shl(5, mload(RECURSIVE_PROOF_PUBLIC_INPUT_INDICES_LOC)), public_inputs_ptr) + + let x0 := calldataload(index_counter) + x0 := add(x0, shl(68, calldataload(add(index_counter, 0x20)))) + x0 := add(x0, shl(136, calldataload(add(index_counter, 0x40)))) + x0 := add(x0, shl(204, calldataload(add(index_counter, 0x60)))) + let y0 := calldataload(add(index_counter, 0x80)) + y0 := add(y0, shl(68, calldataload(add(index_counter, 0xa0)))) + y0 := add(y0, shl(136, calldataload(add(index_counter, 0xc0)))) + y0 := add(y0, shl(204, calldataload(add(index_counter, 0xe0)))) + let x1 := calldataload(add(index_counter, 0x100)) + x1 := add(x1, shl(68, calldataload(add(index_counter, 0x120)))) + x1 := add(x1, shl(136, calldataload(add(index_counter, 0x140)))) + x1 := add(x1, shl(204, calldataload(add(index_counter, 0x160)))) + let y1 := calldataload(add(index_counter, 0x180)) + y1 := add(y1, shl(68, calldataload(add(index_counter, 0x1a0)))) + y1 := add(y1, shl(136, calldataload(add(index_counter, 0x1c0)))) + y1 := add(y1, shl(204, calldataload(add(index_counter, 0x1e0)))) + mstore(RECURSIVE_P1_X_LOC, x0) + mstore(RECURSIVE_P1_Y_LOC, y0) + mstore(RECURSIVE_P2_X_LOC, x1) + mstore(RECURSIVE_P2_Y_LOC, y1) + + // validate these are valid bn128 G1 points + if iszero(and(and(lt(x0, q), lt(x1, q)), and(lt(y0, q), lt(y1, q)))) { + mstore(0x00, PUBLIC_INPUT_INVALID_BN128_G1_POINT_SELECTOR) + revert(0x00, 0x04) + } + } + } + + { + /** + * Generate initial challenge + */ + mstore(0x00, shl(224, mload(N_LOC))) + mstore(0x04, shl(224, mload(NUM_INPUTS_LOC))) + let challenge := keccak256(0x00, 0x08) + + /** + * Generate eta challenge + */ + mstore(PUBLIC_INPUTS_HASH_LOCATION, challenge) + // The public input location is stored at 0x24, we then add 0x24 to skip selector and the length of public inputs + let public_inputs_start := add(calldataload(0x24), 0x24) + // copy the public inputs over + let public_input_size := mul(mload(NUM_INPUTS_LOC), 0x20) + calldatacopy(add(PUBLIC_INPUTS_HASH_LOCATION, 0x20), public_inputs_start, public_input_size) + + // copy W1, W2, W3 into challenge. Each point is 0x40 bytes, so load 0xc0 = 3 * 0x40 bytes (ETA input length) + let w_start := add(calldataload(0x04), 0x24) + calldatacopy(add(add(PUBLIC_INPUTS_HASH_LOCATION, 0x20), public_input_size), w_start, ETA_INPUT_LENGTH) + + // Challenge is the old challenge + public inputs + W1, W2, W3 (0x20 + public_input_size + 0xc0) + let challenge_bytes_size := add(0x20, add(public_input_size, ETA_INPUT_LENGTH)) + + challenge := keccak256(PUBLIC_INPUTS_HASH_LOCATION, challenge_bytes_size) + { + let eta := mod(challenge, p) + mstore(C_ETA_LOC, eta) + mstore(C_ETA_SQR_LOC, mulmod(eta, eta, p)) + mstore(C_ETA_CUBE_LOC, mulmod(mload(C_ETA_SQR_LOC), eta, p)) + } + + /** + * Generate beta challenge + */ + mstore(0x00, challenge) + mstore(0x20, mload(W4_Y_LOC)) + mstore(0x40, mload(W4_X_LOC)) + mstore(0x60, mload(S_Y_LOC)) + mstore(0x80, mload(S_X_LOC)) + challenge := keccak256(0x00, 0xa0) + mstore(C_BETA_LOC, mod(challenge, p)) + + /** + * Generate gamma challenge + */ + mstore(0x00, challenge) + mstore8(0x20, 0x01) + challenge := keccak256(0x00, 0x21) + mstore(C_GAMMA_LOC, mod(challenge, p)) + + /** + * Generate alpha challenge + */ + mstore(0x00, challenge) + mstore(0x20, mload(Z_Y_LOC)) + mstore(0x40, mload(Z_X_LOC)) + mstore(0x60, mload(Z_LOOKUP_Y_LOC)) + mstore(0x80, mload(Z_LOOKUP_X_LOC)) + challenge := keccak256(0x00, 0xa0) + mstore(C_ALPHA_LOC, mod(challenge, p)) + + /** + * Compute and store some powers of alpha for future computations + */ + let alpha := mload(C_ALPHA_LOC) + mstore(C_ALPHA_SQR_LOC, mulmod(alpha, alpha, p)) + mstore(C_ALPHA_CUBE_LOC, mulmod(mload(C_ALPHA_SQR_LOC), alpha, p)) + mstore(C_ALPHA_QUAD_LOC, mulmod(mload(C_ALPHA_CUBE_LOC), alpha, p)) + mstore(C_ALPHA_BASE_LOC, alpha) + + /** + * Generate zeta challenge + */ + mstore(0x00, challenge) + mstore(0x20, mload(T1_Y_LOC)) + mstore(0x40, mload(T1_X_LOC)) + mstore(0x60, mload(T2_Y_LOC)) + mstore(0x80, mload(T2_X_LOC)) + mstore(0xa0, mload(T3_Y_LOC)) + mstore(0xc0, mload(T3_X_LOC)) + mstore(0xe0, mload(T4_Y_LOC)) + mstore(0x100, mload(T4_X_LOC)) + + challenge := keccak256(0x00, 0x120) + + mstore(C_ZETA_LOC, mod(challenge, p)) + mstore(C_CURRENT_LOC, challenge) + } + + /** + * EVALUATE FIELD OPERATIONS + */ + + /** + * COMPUTE PUBLIC INPUT DELTA + * ΔPI = ∏ᵢ∈ℓ(wᵢ + β σ(i) + γ) / ∏ᵢ∈ℓ(wᵢ + β σ'(i) + γ) + */ + { + let beta := mload(C_BETA_LOC) // β + let gamma := mload(C_GAMMA_LOC) // γ + let work_root := mload(OMEGA_LOC) // ω + let numerator_value := 1 + let denominator_value := 1 + + let p_clone := p // move p to the front of the stack + let valid_inputs := true + + // Load the starting point of the public inputs (jump over the selector and the length of public inputs [0x24]) + let public_inputs_ptr := add(calldataload(0x24), 0x24) + + // endpoint_ptr = public_inputs_ptr + num_inputs * 0x20. // every public input is 0x20 bytes + let endpoint_ptr := add(public_inputs_ptr, mul(mload(NUM_INPUTS_LOC), 0x20)) + + // root_1 = β * 0x05 + let root_1 := mulmod(beta, 0x05, p_clone) // k1.β + // root_2 = β * 0x0c + let root_2 := mulmod(beta, 0x0c, p_clone) + // @note 0x05 + 0x07 == 0x0c == external coset generator + + for {} lt(public_inputs_ptr, endpoint_ptr) { public_inputs_ptr := add(public_inputs_ptr, 0x20) } { + /** + * input = public_input[i] + * valid_inputs &= input < p + * temp = input + gamma + * numerator_value *= (β.σ(i) + wᵢ + γ) // σ(i) = 0x05.ωⁱ + * denominator_value *= (β.σ'(i) + wᵢ + γ) // σ'(i) = 0x0c.ωⁱ + * root_1 *= ω + * root_2 *= ω + */ + + let input := calldataload(public_inputs_ptr) + valid_inputs := and(valid_inputs, lt(input, p_clone)) + let temp := addmod(input, gamma, p_clone) + + numerator_value := mulmod(numerator_value, add(root_1, temp), p_clone) + denominator_value := mulmod(denominator_value, add(root_2, temp), p_clone) + + root_1 := mulmod(root_1, work_root, p_clone) + root_2 := mulmod(root_2, work_root, p_clone) + } + + // Revert if not all public inputs are field elements (i.e. < p) + if iszero(valid_inputs) { + mstore(0x00, PUBLIC_INPUT_GE_P_SELECTOR) + revert(0x00, 0x04) + } + + mstore(DELTA_NUMERATOR_LOC, numerator_value) + mstore(DELTA_DENOMINATOR_LOC, denominator_value) + } + + /** + * Compute Plookup delta factor [γ(1 + β)]^{n-k} + * k = num roots cut out of Z_H = 4 + */ + { + let delta_base := mulmod(mload(C_GAMMA_LOC), addmod(mload(C_BETA_LOC), 1, p), p) + let delta_numerator := delta_base + { + let exponent := mload(N_LOC) + let count := 1 + for {} lt(count, exponent) { count := add(count, count) } { + delta_numerator := mulmod(delta_numerator, delta_numerator, p) + } + } + mstore(PLOOKUP_DELTA_NUMERATOR_LOC, delta_numerator) + + let delta_denominator := mulmod(delta_base, delta_base, p) + delta_denominator := mulmod(delta_denominator, delta_denominator, p) + mstore(PLOOKUP_DELTA_DENOMINATOR_LOC, delta_denominator) + } + /** + * Compute lagrange poly and vanishing poly fractions + */ + { + /** + * vanishing_numerator = zeta + * ZETA_POW_N = zeta^n + * vanishing_numerator -= 1 + * accumulating_root = omega_inverse + * work_root = p - accumulating_root + * domain_inverse = domain_inverse + * vanishing_denominator = zeta + work_root + * work_root *= accumulating_root + * vanishing_denominator *= (zeta + work_root) + * work_root *= accumulating_root + * vanishing_denominator *= (zeta + work_root) + * vanishing_denominator *= (zeta + (zeta + accumulating_root)) + * work_root = omega + * lagrange_numerator = vanishing_numerator * domain_inverse + * l_start_denominator = zeta - 1 + * accumulating_root = work_root^2 + * l_end_denominator = accumulating_root^2 * work_root * zeta - 1 + * Note: l_end_denominator term contains a term \omega^5 to cut out 5 roots of unity from vanishing poly + */ + + let zeta := mload(C_ZETA_LOC) + + // compute zeta^n, where n is a power of 2 + let vanishing_numerator := zeta + { + // pow_small + let exponent := mload(N_LOC) + let count := 1 + for {} lt(count, exponent) { count := add(count, count) } { + vanishing_numerator := mulmod(vanishing_numerator, vanishing_numerator, p) + } + } + mstore(ZETA_POW_N_LOC, vanishing_numerator) + vanishing_numerator := addmod(vanishing_numerator, sub(p, 1), p) + + let accumulating_root := mload(OMEGA_INVERSE_LOC) + let work_root := sub(p, accumulating_root) + let domain_inverse := mload(DOMAIN_INVERSE_LOC) + + let vanishing_denominator := addmod(zeta, work_root, p) + work_root := mulmod(work_root, accumulating_root, p) + vanishing_denominator := mulmod(vanishing_denominator, addmod(zeta, work_root, p), p) + work_root := mulmod(work_root, accumulating_root, p) + vanishing_denominator := mulmod(vanishing_denominator, addmod(zeta, work_root, p), p) + vanishing_denominator := + mulmod(vanishing_denominator, addmod(zeta, mulmod(work_root, accumulating_root, p), p), p) + + work_root := mload(OMEGA_LOC) + + let lagrange_numerator := mulmod(vanishing_numerator, domain_inverse, p) + let l_start_denominator := addmod(zeta, sub(p, 1), p) + + accumulating_root := mulmod(work_root, work_root, p) + + let l_end_denominator := + addmod( + mulmod(mulmod(mulmod(accumulating_root, accumulating_root, p), work_root, p), zeta, p), sub(p, 1), p + ) + + /** + * Compute inversions using Montgomery's batch inversion trick + */ + let accumulator := mload(DELTA_DENOMINATOR_LOC) + let t0 := accumulator + accumulator := mulmod(accumulator, vanishing_denominator, p) + let t1 := accumulator + accumulator := mulmod(accumulator, vanishing_numerator, p) + let t2 := accumulator + accumulator := mulmod(accumulator, l_start_denominator, p) + let t3 := accumulator + accumulator := mulmod(accumulator, mload(PLOOKUP_DELTA_DENOMINATOR_LOC), p) + let t4 := accumulator + { + mstore(0, 0x20) + mstore(0x20, 0x20) + mstore(0x40, 0x20) + mstore(0x60, mulmod(accumulator, l_end_denominator, p)) + mstore(0x80, sub(p, 2)) + mstore(0xa0, p) + if iszero(staticcall(gas(), 0x05, 0x00, 0xc0, 0x00, 0x20)) { + mstore(0x0, MOD_EXP_FAILURE_SELECTOR) + revert(0x00, 0x04) + } + accumulator := mload(0x00) + } + + t4 := mulmod(accumulator, t4, p) + accumulator := mulmod(accumulator, l_end_denominator, p) + + t3 := mulmod(accumulator, t3, p) + accumulator := mulmod(accumulator, mload(PLOOKUP_DELTA_DENOMINATOR_LOC), p) + + t2 := mulmod(accumulator, t2, p) + accumulator := mulmod(accumulator, l_start_denominator, p) + + t1 := mulmod(accumulator, t1, p) + accumulator := mulmod(accumulator, vanishing_numerator, p) + + t0 := mulmod(accumulator, t0, p) + accumulator := mulmod(accumulator, vanishing_denominator, p) + + accumulator := mulmod(mulmod(accumulator, accumulator, p), mload(DELTA_DENOMINATOR_LOC), p) + + mstore(PUBLIC_INPUT_DELTA_LOC, mulmod(mload(DELTA_NUMERATOR_LOC), accumulator, p)) + mstore(ZERO_POLY_LOC, mulmod(vanishing_numerator, t0, p)) + mstore(ZERO_POLY_INVERSE_LOC, mulmod(vanishing_denominator, t1, p)) + mstore(L_START_LOC, mulmod(lagrange_numerator, t2, p)) + mstore(PLOOKUP_DELTA_LOC, mulmod(mload(PLOOKUP_DELTA_NUMERATOR_LOC), t3, p)) + mstore(L_END_LOC, mulmod(lagrange_numerator, t4, p)) + } + + /** + * UltraPlonk Widget Ordering: + * + * 1. Permutation widget + * 2. Plookup widget + * 3. Arithmetic widget + * 4. Fixed base widget (?) + * 5. GenPermSort widget + * 6. Elliptic widget + * 7. Auxiliary widget + */ + + /** + * COMPUTE PERMUTATION WIDGET EVALUATION + */ + { + let alpha := mload(C_ALPHA_LOC) + let beta := mload(C_BETA_LOC) + let gamma := mload(C_GAMMA_LOC) + + /** + * t1 = (W1 + gamma + beta * ID1) * (W2 + gamma + beta * ID2) + * t2 = (W3 + gamma + beta * ID3) * (W4 + gamma + beta * ID4) + * result = alpha_base * z_eval * t1 * t2 + * t1 = (W1 + gamma + beta * sigma_1_eval) * (W2 + gamma + beta * sigma_2_eval) + * t2 = (W2 + gamma + beta * sigma_3_eval) * (W3 + gamma + beta * sigma_4_eval) + * result -= (alpha_base * z_omega_eval * t1 * t2) + */ + let t1 := + mulmod( + add(add(mload(W1_EVAL_LOC), gamma), mulmod(beta, mload(ID1_EVAL_LOC), p)), + add(add(mload(W2_EVAL_LOC), gamma), mulmod(beta, mload(ID2_EVAL_LOC), p)), + p + ) + let t2 := + mulmod( + add(add(mload(W3_EVAL_LOC), gamma), mulmod(beta, mload(ID3_EVAL_LOC), p)), + add(add(mload(W4_EVAL_LOC), gamma), mulmod(beta, mload(ID4_EVAL_LOC), p)), + p + ) + let result := mulmod(mload(C_ALPHA_BASE_LOC), mulmod(mload(Z_EVAL_LOC), mulmod(t1, t2, p), p), p) + t1 := + mulmod( + add(add(mload(W1_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA1_EVAL_LOC), p)), + add(add(mload(W2_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA2_EVAL_LOC), p)), + p + ) + t2 := + mulmod( + add(add(mload(W3_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA3_EVAL_LOC), p)), + add(add(mload(W4_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA4_EVAL_LOC), p)), + p + ) + result := + addmod( + result, + sub(p, mulmod(mload(C_ALPHA_BASE_LOC), mulmod(mload(Z_OMEGA_EVAL_LOC), mulmod(t1, t2, p), p), p)), + p + ) + + /** + * alpha_base *= alpha + * result += alpha_base . (L_{n-k}(ʓ) . (z(ʓ.ω) - ∆_{PI})) + * alpha_base *= alpha + * result += alpha_base . (L_1(ʓ)(Z(ʓ) - 1)) + * alpha_Base *= alpha + */ + mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p)) + result := + addmod( + result, + mulmod( + mload(C_ALPHA_BASE_LOC), + mulmod( + mload(L_END_LOC), + addmod(mload(Z_OMEGA_EVAL_LOC), sub(p, mload(PUBLIC_INPUT_DELTA_LOC)), p), + p + ), + p + ), + p + ) + mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p)) + mstore( + PERMUTATION_IDENTITY, + addmod( + result, + mulmod( + mload(C_ALPHA_BASE_LOC), + mulmod(mload(L_START_LOC), addmod(mload(Z_EVAL_LOC), sub(p, 1), p), p), + p + ), + p + ) + ) + mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p)) + } + + /** + * COMPUTE PLOOKUP WIDGET EVALUATION + */ + { + /** + * Goal: f = (w1(z) + q2.w1(zω)) + η(w2(z) + qm.w2(zω)) + η²(w3(z) + qc.w_3(zω)) + q3(z).η³ + * f = η.q3(z) + * f += (w3(z) + qc.w_3(zω)) + * f *= η + * f += (w2(z) + qm.w2(zω)) + * f *= η + * f += (w1(z) + q2.w1(zω)) + */ + let f := mulmod(mload(C_ETA_LOC), mload(Q3_EVAL_LOC), p) + f := + addmod(f, addmod(mload(W3_EVAL_LOC), mulmod(mload(QC_EVAL_LOC), mload(W3_OMEGA_EVAL_LOC), p), p), p) + f := mulmod(f, mload(C_ETA_LOC), p) + f := + addmod(f, addmod(mload(W2_EVAL_LOC), mulmod(mload(QM_EVAL_LOC), mload(W2_OMEGA_EVAL_LOC), p), p), p) + f := mulmod(f, mload(C_ETA_LOC), p) + f := + addmod(f, addmod(mload(W1_EVAL_LOC), mulmod(mload(Q2_EVAL_LOC), mload(W1_OMEGA_EVAL_LOC), p), p), p) + + // t(z) = table4(z).η³ + table3(z).η² + table2(z).η + table1(z) + let t := + addmod( + addmod( + addmod( + mulmod(mload(TABLE4_EVAL_LOC), mload(C_ETA_CUBE_LOC), p), + mulmod(mload(TABLE3_EVAL_LOC), mload(C_ETA_SQR_LOC), p), + p + ), + mulmod(mload(TABLE2_EVAL_LOC), mload(C_ETA_LOC), p), + p + ), + mload(TABLE1_EVAL_LOC), + p + ) + + // t(zw) = table4(zw).η³ + table3(zw).η² + table2(zw).η + table1(zw) + let t_omega := + addmod( + addmod( + addmod( + mulmod(mload(TABLE4_OMEGA_EVAL_LOC), mload(C_ETA_CUBE_LOC), p), + mulmod(mload(TABLE3_OMEGA_EVAL_LOC), mload(C_ETA_SQR_LOC), p), + p + ), + mulmod(mload(TABLE2_OMEGA_EVAL_LOC), mload(C_ETA_LOC), p), + p + ), + mload(TABLE1_OMEGA_EVAL_LOC), + p + ) + + /** + * Goal: numerator = (TABLE_TYPE_EVAL * f(z) + γ) * (t(z) + βt(zω) + γ(β + 1)) * (β + 1) + * gamma_beta_constant = γ(β + 1) + * numerator = f * TABLE_TYPE_EVAL + gamma + * temp0 = t(z) + t(zω) * β + gamma_beta_constant + * numerator *= temp0 + * numerator *= (β + 1) + * temp0 = alpha * l_1 + * numerator += temp0 + * numerator *= z_lookup(z) + * numerator -= temp0 + */ + let gamma_beta_constant := mulmod(mload(C_GAMMA_LOC), addmod(mload(C_BETA_LOC), 1, p), p) + let numerator := addmod(mulmod(f, mload(TABLE_TYPE_EVAL_LOC), p), mload(C_GAMMA_LOC), p) + let temp0 := addmod(addmod(t, mulmod(t_omega, mload(C_BETA_LOC), p), p), gamma_beta_constant, p) + numerator := mulmod(numerator, temp0, p) + numerator := mulmod(numerator, addmod(mload(C_BETA_LOC), 1, p), p) + temp0 := mulmod(mload(C_ALPHA_LOC), mload(L_START_LOC), p) + numerator := addmod(numerator, temp0, p) + numerator := mulmod(numerator, mload(Z_LOOKUP_EVAL_LOC), p) + numerator := addmod(numerator, sub(p, temp0), p) + + /** + * Goal: denominator = z_lookup(zω)*[s(z) + βs(zω) + γ(1 + β)] - [z_lookup(zω) - [γ(1 + β)]^{n-k}]*α²L_end(z) + * note: delta_factor = [γ(1 + β)]^{n-k} + * denominator = s(z) + βs(zω) + γ(β + 1) + * temp1 = α²L_end(z) + * denominator -= temp1 + * denominator *= z_lookup(zω) + * denominator += temp1 * delta_factor + * PLOOKUP_IDENTITY = (numerator - denominator).alpha_base + * alpha_base *= alpha^3 + */ + let denominator := + addmod( + addmod(mload(S_EVAL_LOC), mulmod(mload(S_OMEGA_EVAL_LOC), mload(C_BETA_LOC), p), p), + gamma_beta_constant, + p + ) + let temp1 := mulmod(mload(C_ALPHA_SQR_LOC), mload(L_END_LOC), p) + denominator := addmod(denominator, sub(p, temp1), p) + denominator := mulmod(denominator, mload(Z_LOOKUP_OMEGA_EVAL_LOC), p) + denominator := addmod(denominator, mulmod(temp1, mload(PLOOKUP_DELTA_LOC), p), p) + + mstore(PLOOKUP_IDENTITY, mulmod(addmod(numerator, sub(p, denominator), p), mload(C_ALPHA_BASE_LOC), p)) + + // update alpha + mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_CUBE_LOC), p)) + } + + /** + * COMPUTE ARITHMETIC WIDGET EVALUATION + */ + { + /** + * The basic arithmetic gate identity in standard plonk is as follows. + * (w_1 . w_2 . q_m) + (w_1 . q_1) + (w_2 . q_2) + (w_3 . q_3) + (w_4 . q_4) + q_c = 0 + * However, for Ultraplonk, we extend this to support "passing" wires between rows (shown without alpha scaling below): + * q_arith * ( ( (-1/2) * (q_arith - 3) * q_m * w_1 * w_2 + q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c ) + + * (q_arith - 1)*( α * (q_arith - 2) * (w_1 + w_4 - w_1_omega + q_m) + w_4_omega) ) = 0 + * + * This formula results in several cases depending on q_arith: + * 1. q_arith == 0: Arithmetic gate is completely disabled + * + * 2. q_arith == 1: Everything in the minigate on the right is disabled. The equation is just a standard plonk equation + * with extra wires: q_m * w_1 * w_2 + q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c = 0 + * + * 3. q_arith == 2: The (w_1 + w_4 - ...) term is disabled. THe equation is: + * (1/2) * q_m * w_1 * w_2 + q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c + w_4_omega = 0 + * It allows defining w_4 at next index (w_4_omega) in terms of current wire values + * + * 4. q_arith == 3: The product of w_1 and w_2 is disabled, but a mini addition gate is enabled. α allows us to split + * the equation into two: + * + * q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c + 2 * w_4_omega = 0 + * and + * w_1 + w_4 - w_1_omega + q_m = 0 (we are reusing q_m here) + * + * 5. q_arith > 3: The product of w_1 and w_2 is scaled by (q_arith - 3), while the w_4_omega term is scaled by (q_arith - 1). + * The equation can be split into two: + * + * (q_arith - 3)* q_m * w_1 * w_ 2 + q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c + (q_arith - 1) * w_4_omega = 0 + * and + * w_1 + w_4 - w_1_omega + q_m = 0 + * + * The problem that q_m is used both in both equations can be dealt with by appropriately changing selector values at + * the next gate. Then we can treat (q_arith - 1) as a simulated q_6 selector and scale q_m to handle (q_arith - 3) at + * product. + */ + + let w1q1 := mulmod(mload(W1_EVAL_LOC), mload(Q1_EVAL_LOC), p) + let w2q2 := mulmod(mload(W2_EVAL_LOC), mload(Q2_EVAL_LOC), p) + let w3q3 := mulmod(mload(W3_EVAL_LOC), mload(Q3_EVAL_LOC), p) + let w4q3 := mulmod(mload(W4_EVAL_LOC), mload(Q4_EVAL_LOC), p) + + // @todo - Add a explicit test that hits QARITH == 3 + // w1w2qm := (w_1 . w_2 . q_m . (QARITH_EVAL_LOC - 3)) / 2 + let w1w2qm := + mulmod( + mulmod( + mulmod(mulmod(mload(W1_EVAL_LOC), mload(W2_EVAL_LOC), p), mload(QM_EVAL_LOC), p), + addmod(mload(QARITH_EVAL_LOC), sub(p, 3), p), + p + ), + NEGATIVE_INVERSE_OF_2_MODULO_P, + p + ) + + // (w_1 . w_2 . q_m . (q_arith - 3)) / -2) + (w_1 . q_1) + (w_2 . q_2) + (w_3 . q_3) + (w_4 . q_4) + q_c + let identity := + addmod( + mload(QC_EVAL_LOC), addmod(w4q3, addmod(w3q3, addmod(w2q2, addmod(w1q1, w1w2qm, p), p), p), p), p + ) + + // if q_arith == 3 we evaluate an additional mini addition gate (on top of the regular one), where: + // w_1 + w_4 - w_1_omega + q_m = 0 + // we use this gate to save an addition gate when adding or subtracting non-native field elements + // α * (q_arith - 2) * (w_1 + w_4 - w_1_omega + q_m) + let extra_small_addition_gate_identity := + mulmod( + mload(C_ALPHA_LOC), + mulmod( + addmod(mload(QARITH_EVAL_LOC), sub(p, 2), p), + addmod( + mload(QM_EVAL_LOC), + addmod( + sub(p, mload(W1_OMEGA_EVAL_LOC)), addmod(mload(W1_EVAL_LOC), mload(W4_EVAL_LOC), p), p + ), + p + ), + p + ), + p + ) + + // if q_arith == 2 OR q_arith == 3 we add the 4th wire of the NEXT gate into the arithmetic identity + // N.B. if q_arith > 2, this wire value will be scaled by (q_arith - 1) relative to the other gate wires! + // alpha_base * q_arith * (identity + (q_arith - 1) * (w_4_omega + extra_small_addition_gate_identity)) + mstore( + ARITHMETIC_IDENTITY, + mulmod( + mload(C_ALPHA_BASE_LOC), + mulmod( + mload(QARITH_EVAL_LOC), + addmod( + identity, + mulmod( + addmod(mload(QARITH_EVAL_LOC), sub(p, 1), p), + addmod(mload(W4_OMEGA_EVAL_LOC), extra_small_addition_gate_identity, p), + p + ), + p + ), + p + ), + p + ) + ) + + // update alpha + mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_SQR_LOC), p)) + } + + /** + * COMPUTE GENPERMSORT WIDGET EVALUATION + */ + { + /** + * D1 = (w2 - w1) + * D2 = (w3 - w2) + * D3 = (w4 - w3) + * D4 = (w1_omega - w4) + * + * α_a = alpha_base + * α_b = alpha_base * α + * α_c = alpha_base * α^2 + * α_d = alpha_base * α^3 + * + * range_accumulator = ( + * D1(D1 - 1)(D1 - 2)(D1 - 3).α_a + + * D2(D2 - 1)(D2 - 2)(D2 - 3).α_b + + * D3(D3 - 1)(D3 - 2)(D3 - 3).α_c + + * D4(D4 - 1)(D4 - 2)(D4 - 3).α_d + + * ) . q_sort + */ + let minus_two := sub(p, 2) + let minus_three := sub(p, 3) + let d1 := addmod(mload(W2_EVAL_LOC), sub(p, mload(W1_EVAL_LOC)), p) + let d2 := addmod(mload(W3_EVAL_LOC), sub(p, mload(W2_EVAL_LOC)), p) + let d3 := addmod(mload(W4_EVAL_LOC), sub(p, mload(W3_EVAL_LOC)), p) + let d4 := addmod(mload(W1_OMEGA_EVAL_LOC), sub(p, mload(W4_EVAL_LOC)), p) + + let range_accumulator := + mulmod( + mulmod( + mulmod(addmod(mulmod(d1, d1, p), sub(p, d1), p), addmod(d1, minus_two, p), p), + addmod(d1, minus_three, p), + p + ), + mload(C_ALPHA_BASE_LOC), + p + ) + range_accumulator := + addmod( + range_accumulator, + mulmod( + mulmod( + mulmod(addmod(mulmod(d2, d2, p), sub(p, d2), p), addmod(d2, minus_two, p), p), + addmod(d2, minus_three, p), + p + ), + mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p), + p + ), + p + ) + range_accumulator := + addmod( + range_accumulator, + mulmod( + mulmod( + mulmod(addmod(mulmod(d3, d3, p), sub(p, d3), p), addmod(d3, minus_two, p), p), + addmod(d3, minus_three, p), + p + ), + mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_SQR_LOC), p), + p + ), + p + ) + range_accumulator := + addmod( + range_accumulator, + mulmod( + mulmod( + mulmod(addmod(mulmod(d4, d4, p), sub(p, d4), p), addmod(d4, minus_two, p), p), + addmod(d4, minus_three, p), + p + ), + mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_CUBE_LOC), p), + p + ), + p + ) + range_accumulator := mulmod(range_accumulator, mload(QSORT_EVAL_LOC), p) + + mstore(SORT_IDENTITY, range_accumulator) + + // update alpha + mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_QUAD_LOC), p)) + } + + /** + * COMPUTE ELLIPTIC WIDGET EVALUATION + */ + { + /** + * endo_term = (-x_2) * x_1 * (x_3 * 2 + x_1) * q_beta + * endo_sqr_term = x_2^2 + * endo_sqr_term *= (x_3 - x_1) + * endo_sqr_term *= q_beta^2 + * leftovers = x_2^2 + * leftovers *= x_2 + * leftovers += x_1^2 * (x_3 + x_1) @follow-up Invalid comment in BB widget + * leftovers -= (y_2^2 + y_1^2) + * sign_term = y_2 * y_1 + * sign_term += sign_term + * sign_term *= q_sign + */ + // q_elliptic * (x3 + x2 + x1)(x2 - x1)(x2 - x1) - y2^2 - y1^2 + 2(y2y1)*q_sign = 0 + let x_diff := addmod(mload(X2_EVAL_LOC), sub(p, mload(X1_EVAL_LOC)), p) + let y2_sqr := mulmod(mload(Y2_EVAL_LOC), mload(Y2_EVAL_LOC), p) + let y1_sqr := mulmod(mload(Y1_EVAL_LOC), mload(Y1_EVAL_LOC), p) + let y1y2 := mulmod(mulmod(mload(Y1_EVAL_LOC), mload(Y2_EVAL_LOC), p), mload(QSIGN_LOC), p) + + let x_add_identity := + addmod( + mulmod( + addmod(mload(X3_EVAL_LOC), addmod(mload(X2_EVAL_LOC), mload(X1_EVAL_LOC), p), p), + mulmod(x_diff, x_diff, p), + p + ), + addmod( + sub( + p, + addmod(y2_sqr, y1_sqr, p) + ), + addmod(y1y2, y1y2, p), + p + ), + p + ) + x_add_identity := + mulmod( + mulmod( + x_add_identity, + addmod( + 1, + sub(p, mload(QM_EVAL_LOC)), + p + ), + p + ), + mload(C_ALPHA_BASE_LOC), + p + ) + + // q_elliptic * (x3 + x2 + x1)(x2 - x1)(x2 - x1) - y2^2 - y1^2 + 2(y2y1)*q_sign = 0 + let y1_plus_y3 := addmod( + mload(Y1_EVAL_LOC), + mload(Y3_EVAL_LOC), + p + ) + let y_diff := addmod(mulmod(mload(Y2_EVAL_LOC), mload(QSIGN_LOC), p), sub(p, mload(Y1_EVAL_LOC)), p) + let y_add_identity := + addmod( + mulmod(y1_plus_y3, x_diff, p), + mulmod(addmod(mload(X3_EVAL_LOC), sub(p, mload(X1_EVAL_LOC)), p), y_diff, p), + p + ) + y_add_identity := + mulmod( + mulmod(y_add_identity, addmod(1, sub(p, mload(QM_EVAL_LOC)), p), p), + mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p), + p + ) + + // ELLIPTIC_IDENTITY = (x_identity + y_identity) * Q_ELLIPTIC_EVAL + mstore( + ELLIPTIC_IDENTITY, mulmod(addmod(x_add_identity, y_add_identity, p), mload(QELLIPTIC_EVAL_LOC), p) + ) + } + { + /** + * x_pow_4 = (y_1_sqr - curve_b) * x_1; + * y_1_sqr_mul_4 = y_1_sqr + y_1_sqr; + * y_1_sqr_mul_4 += y_1_sqr_mul_4; + * x_1_pow_4_mul_9 = x_pow_4; + * x_1_pow_4_mul_9 += x_1_pow_4_mul_9; + * x_1_pow_4_mul_9 += x_1_pow_4_mul_9; + * x_1_pow_4_mul_9 += x_1_pow_4_mul_9; + * x_1_pow_4_mul_9 += x_pow_4; + * x_1_sqr_mul_3 = x_1_sqr + x_1_sqr + x_1_sqr; + * x_double_identity = (x_3 + x_1 + x_1) * y_1_sqr_mul_4 - x_1_pow_4_mul_9; + * y_double_identity = x_1_sqr_mul_3 * (x_1 - x_3) - (y_1 + y_1) * (y_1 + y_3); + */ + // (x3 + x1 + x1) (4y1*y1) - 9 * x1 * x1 * x1 * x1 = 0 + let x1_sqr := mulmod(mload(X1_EVAL_LOC), mload(X1_EVAL_LOC), p) + let y1_sqr := mulmod(mload(Y1_EVAL_LOC), mload(Y1_EVAL_LOC), p) + let x_pow_4 := mulmod(addmod(y1_sqr, GRUMPKIN_CURVE_B_PARAMETER_NEGATED, p), mload(X1_EVAL_LOC), p) + let y1_sqr_mul_4 := mulmod(y1_sqr, 4, p) + let x1_pow_4_mul_9 := mulmod(x_pow_4, 9, p) + let x1_sqr_mul_3 := mulmod(x1_sqr, 3, p) + let x_double_identity := + addmod( + mulmod( + addmod(mload(X3_EVAL_LOC), addmod(mload(X1_EVAL_LOC), mload(X1_EVAL_LOC), p), p), + y1_sqr_mul_4, + p + ), + sub(p, x1_pow_4_mul_9), + p + ) + // (y1 + y1) (2y1) - (3 * x1 * x1)(x1 - x3) = 0 + let y_double_identity := + addmod( + mulmod(x1_sqr_mul_3, addmod(mload(X1_EVAL_LOC), sub(p, mload(X3_EVAL_LOC)), p), p), + sub( + p, + mulmod( + addmod(mload(Y1_EVAL_LOC), mload(Y1_EVAL_LOC), p), + addmod(mload(Y1_EVAL_LOC), mload(Y3_EVAL_LOC), p), + p + ) + ), + p + ) + x_double_identity := mulmod(x_double_identity, mload(C_ALPHA_BASE_LOC), p) + y_double_identity := + mulmod(y_double_identity, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p), p) + x_double_identity := mulmod(x_double_identity, mload(QM_EVAL_LOC), p) + y_double_identity := mulmod(y_double_identity, mload(QM_EVAL_LOC), p) + // ELLIPTIC_IDENTITY += (x_double_identity + y_double_identity) * Q_DOUBLE_EVAL + mstore( + ELLIPTIC_IDENTITY, + addmod( + mload(ELLIPTIC_IDENTITY), + mulmod(addmod(x_double_identity, y_double_identity, p), mload(QELLIPTIC_EVAL_LOC), p), + p + ) + ) + + // update alpha + mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_QUAD_LOC), p)) + } + + /** + * COMPUTE AUXILIARY WIDGET EVALUATION + */ + { + { + /** + * Non native field arithmetic gate 2 + * _ _ + * / _ _ _ 14 \ + * q_2 . q_4 | (w_1 . w_2) + (w_1 . w_2) + (w_1 . w_4 + w_2 . w_3 - w_3) . 2 - w_3 - w_4 | + * \_ _/ + * + * limb_subproduct = w_1 . w_2_omega + w_1_omega . w_2 + * non_native_field_gate_2 = w_1 * w_4 + w_4 * w_3 - w_3_omega + * non_native_field_gate_2 = non_native_field_gate_2 * limb_size + * non_native_field_gate_2 -= w_4_omega + * non_native_field_gate_2 += limb_subproduct + * non_native_field_gate_2 *= q_4 + * limb_subproduct *= limb_size + * limb_subproduct += w_1_omega * w_2_omega + * non_native_field_gate_1 = (limb_subproduct + w_3 + w_4) * q_3 + * non_native_field_gate_3 = (limb_subproduct + w_4 - (w_3_omega + w_4_omega)) * q_m + * non_native_field_identity = (non_native_field_gate_1 + non_native_field_gate_2 + non_native_field_gate_3) * q_2 + */ + + let limb_subproduct := + addmod( + mulmod(mload(W1_EVAL_LOC), mload(W2_OMEGA_EVAL_LOC), p), + mulmod(mload(W1_OMEGA_EVAL_LOC), mload(W2_EVAL_LOC), p), + p + ) + + let non_native_field_gate_2 := + addmod( + addmod( + mulmod(mload(W1_EVAL_LOC), mload(W4_EVAL_LOC), p), + mulmod(mload(W2_EVAL_LOC), mload(W3_EVAL_LOC), p), + p + ), + sub(p, mload(W3_OMEGA_EVAL_LOC)), + p + ) + non_native_field_gate_2 := mulmod(non_native_field_gate_2, LIMB_SIZE, p) + non_native_field_gate_2 := addmod(non_native_field_gate_2, sub(p, mload(W4_OMEGA_EVAL_LOC)), p) + non_native_field_gate_2 := addmod(non_native_field_gate_2, limb_subproduct, p) + non_native_field_gate_2 := mulmod(non_native_field_gate_2, mload(Q4_EVAL_LOC), p) + limb_subproduct := mulmod(limb_subproduct, LIMB_SIZE, p) + limb_subproduct := + addmod(limb_subproduct, mulmod(mload(W1_OMEGA_EVAL_LOC), mload(W2_OMEGA_EVAL_LOC), p), p) + let non_native_field_gate_1 := + mulmod( + addmod(limb_subproduct, sub(p, addmod(mload(W3_EVAL_LOC), mload(W4_EVAL_LOC), p)), p), + mload(Q3_EVAL_LOC), + p + ) + let non_native_field_gate_3 := + mulmod( + addmod( + addmod(limb_subproduct, mload(W4_EVAL_LOC), p), + sub(p, addmod(mload(W3_OMEGA_EVAL_LOC), mload(W4_OMEGA_EVAL_LOC), p)), + p + ), + mload(QM_EVAL_LOC), + p + ) + let non_native_field_identity := + mulmod( + addmod(addmod(non_native_field_gate_1, non_native_field_gate_2, p), non_native_field_gate_3, p), + mload(Q2_EVAL_LOC), + p + ) + + mstore(AUX_NON_NATIVE_FIELD_EVALUATION, non_native_field_identity) + } + + { + /** + * limb_accumulator_1 = w_2_omega; + * limb_accumulator_1 *= SUBLIMB_SHIFT; + * limb_accumulator_1 += w_1_omega; + * limb_accumulator_1 *= SUBLIMB_SHIFT; + * limb_accumulator_1 += w_3; + * limb_accumulator_1 *= SUBLIMB_SHIFT; + * limb_accumulator_1 += w_2; + * limb_accumulator_1 *= SUBLIMB_SHIFT; + * limb_accumulator_1 += w_1; + * limb_accumulator_1 -= w_4; + * limb_accumulator_1 *= q_4; + */ + let limb_accumulator_1 := mulmod(mload(W2_OMEGA_EVAL_LOC), SUBLIMB_SHIFT, p) + limb_accumulator_1 := addmod(limb_accumulator_1, mload(W1_OMEGA_EVAL_LOC), p) + limb_accumulator_1 := mulmod(limb_accumulator_1, SUBLIMB_SHIFT, p) + limb_accumulator_1 := addmod(limb_accumulator_1, mload(W3_EVAL_LOC), p) + limb_accumulator_1 := mulmod(limb_accumulator_1, SUBLIMB_SHIFT, p) + limb_accumulator_1 := addmod(limb_accumulator_1, mload(W2_EVAL_LOC), p) + limb_accumulator_1 := mulmod(limb_accumulator_1, SUBLIMB_SHIFT, p) + limb_accumulator_1 := addmod(limb_accumulator_1, mload(W1_EVAL_LOC), p) + limb_accumulator_1 := addmod(limb_accumulator_1, sub(p, mload(W4_EVAL_LOC)), p) + limb_accumulator_1 := mulmod(limb_accumulator_1, mload(Q4_EVAL_LOC), p) + + /** + * limb_accumulator_2 = w_3_omega; + * limb_accumulator_2 *= SUBLIMB_SHIFT; + * limb_accumulator_2 += w_2_omega; + * limb_accumulator_2 *= SUBLIMB_SHIFT; + * limb_accumulator_2 += w_1_omega; + * limb_accumulator_2 *= SUBLIMB_SHIFT; + * limb_accumulator_2 += w_4; + * limb_accumulator_2 *= SUBLIMB_SHIFT; + * limb_accumulator_2 += w_3; + * limb_accumulator_2 -= w_4_omega; + * limb_accumulator_2 *= q_m; + */ + let limb_accumulator_2 := mulmod(mload(W3_OMEGA_EVAL_LOC), SUBLIMB_SHIFT, p) + limb_accumulator_2 := addmod(limb_accumulator_2, mload(W2_OMEGA_EVAL_LOC), p) + limb_accumulator_2 := mulmod(limb_accumulator_2, SUBLIMB_SHIFT, p) + limb_accumulator_2 := addmod(limb_accumulator_2, mload(W1_OMEGA_EVAL_LOC), p) + limb_accumulator_2 := mulmod(limb_accumulator_2, SUBLIMB_SHIFT, p) + limb_accumulator_2 := addmod(limb_accumulator_2, mload(W4_EVAL_LOC), p) + limb_accumulator_2 := mulmod(limb_accumulator_2, SUBLIMB_SHIFT, p) + limb_accumulator_2 := addmod(limb_accumulator_2, mload(W3_EVAL_LOC), p) + limb_accumulator_2 := addmod(limb_accumulator_2, sub(p, mload(W4_OMEGA_EVAL_LOC)), p) + limb_accumulator_2 := mulmod(limb_accumulator_2, mload(QM_EVAL_LOC), p) + + mstore( + AUX_LIMB_ACCUMULATOR_EVALUATION, + mulmod(addmod(limb_accumulator_1, limb_accumulator_2, p), mload(Q3_EVAL_LOC), p) + ) + } + + { + /** + * memory_record_check = w_3; + * memory_record_check *= eta; + * memory_record_check += w_2; + * memory_record_check *= eta; + * memory_record_check += w_1; + * memory_record_check *= eta; + * memory_record_check += q_c; + * + * partial_record_check = memory_record_check; + * + * memory_record_check -= w_4; + */ + + let memory_record_check := mulmod(mload(W3_EVAL_LOC), mload(C_ETA_LOC), p) + memory_record_check := addmod(memory_record_check, mload(W2_EVAL_LOC), p) + memory_record_check := mulmod(memory_record_check, mload(C_ETA_LOC), p) + memory_record_check := addmod(memory_record_check, mload(W1_EVAL_LOC), p) + memory_record_check := mulmod(memory_record_check, mload(C_ETA_LOC), p) + memory_record_check := addmod(memory_record_check, mload(QC_EVAL_LOC), p) + + let partial_record_check := memory_record_check + memory_record_check := addmod(memory_record_check, sub(p, mload(W4_EVAL_LOC)), p) + + mstore(AUX_MEMORY_EVALUATION, memory_record_check) + + // index_delta = w_1_omega - w_1 + let index_delta := addmod(mload(W1_OMEGA_EVAL_LOC), sub(p, mload(W1_EVAL_LOC)), p) + // record_delta = w_4_omega - w_4 + let record_delta := addmod(mload(W4_OMEGA_EVAL_LOC), sub(p, mload(W4_EVAL_LOC)), p) + // index_is_monotonically_increasing = index_delta * (index_delta - 1) + let index_is_monotonically_increasing := mulmod(index_delta, addmod(index_delta, sub(p, 1), p), p) + + // adjacent_values_match_if_adjacent_indices_match = record_delta * (1 - index_delta) + let adjacent_values_match_if_adjacent_indices_match := + mulmod(record_delta, addmod(1, sub(p, index_delta), p), p) + + // AUX_ROM_CONSISTENCY_EVALUATION = ((adjacent_values_match_if_adjacent_indices_match * alpha) + index_is_monotonically_increasing) * alpha + partial_record_check + mstore( + AUX_ROM_CONSISTENCY_EVALUATION, + addmod( + mulmod( + addmod( + mulmod(adjacent_values_match_if_adjacent_indices_match, mload(C_ALPHA_LOC), p), + index_is_monotonically_increasing, + p + ), + mload(C_ALPHA_LOC), + p + ), + memory_record_check, + p + ) + ) + + { + /** + * next_gate_access_type = w_3_omega; + * next_gate_access_type *= eta; + * next_gate_access_type += w_2_omega; + * next_gate_access_type *= eta; + * next_gate_access_type += w_1_omega; + * next_gate_access_type *= eta; + * next_gate_access_type = w_4_omega - next_gate_access_type; + */ + let next_gate_access_type := mulmod(mload(W3_OMEGA_EVAL_LOC), mload(C_ETA_LOC), p) + next_gate_access_type := addmod(next_gate_access_type, mload(W2_OMEGA_EVAL_LOC), p) + next_gate_access_type := mulmod(next_gate_access_type, mload(C_ETA_LOC), p) + next_gate_access_type := addmod(next_gate_access_type, mload(W1_OMEGA_EVAL_LOC), p) + next_gate_access_type := mulmod(next_gate_access_type, mload(C_ETA_LOC), p) + next_gate_access_type := addmod(mload(W4_OMEGA_EVAL_LOC), sub(p, next_gate_access_type), p) + + // value_delta = w_3_omega - w_3 + let value_delta := addmod(mload(W3_OMEGA_EVAL_LOC), sub(p, mload(W3_EVAL_LOC)), p) + // adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation = (1 - index_delta) * value_delta * (1 - next_gate_access_type); + + let adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation := + mulmod( + addmod(1, sub(p, index_delta), p), + mulmod(value_delta, addmod(1, sub(p, next_gate_access_type), p), p), + p + ) + + // AUX_RAM_CONSISTENCY_EVALUATION + + /** + * access_type = w_4 - partial_record_check + * access_check = access_type^2 - access_type + * next_gate_access_type_is_boolean = next_gate_access_type^2 - next_gate_access_type + * RAM_consistency_check_identity = adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation; + * RAM_consistency_check_identity *= alpha; + * RAM_consistency_check_identity += index_is_monotonically_increasing; + * RAM_consistency_check_identity *= alpha; + * RAM_consistency_check_identity += next_gate_access_type_is_boolean; + * RAM_consistency_check_identity *= alpha; + * RAM_consistency_check_identity += access_check; + */ + + let access_type := addmod(mload(W4_EVAL_LOC), sub(p, partial_record_check), p) + let access_check := mulmod(access_type, addmod(access_type, sub(p, 1), p), p) + let next_gate_access_type_is_boolean := + mulmod(next_gate_access_type, addmod(next_gate_access_type, sub(p, 1), p), p) + let RAM_cci := + mulmod( + adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation, + mload(C_ALPHA_LOC), + p + ) + RAM_cci := addmod(RAM_cci, index_is_monotonically_increasing, p) + RAM_cci := mulmod(RAM_cci, mload(C_ALPHA_LOC), p) + RAM_cci := addmod(RAM_cci, next_gate_access_type_is_boolean, p) + RAM_cci := mulmod(RAM_cci, mload(C_ALPHA_LOC), p) + RAM_cci := addmod(RAM_cci, access_check, p) + + mstore(AUX_RAM_CONSISTENCY_EVALUATION, RAM_cci) + } + + { + // timestamp_delta = w_2_omega - w_2 + let timestamp_delta := addmod(mload(W2_OMEGA_EVAL_LOC), sub(p, mload(W2_EVAL_LOC)), p) + + // RAM_timestamp_check_identity = (1 - index_delta) * timestamp_delta - w_3 + let RAM_timestamp_check_identity := + addmod( + mulmod(timestamp_delta, addmod(1, sub(p, index_delta), p), p), sub(p, mload(W3_EVAL_LOC)), p + ) + + /** + * memory_identity = ROM_consistency_check_identity * q_2; + * memory_identity += RAM_timestamp_check_identity * q_4; + * memory_identity += memory_record_check * q_m; + * memory_identity *= q_1; + * memory_identity += (RAM_consistency_check_identity * q_arith); + * + * auxiliary_identity = memory_identity + non_native_field_identity + limb_accumulator_identity; + * auxiliary_identity *= q_aux; + * auxiliary_identity *= alpha_base; + */ + let memory_identity := mulmod(mload(AUX_ROM_CONSISTENCY_EVALUATION), mload(Q2_EVAL_LOC), p) + memory_identity := + addmod(memory_identity, mulmod(RAM_timestamp_check_identity, mload(Q4_EVAL_LOC), p), p) + memory_identity := + addmod(memory_identity, mulmod(mload(AUX_MEMORY_EVALUATION), mload(QM_EVAL_LOC), p), p) + memory_identity := mulmod(memory_identity, mload(Q1_EVAL_LOC), p) + memory_identity := + addmod( + memory_identity, mulmod(mload(AUX_RAM_CONSISTENCY_EVALUATION), mload(QARITH_EVAL_LOC), p), p + ) + + let auxiliary_identity := addmod(memory_identity, mload(AUX_NON_NATIVE_FIELD_EVALUATION), p) + auxiliary_identity := addmod(auxiliary_identity, mload(AUX_LIMB_ACCUMULATOR_EVALUATION), p) + auxiliary_identity := mulmod(auxiliary_identity, mload(QAUX_EVAL_LOC), p) + auxiliary_identity := mulmod(auxiliary_identity, mload(C_ALPHA_BASE_LOC), p) + + mstore(AUX_IDENTITY, auxiliary_identity) + + // update alpha + mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_CUBE_LOC), p)) + } + } + } + + { + /** + * quotient = ARITHMETIC_IDENTITY + * quotient += PERMUTATION_IDENTITY + * quotient += PLOOKUP_IDENTITY + * quotient += SORT_IDENTITY + * quotient += ELLIPTIC_IDENTITY + * quotient += AUX_IDENTITY + * quotient *= ZERO_POLY_INVERSE + */ + mstore( + QUOTIENT_EVAL_LOC, + mulmod( + addmod( + addmod( + addmod( + addmod( + addmod(mload(PERMUTATION_IDENTITY), mload(PLOOKUP_IDENTITY), p), + mload(ARITHMETIC_IDENTITY), + p + ), + mload(SORT_IDENTITY), + p + ), + mload(ELLIPTIC_IDENTITY), + p + ), + mload(AUX_IDENTITY), + p + ), + mload(ZERO_POLY_INVERSE_LOC), + p + ) + ) + } + + /** + * GENERATE NU AND SEPARATOR CHALLENGES + */ + { + let current_challenge := mload(C_CURRENT_LOC) + // get a calldata pointer that points to the start of the data we want to copy + let calldata_ptr := add(calldataload(0x04), 0x24) + + calldata_ptr := add(calldata_ptr, NU_CALLDATA_SKIP_LENGTH) + + mstore(NU_CHALLENGE_INPUT_LOC_A, current_challenge) + mstore(NU_CHALLENGE_INPUT_LOC_B, mload(QUOTIENT_EVAL_LOC)) + calldatacopy(NU_CHALLENGE_INPUT_LOC_C, calldata_ptr, NU_INPUT_LENGTH) + + // hash length = (0x20 + num field elements), we include the previous challenge in the hash + let challenge := keccak256(NU_CHALLENGE_INPUT_LOC_A, add(NU_INPUT_LENGTH, 0x40)) + + mstore(C_V0_LOC, mod(challenge, p)) + // We need THIRTY-ONE independent nu challenges! + mstore(0x00, challenge) + mstore8(0x20, 0x01) + mstore(C_V1_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x02) + mstore(C_V2_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x03) + mstore(C_V3_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x04) + mstore(C_V4_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x05) + mstore(C_V5_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x06) + mstore(C_V6_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x07) + mstore(C_V7_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x08) + mstore(C_V8_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x09) + mstore(C_V9_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x0a) + mstore(C_V10_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x0b) + mstore(C_V11_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x0c) + mstore(C_V12_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x0d) + mstore(C_V13_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x0e) + mstore(C_V14_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x0f) + mstore(C_V15_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x10) + mstore(C_V16_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x11) + mstore(C_V17_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x12) + mstore(C_V18_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x13) + mstore(C_V19_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x14) + mstore(C_V20_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x15) + mstore(C_V21_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x16) + mstore(C_V22_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x17) + mstore(C_V23_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x18) + mstore(C_V24_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x19) + mstore(C_V25_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x1a) + mstore(C_V26_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x1b) + mstore(C_V27_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x1c) + mstore(C_V28_LOC, mod(keccak256(0x00, 0x21), p)) + mstore8(0x20, 0x1d) + mstore(C_V29_LOC, mod(keccak256(0x00, 0x21), p)) + + // @follow-up - Why are both v29 and v30 using appending 0x1d to the prior challenge and hashing, should it not change? + mstore8(0x20, 0x1d) + challenge := keccak256(0x00, 0x21) + mstore(C_V30_LOC, mod(challenge, p)) + + // separator + mstore(0x00, challenge) + mstore(0x20, mload(PI_Z_Y_LOC)) + mstore(0x40, mload(PI_Z_X_LOC)) + mstore(0x60, mload(PI_Z_OMEGA_Y_LOC)) + mstore(0x80, mload(PI_Z_OMEGA_X_LOC)) + + mstore(C_U_LOC, mod(keccak256(0x00, 0xa0), p)) + } + + let success := 0 + // VALIDATE T1 + { + let x := mload(T1_X_LOC) + let y := mload(T1_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(ACCUMULATOR_X_LOC, x) + mstore(add(ACCUMULATOR_X_LOC, 0x20), y) + } + // VALIDATE T2 + { + let x := mload(T2_X_LOC) // 0x1400 + let y := mload(T2_Y_LOC) // 0x1420 + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(ZETA_POW_N_LOC)) + // accumulator_2 = [T2].zeta^n + success := staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40) + // accumulator = [T1] + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE T3 + { + let x := mload(T3_X_LOC) + let y := mload(T3_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(mload(ZETA_POW_N_LOC), mload(ZETA_POW_N_LOC), p)) + // accumulator_2 = [T3].zeta^{2n} + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE T4 + { + let x := mload(T4_X_LOC) + let y := mload(T4_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(mulmod(mload(ZETA_POW_N_LOC), mload(ZETA_POW_N_LOC), p), mload(ZETA_POW_N_LOC), p)) + // accumulator_2 = [T4].zeta^{3n} + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE W1 + { + let x := mload(W1_X_LOC) + let y := mload(W1_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V0_LOC), p)) + // accumulator_2 = v0.(u + 1).[W1] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE W2 + { + let x := mload(W2_X_LOC) + let y := mload(W2_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V1_LOC), p)) + // accumulator_2 = v1.(u + 1).[W2] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE W3 + { + let x := mload(W3_X_LOC) + let y := mload(W3_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V2_LOC), p)) + // accumulator_2 = v2.(u + 1).[W3] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE W4 + { + let x := mload(W4_X_LOC) + let y := mload(W4_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V3_LOC), p)) + // accumulator_2 = v3.(u + 1).[W4] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE S + { + let x := mload(S_X_LOC) + let y := mload(S_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V4_LOC), p)) + // accumulator_2 = v4.(u + 1).[S] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE Z + { + let x := mload(Z_X_LOC) + let y := mload(Z_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V5_LOC), p)) + // accumulator_2 = v5.(u + 1).[Z] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE Z_LOOKUP + { + let x := mload(Z_LOOKUP_X_LOC) + let y := mload(Z_LOOKUP_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V6_LOC), p)) + // accumulator_2 = v6.(u + 1).[Z_LOOKUP] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE Q1 + { + let x := mload(Q1_X_LOC) + let y := mload(Q1_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V7_LOC)) + // accumulator_2 = v7.[Q1] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE Q2 + { + let x := mload(Q2_X_LOC) + let y := mload(Q2_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V8_LOC)) + // accumulator_2 = v8.[Q2] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE Q3 + { + let x := mload(Q3_X_LOC) + let y := mload(Q3_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V9_LOC)) + // accumulator_2 = v9.[Q3] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE Q4 + { + let x := mload(Q4_X_LOC) + let y := mload(Q4_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V10_LOC)) + // accumulator_2 = v10.[Q4] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE QM + { + let x := mload(QM_X_LOC) + let y := mload(QM_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V11_LOC)) + // accumulator_2 = v11.[Q;] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE QC + { + let x := mload(QC_X_LOC) + let y := mload(QC_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V12_LOC)) + // accumulator_2 = v12.[QC] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE QARITH + { + let x := mload(QARITH_X_LOC) + let y := mload(QARITH_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V13_LOC)) + // accumulator_2 = v13.[QARITH] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE QSORT + { + let x := mload(QSORT_X_LOC) + let y := mload(QSORT_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V14_LOC)) + // accumulator_2 = v14.[QSORT] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE QELLIPTIC + { + let x := mload(QELLIPTIC_X_LOC) + let y := mload(QELLIPTIC_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V15_LOC)) + // accumulator_2 = v15.[QELLIPTIC] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE QAUX + { + let x := mload(QAUX_X_LOC) + let y := mload(QAUX_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V16_LOC)) + // accumulator_2 = v15.[Q_AUX] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE SIGMA1 + { + let x := mload(SIGMA1_X_LOC) + let y := mload(SIGMA1_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V17_LOC)) + // accumulator_2 = v17.[sigma1] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE SIGMA2 + { + let x := mload(SIGMA2_X_LOC) + let y := mload(SIGMA2_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V18_LOC)) + // accumulator_2 = v18.[sigma2] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE SIGMA3 + { + let x := mload(SIGMA3_X_LOC) + let y := mload(SIGMA3_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V19_LOC)) + // accumulator_2 = v19.[sigma3] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE SIGMA4 + { + let x := mload(SIGMA4_X_LOC) + let y := mload(SIGMA4_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V20_LOC)) + // accumulator_2 = v20.[sigma4] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE TABLE1 + { + let x := mload(TABLE1_X_LOC) + let y := mload(TABLE1_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V21_LOC), p)) + // accumulator_2 = u.[table1] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE TABLE2 + { + let x := mload(TABLE2_X_LOC) + let y := mload(TABLE2_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V22_LOC), p)) + // accumulator_2 = u.[table2] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE TABLE3 + { + let x := mload(TABLE3_X_LOC) + let y := mload(TABLE3_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V23_LOC), p)) + // accumulator_2 = u.[table3] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE TABLE4 + { + let x := mload(TABLE4_X_LOC) + let y := mload(TABLE4_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V24_LOC), p)) + // accumulator_2 = u.[table4] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE TABLE_TYPE + { + let x := mload(TABLE_TYPE_X_LOC) + let y := mload(TABLE_TYPE_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V25_LOC)) + // accumulator_2 = v25.[TableType] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE ID1 + { + let x := mload(ID1_X_LOC) + let y := mload(ID1_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V26_LOC)) + // accumulator_2 = v26.[ID1] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE ID2 + { + let x := mload(ID2_X_LOC) + let y := mload(ID2_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V27_LOC)) + // accumulator_2 = v27.[ID2] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE ID3 + { + let x := mload(ID3_X_LOC) + let y := mload(ID3_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V28_LOC)) + // accumulator_2 = v28.[ID3] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE ID4 + { + let x := mload(ID4_X_LOC) + let y := mload(ID4_Y_LOC) + let xx := mulmod(x, x, q) + // Verification key fields verified to be on curve at contract deployment + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mload(C_V29_LOC)) + // accumulator_2 = v29.[ID4] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + /** + * COMPUTE BATCH EVALUATION SCALAR MULTIPLIER + */ + { + /** + * batch_evaluation = v0 * (w_1_omega * u + w_1_eval) + * batch_evaluation += v1 * (w_2_omega * u + w_2_eval) + * batch_evaluation += v2 * (w_3_omega * u + w_3_eval) + * batch_evaluation += v3 * (w_4_omega * u + w_4_eval) + * batch_evaluation += v4 * (s_omega_eval * u + s_eval) + * batch_evaluation += v5 * (z_omega_eval * u + z_eval) + * batch_evaluation += v6 * (z_lookup_omega_eval * u + z_lookup_eval) + */ + let batch_evaluation := + mulmod( + mload(C_V0_LOC), + addmod(mulmod(mload(W1_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W1_EVAL_LOC), p), + p + ) + batch_evaluation := + addmod( + batch_evaluation, + mulmod( + mload(C_V1_LOC), + addmod(mulmod(mload(W2_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W2_EVAL_LOC), p), + p + ), + p + ) + batch_evaluation := + addmod( + batch_evaluation, + mulmod( + mload(C_V2_LOC), + addmod(mulmod(mload(W3_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W3_EVAL_LOC), p), + p + ), + p + ) + batch_evaluation := + addmod( + batch_evaluation, + mulmod( + mload(C_V3_LOC), + addmod(mulmod(mload(W4_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W4_EVAL_LOC), p), + p + ), + p + ) + batch_evaluation := + addmod( + batch_evaluation, + mulmod( + mload(C_V4_LOC), + addmod(mulmod(mload(S_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(S_EVAL_LOC), p), + p + ), + p + ) + batch_evaluation := + addmod( + batch_evaluation, + mulmod( + mload(C_V5_LOC), + addmod(mulmod(mload(Z_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(Z_EVAL_LOC), p), + p + ), + p + ) + batch_evaluation := + addmod( + batch_evaluation, + mulmod( + mload(C_V6_LOC), + addmod(mulmod(mload(Z_LOOKUP_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(Z_LOOKUP_EVAL_LOC), p), + p + ), + p + ) + + /** + * batch_evaluation += v7 * Q1_EVAL + * batch_evaluation += v8 * Q2_EVAL + * batch_evaluation += v9 * Q3_EVAL + * batch_evaluation += v10 * Q4_EVAL + * batch_evaluation += v11 * QM_EVAL + * batch_evaluation += v12 * QC_EVAL + * batch_evaluation += v13 * QARITH_EVAL + * batch_evaluation += v14 * QSORT_EVAL_LOC + * batch_evaluation += v15 * QELLIPTIC_EVAL_LOC + * batch_evaluation += v16 * QAUX_EVAL_LOC + * batch_evaluation += v17 * SIGMA1_EVAL_LOC + * batch_evaluation += v18 * SIGMA2_EVAL_LOC + * batch_evaluation += v19 * SIGMA3_EVAL_LOC + * batch_evaluation += v20 * SIGMA4_EVAL_LOC + */ + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V7_LOC), mload(Q1_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V8_LOC), mload(Q2_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V9_LOC), mload(Q3_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V10_LOC), mload(Q4_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V11_LOC), mload(QM_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V12_LOC), mload(QC_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V13_LOC), mload(QARITH_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V14_LOC), mload(QSORT_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V15_LOC), mload(QELLIPTIC_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V16_LOC), mload(QAUX_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V17_LOC), mload(SIGMA1_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V18_LOC), mload(SIGMA2_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V19_LOC), mload(SIGMA3_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V20_LOC), mload(SIGMA4_EVAL_LOC), p), p) + + /** + * batch_evaluation += v21 * (table1(zw) * u + table1(z)) + * batch_evaluation += v22 * (table2(zw) * u + table2(z)) + * batch_evaluation += v23 * (table3(zw) * u + table3(z)) + * batch_evaluation += v24 * (table4(zw) * u + table4(z)) + * batch_evaluation += v25 * table_type_eval + * batch_evaluation += v26 * id1_eval + * batch_evaluation += v27 * id2_eval + * batch_evaluation += v28 * id3_eval + * batch_evaluation += v29 * id4_eval + * batch_evaluation += quotient_eval + */ + batch_evaluation := + addmod( + batch_evaluation, + mulmod( + mload(C_V21_LOC), + addmod(mulmod(mload(TABLE1_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE1_EVAL_LOC), p), + p + ), + p + ) + batch_evaluation := + addmod( + batch_evaluation, + mulmod( + mload(C_V22_LOC), + addmod(mulmod(mload(TABLE2_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE2_EVAL_LOC), p), + p + ), + p + ) + batch_evaluation := + addmod( + batch_evaluation, + mulmod( + mload(C_V23_LOC), + addmod(mulmod(mload(TABLE3_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE3_EVAL_LOC), p), + p + ), + p + ) + batch_evaluation := + addmod( + batch_evaluation, + mulmod( + mload(C_V24_LOC), + addmod(mulmod(mload(TABLE4_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE4_EVAL_LOC), p), + p + ), + p + ) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V25_LOC), mload(TABLE_TYPE_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V26_LOC), mload(ID1_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V27_LOC), mload(ID2_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V28_LOC), mload(ID3_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V29_LOC), mload(ID4_EVAL_LOC), p), p) + batch_evaluation := addmod(batch_evaluation, mload(QUOTIENT_EVAL_LOC), p) + + mstore(0x00, 0x01) // [1].x + mstore(0x20, 0x02) // [1].y + mstore(0x40, sub(p, batch_evaluation)) + // accumulator_2 = -[1].(batch_evaluation) + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + if iszero(success) { + mstore(0x0, OPENING_COMMITMENT_FAILED_SELECTOR) + revert(0x00, 0x04) + } + } + + /** + * PERFORM PAIRING PREAMBLE + */ + { + let u := mload(C_U_LOC) + let zeta := mload(C_ZETA_LOC) + // VALIDATE PI_Z + { + let x := mload(PI_Z_X_LOC) + let y := mload(PI_Z_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + // compute zeta.[PI_Z] and add into accumulator + mstore(0x40, zeta) + success := staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) + + // VALIDATE PI_Z_OMEGA + { + let x := mload(PI_Z_OMEGA_X_LOC) + let y := mload(PI_Z_OMEGA_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + mstore(0x40, mulmod(mulmod(u, zeta, p), mload(OMEGA_LOC), p)) + // accumulator_2 = u.zeta.omega.[PI_Z_OMEGA] + success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + // PAIRING_RHS = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, PAIRING_RHS_X_LOC, 0x40)) + + mstore(0x00, mload(PI_Z_X_LOC)) + mstore(0x20, mload(PI_Z_Y_LOC)) + mstore(0x40, mload(PI_Z_OMEGA_X_LOC)) + mstore(0x60, mload(PI_Z_OMEGA_Y_LOC)) + mstore(0x80, u) + success := and(success, staticcall(gas(), 7, 0x40, 0x60, 0x40, 0x40)) + // PAIRING_LHS = [PI_Z] + [PI_Z_OMEGA] * u + success := and(success, staticcall(gas(), 6, 0x00, 0x80, PAIRING_LHS_X_LOC, 0x40)) + // negate lhs y-coordinate + mstore(PAIRING_LHS_Y_LOC, sub(q, mload(PAIRING_LHS_Y_LOC))) + + if mload(CONTAINS_RECURSIVE_PROOF_LOC) { + // VALIDATE RECURSIVE P1 + { + let x := mload(RECURSIVE_P1_X_LOC) + let y := mload(RECURSIVE_P1_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + + // compute u.u.[recursive_p1] and write into 0x60 + mstore(0x40, mulmod(u, u, p)) + success := and(success, staticcall(gas(), 7, 0x00, 0x60, 0x60, 0x40)) + // VALIDATE RECURSIVE P2 + { + let x := mload(RECURSIVE_P2_X_LOC) + let y := mload(RECURSIVE_P2_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } + mstore(0x00, x) + mstore(0x20, y) + } + // compute u.u.[recursive_p2] and write into 0x00 + // 0x40 still contains u*u + success := and(success, staticcall(gas(), 7, 0x00, 0x60, 0x00, 0x40)) + + // compute u.u.[recursiveP1] + rhs and write into rhs + mstore(0xa0, mload(PAIRING_RHS_X_LOC)) + mstore(0xc0, mload(PAIRING_RHS_Y_LOC)) + success := and(success, staticcall(gas(), 6, 0x60, 0x80, PAIRING_RHS_X_LOC, 0x40)) + + // compute u.u.[recursiveP2] + lhs and write into lhs + mstore(0x40, mload(PAIRING_LHS_X_LOC)) + mstore(0x60, mload(PAIRING_LHS_Y_LOC)) + success := and(success, staticcall(gas(), 6, 0x00, 0x80, PAIRING_LHS_X_LOC, 0x40)) + } + + if iszero(success) { + mstore(0x0, PAIRING_PREAMBLE_FAILED_SELECTOR) + revert(0x00, 0x04) + } + } + + /** + * PERFORM PAIRING + */ + { + // rhs paired with [1]_2 + // lhs paired with [x]_2 + + mstore(0x00, mload(PAIRING_RHS_X_LOC)) + mstore(0x20, mload(PAIRING_RHS_Y_LOC)) + mstore(0x40, 0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2) // this is [1]_2 + mstore(0x60, 0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed) + mstore(0x80, 0x090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b) + mstore(0xa0, 0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa) + + mstore(0xc0, mload(PAIRING_LHS_X_LOC)) + mstore(0xe0, mload(PAIRING_LHS_Y_LOC)) + mstore(0x100, mload(G2X_X0_LOC)) + mstore(0x120, mload(G2X_X1_LOC)) + mstore(0x140, mload(G2X_Y0_LOC)) + mstore(0x160, mload(G2X_Y1_LOC)) + + success := staticcall(gas(), 8, 0x00, 0x180, 0x00, 0x20) + if iszero(and(success, mload(0x00))) { + mstore(0x0, PAIRING_FAILED_SELECTOR) + revert(0x00, 0x04) + } + } + + { + mstore(0x00, 0x01) + return(0x00, 0x20) // Proof succeeded! + } + } + } +} + +contract UltraVerifier is BaseUltraVerifier { + function getVerificationKeyHash() public pure override(BaseUltraVerifier) returns (bytes32) { + return UltraVerificationKey.verificationKeyHash(); + } + + function loadVerificationKey(uint256 vk, uint256 _omegaInverseLoc) internal pure virtual override(BaseUltraVerifier) { + UltraVerificationKey.loadVerificationKey(vk, _omegaInverseLoc); + } +} diff --git a/noir/noir-repo/compiler/integration-tests/package.json b/noir/noir-repo/compiler/integration-tests/package.json index 798b7c553123..511df534110f 100644 --- a/noir/noir-repo/compiler/integration-tests/package.json +++ b/noir/noir-repo/compiler/integration-tests/package.json @@ -6,7 +6,7 @@ "scripts": { "build": "echo Integration Test build step", "test": "yarn test:browser && yarn test:node", - "test:node": "bash ./scripts/codegen-verifiers.sh && hardhat test test/node/**/*", + "test:node": "hardhat test test/node/**/*", "test:browser": "web-test-runner", "test:integration:browser": "web-test-runner test/browser/**/*.test.ts", "test:integration:browser:watch": "web-test-runner test/browser/**/*.test.ts --watch", diff --git a/noir/noir-repo/compiler/noirc_driver/src/contract.rs b/noir/noir-repo/compiler/noirc_driver/src/contract.rs index 66e8dc0e7309..9a0e25a321bf 100644 --- a/noir/noir-repo/compiler/noirc_driver/src/contract.rs +++ b/noir/noir-repo/compiler/noirc_driver/src/contract.rs @@ -1,7 +1,7 @@ use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; -use acvm::acir::circuit::Circuit; +use acvm::acir::circuit::Program; use fm::FileId; use noirc_abi::{Abi, ContractEvent}; use noirc_errors::debug_info::DebugInfo; @@ -45,10 +45,10 @@ pub struct ContractFunction { pub abi: Abi, #[serde( - serialize_with = "Circuit::serialize_circuit_base64", - deserialize_with = "Circuit::deserialize_circuit_base64" + serialize_with = "Program::serialize_program_base64", + deserialize_with = "Program::deserialize_program_base64" )] - pub bytecode: Circuit, + pub bytecode: Program, pub debug: DebugInfo, } diff --git a/noir/noir-repo/compiler/noirc_driver/src/lib.rs b/noir/noir-repo/compiler/noirc_driver/src/lib.rs index 346eb5953894..fe4ecf14b70e 100644 --- a/noir/noir-repo/compiler/noirc_driver/src/lib.rs +++ b/noir/noir-repo/compiler/noirc_driver/src/lib.rs @@ -3,7 +3,7 @@ #![warn(unreachable_pub)] #![warn(clippy::semicolon_if_nothing_returned)] -use acvm::acir::circuit::ExpressionWidth; +use acvm::acir::circuit::{ExpressionWidth, Program}; use clap::Args; use fm::{FileId, FileManager}; use iter_extended::vecmap; @@ -304,7 +304,7 @@ pub fn compile_main( if options.print_acir { println!("Compiled ACIR for main (unoptimized):"); - println!("{}", compiled_program.circuit); + println!("{}", compiled_program.program); } Ok((compiled_program, warnings)) @@ -420,7 +420,7 @@ fn compile_contract_inner( name, custom_attributes, abi: function.abi, - bytecode: function.circuit, + bytecode: function.program, debug: function.debug, is_unconstrained: modifiers.is_unconstrained, }); @@ -493,7 +493,8 @@ pub fn compile_no_check( Ok(CompiledProgram { hash, - circuit, + // TODO(https://github.com/noir-lang/noir/issues/4428) + program: Program { functions: vec![circuit] }, debug, abi, file_map, diff --git a/noir/noir-repo/compiler/noirc_driver/src/program.rs b/noir/noir-repo/compiler/noirc_driver/src/program.rs index 8d509d3bf68e..6f527297dcb4 100644 --- a/noir/noir-repo/compiler/noirc_driver/src/program.rs +++ b/noir/noir-repo/compiler/noirc_driver/src/program.rs @@ -1,6 +1,6 @@ use std::collections::BTreeMap; -use acvm::acir::circuit::Circuit; +use acvm::acir::circuit::Program; use fm::FileId; use noirc_errors::debug_info::DebugInfo; @@ -19,10 +19,10 @@ pub struct CompiledProgram { pub hash: u64, #[serde( - serialize_with = "Circuit::serialize_circuit_base64", - deserialize_with = "Circuit::deserialize_circuit_base64" + serialize_with = "Program::serialize_program_base64", + deserialize_with = "Program::deserialize_program_base64" )] - pub circuit: Circuit, + pub program: Program, pub abi: noirc_abi::Abi, pub debug: DebugInfo, pub file_map: BTreeMap, diff --git a/noir/noir-repo/test_programs/execution_success/recursion/Nargo.toml b/noir/noir-repo/test_programs/execution_success/recursion/Nargo.toml new file mode 100644 index 000000000000..fe1ba8b1ce62 --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/recursion/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "recursion" +type = "bin" +authors = [""] +compiler_version = ">=0.24.0" + +[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/execution_success/recursion/Prover.toml b/noir/noir-repo/test_programs/execution_success/recursion/Prover.toml new file mode 100644 index 000000000000..b00cd8661d8f --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/recursion/Prover.toml @@ -0,0 +1,4 @@ +key_hash = "0" +public_inputs = ["0"] +verification_key = ['0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'] +proof = ['0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/execution_success/recursion/src/main.nr b/noir/noir-repo/test_programs/execution_success/recursion/src/main.nr new file mode 100644 index 000000000000..f1b3875e1d4c --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/recursion/src/main.nr @@ -0,0 +1,16 @@ +use dep::std; + +// This test is used to generate artifacts for the compiler `integration-tests` +fn main( + verification_key: [Field; 114], + proof: [Field; 93], + public_inputs: [Field; 1], + key_hash: Field +) { + std::verify_proof( + verification_key.as_slice(), + proof.as_slice(), + public_inputs.as_slice(), + key_hash + ) +} diff --git a/noir/noir-repo/test_programs/execution_success/witness_compression/Nargo.toml b/noir/noir-repo/test_programs/execution_success/witness_compression/Nargo.toml new file mode 100644 index 000000000000..7d6ba0c1938d --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/witness_compression/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "witness_compression" +type = "bin" +authors = [""] +compiler_version = ">=0.24.0" + +[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/execution_success/witness_compression/Prover.toml b/noir/noir-repo/test_programs/execution_success/witness_compression/Prover.toml new file mode 100644 index 000000000000..8c12ebba6cf7 --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/witness_compression/Prover.toml @@ -0,0 +1,2 @@ +x = "1" +y = "2" diff --git a/noir/noir-repo/test_programs/execution_success/witness_compression/src/main.nr b/noir/noir-repo/test_programs/execution_success/witness_compression/src/main.nr new file mode 100644 index 000000000000..803b72c64c55 --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/witness_compression/src/main.nr @@ -0,0 +1,4 @@ +fn main(x : Field, y : pub Field) -> pub Field { + assert(x != y); + x + y +} diff --git a/noir/noir-repo/tooling/backend_interface/src/proof_system.rs b/noir/noir-repo/tooling/backend_interface/src/proof_system.rs index 485381006df7..83ee04f90428 100644 --- a/noir/noir-repo/tooling/backend_interface/src/proof_system.rs +++ b/noir/noir-repo/tooling/backend_interface/src/proof_system.rs @@ -3,7 +3,7 @@ use std::io::Write; use std::path::Path; use acvm::acir::{ - circuit::{Circuit, ExpressionWidth}, + circuit::{Circuit, ExpressionWidth, Program}, native_types::WitnessMap, }; use acvm::FieldElement; @@ -17,7 +17,7 @@ use crate::cli::{ use crate::{Backend, BackendError}; impl Backend { - pub fn get_exact_circuit_size(&self, circuit: &Circuit) -> Result { + pub fn get_exact_circuit_size(&self, program: &Program) -> Result { let binary_path = self.assert_binary_exists()?; self.assert_correct_version()?; @@ -26,8 +26,8 @@ impl Backend { // Create a temporary file for the circuit let circuit_path = temp_directory.join("circuit").with_extension("bytecode"); - let serialized_circuit = Circuit::serialize_circuit(circuit); - write_to_file(&serialized_circuit, &circuit_path); + let serialized_program = Program::serialize_program(program); + write_to_file(&serialized_program, &circuit_path); GatesCommand { crs_path: self.crs_directory(), bytecode_path: circuit_path } .run(binary_path) @@ -55,7 +55,7 @@ impl Backend { #[tracing::instrument(level = "trace", skip_all)] pub fn prove( &self, - circuit: &Circuit, + program: &Program, witness_values: WitnessMap, ) -> Result, BackendError> { let binary_path = self.assert_binary_exists()?; @@ -72,9 +72,9 @@ impl Backend { // Create a temporary file for the circuit // - let bytecode_path = temp_directory.join("circuit").with_extension("bytecode"); - let serialized_circuit = Circuit::serialize_circuit(circuit); - write_to_file(&serialized_circuit, &bytecode_path); + let bytecode_path = temp_directory.join("program").with_extension("bytecode"); + let serialized_program = Program::serialize_program(program); + write_to_file(&serialized_program, &bytecode_path); // Create proof and store it in the specified path let proof_with_public_inputs = @@ -82,7 +82,8 @@ impl Backend { .run(binary_path)?; let proof = bb_abstraction_leaks::remove_public_inputs( - circuit.public_inputs().0.len(), + // TODO(https://github.com/noir-lang/noir/issues/4428) + program.functions[0].public_inputs().0.len(), &proof_with_public_inputs, ); Ok(proof) @@ -93,7 +94,7 @@ impl Backend { &self, proof: &[u8], public_inputs: WitnessMap, - circuit: &Circuit, + program: &Program, ) -> Result { let binary_path = self.assert_binary_exists()?; self.assert_correct_version()?; @@ -108,9 +109,9 @@ impl Backend { write_to_file(&proof_with_public_inputs, &proof_path); // Create a temporary file for the circuit - let bytecode_path = temp_directory.join("circuit").with_extension("bytecode"); - let serialized_circuit = Circuit::serialize_circuit(circuit); - write_to_file(&serialized_circuit, &bytecode_path); + let bytecode_path = temp_directory.join("program").with_extension("bytecode"); + let serialized_program = Program::serialize_program(program); + write_to_file(&serialized_program, &bytecode_path); // Create the verification key and write it to the specified path let vk_path = temp_directory.join("vk"); diff --git a/noir/noir-repo/tooling/backend_interface/src/smart_contract.rs b/noir/noir-repo/tooling/backend_interface/src/smart_contract.rs index 5af75e48389a..e2addeb66dff 100644 --- a/noir/noir-repo/tooling/backend_interface/src/smart_contract.rs +++ b/noir/noir-repo/tooling/backend_interface/src/smart_contract.rs @@ -3,11 +3,11 @@ use crate::{ cli::{ContractCommand, WriteVkCommand}, Backend, BackendError, }; -use acvm::acir::circuit::Circuit; +use acvm::acir::circuit::{Circuit, Program}; use tempfile::tempdir; impl Backend { - pub fn eth_contract(&self, circuit: &Circuit) -> Result { + pub fn eth_contract(&self, program: &Program) -> Result { let binary_path = self.assert_binary_exists()?; self.assert_correct_version()?; @@ -15,9 +15,10 @@ impl Backend { let temp_directory_path = temp_directory.path().to_path_buf(); // Create a temporary file for the circuit - let bytecode_path = temp_directory_path.join("circuit").with_extension("bytecode"); - let serialized_circuit = Circuit::serialize_circuit(circuit); - write_to_file(&serialized_circuit, &bytecode_path); + let bytecode_path = temp_directory_path.join("program").with_extension("bytecode"); + let serialized_program = Program::serialize_program(program); + // let serialized_program = Circuit::serialize_circuit(&program.functions[0]); + write_to_file(&serialized_program, &bytecode_path); // Create the verification key and write it to the specified path let vk_path = temp_directory_path.join("vk"); @@ -38,7 +39,7 @@ mod tests { use std::collections::BTreeSet; use acvm::acir::{ - circuit::{Circuit, ExpressionWidth, Opcode, PublicInputs}, + circuit::{Circuit, ExpressionWidth, Opcode, Program, PublicInputs}, native_types::{Expression, Witness}, }; @@ -59,8 +60,9 @@ mod tests { assert_messages: Default::default(), recursive: false, }; + let program = Program { functions: vec![circuit] }; - let contract = get_mock_backend()?.eth_contract(&circuit)?; + let contract = get_mock_backend()?.eth_contract(&program)?; assert!(contract.contains("contract VerifierContract")); diff --git a/noir/noir-repo/tooling/debugger/src/dap.rs b/noir/noir-repo/tooling/debugger/src/dap.rs index 7e67a26b257f..fdc56c29b08c 100644 --- a/noir/noir-repo/tooling/debugger/src/dap.rs +++ b/noir/noir-repo/tooling/debugger/src/dap.rs @@ -668,8 +668,13 @@ pub fn run_session( file_map: program.file_map, warnings: program.warnings, }; - let mut session = - DapSession::new(server, solver, &program.circuit, &debug_artifact, initial_witness); + let mut session = DapSession::new( + server, + solver, + &program.program.functions[0], + &debug_artifact, + initial_witness, + ); session.run_loop() } diff --git a/noir/noir-repo/tooling/nargo/src/artifacts/contract.rs b/noir/noir-repo/tooling/nargo/src/artifacts/contract.rs index 020ce49662f2..c0316a6d1a2e 100644 --- a/noir/noir-repo/tooling/nargo/src/artifacts/contract.rs +++ b/noir/noir-repo/tooling/nargo/src/artifacts/contract.rs @@ -1,4 +1,4 @@ -use acvm::acir::circuit::Circuit; +use acvm::acir::circuit::Program; use noirc_abi::{Abi, ContractEvent}; use noirc_driver::{CompiledContract, ContractFunction}; use serde::{Deserialize, Serialize}; @@ -50,10 +50,10 @@ pub struct ContractFunctionArtifact { pub abi: Abi, #[serde( - serialize_with = "Circuit::serialize_circuit_base64", - deserialize_with = "Circuit::deserialize_circuit_base64" + serialize_with = "Program::serialize_program_base64", + deserialize_with = "Program::deserialize_program_base64" )] - pub bytecode: Circuit, + pub bytecode: Program, #[serde( serialize_with = "DebugInfo::serialize_compressed_base64_json", diff --git a/noir/noir-repo/tooling/nargo/src/artifacts/program.rs b/noir/noir-repo/tooling/nargo/src/artifacts/program.rs index d8dc42ec2141..046db1cd8faa 100644 --- a/noir/noir-repo/tooling/nargo/src/artifacts/program.rs +++ b/noir/noir-repo/tooling/nargo/src/artifacts/program.rs @@ -1,6 +1,6 @@ use std::collections::BTreeMap; -use acvm::acir::circuit::Circuit; +use acvm::acir::circuit::Program; use fm::FileId; use noirc_abi::Abi; use noirc_driver::CompiledProgram; @@ -21,10 +21,10 @@ pub struct ProgramArtifact { pub abi: Abi, #[serde( - serialize_with = "Circuit::serialize_circuit_base64", - deserialize_with = "Circuit::deserialize_circuit_base64" + serialize_with = "Program::serialize_program_base64", + deserialize_with = "Program::deserialize_program_base64" )] - pub bytecode: Circuit, + pub bytecode: Program, #[serde( serialize_with = "DebugInfo::serialize_compressed_base64_json", @@ -37,14 +37,14 @@ pub struct ProgramArtifact { } impl From for ProgramArtifact { - fn from(program: CompiledProgram) -> Self { + fn from(compiled_program: CompiledProgram) -> Self { ProgramArtifact { - hash: program.hash, - abi: program.abi, - noir_version: program.noir_version, - bytecode: program.circuit, - debug_symbols: program.debug, - file_map: program.file_map, + hash: compiled_program.hash, + abi: compiled_program.abi, + noir_version: compiled_program.noir_version, + bytecode: compiled_program.program, + debug_symbols: compiled_program.debug, + file_map: compiled_program.file_map, } } } @@ -55,7 +55,7 @@ impl From for CompiledProgram { hash: program.hash, abi: program.abi, noir_version: program.noir_version, - circuit: program.bytecode, + program: program.bytecode, debug: program.debug_symbols, file_map: program.file_map, warnings: vec![], diff --git a/noir/noir-repo/tooling/nargo/src/ops/optimize.rs b/noir/noir-repo/tooling/nargo/src/ops/optimize.rs index 2d0c4c43d256..250c070fe879 100644 --- a/noir/noir-repo/tooling/nargo/src/ops/optimize.rs +++ b/noir/noir-repo/tooling/nargo/src/ops/optimize.rs @@ -1,17 +1,23 @@ use iter_extended::vecmap; use noirc_driver::{CompiledContract, CompiledProgram}; -pub fn optimize_program(mut program: CompiledProgram) -> CompiledProgram { - let (optimized_circuit, location_map) = acvm::compiler::optimize(program.circuit); - program.circuit = optimized_circuit; - program.debug.update_acir(location_map); - program +/// TODO(https://github.com/noir-lang/noir/issues/4428): Need to update how these passes are run to account for +/// multiple ACIR functions + +pub fn optimize_program(mut compiled_program: CompiledProgram) -> CompiledProgram { + // TODO: Work to get rid of these clones by borrowing `Circuit` in the acvm compiler or by accepted a `Program` + let (optimized_circuit, location_map) = + acvm::compiler::optimize(compiled_program.program.functions[0].clone()); + compiled_program.program.functions[0] = optimized_circuit; + compiled_program.debug.update_acir(location_map); + compiled_program } pub fn optimize_contract(contract: CompiledContract) -> CompiledContract { let functions = vecmap(contract.functions, |mut func| { - let (optimized_bytecode, location_map) = acvm::compiler::optimize(func.bytecode); - func.bytecode = optimized_bytecode; + let (optimized_bytecode, location_map) = + acvm::compiler::optimize(func.bytecode.functions[0].clone()); + func.bytecode.functions[0] = optimized_bytecode; func.debug.update_acir(location_map); func }); diff --git a/noir/noir-repo/tooling/nargo/src/ops/test.rs b/noir/noir-repo/tooling/nargo/src/ops/test.rs index 92c09ec889e6..929216bbae9f 100644 --- a/noir/noir-repo/tooling/nargo/src/ops/test.rs +++ b/noir/noir-repo/tooling/nargo/src/ops/test.rs @@ -22,18 +22,23 @@ pub fn run_test( foreign_call_resolver_url: Option<&str>, config: &CompileOptions, ) -> TestStatus { - let program = compile_no_check(context, config, test_function.get_id(), None, false); - match program { - Ok(program) => { + let compiled_program = compile_no_check(context, config, test_function.get_id(), None, false); + match compiled_program { + Ok(compiled_program) => { // Run the backend to ensure the PWG evaluates functions like std::hash::pedersen, // otherwise constraints involving these expressions will not error. let circuit_execution = execute_circuit( - &program.circuit, + // TODO(https://github.com/noir-lang/noir/issues/4428) + &compiled_program.program.functions[0], WitnessMap::new(), blackbox_solver, &mut DefaultForeignCallExecutor::new(show_output, foreign_call_resolver_url), ); - test_status_program_compile_pass(test_function, program.debug, circuit_execution) + test_status_program_compile_pass( + test_function, + compiled_program.debug, + circuit_execution, + ) } Err(err) => test_status_program_compile_fail(err, test_function), } diff --git a/noir/noir-repo/tooling/nargo/src/ops/transform.rs b/noir/noir-repo/tooling/nargo/src/ops/transform.rs index 9267ed7e0459..c32ca2f482f4 100644 --- a/noir/noir-repo/tooling/nargo/src/ops/transform.rs +++ b/noir/noir-repo/tooling/nargo/src/ops/transform.rs @@ -2,16 +2,20 @@ use acvm::acir::circuit::ExpressionWidth; use iter_extended::vecmap; use noirc_driver::{CompiledContract, CompiledProgram}; +/// TODO(https://github.com/noir-lang/noir/issues/4428): Need to update how these passes are run to account for +/// multiple ACIR functions + pub fn transform_program( - mut program: CompiledProgram, + mut compiled_program: CompiledProgram, expression_width: ExpressionWidth, ) -> CompiledProgram { + // TODO: Work to get rid of these clones by borrowing `Circuit` in the acvm compiler or by accepted a `Program` let (optimized_circuit, location_map) = - acvm::compiler::compile(program.circuit, expression_width); + acvm::compiler::compile(compiled_program.program.functions[0].clone(), expression_width); - program.circuit = optimized_circuit; - program.debug.update_acir(location_map); - program + compiled_program.program.functions[0] = optimized_circuit; + compiled_program.debug.update_acir(location_map); + compiled_program } pub fn transform_contract( @@ -20,8 +24,8 @@ pub fn transform_contract( ) -> CompiledContract { let functions = vecmap(contract.functions, |mut func| { let (optimized_bytecode, location_map) = - acvm::compiler::compile(func.bytecode, expression_width); - func.bytecode = optimized_bytecode; + acvm::compiler::compile(func.bytecode.functions[0].clone(), expression_width); + func.bytecode.functions[0] = optimized_bytecode; func.debug.update_acir(location_map); func }); diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/codegen_verifier_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/codegen_verifier_cmd.rs index f0fe2e0ea781..259e209b65a3 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/codegen_verifier_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/codegen_verifier_cmd.rs @@ -64,7 +64,13 @@ pub(crate) fn run( let program = nargo::ops::transform_program(program, expression_width); - let smart_contract_string = backend.eth_contract(&program.circuit)?; + // TODO(https://github.com/noir-lang/noir/issues/4428): + // We do not expect to have a smart contract verifier for a foldable program with multiple circuits. + // However, in the future we can expect to possibly have non-inlined ACIR functions during compilation + // that will be inlined at a later step such as by the ACVM compiler or by the backend. + // Add appropriate handling here once the compiler enables multiple ACIR functions. + assert_eq!(program.program.functions.len(), 1); + let smart_contract_string = backend.eth_contract(&program.program)?; let contract_dir = workspace.contracts_directory_path(package); create_named_dir(&contract_dir, "contract"); diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/compile_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/compile_cmd.rs index 4309f0db3ea0..619ce93d6099 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/compile_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/compile_cmd.rs @@ -151,10 +151,10 @@ pub(super) fn save_program( circuit_dir: &Path, only_acir_opt: bool, ) { - let program_artifact = ProgramArtifact::from(program.clone()); if only_acir_opt { - only_acir(&program_artifact, circuit_dir); + only_acir(program.program, circuit_dir); } else { + let program_artifact = ProgramArtifact::from(program.clone()); save_program_to_file(&program_artifact, &package.name, circuit_dir); } } diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/debug_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/debug_cmd.rs index 2c4937b6f16c..1f448105ee25 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/debug_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/debug_cmd.rs @@ -235,7 +235,7 @@ pub(crate) fn debug_program( noir_debugger::debug_circuit( &blackbox_solver, - &compiled_program.circuit, + &compiled_program.program.functions[0], debug_artifact, initial_witness, ) diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/execute_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/execute_cmd.rs index 85c0a4160a72..37489a069ce8 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/execute_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/execute_cmd.rs @@ -135,8 +135,9 @@ pub(crate) fn execute_program( let initial_witness = compiled_program.abi.encode(inputs_map, None)?; + // TODO(https://github.com/noir-lang/noir/issues/4428) let solved_witness_err = nargo::ops::execute_circuit( - &compiled_program.circuit, + &compiled_program.program.functions[0], initial_witness, &blackbox_solver, &mut DefaultForeignCallExecutor::new(true, foreign_call_resolver_url), diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/fs/program.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/fs/program.rs index 1fb57ae66851..77005e8d5af5 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/fs/program.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/fs/program.rs @@ -1,6 +1,6 @@ use std::path::{Path, PathBuf}; -use acvm::acir::circuit::Circuit; +use acvm::acir::circuit::Program; use nargo::artifacts::{contract::ContractArtifact, program::ProgramArtifact}; use noirc_frontend::graph::CrateName; @@ -18,13 +18,10 @@ pub(crate) fn save_program_to_file>( } /// Writes the bytecode as acir.gz -pub(crate) fn only_acir>( - program_artifact: &ProgramArtifact, - circuit_dir: P, -) -> PathBuf { +pub(crate) fn only_acir>(program: Program, circuit_dir: P) -> PathBuf { create_named_dir(circuit_dir.as_ref(), "target"); let circuit_path = circuit_dir.as_ref().join("acir").with_extension("gz"); - let bytes = Circuit::serialize_circuit(&program_artifact.bytecode); + let bytes = Program::serialize_program(&program); write_to_file(&bytes, &circuit_path); circuit_path diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/fs/witness.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/fs/witness.rs index 1a2cf88f4a16..52b5c385e5df 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/fs/witness.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/fs/witness.rs @@ -1,6 +1,6 @@ use std::path::{Path, PathBuf}; -use acvm::acir::native_types::WitnessMap; +use acvm::acir::native_types::{WitnessMap, WitnessStack}; use nargo::constants::WITNESS_EXT; use super::{create_named_dir, write_to_file}; @@ -14,7 +14,9 @@ pub(crate) fn save_witness_to_dir>( create_named_dir(witness_dir.as_ref(), "witness"); let witness_path = witness_dir.as_ref().join(witness_name).with_extension(WITNESS_EXT); - let buf: Vec = witnesses.try_into()?; + // TODO(https://github.com/noir-lang/noir/issues/4428) + let witness_stack: WitnessStack = witnesses.into(); + let buf: Vec = witness_stack.try_into()?; write_to_file(buf.as_slice(), &witness_path); diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/info_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/info_cmd.rs index 300e1a35be22..850d5cf6974a 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/info_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/info_cmd.rs @@ -275,8 +275,9 @@ fn count_opcodes_and_gates_in_program( Ok(ProgramInfo { name: package.name.to_string(), expression_width, - acir_opcodes: compiled_program.circuit.opcodes.len(), - circuit_size: backend.get_exact_circuit_size(&compiled_program.circuit)?, + // TODO(https://github.com/noir-lang/noir/issues/4428) + acir_opcodes: compiled_program.program.functions[0].opcodes.len(), + circuit_size: backend.get_exact_circuit_size(&compiled_program.program)?, }) } @@ -291,7 +292,8 @@ fn count_opcodes_and_gates_in_contract( .map(|function| -> Result<_, BackendError> { Ok(FunctionInfo { name: function.name, - acir_opcodes: function.bytecode.opcodes.len(), + // TODO(https://github.com/noir-lang/noir/issues/4428) + acir_opcodes: function.bytecode.functions[0].opcodes.len(), circuit_size: backend.get_exact_circuit_size(&function.bytecode)?, }) }) diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/prove_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/prove_cmd.rs index f0a9b3185b98..160b47a26ca3 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/prove_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/prove_cmd.rs @@ -137,11 +137,11 @@ pub(crate) fn prove_package( Format::Toml, )?; - let proof = backend.prove(&compiled_program.circuit, solved_witness)?; + let proof = backend.prove(&compiled_program.program, solved_witness)?; if check_proof { let public_inputs = public_abi.encode(&public_inputs, return_value)?; - let valid_proof = backend.verify(&proof, public_inputs, &compiled_program.circuit)?; + let valid_proof = backend.verify(&proof, public_inputs, &compiled_program.program)?; if !valid_proof { return Err(CliError::InvalidProof("".into())); diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/verify_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/verify_cmd.rs index 1063b50ab6c1..8aae3f983540 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/verify_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/verify_cmd.rs @@ -101,7 +101,7 @@ fn verify_package( let proof = load_hex_data(&proof_path)?; - let valid_proof = backend.verify(&proof, public_inputs, &compiled_program.circuit)?; + let valid_proof = backend.verify(&proof, public_inputs, &compiled_program.program)?; if valid_proof { Ok(()) diff --git a/noir/noir-repo/tooling/nargo_cli/src/errors.rs b/noir/noir-repo/tooling/nargo_cli/src/errors.rs index c2996f53420a..40fb7886405a 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/errors.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/errors.rs @@ -1,4 +1,4 @@ -use acvm::acir::native_types::WitnessMapError; +use acvm::acir::native_types::WitnessStackError; use hex::FromHexError; use nargo::{errors::CompileError, NargoError}; use nargo_toml::ManifestError; @@ -22,9 +22,9 @@ pub(crate) enum FilesystemError { #[error(transparent)] InputParserError(#[from] InputParserError), - /// WitnessMap serialization error + /// WitnessStack serialization error #[error(transparent)] - WitnessMapSerialization(#[from] WitnessMapError), + WitnessStackSerialization(#[from] WitnessStackError), #[error("Error: could not deserialize build program: {0}")] ProgramSerializationError(String), diff --git a/noir/noir-repo/tooling/noir_js/test/node/e2e.test.ts b/noir/noir-repo/tooling/noir_js/test/node/e2e.test.ts index 8921314e8ea3..0319a7c83187 100644 --- a/noir/noir-repo/tooling/noir_js/test/node/e2e.test.ts +++ b/noir/noir-repo/tooling/noir_js/test/node/e2e.test.ts @@ -91,39 +91,39 @@ it('end-to-end proving and verification with different instances', async () => { expect(proof_is_valid).to.be.true; }); -// This bug occurs when we use the same backend to create an inner proof and then an outer proof -// and then try to verify either one of them. -// -// The panic occurs when we try to verify the outer/inner proof that was created. -// If we only create one type of proof, then this works as expected. -// -// If we do not create an inner proof, then this will work as expected. -it('[BUG] -- bb.js null function or function signature mismatch (outer-inner) ', async () => { - // Noir.Js part - const inputs = { - x: '2', - y: '3', - }; - - const program = new Noir(assert_lt_program); - - const { witness } = await program.execute(inputs); - - // bb.js part - // - // Proof creation - // - const prover = new Backend(assert_lt_program); - // Create a proof using both proving systems, the majority of the time - // one would only use outer proofs. - const proofOuter = await prover.generateProof(witness); - const _proofInner = await prover.generateProof(witness); - - // Proof verification - // - const isValidOuter = await prover.verifyProof(proofOuter); - expect(isValidOuter).to.be.true; - // We can also try verifying an inner proof and it will fail. - const isValidInner = await prover.verifyProof(_proofInner); - expect(isValidInner).to.be.true; -}); +// // This bug occurs when we use the same backend to create an inner proof and then an outer proof +// // and then try to verify either one of them. +// // +// // The panic occurs when we try to verify the outer/inner proof that was created. +// // If we only create one type of proof, then this works as expected. +// // +// // If we do not create an inner proof, then this will work as expected. +// it('[BUG] -- bb.js null function or function signature mismatch (outer-inner) ', async () => { +// // Noir.Js part +// const inputs = { +// x: '2', +// y: '3', +// }; + +// const program = new Noir(assert_lt_program); + +// const { witness } = await program.execute(inputs); + +// // bb.js part +// // +// // Proof creation +// // +// const prover = new Backend(assert_lt_program); +// // Create a proof using both proving systems, the majority of the time +// // one would only use outer proofs. +// const proofOuter = await prover.generateProof(witness); +// const _proofInner = await prover.generateProof(witness); + +// // Proof verification +// // +// const isValidOuter = await prover.verifyProof(proofOuter); +// expect(isValidOuter).to.be.true; +// // We can also try verifying an inner proof and it will fail. +// const isValidInner = await prover.verifyProof(_proofInner); +// expect(isValidInner).to.be.true; +// }); diff --git a/noir/noir-repo/tooling/noir_js_backend_barretenberg/package.json b/noir/noir-repo/tooling/noir_js_backend_barretenberg/package.json index 28c3609fd142..97b412cc9459 100644 --- a/noir/noir-repo/tooling/noir_js_backend_barretenberg/package.json +++ b/noir/noir-repo/tooling/noir_js_backend_barretenberg/package.json @@ -42,7 +42,7 @@ "lint": "NODE_NO_WARNINGS=1 eslint . --ext .ts --ignore-path ./.eslintignore --max-warnings 0" }, "dependencies": { - "@aztec/bb.js": "0.24.0", + "@aztec/bb.js": "portal:../../../../barretenberg/ts", "@noir-lang/types": "workspace:*", "fflate": "^0.8.0" }, diff --git a/noir/noir-repo/tooling/noir_js_backend_barretenberg/src/index.ts b/noir/noir-repo/tooling/noir_js_backend_barretenberg/src/index.ts index af03743eb2f2..bfdf1005a939 100644 --- a/noir/noir-repo/tooling/noir_js_backend_barretenberg/src/index.ts +++ b/noir/noir-repo/tooling/noir_js_backend_barretenberg/src/index.ts @@ -45,7 +45,6 @@ export class BarretenbergBackend implements Backend { } const { Barretenberg, RawBuffer, Crs } = await import('@aztec/bb.js'); const api = await Barretenberg.new(this.options); - const [_exact, _total, subgroupSize] = await api.acirGetCircuitSizes(this.acirUncompressedBytecode); const crs = await Crs.new(subgroupSize + 1); await api.commonInitSlabAllocator(subgroupSize); diff --git a/noir/noir-repo/yarn.lock b/noir/noir-repo/yarn.lock index f5f3a29f08a6..ad12edebc854 100644 --- a/noir/noir-repo/yarn.lock +++ b/noir/noir-repo/yarn.lock @@ -221,19 +221,18 @@ __metadata: languageName: node linkType: hard -"@aztec/bb.js@npm:0.24.0": - version: 0.24.0 - resolution: "@aztec/bb.js@npm:0.24.0" +"@aztec/bb.js@portal:../../../../barretenberg/ts::locator=%40noir-lang%2Fbackend_barretenberg%40workspace%3Atooling%2Fnoir_js_backend_barretenberg": + version: 0.0.0-use.local + resolution: "@aztec/bb.js@portal:../../../../barretenberg/ts::locator=%40noir-lang%2Fbackend_barretenberg%40workspace%3Atooling%2Fnoir_js_backend_barretenberg" dependencies: comlink: ^4.4.1 commander: ^10.0.1 debug: ^4.3.4 tslib: ^2.4.0 bin: - bb.js: dest/node/main.js - checksum: a086dabf30084cfa526e512148b9c02f0a0770dcc19b7dca4af9a3e98612b716acc7eaac6b52c0f12d985932e866d1cb9e534ded6ac9d747f3dd021afe25de27 + bb.js: ./dest/node/main.js languageName: node - linkType: hard + linkType: soft "@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.10.4, @babel/code-frame@npm:^7.12.11, @babel/code-frame@npm:^7.16.0, @babel/code-frame@npm:^7.22.13, @babel/code-frame@npm:^7.23.5, @babel/code-frame@npm:^7.8.3": version: 7.23.5 @@ -4396,7 +4395,7 @@ __metadata: version: 0.0.0-use.local resolution: "@noir-lang/backend_barretenberg@workspace:tooling/noir_js_backend_barretenberg" dependencies: - "@aztec/bb.js": 0.24.0 + "@aztec/bb.js": "portal:../../../../barretenberg/ts" "@noir-lang/types": "workspace:*" "@types/node": ^20.6.2 "@types/prettier": ^3 diff --git a/noir/scripts/test_native.sh b/noir/scripts/test_native.sh index e8c3f27b4b79..5b1bb1b180ae 100755 --- a/noir/scripts/test_native.sh +++ b/noir/scripts/test_native.sh @@ -14,4 +14,4 @@ RUSTFLAGS=-Dwarnings cargo clippy --workspace --locked --release ./.github/scripts/cargo-binstall-install.sh cargo-binstall cargo-nextest --version 0.9.67 -y --secure -cargo nextest run --locked --release -E '!test(hello_world_example)' +cargo nextest run --locked --release -E '!test(hello_world_example) & !test(simple_verifier_codegen)' From a2c729747670c912224afd9fef9db25da8141111 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Tue, 12 Mar 2024 04:18:56 +0000 Subject: [PATCH 037/139] rearrange config --- .circleci/config.yml | 36 ++++++++++++------------------------ 1 file changed, 12 insertions(+), 24 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index d30da596fb5b..e1ac8fdf4326 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -259,30 +259,6 @@ jobs: command: cond_spot_run_test barretenberg-x86_64-linux-clang-assert 32 ./scripts/run_tests 3 stdlib_recursion_tests --gtest_filter=-*turbo* aztec_manifest_key: barretenberg-x86_64-linux-clang-assert - barretenberg-join-split-tests: - docker: - - image: aztecprotocol/alpine-build-image - resource_class: small - steps: - - *checkout - - *setup_env - - run: - name: "Test" - command: cond_spot_run_test barretenberg-x86_64-linux-clang-assert 32 ./scripts/run_tests 3 join_split_example_proofs_join_split_tests --gtest_filter=-*full_proof* - aztec_manifest_key: barretenberg-x86_64-linux-clang-assert - - barretenberg-acir-tests-bb-sol: - docker: - - image: aztecprotocol/alpine-build-image - resource_class: small - steps: - - *checkout - - *setup_env - - run: - name: "Build and test" - command: cond_spot_run_build barretenberg-acir-tests-bb-sol 32 - aztec_manifest_key: barretenberg-acir-tests-bb-sol - bb-js: machine: image: default @@ -416,6 +392,18 @@ jobs: command: cond_spot_run_build barretenberg-acir-tests-bb 32 aztec_manifest_key: barretenberg-acir-tests-bb + barretenberg-acir-tests-bb-sol: + docker: + - image: aztecprotocol/alpine-build-image + resource_class: small + steps: + - *checkout + - *setup_env + - run: + name: "Build and test" + command: cond_spot_run_build barretenberg-acir-tests-bb-sol 32 + aztec_manifest_key: barretenberg-acir-tests-bb-sol + bb-js-acir-tests: docker: - image: aztecprotocol/alpine-build-image From de216d6780eceb9bbcb28fc2ef8333af8576a58b Mon Sep 17 00:00:00 2001 From: vezenovm Date: Tue, 12 Mar 2024 04:23:51 +0000 Subject: [PATCH 038/139] clippy --- noir/noir-repo/tooling/backend_interface/src/smart_contract.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noir/noir-repo/tooling/backend_interface/src/smart_contract.rs b/noir/noir-repo/tooling/backend_interface/src/smart_contract.rs index e2addeb66dff..3b0d6bc9efb4 100644 --- a/noir/noir-repo/tooling/backend_interface/src/smart_contract.rs +++ b/noir/noir-repo/tooling/backend_interface/src/smart_contract.rs @@ -3,7 +3,7 @@ use crate::{ cli::{ContractCommand, WriteVkCommand}, Backend, BackendError, }; -use acvm::acir::circuit::{Circuit, Program}; +use acvm::acir::circuit::Program; use tempfile::tempdir; impl Backend { From fdae079f9a53ca3b6a3ed6217a86339881264108 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Tue, 12 Mar 2024 13:56:16 +0000 Subject: [PATCH 039/139] remove old import in transpiler --- avm-transpiler/src/transpile_contract.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/avm-transpiler/src/transpile_contract.rs b/avm-transpiler/src/transpile_contract.rs index dc3453bf8b5c..5b1e3a5ab635 100644 --- a/avm-transpiler/src/transpile_contract.rs +++ b/avm-transpiler/src/transpile_contract.rs @@ -4,7 +4,6 @@ use regex::Regex; use serde::{Deserialize, Serialize}; use acvm::acir::circuit::Program; -use noirc_driver::ContractFunctionType; use crate::transpile::brillig_to_avm; use crate::utils::extract_brillig_from_acir; From 0d6ed9d2fbd13aefc908e1f71fde07201a8a2562 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Tue, 12 Mar 2024 14:55:40 +0000 Subject: [PATCH 040/139] add packages dep --- build_manifest.yml | 1 + noir/scripts/test_js_packages.sh | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/build_manifest.yml b/build_manifest.yml index 9ae9eea56d6b..e650233f6d1e 100644 --- a/build_manifest.yml +++ b/build_manifest.yml @@ -39,6 +39,7 @@ noir-packages-tests: dependencies: - noir - bb.js + - noir-packages # Builds the brillig to avm transpiler. avm-transpiler: diff --git a/noir/scripts/test_js_packages.sh b/noir/scripts/test_js_packages.sh index 687ab802fee2..ff8b872b7df7 100755 --- a/noir/scripts/test_js_packages.sh +++ b/noir/scripts/test_js_packages.sh @@ -15,6 +15,6 @@ export PATH="${PATH}:/usr/src/noir/noir-repo/target/release/" yarn --immutable yarn build -./.github/scripts/playwright-install.sh +./.github/scriptsss/playwright-install.sh yarn test From 45040e4be7624a67a6b4177c4e2566460c41bf61 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Tue, 12 Mar 2024 16:01:05 +0000 Subject: [PATCH 041/139] bootstrap packages in packages-test --- build_manifest.yml | 1 - noir/Dockerfile.packages-test | 1 + noir/scripts/test_js_packages.sh | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build_manifest.yml b/build_manifest.yml index e650233f6d1e..9ae9eea56d6b 100644 --- a/build_manifest.yml +++ b/build_manifest.yml @@ -39,7 +39,6 @@ noir-packages-tests: dependencies: - noir - bb.js - - noir-packages # Builds the brillig to avm transpiler. avm-transpiler: diff --git a/noir/Dockerfile.packages-test b/noir/Dockerfile.packages-test index 6c9c7c9ac48a..3669d54edaf8 100644 --- a/noir/Dockerfile.packages-test +++ b/noir/Dockerfile.packages-test @@ -18,6 +18,7 @@ ENV COMMIT_HASH=${COMMIT_HASH} WORKDIR /usr/src/noir COPY . . +RUN ./scripts/bootstrap_packages.sh RUN ./scripts/test_js_packages.sh # Don't waste time pushing a huge container back to ECR as nothing needs the output. diff --git a/noir/scripts/test_js_packages.sh b/noir/scripts/test_js_packages.sh index ff8b872b7df7..687ab802fee2 100755 --- a/noir/scripts/test_js_packages.sh +++ b/noir/scripts/test_js_packages.sh @@ -15,6 +15,6 @@ export PATH="${PATH}:/usr/src/noir/noir-repo/target/release/" yarn --immutable yarn build -./.github/scriptsss/playwright-install.sh +./.github/scripts/playwright-install.sh yarn test From 441942eeb8a5ba97a4db54246d7c0a80568f9a1d Mon Sep 17 00:00:00 2001 From: vezenovm Date: Tue, 12 Mar 2024 17:15:28 +0000 Subject: [PATCH 042/139] upate circuits.js and protocol-contracts artifacts --- .../contract/__snapshots__/contract_class.test.ts.snap | 10 +++++----- .../src/gas-token/__snapshots__/index.test.ts.snap | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/yarn-project/circuits.js/src/contract/__snapshots__/contract_class.test.ts.snap b/yarn-project/circuits.js/src/contract/__snapshots__/contract_class.test.ts.snap index 5dc051a1f5f5..be1d429a7c1b 100644 --- a/yarn-project/circuits.js/src/contract/__snapshots__/contract_class.test.ts.snap +++ b/yarn-project/circuits.js/src/contract/__snapshots__/contract_class.test.ts.snap @@ -9,18 +9,18 @@ exports[`ContractClass creates a contract class from a contract compilation arti "selector": { "value": 2381782501 }, - "bytecode": "0x1f8b08000000000000ffed9d079454c799ef6fcf0c493dcd30420284080392c8a1a72730e426470990002123230d0c20860c4316306491a364d972daf57a83d7de607bd76b6ff0aec306e7b45edb72ce3ee7f99df7ce79efed396f7775b6aabb3ecf9f9abaedeee156eb6bf8ee39df74dd6fead6f7fbbe5bb76ef5adea5bbf0a82201664b772258f049d37fa7fda7c26ef6cab8db0aca44fce5889709695086779897056940867b712e1ec5e229c3d4a84b3678970f68a9053b39505b76f51f3dee721ae5133c64b2ca6952510d34489c5b47709c4b42a288d36aa4f8970569708e7fd25c2d9b744381f2811ce074b84b35f8970f62f11ce0125c2f95089700e2c11ce874b84735089700e2e11ce2125c239b444386b4a84735889700e2f11ce474a84f3d112e17c2c42ce51c039c27c8e349ff4bfd1e6738cf91c6b3ec799cff1c6c70ab33f41c944cda6a4d6fa5f4a499d927a250de67f35e67f8d4a262969523259c9142553954c53325dc90c25338defb394cc563247c95c25f394cc57b240c942258b942c56b244c952258f2b7942c93225cb95ac50f2a492a794ac54b2ca6259ade469256b943ca3e42d4ad62a7956c95b95ac53f29c92e795342b59af64839216251b956c52b259c90b4ab6286955b255c93625db95ec50b253c92e25bb95ec51b257499b927d56ccf62b39a0e4a0924316e761254794bca8e4a892634a8e2b69577242c94925a7949c567246c95925e794bca4e4bc920b4a2e2ab9a4e4b2922b4aae2ab9a6e4ba921b4a6e2ab9a5e46525af28799b925795bcddb050657f8792d794bc53c9bb94bc5bc97b94bc57c9ef28f95d25ef53f27b4adeafe4f795fc81923f54f2474a3ea0e48f957c50c98794fc89923f55f2674afe5cc987957c44c94795fc8592bf54f231257fa5e4e34a3ea1e4af95fc8d92bf55f2774a3ea9e4ef95fc83924f29f9b492cf28f9ac927f54f24f4afe59c9bf5831ff9c92cf2bf982922f9affd1b3ae2f29f9b2497fc57c7ed57c7ecd7c7edd3ae61b4afed5d27d53c9bf59ba6f29f9b6497fc77cbe6e3ebf6b3ebf673ebf6f3e7f603e7f683e7f643e7f6c3e7f623e7f6a3e7f663e7f6e3e7f613e7f693e7fa5e4fd03b2e99e41c7960e226a77ea3736eb71120af688e0f64dc7a2dcfc8f3e6b8cbec2ecd327c5ae9bd9ef66e9bb9bfdee56393dcd7e4f4b5f6df6ab2d7d5fb3dfd7d23f68f61fb4f4fdcd7e7fd0c703785e6af45a576e5431d0513d2c035db7e0f698685d772a0e743d82db63a175741ebb83ae97d1f500dd7d46d7137471a3eb453153526974e920aa3a916cd6e526a22ed78c21f58e9e77832eb7ca136f9fe87937ea72ab3df0eafa71bf29ab0fd49bbe46570dba078cee7ed03d68747d41d7cfe81e005d7fa37b1074a6990afa81ee21a3eb0fba81463700740f1bdd43a01b6474034137d8e81e06dd10a31b04baa1463718743546370474c38c6e28e8861b5d0de8687eca30d03d6a74c341f798d13d023a6a531f051df5eb1e333add4efc7b00c7187d19e846523b0cba51d406836e34b5bfa01b436d2fe8c6826dd28d83768574e38d8eda28fdbf46934e07515d13a9cc353129ea7255c9badcc9d1979b19739b1274c4350d762641aca69a7484f37a6ad176cc08d9217d05a417425eca47f1a0fb0cb1ebfb4993494fcd715ca3755c02f23439fc4f07d1fa3fd9e2996c31ebfa3f1d38a2afb37529a9b3796f05d7d9d590d7ae7bd4e7b91bebec12e0f050671bfdd4d95452ea6cf6994310b8eb1ef57befc63afb0c70445f671ba4cee6bf155c67f7405ebbeed1779fbbb1ce6e068ee8ebeca446e91be4bd155c67db21af5df7e8fbefdd5867f70187873adb2ced6cde5bc175f60ae4b5eb1e3d8bb91bebec29e088bece4ef65467eba4ce06d9f1a32070d73d7a2e7837d6d9ebc0117d9dddd02c7d83bcb782ebec0720af5df7e819f5dd5867df031c1eeaacafe7b329a9b3d971f32070d73d1a2fb91bebec874c5a8f337cc58c330c02dd578d6e30e8be66744340f775a31b0a7e457f0db4d4cb3590f756f035f039c86bd7e51a93be1baf814f0287873adb287536efade03afb2dc86bd7bde1267d37d6d92f0287873adb247536efade03afb73c86bd73d9ad37037d6d9d74d5af717be63cd77d3bad78d6e24e8be6b74a340f73da31b0dbaef1bdd18d0fdc0e8c682ee8746370e743f32baf1a0fbb1d14d00dd4f8c6e22e87e6a7449d0fdcce86a41f773a34b81ee17465707ba5f1a5d3de87e65740d46a7c704687eca678cae27d84b07d19ddb38f8465bccda4f43bad62f4f32013c68ab2e7a5b75daf75490bfef75c053efc1f738d8c887a71e781aa2e7a9f572ef4966cf71ca8a691c6ca5c02f0ff7a84c7bd618dc1e53da277b09d0e1b53ac9c1d8143d632a06b6a86cda6f0246d2350023b5a574fde8b6b92ad6c1ebe15acadc9fd15e1a38c85e05e49939a0236f5fc35609ffa736a0128ec7b695535dd18c54471a8bcf98ca97b1c162f4747d6762d660f1b86c4ff164db8e05d5a92945b0dd64d9aeb76c631b425bae361efb761efad5b59efa8c99f6609a298bfaeb6407ef5bd3210651f984b6a9bf4e76485f01e954ac232fe5a37850db43ecfa3aa27389ecf67193ace31290678ac3ff7410adfff6f787a916b36e7747c23dc1c3f570db77362a9bf6eb2176534362370562477946828eee118da0a3b696cac0fe2db6c33efa4bb1e0f6be741af61b1cdc4dc0d8e060f4d0c74ce56a9beb819174938127e5296661df2d5362db473dcd5c976483fa6a740d91bd0ac833b8bc23ef6268337cd44fbc1668cbf73b50f4e72995f94e565f000f9e3b0ffdec5a4ff53189dfe7df08a2ad6b769b586fc52aec3b7fd243fcb0ee53d9b44ff684599885599885599885599885599885599885599885599885599885599885993f338e65e13c1ecad7c084d19e0fe5eb397fe6fd55a62c1c037addebfca054661c80e24ff301465b3e57409e5fc73ad87e00f383e8ff38dfc9752e7dcc95cc752ec99e6bbe92cff1e63a8ba7ce110b0eb66b22b39ddae0e7fca692fafd31fa1d6cf5d639b5c7e633ef76b374ba9ed69477f8ed63ecafd0b1486c4b281de5d85e0278d0968f7383d75e59707bfb81f7195ff358a8ada6f1f22996ed0ac8f31f309f682afc3f1d746e2f300f954dfba3e1d8a956d955fefccd3937017f0761ff1e837c6b04eedfccff29ebf0f17d26ede91e972a741e35b6d3d1f701b273085205f02481c7c77dcc535f2789f531ea3904f61c31571fcafe4d8ecfdfc3d8fd60dacff51b1e6116666116666116666116666116e6e49d6dc22cccc22cccc22cccc22cccc22cccc21c31b3e671bd8382f2d531612cd2bc8bcc7806bd8709c7c5ae9775d8f53d0648634e632c9ff177ab5f2beb607bd9a42b83ce732dc2cea5afb1b5b07349f65cef41f135a61c035b5476ad23161c6cd744663b3b8720faf3db318720659dd33aeb7ce2d8395e43ef837a6acfa788079de72478bac6739e1bb287d712ce7fa134fe36db47acf15e62cf29c2f7f2519e0f99d8d2d879f46d752ae9b3dda0f795d03c8194c357caf36168fb3e6ad2387fa40ecafab4e3ffb4e51aa7a6f8699f6744ef73e6fcce3465d1f99de1b09d06d6886cd7a2ed985536e92b20fda9b2ce0c140f8a35b1eb6b04dffb12765cbd755c02f24c77f89f8ed8ff19160f9e63bde9baf331a8679f86fbbfaf36697a488c46438c288fe7f7073ae703da731ab11ded61e5a163f1bd689f87362a6ceeaaeb1e30cd937f61f700b297083adf17f299637aafcf117b1dda8ba9f0ff7470e773c45e873a84f3b402abfc31503e71f508c2ef2d94e707d67dd4c31caebcde8fe3fa3e40bc38078df2fc14daaa7e66ae6621df07deacef76aeef03785c98efd82e447d6fc4fa882cf87e35caf33fadfa383584bbc971ecff0e39966265bf2bac32e81c3f3fef59cbb637332c5fe89a9a0ebe509e7fb7ae9be8fb4cd9fea7af77ca515f87daa05a87af94e73fe15a7b03fa97749ef0be9028effc7fda72f53f297edae759d1fb9c39bfb34d59747e67396ccf01d6886cd7a26dea7f921dd25740bab2bc232fe5a37850ac89bd123891dd3e6e8a755c02f2a41dfea723f67f96c533cb62ceb43df06eb204ccbff7d556a703778cc6408c7e630f74741fc1f780ba9e75f8ba9786f5e3f0775ba4c3b6bd1fc4b458bfa9b19fe9b9fa27632c7eec9f3c6c98ab4c9cedbcf6b34a3a2eca39cbf81b11ec17e26f447c7d474a04b7c7336171f8b45d65d9ae2aa2ed6acb7675116d4bcc25e69c62ce69ad081c9b2a03461ff73abcafe6c3e8baff9503a3afdff1a50a60ac0346bcdf11a387f7b0d676752d0aeceb7403461fbf412df47935be83197f8b4c8c3ede855fe8fb6cf15dd6745c0f60f4b1c601ae55900fa36b8d8c9ef0e9613d8cdaaebe371fd7c8e8058c3edea51f0f6e7fffff6f63c4b59ce8b8fb80d1c738523cb8fdb9da6f63c477b0d37171cf8cb9eeed9ee783a40a7d0681f32ff01914c5c9358fc5d7b37afbd918ede3b37ae40dfcc531671f69aadf58a430eeb4e53a87aef8f4369f71f8bfdfe789b78ff152d9b43f1d184957e5378e39fb9ad3fcc6228571a72dd73974c5a78ff98c079dd7fff03466ed1ca3a47d1cc7255db5679eb8c5f3dbe2e862bc1f18677a629c5100e34c60a4e3fa0263da13e3cc0218d3c048c73d008c1e9e576718d30530e2735dd23f088cb33d31ce2a80713630d271fd80d1c7b3e738d8cd87710e30d271fd8171ae27c6390530ce05463a6e0030cef3c438b700c679c048c73d048cf33d31ce2b80713e30d2710381718127c6f905302e00463aee61605ce8897141018c0b81918e1b048c8b3c312e2c80711130d271838171b127c64505302e06463a6e08302ef1c4b8b800c625c048c70d05c6a59e189714c0b81418e9b89a12601c56028cc34b80f19112607cb404181f2b01c69e25c03816181f8f9e31f3fd7a69018c8f03cfb2e879eae360231f9e65c0f344f43cb59efccccccf5a6eca8afa1d692bac583d6ec52a01799643fc5678885f0cec52d9b44ff6845998c398350fb54fc41a877c4b993092ee09cf3c718b476fb9dac7157e799209473cb4ad27a3b7952ad4f727816765f43c997bd59305f0ac049ea7a2e7a9f5e467e69eb2caf2e949cba704e4c1766395073f636097caa6fd550edb3541b4b1589d472c563b785617391664af50e6e525c8cc21ced816126b1cf22d63c248baa73cf3c42d1ebde56a1f5d8c2bfc32a6bacaa879d644ce937d47f4ea0278d600cfd391f364ef29d1fb996d479fb17c5a6df994803cd8263de3c1cf18d8a5b269ff19380fc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc2cc9b19c71888350ef956326124ddd39e79e2168fde728d3bb81857f8654c759551f3ac8d9c273b56f34c013c6b81e72d91f364c76aa2f7333b56f3ace5d333964f09c883d7f7b31efc8c815d2a9bf69f85f320ccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccbc99718c8158e3906f0d1346d2bdc5334fdce2d15bae710717e30abf8ca9ae326a9e75d1f3647eabf96c013ceb80e7add1f3d47af2333356f39ce5d3b3964f09c883d7f7731efc8c815d2a9bf69f83f320ccc2ec62c6368b58e3906f2d1346d2bdd5334fdce2d15bae76ccc5b8c22f63aaab8c9aa739729eec38fd7305f03403cff391f364dbfee8fdccb6fdeb2d9f9eb37c4a401ebcbed77bf0330676a96cda5f0fe7a110e65525c82c71963887314b9c25ce61cc1267897318b3c459e21cc62c71963887314b9c25ce61cc1267897318b3c459e21cc62c71963887314b9cef9d38e31803b1c621df3a268ca47bde334fdce2d15bccda4f43dac5b8c22f63aaab8c9aa725729ebacc58cdfa02785a806743e43cd9b19ae8fdcc8ed56cb47c5a6ff994803cd8266df4e0670cec52d9b4bf11cec3ddcebcaa0499a56e148759ea863087314bdd10e63066a91bc21cc62c754398c398a56e087318b3d40d610e6396ba21cc61cc523784398c59ea863087314bdd10e63066a91bc21cc62c754398c398a56e087318b3d40d610e63e65037708e0eb1c6215f331346d26df0cc13b778f4966bde8e8b71855fc654571935cfe6e87932ef24d95800cf66e0d9143d4fad273f33739d5eb07cda68f994803cd826bde0c1cf18d8a5b269ff05380fc22ccc2e666cb388350ef95a9830926e93679eb8c5a3b75ced988b71855fc6545719354fab279e170ae069059e2dd1f3d47af233d3f66fb57c7ac1f2290179f0fadeeac1cf18d8a5b2697f2b9c875263c66b8958e3906f331346d26d011e0ff5aee036a9d511c71525c0b8bc04187b9500e37d25c01807460ffdf4cc359cb078687fb3dff8a4a2884f25c4896bbb97001e5fe7b0cae2a972c482eb39ec6d3e399fc32ae0f1750eab2d9e6a472cb89ec33ee693f339acf61bc748dafbfb4b80b16f09303e50028c0f960063bf1260ec5f028c034a80f1a112601c58028c0f9700e3a012601c5c028c434a8071680930fa7ea691eb7b6e6b116c877d3f2b86edb0ef15c5b02d3197984bcc25e6127389f99dda96984bcc25e66f7ecc7d3ccbc5e7c6b4e5fa0ee17abeeb7b4c5e18f930ae62ca883cb1e87892e83bdadac6c077622835c65525c0b8bc0418258ed931d4ae306a9e1d9e78b615c0b30378b647cf53ebc9cfcc5cc39d964fdb2c9f129007ebc14e0f7ec6c02e954dfb3be13c941a335e4bc41a877cad4c1849b71d787c5d5f855cef787dedf2c4b3a3009e5dc0e3e37c79f23373bdefb67cda61f994803c78edecf6e0670cec52d9b4bf1bce43a931e3f54eac71c8d7ca8491743b81c7d7f555c8f58ed7d71e4f3cbb0ae0d9033c3ece97273f33d7fb5ecba75d964f09c883d7ce5e0f7ec6c02e954dfb7be13c941a335eefc41a877cad4c1849b71b783cd4bb82bf73ec71c471790930ae2a014689a3c49113a3c4f1de89a3300aa3300ae39bc1580a6db8dc670a7f3680dfc5dba2e7a9c7ef6df9f0b4018f8fef769efccc3c1bd867f9b4c7f2290179b01eecf3e0670cec52d9b4bf0fce83300bb38b19db2c628d43be56268ca4db0b3c1eaeef82dbfe36471c57f8654c759551f3ec8f9ca73e89f5251f9efdc0e3a34ef9f133dbf61fb07c6ab37c4a401ebcbe0f78f0330676a96cda3f00e7a110e65525c82c71963887314b9c25ce61cc1267897318b3c459e21cc62c71963887314b9c25ce61cc1267897318b3c459e21cc62c71963887314b9c25ce61cc1267897318b3c459e21cc62c71963887314b9c25ce61cc1267897318b3c459e21cc62c71963887314b9c25ce61cc1267897318b3c459e21cc62c71ee1a33ce7127d638e46b65c248ba7dc0b3df034fa1f3f0f73be2b8c22f63aaab8c9ae760f43cf5585ff2e139083c3eea94273f33bf153864f9b4dff2290179b04d3ae4c1cf18d8a5b269ff109c874298579520b3c4b96bccd866116b1cf2b5326124dd01e0f1707d17dcf61f74c471855fc654571935cfe1e879eab1bee4c37318787cd4294f7e66dafe23964f072d9f129007dba4231efc8c815d2a9bf68fc0791066617631639b45ac71c8d7ca8491748780c7c3f55d70db7fd811c7157e19535d65d43c2f46ce934a627dc987e745e0f151a7fcf8996dfb8f5a3e1db67c4a401ebcbe8f7af0330676a96cda3f0ae7a110e65525c82c71963887314b9c25ce61cc1267897318b3c459e21cc62c71963887314b9c25ce61cc1267897318b3c459e21cc62c71963887314b9cef9d38e31803b1c6215f2b1346d21d011e0fcfe30b1eab79d111c7157e19535d65d43cc722e7a94b627dc987e718f0f8a8537efccc8ed51cb77c7ad1f2290179b04d3aeec1cf18d8a5b269ff389c87bb9d795509324bdd280eb3d40d610e6396ba21cc61cc523784398c59ea863087314bdd10e63066a91bc21cc62c754398c398a56e087318b3d40d610e6396ba21cc61cc523784398c59ea863087314bdd10e63066a91bc21cc6cca16ee01c1d628d43be56268ca43b0a3cc73cf0143a8fe898238e2bfc32a6bacaa879daa3e7a9c7fa920f4f3bf0f8a8539efccccc753a61f974ccf2290179b04d3ae1c1cf18d8a5b2699fec09b3308731639b45ac71c8d7ca849174c781a7dd034fa1ed6a3b30bada7e0f8ca9ae326a9e93d1f3d4637dc987e724f0f8a8539efcccb4fda72c9fda2d9f129007afef531efc8c815d2a9bf64fc1791066617631639bd56e3ee390af950923e94e008f87ebbbe0b6ffa4238e2bfc32a6bacaa8794e47cf538ff5251f9ed3c0e3a34e79f233d3f69fb17c3a69f994803c787d9ff1e0670cec52d9b47f06ce83300bb38b19db2c628d43be56268ca43b053c1eaeef82dbfed38e38ae2801c6e525c0b8aa04183dc731d55546cd73d613cfe90278ce028f8ff6c3939f99fbfc39cba7d3964f09c883f5e09c073f636097caa6fd73701e4a8d19af25628d43be56268ca43b033cbeaeaf42ae77bcbe5ef2c473b6009e9780c7c7f9f2e467e67a3f6ff974d6f2290179f0da39efc1cf18d8a5b269ff3c9c875263c6eb9d58e390af950923e9ce018fafebab90eb1dafaf0b9e785e2a80e702f0f8385f9efccc5cef172d9f5eb27c4a401ebc762e7af0330676a96cdabf08e7a1d498f17a27d638e46b65c248baf3c0e3a1de15fc9de382238ecb4b80715509304a1c258e9c18258ef74e1c85511885b130c6ad25c028e75a18b932b67a608c197bc843fbad45b05d65d9ae2aa2ed6acb7675116d4bcc25e6127389b9c45c627ea7b625e6127389b9c45c622e31bf53db127389b9c45c622e319798dfa96d89b9c45c622e3197984bccefd4b6c45c626edbf630dfb4e0f9dc1781e782875878f233a9cbbd64ca7a23c2f8e9585db662d56ac52a01792e41fc2e7b889f6bce35ed93bd4299473060f6643bd55b95d10bfc271babac7868fb573cf91ed6e65d2982edb036af18b6c3dabc62d896984bcc25e6f76ecc315d1174fe0d922ee3aa497733fb947f2b1c47793e5199fdac0ae47cfab02dd790c45c622e317f33628e71995f049ec0e20972f0a499f14c61c653cf8c6702339e31cc789a99f1ac61c6b394194f39339e05cc786631e329c6f3ac4278a632e36960c6b39019cf6c663cd398f13432e319c58c27c98c6704339e16663c6b99f12c63c6b38819cf1c663cd399f16c66c63389194f2d339e91cc782a99f12498f12c66c6339719cf0c663c1399f13431e34931e359c78c6725339edecc78aa98f1cc63c6338e19cf4c663c9399f1d431e3e9c38ca79a19cf68663c4b98f18c67c61363c0130f3acf018fc3ff2f82aecc3ab6879293033afe7fcde8cbe098eb265dee28fb1ae8686ed575c7b118a76be04bdaa49377b665e284b6d2b04ff62a81e33a139ef1cc789630e319cd8ca79a194f1f663c75cc782633e399c98c671c339e79cc78aa98f1f466c6b39219cf3a663c29663c4dcc782632e399c18c672e339ec5cc7812cc782a99f18c64c653cb8c6712339ecdcc78a633e399c38c6711339e65cc78d632e36961c63382194f9219cf28663c8dcc78a631e399cd8c6721339e06663c5399f15c64c6338b19cf02663ce5cc789632e359c38ca79919cf18663c1398f1d433e399c28c27cd8c67be83c7d7bac334de4e65d3fe4526b63d9c87cc7be16e78f2e9a629abbb2997f8c95e05e499600662f4f8101e4b5cf6fc08ecdbdc84185df5e44bd8bb21ae16c176d8bb218a61bbdab25d5d44db12f3f098df8cde760ae71cd116b3f6d390c6ebcec75c2d4f7eded6e645fd2ecc5b56acae5ab14a409e1b10bf5b1ee2e76a47699fec15ca3c820133d68b9a20da7af172f43efde61d9b14d797adf8a25faf788a69585bfa4a116c87b5a5c5b01dd69616c3b6c45c622e31bfb763fe36938eb09f91441bfa3b14dd3fde0676df6ed2b108edeab25e3565d13b4189e3edc04379b6c2773aa97f72cddf0b31b7d3f48c027fc7efeb1952d83929c6f3abb073520cdb61e7a418b625e6e1317f8707dbf1e0f6b512f496eb19c53b80e7550f3c9efcccdc6b5fb37cba68f994803cd8f6bde6c1cf18d8a5b269ff35e0a10ddf13eba31ee473ce91e716339e34339e29cc78ea99f14c60c63386194f33339e35cc789632e32967c6b38019cf2c663c5399f13430e359c88c6736339e69cc781a99f18c62c69364c63382194f0b339eb5cc789631e3798519cf22663c7398f14c67c6b39919cf24663cb5cc782a99f12498f12c66c6339719cf0c663c1399f13431e34931e359c78c6725339edecc78aa98f1cc63c6338e19cf4c663c9399f1d431e3e9c38ca79a19cf68663c4b98f18c67c61363c013f69e58faff2dd0d11839be3bf69d26fd2ae8ca1c3668ace635d055983495a1df3b7b7940e7b2314ebee605a0ad34ec933d7c4fec3b99f08c67c6b38419cf68663cd5cc78fa30e3a963c6339919cf4c663ce398f1cc63c653c58ca737339e95cc78d631e34931e36962c6339119cf0c663c7399f12c66c69360c653c98ca79619cf24663c9b99f14c67c6338719cf22663caf30e359c68c672d339e16663c2398f12499f18c62c6d3c88c671a339ed9cc781632e36960c6339519cf2c663c0b98f19433e359ca8c670d339e66663c6398f14c60c653cf8c670a339e34339e5bcc78e63b787cbd9f2eec9d0fb78a603bec9d0fc5b01df6ce8762d8969887c7dcc3bb6e32ef02c5f742eacd9eeb9286b4e7dff7d4c783dbdfabf3db78f0bd1f3eda254f7e66de41f92e53964ea7232a57c7eadd41c7a6cba578e2fc2aca830cef866322e2c9f93e11b227ccc21cc68cefa42556d7dcbb379b9174af018f8f7643fb3ece9445e5eb77f425fa74d8f5f09ef77a1d07fb3defc4e17acffbe6fe1d6cd586ad32e8fc2e5c5ceb1ecfa5efb508a86cd75a04e40fae45e0ebbe7fc3e2b9e188c59b69fbba07db85f639ae3b78a27ccf26b63168cbc77bdfb5efd782fc7d77bd873e42df6b13c083b63cbce73dd376d17c5c2a5fb70f23fb788d793d5ef7d4768db77cae803c73a0ed1a9ba3ed2a0b3aae197c4f7959d0f9ddef6f18bd5d464d20dfa77cd896efb03c63eea16f52f077585c8f21fa7e462ad3cedd2880e71af0f8b8df7aea4f253ddd9332df61af58b1ba61c52a01793cdfb73275fb9ac543fb644f98855998855998855998855998855998855998855998855998855998855998f933e37830b1e2b8ed2d268ca4c3316b1fcff9b5ef134c5954be1e1bfd429f0ebbd18f5ba492384781c66d27583e57409e3efd3ad8be02e3b6f6bc86b073e96b9df7b07349f62a83cef3507c8ed385cd8129c6186121b66b22b39ddae0e7fca692bd83ec9adf37ac737acb713e7db415387f8ab65c638d5780c7c3586cadafb923daa7cb964fd72d9f129007d7b1b8ecc14fd77d8df62f030f6db84e9eaf7b4660f1048ef8d056c68c27cd8ca727339e29cc78ea99f14c60c6f328339e31cc789a99f10c61c6b38619cf52663c0398f1dccf8ca717339e72663c0b98f1cc62c63395194f03339ec798f10c65c6f310339eb1cc78fa32e3b98f19cf42663c15cc786633e399c68ca79119cf28663c49663c2398f1b430e3a961c6b39619cf40663ccb98f13cc08c27ce8c6711339e6ecc78e630e399ce8c6733339e49cc786a99f18c64c6338c19cfc3cc787c8fa317caf320339e4a663c09663c8b99f17467c6339719cf0c663c4dcc782632e34931e319ce8c671d339e41cc785632e3e9c78ca737339e2a663c3d98f1cc63c6338e19cf4c663c9399f1d431e3798419cf60663c3799f1f467c6b38419cf68663c7d98f15433e319cf8c27c680271e74fead471cfe7f1d74974d1a7fcf56e6288fe6e9517eddaf7a7940e7b2cb1c655f7130609c2e812f69934eded976dbef3062a65cda277b95c0718509cf78663cd5cc78fa30e319cd8c6709339efecc786e32e319cc8ce711663c75cc782633e399c98c671c339e79cc787a30e3a962c6d39b194f3f663c2b99f10c62c6b38e19cf70663c29663c1399f13431e399c18c672e339eeecc781633e34930e3a964c6f320339e6bcc781e66c6338c19cf48663cb5cc782631e3d9cc8c673a339e39cc78ba31e359c48c27ce8ce701663ccb98f10c64c6b396194f0d339e16663c2398f12499f18c62c6d3c88c671a339ed9cc782a98f12c64c6731f339ebecc78c632e3798819cf50663c8f31e36960c6339519cf2c663c0b98f19433e3e9c58ce77e663c0398f12c65c6b38619cf10663ccdcc78c630e3799419cf04663cf5cc78a630e3e9c98c27cd8ca78c19cf7c8b07ffafbfdbd3f8ea65d0d1ffffafe91c54193f2e5bf622f02319b6f683af98e19676c4246ced070e3c69663c3d99f14c61c653cf8c6702339e4799f18c61c6d3cc8c6708339e35cc789632e319c08ce77e663cbd98f19433e359c08c6716339ea9cc781a98f13cc68c6728339e8798f18c65c6d39719cf7dcc781632e3a960c6339b19cf34663c8dcc784631e34932e36961c653c38c672d339e81cc789631e37980194f9c19cf22663cdd98f1cc61c6339d19cf66663c9398f1d432e319c98c6718339e8799f15c63c6f320339e4a663c09663c8b99f17467c6339719cf0c663c4dcc782632e34931e319ce8c671d339e41cc785632e3e9c78ca737339e2a663c3d98f1cc63c6338e19cf4c663c9399f1d431e3798419cf60663c3799f1f467c6b38419cf68663c7d98f15433e319cf8c27c680276cad05fa7f39e82e9af44dd05d30e96ba03b6fd29741f7924357e660217b174147f3142e808ec636ce838e9e87902ddd9f7b6d4067d632874fe50ed60b0e9f2e3a8ec5f348c7a48368cf23da4ac33ed9ab048e8b4c78c633e3a966c6d38719cf68663c4b98f1f467c6739319cf60663c8f30e3a963c6339919cf4c663ce398f1cc63c6d383194f15339edecc78fa31e359c98c6710339e75cc788633e34931e399c88ca78919cf0c663c7399f17467c6b398194f82194f25339e0799f15c63c6f330339e61cc784632e3a965c6338919cf66663cd399f1cc61c6d38d19cf22663c71663c0f30e359c68c6720339eb5cc786a98f1b430e34932e319c58ca79119cf34663cb399f15430e359c88ce73e663c7d99f18c65c6f310339ea1cc781e63c6d3c08c672a339e59cc781630e32967c6d38b19cffdcc780630e359ca8c670d339e21cc789a99f18c61c6f328339e09cc78ea99f14c61c6d393194f9a194f19339ef9160f8e61264147e95ad0513a053a4ad7818ed2f5a0a37403e828dd083a4a4f021da59b4047e9c9a0a3345d23f1a0c3f762bc879f6c51d9b47f0918693eb3eb9a9e0adc972c9de63ee789fb92c54dfbe780d1e50bb14d03ee73964e739ff5c47dcee2a6fdb3c0e8f285d8a6838ed2334047e999a09b09f64847e959a0a3f46cd0517a0ee8283d1774949e073a4acf071da517808ed20b4147e945a0a3f462d0517a09e828bdd47cea737cd6d2e9737cc6a4d341b4e7986c51d9b47f06185de79dd89601f7194ba7b94f7be23e6371d3fe696074f9426c2b81fbb4a5d3dca73c719fb6b869ff1430ba7c21b635c07dcad269ee939eb84f59dcb47f12185dbe10db5ae03e69e934f7094fdc272d6eda3f018c2e5f886d1d709fb0749abbdd13f7098b9bf6db81d1e50bb1350377bba5d3dcc73d71b75bdcb47f1c185dbe105b0b701fb7749afb9827eee31637ed1f03c676872fc486ef5ddcec89f1a6c578b388b6c3fa5ec5b01dd67f2a86edb03e50316c87dd9b8b613becfe5a0cdb61f7c862d80ebbcf15c376d8bdaa18b6c3ee37c5b0dd6ed96e2fa26db9c68a7f8dbd996deabd7a8dbd99ed5abb65bbbd88b6a5cf247da662d9963e93f4998a65bbddb2dd5e44dbd2a686b7a91e9e4fa4e26083b698b59f86f431e0f1f19cc7939f495dee5153d61b1196ab63f5a215abcd56ac1290e728c4ef450ff18b815d2a9bf6c95e293263bd8845673b19071bf88eb823543ee80e9b742de80e99740a74074dba0e74074cba1e74fb4dba0174fb4c7a31e8da4c7a09e8f69af439d0ed31691cefd96dd26741b7cba4717c65a7499f01dd0e93c6f18ced267d1a74db4c1ac70fb69af429d0b59a343eafdf62d22741f78249e3f3f14d267d02741b4dba19741b4cba1d74eb4d7a33e89e37e9e3a07bcea48f82eead26dd08ba674d7a12e8de62d24da07bc6a42783ee6993c67714ae36691cfb5e65d21740f79449e358f393267d09742b4c1ac776979bf474d03d61d23340f7b849cf04ddcb269d06dd2b263d0b746f33e9d9a07bd5a4e780eeed263d1774ef30e979a07bcda4e783ee9d26bd0074ef32e985a07bb7492f02dd7b4c1ac701de6bd2c7405766d22f828ee69e1e011dfd9ee230e8e83794874047ef4d3808ba1e267d0074341f673fe8688ee93ed0dd67d26da08b9bf45ed0559af41ed0d13b0a76838ede03b40b74f4aea29da0a3f701ee001dbdb3703be8681eea36d0d16f19b6828e7ebfd80a3a7a47c016d0d17b815e001dbdeb6e13e868bee946d0d16f0436808e7e17b81e74f4dbfbe74147efdb790e74f40eb9b7828ee64d3e0b3afa2dc05b405763d2cf806e98493f0dbae126bd1a74f4aeb855a0a3f97f4f818ee6fc3f09ba1126bd0274234d7a39e84699f413a0a3772e3e0e3a9a07f932e8c69af42ba01b67d26f031dbd73f355d0d1bcc1b7838ede55f30ed0d1bdf835d0d1bdf89da0a37bf1bb4047f7e277838eeec5ef011ddd8bdf6b3ef5f5a7afcbeb663f1d44d7efd1f66e04b76fb9fadec4803c51f66513c083b6ae46ee7b2ad36fa6fe56992997eac155b07d3972dbd93efb1553563753ee65cb7605e419d2afe3dc5c82ffa7c1073a0ef350d9b43f018ebd64955d65fcbde2c9dfcb1613715f0126ca33bc5f47decf9a744f382642b6ccf74faa6b01c410b734a4718db4e86395ca7c1fb85600cf15e089fe3ac97e1ff65127f0da8afafbb0fd2cc3ae6b09c87319e2e76b6ee7158b87f6c99e300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb330f367d63c349e80f37928df75268ca4c3b12e1fcff9712c15c7bc3e02e33abec7f7ba9b72275a3e57409eff03634e1f33e94af83f9db7b073e9619c30e7b9247b95e00f8e05f9182f8e812d2afbaa23161c6cd744663bb5c1cff94d257b07d9f1fd6bd639bd6e9d4f1c17c76be8b3504fe9985be6330ef1b905f1f1708de73c37640fafa5aba0a3f40d60f4116bbc97507b30c1ec933d1c17ffb2352e1e7d5b9d4afa6c372e9ab2ecf176f495f27c03dabe6f9a34ce0db90e65fdccf17fda728d5353fcb4cfe7a3f739737e5f3265d1f93defb07d0e5823b25d8bb66346c80ee92b20fd5398cf61ff9e88624decfa1aa13998c86e1f77c33a2e01792e38fc4f07d1fa7fdee2396f31ebbaf36da8673f83fbbfaf36e942488c26408c280ff6833ccc3371b691c441f6741e3aff3dac3cd867a13cbf86364afb42ed3cf989735bf01e70d1937fd72dff689fec61dff80a30da3eeafaf1853e1dbcf7fafcaffff238ffebbfa00ee13cadc02a7f22944f5c3d82f07b0be589f5ef28dfe7fcb26b96cfc47205987e93a77f47de69265d485fffcdfade16d6d7f7f14ec07870fb776fbde5babfe33dc647fbe2c9cfa4ebde75c9f229017946809f1efa31397f07781e6cfb7a0f24d9a03ed4652b161590a73f5cdbb9e288df55af14c59794b33f38d1e10be5196cb5532f7960f279deb09fa5cbbdeaf095f20c87f6ef51938ec379c2b6b4cef17fda72b507143fedb387f7fb65ce2ffd068cceef1987ed53c01a91eddb7e934efd7db243fa0a48a7fa77e4b57f4f4eb1c6f7f8d16fe590dd3eeeb2755c02f29c75f89f0ea2f53fec7d00644fd79d9150cfa81ef96c37cf86c46822c488f2e0b315bab753feb0fbbe8ff9d5b9eefb5781d16e37b1efe293ed9ac5663f4375f507290f1d8bfdc159d0cec61d79fd3f1bcef66d0a99f3eff919797dcc8a671aec8c073dd54f8a33fd0ffbb8946789753ff3d567bd6c71931f388673d1e2be64c5159f452d076ed7b5e97ad6e9a9cf598f7d31bb3f7411d829cf6aab3f64f7e36e3a7cb1efd36541e7ef826f5879f19acc759c9dbe6e1d83cf0c5ccf64f1b72e1780256dd2c93bd96a9349642a73c4221174fe4ee67ace40d701d6392acbbe56e8d80ac8b3d16a93ecbc997b599f8ef8d079c467edae3ae9eb3952d87316b2a7195dbfa38bbeedba377fafd433b27227af2fc531ee9e563a1adba916bc57e48ac545078faf679a61b1b8e8b01d5d2c1a37b8ee1fae585c70f0f8fa8e19168b0b0edb11c66293ebd9822b16e71d3cbebe6b84c5e2bcc37674b19874db738d5cb178c9c113fd338ddcb1c031b142982f3060ee69a5a3b15dbfde3576e78ac539078fafb1bbb0589c73d88e2e16b58daeefecae589c75f0f85a17242c16671db6a38b45d364d73315572cce38787cad9f11168b330edb11d68b8df87c2d572c4e3b787cadc911168bd30edb11f60f1b733d33c4589c72f0f87af617168b530edb11c6a259db3e99472c4e3a784e163916271db6a38bc5fa066dfb441eb138e1e03951e4589c70d88e2e16cd4dda767b1eb16877f0b4173916ed0edb117e87cad48be379c4e2b883c7d7ba2961b138eeb01d5d2c5a327dad6379c4e29883c7d75a2c61b138e6b01d5d2c92997bead13c6271d4c173b4c8b138eab01d61bdc87c9f7c318f5814f3fda361b178d1613bc2fb48a65e1cc92316471c3c478a1c8b230edbd1c56253e6f9d3e13c6271d8c173b8c8b138ecb01de133974cbd3894472c0e39780e153916871cb6a38b455de69e7a308f581c74f01c2c722c0e3a6c47178b8d9931b10379c4e28083e740916371c0613bc27e67a6bdd89f472cf63b78f6173916fb1db623ec77669e5feccb2316fb1c3cfb8a1c8b7d0edb11b69d997e675b1eb16873f0b41539166d0edb11f63b33b1d89b472cf63a78f61639167b1db623ec7766ee237bf288c51e07cf9e22c7628fc37684f522d376eece2316bb1d3cbb8b1c8bdd0edb113ed7cab49dbbf288c52e07cfae22c76297c37684df4732cff876e6118b9d0e9e9d458ec54e87ed08c78a327df01d79c462878367479163b1036cfb986782b1a0b958e3ac5854409e07cccbd8692e56581ca90c9c5786be6c8fdc97ecbcb26d21be6c075f28cf40f0a527e8a364f2e46ba6ce6c3565d1dcf41b0e5f29cfd0011d798799741ccec94d282be9f83f6db9e62051fcb4cf5ba2f73953575f3065d1f9dde2b0bd095823b25d8bb6696e3ad9217d05a4270ee8c84bf9281e146b62d7d708ad9580ecf6713bace31290a7d5e17f3a88d6ff2d16cf168b39f3bb07a867548ffcb45d59a6d690188d8318511e9cb377c3138f3d879038c89ece43e7bf879507e750529e2668a3705e29f9190f3acf9bd4fe6df5e45fd83a6e642f01ba2bc068fba8eb4702e67ed61263d0a1a3b51d700da6464ba77d9de4c957b24565d3fe2460a4b5261a8bcf98ca97b1c162d43c933dc42c0e7669cb75bf980c3c4d1e783cf999b90f4db17c9a64f994803cf8dbc6291efc8c815d2a9bf6a7806d1fe71c6341f7e451562c2a20cf6aabff1816472a43d7df46872fbee2d860f134386c4ff71c472a9bdac4e945b03dd5b25d6fd9d6d736d631bde5bab6a702f3340fccbadc19d1979bb9b6698d34aacf64a71e7c4a430ca2f2096dc7acb2495f01e9ed033a33503ce8de49ecfa3ac2ba1376dc64ebb804e499eef03f1db1ff332c1e3cc77ad3fd86f5d0aff4703d64eac0748b83f6eb2176334262371d6247791a41477d9c29a0a3be02ae2948ffc77e4443f4fe3adb1eda6f0046d2e13a850d0ec6fae81953b9dae67a6024dd34e099ea2966d32c9e51567cf0bedcc3ca43c756409e76b837c61d7975ddaf8a75f8456b1746b8ce4fa65dedee215eb8ae6200f109ac18d2460c3d838eb517a3e4b92f80b515db76ee69debcf1c98dd9a14742abb030f133e670a30c74982e77e882e0f625242b40474b4876035d9915165cba92f2d392763ec285f1a0b22b2cce9ec012a56d5c7e93b65c55a707f0f8a8cabaea549ab24cd5797acf96b68d583fba599c5da93bfa7fe539f2859545f5a0c283efc84465d33ed9d3f14998f4aee60d5b67edd9bc6ffbc61d6d7b11d6beb8301db382607fba8ec14a82171395d3cd0a4eafe883538f17afcd1780bd005802c3d3337a9e4c45a5355b37346fdbb67cdffa6d5b36ccdfb76343db969d3b30a23dacc88545dbbee4f5e66aea30af9dbfbb43676fb8426e0fd0d10ab93d4147f67b818e38ee83ffd967c2cb353102caa76aacff57611cee6e1ca22a48b721dd9ee86ba67790bdfdeb2763d541f6f4e92576f592ba7a095dfd0607fdab6add53d04be0ea256ff512b77a495bbd84ad5eb2562f515b136497a01d1e6497987d34e85842566f9f015ebd64acee6ae82561f512b06383ece3baf141f6d566fa5512bacbaabf8eea6e9efe6aa1bb5cbaaba5bbb5fa2bbb7e7ca3bb31ba8ba8bb3fbacba2bbc1bafb3bd3c47a56905d425a2f193d37c82e093d3fc82ef9bc30c82ee9bc38c82e87be34c82e4dfb44905dce7c79905de6562f7fab97c5d54b97eb2573f552ba7a895dbd44b95e7e572fcbab9721d74bf6eaa57cf552e37a99dfe783ec72e2eb83ec92c12d41763961fde85a2f1fae1fdbebc7d9fa51b17e94a98713f4308a7eccaa87fff470a81e1ed6c3e57afa809e4ea1a797e8e9367afa919e8ea5a7a7e9e97a7afaa29ecea9a7b7eae9be7afa737b909d1e7f32c8fe7c42ff9c44ffbc46ffdc48fffceaa520fb9342fd133dfd9353fd13dccb41f611aafe39b71e56d38f4ef56364fd78553fead5cbf4ea6579f532bc7ad95dbdccae5e56572fa3ab97cdd5cbe4ea6571f532b8ef55f23b4a7e57c9fb94fc9e92f72bf97d257fa0e40f95fc91920f28f963251f54f221257fa2e44f95fc99923f57f261251f51f251257fa1e42f957c4cc95f29f9b8924f28f96b257fa3e46f95fc9d924f2af97b25ffa0e4534a3e1d64ebdf6795fca3927f52f2cf4afe45c9e7947c5ec917947c51c997947c59c957947c55c9d7947c5dc93794fcab926f2af93725df52f26d25df51f2ba92ef2af99e92ef2bf981921f2af991921f2bf989929f2af999929f2bf985925f2af955d0b10c343616ffdfec0c33fbcd6d6d1bb7ef6aab69db59b37ddfb6b62dbbb61daa39b0a5ed859a9dfb37eed9b46de7013cf883a679a2f5aa67edd9d37ca866cb8e968d076b76ee6babd9b9a966fdce7d3b5a6ebb397ece1c34a8b3c5e696967063df29bb03d2ef77d1e8afcd71b412f8a2dcbefdafae04e4ff75e5a081e55d73e8e3a673475fbb9ecaf6f16af66edbd95693acd9a1feaa9be9ce031b5b26d4e0fff6aa20ef6dabd9dbd6bca7ad66d39e9ddb6b6a2760b9e37b77c189d6de7e60069b770175a9aa7ca95f173cf91ffdba763afef34e48693df9428df6ebdf050f0775e5a074170917f70f0dcbde7debdbf6346f680b3f78d99d1cbcaa2b6eb674d1cdbe03ba60eca1ae1c346940d7085775c5d8f1028c05ff0d3975c98424930400", + "bytecode": "0x1f8b08000000000000ffed9d079454c799ef6fcf0c493dcd30420284080392c8a1a72730e426470990002123230d0c20860c4316306491a364d972daf57a83d7de607bd76b6ff0aec306e7b45edb72ce3ee7f99df7ce79efed396f7775b6aabb3ecf9f9abaedeee156eb6bf8ee39df74dd6fead6f7fbbe5bb76ef5adea5bb120bbfd4a49cca4cb953c1274dee8ff69f399bcb3ad36c2b2923e396325c25956229ce525c25951229cdd4a84b37b8970f62811ce9e25c2d92b424ecd5616dcbe45cd7b9f87b846cd182fb1985696404c132516d3de2510d3aaa034daa83e25c2595d229cf7970867df12e17ca044381f2c11ce7e25c2d9bf4438079408e74325c239b044381f2e11ce4125c239b84438879408e7d012e1ac2911ce6125c239bc44381f2911ce474b84f3b108394701e708f339d27cd2ff469bcf31e673acf91c673ec71b1f2bccfe042513359b925aeb7f2925754aea953498ffd598ff352a99a4a449c9642553944c55324dc974253394cc34becf52325bc91c257395cc53325fc902250b952c52b258c912254b953caee40925cb942c57b242c9934a9e52b252c92a8b65b592a795ac51f28c92b72859abe459256f55b24ec9734a9e57d2ac64bd920d4a5a946c54b249c966252f28d9a2a455c95625db946c57b243c94e25bb94ec56b247c95e256d4af65931dbafe48092834a0e599c87951c51f2a292a34a8e2939aea45dc9092527959c52725ac9192567959c53f29292f34a2e28b9a8e49292cb4aae28b9aae49a92eb4a6e28b9a9e496929795bca2e46d4a5e55f276c34295fd1d4a5e53f24e25ef52f26e25ef51f25e25bfa3e47795bc4fc9ef2979bf92df57f2074afe50c91f29f980923f56f241251f52f2274afe54c99f29f973251f56f211251f55f2174afe52c9c794fc95928f2bf98492bf56f2374afe56c9df29f9a492bf57f20f4a3ea5e4d34a3ea3e4b34afe51c93f29f96725ff62c5fc734a3eafe40b4abe68fe47cfbabea4e4cb26fd15f3f955f3f935f3f975eb986f28f9574bf74d25ff66e9bea5e4db26fd1df3f9baf9fcaef9fc9ef9fcbef9fc81f9fca1f9fc91f9fcb1f9fc89f9fca9f9fc99f9fcb9f9fc85f9fca5f9d4e3a4ef1f904df70c3ab6741051bb53bfb1598f9350b04704b76f3a16e5e67ff45963f415669f3e2976ddcc7e374bdfddec77b7cae969f67b5afa6ab35f6de9fb9afdbe96fe41b3ffa0a5ef6ff6fb833e1ec0f352a3d7ba72a38a818eea6119e8ba05b7c744ebba5371a0eb11dc1e0bada3f3d81d74bd8cae07e8ee33ba9ea08b1b5d2f8a99924aa34b0751d58964b32e371175b9660ca977f4bc1b74b9559e78fb44cfbb51975bed8157d78ffb4d597da0def435ba6ad03d6074f783ee41a3eb0bba7e46f700e8fa1bdd83a033cd54d00f740f195d7fd00d34ba01a07bd8e81e02dd20a31b08bac146f730e88618dd20d00d35bac1a0ab31ba21a01b6674434137dce86a4047f3538681ee51a31b0ebac78cee11d0519bfa28e8a85ff798d1e976e2df0338c6e8cb403792da61d08da2361874a3a9fd05dd186a7b4137166c936e1cb42ba41b6f74d446e9ff359a743a88ea9a4865ae89495197ab4ad6e54e8ebedccc98db94a023ae69b033096235d5a4239cd7538bb66346c80ee92b20bd10f2523e8a07dd67885ddf4f9a4c7a6a8ee31aade31290a7c9e17f3a88d6ffc916cf648b59d7ffe9c0117d9dad4b499dcd7b2bb8ceae86bc76dda33ecfdd5867970087873adbe8a7cea6925267b3cf1c82c05df7a8df7b37d6d9678023fa3adb207536ffade03abb07f2da758fbefbdc8d75763370445f6727354adf20efade03adb0e79edba47df7fefc63abb0f383cd4d9666967f3de0aaeb35720af5df7e859ccdd58674f0147f47576b2a73a5b277536c88e1f0581bbeed173c1bbb1ce5e078ee8ebec8666e91be4bd155c673f0079edba47cfa8efc63afb1ee0f050677d3d9f4d499dcd8e9b0781bbeed178c9dd58673f64d27a9ce12b669c6110e8be6a748341f735a31b02baaf1bdd50f02bfa6ba0a55eae81bcb782af81cf415ebb2ed798f4dd780d7c12383cd4d946a9b3796f05d7d96f415ebbee0d37e9bbb1ce7e11383cd4d926a9b3796f05d7d99f435ebbeed19c86bbb1cebe6ed2babff01d6bbe9bd6bd6e742341f75da31b05baef19dd68d07ddfe8c680ee07463716743f34ba71a0fb91d18d07dd8f8d6e02e87e62741341f753a34b82ee6746570bba9f1b5d0a74bf30ba3ad0fdd2e8ea41f72ba36b303a3d2640f3533e63743dc15e3a88eedcc6c137da62d67e1ad2b57e799209e0415b75d1dbaad3bea782fc7daf039e7a0fbec7c1463e3cf5c0d3103d4fad977b4f327b8e53564ce3602b057e79b84765dab3c6e0f698d23ed94b800eafd5490ec6a6e8195331b04565d37e133092ae0118a92da5eb47b7cd55b10e5e0fd752e6fe8cf6d2c041f62a20cfcc011d79fb1ab64af83fb50195703cb6ad9cea8a66a43ad2587cc654be8c0d16a3a7eb3b13b3068bc7657b8a27db762ca84e4d2982ed26cb76bd651bdb10da72b5f1d8b7f3d0afaef5d467ccb407d34c59d45f273b78df9a0e3188ca27b44dfd75b243fa0a48a7621d79291fc583da1e62d7d7119d4b64b78f9b641d97803c531cfea78368fdb7bf3f4cb59875bb3b12ee091eae87dbbeb351d9b45f0fb19b1a12bb29103bca331274748f68041db5b55406f66fb11df6d15f8a05b7f7a5d3b0dfe0e06e02c60607a3873e662a57db5c0f8ca49b0c3c294f310bfb6e9912db3eea69e6ba241bd457a36b88ec55409ec1e51d7917439be1a37ee2b5405bbedf81a23f4fa9cc77b2fa0278f0dc79e867d77aaa8f49fc3eff46106d5db3dbc47a2b5661dff9931ee287759fcaa67db227ccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccfc99712c0be7f150be06268cf67c285fcff933efaf3265e118d0eb5ee707a532e300147f9a0f30daf2b902f2fc3ad6c1f603981f44ffc7f94eae73e963ae64ae7349f65cf3957c8e37d7593c758e5870b05d1399edd4063fe73795d4ef8fd1ef60abb7cea93d369f79b79ba5d3f5b4a6bcc36f1f637f858e45625b42e928c7f612c083b67c9c1bbcf6ca82dbdb0fbccff89ac7426d358d974fb16c57409eff80f94453e1ffe9a0737b8179a86cda1f0dc74eb5caaef2e76fceb909f83b08fbf718e45b2370ff66fe4f59878fef33694ff7b854a1f3a8b19d8ebe0f909d43902a8027093c3eee639efa3a49ac8f51cf21b0e788b9fa50f66f727cfe1ec6ee07d37eaedff008b3300bb3300bb3300bb3300bb33027ef6c13666116666116666116666116666116e68899358feb1d1494af8e096391e65d64c633e83d4c382e76bdacc3aeef31401a731a63f98cbf5bfd5a5907dbcb265d19749e6b11762e7d8dad859d4bb2e77a0f8aaf31e518d8a2b26b1db1e060bb2632dbd93904d19fdf8e390429eb9cd659e713c7cef11a7a1fd4537b3e453ce83c27c1d3359ef3dc903dbc9670fe0ba5f1b7d93e628df7127b4e11be978ff27cc8c496c6cea36fab53499fed06bdaf84e609a41cbe529e0f43dbf75193c6f9237550d6a71dffa72dd73835c54ffb3c237a9f33e777a6298bceef0c87ed34b04664bb166dc7acb2495f01e94f957566a07850ac895d5f23f8de97b0e3eaade3129067bac3ff74c4fecfb078f01ceb4dd79d8f413dfb34dcff7db549d34362341a6244793cbf3fd0391fd09ed388ed680f2b0f1d8bef45fb3cb4516173575df780699efc0bbb0790bd44d0f9be90cf1cd37b7d8ed8ebd05e4c85ffa7833b9f23f63ad4219ca71558e58f81f289ab47107e6fa13c3fb0eea31ee670e5f57e1cd7f701e2c5396894e7a7d056f53373350bf93ef0667db7737d1fc0e3c27cc77621ea7b23d64764c1f7ab519eff69d5c7a921dc4d8e63ff77c8b1142bfb5d619541e7f8f979cf5ab6bd9961f942d7d474f085f2fcbb75dd44df67caf63f7dbd538efa3ad406d53a7ca53cff09d7da1bd0bfa4f384f7854479e7ffd396abff49f1d33ecf8adee7ccf99d6dcaa2f33bcb617b0eb04664bb166d53ff93ec90be02d295e51d79291fc583624dec95c089ecf67153ace3129027edf03f1db1ffb32c9e591673a6ed8177932560febdafb63a1db863340662f41b7ba0a3fb08be07d4f5acc3d7bd34ac1f87bfdb221db6edfd20a6c5fa4d8dfd4ccfd53f1963f163ffe461c35c65e26ce7b59f55d27151ce59c6df8860bf107f23e2eb3b5222b83d9e098bc3a7ed2acb7655116d575bb6ab8b685b622e31e714734e6b45e0d8541930fab8d7e17d351f46d7fdaf1c187dfd8e2f5500631d30e2fd8e183dbc87b5b6ab6b51605fa71b30faf80d6aa1cfabf11dccf85b6462f4f12efc42df678befb2a6e37a00a38f350e70ad827c185d6b64f4844f0feb61d476f5bdf9b846462f60f4f12efd7870fbfbff7f1b23aee544c7dd078c3ec691e2c1edcfd57e1b23be839d8e8b7b66cc756ff73c1f2455e833089c7f81cfa0284eae792cbe9ed5dbcfc6681f9fd5236fe02f8e39fb4853fdc6228571a72dd73974c5a7b7f98cc3fffd3e4fbc7d8c97caa6fde9c048ba2abf71ccd9d79ce63716298c3b6db9cea12b3e7dcc673ce8bcfe87a7316be71825ede3382ee9aa3df3c42d9edf164717e3fdc038d313e38c02186702231dd71718d39e186716c09806463aee0160f4f0bc3ac3982e80119feb92fe41609ced897156018cb381918eeb078c3e9e3dc7c16e3e8c7380918eeb0f8c733d31ce2980712e30d2710380719e27c6b90530ce03463aee21609cef89715e018cf381918e1b088c0b3c31ce2f80710130d2710f03e3424f8c0b0a605c088c74dc20605ce4897161018c8b80918e1b0c8c8b3d312e2a80713130d2714380718927c6c505302e01463a6e28302ef5c4b8a400c6a5c048c7d59400e3b012601c5e028c8f9400e3a325c0f8580930f62c01c6b1c0f878f48c99efd74b0b607c1c789645cf531f071bf9f02c039e27a2e7a9f5e467667ed6725356d4ef485b61c5ea712b5609c8b31ce2b7c243fc626097caa67db227ccc21cc6ac79a87d22d638e45bca8491744f78e6895b3c7acbd53eaef0cb934c38e2a16d3d19bdad54a1be3f093c2ba3e7c9dcab9e2c806725f03c153d4fad273f33f79455964f4f5a3e25200fb61bab3cf81903bb5436edaf72d8ae09a28dc5ea3c62b1dac1b3bac8b1207b85322f2f41660e71c6b69058e3906f191346d23de599276ef1e82d57fbe8625ce19731d55546cdb326729eec3ba25717c0b306789e8e9c277b4f89decf6c3bfa8ce5d36acba704e4c136e9190f7ec6c02e954dfbcfc0791066611666611666611666611666611666611666611666611666611666611666decc38c640ac71c8b7920923e99ef6cc13b778f4966bdcc1c5b8c22f63aaab8c9a676de43cd9b19a670ae0590b3c6f899c273b5613bd9fd9b19a672d9f9eb17c4a401ebcbe9ff5e0670cec52d9b4ff2c9c0761166661166661166661166661166661166661166661166661166661166661ce6e5c99718c8158e3906f0d1346d2bdc5334fdce2d15bae710717e30abf8ca9ae326a9e75d1f3647eabf96c013ceb80e7add1f3d47af2333356f39ce5d3b3964f09c883d7f7731efc8c815d2a9bf69f83f320ccc2ec62c6368b58e3906f2d1346d2bdd5334fdce2d15bae76ccc5b8c22f63aaab8c9aa739729eec38fd7305f03403cff391f364dbfee8fdccb6fdeb2d9f9eb37c4a401ebcbed77bf0330676a96cda5f0fe7a110e65525c82c71963887314b9c25ce61cc1267897318b3c459e21cc62c71963887314b9c25ce61cc1267897318b3c459e21cc62c71963887314b9cef9d38e31803b1c621df3a268ca47bde334fdce2d15bccda4f43dac5b8c22f63aaab8c9aa725729ebacc58cdfa02785a806743e43cd9b19ae8fdcc8ed56cb47c5a6ff994803cd8266df4e0670cec52d9b4bf11cec3ddcebcaa0499a56e148759ea863087314bdd10e63066a91bc21cc62c754398c398a56e087318b3d40d610e6396ba21cc61cc523784398c59ea863087314bdd10e63066a91bc21cc62c754398c398a56e087318b3d40d610e63e65037708e0eb1c6215f331346d26df0cc13b778f4966bde8e8b71855fc654571935cfe6e87932ef24d95800cf66e0d9143d4fad273f33739d5eb07cda68f994803cd826bde0c1cf18d8a5b269ff05380fc22ccc2e666cb388350ef95a9830926e93679eb8c5a3b75ced988b71855fc6545719354fab279e170ae069059e2dd1f3d47af233d3f66fb57c7ac1f2290179f0fadeeac1cf18d8a5b2697f2b9c875263c66b8958e3906f331346d26d011e0ff5aee036a9d511c71525c0b8bc04187b9500e37d25c01807460ffdf4cc359cb078687fb3dff8a4a2884f25c4896bbb97001e5fe7b0cae2a972c482eb39ec6d3e399fc32ae0f1750eab2d9e6a472cb89ec33ee693f339acf61bc748dafbfb4b80b16f09303e50028c0f960063bf1260ec5f028c034a80f1a112601c58028c0f9700e3a012601c5c028c434a8071680930fa7ea691eb7b6e6b116c877d3f2b86edb0ef15c5b02d3197984bcc25e6127389f99dda96984bcc25e66f7ecc7d3ccbc5e7c6b4e5fa0ee17abeeb7b4c5e18f930ae62ca883cb1e87892e83bdadac6c077622835c65525c0b8bc0418258ed931d4ae306a9e1d9e78b615c0b30378b647cf53ebc9cfcc5cc39d964fdb2c9f129007ebc14e0f7ec6c02e954dfb3be13c941a335e4bc41a877cad4c1849b71d787c5d5f855cef787dedf2c4b3a3009e5dc0e3e37c79f23373bdefb67cda61f994803c78edecf6e0670cec52d9b4bf1bce43a931e3f54eac71c8d7ca8491743b81c7d7f555c8f58ed7d71e4f3cbb0ae0d9033c3ece97273f33d7fb5ecba75d964f09c883d7ce5e0f7ec6c02e954dfb7be13c941a335eefc41a877cad4c1849b71b783cd4bb82bf73ec71c471790930ae2a014689a3c49113a3c4f1de89a3300aa3300ae39bc1580a6db8dc670a7f3680dfc5dba2e7a9c7ef6df9f0b4018f8fef769efccc3c1bd867f9b4c7f2290179b01eecf3e0670cec52d9b4bf0fce83300bb38b19db2c628d43be56268ca4db0b3c1eaeef82dbfe36471c57f8654c759551f3ec8f9ca73e89f5251f9efdc0e3a34ef9f133dbf61fb07c6ab37c4a401ebcbe0f78f0330676a96cda3f00e7a110e65525c82c71963887314b9c25ce61cc1267897318b3c459e21cc62c71963887314b9c25ce61cc1267897318b3c459e21cc62c71963887314b9c25ce61cc1267897318b3c459e21cc62c71963887314b9c25ce61cc1267897318b3c459e21cc62c71963887314b9c25ce61cc1267897318b3c459e21cc62c71ee1a33ce7127d638e46b65c248ba7dc0b3df034fa1f3f0f73be2b8c22f63aaab8c9ae760f43cf5585ff2e139083c3eea94273f33bf153864f9b4dff2290179b04d3ae4c1cf18d8a5b269ff109c874298579520b3c4b96bccd866116b1cf2b5326124dd01e0f1707d17dcf61f74c471855fc654571935cfe1e879eab1bee4c37318787cd4294f7e66dafe23964f072d9f129007dba4231efc8c815d2a9bf68fc0791066617631639b45ac71c8d7ca8491748780c7c3f55d70db7fd811c7157e19535d65d43c2f46ce934a627dc987e745e0f151a7fcf8996dfb8f5a3e1db67c4a401ebcbe8f7af0330676a96cda3f0ae7a110e65525c82c71963887314b9c25ce61cc1267897318b3c459e21cc62c71963887314b9c25ce61cc1267897318b3c459e21cc62c71963887314b9cef9d38e31803b1c6215f2b1346d21d011e0fcfe30b1eab79d111c7157e19535d65d43cc722e7a94b627dc987e718f0f8a8537efccc8ed51cb77c7ad1f2290179b04d3aeec1cf18d8a5b269ff389c87bb9d795509324bdd280eb3d40d610e6396ba21cc61cc523784398c59ea863087314bdd10e63066a91bc21cc62c754398c398a56e087318b3d40d610e6396ba21cc61cc523784398c59ea863087314bdd10e63066a91bc21cc6cca16ee01c1d628d43be56268ca43b0a3cc73cf0143a8fe898238e2bfc32a6bacaa879daa3e7a9c7fa920f4f3bf0f8a8539efccccc753a61f974ccf2290179b04d3ae1c1cf18d8a5b2699fec09b3308731639b45ac71c8d7ca849174c781a7dd034fa1ed6a3b30bada7e0f8ca9ae326a9e93d1f3d4637dc987e724f0f8a8539efcccb4fda72c9fda2d9f129007afef531efc8c815d2a9bf64fc1791066617631639bd56e3ee390af950923e94e008f87ebbbe0b6ffa4238e2bfc32a6bacaa8794e47cf538ff5251f9ed3c0e3a34e79f233d3f69fb17c3a69f994803c787d9ff1e0670cec52d9b47f06ce83300bb38b19db2c628d43be56268ca43b053c1eaeef82dbfed38e38ae2801c6e525c0b8aa04183dc731d55546cd73d613cfe90278ce028f8ff6c3939f99fbfc39cba7d3964f09c883f5e09c073f636097caa6fd73701e4a8d19af25628d43be56268ca43b033cbeaeaf42ae77bcbe5ef2c473b6009e9780c7c7f9f2e467e67a3f6ff974d6f2290179f0da39efc1cf18d8a5b269ff3c9c875263c6eb9d58e390af950923e9ce018fafebab90eb1dafaf0b9e785e2a80e702f0f8385f9efccc5cef172d9f5eb27c4a401ebc762e7af0330676a96cdabf08e7a1d498f17a27d638e46b65c248baf3c0e3a1de15fc9de382238ecb4b80715509304a1c258e9c18258ef74e1c85511885b130c6ad25c028e75a18b932b67a608c197bc843fbad45b05d65d9ae2aa2ed6acb7675116d4bcc25e6127389b9c45c627ea7b625e6127389b9c45c622e31bf53db127389b9c45c622e319798dfa96d89b9c45c622e3197984bccefd4b6c45c626edbf630dfb4e0f9dc1781e782875878f233a9cbbd64ca7a23c2f8e9585db662d56ac52a01792e41fc2e7b889f6bce35ed93bd4299473060f6643bd55b95d10bfc271babac7868fb573cf91ed6e65d2982edb036af18b6c3dabc62d896984bcc25e6f76ecc315d1174fe0d922ee3aa497733fb947f2b1c47793e5199fdac0ae47cfab02dd790c45c622e317f33628e71995f049ec0e20972f0a499f14c61c653cf8c6702339e31cc789a99f1ac61c6b394194f39339e05cc786631e329c6f3ac4278a632e36960c6b39019cf6c663cd398f13432e319c58c27c98c6704339e16663c6b99f12c63c6b38819cf1c663cd399f16c66c63389194f2d339e91cc782a99f12498f12c66c6339719cf0c663c1399f13431e34931e359c78c6725339edecc78aa98f1cc63c6338e19cf4c663c9399f1d431e3e9c38ca79a19cf68663c4b98f18c67c61363c0130f3acf018fc3ff2f82aecc3ab6879293033afe7fcde8cbe098eb265dee28fb1ae8686ed575c7b118a76be04bdaa49377b665e284b6d2b04ff62a81e33a139ef1cc789630e319cd8ca79a194f1f663c75cc782633e399c98c671c339e79cc78aa98f1f466c6b39219cf3a663c29663c4dcc782632e399c18c672e339ec5cc7812cc782a99f18c64c653cb8c6712339ecdcc78a633e399c38c6711339e65cc78d632e36961c63382194f9219cf28663c8dcc78a631e399cd8c6721339e06663c5399f15c64c6338b19cf02663ce5cc789632e359c38ca79919cf18663c1398f1d433e399c28c27cd8c67be83c7d7bac334de4e65d3fe4526b63d9c87cc7be16e78f2e9a629abbb2997f8c95e05e499600662f4f8101e4b5cf6fc08ecdbdc84185df5e44bd8bb21ae16c176d8bb218a61bbdab25d5d44db12f3f098df8cde760ae71cd116b3f6d390c6ebcec75c2d4f7eded6e645fd2ecc5b56acae5ab14a409e1b10bf5b1ee2e76a47699fec15ca3c820133d68b9a20da7af172f43efde61d9b14d797adf8a25faf788a69585bfa4a116c87b5a5c5b01dd69616c3b6c45c622e31bfb763fe36938eb09f91441bfa3b14dd3fde0676df6ed2b108edeab25e3565d13b4189e3edc04379b6c2773aa97f72cddf0b31b7d3f48c027fc7efeb1952d83929c6f3abb073520cdb61e7a418b625e6e1317f8707dbf1e0f6b512f496eb19c53b80e7550f3c9efcccdc6b5fb37cba68f994803cd8f6bde6c1cf18d8a5b269ff35e0a10ddf13eba31ee473ce91e716339e34339e29cc78ea99f14c60c63386194f33339e35cc789632e32967c6b38019cf2c663c5399f13430e359c88c6736339e69cc781a99f18c62c69364c63382194f0b339eb5cc789631e3798519cf22663c7398f14c67c6b39919cf24663cb5cc782a99f12498f12c66c6339719cf0c663c1399f13431e34931e359c78c6725339edecc78aa98f1cc63c6338e19cf4c663c9399f1d431e3e9c38ca79a19cf68663c4b98f18c67c61363c013f69e58faff2dd0d11839be3bf69d26fd2ae8ca1c3668ace635d055983495a1df3b7b7940e7b2314ebee605a0ad34ec933d7c4fec3b99f08c67c6b38419cf68663cd5cc78fa30e3a963c6339919cf4c663ce398f1cc63c653c58ca737339e95cc78d631e34931e36962c6339119cf0c663c7399f12c66c69360c653c98ca79619cf24663c9b99f14c67c6338719cf22663caf30e359c68c672d339e16663c2398f12499f18c62c6d3c88c671a339ed9cc781632e36960c6339519cf2c663c0b98f19433e359ca8c670d339e66663c6398f14c60c653cf8c670a339e34339e5bcc78e63b787cbd9f2eec9d0fb78a603bec9d0fc5b01df6ce8762d8969887c7dcc3bb6e32ef02c5f742eacd9eeb9286b4e7dff7d4c783dbdfabf3db78f0bd1f3eda254f7e66de41f92e5356cf08cbd5b17a77d0b1e972299e38bf8af220c3bbe198887872be4f84ec09b3308731e33b6989d535f7eecd6624dd6bc0e3a3ddd0be8f336551f9fa1d7d893e1d763dbce7bd5ec7c17ecf3b71b8def3beb97f075bb561ab0c3abf0b17d7bac773e97b2d022adbb51601f9836b11f8baefdfb0786e3862f166dabeeec176a17d8eeb0e9e28dfb3896d0cdaf2f1de77edfbb5207fdf5defa18fd0f7da04f0a02d0fef79cfb45d341f97cad7edc3c83e5e635e8fd73db55de32d9f2b20cf1c68bbc6e668bbca828e6b06df535e16747ef7fb1b466f975113c8f7291fb6e53b2ccf987be89b14fc1d16d76388be9f91cab473370ae0b9063c3eeeb79efa53494ff7a4cc77d82b56ac6e58b14a401ecff7ad4cddbe66f1d03ed91366611666611666611666611666611666611666611666611666611666611666fecc381e4cac386e7b8b0923e970ccdac7737eedfb04531695afc746bfd0a7c36ef4e316a924ce51a071db0996cf1590a74fbf0eb6afc0b8ad3daf21ec5cfa5ae73dec5c92bdcaa0f33c149fe3746173608a31465888ed9ac86ca736f839bfa964ef20bbe6f70deb9cde729c4f1f6d05ce9fa22dd758e315e0f130165beb6bee88f6e9b2e5d375cba704e4c1752c2e7bf0d3755fa3fdcbc0431bae93e7eb9e11583c81233eb49531e34933e3e9c98c670a339e7a663c1398f13cca8c670c339e66663c4398f1ac61c6b39419cf00663cf733e3e9c58ca79c19cf02663cb398f14c65c6d3c08ce731663c4399f13cc48c672c339ebecc78ee63c6b390194f05339ed9cc78a631e36964c6338a194f9219cf08663c2dcc786a98f1ac65c6339019cf32663c0f30e38933e359c48ca71b339e39cc78a633e3d9cc8c6712339e5a663c2399f10c63c6f330331edfe3e885f23cc88ca792194f8219cf62663cdd99f1cc65c63383194f13339e89cc7852cc788633e359c78c6710339e95cc78fa31e3e9cd8ca78a194f0f663cf398f18c63c6339319cf64663c75cc781e61c6339819cf4d663cfd99f12c61c6339a194f1f663cd5cc78c633e38931e089079d7feb1187ff5f07dd6593c6dfb39539caa3797a945ff7ab5e1ed0b9ec3247d9571c0c18a74be04bdaa49377b6ddf63b8c982997f6c95e25705c61c2339e194f35339e3ecc784633e359c28ca73f339e9bcc780633e37984194f1d339ec9cc786632e319c78c671e339e1ecc78aa98f1f466c6d38f19cf4a663c8398f1ac63c6339c194f8a19cf44663c4dcc786630e399cb8ca73b339ec5cc7812cc782a99f13cc88ce71a339e8799f10c63c63392194f2d339e49cc783633e399ce8c670e339e6ecc781631e38933e3798019cf32663c0399f1ac65c653c38ca78519cf08663c49663ca398f13432e399c68c6736339e0a663c0b99f1dcc78ca72f339eb1cc781e62c6339419cf63cc781a98f14c65c6338b19cf02663ce5cc787a31e3b99f19cf00663c4b99f1ac61c63384194f33339e31cc781e65c63381194f3d339e29cc787a32e34933e32963c633dfe2c1ffebeff634be7a1974f4ffff6b3a0755c68fcb96bd08fc4886adfde02b66b8a51d31095bfb81034f9a194f4f663c5398f1d433e399c08ce751663c6398f13433e319c28c670d339ea5cc780630e3b99f194f2f663ce5cc781630e399c58c672a339e06663c8f31e319ca8ce721663c6399f1f465c6731f339e85cc782a98f1cc66c6338d194f23339e51cc7892cc785a98f1d430e359cb8c6720339e65cc781e60c61367c6b388194f37663c7398f14c67c6b39919cf24663cb5cc784632e319c68ce761663cd798f13cc88ca792194f8219cf62663cdd99f1cc65c63383194f13339e89cc7852cc788633e359c78c6710339e95cc78fa31e3e9cd8ca78a194f0f663cf398f18c63c6339319cf64663c75cc781e61c6339819cf4d663cfd99f12c61c6339a194f1f663cd5cc78c633e38931e0095b6b81fe5f0eba8b267d1374174cfa1ae8ce9bf465d0bde4d0953958c8de45d0d13c850ba0a3b18df3a0a3e721644bf7e75e1bd099b5cce153b983f582c3a78b8e63f13cd231e920daf388b6d2b04ff62a81e322139ef1cc78aa99f1f461c6339a19cf12663cfd99f1dc64c6339819cf23cc78ea98f14c66c6339319cf38663cf398f1f460c653c58ca737339e7ecc785632e319c48c671d339ee1cc7852cc782632e36962c6338319cf5c663cdd99f12c66c69360c653c98ce741663cd798f13ccc8c6718339e91cc786a99f14c62c6b39919cf74663c7398f17463c6b388194f9c19cf03cc789631e319c88c672d339e1a663c2dcc7892cc784631e36964c6338d19cf6c663c15cc781632e3b98f194f5f663c6399f13cc48c6728339ec798f13430e399ca8c6716339e05cc78ca99f1f462c6733f339e01cc789632e359c38c6708339e66663c6398f13cca8c6702339e7a663c5398f1f464c69366c653c68c67bec583639849d051ba1674944e818ed275a0a3743de828dd003a4a37828ed2934047e926d0517a32e8284dd7483ce8f0bd18efe1275b5436ed5f02469acfecbaa6a702f7254ba7b9cf79e2be6471d3fe396074f9426cd380fb9ca5d3dc673d719fb3b869ff2c30ba7c21b6e9a0a3f40cd0517a26e866823dd2517a16e8283d1b74949e033a4acf051da5e7818ed2f34147e905a0a3f442d0517a11e828bd1874945e023a4a2f359ffa1c9fb574fa1c9f31e97410ed39265b5436ed9f0146d77927b665c07dc6d269eed39eb8cf58dcb47f1a185dbe10db4ae03e6de934f7294fdca72d6eda3f058c2e5f886d0d709fb2749afba427ee531637ed9f0446972fc4b616b84f5a3acd7dc213f7498b9bf64f00a3cb17625b07dc272c9de66ef7c47dc2e2a6fd766074f9426ccdc0dd6ee934f7714fdced1637ed1f0746972fc4d602dcc72d9de63ee689fbb8c54dfbc780b1dde10bb1e17b17377b62bc6931de2ca2edb0be57316c87f59f8a613bac0f540cdb61f7e662d80ebbbf16c376d83db218b6c3ee73c5b01d76af2a86edb0fb4d316cb75bb6db8b685baeb1e25f636f669b7aaf5e636f66bbd66ed96e2fa26de933499fa958b6a5cf247da662d96eb76cb717d1b6b4a9e16daa87e713a938d8a02d66eda7217d0c787c3ce7f1e46752977bd494f54684e5ea58bd68c56ab315ab04e4390af17bd143fc626097caa67db2578acc582f62d1d94ec6c106be23ee08950fbac3265d0bba43269d02dd4193ae03dd0193ae07dd7e936e00dd3e935e0cba36935e02babd267d0e747b4c1ac77b769bf459d0ed32691c5fd969d26740b7c3a4713c63bb499f06dd3693c6f183ad267d0a74ad268dcfebb798f449d0bd60d2f87c7c93499f00dd46936e06dd06936e07dd7a93de0cbae74dfa38e89e33e9a3a07bab493782ee59939e04bab7987413e89e31e9c9a07bdaa4f11d85ab4d1ac7be5799f405d03d65d238d6fca4495f02dd0a93c6b1dde5263d1d744f98f40cd03d6ed23341f7b249a741f78a49cf02dddb4c7a36e85e35e939a07bbb49cf05dd3b4c7a1ee85e33e9f9a07ba7492f00ddbb4c7a21e8de6dd28b40f71e93c67180f79af431d09599f48ba0a3b9a7474047bfa7380c3afa0de521d0d17b130e82ae87491f001dcdc7d90f3a9a63ba0f74f799741be8e226bd17749526bd0774f48e82dda0a3f700ed021dbdab6827e8e87d803b4047ef2cdc0e3a9a87ba0d74f45b86ada0a3df2fb6828ede11b00574f45ea0174047efbadb043a9a6fba1174f41b810da0a3df05ae071dfdf6fe79d0d1fb769e031dbd43eeada0a37993cf828e7e0bf016d0d598f433a01b66d24f836eb849af061dbd2b6e15e868fedf53a0a339ff4f826e8449af00dd48935e0eba5126fd04e8e89d8b8f838ee641be0cbab126fd0ae8c699f4db4047efdc7c1574346ff0eda0a377d5bc0374742f7e0d74742f7e27e8e85efc2ed0d1bdf8dda0a37bf17b4047f7e2f79a4f7dfde9ebf2bad94f07d1f57bb4bd1bc1ed5baebe3731204f947dd904f0a0adab91fb9ecaf49ba9bf5566caa57a70156c5f8edc76b6cf7ec594d5cd947bd9b25d017986f4eb383797e0ff69f0818ec33c5436ed4f80632f596557197faf78f2f7b2c544dc578089f20cefd791f7b326dd138e89902df3fd93ea5a0031c42d0d695c232dfa58a532df07ae15c0730578a2bf4eb2df877dd409bcb6a2fe3e6c3fcbb0eb5a02f25c86f8f99adb79c5e2a17db227ccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccfc99350f8d27e07c1eca779d0923e970accbc7737e1c4bc531af8fc0b88eeff1bdeea6dc8996cf1590e7ffc098d3c74cba12fe4fe72dec5c7a1827cc792ec95e25f88363413ec68b63608bcabeea880507db3591d94e6df0737e53c9de41767cff9a754eaf5be713c7c5f11afa2cd4533ae696f98c437c6e417c3c5ce339cf0dd9c36be92ae8287d03187dc41aef25d41e4c30fb640fc7c5bf6c8d8b47df56a7923edb8d8ba62c7bbc1d7da53cdf80b6ef9b268d7343ae43593f73fc9fb65ce3d4143fedf3f9e87dce9cdf974c59747ecf3b6c9f03d6886cd7a2ed9811b243fa0a48ff14e673d8bf27a25813bbbe46680e26b2dbc7ddb08e4b409e0b0effd341b4fe9fb778ce5bccbaee7c1bead9cfe0feefab4dba1012a3091023ca83fd200ff34c9c6d2471903d9d87ce7f0f2b0ff65928cfafa18dd2be503b4f7ee2dc16bc075cf4e4df75cb3fda277bd837be028cb68fba7e7ca14f07efbd3effebbf3ccefffa2fa843384f2bb0ca9f08e513578f20fcde427962fd3bcaf739bfec9ae533b15c01a6dfe4e9df91779a4917d2d77fb3beb785f5f57dbc13301edcfedd5b6fb9eeef788ff1d1be78f233e9ba775db27c4a409e11e0a7877e4ccedf019e07dbbede034936a80f75d98a4505e4e90fd776ae38e277d52b45f125e5ec0f4e74f84279065bedd44b1e987c9e37ec67e972af3a7ca53cc3a1fd7bd4a4e3709eb02dad73fc9fb65ced01c54ffbece1fd7e99f34bbf01a3f37bc661fb14b04664fbb6dfa4537f9fec90be02d2a9fe1d79eddf9353acf13d7ef45b3964b78fbb6c1d97803c671dfea78368fd0f7b1f00d9d3756724d433aa473edbcdb321319a0831a23cf86c85eeed943fecbeef637e75aefbfe5560b4db4decbbf864bb66b1d9cf505dfd41ca43c7627f7016b4b371475effcf86b37d9b42e6fc7b7e465e1fb3e299063be3414ff593e24cffc33e2ee55962ddcf7cf5592f5bdce4078ee15cb4b82f5971c56751cb81db756dba9e757aea73d6635fccee0f5d0476cab3daea0fd9fdb89b0e5fecfb7459d0f9bbe01b565ebc26731d67a7af5bc7e03303d73359fcadcb0560499b74f24eb6da641299ca1cb148049dbf93b99e33d07580758ecab2af153ab602f26cb4da243b6fe65ed6a7233e741ef159bbab4efa7a8e14f69c85ec6946d7efe8a26fbbeecddf2bf58cacdcc9eb4b718cbba7958ec676aa05ef15b96271d1c1e3eb9966582c2e3a6c47178bc60daefb872b16171c3cbebe6386c5e282c37684b1d8e47ab6e08ac579078fafef1a61b138efb01d5d2c26ddf65c23572c5e72f044ff4c23772c704cac10e60b0c987b5ae9686cd7af778dddb96271cec1e36bec2e2c16e71cb6a38b456da3eb3bbb2b16671d3cbed605098bc55987ede862d134d9f54cc5158b330e1e5feb6784c5e28cc37684f562233e5fcb158bd30e1e5f6b7284c5e2b4c37684fdc3c65ccf0c3116a71c3cbe9efd85c5e294c37684b168d6b64fe6118b930e9e93458ec54987ede862b1be41db3e91472c4e38784e143916271cb6a38b457393b6dd9e472cda1d3ced458e45bbc37684dfa132f5e2781eb138eee0f1b56e4a582c8e3b6c47178b964c5feb581eb138e6e0f1b5164b582c8e396c47178b64e69e7a348f581c75f01c2d722c8e3a6c47582f32df275fcc2316c57cff68582c5e74d88ef03e92a91747f288c51107cf9122c7e288c37674b1d89479fe74388f581c76f01c2e722c0e3b6c47f8cc25532f0ee5118b430e9e43458ec52187ede8625197b9a71ecc2316071d3c078b1c8b830edbd1c56263664cec401eb138e0e03950e4581c70d88eb0df99692ff6e7118bfd0e9efd458ec57e87ed08fb9d99e717fbf288c53e07cfbe22c7629fc376846d67a6dfd996472cda1c3c6d458e459bc37684fdce4c2cf6e6118bbd0e9ebd458ec55e87ed08fb9d99fbc89e3c62b1c7c1b3a7c8b1d8e3b01d61bdc8b49dbbf388c56e07cfee22c762b7c37684cfb5326de7ae3c62b1cbc1b3abc8b1d8e5b01de1f791cc33be9d79c462a78367679163b1d3613bc2b1a24c1f7c471eb1d8e1e0d951e458ec00db3ee699602c682ed6382b161590e701f332769a8b1516472a03e795a12fdb23f7253baf6c5b882fdbc117ca33107ce909fa28993cf99aa9335b4d593437fd86c357ca33744047de61261d87737213ca4a3afe4f5bae3948143fedf396e87dced4d5174c59747eb7386c6f02d6886cd7a26d9a9b4e76485f01e989033af2523e8a07c59ad8f535426b2520bb7ddc0eebb804e46975f89f0ea2f57f8bc5b3c562cefcee01ea19d5233f6d5796a9352446e320469407e7ecddf0c463cf21240eb2a7f3d0f9ef61e5c1399494a709da289c574a7ec683cef326b57f5b3df917b68e1bd94b80ee0a30da3eeafa9180b99fb5c41874e8686d075c83a9d1d2695f2779f2956c51d9b43f091869ad89c6e233a6f2656cb01835cf640f318b835dda72dd2f26034f93071e4f7e66ee43532c9f26593e25200ffeb6718a073f636097caa6fd2960dbc739c758d03d7994158b0ac8b3daea3f86c591cad0f5b7d1e18baf3836583c0d0edbd33dc791caa636717a116c4fb56cd75bb6f5b58d754c6fb9aeeda9c03ccd03b32e7746f4e566ae6d5a238dea33d9a9079fd21083a87c42db31ab6cd257407afb80ce0c140fba7712bbbe8eb0ee841d37d93a2e0179a63bfc4f47ecff0c8b07cfb1de74bf613df42b3d5c0f993a30dde2a0fd7a88dd8c90d84d87d8519e46d0511f670ae8a8af806b0ad2ffb11fd110bdbfceb687f61b809174b84e618383b13e7ac654aeb6b91e1849370d78a67a8ad9348b6794151fbc2ff7b0f2d0b11590a71dee8d71475e5df7ab621d7ed1da8511aef3936957bb7b8817aeab18407c022b86b41143cfa063edc52879ee0b606dc5b69d7b9a376f7c726376e891d02a2c4cfc8c39dc28031da6cb1dba20b87d09c90ad0d11292dd405766850597aea4fcb4a49d8f70613ca8ec0a8bb327b044691b97dfa42d57d5e9013c3eaab2ae3a95a62c53759edeb3a56d23d68f6e166757ea8efe5f798e7c6165513da8f0e03b3251d9b44ff6747c1226bdab79c3d6597b36efdbbe7147db5e84b52f2e4cc7ac20d89fae63b092e0c544e574b382d32bfae0d4e3c56bf305602f0096c0f0f48c9e27535169cdd60dcddbb62ddfb77edb960df3f7edd8d0b665e70e8c680f2b7261d1b62f79bdb99a3acc6be7efeed0d91bae90db0374b4426e4fd091fd5ea0238efbe07ff699f0724d8c80f2a91aebff551887bb1b87a80ad26d48b727fa9ae91d646ffffac95875903d7d7a895dbda4ae5e4257bfc141ffaa5af714f412b87ac95bbdc4ad5ed2562f61ab97acd54bd4d604d925688707d925661f0d3a9690d5db6780572f19abbb1a7a4958bd04ecd820fbb86e7c907db5997e9584eeb2eaafa3ba9ba7bf5ae82e97ee6ae96eadfecaae1fdfe86e8cee22eaee8feeb2e86eb0eefece34b19e15649790d64b46cf0db24b42cf0fb24b3e2f0cb24b3a2f0eb2cba12f0db24bd33e116497335f1e6497b9d5cbdfea6571f5d2e57ac95cbd94ae5e62572f51ae97dfd5cbf2ea65c8f592bd7a295fbdd4b85ee6f7f920bb9cf8fa20bb64704b905d4e583fbad6cb87ebc7f6fa71b67e54ac1f65eae1043d8ca21fb3eae13f3d1caa8787f570b99e3ea0a753e8e9257aba8d9e7ea4a763e9e9697aba9e9ebea8a773eae9ad7abaaf9efedc1e64a7c79f0cb23f9fd03f27d13fafd13f37d23fbf7a29c8fea450ff444fffe454ff04f772907d84aa7fcead87d5f4a353fd18593f5ed58f7af532bd7a595ebd0caf5e76572fb3ab97d5d5cbe8ea6573f532b97a595cbd0cee7b95fc8e92df55f23e25bfa7e4fd4a7e5fc91f28f943257fa4e4034afe58c907957c48c99f28f953257fa6e4cf957c58c947947c54c95f28f94b251f53f2574a3eaee4134afe5ac9df28f95b257fa7e4934afe5ec93f28f994924f07d9faf75925ffa8e49f94fcb3927f51f239259f57f205255f54f225255f56f215255f55f235255f57f20d25ffaae49b4afe4dc9b7947c5bc97794bcaee4bb4abea7e4fb4a7ea0e4874a7ea4e4c74a7ea2e4a74a7ea6e4e74a7ea1e4974a7e15742c038d8dc5ff373bc3cc7e735bdbc6edbbda6ada76d66cdfb7ad6dcbae6d876a0e6c697ba166e7fe8d7b366ddb79000ffea0699e68bdea597bf6341faad9b2a365e3c19a9dfbda6a766eaa59bf73df8e96db6e8e9f33070dea6cb1b9a525dcd877caee80f4fb5d34fa6b731cad04be28b76fffab2b01f97f5d39686079d71cfab8e9dcd1d7aea7b27dbc9abddb76b6d5246b76a8bfea66baf3c0c6960935f8bfbd2ac87bdb6af6b635ef69abd9b467e7f69ada0958eef8de5d70a2b5b71f98c1e65d405daa2a5fead7054ffe47bfae9d8effbc13525a4fbe50a3fdfa77c1c3415d3928dd45c2c5fd43c3b277dffab63dcd1bdac20f5e762707afea8a9b2d5d74b3ef802e187ba82b074d1ad035c2555d3176bc0063c17f03d9f72ad92c930400", "isInternal": false }, { "selector": { "value": 2603445359 }, - "bytecode": "0x1f8b08000000000000ffed9d79741cc5b5c67b6459963d1acbf2be5bac5e4648a319c9b6b08d65b3181bb3790163360b5b3606db32b60c983d648310080961c90664634908d94312b2ef2464812c2404b213c8bf39efe49d774e4edebb3553f7e853b96bdeb4dc35ae96ef9c7335d557357d7ff7ebdb353dd5dd336f0441900a4a8f1164c706873ef8ffddfa3977788ff618d79573c9994a08674d4238472484b336219c2313c2599710ce5109e1ac4f08e7e81839155b4d30f81137ef1807bac6cd984e98a60d09d03493304dc72640d3c6201963d4b88470362584737c42382724847362423827258473724238a72484736a4238a72584737a42386724847366423867258473764238e72484b339219cc72484f3d884701e9710cee363e49c079c27e8e713f5f35cfdcc7de6ebe705fa39ab9f5b748eb57af924b256b236c567fc4f9d68c89315c83af4ff9af5ff3ac916922d225b4cd6457632d912b2a564cbc84e215baef35f41b692ec54b2d3c84e273b836c15d99964abc9d6909d45b696ec6cb273c8ce253b8fec7cb27564ebc936182c1bc92e20bb906c13d945649bc92e26bb84ec52b2cbc82e27db42d6437605d956b26d64bd64dbc976905d49b693ec2ab2abc97691ed26db43d647b697ec1ab27d64fbc9fa0dcd0e905d4b761dd9f506e741b21bc86e24bb89ec66b25bc86e25bb8dec4d64b793bd99ec2d646f257b1bd9dbc9ee20bb93ec1d647791bd93ec6eb27bc8de45762fd9bbc9de43761fd97bc9ee277b80ec41b287340b17fbfbc8de4ff601b20f927d88ec61b247c81e25fb30d947c83e4af631b28f933d46f638d913644f927d82ec93644f917d8aec69b24f937d86ecb3649f23fb3cd917c8be48f625b267c8be4cf615b2af923d4bf635b2af937d83ec9b64df22fb36d977c8be4bf63db2ef93fd80ec87643f32347f8eecc7643f217b5eff8fe7907e4af633ddfeb97efe857e7e413fbf68bce69764bf327cbf26fb8de17b89ecb7bafd3bfdfcb27efebd7e7e453fbfaa9fffa09fffa89fffa49fffac9fffa29fffaa9fffa69f5fd3cf7fd7cfafebe737c80ae34bedfa60e0d11dc434ee74f476a9f30f2cf609c1e087d26284fe1f3f376b7fad5ee667d66ea45e1e69f8ebf4729db19e7abd5c6ff89bf47293e19fa0972718fe497a7992e19fa297a7803f1dc03ca4f62bdf08ed4a818febb0067c2383c19a285f1daf0e7ca382c15a281f6fc73af08dd6be51e01ba37df5e04b6bdf68d68cac41fbba83b86a22d7a3d69b897bbdfadcccd8f879b7aaf5363ae21d173f6faf5a6f93035e551f7ab808c641dd4cd0be26f04dd4bef1e09ba47d13c03759fb26826f8af64d02df54ed9b0cbe69da37057cd3b56f2af86668df34f0cdd4bee9e09ba57d33c0375bfb66826f8ef6cd025fb3f6cd06df31da37077cc76a5f33f88ed3be63c077bcf61d0b3e1e3f8f031f1fc31daf7d6a4cf85700afd1fe1af09dc8632ef8e6f2780bbe793cd6826f3e8fb3e05b00b1d9978531847d2ddac7e391fadf42ddee0ee2aafffc36b5de4571af97d6acd6db15ff7a8be7ad4e0e0674ed86388b40ab25ba1de3b531ed183ba58de3b0bf16daaba02ff7633df83d85d9d57bc762dd5e52e6750b8dd765a0cfe290fcbb8378f3ef3278ba0c6655ff4b8123fe9a2db44bcd56fc885cb31ba1af597b7c7c331c6b760d7038a8d94e37359bcf49cd96e6178220bcf6f8187738d6ec26e088bf663ba5662b7f44aed96ba0af597bfc396738d6ec76e088bf661775cab141c58fc8357b2bf4356b8f3feb0ec79aed070e0735db25e36cc58fc8357b37f4356b8fe75d8663cdde0e1cf1d76c97a39a2d48cd06a5734541105e7b3c07381c6bf65ee088bf66b776c9b141c58fc835fb24f4356b8fe7a38763cd3e0c1c0e6ad6d5fc6c5e6ab6748e3c08c26b8fcf8d0cc79a7d4ab7d579869febf30c33c1f70bed9b05be17b46f36f85ed4be399057fcfbc0b682ec03153f22ef03cf415fb3969b757b38ee03df000e0735db29355bf12372cdbe047dcdda3b56b78763cd3e0f1c0e6a7691d46cc58fc835fb1af4356b8faf5f188e35fbb26eabe385dfe9e38513c1f7b2f6cd05dfefb56f1ef85ed1bef9e07b55fb1680ef0fda9705df1fb5af057c7fd2be93c0f767ed6b05df5fb4af0d7c7fd5be1cf8fea67dede07b4dfbf2e0fbbbf615c0f7baf67580ef0dedebd43e754e80af4ff99ef6d5434edd417cdbb6784d4a30f8913296bba1dde296279709065f57cdb15ae38f5550b99f14549e7b2bf0b439c83d0d312ae169039e5cfc3cc56b2fdae35f6f711b9f64689a865827415e790779a52016af9b97395e067c381ee443180bf133e653108bd7cdcb0560641f8e4f3cbef2fea3c6e6b1a9015e07fb52f1fd19e3750307c7ab853e2f340df41dafd91ae0ff3c0634401bc7ef9ce17354abed787d3faf9b97db819173cc559f315f29639bc1580f6c31f214356b3378da42b4385a633b18ab8bfb1fc7e0fd8ff7258e570b7dfea766a0ef8929a76cf9a8efb3589ff18ffff91cee9b95f0e481c7c518e3e87d2e87ef4dff09e2adb50e43ab9ca15506fa1440bf0e07fa957bafe478c22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc2ec3f339e3fc6f36d61e7668f2423fbda81c7c53c7ff13b49f4ba78fdeabcce33705e27fef316f91c9e77e46bb2e61939d7429fe752036ccf869cf3c5f3bbad86cfd13517c56d89d75c74c332c7c373d0780d88ab73885983271ba2850fb19b638b9ddfea66fbe673ea3b01d4f7eab418db34ecfa9305864fd5e9bf6b06f27671ee2feab9481c4bb81de7b9bd4c70e8b5036eae71298d1f3c5ed50483c70f7c9fe98c3df6e073987cbebcd3885d0b7d5e4a0d6c9b85f0ffeee0d0eb72b00faf9b97e7c16b171aeb6e74976fd96b133a819bdb75466e2dc0cd7d5e81f1fc56d84f1cbcc7e5f1fab000780323277ee039fbf88f014ad710e423f074008f83ebc5da1d1debe4b01ee3be8660a1a155d83114f7e904fd62bf1e5eef1fe671302f733c61166661166661166661166661166661166661166661166661166661166661f69f19efef66d634f46bf784b14ad75d14cf67f0f76de079b1dd3503715d9f03e4734ef38d9c6ba1cfd335036cd7e8764370e8b516b66de9eadc9a6d5b72bc06c807cf05b9ba67bd60f01442b4f02176736cb14bd710c4bf7d07ae21c81bdbb4ddd89e78ee1cf7a15ba14ecdefb848833ed5b86ec9b66d381eee4b05f0711befcd76a135be9798d714713c3c777ea7d696cf9dc73f56e7732ec70dfeee2abe4e201f922bf7b907c6be7b751baf1f6987753d12f27f7e943b4fcdfa1d89eff1c2d83e7c8fd7c335037dcdefe362ada37e8f57ce789d8fdfe3751fd4d923f0feef6a4c5a1c846b340f34e23e781ce4e03a93d031d2bcb652f5e1ed3fcae883c72cdce77118a36cd7ae867df79183efe72bfbdd471c0f8f8d3b80d1ccd1bcc6f468bf46ec19182f16c2ffbb83c3bf46ec19a821bc4e2b30d63f1fd6cf5ca302fb7b0bf779d6781f75b56fd9ae41c37dcbfc3cc0bc780d1af7f9168c55ff84e32cf3d81fafd7aac6673bdbf5e11c0f8fa9a2e48ee342dcef8d588fc8c2f1b01e7f6cd4e3420b776bc86b7f6a792d6bc5d71ce36727533fa5c362784d772c3a94c69b2e2317dea716432edce797c67e13ff3153e9f833fe5c071f0ff1185408c995fbfc16f6b597e1f892b7138e95ff08f93f3fca1d7fb27e2ae7a5f1e75cdcbecbf4ba78fb2e0d897d0ab0c614bb1d63f3f127c7617f2db4df80f713eec77ab0d6ccaef6113e864376f3759dc6eb32d0674948fedd41bcf92f3578961accaa765e853afb071c7fba1aab9758349a0f1a711fbc278adf47b8bfed3dc6c5f5bee5de63c2be1f12c7f67f3a9dd30b6733e7f4c28e4fb80fbf168f4ffe1bc6d974485f73ae92df43e2bc6619ef11c942dc7f87c4ed8e59cf4c3058cf8cc1e13276a311bbb18ab19b8cd84d558c2d9a8be63e69eed3f77fe3f774d72480714402186b13c03832018c7509601c9500c6fa04308e4e00e3980430a681f148beb73bd0271f873e0da0534b08b7abfbf15b0c46f3bb1232062ff31cc963245fb7e158fdecf3366c049e6176ac19cb361ca79f7dde864d6e758c65bc1f9f00c60909609c9800c64909609c9c00c62909609c9a00c66909609c9e00c61909609c9900c65909609c9d00c63909606c4e00e33109603c36018cc72580f1f804309e9000c624cc552e70cb38e4cfd78ac7c16f4276e067f44a785c7fb7a6a33c8bd767f1758c717f479af9bb8e2d865678cf89ebdf834d05f6ef4ae578c22ccc36661c0bf1f7b9b95fd613c6b0ef1e76306e447e4f6975cb33e8b7b75bdd6e8bc8ef556e7f13b4f45e7534fc2668d8fd2d61dff7ce7d70dc3852d73162ece6205e2d3a2ad0a24af7603bf9befeb60432fbf21b033c3e85fdc640d613c62afdc640e4f7aa7c888ead6e19f3436574752f33d64b253cf8bd182e6aca4d9ee5bfcb99e3e1f77fe098e4ea9a7ef3fe385eaee43b4b84599885599885599885599885599885599885599885599885599885599885d90f663cc780dfe5ccfdb29e309adf93e4683e3ef2b99ace101d5bdd32e687ca88df7f161f4fe95c4d94efa95a043c2e6aca4d9ea57335e6f76d761a39e1f76de2feedea3bc816193cbcbc18b683300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb330fbcd8ce71898350dfdb29e30b26f21f0b8f83da6a8e7411685e8d8ea96313f5446c5e3e037e43ab05e2ae1c1dff57051538ef21cf45b79bcee45464e19e883fbf7c90ef24c05f6df8fc3dfd51366610e63c6318b59d3d02feb0923fb16038f83fd3bf2d8df15a263ab5bc6fc5019154ffcbf61593a4fdf1581077fd3c8454db9c9b334f69bbf9564fe566706fae0feede077b3427f27899797c27688c25c4820b3e82c3adb984567d1d9c62c3a8bce3666d15974b6318bcea2b38d5974169d6dcca2b3e86c63169d45671bb3e82c3adb9845e7a347673cc7c0ac69e897f584917d27038f83f9f8c8e76a9684e8d8ea96313f5446c5b32c769e420eeba5129e65c0e3a2a6dce4593a57738a91d31223a70cf4c131e9140779a6202eaf9b974f81ed30dc990b096496daa80eb3d48630db98a53684d9c62cb521cc3666a90d61b6314b6d08b38d596a43986dcc521bc26c6396da10661bb3d48630db98a53684d9c62cb521cc3666a90d61b6314b6d08b38d596a43986dcc3ed4065ea3c3ac69e897f584917d4b816799039ea8d7112d0bd1b1d52d637ea88c8a6779fc3c1d582f95f02c071e1735e528cfe2b54edd464ecb8c9c32d007c7a46e0779a6202eaf1bf30ef476e81666610e61c6318b59d3d02feb0923fb4e011e07fb77e4b17f79888ead6e19f34365543c2b1cf12c8fc0b30278bae3e76977946771ec5f69e4b4dcc829037d70ff5ee920cf14c4e575f3f24ad80e4963c67d8959d3d02feb0923d618f338a8bbc863d28a101d5b13c0d89600c6d109601c9300c63430661d30a6743ce4e1e5ac5b7df271e8d3003af93aee6580c7d5366c34781a43b4f0751b8ed5cf3e6fc346e071b50d9b0c9ea6102d7cdd86e3f4b3cfdbb0c9ad8eb18cf7e313c03821018c1313c03829018c9313c03825018c5313c0382d018cd313c03823018c3313c0382b018cb313c03827018c38a771243fe71ec9cf6747f27385682e9ae70eef219a8be6a2b9682e9a07a279eef01ea2b9c79a27e13384300e6fc682a78cc8938a8f2787b963ac951ee4ce0c49632c2480d1f57546a2632c8cf9a1322a9ed31cf1ac8cc0731af09c1a3f4fbba33c8bd71a9e6ee4b4d2c829037db00e4e7790670ae2f2ba79f974d80e4963c67d8959d3d02feb0923fb4e051e57fb5794fd1df7af331cf19c1681e70ce071b1bd1ce559dcdf5719399d66e494813eb8efac7290670ae2f2ba7979156c87a431e3feceac69e897f584917da7038fabfd2bcafe8efbd7998e78ce88c07326f0b8d85e8ef22ceeefab8d9cce3072ca401fdc77563bc833057179ddbcbc1ab643d298717f67d634f4cb7ac2c8be55c0e3a0ee227fe6383344c7b604301612c0283a8a8e3e318a8e478f8ec2288cc2288c4782310963b8bccf449f1bc0cfe26be2e7e9c0cf6d95f0ac011e179fed1ce5599c1b38cbc8e94c23a70cf4c13a38cb419e2988cbebe6e5b3603b08b3308731e398c5ac69e897f584917dab81c7c1fe1d79ec5f13a263ab5bc6fc501915cfdad8793a72582f95f0ac051e1735e526cfd2d87fb691d31a23a70cf4c1fdfb6c0779a6202eaf9b97cf86ed1085b9904066d15974b6318bcea2b38d5974169d6dcca2b3e86c63169d45671bb3e82c3adb984567d1d9c62c3a8bce3666d15974b6318bcea2b38d5974169d6dcca2b3e86c63169d45671bb3e82c3adb984567d1d9c62c3a8bce3666d15974b6318bcea2b38d5974169d6dcca2b3e86c63169d87c6ac78f8ba73664d43bfac278cec3b0b78d63ae0897a1dfeda101d5bdd32e687caa878ce899fa703eba5129e7380c7454d39cab378afc0b9464e6b8d9c32d007c7a4731de49982b8bc6e5e3e17b64314e642029945e7a131e398c5ac69e897f584917d67038f83fd3bf2d87f4e888ead6e19f34365543ce7c5cfd381f55209cf79c0e3a2a61ce5591cfbcf37723ac7c829037d704c3adf419e2988cbebe6e5f3613b08b3308731e398c5ac69e897f584917de7028f83fd3bf2d87f5e888ead6e19f34365543ceb62e7c9e7b05e2ae159073c2e6aca4d9ea5b17fbd91d379464e19e883fbf77a0779a6202eaf9b97d7c37688c25c4820b3e82c3adb984567d1d9c62c3a8bce3666d15974b6318bcea2b38d5974169d6dcca2b3e86c63169d45671bb3e82c3adb9845e7a347673cc7c0ac69e897f584917de7038f83f9f8c8e76ad685e8d8ea96313f5446c5b321769e420eeba5129e0dc0e3a2a6dce4593a57b3d1c8699d915306fae098b4d1419e2988cbebe6e58db01d863b732181cc521bd56196da10661bb3d48630db98a53684d9c62cb521cc3666a90d61b6314b6d08b38d596a43986dcc521bc26c6396da10661bb3d48630db98a53684d9c62cb521cc3666a90d61b6314b6d08b38dd987dac06b7498350dfdb29e30b26f3df06c70c013f53aa20d213ab6ba65cc0f9551f15c103f4f07d64b253c17008f8b9a729467f15aa70b8d9c36183965a00f8e49173ac833057179ddbc7c216c076116e630661cb398350dfdb29e30b26f23f038d8bf238ffd1784e8d8ea96313f5446c5b3297e9e0eac974a7836018f8b9a72946771ecbfc8c8e90223a70cf4c1fdfb220779a6202eaf9b972f82ed20ccc21cc68c6316b3a6a15fd61346f65d083c0ef6efc863ffa6101d5bdd32e687caa87836c7cfd381f55209cf66e07151538ef22c8efd171b396d3272ca401fdcbf2f7690670ae2f2ba79f962d80ec22ccc61cc3866316b1afa653d6164df45c0e360ff8e3cf66f0ed1b135018c6d09602c2480d1b18ef9a1322a9e4b1cf16c8ec07309f0b8183f1ce5597c9fbfd4c869b3915306fa601d5cea20cf14c4e575f3f2a5b01d92c68cfb12b3a6a15fd61346f65d0c3caef6af28fb3bee5f9739e2b92402cf65c0e3627b39cab3b8bf5f6ee47489915306fae0be73b9833c531097d7cdcb97c376481a33eeefcc9a867e594f18d97729f0b8dabfa2ecefb87f6d71c47359049e2dc0e3627b39cab3b8bff718395d66e494813eb8eff438c833057179ddbcccf192c88cfb3bb3a6a15fd61346f65d0e3c5b1cf044dddfb70063d8670e5f190b0960141d45479f1845c7a34747611446618cc6b822018cb2ad85d157c6ac03c6948e873cbc9cad42ec4623766315633719b19baa185b3417cd4573d15c3417cd0f37b6682e9a8be6a2b9682e9a1f6e6cd15c3417cd4573d15c343fdcd8a2b9682e9a8be6a2b9687eb8b14573d1dc8cdd137fecc8d773f700cf16075a38ca33a7d67b855ed77f62d44f69b5d5d02a6b6895813e57807e5b1de81776cd352f73bca8cc277ac0ec28767e2cad6334e4cf310a861e2afe3647b9dbc6bc6d55886d1bf3aa11db36e65523b6682e9a8be647afe6d8ae0d0ebd0749ada357b747ea65eebf025ec77d1e68283d3706b23d5dc4967d483417cd45f323a139ea5253059ec0e009caf0ccf68c67aa673ce33de319ed19cf08cf78e67ac633c7339e699ef14cf08c678c673cb59ef14cf78c67a2673c69cf78467ac633cf339e199ef1ccf78c6792673c0d9ef1643ce3a9f38c67a6673c933de319eb194fa3673c0b3ce319e5194f8f673cb33ce399e219cf38cf789a3ce3a9f78c27e5014f3a38f49a9a34fcbf077c35c66bd5783571fcc0ffb76b7f0dbc66876e8f0859f776f0f1b9aa1d21af459db6432eddba9d3bbc4751278cd50dcb1caf01387678c253ef194f93673ce33ce399e219cf2ccf787a3ce319e519cf02cf781a3de319eb19cf64cf78667ac653e7194fc6339e06cf782679c633df339e199ef1ccf38c67a4673c69cf78267ac633dd339e5acf78c678c633c1339e699ef1ccf18c67ae673c233ce319ed19cf78cf78a67ac633db339e9a109e1e473c3c7fc9ebe6e51e4f623bd80ec5fb16af7494d34ebdae3abd5ee6e778b5d0e721fdc14dcd47e06b99cb9c6fc6b9a69da051afa35c6cd72ef75621b6eddae56ac4b65dbb5c8dd8a2b9682e9a8be6ea11e33df59d72bf45e53c72bf45791eb9dfa23ccf5ccf78e47e8bf23c72bf45791eb9dfa23c8fdc6f519e47eeb728cfd3e3198fdcff519e47eeff28cf23f77f94e791fb3fcaf3c8fd1fe579e4fe8ff23c72bf45791eb9dfa23c8fdc6f7128cfff77bf05de27c1e7a67ac177a56ef780af262406af6727f86a759bd7a1c69b39e30f65a881d75c15c27565483c8e7355c86baba13bc6ea86658e87f76f5ce5094fbd673c4d9ef18cf38c678a673cb33ce319e519cf02cf781a3de319eb19cf64cf78667ac653e7194fc6339e06cf782679c633df339e199ef1f478c633cf339e919ef1a43de399e819cf74cf786a3de319e319cf04cf78a679c633c7339eb99ef18cf08c67b4673ce33de399ea19cf6ccf786a42787a1cf1d8aea3eda9426cdb75b4d5886dbb8eb61ab14573d15c343fba35bf3afed81de960f06fb6a947ca58ee86f6d5c0e3e2fdce519ec5fbef76e975c5788f434e69b5dbd0aac7d02a037d76817ebb1de89782b8bc6e5ee678c22ccc3666157b4ffcb18be30cc6667d0283871f7b1c6be128cfe278d017846bccf132d007b7799f833c531097d7cdcb7d21b19b8378b5d85b81167b4378f656590b8e1795795702997dd059c5be26f6d8f95cda88cdfa04060f3fae71ac859b3c4bfbd6be205c638e97813e58a7fb1ce49982b8bc6e5ede07db4198855998855998855998855998855998855998855998855998855998855998fd6656b1f7c71ebb347f8fb1599fc0e0e1c77ec75ab8c9b3347fdf1f846bccf132d007b779bf833c531097d7cdcbfdb01d84599885599885599885599885599885599885599885599885599885599885d96f6615fb40fcb18bf7f9606cd6273078f871c0b1168ef22ccedf5f1b846bccf132d007b7f9b50ef24c415c5e372f5f0bdb419885398c59c5be2ef6d8a5f379189bf5090c1e7e5ce7580b377996c683eb83708d395e06fae036bfde419e2988cbebe6e5eb613b4461ee4b20b3e82c3adb984567d1d9c62c3a8bce3666d15974b6318bcea2b38d5974169d6dcca2b3e86c63169d45671bb3e82c3adb9845e7a3476715fb60ecb10bc5f97b8ccdfa04060f3f0e3ad6c24d9ea5f9fb1b82708d395e06fa609ddee020cf14c4e575f3f20db01d863b735f0299a536aac32cb521cc3666a90d61b6314b6d08b38d596a43986dcc521bc26c6396da10661bb3d48630db98a53684d9c62cb521cc3666a90d61b6314b6d08b38d596a43986dcc521bc26c6396da10661bb30fb5a162df187fece2fdec189bf5090c1e7edce8580b477916af7fb92908d798e365a00fd6e94d0ef24c415c5e372fdf04db419885398c59c5be39fed8f9b4119bf5090c1e7edcec580b477916c7835b82708d395e06fae036bfc5419e2988cbebe6e55b603b248d19b75f2abed8c5eb3639468d7e56be5b757b04f86ed3ed5af0bd49b74782ef76ddae03df9b757b14f8de02b9b1efadbabd007c6fd3ed1ef0bd5db7b781ef0eddbe1a7c77eaf66ef0bd43b7f780ef2eddde0bbe77eaf635e0bb5bb7f781ef1eddde0fbe77e9763ff8eed5ed03e07bb76e5f0bbef7e8f675e0bb4fb7af07df7b75fb20f8eed7ed1bc0f7806edf08be0775fb26f03da4dbbbc0f73edd1e0dbef7ebf618f07d00dafcfc41dd6e00df87743b03be87757b2cf81ed1ed46f03daadbe3c0f761dd6e02df47747b3cf83eaadb13c0f731dd9e08be8febf624f03da6db93c1f7b86e4f01df13ba3d157c4feaf634f07d42b7a783ef93ba3d037c4fe9f64cf07d4ab76781ef69dd9e0dbe4febf61cf07d46b771fb7e56b76f061f8f03b7808fc7815bc1c7e3c06de0e371e04de0e371e076f0f138f066f0f138f016f071ddbd157c5c776f031fd7dddbc1c7757707f8b8eeee041fd7dd3bc0c7757717f8b8eede093eaebbbbc1c775770ff8b8eede053eaebb7bc1c775f76ef071ddbd077c5c77f7818febeebde0e3babb1f7c5c770f808febee41f071dd3d043eaebbf7818febeefde0e3bac371a159b73f08be6374fb43e03b56b71f06df71bafd08f88ed7ed47c177826e7f187c27eaf647c03757b73f0abe79bafd31f0cdd7ed8f838fdf9b1e035f56b71f075f8b6e3f01be9374fb49f0b5eaf627c0d7a6db9f045f4eb79f025fbb6e7f0a7c79dd7e1a7c05ddfe34f83a74fb33e0ebd46d1e17d4fed700b9709e0dc07d52080ffbea81a73b88f7988963f1ba79390f8cac637bf519f39532e60c46c5d3e14033ac0d7e94fb4cd2013c05073c8ef22c7e26e93472ca1b3965a0cf899067a7833c531097d7cdcb9d10dbc536472deaf47ae71a5ad4429f37f41b9a7aff2ba723af43d56f7b482eae74cc193cb990d88b1debc8ebe631717115622f3462b719b1713ce747b97d7b21302f72c0acd6db15ff7a8bfbf6c97a5d5ccf1ca70d725a021ac49513c64e69e338ecaf85f6ff360df4e57eac07bf7732bbda8f785b22bbf9ba0ee37519e8b33824ffee20defcbb0c9e2e83591dffff57d3008783fda158038b0d0e5e6e03edba2cda2d06edb84f3bf8f818a7137c7cacc0ebc063253c8e68893fdfd0b187975b80917d0b81b12584b13d7ec6e2b14e8bc1d812a22dfb1601cf42479a2d3278e61afae0fbf228a30fbfb616fa8cd71fec1a83c19f21b8afaafdb1a981bcf833f37f8278c7d53a077ae1e7f900f4090c0df9c10cf5c1c067fe3879c604039fe9f7f7f7edebd9d1bbaeb7675b0ad06a0d4c7c4e85a451033e6c8f08f105c1e0a90b9cf2e4a90b9cf2ac3164c12913eeaf3e4aa9b4787aa077f7cefe8d7b7af76cdd77706f7fefb6b57d3b907aa4418fa4b60c90147dfca80f062659ba83784f76d419b1ca154f3d3c8f8a9fa7dd519ec5379ed1464e75464e19e83312fe37da419e2988cbebe6e5d121b1631c888a5a8ca9408b31213c63aaac054e54b30ff754fe3f9e9ca83172c13d1a7332eb3cd68438e009b0fe948653ff533bfb489dcca8606063f3e8a98e2ad54650339cea5d4bcd60aa83333504a919493503a9661cd50ca39a515433886ac650cd10aa19413503a866fcd40c9f9ad16b0e4a33766a864ecdc81d0f5cdf0356f5895abd3baa19353583a666ccd451957af7574722eae8571da9a94f6feae8407daa54330cea9d561dc5a87768f5aeaa8ed4d4119a3aa25647984bc996919d42b65c6bbd826c25d9a964a7919d4e7606d92ab233c95693ad213b8b6c2dd9d964e7909d4b761ed9f964ebc8d6936d20db487601d985649bc82e22db4c7631d9256497925d467639d996a07456ea0ab2ad41e96c542fd976b21d645792ed24bb2a289d955233efea4c943af3a4ae8651679bd4d9257536499d3d52678bd4d9217536489dfd51677bd4d91d7536479dbd51676bd44cbd9a995733f1b705a5997635b3ae66d2d5ccb99a295733e36a26fc8ea034d3ad66b6ef0a4a33d76aa65acd4cab996835f3ac669ad5ccb29a495633c76aa658cd0cab996035f3ab667ad5ccae9ac95533b76aa656cdccaa99d84783d24cab9a595533a96ae654cd94aa99513513fa44509ae954339b6a2653cd5caa994a3533a96622d5cca39a69fc1cd9e7c9be40f645b22f913d43f665b2af907d95ec59b2af917d9dec1b64df24fb16d9b7c9be43f6dda05483df27fb01d90fc97e44f61cd98fc97e42f63cd94fc97e46f673b25f90bd40f622d92fc97e45f66bb2df90bd44f65bb2df91bd4cf67bb257c85e25fb03d91fc9fe44f667b2bf90fd95ec6f64af91fd9dec75b2378281330e3850fc462ff0ec774f7f7fefeebdfdcdfd7dcdbb0feceadfb977d7c1e6eb76f65fd9dc776defbeedbbfaaec317dfa187269eda5fb16f5fcfc1e69d7bb6f55edfdc77a0bfb96f7bf3157d07f66cdb8f2f7a4cbf68e6a1117bb66db307fb52cd61907e7588419fd3afe39326abcbe7f6fc50047971282ffad71013ba5f9f8a5aaa97d7978e689bf7efeaeb6fce35efa1bf3dbbe835bddb5a9bf17ffb49e4fdfdcdfbfb7bf6f5376fdfd7b7bbb9bd15d7fb60660849bcde348417358daf3cf3e0ff00fdc58975355f0300", + "bytecode": "0x1f8b08000000000000ffed9d79741cc5b5c67b6459963d1acbf2be5bac5e4648a319c9b6b08d65b3181bb3790163360b5b3606db32b60c983d648310080961c90664634908d94312b2ef2464812c2404b213c8bf39efe49d774e4edebb3553f7e853b96bdeb4dc35ae96ef9c7335d557357d7ff7ebdb353dd5dd33a9a0f478832ca5db23c88e0d0e7df0ffbbf573eef01eed31ae2be792339510ce9a84708e4808676d4238472684b32e219ca312c2599f10ced131722ab69a60f0236ede310e748d9b319d304d1b12a06926619a8e4d80a68d4132c6a87109e16c4a08e7f884704e4808e7c484704e4a08e7e484704e4908e7d484704e4b08e7f48470ce4808e7cc8470ce4a08e7ec8470ce4908677342388f4908e7b109e13c2e219cc7c7c8390f384fd0cf27eae7b9fa99fbccd7cf0bf473563fb7e81c6bf5f24964ad646d8acff89f3ad190272b9075e8ff35ebff75922d245b44b698ac8bec64b225644bc996919d42b65ce7bf826c25d9a964a7919d4e7606d92ab233c95693ad213b8b6c2dd9d964e7909d4b761ed9f964ebc8d6936d305836925d407621d926b28bc836935d4c7609d9a56497915d4eb685ac87ec0ab2ad64dbc87ac9b693ed20bb926c27d955645793ed22db4db687ac8f6c2fd93564fbc8f693f51b9a1d20bb96ec3ab2eb0dce83643790dd487613d9cd64b790dd4a761bd99bc86e277b33d95bc8de4af636b2b793dd417627d93bc8ee227b27d9dd64f790bd8bec5eb27793bd87ec3eb2f792dd4ff600d983640f69162ef6f791bd9fec03641f24fb10d9c3648f903d4af661b28f907d94ec63641f277b8cec71b227c89e24fb04d927c99e22fb14d9d3649f26fb0cd967c93e47f679b22f907d91ec4b64cf907d99ec2b645f257b96ec6b645f27fb06d937c9be45f66db2ef907d97ec7b64df27fb01d90fc97e6468fe1cd98fc97e42f6bcfe1fcf21fd94ec67bafd73fdfc0bfdfc827e7ed178cd2fc97e65f87e4df61bc3f712d96f75fb77faf965fdfc7bfdfc8a7e7e553fff413fff513fff493fff593fff453fff553fff4d3fbfa69fffae9f5fd7cfeafc63617ca95d1f0c3cba8398c69d8ede2e75fe81c53e2118fc505a8cd0ffe3e766edafd5cbfcccda8dd4cb230d7f9d5eae33d653af97eb0d7f935e6e32fc13f4f204c33f492f4f32fc53f4f214f0a7039887d47ee51ba15d29f0711dd6806f64305813e5abe3d5816f5430580be5e3ed5807bed1da370a7c63b4af1e7c69ed1bcd9a9135685f7710574de47ad47a3371af579f9b191b3fef56b5de4647bce3e2e7ed55eb6d72c0abea430f17c138a89b09dad704be89da371e7c93b46f02f8266bdf44f04dd1be49e09baa7d93c1374dfba6806fbaf64d05df0ced9b06be99da371d7cb3b46f06f8666bdf4cf0cdd1be59e06bd6bed9e03b46fbe680ef58ed6b06df71da770cf88ed7be63c1c7e3e771e0e363b8e3b54f8d09ff0ae035da5f03be1379cc05df5c1e6fc1378fc75af0cde771167c0b2036fbb23086b0af45fb783c52ff5ba8dbdd415cf59fdfa6d6bb28eef5d29ad57abbe25f6ff1bcd5c9c180aedd10671168b544b763bc36a61d63a7b4711cf6d7427b15f4e57eac07bfa730bb7aef58acdb4bcabc6ea1f1ba0cf4591c927f77106ffe5d064f97c1acea7f2970c45fb38576a9d98a1f916b7623f4356b8f8f6f8663cdae010e0735dbe9a666f339a9d9d2fc421084d71e1fe30ec79add041cf1d76ca7d46ce58fc8357b0df4356b8f3fe70cc79add0e1cf1d7eca24e3936a8f811b9666f85be66edf167dde158b3fdc0e1a066bb649cadf811b966ef86be66edf1bccb70acd9db8123fe9aed7254b305a9d9a074ae2808c26b8fe7008763cdde0b1cf1d7ecd62e3936a8f811b9669f84be66edf17cf470acd98781c341cdba9a9fcd4bcd96ce91074178edf1b991e158b34fe9b63acff0737d9e6126f87ea17db3c0f782f6cd06df8bda3707f28a7f1fd856907da0e247e47de039e86bd672b36e0fc77de01bc0e1a0663ba5662b7e44aed997a0af597bc7eaf670acd9e781c341cd2e929aadf811b9665f83be66edf1f50bc3b1665fd66d75bcf03b7dbc7022f85ed6beb9e0fbbdf6cd03df2bda371f7caf6adf02f0fd41fbb2e0fba3f6b580ef4fda7712f8feac7dade0fb8bf6b581efafda9703dfdfb4af1d7caf695f1e7c7fd7be02f85ed7be0ef0bda17d9ddaa7ce09f0f529dfd3be7ac8a93b886fdb16af4909063f52c67237b45bdcf2e432c1e0ebaa39566bfcb10a2af79382ca736f059e3607b9a72146253c6dc0938b9fa778ed457bfceb2d6ee3930c4dd310eb24c82bef20af14c4e275f332c7cb800fc7837c0863217ec67c0a62f1ba79b9008cecc3f189c757de7fd4d83c3635c0eb605f2abe3f63bc6ee0e078b5d0e785a681bee3355b03fc9fc7800668e3f89d337c8e6ab51dafefe775f3723b30728eb9ea33e62b656c3318eb812d469ea2666d064f5b8816476b6c07637571ffe318bcfff1bec4f16aa1cfffd40cf43d31e5942d1ff57d16eb33fef13f9fc37db3129e3cf0b818631cbdcfe5f0bde93f41bcb5d661689533b4ca409f02e8d7e140bf72ef951c4f98855998855998855998855998855998855998855998855998855998855998fd67c6f3c778be2decdcec9164645f3bf0b898e72f7e27895e17af5f9dd77906ceebc47fde229fc3f38e7c4dd63c23e75ae8f35c6a80edd99073be787eb7d5f039bae6a2b82df19a8b6e58e678780e1aaf0171750e316bf06443b4f02176736cb1f35bdd6cdf7c4e7d2780fa5e9d16639b865d7fb2c0f0a93afd77cd40de2ecefd453d17896309b7e33cb797090ebd76c0cd352ea5f183c7ab9a60f0f881ef339db1c71e7c0e93cf97771ab16ba1cf4ba9816db310fedf1d1c7a5d0ef6e175f3f23c78ed4263dd8deef22d7b6d42277073bbcec8ad05b8b9cf2b309edf0afb8983f7b83c5e1f16006f60e4c40f3c671fff3140e91a827c049e0ee07170bd58bba3639d1cd663dcd7102c34b40a3b86e23e9da05fecd7c3ebfdc33c0ee6658e27ccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccfe33e3fdddcc9a867eed9e3056e9ba8be2f90cfebe0d3c2fb6bb6620aeeb73807cce69be91732df479ba6680ed1add6e080ebdd6c2b62d5d9d5bb36d4b8ed700f9e0b92057f7ac170c9e4288163ec46e8e2d76e91a82f8b7efc0350479639bb61bdb13cf9de33e742bd4a9f91d1769d0a71ad72dd9b60dc7c37da9003e6ee3bdd92eb4c6f712f39a228e87e7ceefd4daf2b9f3f8c7ea7ccee5b8c1df5dc5d709e44372e53ef7c0d877af6ee3f523edb0ae4742fecf8f72e7a959bf23f13d5e18db87eff17ab866a0aff97d5cac75d4eff1ca19aff3f17bbcee833a7b04deff5d8d498b83708de68146dc078f831c5c67123a469ad756aa3ebcfd47197df09885fb3c0e6394eddad5b0ef3e72f0fd7c65bffb88e3e1b17107309a399ad7981eedd7883d03e3c542f87f7770f8d7883d033584d76905c6fae7c3fa996b54607f6fe13ecf1aefa3aef62ddb3568b86f999f079817af41e33edf82b1ea9f709c651efbe3f55ad5f86c67bb3e9ce3e1315594dc715c88fbbd11eb1159381ed6e38f8d7a5c68e16e0d79ed4f2daf65adf89a63fcec64eaa774580cafe98e4587d278d365e4c2fbd462c885fbfcd2d86fe23f662a1d7fc69febe0e3211e830a21b9729fdfc2bef6321c5ff276c2b1f21f21ffe747b9e34fd64fe5bc34fe9c8bdb77995e176fdfa521b14f01d69862b7636c3efee438ecaf85f61bf07ec2fd580fd69ad9d53ec2c770c86ebeaed3785d06fa2c09c9bf3b8837ffa506cf528359d5ceab5067ff80e34f5763f5128b46f34123ee83f744f1fb08f7b7bdc7b8b8deb7dc7b4cd8f743e2d8fe4fa7737ae16ce69c5ed8f109f7e1d7e2f1c97fc3389b0ee96bce55f27b489cd72ce33d225988fbef90b8dd31eb990906eb9931385cc66e3462375631769311bba98ab14573d1dc27cd7dfafe6ffc9eee9a04308e4800636d0218472680b12e018ca312c0589f00c6d109601c9300c634301ec9f77607fae4e3d0a701746a09e176753f7e8bc1687e5742c6e0659e23798ce4eb361cab9f7dde868dc033cc8e3563d986e3f4b3cfdbb0c9ad8eb18cf7e313c03821018c1313c03829018c9313c03825018c5313c0382d018cd313c03823018c3313c0382b018cb313c03827018ccd09603c26018cc72680f1b804301e9f00c61312c09884b9ca056e1987fcf95af138f84dc80efc8c5e098febefd6749467f1fa2cbe8e31eeef48337fd7b1c5d00aef3971fd7bb0a9c0fe5da91c4f9885d9c68c6321fe3e37f7cb7ac218f6ddc30ec68dc8ef29ad6e7906fdf676abdb6d11f9bdcaed6f8296deab8e86df040dbbbf25ecfbdeb90f8e1b47ea3a468cdd1cc4ab4547055a54e91e6c27dfd7df9640665f7e6380c7a7b0df18c87ac258a5df1888fc5e950fd1b1d52d637ea88caeee65c67aa98407bf17c3454db9c9b3fc7739733cfcfe0f1c935c5dd36fde1fc7cb957c6789300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb330fbc18ce718f0bb9cb95fd61346f37b921ccdc7473e57d319a263ab5bc6fc5019f1fbcfe2e3299dab89f23d558b80c7454db9c9b374aec6fcbecd4e2327fcbe4ddcbf5d7d07d92283879717c3761066611666611666611666611666611666611666611666611666611666611666bf99f11c03b3a6a15fd61346f62d041e17bfc714f53cc8a2101d5bdd32e687caa8781cfc865c07d64b253cf8bb1e2e6aca519e837e2b8fd7bdc8c829037d70ff3ed9419ea9c0fefb71f8bb7ac22ccc61cc3866316b1afa653d6164df62e071b07f471efbbb42746c75cb981f2aa3e289ff372c4be7e9bb22f0e06f1ab9a829377996c67ef3b792ccdfeacc401fdcbf1dfc6e56e8ef24f1f252d80e51980b0964169d45671bb3e82c3adb984567d1d9c62c3a8bce3666d15974b6318bcea2b38d5974169d6dcca2b3e86c63169d45671bb3e87cf4e88ce71898350dfdb29e30b2ef64e071301f1ff95ccd92101d5bdd32e687caa87896c5ce53c861bd54c2b30c785cd4949b3c4be76a4e31725a62e494813e38269de220cf14c4e575f3f229b01d863b732181cc521bd56196da10661bb3d48630db98a53684d9c62cb521cc3666a90d61b6314b6d08b38d596a43986dcc521bc26c6396da10661bb3d48630db98a53684d9c62cb521cc3666a90d61b6314b6d08b38dd987dac06b7498350dfdb29e30b26f29f02c73c013f53aa265213ab6ba65cc0f9551f12c8f9fa703eba5129ee5c0e3a2a61ce559bcd6a9dbc86999915306fae098d4ed20cf14c4e57563de81de0eddc22ccc21cc3866316b1afa653d6164df29c0e360ff8e3cf62f0fd1b1d52d637ea88c8a6785239ee5117856004f77fc3ced8ef22c8efd2b8d9c961b3965a00feedf2b1de49982b8bc6e5e5e09db2169ccb82f316b1afa653d61c41a631e077517794c5a11a2636b0218db12c0383a018c6312c09806c6ac03c6948e873cbc9c75ab4f3e0e7d1a40275fc7bd0cf0b8da868d064f638816be6ec3b1fad9e76dd8083caeb66193c1d314a285afdb709c7ef6791b36b9d53196f17e7c02182724807162021827258071720218a72480716a0218a72580717a02186724807166021867258071760218e7248011e7348ee4e7dc23f9f9ec487eae10cd45f3dce13d4473d15c3417cd45f34034cf1dde4334f758f3247c8610c6e1cd58f094117952f1f1e430778cb5d283dc9921698c850430babece48748c85313f5446c5739a239e9511784e039e53e3e769779467f15ac3d38d9c561a3965a00fd6c1e90ef24c415c5e372f9f0edb2169ccb82f316b1afa653d6164dfa9c0e36aff8ab2bfe3fe7586239ed322f09c013c2eb697a33c8bfbfb2a23a7d38c9c32d007f79d550ef24c415c5e372faf82ed903466dcdf99350dfdb29e30b2ef74e071b57f45d9df71ff3ad311cf191178ce041e17dbcb519ec5fd7db591d319464e19e883fbce6a0779a6202eaf9b9757c376481a33eeefcc9a867e594f18d9b70a781cd45de4cf1c6786e8d89600c64202184547d1d12746d1f1e8d1511885511885f1483026610c97f799e87303f8597c4dfc3c1df8b9ad129e35c0e3e2b39da33c8b73036719399d69e494813e58076739c833057179ddbc7c166c076116e630661cb398350dfdb29e30b26f35f038d8bf238ffd6b42746c75cb981f2aa3e2591b3b4f470eeba5129eb5c0e3a2a6dce4591afbcf36725a63e494813eb87f9fed20cf14c4e575f3f2d9b01da2301712c82c3a8bce3666d15974b6318bcea2b38d5974169d6dcca2b3e86c63169d45671bb3e82c3adb984567d1d9c62c3a8bce3666d15974b6318bcea2b38d5974169d6dcca2b3e86c63169d45671bb3e82c3adb984567d1d9c62c3a8bce3666d15974b6318bcea2b38d5974169d6dcca2f3d098150f5f77ceac69e897f584917d6701cf5a073c51afc35f1ba263ab5bc6fc501915cf39f1f37460bd54c2730ef0b8a829477916ef1538d7c869ad915306fae09874ae833c531097d7cdcbe7c27688c25c4820b3e83c34661cb398350dfdb29e30b2ef6ce071b07f471efbcf09d1b1d52d637ea88c8ae7bcf8793ab05e2ae1390f785cd494a33c8b63fff9464ee7183965a00f8e49e73bc833057179ddbc7c3e6c076116e630661cb398350dfdb29e30b2ef5ce071b07f471efbcf0bd1b1d52d637ea88c8a675dec3cf91cd64b253ceb80c7454db9c9b334f6af37723acfc829037d70ff5eef20cf14c4e575f3f27ad80e51980b0964169d45671bb3e82c3adb984567d1d9c62c3a8bce3666d15974b6318bcea2b38d5974169d6dcca2b3e86c63169d45671bb3e87cf4e88ce71898350dfdb29e30b2ef7ce071301f1ff95ccdba101d5bdd32e687caa87836c4ce53c861bd54c2b301785cd4949b3c4be76a361a39ad3372ca401f1c93363ac833057179ddbcbc11b6c370672e2490596aa33acc521bc26c6396da10661bb3d48630db98a53684d9c62cb521cc3666a90d61b6314b6d08b38d596a43986dcc521bc26c6396da10661bb3d48630db98a53684d9c62cb521cc3666a90d61b631fb501b788d0eb3a6a15fd61346f6ad079e0d0e78a25e47b42144c756b78cf9a1322a9e0be2e7e9c07aa984e702e07151538ef22c5eeb74a191d30623a70cf4c131e9420779a6202eaf9b972f84ed20ccc21cc68c6316b3a6a15fd61346f66d041e07fb77e4b1ff82101d5bdd32e687caa87836c5cfd381f55209cf26e07151538ef22c8efd1719395d60e494813eb87f5fe420cf14c4e575f3f245b01d845998c39871cc62d634f4cb7ac2c8be0b81c7c1fe1d79ecdf14a263ab5bc6fc501915cfe6f8793ab05e2ae1d90c3c2e6aca519ec5b1ff6223a74d464e19e883fbf7c50ef24c415c5e372f5f0cdb419885398c19c72c664d43bfac278cecbb08781cecdf91c7fecd213ab62680b12d018c8504303ad6313f5446c57389239ecd11782e011e17e387a33c8beff3971a396d3672ca401fac834b1de49982b8bc6e5ebe14b643d298715f62d634f4cb7ac2c8be8b81c7d5fe15657fc7fdeb32473c9744e0b90c785c6c2f477916f7f7cb8d9c2e3172ca401fdc772e7790670ae2f2ba79f972d80e4963c6fd9d59d3d02feb0923fb2e051e57fb5794fd1df7af2d8e782e8bc0b305785c6c2f477916f7f71e23a7cb8c9c32d007f79d1e0779a6202eaf9b97395e1299717f67d634f4cb7ac2c8becb81678b039ea8fbfb16600cfbcce12b6321018ca2a3e8e813a3e878f4e8288cc2288cd11857248051b6b530faca9875c098d2f1908797b35588dd68c46eac62ec2623765315638be6a2b9682e9a8be6a2f9e1c616cd4573d15c3417cd45f3c38d2d9a8be6a2b9682e9a8be6871b5b3417cd4573d15c3417cd0f37b6682e9a9bb17be28f1df97aee1ee0d9e2400b4779e6d47aafd0ebfa4f8cfa29adb61a5a650dad32d0e70ad06fab03fdc2aeb9e6658e1795f9440f981dc5ce8fa5758c86fc3946c1d043c5dfe62877db98b7ad0ab16d635e3562dbc6bc6ac416cd4573d1fce8d51cdbb5c1a1f720a975f4eaf648bdccfd57c0ebb8cf030da5e7c640b6a78bd8b20f89e6a2b9687e2434475d6aaac013183c41199ed99ef14cf58c67bc673ca33de319e119cf5ccf78e678c633cd339e099ef18cf18ca7d6339ee99ef14cf48c27ed19cf48cf78e679c633c3339ef99ef14cf28ca7c1339e8c673c759ef1ccf48c67b2673c633de369f48c6781673ca33ce3e9f18c6796673c533ce319e7194f93673cf59ef1a43ce04907875e539386fff780afc678ad1aaf268e1ff8ff76edaf81d7ecd0ed1121ebde0e3e3e57b523e4b5a8d376c8a55bb77387f728ea84b1ba6199e33500c70e4f78ea3de369f28c679c673c533ce399e5194f8f673ca33ce359e0194fa3673c633de399ec19cf4ccf78ea3ce3c978c6d3e019cf24cf78e67bc633c3339e799ef18cf48c27ed19cf44cf78a67bc653eb19cf18cf782678c633cd339e399ef1ccf58c6784673ca33de319ef19cf54cf78667bc65313c2d3e38887e72f79ddbcdce3496c07dba178dfe2958e72daa9d755a7d7cbfc1caf16fa3ca43fb8a9f9087c2d7399f3cd38d7b41334ea75948beddae5de2ac4b65dbb5c8dd8b66b97ab115b3417cd4573d15c3d62bca7be53eeb7a89c47eeb728cf23f75b94e799eb198fdc6f519e47eeb728cf23f75b94e791fb2dcaf3c8fd16e5797a3ce391fb3fcaf3c8fd1fe579e4fe8ff23c72ff47791eb9ffa33c8fdcff519e47eeb728cf23f75b94e791fb2d0ee5f9ffeeb7c0fb24f8dc542ff8aed4ed1ef0d584c4e0f5ec045fad6ef33ad4783367fca10c35f09aab42b8ae0c89c771ae0a796d3574c758ddb0ccf1f0fe8dab3ce1a9f78ca7c9339e719ef14cf18c6796673ca33ce359e0194fa3673c633de399ec19cf4ccf78ea3ce3c978c6d3e019cf24cf78e67bc633c3339e1ecf78e679c633d2339eb4673c133de399ee194fad673c633ce399e019cf34cf78e678c633d7339e119ef18cf68c67bc673c533de399ed194f4d084f8f231edb75b43d55886dbb8eb61ab16dd7d15623b6682e9a8be647b7e657c71fbb231d0cfecd36f54819cbddd0be1a785cbcdf39cab378ffdd2ebdae18ef71c829ad761b5af5185a65a0cf2ed06fb703fd521097d7cdcb1c4f9885d9c6ac62ef893f76719cc1d8ac4f60f0f0638f632d1ce5591c0ffa82708d395e06fae036ef7390670ae2f2ba79b92f24767310af167b2bd0626f08cfde2a6bc1f1a232ef4a20b30f3aabd8d7c41e3b9f4b1bb1599fc0e0e1c7358eb570936769dfda17846bccf132d007eb749f833c531097d7cdcbfb603b08b3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3dfcc2af6fed86397e6ef3136eb13183cfcd8ef580b377996e6effb83708d395e06fae036ef7790670ae2f2ba79b91fb683300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb330fbcdac621f883f76f13e1f8ccdfa04060f3f0e38d6c2519ec5f9fb6b83708d395e06fae036bfd6419e2988cbebe6e56b613b08b3308731abd8d7c51ebb743e0f63b33e81c1c38feb1c6be126cfd278707d10ae31c7cb401fdce6d73bc833057179ddbc7c3d6c8728cc7d0964169d45671bb3e82c3adb984567d1d9c62c3a8bce3666d15974b6318bcea2b38d5974169d6dcca2b3e86c63169d45671bb3e87cf4e8ac621f8c3d76a1387f8fb1599fc0e0e1c741c75ab8c9b3347f7f4310ae31c7cb401facd31b1ce49982b8bc6e5ebe01b6c37067ee4b20b3d4467598a53684d9c62cb521cc3666a90d61b6314b6d08b38d596a43986dcc521bc26c6396da10661bb3d48630db98a53684d9c62cb521cc3666a90d61b6314b6d08b38d596a43986dcc521bc26c63f6a13654ec1be38f5dbc9f1d63b33e81c1c38f1b1d6be128cfe2f52f3705e11a73bc0cf4c13abdc9419e2988cbebe6e59b603b08b3308731abd837c71f3b9f3662b33e81c1c38f9b1d6be128cfe278704b10ae31c7cb401fdce6b738c833057179ddbc7c0b6c87a431e3f64bc517bb78dd26c7a8d1cfca77ab6e8f00df6dba5d0bbe37e9f648f0ddaedb75e07bb36e8f02df5b2037f6bd55b71780ef6dbadd03beb7ebf636f0dda1db5783ef4eddde0dbe77e8f61ef0dda5db7bc1f74eddbe067c77ebf63ef0dda3dbfbc1f72eddee07dfbdba7d007cefd6ed6bc1f71eddbe0e7cf7e9f6f5e07baf6e1f04dffdba7d03f81ed0ed1bc1f7a06edf04be87747b17f8dea7dba3c1f77edd1e03be0f409b9f3fa8db0de0fb906e67c0f7b06e8f05df23badd08be47757b1cf83eacdb4de0fb886e8f07df47757b02f83ea6db13c1f771dd9e04bec7747b32f81ed7ed29e07b42b7a782ef49dd9e06be4fe8f674f07d52b76780ef29dd9e09be4fe9f62cf03daddbb3c1f769dd9e03becfe8366edfcfeaf6cde0e371e016f0f138702bf8781cb80d7c3c0ebc097c3c0edc0e3e1e07de0c3e1e07de023eaebbb7828febee6de0e3ba7b3bf8b8eeee001fd7dd9de0e3ba7b07f8b8eeee021fd7dd3bc1c7757737f8b8eeee011fd7ddbbc0c775772ff8b8eede0d3eaebbf7808febee3ef071ddbd177c5c77f7838febee01f071dd3d083eaebb87c0c775f73ef071ddbd1f7c5c77382e34ebf607c1778c6e7f087cc7eaf6c3e03b4eb71f01dff1bafd28f84ed0ed0f83ef44ddfe08f8e6eaf647c1374fb73f06bef9bafd71f0f17bd363e0cbeaf6e3e06bd1ed27c077926e3f09be56ddfe04f8da74fb93e0cbe9f653e06bd7ed4f812fafdb4f83afa0db9f065f876e7f067c9dbacde382daff1a2017ceb301b84f0ae1615f3df07407f11e33712c5e372fe78191756caf3e63be52c69cc1a8783a1c6886b5c18f729f493a80a7e080c7519ec5cf249d464e7923a70cf43911f2ec7490670ae2f2ba79b91362bbd8e6a8459d5eef5c438b5ae8f3867e4353ef7fe574e475a8fa6d0fc9c5958e39832717127bb1631d79dd3c262eae42ec8546ec3623368ee7fc28b76f2f04e6450e98d57abbe25f6f71df3e59af8beb99e3b4414e4b4083b872c2d8296d1c87fdb5d0fedfa681bedc8ff5e0f74e6657fb116f4b64375fd761bc2e037d1687e4df1dc49b7f97c1d36530abe3ffff6a1ae070b03f146b60b1c1c1cb6da05d9745bbc5a01df769071f1fe374828f8f15781d78ac84c7112df1e71b3af6f0720b30b26f2130b68430b6c7cf583cd66931185b42b465df22e059e848b34506cf5c431f7c5f1e65f4e1d7d6429ff1fa835d6330f83304f755b53f363590177f66fe4f10efb85ae7402ffc3c1f803e81a1213f98a13e18f8cc1f27cf9860e033fdfefebe7d3d3b7ad7f5f66c4b015aad8189cfa990346ac087ed1121be20183c7581539e3c7581539e35862c3865c2fdd5472995164f0ff4eeded9bf714fef9eadfb0eeeedefddb6b66f07528f34e891d4960192a28f1ff5c1c0244b7710efc98e3a2356b9e2a987e751f1f3b43bcab3f8c633dac8a9cec829037d46c2ff463bc833057179ddbc3c3a24768c0351518b311568312684674c95b5c0896af6e19ecaffc7931335462eb847634e669dc79a10073c01d69fd270ea7f6a671fa99319150c6c6c1e3dd551a5da086a8653bd6ba9194c7570a686203523a96620d58ca39a6154338a6a0651cd18aa19423523a86600d58c9f9ae153337acd4169c64ecdd0a919b9e381eb7bc0aa3e51ab774735a3a666d0d48c993aaa52effeea48441dfdaa2335f5e94d1d1da84f956a8641bdd3aaa318f50eadde55d5919a3a425347d4ea087329d932b253c8966bad5790ad243b95ec34b2d3c9ce205b457626d96ab235646791ad253b9bec1cb273c9ce233b9f6c1dd97ab20d641bc92e20bb906c13d945649bc92e26bb84ec52b2cbc82e27db1294ce4a5d41b635289d8dea25db4eb683ec4ab29d645705a5b3526ae65d9d8952679ed4d530ea6c933abba4ce26a9b347ea6c913a3ba4ce06a9b33fea6c8f3abba3cee6a8b337ea6c8d9aa95733f36a26feb6a034d3ae66d6d54cba9a395733e56a665ccd84df119466bad5ccf65d4169e65acd54ab99693513ad669ed54cb39a595633c96ae658cd14ab99613513ac667ed54caf9ad95533b96ae656cdd4aa99593513fb68509a695533ab6a2655cd9caa99523533aa66429f084a339d6a6653cd64aa994b3553a96626d54ca49a7954338d9f23fb3cd917c8be48f625b267c8be4cf615b2af923d4bf635b2af937d83ec9b64df22fb36d977c8be1b946af0fb643f20fb21d98fc89e23fb31d94fc89e27fb29d9cfc87e4ef60bb217c85e24fb25d9afc87e4df61bb297c87e4bf63bb297c97e4ff60ad9ab647f20fb23d99fc8fe4cf617b2bf92fd8dec35b2bf93bd4ef6463070c601078adfe8059efdeee9efefddbdb7bfb9bfaf79f7815dfd3bf7ee3ad87cddcefe2b9bfbaeedddb77d57df75f8e23bf4d0c453fb2bf6edeb39d8bc73cfb6deeb9bfb0ef437f76d6fbea2efc09e6dfbf1458fe917cd3c3462cfb66df6605faa390cd2af0e31e873fa757cd26475f9dc9e1f8a202f0ee545ff1a6242f7eb53514bf5f2fad2116df3fe5d7dfdcdb9e63df4b76717bda6775b6b33fe6f3f89bcbfbf797f7fcfbefee6edfbfa7637b7b7e27a1fcc0c2189d79b86f0a2a6f195671efc1f78fc6b863d5f0300", "isInternal": false } ], - "packedBytecode": "0x000000028df71de500000036421f8b08000000000000ffed9d079454c799ef6fcf0c493dcd30420284080392c8a1a72730e426470990002123230d0c20860c4316306491a364d972daf57a83d7de607bd76b6ff0aec306e7b45edb72ce3ee7f99df7ce79efed396f7775b6aabb3ecf9f9abaedeee156eb6bf8ee39df74dd6fead6f7fbbe5bb76ef5adea5bbf0a82201664b772258f049d37fa7fda7c26ef6cab8db0aca44fce5889709695086779897056940867b712e1ec5e229c3d4a84b3678970f68a9053b39505b76f51f3dee721ae5133c64b2ca6952510d34489c5b47709c4b42a288d36aa4f8970569708e7fd25c2d9b744381f2811ce074b84b35f8970f62f11ce0125c2f95089700e2c11ce874b84735089700e2e11ce2125c239b444386b4a84735889700e2f11ce474a84f3d112e17c2c42ce51c039c27c8e349ff4bfd1e6738cf91c6b3ec799cff1c6c70ab33f41c944cda6a4d6fa5f4a499d927a250de67f35e67f8d4a262969523259c9142553954c53325dc90c25338defb394cc563247c95c25f394cc57b240c942258b942c56b244c952258f2b7942c93225cb95ac50f2a492a794ac54b2ca6259ade469256b943ca3e42d4ad62a7956c95b95ac53f29c92e795342b59af64839216251b956c52b259c90b4ab6286955b255c93625db95ec50b253c92e25bb95ec51b257499b927d56ccf62b39a0e4a0924316e761254794bca8e4a892634a8e2b69577242c94925a7949c567246c95925e794bca4e4bc920b4a2e2ab9a4e4b2922b4aae2ab9a6e4ba921b4a6e2ab9a5e46525af28799b925795bcddb050657f8792d794bc53c9bb94bc5bc97b94bc57c9ef28f95d25ef53f27b4adeafe4f795fc81923f54f2474a3ea0e48f957c50c98794fc89923f55f2674afe5cc987957c44c94795fc8592bf54f231257fa5e4e34a3ea1e4af95fc8d92bf55f2774a3ea9e4ef95fc83924f29f9b492cf28f9ac927f54f24f4afe59c9bf5831ff9c92cf2bf982922f9affd1b3ae2f29f9b2497fc57c7ed57c7ecd7c7edd3ae61b4afed5d27d53c9bf59ba6f29f9b6497fc77cbe6e3ebf6b3ebf673ebf6f3e7f603e7f683e7f643e7f6c3e7f623e7f6a3e7f663e7f6e3e7f613e7f693e7fa5e4fd03b2e99e41c7960e226a77ea3736eb71120af688e0f64dc7a2dcfc8f3e6b8cbec2ecd327c5ae9bd9ef66e9bb9bfdee56393dcd7e4f4b5f6df6ab2d7d5fb3dfd7d23f68f61fb4f4fdcd7e7fd0c703785e6af45a576e5431d0513d2c035db7e0f698685d772a0e743d82db63a175741ebb83ae97d1f500dd7d46d7137471a3eb453153526974e920aa3a916cd6e526a22ed78c21f58e9e77832eb7ca136f9fe87937ea72ab3df0eafa71bf29ab0fd49bbe46570dba078cee7ed03d68747d41d7cfe81e005d7fa37b1074a6990afa81ee21a3eb0fba81463700740f1bdd43a01b6474034137d8e81e06dd10a31b04baa1463718743546370474c38c6e28e8861b5d0de8687eca30d03d6a74c341f798d13d023a6a531f051df5eb1e333add4efc7b00c7187d19e846523b0cba51d406836e34b5bfa01b436d2fe8c6826dd28d83768574e38d8eda28fdbf46934e07515d13a9cc353129ea7255c9badcc9d1979b19739b1274c4350d762641aca69a7484f37a6ad176cc08d9217d05a417425eca47f1a0fb0cb1ebfb4993494fcd715ca3755c02f23439fc4f07d1fa3fd9e2996c31ebfa3f1d38a2afb37529a9b3796f05d7d9d590d7ae7bd4e7b91bebec12e0f050671bfdd4d95452ea6cf6994310b8eb1ef57befc63afb0c70445f671ba4cee6bf155c67f7405ebbeed1779fbbb1ce6e068ee8ebeca446e91be4bd155c67db21af5df7e8fbefdd5867f70187873adb2ced6cde5bc175f60ae4b5eb1e3d8bb91bebec29e088bece4ef65467eba4ce06d9f1a32070d73d7a2e7837d6d9ebc0117d9dddd02c7d83bcb782ebec0720af5df7e819f5dd5867df031c1eeaacafe7b329a9b3d971f32070d73d1a2fb91bebec874c5a8f337cc58c330c02dd578d6e30e8be66744340f775a31b0a7e457f0db4d4cb3590f756f035f039c86bd7e51a93be1baf814f0287873adb287536efade03afb2dc86bd7bde1267d37d6d92f0287873adb247536efade03afb73c86bd73d9ad37037d6d9d74d5af717be63cd77d3bad78d6e24e8be6b74a340f73da31b0dbaef1bdd18d0fdc0e8c682ee8746370e743f32baf1a0fbb1d14d00dd4f8c6e22e87e6a7449d0fdcce86a41f773a34b81ee17465707ba5f1a5d3de87e65740d46a7c704687eca678cae27d84b07d19ddb38f8465bccda4f43bad62f4f32013c68ab2e7a5b75daf75490bfef75c053efc1f738d8c887a71e781aa2e7a9f572ef4966cf71ca8a691c6ca5c02f0ff7a84c7bd618dc1e53da277b09d0e1b53ac9c1d8143d632a06b6a86cda6f0246d2350023b5a574fde8b6b92ad6c1ebe15acadc9fd15e1a38c85e05e49939a0236f5fc35609ffa736a0128ec7b695535dd18c54471a8bcf98ca97b1c162f4747d6762d660f1b86c4ff164db8e05d5a92945b0dd64d9aeb76c631b425bae361efb761efad5b59efa8c99f6609a298bfaeb6407ef5bd3210651f984b6a9bf4e76485f01e954ac232fe5a37850db43ecfa3aa27389ecf67193ace31290678ac3ff7410adfff6f787a916b36e7747c23dc1c3f570db77362a9bf6eb2176534362370562477946828eee118da0a3b696cac0fe2db6c33efa4bb1e0f6be741af61b1cdc4dc0d8e060f4d0c74ce56a9beb819174938127e5296661df2d5362db473dcd5c976483fa6a740d91bd0ac833b8bc23ef6268337cd44fbc1668cbf73b50f4e72995f94e565f000f9e3b0ffdec5a4ff53189dfe7df08a2ad6b769b586fc52aec3b7fd243fcb0ee53d9b44ff684599885599885599885599885599885599885599885599885599885599885993f338e65e13c1ecad7c084d19e0fe5eb397fe6fd55a62c1c037addebfca054661c80e24ff301465b3e57409e5fc73ad87e00f383e8ff38dfc9752e7dcc95cc752ec99e6bbe92cff1e63a8ba7ce110b0eb66b22b39ddae0e7fca692fafd31fa1d6cf5d639b5c7e633ef76b374ba9ed69477f8ed63ecafd0b1486c4b281de5d85e0278d0968f7383d75e59707bfb81f7195ff358a8ada6f1f22996ed0ac8f31f309f682afc3f1d746e2f300f954dfba3e1d8a956d955fefccd3937017f0761ff1e837c6b04eedfccff29ebf0f17d26ede91e972a741e35b6d3d1f701b273085205f02481c7c77dcc535f2789f531ea3904f61c31571fcafe4d8ecfdfc3d8fd60dacff51b1e6116666116666116666116666116e6e49d6dc22cccc22cccc22cccc22cccc22cccc21c31b3e671bd8382f2d531612cd2bc8bcc7806bd8709c7c5ae9775d8f53d0648634e632c9ff177ab5f2beb607bd9a42b83ce732dc2cea5afb1b5b07349f65cef41f135a61c035b5476ad23161c6cd744663b3b8720faf3db318720659dd33aeb7ce2d8395e43ef837a6acfa788079de72478bac6739e1bb287d712ce7fa134fe36db47acf15e62cf29c2f7f2519e0f99d8d2d879f46d752ae9b3dda0f795d03c8194c357caf36168fb3e6ad2387fa40ecafab4e3ffb4e51aa7a6f8699f6744ef73e6fcce3465d1f99de1b09d06d6886cd7a2ed985536e92b20fda9b2ce0c140f8a35b1eb6b04dffb12765cbd755c02f24c77f89f8ed8ff19160f9e63bde9baf331a8679f86fbbfaf36697a488c46438c288fe7f7073ae703da731ab11ded61e5a163f1bd689f87362a6ceeaaeb1e30cd937f61f700b297083adf17f299637aafcf117b1dda8ba9f0ff7470e773c45e873a84f3b402abfc31503e71f508c2ef2d94e707d67dd4c31caebcde8fe3fa3e40bc38078df2fc14daaa7e66ae6621df07deacef76aeef03785c98efd82e447d6fc4fa882cf87e35caf33fadfa383584bbc971ecff0e39966265bf2bac32e81c3f3fef59cbb637332c5fe89a9a0ebe509e7fb7ae9be8fb4cd9fea7af77ca515f87daa05a87af94e73fe15a7b03fa97749ef0be9028effc7fda72f53f297edae759d1fb9c39bfb34d59747e67396ccf01d6886cd7a26dea7f921dd25740bab2bc232fe5a37850ac89bd123891dd3e6e8a755c02f2a41dfea723f67f96c533cb62ceb43df06eb204ccbff7d556a703778cc6408c7e630f74741fc1f780ba9e75f8ba9786f5e3f0775ba4c3b6bd1fc4b458bfa9b19fe9b9fa27632c7eec9f3c6c98ab4c9cedbcf6b34a3a2eca39cbf81b11ec17e26f447c7d474a04b7c7336171f8b45d65d9ae2aa2ed6acb7675116d4bcc25e69c62ce69ad081c9b2a03461ff73abcafe6c3e8baff9503a3afdff1a50a60ac0346bcdf11a387f7b0d676752d0aeceb7403461fbf412df47935be83197f8b4c8c3ede855fe8fb6cf15dd6745c0f60f4b1c601ae55900fa36b8d8c9ef0e9613d8cdaaebe371fd7c8e8058c3edea51f0f6e7fffff6f63c4b59ce8b8fb80d1c738523cb8fdb9da6f63c477b0d37171cf8cb9eeed9ee783a40a7d0681f32ff01914c5c9358fc5d7b37afbd918ede3b37ae40dfcc531671f69aadf58a430eeb4e53a87aef8f4369f71f8bfdfe789b78ff152d9b43f1d184957e5378e39fb9ad3fcc6228571a72dd73974c5a78ff98c079dd7fff03466ed1ca3a47d1cc7255db5679eb8c5f3dbe2e862bc1f18677a629c5100e34c60a4e3fa0263da13e3cc0218d3c048c73d008c1e9e576718d30530e2735dd23f088cb33d31ce2a80713630d271fd80d1c7b3e738d8cd87710e30d271fd8171ae27c6390530ce05463a6e0030cef3c438b700c679c048c73d048cf33d31ce2b80713e30d2710381718127c6f905302e00463aee61605ce8897141018c0b81918e1b048c8b3c312e2c80711130d271838171b127c64505302e06463a6e08302ef1c4b8b800c625c048c70d05c6a59e189714c0b81418e9b89a12601c56028cc34b80f19112607cb404181f2b01c69e25c03816181f8f9e31f3fd7a69018c8f03cfb2e879eae360231f9e65c0f344f43cb59efccccccf5a6eca8afa1d692bac583d6ec52a01799643fc5678885f0cec52d9b44ff6845998c398350fb54fc41a877c4b993092ee09cf3c718b476fb9dac7157e799209473cb4ad27a3b7952ad4f727816765f43c997bd59305f0ac049ea7a2e7a9f5e467e69eb2caf2e949cba704e4c1766395073f636097caa6fd550edb3541b4b1589d472c563b785617391664af50e6e525c8cc21ced816126b1cf22d63c248baa73cf3c42d1ebde56a1f5d8c2bfc32a6bacaa879d644ce937d47f4ea0278d600cfd391f364ef29d1fb996d479fb17c5a6df994803cd8263de3c1cf18d8a5b269ff19380fc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc2cc9b19c71888350ef956326124ddd39e79e2168fde728d3bb81857f8654c759551f3ac8d9c273b56f34c013c6b81e72d91f364c76aa2f7333b56f3ace5d333964f09c883d7f7b31efc8c815d2a9bf69f85f320ccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccbc99718c8158e3906f0d1346d2bdc5334fdce2d15bae710717e30abf8ca9ae326a9e75d1f3647eabf96c013ceb80e7add1f3d47af2333356f39ce5d3b3964f09c883d7f7731efc8c815d2a9bf69f83f320ccc2ec62c6368b58e3906f2d1346d2bdd5334fdce2d15bae76ccc5b8c22f63aaab8c9aa739729eec38fd7305f03403cff391f364dbfee8fdccb6fdeb2d9f9eb37c4a401ebcbed77bf0330676a96cda5f0fe7a110e65525c82c71963887314b9c25ce61cc1267897318b3c459e21cc62c71963887314b9c25ce61cc1267897318b3c459e21cc62c71963887314b9cef9d38e31803b1c621df3a268ca47bde334fdce2d15bccda4f43dac5b8c22f63aaab8c9aa725729ebacc58cdfa02785a806743e43cd9b19ae8fdcc8ed56cb47c5a6ff994803cd8266df4e0670cec52d9b4bf11cec3ddcebcaa0499a56e148759ea863087314bdd10e63066a91bc21cc62c754398c398a56e087318b3d40d610e6396ba21cc61cc523784398c59ea863087314bdd10e63066a91bc21cc62c754398c398a56e087318b3d40d610e63e65037708e0eb1c6215f331346d26df0cc13b778f4966bde8e8b71855fc654571935cfe6e87932ef24d95800cf66e0d9143d4fad273f33739d5eb07cda68f994803cd826bde0c1cf18d8a5b269ff05380fc22ccc2e666cb388350ef95a9830926e93679eb8c5a3b75ced988b71855fc6545719354fab279e170ae069059e2dd1f3d47af233d3f66fb57c7ac1f2290179f0fadeeac1cf18d8a5b2697f2b9c875263c66b8958e3906f331346d26d011e0ff5aee036a9d511c71525c0b8bc04187b9500e37d25c01807460ffdf4cc359cb078687fb3dff8a4a2884f25c4896bbb97001e5fe7b0cae2a972c482eb39ec6d3e399fc32ae0f1750eab2d9e6a472cb89ec33ee693f339acf61bc748dafbfb4b80b16f09303e50028c0f960063bf1260ec5f028c034a80f1a112601c58028c0f9700e3a012601c5c028c434a8071680930fa7ea691eb7b6e6b116c877d3f2b86edb0ef15c5b02d3197984bcc25e6127389f99dda96984bcc25e66f7ecc7d3ccbc5e7c6b4e5fa0ee17abeeb7b4c5e18f930ae62ca883cb1e87892e83bdadac6c077622835c65525c0b8bc0418258ed931d4ae306a9e1d9e78b615c0b30378b647cf53ebc9cfcc5cc39d964fdb2c9f129007ebc14e0f7ec6c02e954dfb3be13c941a335e4bc41a877cad4c1849b71d787c5d5f855cef787dedf2c4b3a3009e5dc0e3e37c79f23373bdefb67cda61f994803c78edecf6e0670cec52d9b4bf1bce43a931e3f54eac71c8d7ca8491743b81c7d7f555c8f58ed7d71e4f3cbb0ae0d9033c3ece97273f33d7fb5ecba75d964f09c883d7ce5e0f7ec6c02e954dfb7be13c941a335eefc41a877cad4c1849b71b783cd4bb82bf73ec71c471790930ae2a014689a3c49113a3c4f1de89a3300aa3300ae39bc1580a6db8dc670a7f3680dfc5dba2e7a9c7ef6df9f0b4018f8fef769efccc3c1bd867f9b4c7f2290179b01eecf3e0670cec52d9b4bf0fce83300bb38b19db2c628d43be56268ca4db0b3c1eaeef82dbfe36471c57f8654c759551f3ec8f9ca73e89f5251f9efdc0e3a34ef9f133dbf61fb07c6ab37c4a401ebcbe0f78f0330676a96cda3f00e7a110e65525c82c71963887314b9c25ce61cc1267897318b3c459e21cc62c71963887314b9c25ce61cc1267897318b3c459e21cc62c71963887314b9c25ce61cc1267897318b3c459e21cc62c71963887314b9c25ce61cc1267897318b3c459e21cc62c71963887314b9c25ce61cc1267897318b3c459e21cc62c71ee1a33ce7127d638e46b65c248ba7dc0b3df034fa1f3f0f73be2b8c22f63aaab8c9ae760f43cf5585ff2e139083c3eea94273f33bf153864f9b4dff2290179b04d3ae4c1cf18d8a5b269ff109c874298579520b3c4b96bccd866116b1cf2b5326124dd01e0f1707d17dcf61f74c471855fc654571935cfe1e879eab1bee4c37318787cd4294f7e66dafe23964f072d9f129007dba4231efc8c815d2a9bf68fc0791066617631639b45ac71c8d7ca8491748780c7c3f55d70db7fd811c7157e19535d65d43c2f46ce934a627dc987e745e0f151a7fcf8996dfb8f5a3e1db67c4a401ebcbe8f7af0330676a96cda3f0ae7a110e65525c82c71963887314b9c25ce61cc1267897318b3c459e21cc62c71963887314b9c25ce61cc1267897318b3c459e21cc62c71963887314b9cef9d38e31803b1c6215f2b1346d21d011e0fcfe30b1eab79d111c7157e19535d65d43cc722e7a94b627dc987e718f0f8a8537efccc8ed51cb77c7ad1f2290179b04d3aeec1cf18d8a5b269ff389c87bb9d795509324bdd280eb3d40d610e6396ba21cc61cc523784398c59ea863087314bdd10e63066a91bc21cc62c754398c398a56e087318b3d40d610e6396ba21cc61cc523784398c59ea863087314bdd10e63066a91bc21cc6cca16ee01c1d628d43be56268ca43b0a3cc73cf0143a8fe898238e2bfc32a6bacaa879daa3e7a9c7fa920f4f3bf0f8a8539efccccc753a61f974ccf2290179b04d3ae1c1cf18d8a5b2699fec09b3308731639b45ac71c8d7ca849174c781a7dd034fa1ed6a3b30bada7e0f8ca9ae326a9e93d1f3d4637dc987e724f0f8a8539efcccb4fda72c9fda2d9f129007afef531efc8c815d2a9bf64fc1791066617631639bd56e3ee390af950923e94e008f87ebbbe0b6ffa4238e2bfc32a6bacaa8794e47cf538ff5251f9ed3c0e3a34e79f233d3f69fb17c3a69f994803c787d9ff1e0670cec52d9b47f06ce83300bb38b19db2c628d43be56268ca43b053c1eaeef82dbfed38e38ae2801c6e525c0b8aa04183dc731d55546cd73d613cfe90278ce028f8ff6c3939f99fbfc39cba7d3964f09c883f5e09c073f636097caa6fd73701e4a8d19af25628d43be56268ca43b033cbeaeaf42ae77bcbe5ef2c473b6009e9780c7c7f9f2e467e67a3f6ff974d6f2290179f0da39efc1cf18d8a5b269ff3c9c875263c6eb9d58e390af950923e9ce018fafebab90eb1dafaf0b9e785e2a80e702f0f8385f9efccc5cef172d9f5eb27c4a401ebc762e7af0330676a96cdabf08e7a1d498f17a27d638e46b65c248baf3c0e3a1de15fc9de382238ecb4b80715509304a1c258e9c18258ef74e1c85511885b130c6ad25c028e75a18b932b67a608c197bc843fbad45b05d65d9ae2aa2ed6acb7675116d4bcc25e6127389b9c45c627ea7b625e6127389b9c45c622e31bf53db127389b9c45c622e319798dfa96d89b9c45c622e3197984bccefd4b6c45c626edbf630dfb4e0f9dc1781e782875878f233a9cbbd64ca7a23c2f8e9585db662d56ac52a01792e41fc2e7b889f6bce35ed93bd4299473060f6643bd55b95d10bfc271babac7868fb573cf91ed6e65d2982edb036af18b6c3dabc62d896984bcc25e6f76ecc315d1174fe0d922ee3aa497733fb947f2b1c47793e5199fdac0ae47cfab02dd790c45c622e317f33628e71995f049ec0e20972f0a499f14c61c653cf8c6702339e31cc789a99f1ac61c6b394194f39339e05cc786631e329c6f3ac4278a632e36960c6b39019cf6c663cd398f13432e319c58c27c98c6704339e16663c6b99f12c63c6b38819cf1c663cd399f16c66c63389194f2d339e91cc782a99f12498f12c66c6339719cf0c663c1399f13431e34931e359c78c6725339edecc78aa98f1cc63c6338e19cf4c663c9399f1d431e3e9c38ca79a19cf68663c4b98f18c67c61363c0130f3acf018fc3ff2f82aecc3ab6879293033afe7fcde8cbe098eb265dee28fb1ae8686ed575c7b118a76be04bdaa49377b665e284b6d2b04ff62a81e33a139ef1cc789630e319cd8ca79a194f1f663c75cc782633e399c98c671c339e79cc78aa98f1f466c6b39219cf3a663c29663c4dcc782632e399c18c672e339ec5cc7812cc782a99f18c64c653cb8c6712339ecdcc78a633e399c38c6711339e65cc78d632e36961c63382194f9219cf28663c8dcc78a631e399cd8c6721339e06663c5399f15c64c6338b19cf02663ce5cc789632e359c38ca79919cf18663c1398f1d433e399c28c27cd8c67be83c7d7bac334de4e65d3fe4526b63d9c87cc7be16e78f2e9a629abbb2997f8c95e05e499600662f4f8101e4b5cf6fc08ecdbdc84185df5e44bd8bb21ae16c176d8bb218a61bbdab25d5d44db12f3f098df8cde760ae71cd116b3f6d390c6ebcec75c2d4f7eded6e645fd2ecc5b56acae5ab14a409e1b10bf5b1ee2e76a47699fec15ca3c820133d68b9a20da7af172f43efde61d9b14d797adf8a25faf788a69585bfa4a116c87b5a5c5b01dd69616c3b6c45c622e31bfb763fe36938eb09f91441bfa3b14dd3fde0676df6ed2b108edeab25e3565d13b4189e3edc04379b6c2773aa97f72cddf0b31b7d3f48c027fc7efeb1952d83929c6f3abb073520cdb61e7a418b625e6e1317f8707dbf1e0f6b512f496eb19c53b80e7550f3c9efcccdc6b5fb37cba68f994803cd8f6bde6c1cf18d8a5b269ff35e0a10ddf13eba31ee473ce91e716339e34339e29cc78ea99f14c60c63386194f33339e35cc789632e32967c6b38019cf2c663c5399f13430e359c88c6736339e69cc781a99f18c62c69364c63382194f0b339eb5cc789631e3798519cf22663c7398f14c67c6b39919cf24663cb5cc782a99f12498f12c66c6339719cf0c663c1399f13431e34931e359c78c6725339edecc78aa98f1cc63c6338e19cf4c663c9399f1d431e3e9c38ca79a19cf68663c4b98f18c67c61363c013f69e58faff2dd0d11839be3bf69d26fd2ae8ca1c3668ace635d055983495a1df3b7b7940e7b2314ebee605a0ad34ec933d7c4fec3b99f08c67c6b38419cf68663cd5cc78fa30e3a963c6339919cf4c663ce398f1cc63c653c58ca737339e95cc78d631e34931e36962c6339119cf0c663c7399f12c66c69360c653c98ca79619cf24663c9b99f14c67c6338719cf22663caf30e359c68c672d339e16663c2398f12499f18c62c6d3c88c671a339ed9cc781632e36960c6339519cf2c663c0b98f19433e359ca8c670d339e66663c6398f14c60c653cf8c670a339e34339e5bcc78e63b787cbd9f2eec9d0fb78a603bec9d0fc5b01df6ce8762d8969887c7dcc3bb6e32ef02c5f742eacd9eeb9286b4e7dff7d4c783dbdfabf3db78f0bd1f3eda254f7e66de41f92e53964ea7232a57c7eadd41c7a6cba578e2fc2aca830cef866322e2c9f93e11b227ccc21cc68cefa42556d7dcbb379b9174af018f8f7643fb3ece9445e5eb77f425fa74d8f5f09ef77a1d07fb3defc4e17acffbe6fe1d6cd586ad32e8fc2e5c5ceb1ecfa5efb508a86cd75a04e40fae45e0ebbe7fc3e2b9e188c59b69fbba07db85f639ae3b78a27ccf26b63168cbc77bdfb5efd782fc7d77bd873e42df6b13c083b63cbce73dd376d17c5c2a5fb70f23fb788d793d5ef7d4768db77cae803c73a0ed1a9ba3ed2a0b3aae197c4f7959d0f9ddef6f18bd5d464d20dfa77cd896efb03c63eea16f52f077585c8f21fa7e462ad3cedd2880e71af0f8b8df7aea4f253ddd9332df61af58b1ba61c52a01793cdfb73275fb9ac543fb644f98855998855998855998855998855998855998855998855998855998855998f933e37830b1e2b8ed2d268ca4c3316b1fcff9b5ef134c5954be1e1bfd429f0ebbd18f5ba492384781c66d27583e57409e3efd3ad8be02e3b6f6bc86b073e96b9df7b07349f62a83cef3507c8ed385cd8129c6186121b66b22b39ddae0e7fca692bd83ec9adf37ac737acb713e7db415387f8ab65c638d5780c7c3586cadafb923daa7cb964fd72d9f129007d7b1b8ecc14fd77d8df62f030f6db84e9eaf7b4660f1048ef8d056c68c27cd8ca727339e29cc78ea99f14c60c6f328339e31cc789a99f10c61c6b38619cf52663c0398f1dccf8ca717339e72663c0b98f1cc62c63395194f03339ec798f10c65c6f310339eb1cc78fa32e3b98f19cf42663c15cc786633e399c68ca79119cf28663c49663c2398f1b430e3a961c6b39619cf40663ccb98f13cc08c27ce8c6711339e6ecc78e630e399ce8c6733339e49cc786a99f18c64c6338c19cfc3cc787c8fa317caf320339e4a663c09663c8b99f17467c6339719cf0c663c4dcc782632e34931e319ce8c671d339e41cc785632e3e9c78ca737339e2a663c3d98f1cc63c6338e19cf4c663c9399f1d431e3798419cf60663c3799f1f467c6b38419cf68663c7d98f15433e319cf8c27c680271e74fead471cfe7f1d74974d1a7fcf56e6288fe6e9517eddaf7a7940e7b2cb1c655f7130609c2e812f69934eded976dbef3062a65cda277b95c0718509cf78663cd5cc78fa30e319cd8c6709339efecc786e32e319cc8ce711663c75cc782633e399c98c671c339e79cc787a30e3a962c6d39b194f3f663c2b99f10c62c6b38e19cf70663c29663c1399f13431e399c18c672e339eeecc781633e34930e3a964c6f320339e6bcc781e66c6338c19cf48663cb5cc782631e3d9cc8c673a339e39cc78ba31e359c48c27ce8ce701663ccb98f10c64c6b396194f0d339e16663c2398f12499f18c62c6d3c88c671a339ed9cc782a98f12c64c6731f339ebecc78c632e3798819cf50663c8f31e36960c6339519cf2c663c0b98f19433e3e9c58ce77e663c0398f12c65c6b38619cf10663ccdcc78c630e3799419cf04663cf5cc78a630e3e9c98c27cd8ca78c19cf7c8b07ffafbfdbd3f8ea65d0d1ffffafe91c54193f2e5bf622f02319b6f683af98e19676c4246ced070e3c69663c3d99f14c61c653cf8c6702339e4799f18c61c6d3cc8c6708339e35cc789632e319c08ce77e663cbd98f19433e359c08c6716339ea9cc781a98f13cc68c6728339e8798f18c65c6d39719cf7dcc781632e3a960c6339b19cf34663c8dcc784631e34932e36961c653c38c672d339e81cc789631e37980194f9c19cf22663cdd98f1cc61c6339d19cf66663c9398f1d432e319c98c6718339e8799f15c63c6f320339e4a663c09663c8b99f17467c6339719cf0c663c4dcc782632e34931e319ce8c671d339e41cc785632e3e9c78ca737339e2a663c3d98f1cc63c6338e19cf4c663c9399f1d431e3798419cf60663c3799f1f467c6b38419cf68663c7d98f15433e319cf8c27c680276cad05fa7f39e82e9af44dd05d30e96ba03b6fd29741f7924357e660217b174147f3142e808ec636ce838e9e87902ddd9f7b6d4067d632874fe50ed60b0e9f2e3a8ec5f348c7a48368cf23da4ac33ed9ab048e8b4c78c633e3a966c6d38719cf68663c4b98f1f467c6739319cf60663c8f30e3a963c6339919cf4c663ce398f1cc63c6d383194f15339edecc78fa31e359c98c6710339e75cc788633e34931e399c88ca78919cf0c663c7399f17467c6b398194f82194f25339e0799f15c63c6f330339e61cc784632e3a965c6338919cf66663cd399f1cc61c6d38d19cf22663c71663c0f30e359c68c6720339eb5cc786a98f1b430e34932e319c58ca79119cf34663cb399f15430e359c88ce73e663c7d99f18c65c6f310339ea1cc781e63c6d3c08c672a339e59cc781630e32967c6d38b19cffdcc780630e359ca8c670d339e21cc789a99f18c61c6f328339e09cc78ea99f14c61c6d393194f9a194f19339ef9160f8e61264147e95ad0513a053a4ad7818ed2f5a0a37403e828dd083a4a4f021da59b4047e9c9a0a3345d23f1a0c3f762bc879f6c51d9b47f0918693eb3eb9a9e0adc972c9de63ee789fb92c54dfbe780d1e50bb14d03ee73964e739ff5c47dcee2a6fdb3c0e8f285d8a6838ed2334047e999a09b09f64847e959a0a3f46cd0517a0ee8283d1774949e073a4acf071da517808ed20b4147e945a0a3f462d0517a09e828bdd47cea737cd6d2e9737cc6a4d341b4e7986c51d9b47f06185de79dd89601f7194ba7b94f7be23e6371d3fe696074f9426c2b81fbb4a5d3dca73c719fb6b869ff1430ba7c21b635c07dcad269ee939eb84f59dcb47f12185dbe10db5ae03e69e934f7094fdc272d6eda3f018c2e5f886d1d709fb0749abbdd13f7098b9bf6db81d1e50bb1350377bba5d3dcc73d71b75bdcb47f1c185dbe105b0b701fb7749afb9827eee31637ed1f03c676872fc486ef5ddcec89f1a6c578b388b6c3fa5ec5b01dd67f2a86edb03e50316c87dd9b8b613becfe5a0cdb61f7c862d80ebbcf15c376d8bdaa18b6c3ee37c5b0dd6ed96e2fa26db9c68a7f8dbd996deabd7a8dbd99ed5abb65bbbd88b6a5cf247da662d9963e93f4998a65bbddb2dd5e44dbd2a686b7a91e9e4fa4e26083b698b59f86f431e0f1f19cc7939f495dee5153d61b1196ab63f5a215abcd56ac1290e728c4ef450ff18b815d2a9bf6c95e293263bd8845673b19071bf88eb823543ee80e9b742de80e99740a74074dba0e74074cba1e74fb4dba0174fb4c7a31e8da4c7a09e8f69af439d0ed31691cefd96dd26741b7cba4717c65a7499f01dd0e93c6f18ced267d1a74db4c1ac70fb69af429d0b59a343eafdf62d22741f78249e3f3f14d267d02741b4dba19741b4cba1d74eb4d7a33e89e37e9e3a07bcea48f82eead26dd08ba674d7a12e8de62d24da07bc6a42783ee6993c67714ae36691cfb5e65d21740f79449e358f393267d09742b4c1ac776979bf474d03d61d23340f7b849cf04ddcb269d06dd2b263d0b746f33e9d9a07bd5a4e780eeed263d1774ef30e979a07bcda4e783ee9d26bd0074ef32e985a07bb7492f02dd7b4c1ac701de6bd2c7405766d22f828ee69e1e011dfd9ee230e8e83794874047ef4d3808ba1e267d0074341f673fe8688ee93ed0dd67d26da08b9bf45ed0559af41ed0d13b0a76838ede03b40b74f4aea29da0a3f701ee001dbdb3703be8681eea36d0d16f19b6828e7ebfd80a3a7a47c016d0d17b815e001dbdeb6e13e868bee946d0d16f0436808e7e17b81e74f4dbfbe74147efdb790e74f40eb9b7828ee64d3e0b3afa2dc05b405763d2cf806e98493f0dbae126bd1a74f4aeb855a0a3f97f4f818ee6fc3f09ba1126bd0274234d7a39e84699f413a0a3772e3e0e3a9a07f932e8c69af42ba01b67d26f031dbd73f355d0d1bcc1b7838ede55f30ed0d1bdf835d0d1bdf89da0a37bf1bb4047f7e277838eeec5ef011ddd8bdf6b3ef5f5a7afcbeb663f1d44d7efd1f66e04b76fb9fadec4803c51f66513c083b6ae46ee7b2ad36fa6fe56992997eac155b07d3972dbd93efb1553563753ee65cb7605e419d2afe3dc5c82ffa7c1073a0ef350d9b43f018ebd64955d65fcbde2c9dfcb1613715f0126ca33bc5f47decf9a744f382642b6ccf74faa6b01c410b734a4718db4e86395ca7c1fb85600cf15e089fe3ac97e1ff65127f0da8afafbb0fd2cc3ae6b09c87319e2e76b6ee7158b87f6c99e300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb330f367d63c349e80f37928df75268ca4c3b12e1fcff9712c15c7bc3e02e33abec7f7ba9b72275a3e57409eff03634e1f33e94af83f9db7b073e9619c30e7b9247b95e00f8e05f9182f8e812d2afbaa23161c6cd744663bb5c1cff94d257b07d9f1fd6bd639bd6e9d4f1c17c76be8b3504fe9985be6330ef1b905f1f1708de73c37640fafa5aba0a3f40d60f4116bbc97507b30c1ec933d1c17ffb2352e1e7d5b9d4afa6c372e9ab2ecf176f495f27c03dabe6f9a34ce0db90e65fdccf17fda728d5353fcb4cfe7a3f739737e5f3265d1f93defb07d0e5823b25d8bb66346c80ee92b20fd5398cf61ff9e88624decfa1aa13998c86e1f77c33a2e01792e38fc4f07d1fa7fdee2396f31ebbaf36da8673f83fbbfaf36e942488c26408c280ff6833ccc3371b691c441f6741e3aff3dac3cd867a13cbf86364afb42ed3cf989735bf01e70d1937fd72dff689fec61dff80a30da3eeafaf1853e1dbcf7fafcaffff238ffebbfa00ee13cadc02a7f22944f5c3d82f07b0be589f5ef28dfe7fcb26b96cfc47205987e93a77f47de69265d485fffcdfade16d6d7f7f14ec07870fb776fbde5babfe33dc647fbe2c9cfa4ebde75c9f229017946809f1efa31397f07781e6cfb7a0f24d9a03ed4652b161590a73f5cdbb9e288df55af14c59794b33f38d1e10be5196cb5532f7960f279deb09fa5cbbdeaf095f20c87f6ef51938ec379c2b6b4cef17fda72b507143fedb387f7fb65ce2ffd068cceef1987ed53c01a91eddb7e934efd7db243fa0a48a7fa77e4b57f4f4eb1c6f7f8d16fe590dd3eeeb2755c02f29c75f89f0ea2f53fec7d00644fd79d9150cfa81ef96c37cf86c46822c488f2e0b315bab753feb0fbbe8ff9d5b9eefb5781d16e37b1efe293ed9ac5663f4375f507290f1d8bfdc159d0cec61d79fd3f1bcef66d0a99f3eff919797dcc8a671aec8c073dd54f8a33fd0ffbb8946789753ff3d567bd6c71931f388673d1e2be64c5159f452d076ed7b5e97ad6e9a9cf598f7d31bb3f7411d829cf6aab3f64f7e36e3a7cb1efd36541e7ef826f5879f19acc759c9dbe6e1d83cf0c5ccf64f1b72e1780256dd2c93bd96a9349642a73c4221174fe4ee67ace40d701d6392acbbe56e8d80ac8b3d16a93ecbc997b599f8ef8d079c467edae3ae9eb3952d87316b2a7195dbfa38bbeedba377fafd433b27227af2fc531ee9e563a1adba916bc57e48ac545078faf679a61b1b8e8b01d5d2c1a37b8ee1fae585c70f0f8fa8e19168b0b0edb11c66293ebd9822b16e71d3cbebe6b84c5e2bcc37674b19874db738d5cb178c9c113fd338ddcb1c031b142982f3060ee69a5a3b15dbfde3576e78ac539078fafb1bbb0589c73d88e2e16b58daeefecae589c75f0f85a17242c16671db6a38b45d364d73315572cce38787cad9f11168b330edb11d68b8df87c2d572c4e3b787cadc911168bd30edb11f60f1b733d33c4589c72f0f87af617168b530edb11c6a259db3e99472c4e3a784e163916271db6a38bc5fa066dfb441eb138e1e03951e4589c70d88e2e16cd4dda767b1eb16877f0b4173916ed0edb117e87cad48be379c4e2b883c7d7ba2961b138eeb01d5d2c5a327dad6379c4e29883c7d75a2c61b138e6b01d5d2c92997bead13c6271d4c173b4c8b138eab01d61bdc87c9f7c318f5814f3fda361b178d1613bc2fb48a65e1cc92316471c3c478a1c8b230edbd1c56253e6f9d3e13c6271d8c173b8c8b138ecb01de133974cbd3894472c0e39780e153916871cb6a38b455de69e7a308f581c74f01c2c722c0e3a6c47178b8d9931b10379c4e28083e740916371c0613bc27e67a6bdd89f472cf63b78f6173916fb1db623ec77669e5feccb2316fb1c3cfb8a1c8b7d0edb11b69d997e675b1eb16873f0b41539166d0edb11f63b33b1d89b472cf63a78f61639167b1db623ec7766ee237bf288c51e07cf9e22c7628fc37684f522d376eece2316bb1d3cbb8b1c8bdd0edb113ed7cab49dbbf288c52e07cfae22c76297c37684df4732cff876e6118b9d0e9e9d458ec54e87ed08c78a327df01d79c462878367479163b1036cfb986782b1a0b958e3ac5854409e07cccbd8692e56581ca90c9c5786be6c8fdc97ecbcb26d21be6c075f28cf40f0a527e8a364f2e46ba6ce6c3565d1dcf41b0e5f29cfd0011d798799741ccec94d282be9f83f6db9e62051fcb4cf5ba2f73953575f3065d1f9dde2b0bd095823b25d8bb6696e3ad9217d05a4270ee8c84bf9281e146b62d7d708ad9580ecf6713bace31290a7d5e17f3a88d6ff2d16cf168b39f3bb07a867548ffcb45d59a6d690188d8318511e9cb377c3138f3d879038c89ece43e7bf879507e750529e2668a3705e29f9190f3acf9bd4fe6df5e45fd83a6e642f01ba2bc068fba8eb4702e67ed61263d0a1a3b51d700da6464ba77d9de4c957b24565d3fe2460a4b5261a8bcf98ca97b1c162d43c933dc42c0e7669cb75bf980c3c4d1e783cf999b90f4db17c9a64f994803cf8dbc6291efc8c815d2a9bf6a7806d1fe71c6341f7e451562c2a20cf6aabff1816472a43d7df46872fbee2d860f134386c4ff71c472a9bdac4e945b03dd5b25d6fd9d6d736d631bde5bab6a702f3340fccbadc19d1979bb9b6698d34aacf64a71e7c4a430ca2f2096dc7acb2495f01e9ed033a33503ce8de49ecfa3ac2ba1376dc64ebb804e499eef03f1db1ff332c1e3cc77ad3fd86f5d0aff4703d64eac0748b83f6eb2176334262371d6247791a41477d9c29a0a3be02ae2948ffc77e4443f4fe3adb1eda6f0046d2e13a850d0ec6fae81953b9dae67a6024dd34e099ea2966d32c9e51567cf0bedcc3ca43c756409e76b837c61d7975ddaf8a75f8456b1746b8ce4fa65dedee215eb8ae6200f109ac18d2460c3d838eb517a3e4b92f80b515db76ee69debcf1c98dd9a14742abb030f133e670a30c74982e77e882e0f625242b40474b4876035d9915165cba92f2d392763ec285f1a0b22b2cce9ec012a56d5c7e93b65c55a707f0f8a8cabaea549ab24cd5797acf96b68d583fba599c5da93bfa7fe539f2859545f5a0c283efc84465d33ed9d3f14998f4aee60d5b67edd9bc6ffbc61d6d7b11d6beb8301db382607fba8ec14a82171395d3cd0a4eafe883538f17afcd1780bd005802c3d3337a9e4c45a5355b37346fdbb67cdffa6d5b36ccdfb76343db969d3b30a23dacc88545dbbee4f5e66aea30af9dbfbb43676fb8426e0fd0d10ab93d4147f67b818e38ee83ffd967c2cb353102caa76aacff57611cee6e1ca22a48b721dd9ee86ba67790bdfdeb2763d541f6f4e92576f592ba7a095dfd0607fdab6add53d04be0ea256ff512b77a495bbd84ad5eb2562f515b136497a01d1e6497987d34e85842566f9f015ebd64acee6ae82561f512b06383ece3baf141f6d566fa5512bacbaabf8eea6e9efe6aa1bb5cbaaba5bbb5fa2bbb7e7ca3bb31ba8ba8bb3fbacba2bbc1bafb3bd3c47a56905d425a2f193d37c82e093d3fc82ef9bc30c82ee9bc38c82e87be34c82e4dfb44905dce7c79905de6562f7fab97c5d54b97eb2573f552ba7a895dbd44b95e7e572fcbab9721d74bf6eaa57cf552e37a99dfe783ec72e2eb83ec92c12d41763961fde85a2f1fae1fdbebc7d9fa51b17e94a98713f4308a7eccaa87fff470a81e1ed6c3e57afa809e4ea1a797e8e9367afa919e8ea5a7a7e9e97a7afaa29ecea9a7b7eae9be7afa737b909d1e7f32c8fe7c42ff9c44ffbc46ffdc48fffceaa520fb9342fd133dfd9353fd13dccb41f611aafe39b71e56d38f4ef56364fd78553fead5cbf4ea6579f532bc7ad95dbdccae5e56572fa3ab97cdd5cbe4ea6571f532b8ef55f23b4a7e57c9fb94fc9e92f72bf97d257fa0e40f95fc91920f28f963251f54f221257fa2e44f95fc99923f57f261251f51f251257fa1e42f957c4cc95f29f9b8924f28f96b257fa3e46f95fc9d924f2af97b25ffa0e4534a3e1d64ebdf6795fca3927f52f2cf4afe45c9e7947c5ec917947c51c997947c59c957947c55c9d7947c5dc93794fcab926f2af93725df52f26d25df51f2ba92ef2af99e92ef2bf981921f2af991921f2bf989929f2af999929f2bf985925f2af955d0b10c343616ffdfec0c33fbcd6d6d1bb7ef6aab69db59b37ddfb6b62dbbb61daa39b0a5ed859a9dfb37eed9b46de7013cf883a679a2f5aa67edd9d37ca866cb8e968d076b76ee6babd9b9a966fdce7d3b5a6ebb397ece1c34a8b3c5e696967063df29bb03d2ef77d1e8afcd71b412f8a2dcbefdafae04e4ff75e5a081e55d73e8e3a673475fbb9ecaf6f16af66edbd95693acd9a1feaa9be9ce031b5b26d4e0fff6aa20ef6dabd9dbd6bca7ad66d39e9ddb6b6a2760b9e37b77c189d6de7e60069b770175a9aa7ca95f173cf91ffdba763afef34e48693df9428df6ebdf050f0775e5a074170917f70f0dcbde7debdbf6346f680b3f78d99d1cbcaa2b6eb674d1cdbe03ba60eca1ae1c346940d7085775c5d8f1028c05ff0d3975c984249304009b2d6c6f00000023561f8b08000000000000ffed9d79741cc5b5c67b6459963d1acbf2be5bac5e4648a319c9b6b08d65b3181bb3790163360b5b3606db32b60c983d648310080961c90664634908d94312b2ef2464812c2404b213c8bf39efe49d774e4edebb3553f7e853b96bdeb4dc35ae96ef9c7335d557357d7ff7ebdb353dd5dd336f0441900a4a8f1164c706873ef8ffddfa3977788ff618d79573c9994a08674d4238472484b336219c2313c2599710ce5109e1ac4f08e7e81839155b4d30f81137ef1807bac6cd984e98a60d09d03493304dc72640d3c6201963d4b88470362584737c42382724847362423827258473724238a72484736a4238a72584737a42386724847366423867258473764238e72484b339219cc72484f3d884701e9710cee363e49c079c27e8e713f5f35cfdcc7de6ebe705fa39ab9f5b748eb57af924b256b236c567fc4f9d68c89315c83af4ff9af5ff3ac916922d225b4cd6457632d912b2a564cbc84e215baef35f41b692ec54b2d3c84e273b836c15d99964abc9d6909d45b696ec6cb273c8ce253b8fec7cb27564ebc936182c1bc92e20bb906c13d945649bc92e26bb84ec52b2cbc82e27db42d6437605d956b26d64bd64dbc976905d49b693ec2ab2abc97691ed26db43d647b697ec1ab27d64fbc9fa0dcd0e905d4b761dd9f506e741b21bc86e24bb89ec66b25bc86e25bb8dec4d64b793bd99ec2d646f257b1bd9dbc9ee20bb93ec1d647791bd93ec6eb27bc8de45762fd9bbc9de43761fd97bc9ee277b80ec41b287340b17fbfbc8de4ff601b20f927d88ec61b247c81e25fb30d947c83e4af631b28f933d46f638d913644f927d82ec93644f917d8aec69b24f937d86ecb3649f23fb3cd917c8be48f625b267c8be4cf615b2af923d4bf635b2af937d83ec9b64df22fb36d977c8be4bf63db2ef93fd80ec87643f32347f8eecc7643f217b5eff8fe7907e4af633ddfeb97efe857e7e413fbf68bce69764bf327cbf26fb8de17b89ecb7bafd3bfdfcb27efebd7e7e453fbfaa9fffa09fffa89fffa49fffac9fffa29fffaa9fffa69f5fd3cf7fd7cfafebe737c80ae34bedfa60e0d11dc434ee74f476a9f30f2cf609c1e087d26284fe1f3f376b7fad5ee667d66ea45e1e69f8ebf4729db19e7abd5c6ff89bf47293e19fa0972718fe497a7992e19fa297a7803f1dc03ca4f62bdf08ed4a818febb0067c2383c19a285f1daf0e7ca382c15a281f6fc73af08dd6be51e01ba37df5e04b6bdf68d68cac41fbba83b86a22d7a3d69b897bbdfadcccd8f879b7aaf5363ae21d173f6faf5a6f93035e551f7ab808c641dd4cd0be26f04dd4bef1e09ba47d13c03759fb26826f8af64d02df54ed9b0cbe69da37057cd3b56f2af86668df34f0cdd4bee9e09ba57d33c0375bfb66826f8ef6cd025fb3f6cd06df31da37077cc76a5f33f88ed3be63c077bcf61d0b3e1e3f8f031f1fc31daf7d6a4cf85700afd1fe1af09dc8632ef8e6f2780bbe793cd6826f3e8fb3e05b00b1d9978531847d2ddac7e391fadf42ddee0ee2aafffc36b5de4571af97d6acd6db15ff7a8be7ad4e0e0674ed86388b40ab25ba1de3b531ed183ba58de3b0bf16daaba02ff7633df83d85d9d57bc762dd5e52e6750b8dd765a0cfe290fcbb8378f3ef3278ba0c6655ff4b8123fe9a2db44bcd56fc885cb31ba1af597b7c7c331c6b760d7038a8d94e37359bcf49cd96e6178220bcf6f8187738d6ec26e088bf663ba5662b7f44aed96ba0af597bfc396738d6ec76e088bf661775cab141c58fc8357b2bf4356b8f3feb0ec79aed070e0735db25e36cc58fc8357b37f4356b8fe75d8663cdde0e1cf1d76c97a39a2d48cd06a5734541105e7b3c07381c6bf65ee088bf66b776c9b141c58fc835fb24f4356b8fe7a38763cd3e0c1c0e6ad6d5fc6c5e6ab6748e3c08c26b8fcf8d0cc79a7d4ab7d579869febf30c33c1f70bed9b05be17b46f36f85ed4be399057fcfbc0b682ec03153f22ef03cf415fb3969b757b38ee03df000e0735db29355bf12372cdbe047dcdda3b56b78763cd3e0f1c0e6a7691d46cc58fc835fb1af4356b8faf5f188e35fbb26eabe385dfe9e38513c1f7b2f6cd05dfefb56f1ef85ed1bef9e07b55fb1680ef0fda9705df1fb5af057c7fd2be93c0f767ed6b05df5fb4af0d7c7fd5be1cf8fea67dede07b4dfbf2e0fbbbf615c0f7baf67580ef0dedebd43e754e80af4ff99ef6d5434edd417cdbb6784d4a30f8913296bba1dde296279709065f57cdb15ae38f5550b99f14549e7b2bf0b439c83d0d312ae169039e5cfc3cc56b2fdae35f6f711b9f64689a865827415e790779a52016af9b97395e067c381ee443180bf133e653108bd7cdcb0560641f8e4f3cbef2fea3c6e6b1a9015e07fb52f1fd19e3750307c7ab853e2f340df41dafd91ae0ff3c0634401bc7ef9ce17354abed787d3faf9b97db819173cc559f315f29639bc1580f6c31f214356b3378da42b4385a633b18ab8bfb1fc7e0fd8ff7258e570b7dfea766a0ef8929a76cf9a8efb3589ff18ffff91cee9b95f0e481c7c518e3e87d2e87ef4dff09e2adb50e43ab9ca15506fa1440bf0e07fa957bafe478c22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc2ec3f339e3fc6f36d61e7668f2423fbda81c7c53c7ff13b49f4ba78fdeabcce33705e27fef316f91c9e77e46bb2e61939d7429fe752036ccf869cf3c5f3bbad86cfd13517c56d89d75c74c332c7c373d0780d88ab73885983271ba2850fb19b638b9ddfea66fbe673ea3b01d4f7eab418db34ecfa9305864fd5e9bf6b06f27671ee2feab9481c4bb81de7b9bd4c70e8b5036eae71298d1f3c5ed50483c70f7c9fe98c3df6e073987cbebcd3885d0b7d5e4a0d6c9b85f0ffeee0d0eb72b00faf9b97e7c16b171aeb6e74976fd96b133a819bdb75466e2dc0cd7d5e81f1fc56d84f1cbcc7e5f1fab000780323277ee039fbf88f014ad710e423f074008f83ebc5da1d1debe4b01ee3be8660a1a155d83114f7e904fd62bf1e5eef1fe671302f733c61166661166661166661166661166661166661166661166661166661166661f69f19efef66d634f46bf784b14ad75d14cf67f0f76de079b1dd3503715d9f03e4734ef38d9c6ba1cfd335036cd7e8764370e8b516b66de9eadc9a6d5b72bc06c807cf05b9ba67bd60f01442b4f02176736cb14bd710c4bf7d07ae21c81bdbb4ddd89e78ee1cf7a15ba14ecdefb848833ed5b86ec9b66d381eee4b05f0711befcd76a135be9798d714713c3c777ea7d696cf9dc73f56e7732ec70dfeee2abe4e201f922bf7b907c6be7b751baf1f6987753d12f27f7e943b4fcdfa1d89eff1c2d83e7c8fd7c335037dcdefe362ada37e8f57ce789d8fdfe3751fd4d923f0feef6a4c5a1c846b340f34e23e781ce4e03a93d031d2bcb652f5e1ed3fcae883c72cdce77118a36cd7ae867df79183efe72bfbdd471c0f8f8d3b80d1ccd1bcc6f468bf46ec19182f16c2ffbb83c3bf46ec19a821bc4e2b30d63f1fd6cf5ca302fb7b0bf779d6781f75b56fd9ae41c37dcbfc3cc0bc780d1af7f9168c55ff84e32cf3d81fafd7aac6673bdbf5e11c0f8fa9a2e48ee342dcef8d588fc8c2f1b01e7f6cd4e3420b776bc86b7f6a792d6bc5d71ce36727533fa5c362784d772c3a94c69b2e2317dea716432edce797c67e13ff3153e9f833fe5c071f0ff1185408c995fbfc16f6b597e1f892b7138e95ff08f93f3fca1d7fb27e2ae7a5f1e75cdcbecbf4ba78fb2e0d897d0ab0c614bb1d63f3f127c7617f2db4df80f713eec77ab0d6ccaef6113e864376f3759dc6eb32d0674948fedd41bcf92f3578961accaa765e853afb071c7fba1aab9758349a0f1a711fbc278adf47b8bfed3dc6c5f5bee5de63c2be1f12c7f67f3a9dd30b6733e7f4c28e4fb80fbf168f4ffe1bc6d974485f73ae92df43e2bc6619ef11c942dc7f87c4ed8e59cf4c3058cf8cc1e13276a311bbb18ab19b8cd84d558c2d9a8be63e69eed3f77fe3f774d72480714402186b13c03832018c7509601c9500c6fa04308e4e00e3980430a681f148beb73bd0271f873e0da0534b08b7abfbf15b0c46f3bb1232062ff31cc963245fb7e158fdecf3366c049e6176ac19cb361ca79f7dde864d6e758c65bc1f9f00c60909609c9800c64909609c9c00c62909609c9a00c66909609c9e00c61909609c9900c65909609c9d00c63909606c4e00e33109603c36018cc72580f1f804309e9000c624cc552e70cb38e4cfd78ac7c16f4276e067f44a785c7fb7a6a33c8bd767f1758c717f479af9bb8e2d865678cf89ebdf834d05f6ef4ae578c22ccc36661c0bf1f7b9b95fd613c6b0ef1e76306e447e4f6975cb33e8b7b75bdd6e8bc8ef556e7f13b4f45e7534fc2668d8fd2d61dff7ce7d70dc3852d73162ece6205e2d3a2ad0a24af7603bf9befeb60432fbf21b033c3e85fdc640d613c62afdc640e4f7aa7c888ead6e19f3436574752f33d64b253cf8bd182e6aca4d9ee5bfcb99e3e1f77fe098e4ea9a7ef3fe385eaee43b4b84599885599885599885599885599885599885599885599885599885599885d90f663cc780dfe5ccfdb29e309adf93e4683e3ef2b99ace101d5bdd32e687ca88df7f161f4fe95c4d94efa95a043c2e6aca4d9ea57335e6f76d761a39e1f76de2feedea3bc816193cbcbc18b683300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb330fbcd8ce71898350dfdb29e30b26f21f0b8f83da6a8e7411685e8d8ea96313f5446c5e3e037e43ab05e2ae1c1dff57051538ef21cf45b79bcee45464e19e883fbf7c90ef24c05f6df8fc3dfd51366610e63c6318b59d3d02feb0923fb16038f83fd3bf2d8df15a263ab5bc6fc5019154ffcbf61593a4fdf1581077fd3c8454db9c9b334f69bbf9564fe566706fae0feede077b3427f27899797c27688c25c4820b3e82c3adb984567d1d9c62c3a8bce3666d15974b6318bcea2b38d5974169d6dcca2b3e86c63169d45671bb3e82c3adb9845e7a347673cc7c0ac69e897f584917d27038f83f9f8c8e76a9684e8d8ea96313f5446c5b32c769e420eeba5129e65c0e3a2a6dce4593a57738a91d31223a70cf4c131e9140779a6202eaf9b974f81ed30dc990b096496daa80eb3d48630db98a53684d9c62cb521cc3666a90d61b6314b6d08b38d596a43986dcc521bc26c6396da10661bb3d48630db98a53684d9c62cb521cc3666a90d61b6314b6d08b38d596a43986dcc3ed4065ea3c3ac69e897f584917d4b816799039ea8d7112d0bd1b1d52d637ea88c8a6779fc3c1d582f95f02c071e1735e528cfe2b54edd464ecb8c9c32d007c7a46e0779a6202eaf1bf30ef476e81666610e61c6318b59d3d02feb0923fb4e011e07fb77e4b17f79888ead6e19f34365543c2b1cf12c8fc0b30278bae3e76977946771ec5f69e4b4dcc829037d70ff5ee920cf14c4e575f3f24ad80e4963c67d8959d3d02feb0923d618f338a8bbc863d28a101d5b13c0d89600c6d109601c9300c63430661d30a6743ce4e1e5ac5b7df271e8d3003af93aee6580c7d5366c34781a43b4f0751b8ed5cf3e6fc346e071b50d9b0c9ea6102d7cdd86e3f4b3cfdbb0c9ad8eb18cf7e313c03821018c1313c03829018c9313c03825018c5313c0382d018cd313c03823018c3313c0382b018cb313c03827018c38a771243fe71ec9cf6747f27385682e9ae70eef219a8be6a2b9682e9a07a279eef01ea2b9c79a27e13384300e6fc682a78cc8938a8f2787b963ac951ee4ce0c49632c2480d1f57546a2632c8cf9a1322a9ed31cf1ac8cc0731af09c1a3f4fbba33c8bd71a9e6ee4b4d2c829037db00e4e7790670ae2f2ba79f974d80e4963c67d8959d3d02feb0923fb4e051e57fb5794fd1df7af331cf19c1681e70ce071b1bd1ce559dcdf5719399d66e494813eb8efac7290670ae2f2ba7979156c87a431e3feceac69e897f584917da7038fabfd2bcafe8efbd7998e78ce88c07326f0b8d85e8ef22ceeefab8d9cce3072ca401fdc77563bc833057179ddbcbc1ab643d298717f67d634f4cb7ac2c8be55c0e3a0ee227fe6383344c7b604301612c0283a8a8e3e318a8e478f8ec2288cc2288c4782310963b8bccf449f1bc0cfe26be2e7e9c0cf6d95f0ac011e179fed1ce5599c1b38cbc8e94c23a70cf4c13a38cb419e2988cbebe6e5b3603b08b3308731e398c5ac69e897f584917dab81c7c1fe1d79ec5f13a263ab5bc6fc501915cfdad8793a72582f95f0ac051e1735e526cfd2d87fb691d31a23a70cf4c1fdfb6c0779a6202eaf9b97cf86ed1085b9904066d15974b6318bcea2b38d5974169d6dcca2b3e86c63169d45671bb3e82c3adb984567d1d9c62c3a8bce3666d15974b6318bcea2b38d5974169d6dcca2b3e86c63169d45671bb3e82c3adb984567d1d9c62c3a8bce3666d15974b6318bcea2b38d5974169d6dcca2b3e86c63169d87c6ac78f8ba73664d43bfac278cec3b0b78d63ae0897a1dfeda101d5bdd32e687caa878ce899fa703eba5129e7380c7454d39cab378afc0b9464e6b8d9c32d007c7a4731de49982b8bc6e5e3e17b64314e642029945e7a131e398c5ac69e897f584917d67038f83fd3bf2d87f4e888ead6e19f34365543ce7c5cfd381f55209cf79c0e3a2a61ce5591cfbcf37723ac7c829037d704c3adf419e2988cbebe6e5f3613b08b3308731e398c5ac69e897f584917de7028f83fd3bf2d87f5e888ead6e19f34365543ceb62e7c9e7b05e2ae159073c2e6aca4d9ea5b17fbd91d379464e19e883fbf77a0779a6202eaf9b97d7c37688c25c4820b3e82c3adb984567d1d9c62c3a8bce3666d15974b6318bcea2b38d5974169d6dcca2b3e86c63169d45671bb3e82c3adb9845e7a347673cc7c0ac69e897f584917de7038f83f9f8c8e76ad685e8d8ea96313f5446c5b321769e420eeba5129e0dc0e3a2a6dce4593a57b3d1c8699d915306fae098b4d1419e2988cbebe6e58db01d863b732181cc521bd56196da10661bb3d48630db98a53684d9c62cb521cc3666a90d61b6314b6d08b38d596a43986dcc521bc26c6396da10661bb3d48630db98a53684d9c62cb521cc3666a90d61b6314b6d08b38dd987dac06b7498350dfdb29e30b26f3df06c70c013f53aa20d213ab6ba65cc0f9551f15c103f4f07d64b253c17008f8b9a729467f15aa70b8d9c36183965a00f8e49173ac833057179ddbc7c216c076116e630661cb398350dfdb29e30b26f23f038d8bf238ffd1784e8d8ea96313f5446c5b3297e9e0eac974a7836018f8b9a72946771ecbfc8c8e90223a70cf4c1fdfb220779a6202eaf9b972f82ed20ccc21cc68c6316b3a6a15fd61346f65d083c0ef6efc863ffa6101d5bdd32e687caa87836c7cfd381f55209cf66e07151538ef22c8efd171b396d3272ca401fdcbf2f7690670ae2f2ba79f962d80ec22ccc61cc3866316b1afa653d6164df45c0e360ff8e3cf66f0ed1b135018c6d09602c2480d1b18ef9a1322a9e4b1cf16c8ec07309f0b8183f1ce5597c9fbfd4c869b3915306fa601d5cea20cf14c4e575f3f2a5b01d92c68cfb12b3a6a15fd61346f65d0c3caef6af28fb3bee5f9739e2b92402cf65c0e3627b39cab3b8bf5f6ee47489915306fae0be73b9833c531097d7cdcb97c376481a33eeefcc9a867e594f18d97729f0b8dabfa2ecefb87f6d71c47359049e2dc0e3627b39cab3b8bff718395d66e494813eb8eff438c833057179ddbcccf192c88cfb3bb3a6a15fd61346f65d0e3c5b1cf044dddfb70063d8670e5f190b0960141d45479f1845c7a34747611446618cc6b822018cb2ad85d157c6ac03c6948e873cbc9cad42ec4623766315633719b19baa185b3417cd4573d15c3417cd0f37b6682e9a8be6a2b9682e9a1f6e6cd15c3417cd4573d15c343fdcd8a2b9682e9a8be6a2b9687eb8b14573d1dc8cdd137fecc8d773f700cf16075a38ca33a7d67b855ed77f62d44f69b5d5d02a6b6895813e57807e5b1de81776cd352f73bca8cc277ac0ec28767e2cad6334e4cf310a861e2afe3647b9dbc6bc6d55886d1bf3aa11db36e65523b6682e9a8be647afe6d8ae0d0ebd0749ada357b747ea65eebf025ec77d1e68283d3706b23d5dc4967d483417cd45f323a139ea5253059ec0e009caf0ccf68c67aa673ce33de319ed19cf08cf78e67ac633c7339e699ef14cf08c678c673cb59ef14cf78c67a2673c69cf78467ac633cf339e199ef1ccf78c6792673c0d9ef1643ce3a9f38c67a6673c933de319eb194fa3673c0b3ce319e5194f8f673cb33ce399e219cf38cf789a3ce3a9f78c27e5014f3a38f49a9a34fcbf077c35c66bd5783571fcc0ffb76b7f0dbc66876e8f0859f776f0f1b9aa1d21af459db6432eddba9d3bbc4751278cd50dcb1caf01387678c253ef194f93673ce33ce399e219cf2ccf787a3ce319e519cf02cf781a3de319eb19cf64cf78667ac653e7194fc6339e06cf782679c633df339e199ef1ccf38c67a4673c69cf78267ac633dd339e5acf78c678c633c1339e699ef1ccf18c67ae673c233ce319ed19cf78cf78a67ac633db339e9a109e1e473c3c7fc9ebe6e51e4f623bd80ec5fb16af7494d34ebdae3abd5ee6e778b5d0e721fdc14dcd47e06b99cb9c6fc6b9a69da051afa35c6cd72ef75621b6eddae56ac4b65dbb5c8dd8a2b9682e9a8be6ea11e33df59d72bf45e53c72bf45791eb9dfa23ccf5ccf78e47e8bf23c72bf45791eb9dfa23c8fdc6f519e47eeb728cfd3e3198fdcff519e47eeff28cf23f77f94e791fb3fcaf3c8fd1fe579e4fe8ff23c72bf45791eb9dfa23c8fdc6f7128cfff77bf05de27c1e7a67ac177a56ef780af262406af6727f86a759bd7a1c69b39e30f65a881d75c15c27565483c8e7355c86baba13bc6ea86658e87f76f5ce5094fbd673c4d9ef18cf38c678a673cb33ce319e519cf02cf781a3de319eb19cf64cf78667ac653e7194fc6339e06cf782679c633df339e199ef1f478c633cf339e919ef1a43de399e819cf74cf786a3de319e319cf04cf78a679c633c7339eb99ef18cf08c67b4673ce33de399ea19cf6ccf786a42787a1cf1d8aea3eda9426cdb75b4d5886dbb8eb61ab14573d15c343fba35bf3afed81de960f06fb6a947ca58ee86f6d5c0e3e2fdce519ec5fbef76e975c5788f434e69b5dbd0aac7d02a037d76817ebb1de89782b8bc6e5ee678c22ccc3666157b4ffcb18be30cc6667d0283871f7b1c6be128cfe278d017846bccf132d007b7799f833c531097d7cdcb7d21b19b8378b5d85b81167b4378f656590b8e1795795702997dd059c5be26f6d8f95cda88cdfa04060f3fae71ac859b3c4bfbd6be205c638e97813e58a7fb1ce49982b8bc6e5ede07db4198855998855998855998855998855998855998855998855998855998855998fd6656b1f7c71ebb347f8fb1599fc0e0e1c77ec75ab8c9b3347fdf1f846bccf132d007b779bf833c531097d7cdcbfdb01d84599885599885599885599885599885599885599885599885599885599885d96f6615fb40fcb18bf7f9606cd6273078f871c0b1168ef22ccedf5f1b846bccf132d007b7f9b50ef24c415c5e372f5f0bdb419885398c59c5be2ef6d8a5f379189bf5090c1e7e5ce7580b377996c683eb83708d395e06fae036bfde419e2988cbebe6e5eb613b4461ee4b20b3e82c3adb984567d1d9c62c3a8bce3666d15974b6318bcea2b38d5974169d6dcca2b3e86c63169d45671bb3e82c3adb9845e7a3476715fb60ecb10bc5f97b8ccdfa04060f3f0e3ad6c24d9ea5f9fb1b82708d395e06fa609ddee020cf14c4e575f3f20db01d863b735f0299a536aac32cb521cc3666a90d61b6314b6d08b38d596a43986dcc521bc26c6396da10661bb3d48630db98a53684d9c62cb521cc3666a90d61b6314b6d08b38d596a43986dcc521bc26c6396da10661bb30fb5a162df187fece2fdec189bf5090c1e7edce8580b477916af7fb92908d798e365a00fd6e94d0ef24c415c5e372fdf04db419885398c59c5be39fed8f9b4119bf5090c1e7edcec580b477916c7835b82708d395e06fae036bfc5419e2988cbebe6e55b603b248d19b75f2abed8c5eb3639468d7e56be5b757b04f86ed3ed5af0bd49b74782ef76ddae03df9b757b14f8de02b9b1efadbabd007c6fd3ed1ef0bd5db7b781ef0eddbe1a7c77eaf66ef0bd43b7f780ef2eddde0bbe77eaf635e0bb5bb7f781ef1eddde0fbe77e9763ff8eed5ed03e07bb76e5f0bbef7e8f675e0bb4fb7af07df7b75fb20f8eed7ed1bc0f7806edf08be0775fb26f03da4dbbbc0f73edd1e0dbef7ebf618f07d00dafcfc41dd6e00df87743b03be87757b2cf81ed1ed46f03daadbe3c0f761dd6e02df47747b3cf83eaadb13c0f731dd9e08be8febf624f03da6db93c1f7b86e4f01df13ba3d157c4feaf634f07d42b7a783ef93ba3d037c4fe9f64cf07d4ab76781ef69dd9e0dbe4febf61cf07d46b771fb7e56b76f061f8f03b7808fc7815bc1c7e3c06de0e371e04de0e371e076f0f138f066f0f138f016f071ddbd157c5c776f031fd7dddbc1c7757707f8b8eeee041fd7dd3bc0c7757717f8b8eede093eaebbbbc1c775770ff8b8eede053eaebb7bc1c775f76ef071ddbd077c5c77f7818febeebde0e3babb1f7c5c770f808febee41f071dd3d043eaebbf7818febeefde0e3bac371a159b73f08be6374fb43e03b56b71f06df71bafd08f88ed7ed47c177826e7f187c27eaf647c03757b73f0abe79bafd31f0cdd7ed8f838fdf9b1e035f56b71f075f8b6e3f01be9374fb49f0b5eaf627c0d7a6db9f045f4eb79f025fbb6e7f0a7c79dd7e1a7c05ddfe34f83a74fb33e0ebd46d1e17d4fed700b9709e0dc07d52080ffbea81a73b88f7988963f1ba79390f8cac637bf519f39532e60c46c5d3e14033ac0d7e94fb4cd2013c05073c8ef22c7e26e93472ca1b3965a0cf899067a7833c531097d7cdcb9d10dbc536472deaf47ae71a5ad4429f37f41b9a7aff2ba723af43d56f7b482eae74cc193cb990d88b1debc8ebe631717115622f3462b719b1713ce747b97d7b21302f72c0acd6db15ff7a8bfbf6c97a5d5ccf1ca70d725a021ac49513c64e69e338ecaf85f6ff360df4e57eac07bf7732bbda8f785b22bbf9ba0ee37519e8b33824ffee20defcbb0c9e2e83591dffff57d3008783fda158038b0d0e5e6e03edba2cda2d06edb84f3bf8f818a7137c7cacc0ebc063253c8e68893fdfd0b187975b80917d0b81b12584b13d7ec6e2b14e8bc1d812a22dfb1601cf42479a2d3278e61afae0fbf228a30fbfb616fa8cd71fec1a83c19f21b8afaafdb1a981bcf833f37f8278c7d53a077ae1e7f900f4090c0df9c10cf5c1c067fe3879c604039fe9f7f7f7edebd9d1bbaeb7675b0ad06a0d4c7c4e85a451033e6c8f08f105c1e0a90b9cf2e4a90b9cf2ac3164c12913eeaf3e4aa9b4787aa077f7cefe8d7b7af76cdd77706f7fefb6b57d3b907aa4418fa4b60c90147dfca80f062659ba83784f76d419b1ca154f3d3c8f8a9fa7dd519ec5379ed1464e75464e19e83312fe37da419e2988cbebe6e5d121b1631c888a5a8ca9408b31213c63aaac054e54b30ff754fe3f9e9ca83172c13d1a7332eb3cd68438e009b0fe948653ff533bfb489dcca8606063f3e8a98e2ad54650339cea5d4bcd60aa83333504a919493503a9661cd50ca39a515433886ac650cd10aa19413503a866fcd40c9f9ad16b0e4a33766a864ecdc81d0f5cdf0356f5895abd3baa19353583a666ccd451957af7574722eae8571da9a94f6feae8407daa54330cea9d561dc5a87768f5aeaa8ed4d4119a3aa25647984bc996919d42b65c6bbd826c25d9a964a7919d4e7606d92ab233c95693ad213b8b6c2dd9d964e7909d4b761ed9f964ebc8d6936d20db487601d985649bc82e22db4c7631d9256497925d467639d996a07456ea0ab2ad41e96c542fd976b21d645792ed24bb2a289d955233efea4c943af3a4ae8651679bd4d9257536499d3d52678bd4d9217536489dfd51677bd4d91d7536479dbd51676bd44cbd9a995733f1b705a5997635b3ae66d2d5ccb99a295733e36a26fc8ea034d3ad66b6ef0a4a33d76aa65acd4cab996835f3ac669ad5ccb29a495633c76aa658cd0cab996035f3ab667ad5ccae9ac95533b76aa656cdccaa99d84783d24cab9a595533a96ae654cd94aa99513513fa44509ae954339b6a2653cd5caa994a3533a96622d5cca39a69fc1cd9e7c9be40f645b22f913d43f665b2af907d95ec59b2af917d9dec1b64df24fb16d9b7c9be43f6dda05483df27fb01d90fc97e44f61cd98fc97e42f63cd94fc97e46f673b25f90bd40f622d92fc97e45f66bb2df90bd44f65bb2df91bd4cf67bb257c85e25fb03d91fc9fe44f667b2bf90fd95ec6f64af91fd9dec75b2378281330e3850fc462ff0ec774f7f7fefeebdfdcdfd7dcdbb0feceadfb977d7c1e6eb76f65fd9dc776defbeedbbfaaec317dfa187269eda5fb16f5fcfc1e69d7bb6f55edfdc77a0bfb96f7bf3157d07f66cdb8f2f7a4cbf68e6a1117bb66db307fb52cd61907e7588419fd3afe39326abcbe7f6fc50047971282ffad71013ba5f9f8a5aaa97d7978e689bf7efeaeb6fce35efa1bf3dbbe835bddb5a9bf17ffb49e4fdfdcdfbfb7bf6f5376fdfd7b7bbb9bd15d7fb60660849bcde348417358daf3cf3e0ff00fdc58975355f0300", + "packedBytecode": "0x000000028df71de500000036441f8b08000000000000ffed9d079454c799ef6fcf0c493dcd30420284080392c8a1a72730e426470990002123230d0c20860c4316306491a364d972daf57a83d7de607bd76b6ff0aec306e7b45edb72ce3ee7f99df7ce79efed396f7775b6aabb3ecf9f9abaedeee156eb6bf8ee39df74dd6fead6f7fbbe5bb76ef5adea5bb120bbfd4a49cca4cb953c1274dee8ff69f399bcb3ad36c2b2923e396325c25956229ce525c25951229cdd4a84b37b8970f62811ce9e25c2d92b424ecd5616dcbe45cd7b9f87b846cd182fb1985696404c132516d3de2510d3aaa034daa83e25c2595d229cf7970867df12e17ca044381f2c11ce7e25c2d9bf4438079408e74325c239b044381f2e11ce4125c239b84438879408e7d012e1ac2911ce6125c239bc44381f2911ce474b84f3b108394701e708f339d27cd2ff469bcf31e673acf91c673ec71b1f2bccfe042513359b925aeb7f2925754aea953498ffd598ff352a99a4a449c9642553944c55324dc974253394cc34becf52325bc91c257395cc53325fc902250b952c52b258c912254b953caee40925cb942c57b242c9934a9e52b252c92a8b65b592a795ac51f28c92b72859abe459256f55b24ec9734a9e57d2ac64bd920d4a5a946c54b249c966252f28d9a2a455c95625db946c57b243c94e25bb94ec56b247c95e256d4af65931dbafe48092834a0e599c87951c51f2a292a34a8e2939aea45dc9092527959c52725ac9192567959c53f29292f34a2e28b9a8e49292cb4aae28b9aae49a92eb4a6e28b9a9e496929795bca2e46d4a5e55f276c34295fd1d4a5e53f24e25ef52f26e25ef51f25e25bfa3e47795bc4fc9ef2979bf92df57f2074afe50c91f29f980923f56f241251f52f2274afe54c99f29f973251f56f211251f55f2174afe52c9c794fc95928f2bf98492bf56f2374afe56c9df29f9a492bf57f20f4a3ea5e4d34a3ea3e4b34afe51c93f29f96725ff62c5fc734a3eafe40b4abe68fe47cfbabea4e4cb26fd15f3f955f3f935f3f975eb986f28f9574bf74d25ff66e9bea5e4db26fd1df3f9baf9fcaef9fc9ef9fcbef9fc81f9fca1f9fc91f9fcb1f9fc89f9fca9f9fc99f9fcb9f9fc85f9fca5f9d4e3a4ef1f904df70c3ab6741051bb53bfb1598f9350b04704b76f3a16e5e67ff45963f415669f3e2976ddcc7e374bdfddec77b7cae969f67b5afa6ab35f6de9fb9afdbe96fe41b3ffa0a5ef6ff6fb833e1ec0f352a3d7ba72a38a818eea6119e8ba05b7c744ebba5371a0eb11dc1e0bada3f3d81d74bd8cae07e8ee33ba9ea08b1b5d2f8a99924aa34b0751d58964b32e371175b9660ca977f4bc1b74b9559e78fb44cfbb51975bed8157d78ffb4d597da0def435ba6ad03d6074f783ee41a3eb0bba7e46f700e8fa1bdd83a033cd54d00f740f195d7fd00d34ba01a07bd8e81e02dd20a31b08bac146f730e88618dd20d00d35bac1a0ab31ba21a01b6674434137dce86a4047f3538681ee51a31b0ebac78cee11d0519bfa28e8a85ff798d1e976e2df0338c6e8cb403792da61d08da2361874a3a9fd05dd186a7b4137166c936e1cb42ba41b6f74d446e9ff359a743a88ea9a4865ae89495197ab4ad6e54e8ebedccc98db94a023ae69b033096235d5a4239cd7538bb66346c80ee92b20bd10f2523e8a07dd67885ddf4f9a4c7a6a8ee31aade31290a7c9e17f3a88d6ffc916cf648b59d7ffe9c0117d9dad4b499dcd7b2bb8ceae86bc76dda33ecfdd5867970087873adbe8a7cea6925267b3cf1c82c05df7a8df7b37d6d9678023fa3adb207536ffade03abb07f2da758fbefbdc8d75763370445f6727354adf20efade03adb0e79edba47df7fefc63abb0f383cd4d9666967f3de0aaeb35720af5df7e859ccdd58674f0147f47576b2a73a5b277536c88e1f0581bbeed173c1bbb1ce5e078ee8ebec8666e91be4bd155c673f0079edba47cfa8efc63afb1ee0f050677d3d9f4d499dcd8e9b0781bbeed178c9dd58673f64d27a9ce12b669c6110e8be6a748341f735a31b02baaf1bdd50f02bfa6ba0a55eae81bcb782af81cf415ebb2ed798f4dd780d7c12383cd4d946a9b3796f05d7d96f415ebbee0d37e9bbb1ce7e11383cd4d926a9b3796f05d7d99f435ebbeed19c86bbb1cebe6ed2babff01d6bbe9bd6bd6e742341f75da31b05baef19dd68d07ddfe8c680ee07463716743f34ba71a0fb91d18d07dd8f8d6e02e87e62741341f753a34b82ee6746570bba9f1b5d0a74bf30ba3ad0fdd2e8ea41f72ba36b303a3d2640f3533e63743dc15e3a88eedcc6c137da62d67e1ad2b57e799209e0415b75d1dbaad3bea782fc7daf039e7a0fbec7c1463e3cf5c0d3103d4fad977b4f327b8e53564ce3602b057e79b84765dab3c6e0f698d23ed94b800eafd5490ec6a6e8195331b04565d37e133092ae0118a92da5eb47b7cd55b10e5e0fd752e6fe8cf6d2c041f62a20cfcc011d79fb1ab64af83fb50195703cb6ad9cea8a66a43ad2587cc654be8c0d16a3a7eb3b13b3068bc7657b8a27db762ca84e4d2982ed26cb76bd651bdb10da72b5f1d8b7f3d0afaef5d467ccb407d34c59d45f273b78df9a0e3188ca27b44dfd75b243fa0a48a7621d79291fc583da1e62d7d7119d4b64b78f9b641d97803c531cfea78368fdb7bf3f4cb59875bb3b12ee091eae87dbbeb351d9b45f0fb19b1a12bb29103bca331274748f68041db5b55406f66fb11df6d15f8a05b7f7a5d3b0dfe0e06e02c60607a3873e662a57db5c0f8ca49b0c3c294f310bfb6e9912db3eea69e6ba241bd457a36b88ec55409ec1e51d7917439be1a37ee2b5405bbedf81a23f4fa9cc77b2fa0278f0dc79e867d77aaa8f49fc3eff46106d5db3dbc47a2b5661dff9931ee287759fcaa67db227ccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccfc99712c0be7f150be06268cf67c285fcff933efaf3265e118d0eb5ee707a532e300147f9a0f30daf2b902f2fc3ad6c1f603981f44ffc7f94eae73e963ae64ae7349f65cf3957c8e37d7593c758e5870b05d1399edd4063fe73795d4ef8fd1ef60abb7cea93d369f79b79ba5d3f5b4a6bcc36f1f637f858e45625b42e928c7f612c083b67c9c1bbcf6ca82dbdb0fbccff89ac7426d358d974fb16c57409eff80f94453e1ffe9a0737b8179a86cda1f0dc74eb5caaef2e76fceb909f83b08fbf718e45b2370ff66fe4f59878fef33694ff7b854a1f3a8b19d8ebe0f909d43902a8027093c3eee639efa3a49ac8f51cf21b0e788b9fa50f66f727cfe1ec6ee07d37eaedff008b3300bb3300bb3300bb3300bb33027ef6c13666116666116666116666116666116e68899358feb1d1494af8e096391e65d64c633e83d4c382e76bdacc3aeef31401a731a63f98cbf5bfd5a5907dbcb265d19749e6b11762e7d8dad859d4bb2e77a0f8aaf31e518d8a2b26b1db1e060bb2632dbd93904d19fdf8e390429eb9cd659e713c7cef11a7a1fd4537b3e453ce83c27c1d3359ef3dc903dbc9670fe0ba5f1b7d93e628df7127b4e11be978ff27cc8c496c6cea36fab53499fed06bdaf84e609a41cbe529e0f43dbf75193c6f9237550d6a71dffa72dd73835c54ffb3c237a9f33e777a6298bceef0c87ed34b04664bb166dc7acb2495f01e94f957566a07850ac895d5f23f8de97b0e3eaade3129067bac3ff74c4fecfb078f01ceb4dd79d8f413dfb34dcff7db549d34362341a6244793cbf3fd0391fd09ed388ed680f2b0f1d8bef45fb3cb4516173575df780699efc0bbb0790bd44d0f9be90cf1cd37b7d8ed8ebd05e4c85ffa7833b9f23f63ad4219ca71558e58f81f289ab47107e6fa13c3fb0eea31ee670e5f57e1cd7f701e2c5396894e7a7d056f53373350bf93ef0667db7737d1fc0e3c27cc77621ea7b23d64764c1f7ab519eff69d5c7a921dc4d8e63ff77c8b1142bfb5d619541e7f8f979cf5ab6bd9961f942d7d474f085f2fcbb75dd44df67caf63f7dbd538efa3ad406d53a7ca53cff09d7da1bd0bfa4f384f7854479e7ffd396abff49f1d33ecf8adee7ccf99d6dcaa2f33bcb617b0eb04664bb166d53ff93ec90be02d295e51d79291fc583624dec95c089ecf67153ace3129027edf03f1db1ffb32c9e591673a6ed8177932560febdafb63a1db863340662f41b7ba0a3fb08be07d4f5acc3d7bd34ac1f87bfdb221db6edfd20a6c5fa4d8dfd4ccfd53f1963f163ffe461c35c65e26ce7b59f55d27151ce59c6df8860bf107f23e2eb3b5222b83d9e098bc3a7ed2acb7655116d575bb6ab8b685b622e31e714734e6b45e0d8541930fab8d7e17d351f46d7fdaf1c187dfd8e2f5500631d30e2fd8e183dbc87b5b6ab6b51605fa71b30faf80d6aa1cfabf11dccf85b6462f4f12efc42df678befb2a6e37a00a38f350e70ad827c185d6b64f4844f0feb61d476f5bdf9b846462f60f4f12efd7870fbfbff7f1b23aee544c7dd078c3ec691e2c1edcfd57e1b23be839d8e8b7b66cc756ff73c1f2455e833089c7f81cfa0284eae792cbe9ed5dbcfc6681f9fd5236fe02f8e39fb4853fdc6228571a72dd73974c5a7b7f98cc3fffd3e4fbc7d8c97caa6fde9c048ba2abf71ccd9d79ce63716298c3b6db9cea12b3e7dcc673ce8bcfe87a7316be71825ede3382ee9aa3df3c42d9edf164717e3fdc038d313e38c02186702231dd71718d39e186716c09806463aee0160f4f0bc3ac3982e80119feb92fe41609ced897156018cb381918eeb078c3e9e3dc7c16e3e8c7380918eeb0f8c733d31ce2980712e30d2710380719e27c6b90530ce03463aee21609cef89715e018cf381918e1b088c0b3c31ce2f80710130d2710f03e3424f8c0b0a605c088c74dc20605ce4897161018c8b80918e1b0c8c8b3d312e2a80713130d2714380718927c6c505302e01463a6e28302ef5c4b8a400c6a5c048c7d59400e3b012601c5e028c8f9400e3a325c0f8580930f62c01c6b1c0f878f48c99efd74b0b607c1c789645cf531f071bf9f02c039e27a2e7a9f5e467667ed6725356d4ef485b61c5ea712b5609c8b31ce2b7c243fc626097caa67db227ccc21cc6ac79a87d22d638e45bca8491744f78e6895b3c7acbd53eaef0cb934c38e2a16d3d19bdad54a1be3f093c2ba3e7c9dcab9e2c806725f03c153d4fad273f33f79455964f4f5a3e25200fb61bab3cf81903bb5436edaf72d8ae09a28dc5ea3c62b1dac1b3bac8b1207b85322f2f41660e71c6b69058e3906f191346d23de599276ef1e82d57fbe8625ce19731d55546cdb326729eec3ba25717c0b306789e8e9c277b4f89decf6c3bfa8ce5d36acba704e4c136e9190f7ec6c02e954dfbcfc0791066611666611666611666611666611666611666611666611666611666611666decc38c640ac71c8b7920923e99ef6cc13b778f4966bdcc1c5b8c22f63aaab8c9a676de43cd9b19a670ae0590b3c6f899c273b5613bd9fd9b19a672d9f9eb17c4a401ebcbe9ff5e0670cec52d9b4ff2c9c0761166661166661166661166661166661166661166661166661166661166661ce6e5c99718c8158e3906f0d1346d2bdc5334fdce2d15bae710717e30abf8ca9ae326a9e75d1f3647eabf96c013ceb80e7add1f3d47af2333356f39ce5d3b3964f09c883d7f7731efc8c815d2a9bf69f83f320ccc2ec62c6368b58e3906f2d1346d2bdd5334fdce2d15bae76ccc5b8c22f63aaab8c9aa739729eec38fd7305f03403cff391f364dbfee8fdccb6fdeb2d9f9eb37c4a401ebcbed77bf0330676a96cda5f0fe7a110e65525c82c71963887314b9c25ce61cc1267897318b3c459e21cc62c71963887314b9c25ce61cc1267897318b3c459e21cc62c71963887314b9cef9d38e31803b1c621df3a268ca47bde334fdce2d15bccda4f43dac5b8c22f63aaab8c9aa725729ebacc58cdfa02785a806743e43cd9b19ae8fdcc8ed56cb47c5a6ff994803cd8266df4e0670cec52d9b4bf11cec3ddcebcaa0499a56e148759ea863087314bdd10e63066a91bc21cc62c754398c398a56e087318b3d40d610e6396ba21cc61cc523784398c59ea863087314bdd10e63066a91bc21cc62c754398c398a56e087318b3d40d610e63e65037708e0eb1c6215f331346d26df0cc13b778f4966bde8e8b71855fc654571935cfe6e87932ef24d95800cf66e0d9143d4fad273f33739d5eb07cda68f994803cd826bde0c1cf18d8a5b269ff05380fc22ccc2e666cb388350ef95a9830926e93679eb8c5a3b75ced988b71855fc6545719354fab279e170ae069059e2dd1f3d47af233d3f66fb57c7ac1f2290179f0fadeeac1cf18d8a5b2697f2b9c875263c66b8958e3906f331346d26d011e0ff5aee036a9d511c71525c0b8bc04187b9500e37d25c01807460ffdf4cc359cb078687fb3dff8a4a2884f25c4896bbb97001e5fe7b0cae2a972c482eb39ec6d3e399fc32ae0f1750eab2d9e6a472cb89ec33ee693f339acf61bc748dafbfb4b80b16f09303e50028c0f960063bf1260ec5f028c034a80f1a112601c58028c0f9700e3a012601c5c028c434a8071680930fa7ea691eb7b6e6b116c877d3f2b86edb0ef15c5b02d3197984bcc25e6127389f99dda96984bcc25e66f7ecc7d3ccbc5e7c6b4e5fa0ee17abeeb7b4c5e18f930ae62ca883cb1e87892e83bdadac6c077622835c65525c0b8bc0418258ed931d4ae306a9e1d9e78b615c0b30378b647cf53ebc9cfcc5cc39d964fdb2c9f129007ebc14e0f7ec6c02e954dfb3be13c941a335e4bc41a877cad4c1849b71d787c5d5f855cef787dedf2c4b3a3009e5dc0e3e37c79f23373bdefb67cda61f994803c78edecf6e0670cec52d9b4bf1bce43a931e3f54eac71c8d7ca8491743b81c7d7f555c8f58ed7d71e4f3cbb0ae0d9033c3ece97273f33d7fb5ecba75d964f09c883d7ce5e0f7ec6c02e954dfb7be13c941a335eefc41a877cad4c1849b71b783cd4bb82bf73ec71c471790930ae2a014689a3c49113a3c4f1de89a3300aa3300ae39bc1580a6db8dc670a7f3680dfc5dba2e7a9c7ef6df9f0b4018f8fef769efccc3c1bd867f9b4c7f2290179b01eecf3e0670cec52d9b4bf0fce83300bb38b19db2c628d43be56268ca4db0b3c1eaeef82dbfe36471c57f8654c759551f3ec8f9ca73e89f5251f9efdc0e3a34ef9f133dbf61fb07c6ab37c4a401ebcbe0f78f0330676a96cda3f00e7a110e65525c82c71963887314b9c25ce61cc1267897318b3c459e21cc62c71963887314b9c25ce61cc1267897318b3c459e21cc62c71963887314b9c25ce61cc1267897318b3c459e21cc62c71963887314b9c25ce61cc1267897318b3c459e21cc62c71963887314b9c25ce61cc1267897318b3c459e21cc62c71ee1a33ce7127d638e46b65c248ba7dc0b3df034fa1f3f0f73be2b8c22f63aaab8c9ae760f43cf5585ff2e139083c3eea94273f33bf153864f9b4dff2290179b04d3ae4c1cf18d8a5b269ff109c874298579520b3c4b96bccd866116b1cf2b5326124dd01e0f1707d17dcf61f74c471855fc654571935cfe1e879eab1bee4c37318787cd4294f7e66dafe23964f072d9f129007dba4231efc8c815d2a9bf68fc0791066617631639b45ac71c8d7ca8491748780c7c3f55d70db7fd811c7157e19535d65d43c2f46ce934a627dc987e745e0f151a7fcf8996dfb8f5a3e1db67c4a401ebcbe8f7af0330676a96cda3f0ae7a110e65525c82c71963887314b9c25ce61cc1267897318b3c459e21cc62c71963887314b9c25ce61cc1267897318b3c459e21cc62c71963887314b9cef9d38e31803b1c6215f2b1346d21d011e0fcfe30b1eab79d111c7157e19535d65d43cc722e7a94b627dc987e718f0f8a8537efccc8ed51cb77c7ad1f2290179b04d3aeec1cf18d8a5b269ff389c87bb9d795509324bdd280eb3d40d610e6396ba21cc61cc523784398c59ea863087314bdd10e63066a91bc21cc62c754398c398a56e087318b3d40d610e6396ba21cc61cc523784398c59ea863087314bdd10e63066a91bc21cc6cca16ee01c1d628d43be56268ca43b0a3cc73cf0143a8fe898238e2bfc32a6bacaa879daa3e7a9c7fa920f4f3bf0f8a8539efccccc753a61f974ccf2290179b04d3ae1c1cf18d8a5b2699fec09b3308731639b45ac71c8d7ca849174c781a7dd034fa1ed6a3b30bada7e0f8ca9ae326a9e93d1f3d4637dc987e724f0f8a8539efcccb4fda72c9fda2d9f129007afef531efc8c815d2a9bf64fc1791066617631639bd56e3ee390af950923e94e008f87ebbbe0b6ffa4238e2bfc32a6bacaa8794e47cf538ff5251f9ed3c0e3a34e79f233d3f69fb17c3a69f994803c787d9ff1e0670cec52d9b47f06ce83300bb38b19db2c628d43be56268ca43b053c1eaeef82dbfed38e38ae2801c6e525c0b8aa04183dc731d55546cd73d613cfe90278ce028f8ff6c3939f99fbfc39cba7d3964f09c883f5e09c073f636097caa6fd73701e4a8d19af25628d43be56268ca43b033cbeaeaf42ae77bcbe5ef2c473b6009e9780c7c7f9f2e467e67a3f6ff974d6f2290179f0da39efc1cf18d8a5b269ff3c9c875263c6eb9d58e390af950923e9ce018fafebab90eb1dafaf0b9e785e2a80e702f0f8385f9efccc5cef172d9f5eb27c4a401ebc762e7af0330676a96cdabf08e7a1d498f17a27d638e46b65c248baf3c0e3a1de15fc9de382238ecb4b80715509304a1c258e9c18258ef74e1c85511885b130c6ad25c028e75a18b932b67a608c197bc843fbad45b05d65d9ae2aa2ed6acb7675116d4bcc25e6127389b9c45c627ea7b625e6127389b9c45c622e31bf53db127389b9c45c622e319798dfa96d89b9c45c622e3197984bccefd4b6c45c626edbf630dfb4e0f9dc1781e782875878f233a9cbbd64ca7a23c2f8e9585db662d56ac52a01792e41fc2e7b889f6bce35ed93bd4299473060f6643bd55b95d10bfc271babac7868fb573cf91ed6e65d2982edb036af18b6c3dabc62d896984bcc25e6f76ecc315d1174fe0d922ee3aa497733fb947f2b1c47793e5199fdac0ae47cfab02dd790c45c622e317f33628e71995f049ec0e20972f0a499f14c61c653cf8c6702339e31cc789a99f1ac61c6b394194f39339e05cc786631e329c6f3ac4278a632e36960c6b39019cf6c663cd398f13432e319c58c27c98c6704339e16663c6b99f12c63c6b38819cf1c663cd399f16c66c63389194f2d339e91cc782a99f12498f12c66c6339719cf0c663c1399f13431e34931e359c78c6725339edecc78aa98f1cc63c6338e19cf4c663c9399f1d431e3e9c38ca79a19cf68663c4b98f18c67c61363c0130f3acf018fc3ff2f82aecc3ab6879293033afe7fcde8cbe098eb265dee28fb1ae8686ed575c7b118a76be04bdaa49377b665e284b6d2b04ff62a81e33a139ef1cc789630e319cd8ca79a194f1f663c75cc782633e399c98c671c339e79cc78aa98f1f466c6b39219cf3a663c29663c4dcc782632e399c18c672e339ec5cc7812cc782a99f18c64c653cb8c6712339ecdcc78a633e399c38c6711339e65cc78d632e36961c63382194f9219cf28663c8dcc78a631e399cd8c6721339e06663c5399f15c64c6338b19cf02663ce5cc789632e359c38ca79919cf18663c1398f1d433e399c28c27cd8c67be83c7d7bac334de4e65d3fe4526b63d9c87cc7be16e78f2e9a629abbb2997f8c95e05e499600662f4f8101e4b5cf6fc08ecdbdc84185df5e44bd8bb21ae16c176d8bb218a61bbdab25d5d44db12f3f098df8cde760ae71cd116b3f6d390c6ebcec75c2d4f7eded6e645fd2ecc5b56acae5ab14a409e1b10bf5b1ee2e76a47699fec15ca3c820133d68b9a20da7af172f43efde61d9b14d797adf8a25faf788a69585bfa4a116c87b5a5c5b01dd69616c3b6c45c622e31bfb763fe36938eb09f91441bfa3b14dd3fde0676df6ed2b108edeab25e3565d13b4189e3edc04379b6c2773aa97f72cddf0b31b7d3f48c027fc7efeb1952d83929c6f3abb073520cdb61e7a418b625e6e1317f8707dbf1e0f6b512f496eb19c53b80e7550f3c9efcccdc6b5fb37cba68f994803cd8f6bde6c1cf18d8a5b269ff35e0a10ddf13eba31ee473ce91e716339e34339e29cc78ea99f14c60c63386194f33339e35cc789632e32967c6b38019cf2c663c5399f13430e359c88c6736339e69cc781a99f18c62c69364c63382194f0b339eb5cc789631e3798519cf22663c7398f14c67c6b39919cf24663cb5cc782a99f12498f12c66c6339719cf0c663c1399f13431e34931e359c78c6725339edecc78aa98f1cc63c6338e19cf4c663c9399f1d431e3e9c38ca79a19cf68663c4b98f18c67c61363c013f69e58faff2dd0d11839be3bf69d26fd2ae8ca1c3668ace635d055983495a1df3b7b7940e7b2314ebee605a0ad34ec933d7c4fec3b99f08c67c6b38419cf68663cd5cc78fa30e3a963c6339919cf4c663ce398f1cc63c653c58ca737339e95cc78d631e34931e36962c6339119cf0c663c7399f12c66c69360c653c98ca79619cf24663c9b99f14c67c6338719cf22663caf30e359c68c672d339e16663c2398f12499f18c62c6d3c88c671a339ed9cc781632e36960c6339519cf2c663c0b98f19433e359ca8c670d339e66663c6398f14c60c653cf8c670a339e34339e5bcc78e63b787cbd9f2eec9d0fb78a603bec9d0fc5b01df6ce8762d8969887c7dcc3bb6e32ef02c5f742eacd9eeb9286b4e7dff7d4c783dbdfabf3db78f0bd1f3eda254f7e66de41f92e5356cf08cbd5b17a77d0b1e972299e38bf8af220c3bbe198887872be4f84ec09b3308731e33b6989d535f7eecd6624dd6bc0e3a3ddd0be8f336551f9fa1d7d893e1d763dbce7bd5ec7c17ecf3b71b8def3beb97f075bb561ab0c3abf0b17d7bac773e97b2d022adbb51601f9836b11f8baefdfb0786e3862f166dabeeec176a17d8eeb0e9e28dfb3896d0cdaf2f1de77edfbb5207fdf5defa18fd0f7da04f0a02d0fef79cfb45d341f97cad7edc3c83e5e635e8fd73db55de32d9f2b20cf1c68bbc6e668bbca828e6b06df535e16747ef7fb1b466f975113c8f7291fb6e53b2ccf987be89b14fc1d16d76388be9f91cab473370ae0b9063c3eeeb79efa53494ff7a4cc77d82b56ac6e58b14a401ecff7ad4cddbe66f1d03ed91366611666611666611666611666611666611666611666611666611666611666fecc381e4cac386e7b8b0923e970ccdac7737eedfb04531695afc746bfd0a7c36ef4e316a924ce51a071db0996cf1590a74fbf0eb6afc0b8ad3daf21ec5cfa5ae73dec5c92bdcaa0f33c149fe3746173608a31465888ed9ac86ca736f839bfa964ef20bbe6f70deb9cde729c4f1f6d05ce9fa22dd758e315e0f130165beb6bee88f6e9b2e5d375cba704e4c1752c2e7bf0d3755fa3fdcbc0431bae93e7eb9e11583c81233eb49531e34933e3e9c98c670a339e7a663c1398f13cca8c670c339e66663c4398f1ac61c6b39419cf00663cf733e3e9c58ca79c19cf02663cb398f14c65c6d3c08ce731663c4399f13cc48c672c339ebecc78ee63c6b390194f05339ed9cc78a631e36964c6338a194f9219cf08663c2dcc786a98f1ac65c6339019cf32663c0f30e38933e359c48ca71b339e39cc78a633e3d9cc8c6712339e5a663c2399f10c63c6f330331edfe3e885f23cc88ca792194f8219cf62663cdd99f1cc65c63383194f13339e89cc7852cc788633e359c78c6710339e95cc78fa31e3e9cd8ca78a194f0f663cf398f18c63c6339319cf64663c75cc781e61c6339819cf4d663cfd99f12c61c6339a194f1f663cd5cc78c633e38931e089079d7feb1187ff5f07dd6593c6dfb39539caa3797a945ff7ab5e1ed0b9ec3247d9571c0c18a74be04bdaa49377b6ddf63b8c982997f6c95e25705c61c2339e194f35339e3ecc784633e359c28ca73f339e9bcc780633e37984194f1d339ec9cc786632e319c78c671e339e1ecc78aa98f1f466c6d38f19cf4a663c8398f1ac63c6339c194f8a19cf44663c4dcc786630e399cb8ca73b339ec5cc7812cc782a99f13cc88ce71a339e8799f10c63c63392194f2d339e49cc783633e399ce8c670e339e6ecc781631e38933e3798019cf32663c0399f1ac65c653c38ca78519cf08663c49663ca398f13432e399c68c6736339e0a663c0b99f1dcc78ca72f339eb1cc781e62c6339419cf63cc781a98f14c65c6338b19cf02663ce5cc787a31e3b99f19cf00663c4b99f1ac61c63384194f33339e31cc781e65c63381194f3d339e29cc787a32e34933e32963c633dfe2c1ffebeff634be7a1974f4ffff6b3a0755c68fcb96bd08fc4886adfde02b66b8a51d31095bfb81034f9a194f4f663c5398f1d433e399c08ce751663c6398f13433e319c28c670d339ea5cc780630e3b99f194f2f663ce5cc781630e399c58c672a339e06663c8f31e319ca8ce721663c6399f1f465c6731f339e85cc782a98f1cc66c6338d194f23339e51cc7892cc785a98f1d430e359cb8c6720339e65cc781e60c61367c6b388194f37663c7398f14c67c6b39919cf24663cb5cc784632e319c68ce761663cd798f13cc88ca792194f8219cf62663cdd99f1cc65c63383194f13339e89cc7852cc788633e359c78c6710339e95cc78fa31e3e9cd8ca78a194f0f663cf398f18c63c6339319cf64663c75cc781e61c6339819cf4d663cfd99f12c61c6339a194f1f663cd5cc78c633e38931e0095b6b81fe5f0eba8b267d1374174cfa1ae8ce9bf465d0bde4d0953958c8de45d0d13c850ba0a3b18df3a0a3e721644bf7e75e1bd099b5cce153b983f582c3a78b8e63f13cd231e920daf388b6d2b04ff62a81e322139ef1cc78aa99f1f461c6339a19cf12663cfd99f1dc64c6339819cf23cc78ea98f14c66c6339319cf38663cf398f1f460c653c58ca737339e7ecc785632e319c48c671d339ee1cc7852cc782632e36962c6338319cf5c663cdd99f12c66c69360c653c98ce741663cd798f13ccc8c6718339e91cc786a99f14c62c6b39919cf74663c7398f17463c6b388194f9c19cf03cc789631e319c88c672d339e1a663c2dcc7892cc784631e36964c6338d19cf6c663c15cc781632e3b98f194f5f663c6399f13cc48c6728339ec798f13430e399ca8c6716339e05cc78ca99f1f462c6733f339e01cc789632e359c38c6708339e66663c6398f13cca8c6702339e7a663c5398f1f464c69366c653c68c67bec583639849d051ba1674944e818ed275a0a3743de828dd003a4a37828ed2934047e926d0517a32e8284dd7483ce8f0bd18efe1275b5436ed5f02469acfecbaa6a702f7254ba7b9cf79e2be6471d3fe396074f9426cd380fb9ca5d3dc673d719fb3b869ff2c30ba7c21b6e9a0a3f40cd0517a26e866823dd2517a16e8283d1b74949e033a4acf051da5e7818ed2f34147e905a0a3f442d0517a11e828bd1874945e023a4a2f359ffa1c9fb574fa1c9f31e97410ed39265b5436ed9f0146d77927b665c07dc6d269eed39eb8cf58dcb47f1a185dbe10db4ae03e6de934f7294fdca72d6eda3f058c2e5f886d0d709fb2749afba427ee531637ed9f0446972fc4b616b84f5a3acd7dc213f7498b9bf64f00a3cb17625b07dc272c9de66ef7c47dc2e2a6fd766074f9426ccdc0dd6ee934f7714fdced1637ed1f0746972fc4d602dcc72d9de63ee689fbb8c54dfbc780b1dde10bb1e17b17377b62bc6931de2ca2edb0be57316c87f59f8a613bac0f540cdb61f7e662d80ebbbf16c376d83db218b6c3ee73c5b01d76af2a86edb0fb4d316cb75bb6db8b685baeb1e25f636f669b7aaf5e636f66bbd66ed96e2fa26de933499fa958b6a5cf247da662d96eb76cb717d1b6b4a9e16daa87e713a938d8a02d66eda7217d0c787c3ce7f1e46752977bd494f54684e5ea58bd68c56ab315ab04e4390af17bd143fc626097caa67db2578acc582f62d1d94ec6c106be23ee08950fbac3265d0bba43269d02dd4193ae03dd0193ae07dd7e936e00dd3e935e0cba36935e02babd267d0e747b4c1ac77b769bf459d0ed32691c5fd969d26740b7c3a4713c63bb499f06dd3693c6f183ad267d0a74ad268dcfebb798f449d0bd60d2f87c7c93499f00dd46936e06dd06936e07dd7a93de0cbae74dfa38e89e33e9a3a07bab493782ee59939e04bab7987413e89e31e9c9a07bdaa4f11d85ab4d1ac7be5799f405d03d65d238d6fca4495f02dd0a93c6b1dde5263d1d744f98f40cd03d6ed23341f7b249a741f78a49cf02dddb4c7a36e85e35e939a07bbb49cf05dd3b4c7a1ee85e33e9f9a07ba7492f00ddbb4c7a21e8de6dd28b40f71e93c67180f79af431d09599f48ba0a3b9a7474047bfa7380c3afa0de521d0d17b130e82ae87491f001dcdc7d90f3a9a63ba0f74f799741be8e226bd17749526bd0774f48e82dda0a3f700ed021dbdab6827e8e87d803b4047ef2cdc0e3a9a87ba0d74f45b86ada0a3df2fb6828ede11b00574f45ea0174047efbadb043a9a6fba1174f41b810da0a3df05ae071dfdf6fe79d0d1fb769e031dbd43eeada0a37993cf828e7e0bf016d0d598f433a01b66d24f836eb849af061dbd2b6e15e868fedf53a0a339ff4f826e8449af00dd48935e0eba5126fd04e8e89d8b8f838ee641be0cbab126fd0ae8c699f4db4047efdc7c1574346ff0eda0a377d5bc0374742f7e0d74742f7e27e8e85efc2ed0d1bdf8dda0a37bf17b4047f7e2f79a4f7dfde9ebf2bad94f07d1f57bb4bd1bc1ed5baebe3731204f947dd904f0a0adab91fb9ecaf49ba9bf5566caa57a70156c5f8edc76b6cf7ec594d5cd947bd9b25d017986f4eb383797e0ff69f0818ec33c5436ed4f80632f596557197faf78f2f7b2c544dc578089f20cefd791f7b326dd138e89902df3fd93ea5a0031c42d0d695c232dfa58a532df07ae15c0730578a2bf4eb2df877dd409bcb6a2fe3e6c3fcbb0eb5a02f25c86f8f99adb79c5e2a17db227ccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccfc99350f8d27e07c1eca779d0923e970accbc7737e1c4bc531af8fc0b88eeff1bdeea6dc8996cf1590e7ffc098d3c74cba12fe4fe72dec5c7a1827cc792ec95e25f88363413ec68b63608bcabeea880507db3591d94e6df0737e53c9de41767cff9a754eaf5be713c7c5f11afa2cd4533ae696f98c437c6e417c3c5ce339cf0dd9c36be92ae8287d03187dc41aef25d41e4c30fb640fc7c5bf6c8d8b47df56a7923edb8d8ba62c7bbc1d7da53cdf80b6ef9b268d7343ae43593f73fc9fb65ce3d4143fedf3f9e87dce9cdf974c59747ecf3b6c9f03d6886cd7a2ed9811b243fa0a48ff14e673d8bf27a25813bbbe46680e26b2dbc7ddb08e4b409e0b0effd341b4fe9fb778ce5bccbaee7c1bead9cfe0feefab4dba1012a3091023ca83fd200ff34c9c6d2471903d9d87ce7f0f2b0ff65928cfafa18dd2be503b4f7ee2dc16bc075cf4e4df75cb3fda277bd837be028cb68fba7e7ca14f07efbd3effebbf3ccefffa2fa843384f2bb0ca9f08e513578f20fcde427962fd3bcaf739bfec9ae533b15c01a6dfe4e9df91779a4917d2d77fb3beb785f5f57dbc13301edcfedd5b6fb9eeef788ff1d1be78f233e9ba775db27c4a409e11e0a7877e4ccedf019e07dbbede034936a80f75d98a4505e4e90fd776ae38e277d52b45f125e5ec0f4e74f84279065bedd44b1e987c9e37ec67e972af3a7ca53cc3a1fd7bd4a4e3709eb02dad73fc9fb65ced01c54ffbece1fd7e99f34bbf01a3f37bc661fb14b04664fbb6dfa4537f9fec90be02d2a9fe1d79eddf9353acf13d7ef45b3964b78fbb6c1d97803c671dfea78368fd0f7b1f00d9d3756724d433aa473edbcdb321319a0831a23cf86c85eeed943fecbeef637e75aefbfe5560b4db4decbbf864bb66b1d9cf505dfd41ca43c7627f7016b4b371475effcf86b37d9b42e6fc7b7e465e1fb3e299063be3414ff593e24cffc33e2ee55962ddcf7cf5592f5bdce4078ee15cb4b82f5971c56751cb81db756dba9e757aea73d6635fccee0f5d0476cab3daea0fd9fdb89b0e5fecfb7459d0f9bbe01b565ebc26731d67a7af5bc7e03303d73359fcadcb0560499b74f24eb6da641299ca1cb148049dbf93b99e33d07580758ecab2af153ab602f26cb4da243b6fe65ed6a7233e741ef159bbab4efa7a8e14f69c85ec6946d7efe8a26fbbeecddf2bf58cacdcc9eb4b718cbba7958ec676aa05ef15b96271d1c1e3eb9966582c2e3a6c47178bc60daefb872b16171c3cbebe6386c5e282c37684b1d8e47ab6e08ac579078fafef1a61b138efb01d5d2c26ddf65c23572c5e72f044ff4c23772c704cac10e60b0c987b5ae9686cd7af778dddb96271cec1e36bec2e2c16e71cb6a38b456da3eb3bbb2b16671d3cbed605098bc55987ede862d134d9f54cc5158b330e1e5feb6784c5e28cc37684f562233e5fcb158bd30e1e5f6b7284c5e2b4c37684fdc3c65ccf0c3116a71c3cbe9efd85c5e294c37684b168d6b64fe6118b930e9e93458ec54987ede862b1be41db3e91472c4e38784e143916271cb6a38b457393b6dd9e472cda1d3ced458e45bbc37684dfa132f5e2781eb138eee0f1b56e4a582c8e3b6c47178b964c5feb581eb138e6e0f1b5164b582c8e396c47178b64e69e7a348f581c75f01c2d722c8e3a6c47582f32df275fcc2316c57cff68582c5e74d88ef03e92a91747f288c51107cf9122c7e288c37674b1d89479fe74388f581c76f01c2e722c0e3b6c47f8cc25532f0ee5118b430e9e43458ec52187ede8625197b9a71ecc2316071d3c078b1c8b830edbd1c56263664cec401eb138e0e03950e4581c70d88eb0df99692ff6e7118bfd0e9efd458ec57e87ed08fb9d99e717fbf288c53e07cfbe22c7629fc376846d67a6dfd996472cda1c3c6d458e459bc37684fdce4c2cf6e6118bbd0e9ebd458ec55e87ed08fb9d99fbc89e3c62b1c7c1b3a7c8b1d8e3b01d61bdc8b49dbbf388c56e07cfee22c762b7c37684cfb5326de7ae3c62b1cbc1b3abc8b1d8e5b01de1f791cc33be9d79c462a78367679163b1d3613bc2b1a24c1f7c471eb1d8e1e0d951e458ec00db3ee699602c682ed6382b161590e701f332769a8b1516472a03e795a12fdb23f7253baf6c5b882fdbc117ca33107ce909fa28993cf99aa9335b4d593437fd86c357ca33744047de61261d87737213ca4a3afe4f5bae3948143fedf396e87dced4d5174c59747eb7386c6f02d6886cd7a26d9a9b4e76485f01e989033af2523e8a07c59ad8f535426b2520bb7ddc0eebb804e46975f89f0ea2f57f8bc5b3c562cefcee01ea19d5233f6d5796a9352446e320469407e7ecddf0c463cf21240eb2a7f3d0f9ef61e5c1399494a709da289c574a7ec683cef326b57f5b3df917b68e1bd94b80ee0a30da3eeafa9180b99fb5c41874e8686d075c83a9d1d2695f2779f2956c51d9b43f091869ad89c6e233a6f2656cb01835cf640f318b835dda72dd2f26034f93071e4f7e66ee43532c9f26593e25200ffeb6718a073f636097caa6fd2960dbc739c758d03d7994158b0ac8b3daea3f86c591cad0f5b7d1e18baf3836583c0d0edbd33dc791caa636717a116c4fb56cd75bb6f5b58d754c6fb9aeeda9c03ccd03b32e7746f4e566ae6d5a238dea33d9a9079fd21083a87c42db31ab6cd257407afb80ce0c140fba7712bbbe8eb0ee841d37d93a2e0179a63bfc4f47ecff0c8b07cfb1de74bf613df42b3d5c0f993a30dde2a0fd7a88dd8c90d84d87d8519e46d0511f670ae8a8af806b0ad2ffb11fd110bdbfceb687f61b809174b84e618383b13e7ac654aeb6b91e1849370d78a67a8ad9348b6794151fbc2ff7b0f2d0b11590a71dee8d71475e5df7ab621d7ed1da8511aef3936957bb7b8817aeab18407c022b86b41143cfa063edc52879ee0b606dc5b69d7b9a376f7c726376e891d02a2c4cfc8c39dc28031da6cb1dba20b87d09c90ad0d11292dd405766850597aea4fcb4a49d8f70613ca8ec0a8bb327b044691b97dfa42d57d5e9013c3eaab2ae3a95a62c53759edeb3a56d23d68f6e166757ea8efe5f798e7c6165513da8f0e03b3251d9b44ff6747c1226bdab79c3d6597b36efdbbe7147db5e84b52f2e4cc7ac20d89fae63b092e0c544e574b382d32bfae0d4e3c56bf305602f0096c0f0f48c9e27535169cdd60dcddbb62ddfb77edb960df3f7edd8d0b665e70e8c680f2b7261d1b62f79bdb99a3acc6be7efeed0d91bae90db0374b4426e4fd091fd5ea0238efbe07ff699f0724d8c80f2a91aebff551887bb1b87a80ad26d48b727fa9ae91d646ffffac95875903d7d7a895dbda4ae5e4257bfc141ffaa5af714f412b87ac95bbdc4ad5ed2562f61ab97acd54bd4d604d925688707d925661f0d3a9690d5db6780572f19abbb1a7a4958bd04ecd820fbb86e7c907db5997e9584eeb2eaafa3ba9ba7bf5ae82e97ee6ae96eadfecaae1fdfe86e8cee22eaee8feeb2e86eb0eefece34b19e15649790d64b46cf0db24b42cf0fb24b3e2f0cb24b3a2f0eb2cba12f0db24bd33e116497335f1e6497b9d5cbdfea6571f5d2e57ac95cbd94ae5e62572f51ae97dfd5cbf2ea65c8f592bd7a295fbdd4b85ee6f7f920bb9cf8fa20bb64704b905d4e583fbad6cb87ebc7f6fa71b67e54ac1f65eae1043d8ca21fb3eae13f3d1caa8787f570b99e3ea0a753e8e9257aba8d9e7ea4a763e9e9697aba9e9ebea8a773eae9ad7abaaf9efedc1e64a7c79f0cb23f9fd03f27d13fafd13f37d23fbf7a29c8fea450ff444fffe454ff04f772907d84aa7fcead87d5f4a353fd18593f5ed58f7af532bd7a595ebd0caf5e76572fb3ab97d5d5cbe8ea6573f532b97a595cbd0cee7b95fc8e92df55f23e25bfa7e4fd4a7e5fc91f28f943257fa4e4034afe58c907957c48c99f28f953257fa6e4cf957c58c947947c54c95f28f94b251f53f2574a3eaee4134afe5ac9df28f95b257fa7e4934afe5ec93f28f994924f07d9faf75925ffa8e49f94fcb3927f51f239259f57f205255f54f225255f56f215255f55f235255f57f20d25ffaae49b4afe4dc9b7947c5bc97794bcaee4bb4abea7e4fb4a7ea0e4874a7ea4e4c74a7ea2e4a74a7ea6e4e74a7ea1e4974a7e15742c038d8dc5ff373bc3cc7e735bdbc6edbbda6ada76d66cdfb7ad6dcbae6d876a0e6c697ba166e7fe8d7b366ddb79000ffea0699e68bdea597bf6341faad9b2a365e3c19a9dfbda6a766eaa59bf73df8e96db6e8e9f33070dea6cb1b9a525dcd877caee80f4fb5d34fa6b731cad04be28b76fffab2b01f97f5d39686079d71cfab8e9dcd1d7aea7b27dbc9abddb76b6d5246b76a8bfea66baf3c0c6960935f8bfbd2ac87bdb6af6b635ef69abd9b467e7f69ada0958eef8de5d70a2b5b71f98c1e65d405daa2a5fead7054ffe47bfae9d8effbc13525a4fbe50a3fdfa77c1c3415d3928dd45c2c5fd43c3b277dffab63dcd1bdac20f5e762707afea8a9b2d5d74b3ef802e187ba82b074d1ad035c2555d3176bc0063c17f03d9f72ad92c9304009b2d6c6f00000023571f8b08000000000000ffed9d79741cc5b5c67b6459963d1acbf2be5bac5e4648a319c9b6b08d65b3181bb3790163360b5b3606db32b60c983d648310080961c90664634908d94312b2ef2464812c2404b213c8bf39efe49d774e4edebb3553f7e853b96bdeb4dc35ae96ef9c7335d557357d7ff7ebdb353dd5dd33a9a0f478832ca5db23c88e0d0e7df0ffbbf573eef01eed31ae2be792339510ce9a84708e4808676d4238472684b32e219ca312c2599f10ced131722ab69a60f0236ede310e748d9b319d304d1b12a06926619a8e4d80a68d4132c6a87109e16c4a08e7f884704e4808e7c484704e4a08e7e484704e4908e7d484704e4b08e7f48470ce4808e7cc8470ce4a08e7ec8470ce4908677342388f4908e7b109e13c2e219cc7c7c8390f384fd0cf27eae7b9fa99fbccd7cf0bf473563fb7e81c6bf5f24964ad646d8acff89f3ad190272b9075e8ff35ebff75922d245b44b698ac8bec64b225644bc996919d42b65ce7bf826c25d9a964a7919d4e7606d92ab233c95693ad213b8b6c2dd9d964e7909d4b761ed9f964ebc8d6936d305836925d407621d926b28bc836935d4c7609d9a56497915d4eb685ac87ec0ab2ad64dbc87ac9b693ed20bb926c27d955645793ed22db4db687ac8f6c2fd93564fbc8f693f51b9a1d20bb96ec3ab2eb0dce83643790dd487613d9cd64b790dd4a761bd99bc86e277b33d95bc8de4af636b2b793dd417627d93bc8ee227b27d9dd64f790bd8bec5eb27793bd87ec3eb2f792dd4ff600d983640f69162ef6f791bd9fec03641f24fb10d9c3648f903d4af661b28f907d94ec63641f277b8cec71b227c89e24fb04d927c99e22fb14d9d3649f26fb0cd967c93e47f679b22f907d91ec4b64cf907d99ec2b645f257b96ec6b645f27fb06d937c9be45f66db2ef907d97ec7b64df27fb01d90fc97e6468fe1cd98fc97e42f6bcfe1fcf21fd94ec67bafd73fdfc0bfdfc827e7ed178cd2fc97e65f87e4df61bc3f712d96f75fb77faf965fdfc7bfdfc8a7e7e553fff413fff513fff493fff593fff453fff553fff4d3fbfa69fffae9f5fd7cfeafc63617ca95d1f0c3cba8398c69d8ede2e75fe81c53e2118fc505a8cd0ffe3e766edafd5cbfcccda8dd4cb230d7f9d5eae33d653af97eb0d7f935e6e32fc13f4f204c33f492f4f32fc53f4f214f0a7039887d47ee51ba15d29f0711dd6806f64305813e5abe3d5816f5430580be5e3ed5807bed1da370a7c63b4af1e7c69ed1bcd9a9135685f7710574de47ad47a3371af579f9b191b3fef56b5de4647bce3e2e7ed55eb6d72c0abea430f17c138a89b09dad704be89da371e7c93b46f02f8266bdf44f04dd1be49e09baa7d93c1374dfba6806fbaf64d05df0ced9b06be99da371d7cb3b46f06f8666bdf4cf0cdd1be59e06bd6bed9e03b46fbe680ef58ed6b06df71da770cf88ed7be63c1c7e3e771e0e363b8e3b54f8d09ff0ae035da5f03be1379cc05df5c1e6fc1378fc75af0cde771167c0b2036fbb23086b0af45fb783c52ff5ba8dbdd415cf59fdfa6d6bb28eef5d29ad57abbe25f6ff1bcd5c9c180aedd10671168b544b763bc36a61d63a7b4711cf6d7427b15f4e57eac07bfa730bb7aef58acdb4bcabc6ea1f1ba0cf4591c927f77106ffe5d064f97c1acea7f2970c45fb38576a9d98a1f916b7623f4356b8f8f6f8663cdae010e0735dbe9a666f339a9d9d2fc421084d71e1fe30ec79add041cf1d76ca7d46ce58fc8357b0df4356b8f3fe70cc79add0e1cf1d7eca24e3936a8f811b9666f85be66edf167dde158b3fdc0e1a066bb649cadf811b966ef86be66edf1bccb70acd9db8123fe9aed7254b305a9d9a074ae2808c26b8fe7008763cdde0b1cf1d7ecd62e3936a8f811b9669f84be66edf17cf470acd98781c341cdba9a9fcd4bcd96ce91074178edf1b991e158b34fe9b63acff0737d9e6126f87ea17db3c0f782f6cd06df8bda3707f28a7f1fd856907da0e247e47de039e86bd672b36e0fc77de01bc0e1a0663ba5662b7e44aed997a0af597bc7eaf670acd9e781c341cd2e929aadf811b9665f83be66edf1f50bc3b1665fd66d75bcf03b7dbc7022f85ed6beb9e0fbbdf6cd03df2bda371f7caf6adf02f0fd41fbb2e0fba3f6b580ef4fda7712f8feac7dade0fb8bf6b581efafda9703dfdfb4af1d7caf695f1e7c7fd7be02f85ed7be0ef0bda17d9ddaa7ce09f0f529dfd3be7ac8a93b886fdb16af4909063f52c67237b45bdcf2e432c1e0ebaa39566bfcb10a2af79382ca736f059e3607b9a72146253c6dc0938b9fa778ed457bfceb2d6ee3930c4dd310eb24c82bef20af14c4e275f332c7cb800fc7837c0863217ec67c0a62f1ba79b9008cecc3f189c757de7fd4d83c3635c0eb605f2abe3f63bc6ee0e078b5d0e785a681bee3355b03fc9fc7800668e3f89d337c8e6ab51dafefe775f3723b30728eb9ea33e62b656c3318eb812d469ea2666d064f5b8816476b6c07637571ffe318bcfff1bec4f16aa1cfffd40cf43d31e5942d1ff57d16eb33fef13f9fc37db3129e3cf0b818631cbdcfe5f0bde93f41bcb5d661689533b4ca409f02e8d7e140bf72ef951c4f98855998855998855998855998855998855998855998855998855998855998fd67c6f3c778be2decdcec9164645f3bf0b898e72f7e27895e17af5f9dd77906ceebc47fde229fc3f38e7c4dd63c23e75ae8f35c6a80edd99073be787eb7d5f039bae6a2b82df19a8b6e58e678780e1aaf0171750e316bf06443b4f02176736cb1f35bdd6cdf7c4e7d2780fa5e9d16639b865d7fb2c0f0a93afd77cd40de2ecefd453d17896309b7e33cb797090ebd76c0cd352ea5f183c7ab9a60f0f881ef339db1c71e7c0e93cf97771ab16ba1cf4ba9816db310fedf1d1c7a5d0ef6e175f3f23c78ed4263dd8deef22d7b6d42277073bbcec8ad05b8b9cf2b309edf0afb8983f7b83c5e1f16006f60e4c40f3c671fff3140e91a827c049e0ee07170bd58bba3639d1cd663dcd7102c34b40a3b86e23e9da05fecd7c3ebfdc33c0ee6658e27ccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccfe33e3fdddcc9a867eed9e3056e9ba8be2f90cfebe0d3c2fb6bb6620aeeb73807cce69be91732df479ba6680ed1add6e080ebdd6c2b62d5d9d5bb36d4b8ed700f9e0b92057f7ac170c9e4288163ec46e8e2d76e91a82f8b7efc0350479639bb61bdb13cf9de33e742bd4a9f91d1769d0a71ad72dd9b60dc7c37da9003e6ee3bdd92eb4c6f712f39a228e87e7ceefd4daf2b9f3f8c7ea7ccee5b8c1df5dc5d709e44372e53ef7c0d877af6ee3f523edb0ae4742fecf8f72e7a959bf23f13d5e18db87eff17ab866a0aff97d5cac75d4eff1ca19aff3f17bbcee833a7b04deff5d8d498b83708de68146dc078f831c5c67123a469ad756aa3ebcfd47197df09885fb3c0e6394eddad5b0ef3e72f0fd7c65bffb88e3e1b17107309a399ad7981eedd7883d03e3c542f87f7770f8d7883d033584d76905c6fae7c3fa996b54607f6fe13ecf1aefa3aef62ddb3568b86f999f079817af41e33edf82b1ea9f709c651efbe3f55ad5f86c67bb3e9ce3e1315594dc715c88fbbd11eb1159381ed6e38f8d7a5c68e16e0d79ed4f2daf65adf89a63fcec64eaa774580cafe98e4587d278d365e4c2fbd462c885fbfcd2d86fe23f662a1d7fc69febe0e3211e830a21b9729fdfc2bef6321c5ff276c2b1f21f21ffe747b9e34fd64fe5bc34fe9c8bdb77995e176fdfa521b14f01d69862b7636c3efee438ecaf85f61bf07ec2fd580fd69ad9d53ec2c770c86ebeaed3785d06fa2c09c9bf3b8837ffa506cf528359d5ceab5067ff80e34f5763f5128b46f34123ee83f744f1fb08f7b7bdc7b8b8deb7dc7b4cd8f743e2d8fe4fa7737ae16ce69c5ed8f109f7e1d7e2f1c97fc3389b0ee96bce55f27b489cd72ce33d225988fbef90b8dd31eb990906eb9931385cc66e3462375631769311bba98ab14573d1dc27cd7dfafe6ffc9eee9a04308e4800636d0218472680b12e018ca312c0589f00c6d109601c9300c634301ec9f77607fae4e3d0a701746a09e176753f7e8bc1687e5742c6e0659e23798ce4eb361cab9f7dde868dc033cc8e3563d986e3f4b3cfdbb0c9ad8eb18cf7e313c03821018c1313c03829018c9313c03825018c5313c0382d018cd313c03823018c3313c0382b018cb313c03827018ccd09603c26018cc72680f1b804301e9f00c61312c09884b9ca056e1987fcf95af138f84dc80efc8c5e098febefd6749467f1fa2cbe8e31eeef48337fd7b1c5d00aef3971fd7bb0a9c0fe5da91c4f9885d9c68c6321fe3e37f7cb7ac218f6ddc30ec68dc8ef29ad6e7906fdf676abdb6d11f9bdcaed6f8296deab8e86df040dbbbf25ecfbdeb90f8e1b47ea3a468cdd1cc4ab4547055a54e91e6c27dfd7df9640665f7e6380c7a7b0df18c87ac258a5df1888fc5e950fd1b1d52d637ea88caeee65c67aa98407bf17c3454db9c9b3fc7739733cfcfe0f1c935c5dd36fde1fc7cb957c6789300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb330fbc18ce718f0bb9cb95fd61346f37b921ccdc7473e57d319a263ab5bc6fc5019f1fbcfe2e3299dab89f23d558b80c7454db9c9b374aec6fcbecd4e2327fcbe4ddcbf5d7d07d92283879717c3761066611666611666611666611666611666611666611666611666611666611666bf99f11c03b3a6a15fd61346f62d041e17bfc714f53cc8a2101d5bdd32e687caa8781cfc865c07d64b253cf8bb1e2e6aca519e837e2b8fd7bdc8c829037d70ff3ed9419ea9c0fefb71f8bb7ac22ccc61cc3866316b1afa653d6164df62e071b07f471efbbb42746c75cb981f2aa3e289ff372c4be7e9bb22f0e06f1ab9a829377996c67ef3b792ccdfeacc401fdcbf1dfc6e56e8ef24f1f252d80e51980b0964169d45671bb3e82c3adb984567d1d9c62c3a8bce3666d15974b6318bcea2b38d5974169d6dcca2b3e86c63169d45671bb3e87cf4e88ce71898350dfdb29e30b2ef64e071301f1ff95ccd92101d5bdd32e687caa87896c5ce53c861bd54c2b30c785cd4949b3c4be76a4e31725a62e494813e38269de220cf14c4e575f3f229b01d863b732181cc521bd56196da10661bb3d48630db98a53684d9c62cb521cc3666a90d61b6314b6d08b38d596a43986dcc521bc26c6396da10661bb3d48630db98a53684d9c62cb521cc3666a90d61b6314b6d08b38dd987dac06b7498350dfdb29e30b26f29f02c73c013f53aa265213ab6ba65cc0f9551f12c8f9fa703eba5129ee5c0e3a2a61ce559bcd6a9dbc86999915306fae098d4ed20cf14c4e57563de81de0eddc22ccc21cc3866316b1afa653d6164df29c0e360ff8e3cf62f0fd1b1d52d637ea88c8a6785239ee5117856004f77fc3ced8ef22c8efd2b8d9c961b3965a00feedf2b1de49982b8bc6e5e5e09db2169ccb82f316b1afa653d61c41a631e077517794c5a11a2636b0218db12c0383a018c6312c09806c6ac03c6948e873cbc9c75ab4f3e0e7d1a40275fc7bd0cf0b8da868d064f638816be6ec3b1fad9e76dd8083caeb66193c1d314a285afdb709c7ef6791b36b9d53196f17e7c02182724807162021827258071720218a72480716a0218a72580717a02186724807166021867258071760218e7248011e7348ee4e7dc23f9f9ec487eae10cd45f3dce13d4473d15c3417cd45f34034cf1dde4334f758f3247c8610c6e1cd58f094117952f1f1e430778cb5d283dc9921698c850430babece48748c85313f5446c5739a239e9511784e039e53e3e769779467f15ac3d38d9c561a3965a00fd6c1e90ef24c415c5e372f9f0edb2169ccb82f316b1afa653d6164dfa9c0e36aff8ab2bfe3fe7586239ed322f09c013c2eb697a33c8bfbfb2a23a7d38c9c32d007f79d550ef24c415c5e372faf82ed903466dcdf99350dfdb29e30b2ef74e071b57f45d9df71ff3ad311cf191178ce041e17dbcb519ec5fd7db591d319464e19e883fbce6a0779a6202eaf9b9757c376481a33eeefcc9a867e594f18d9b70a781cd45de4cf1c6786e8d89600c64202184547d1d12746d1f1e8d1511885511885f1483026610c97f799e87303f8597c4dfc3c1df8b9ad129e35c0e3e2b39da33c8b73036719399d69e494813e58076739c833057179ddbc7c166c076116e630661cb398350dfdb29e30b26f35f038d8bf238ffd6b42746c75cb981f2aa3e2591b3b4f470eeba5129eb5c0e3a2a6dce4591afbcf36725a63e494813eb87f9fed20cf14c4e575f3f2d9b01da2301712c82c3a8bce3666d15974b6318bcea2b38d5974169d6dcca2b3e86c63169d45671bb3e82c3adb984567d1d9c62c3a8bce3666d15974b6318bcea2b38d5974169d6dcca2b3e86c63169d45671bb3e82c3adb984567d1d9c62c3a8bce3666d15974b6318bcea2b38d5974169d6dcca2f3d098150f5f77ceac69e897f584917d6701cf5a073c51afc35f1ba263ab5bc6fc501915cf39f1f37460bd54c2730ef0b8a829477916ef1538d7c869ad915306fae09874ae833c531097d7cdcbe7c27688c25c4820b3e83c34661cb398350dfdb29e30b2ef6ce071b07f471efbcf09d1b1d52d637ea88c8ae7bcf8793ab05e2ae1390f785cd494a33c8b63fff9464ee7183965a00f8e49e73bc833057179ddbc7c3e6c076116e630661cb398350dfdb29e30b2ef5ce071b07f471efbcf0bd1b1d52d637ea88c8a675dec3cf91cd64b253ceb80c7454db9c9b334f6af37723acfc829037d70ff5eef20cf14c4e575f3f27ad80e51980b0964169d45671bb3e82c3adb984567d1d9c62c3a8bce3666d15974b6318bcea2b38d5974169d6dcca2b3e86c63169d45671bb3e87cf4e88ce71898350dfdb29e30b2ef7ce071301f1ff95ccdba101d5bdd32e687caa87836c4ce53c861bd54c2b301785cd4949b3c4be76a361a39ad3372ca401f1c93363ac833057179ddbcbc11b6c370672e2490596aa33acc521bc26c6396da10661bb3d48630db98a53684d9c62cb521cc3666a90d61b6314b6d08b38d596a43986dcc521bc26c6396da10661bb3d48630db98a53684d9c62cb521cc3666a90d61b631fb501b788d0eb3a6a15fd61346f6ad079e0d0e78a25e47b42144c756b78cf9a1322a9e0be2e7e9c07aa984e702e07151538ef22c5eeb74a191d30623a70cf4c131e9420779a6202eaf9b972f84ed20ccc21cc68c6316b3a6a15fd61346f66d041e07fb77e4b1ff82101d5bdd32e687caa87836c5cfd381f55209cf26e07151538ef22c8efd1719395d60e494813eb87f5fe420cf14c4e575f3f245b01d845998c39871cc62d634f4cb7ac2c8be0b81c7c1fe1d79ecdf14a263ab5bc6fc501915cfe6f8793ab05e2ae1d90c3c2e6aca519ec5b1ff6223a74d464e19e883fbf7c50ef24c415c5e372f5f0cdb419885398c19c72c664d43bfac278cecbb08781cecdf91c7fecd213ab62680b12d018c8504303ad6313f5446c57389239ecd11782e011e17e387a33c8beff3971a396d3672ca401fac834b1de49982b8bc6e5ebe14b643d298715f62d634f4cb7ac2c8be8b81c7d5fe15657fc7fdeb32473c9744e0b90c785c6c2f477916f7f7cb8d9c2e3172ca401fdc772e7790670ae2f2ba79f972d80e4963c6fd9d59d3d02feb0923fb2e051e57fb5794fd1df7af2d8e782e8bc0b305785c6c2f477916f7f71e23a7cb8c9c32d007f79d1e0779a6202eaf9b97395e1299717f67d634f4cb7ac2c8becb81678b039ea8fbfb16600cfbcce12b6321018ca2a3e8e813a3e878f4e8288cc2288cd11857248051b6b530faca9875c098d2f1908797b35588dd68c46eac62ec2623765315638be6a2b9682e9a8be6a2f9e1c616cd4573d15c3417cd45f3c38d2d9a8be6a2b9682e9a8be6871b5b3417cd4573d15c3417cd0f37b6682e9a9bb17be28f1df97aee1ee0d9e2400b4779e6d47aafd0ebfa4f8cfa29adb61a5a650dad32d0e70ad06fab03fdc2aeb9e6658e1795f9440f981dc5ce8fa5758c86fc3946c1d043c5dfe62877db98b7ad0ab16d635e3562dbc6bc6ac416cd4573d1fce8d51cdbb5c1a1f720a975f4eaf648bdccfd57c0ebb8cf030da5e7c640b6a78bd8b20f89e6a2b9687e2434475d6aaac013183c41199ed99ef14cf58c67bc673ca33de319e119cf5ccf78e678c633cd339e099ef18cf18ca7d6339ee99ef14cf48c27ed19cf48cf78e679c633c3339ef99ef14cf28ca7c1339e8c673c759ef1ccf48c67b2673c633de369f48c6781673ca33ce3e9f18c6796673c533ce319e7194f93673cf59ef1a43ce04907875e539386fff780afc678ad1aaf268e1ff8ff76edaf81d7ecd0ed1121ebde0e3e3e57b523e4b5a8d376c8a55bb77387f728ea84b1ba6199e33500c70e4f78ea3de369f28c679c673c533ce399e5194f8f673ca33ce359e0194fa3673c633de399ec19cf4ccf78ea3ce3c978c6d3e019cf24cf78e67bc633c3339e799ef18cf48c27ed19cf44cf78a67bc653eb19cf18cf782678c633cd339e399ef1ccf58c6784673ca33de319ef19cf54cf78667bc65313c2d3e38887e72f79ddbcdce3496c07dba178dfe2958e72daa9d755a7d7cbfc1caf16fa3ca43fb8a9f9087c2d7399f3cd38d7b41334ea75948beddae5de2ac4b65dbb5c8dd8b66b97ab115b3417cd4573d15c3d62bca7be53eeb7a89c47eeb728cf23f75b94e799eb198fdc6f519e47eeb728cf23f75b94e791fb2dcaf3c8fd16e5797a3ce391fb3fcaf3c8fd1fe579e4fe8ff23c72ff47791eb9ffa33c8fdcff519e47eeb728cf23f75b94e791fb2d0ee5f9ffeeb7c0fb24f8dc542ff8aed4ed1ef0d584c4e0f5ec045fad6ef33ad4783367fca10c35f09aab42b8ae0c89c771ae0a796d3574c758ddb0ccf1f0fe8dab3ce1a9f78ca7c9339e719ef14cf18c6796673ca33ce359e0194fa3673c633de399ec19cf4ccf78ea3ce3c978c6d3e019cf24cf78e67bc633c3339e1ecf78e679c633d2339eb4673c133de399ee194fad673c633ce399e019cf34cf78e678c633d7339e119ef18cf68c67bc673c533de399ed194f4d084f8f231edb75b43d55886dbb8eb61ab16dd7d15623b6682e9a8be647b7e657c71fbb231d0cfecd36f54819cbddd0be1a785cbcdf39cab378ffdd2ebdae18ef71c829ad761b5af5185a65a0cf2ed06fb703fd521097d7cdcb1c4f9885d9c6ac62ef893f76719cc1d8ac4f60f0f0638f632d1ce5591c0ffa82708d395e06fae036ef7390670ae2f2ba79b92f24767310af167b2bd0626f08cfde2a6bc1f1a232ef4a20b30f3aabd8d7c41e3b9f4b1bb1599fc0e0e1c7358eb570936769dfda17846bccf132d007eb749f833c531097d7cdcbfb603b08b3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3dfcc2af6fed86397e6ef3136eb13183cfcd8ef580b377996e6effb83708d395e06fae036ef7790670ae2f2ba79b91fb683300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb330fbcdac621f883f76f13e1f8ccdfa04060f3f0e38d6c2519ec5f9fb6b83708d395e06fae036bfd6419e2988cbebe6e56b613b08b3308731abd8d7c51ebb743e0f63b33e81c1c38feb1c6be126cfd278707d10ae31c7cb401fdce6d73bc833057179ddbc7c3d6c8728cc7d0964169d45671bb3e82c3adb984567d1d9c62c3a8bce3666d15974b6318bcea2b38d5974169d6dcca2b3e86c63169d45671bb3e87cf4e8ac621f8c3d76a1387f8fb1599fc0e0e1c741c75ab8c9b3347f7f4310ae31c7cb401facd31b1ce49982b8bc6e5ebe01b6c37067ee4b20b3d4467598a53684d9c62cb521cc3666a90d61b6314b6d08b38d596a43986dcc521bc26c6396da10661bb3d48630db98a53684d9c62cb521cc3666a90d61b6314b6d08b38d596a43986dcc521bc26c63f6a13654ec1be38f5dbc9f1d63b33e81c1c38f1b1d6be128cfe2f52f3705e11a73bc0cf4c13abdc9419e2988cbebe6e59b603b08b3308731abd837c71f3b9f3662b33e81c1c38f9b1d6be128cfe278704b10ae31c7cb401fdce6b738c833057179ddbc7c0b6c87a431e3f64bc517bb78dd26c7a8d1cfca77ab6e8f00df6dba5d0bbe37e9f648f0ddaedb75e07bb36e8f02df5b2037f6bd55b71780ef6dbadd03beb7ebf636f0dda1db5783ef4eddde0dbe77e8f61ef0dda5db7bc1f74eddbe067c77ebf63ef0dda3dbfbc1f72eddee07dfbdba7d007cefd6ed6bc1f71eddbe0e7cf7e9f6f5e07baf6e1f04dffdba7d03f81ed0ed1bc1f7a06edf04be87747b17f8dea7dba3c1f77edd1e03be0f409b9f3fa8db0de0fb906e67c0f7b06e8f05df23badd08be47757b1cf83eacdb4de0fb886e8f07df47757b02f83ea6db13c1f771dd9e04bec7747b32f81ed7ed29e07b42b7a782ef49dd9e06be4fe8f674f07d52b76780ef29dd9e09be4fe9f62cf03daddbb3c1f769dd9e03becfe8366edfcfeaf6cde0e371e016f0f138702bf8781cb80d7c3c0ebc097c3c0edc0e3e1e07de0c3e1e07de023eaebbb7828febee6de0e3ba7b3bf8b8eeee001fd7dd9de0e3ba7b07f8b8eeee021fd7dd3bc1c7757737f8b8eeee011fd7ddbbc0c775772ff8b8eede0d3eaebbf7808febee3ef071ddbd177c5c77f7838febee01f071dd3d083eaebb87c0c775f73ef071ddbd1f7c5c77382e34ebf607c1778c6e7f087cc7eaf6c3e03b4eb71f01dff1bafd28f84ed0ed0f83ef44ddfe08f8e6eaf647c1374fb73f06bef9bafd71f0f17bd363e0cbeaf6e3e06bd1ed27c077926e3f09be56ddfe04f8da74fb93e0cbe9f653e06bd7ed4f812fafdb4f83afa0db9f065f876e7f067c9dbacde382daff1a2017ceb301b84f0ae1615f3df07407f11e33712c5e372fe78191756caf3e63be52c69cc1a8783a1c6886b5c18f729f493a80a7e080c7519ec5cf249d464e7923a70cf43911f2ec7490670ae2f2ba79b91362bbd8e6a8459d5eef5c438b5ae8f3867e4353ef7fe574e475a8fa6d0fc9c5958e39832717127bb1631d79dd3c262eae42ec8546ec3623368ee7fc28b76f2f04e6450e98d57abbe25f6f71df3e59af8beb99e3b4414e4b4083b872c2d8296d1c87fdb5d0fedfa681bedc8ff5e0f74e6657fb116f4b64375fd761bc2e037d1687e4df1dc49b7f97c1d36530abe3ffff6a1ae070b03f146b60b1c1c1cb6da05d9745bbc5a01df769071f1fe374828f8f15781d78ac84c7112df1e71b3af6f0720b30b26f2130b68430b6c7cf583cd66931185b42b465df22e059e848b34506cf5c431f7c5f1e65f4e1d7d6429ff1fa835d6330f83304f755b53f363590177f66fe4f10efb85ae7402ffc3c1f803e81a1213f98a13e18f8cc1f27cf9860e033fdfefebe7d3d3b7ad7f5f66c4b015aad8189cfa990346ac087ed1121be20183c7581539e3c7581539e35862c3865c2fdd5472995164f0ff4eeded9bf714fef9eadfb0eeeedefddb6b66f07528f34e891d4960192a28f1ff5c1c0244b7710efc98e3a2356b9e2a987e751f1f3b43bcab3f8c633dac8a9cec829037d46c2ff463bc833057179ddbc3c3a24768c0351518b311568312684674c95b5c0896af6e19ecaffc7931335462eb847634e669dc79a10073c01d69fd270ea7f6a671fa99319150c6c6c1e3dd551a5da086a8653bd6ba9194c7570a686203523a96620d58ca39a6154338a6a0651cd18aa19423523a86600d58c9f9ae153337acd4169c64ecdd0a919b9e381eb7bc0aa3e51ab774735a3a666d0d48c993aaa52effeea48441dfdaa2335f5e94d1d1da84f956a8641bdd3aaa318f50eadde55d5919a3a425347d4ea087329d932b253c8966bad5790ad243b95ec34b2d3c9ce205b457626d96ab235646791ad253b9bec1cb273c9ce233b9f6c1dd97ab20d641bc92e20bb906c13d945649bc92e26bb84ec52b2cbc82e27db1294ce4a5d41b635289d8dea25db4eb683ec4ab29d645705a5b3526ae65d9d8952679ed4d530ea6c933abba4ce26a9b347ea6c913a3ba4ce06a9b33fea6c8f3abba3cee6a8b337ea6c8d9aa95733f36a26feb6a034d3ae66d6d54cba9a395733e56a665ccd84df119466bad5ccf65d4169e65acd54ab99693513ad669ed54cb39a595633c96ae658cd14ab99613513ac667ed54caf9ad95533b96ae656cdd4aa99593513fb68509a695533ab6a2655cd9caa99523533aa66429f084a339d6a6653cd64aa994b3553a96626d54ca49a7954338d9f23fb3cd917c8be48f625b267c8be4cf615b2af923d4bf635b2af937d83ec9b64df22fb36d977c8be1b946af0fb643f20fb21d98fc89e23fb31d94fc89e27fb29d9cfc87e4ef60bb217c85e24fb25d9afc87e4df61bb297c87e4bf63bb297c97e4ff60ad9ab647f20fb23d99fc8fe4cf617b2bf92fd8dec35b2bf93bd4ef6463070c601078adfe8059efdeee9efefddbdb7bfb9bfaf79f7815dfd3bf7ee3ad87cddcefe2b9bfbaeedddb77d57df75f8e23bf4d0c453fb2bf6edeb39d8bc73cfb6deeb9bfb0ef437f76d6fbea2efc09e6dfbf1458fe917cd3c3462cfb66df6605faa390cd2af0e31e873fa757cd26475f9dc9e1f8a202f0ee545ff1a6242f7eb53514bf5f2fad2116df3fe5d7dfdcdb9e63df4b76717bda6775b6b33fe6f3f89bcbfbf797f7fcfbefee6edfbfa7637b7b7e27a1fcc0c2189d79b86f0a2a6f195671efc1f78fc6b863d5f0300", "privateFunctions": [ { "selector": { @@ -44,8 +44,8 @@ exports[`ContractClass creates a contract class from a contract compilation arti "isInternal": false } ], - "id": "0x14984eeda340fba89c656a26cd74e08be8fc849619982aa26f94077a897f56a6", + "id": "0x0f83595b23cd7c0bb0bfd8793e8d3cef253ed9b79f65eeb030776de21b1504db", "privateFunctionsRoot": "0x05fa82a96814b6294d557d507151f7ccc12f70522ec4d9d0395a90e87e8087c6", - "publicBytecodeCommitment": "0x0bf394d6e8a18153fea19434af4dba812bd80872d27c85d18c5e4ec7046172f6" + "publicBytecodeCommitment": "0x0f25b9a08d5ebc9aed312ec2d49bb8d1aaf25fe68cddd97944254875f091191a" }" `; diff --git a/yarn-project/protocol-contracts/src/gas-token/__snapshots__/index.test.ts.snap b/yarn-project/protocol-contracts/src/gas-token/__snapshots__/index.test.ts.snap index 387a8dcf251b..7ec7bd797dfa 100644 --- a/yarn-project/protocol-contracts/src/gas-token/__snapshots__/index.test.ts.snap +++ b/yarn-project/protocol-contracts/src/gas-token/__snapshots__/index.test.ts.snap @@ -2,10 +2,10 @@ exports[`GasToken returns canonical protocol contract 1`] = ` { - "address": AztecAddress<0x01ffec73ac535628f98088b70f766f47989801a0dfc754cf4996f505cfd8f082>, + "address": AztecAddress<0x297f147bc0e40c476be08162f5a97ea890e8d6396b8fbaf8f71fd95751926b5b>, "instance": { - "address": AztecAddress<0x01ffec73ac535628f98088b70f766f47989801a0dfc754cf4996f505cfd8f082>, - "contractClassId": Fr<0x2c32fd0ebccda2e20057f37fa2e6085c07d9a1236a72a54f58c724418f7b4438>, + "address": AztecAddress<0x297f147bc0e40c476be08162f5a97ea890e8d6396b8fbaf8f71fd95751926b5b>, + "contractClassId": Fr<0x233c031c6466ffbaffe911450b38aac76414bca3bd9cd6685afecf406038ac63>, "initializationHash": Fr<0x0bf6e812f14bb029f7cb9c8da8367dd97c068e788d4f21007fd97014eba8cf9f>, "portalContractAddress": EthAddress<0x0000000000000000000000000000000000000000>, "publicKeysHash": Fr<0x27b1d0839a5b23baf12a8d195b18ac288fcf401afb2f70b8a4b529ede5fa9fed>, @@ -18,7 +18,7 @@ exports[`GasToken returns canonical protocol contract 1`] = ` exports[`GasToken returns canonical protocol contract 2`] = ` { "artifactHash": Fr<0x076fb6d7493b075a880eeed90fec7c4c01e0a24d442522449e4d56c26357205f>, - "id": Fr<0x2c32fd0ebccda2e20057f37fa2e6085c07d9a1236a72a54f58c724418f7b4438>, + "id": Fr<0x233c031c6466ffbaffe911450b38aac76414bca3bd9cd6685afecf406038ac63>, "privateFunctions": [ { "isInternal": false, @@ -27,7 +27,7 @@ exports[`GasToken returns canonical protocol contract 2`] = ` }, ], "privateFunctionsRoot": Fr<0x13b29c3f4a96eb14d5d3539a6308ff9736ad5d67e3f61ffbb7da908e14980828>, - "publicBytecodeCommitment": Fr<0x1c5e1c199e3affad8f3d3ec7db3e3b40639b3c0ef82351506ceb25cde3b04924>, + "publicBytecodeCommitment": Fr<0x2fa5bdfc9fcec2dbd358a80c1db5084a5c599f4637b5fe71a506d4cb957663a6>, "version": 1, } `; From 20d58ac644c7a41355b9999bf1f677fbd423534f Mon Sep 17 00:00:00 2001 From: vezenovm Date: Tue, 12 Mar 2024 17:36:02 +0000 Subject: [PATCH 043/139] increase timeout --- .../end-to-end/src/benchmarks/bench_process_history.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/end-to-end/src/benchmarks/bench_process_history.test.ts b/yarn-project/end-to-end/src/benchmarks/bench_process_history.test.ts index 8d0747cf27f5..2de00af5b6d4 100644 --- a/yarn-project/end-to-end/src/benchmarks/bench_process_history.test.ts +++ b/yarn-project/end-to-end/src/benchmarks/bench_process_history.test.ts @@ -30,7 +30,7 @@ describe('benchmarks/process_history', () => { beforeEach(async () => { ({ context, contract, sequencer } = await benchmarkSetup({ maxTxsPerBlock: BLOCK_SIZE })); - }, 60_000); + }, 70_000); it( `processes chain history of ${MAX_CHAIN_LENGTH} with ${BLOCK_SIZE}-tx blocks`, From a5b7d094a526efc326f41f622c0f6c650063dd7d Mon Sep 17 00:00:00 2001 From: vezenovm Date: Tue, 12 Mar 2024 17:55:02 +0000 Subject: [PATCH 044/139] more timeout increase --- .../end-to-end/src/benchmarks/bench_publish_rollup.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/end-to-end/src/benchmarks/bench_publish_rollup.test.ts b/yarn-project/end-to-end/src/benchmarks/bench_publish_rollup.test.ts index fea4012690b2..815c352a35f9 100644 --- a/yarn-project/end-to-end/src/benchmarks/bench_publish_rollup.test.ts +++ b/yarn-project/end-to-end/src/benchmarks/bench_publish_rollup.test.ts @@ -14,7 +14,7 @@ describe('benchmarks/publish_rollup', () => { beforeEach(async () => { ({ context, contract, sequencer } = await benchmarkSetup({ maxTxsPerBlock: 1024 })); - }, 60_000); + }, 70_000); it.each(BENCHMARK_BLOCK_SIZES)( `publishes a rollup with %d txs`, From 6ec4afd742364def83799e31e91f0d0cbb5ae2a3 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Tue, 12 Mar 2024 18:31:20 +0000 Subject: [PATCH 045/139] dont bootstrap in packages tests --- build_manifest.yml | 1 + noir/Dockerfile.packages-test | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/build_manifest.yml b/build_manifest.yml index 9ae9eea56d6b..e650233f6d1e 100644 --- a/build_manifest.yml +++ b/build_manifest.yml @@ -39,6 +39,7 @@ noir-packages-tests: dependencies: - noir - bb.js + - noir-packages # Builds the brillig to avm transpiler. avm-transpiler: diff --git a/noir/Dockerfile.packages-test b/noir/Dockerfile.packages-test index 3669d54edaf8..9fa3645cde0f 100644 --- a/noir/Dockerfile.packages-test +++ b/noir/Dockerfile.packages-test @@ -1,8 +1,10 @@ FROM aztecprotocol/noir AS noir FROM --platform=linux/amd64 aztecprotocol/bb.js as bb.js +FROM --platform=linux/amd64 aztecprotocol/noir-packages as noir-packages FROM node:20 AS builder COPY --from=bb.js /usr/src/barretenberg/ts /usr/src/barretenberg/ts +COPY --from=noir-packages /usr/src/noir/packages /usr/src/noir/packages WORKDIR /usr/src/barretenberg/ts RUN yarn --immutable @@ -18,7 +20,7 @@ ENV COMMIT_HASH=${COMMIT_HASH} WORKDIR /usr/src/noir COPY . . -RUN ./scripts/bootstrap_packages.sh +# RUN ./scripts/bootstrap_packages.sh RUN ./scripts/test_js_packages.sh # Don't waste time pushing a huge container back to ECR as nothing needs the output. From a8ccd5c6b7aa65a1895318a1859e05f2db6cdfc1 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Tue, 12 Mar 2024 18:55:27 +0000 Subject: [PATCH 046/139] remove noir-packages dep --- build_manifest.yml | 2 +- noir/Dockerfile.packages-test | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build_manifest.yml b/build_manifest.yml index e650233f6d1e..17c72bff2e43 100644 --- a/build_manifest.yml +++ b/build_manifest.yml @@ -39,7 +39,7 @@ noir-packages-tests: dependencies: - noir - bb.js - - noir-packages + # - noir-packages # Builds the brillig to avm transpiler. avm-transpiler: diff --git a/noir/Dockerfile.packages-test b/noir/Dockerfile.packages-test index 9fa3645cde0f..9fde2e81d476 100644 --- a/noir/Dockerfile.packages-test +++ b/noir/Dockerfile.packages-test @@ -1,10 +1,10 @@ FROM aztecprotocol/noir AS noir FROM --platform=linux/amd64 aztecprotocol/bb.js as bb.js -FROM --platform=linux/amd64 aztecprotocol/noir-packages as noir-packages +# FROM --platform=linux/amd64 aztecprotocol/noir-packages as noir-packages FROM node:20 AS builder COPY --from=bb.js /usr/src/barretenberg/ts /usr/src/barretenberg/ts -COPY --from=noir-packages /usr/src/noir/packages /usr/src/noir/packages +# COPY --from=noir-packages /usr/src/noir/packages /usr/src/noir/packages WORKDIR /usr/src/barretenberg/ts RUN yarn --immutable From 0c78c33d73535d69765503126a47e89041929a99 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Tue, 12 Mar 2024 19:13:55 +0000 Subject: [PATCH 047/139] need packages dep in packages.test --- noir/Dockerfile.packages-test | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/noir/Dockerfile.packages-test b/noir/Dockerfile.packages-test index 9fde2e81d476..7c9982384335 100644 --- a/noir/Dockerfile.packages-test +++ b/noir/Dockerfile.packages-test @@ -1,10 +1,10 @@ FROM aztecprotocol/noir AS noir FROM --platform=linux/amd64 aztecprotocol/bb.js as bb.js -# FROM --platform=linux/amd64 aztecprotocol/noir-packages as noir-packages +FROM --platform=linux/amd64 aztecprotocol/noir-packages as noir-packages FROM node:20 AS builder COPY --from=bb.js /usr/src/barretenberg/ts /usr/src/barretenberg/ts -# COPY --from=noir-packages /usr/src/noir/packages /usr/src/noir/packages +COPY --from=noir-packages /usr/src/noir/packages /usr/src/noir/packages WORKDIR /usr/src/barretenberg/ts RUN yarn --immutable @@ -20,7 +20,6 @@ ENV COMMIT_HASH=${COMMIT_HASH} WORKDIR /usr/src/noir COPY . . -# RUN ./scripts/bootstrap_packages.sh RUN ./scripts/test_js_packages.sh # Don't waste time pushing a huge container back to ECR as nothing needs the output. From 27359e8fe89e8af660f00fe1dc84e3f2ba066e94 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Tue, 12 Mar 2024 19:17:08 +0000 Subject: [PATCH 048/139] test inrease counter timeout --- .../end-to-end/src/benchmarks/bench_process_history.test.ts | 2 +- .../end-to-end/src/benchmarks/bench_publish_rollup.test.ts | 2 +- yarn-project/end-to-end/src/e2e_counter_contract.test.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn-project/end-to-end/src/benchmarks/bench_process_history.test.ts b/yarn-project/end-to-end/src/benchmarks/bench_process_history.test.ts index 2de00af5b6d4..b518d8bf151c 100644 --- a/yarn-project/end-to-end/src/benchmarks/bench_process_history.test.ts +++ b/yarn-project/end-to-end/src/benchmarks/bench_process_history.test.ts @@ -30,7 +30,7 @@ describe('benchmarks/process_history', () => { beforeEach(async () => { ({ context, contract, sequencer } = await benchmarkSetup({ maxTxsPerBlock: BLOCK_SIZE })); - }, 70_000); + }, 100_000); it( `processes chain history of ${MAX_CHAIN_LENGTH} with ${BLOCK_SIZE}-tx blocks`, diff --git a/yarn-project/end-to-end/src/benchmarks/bench_publish_rollup.test.ts b/yarn-project/end-to-end/src/benchmarks/bench_publish_rollup.test.ts index 815c352a35f9..5cae33317c13 100644 --- a/yarn-project/end-to-end/src/benchmarks/bench_publish_rollup.test.ts +++ b/yarn-project/end-to-end/src/benchmarks/bench_publish_rollup.test.ts @@ -14,7 +14,7 @@ describe('benchmarks/publish_rollup', () => { beforeEach(async () => { ({ context, contract, sequencer } = await benchmarkSetup({ maxTxsPerBlock: 1024 })); - }, 70_000); + }, 100_000); it.each(BENCHMARK_BLOCK_SIZES)( `publishes a rollup with %d txs`, diff --git a/yarn-project/end-to-end/src/e2e_counter_contract.test.ts b/yarn-project/end-to-end/src/e2e_counter_contract.test.ts index f47c6ba8d203..52e944973091 100644 --- a/yarn-project/end-to-end/src/e2e_counter_contract.test.ts +++ b/yarn-project/end-to-end/src/e2e_counter_contract.test.ts @@ -25,7 +25,7 @@ describe('e2e_counter_contract', () => { counterContract = await CounterContract.deploy(wallet, 0, owner).send().deployed(); logger(`Counter contract deployed at ${counterContract.address}`); - }, 25_000); + }, 50_000); afterAll(() => teardown()); From 1d04bdbbbc6e097d09f2cafa12202699eddb4c72 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Tue, 12 Mar 2024 19:23:39 +0000 Subject: [PATCH 049/139] switch order of config --- .circleci/config.yml | 258 +++++++++++++++++++++---------------------- build_manifest.yml | 2 +- 2 files changed, 130 insertions(+), 130 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index e1ac8fdf4326..02951a234843 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -105,31 +105,19 @@ jobs: command: cond_spot_run_build barretenberg-wasm-linux-clang 128 aztec_manifest_key: barretenberg-wasm-linux-clang - barretenberg-x86_64-linux-gcc: - docker: - - image: aztecprotocol/alpine-build-image - resource_class: small - steps: - - *checkout - - *setup_env - - run: - name: "Build" - command: cond_spot_run_build barretenberg-x86_64-linux-gcc 128 - aztec_manifest_key: barretenberg-x86_64-linux-gcc - - barretenberg-x86_64-linux-clang: - docker: - - image: aztecprotocol/alpine-build-image - resource_class: small + bb-js: + machine: + image: default + resource_class: large steps: - *checkout - *setup_env - run: - name: "Build" - command: cond_spot_run_build barretenberg-x86_64-linux-clang 128 - aztec_manifest_key: barretenberg-x86_64-linux-clang + name: "Build and test" + command: build bb.js + aztec_manifest_key: bb.js - barretenberg-x86_64-linux-clang-fuzzing: + bb-js-tests: docker: - image: aztecprotocol/alpine-build-image resource_class: small @@ -137,11 +125,12 @@ jobs: - *checkout - *setup_env - run: - name: "Build" - command: cond_spot_run_build barretenberg-x86_64-linux-clang-fuzzing 128 - aztec_manifest_key: barretenberg-x86_64-linux-clang-fuzzing - - barretenberg-x86_64-linux-clang-assert: + name: "Build and test" + command: cond_spot_run_test bb.js 32 ./scripts/run_tests + aztec_manifest_key: bb.js + + # Noir + noir-x86_64: docker: - image: aztecprotocol/alpine-build-image resource_class: small @@ -150,10 +139,10 @@ jobs: - *setup_env - run: name: "Build" - command: cond_spot_run_build barretenberg-x86_64-linux-clang-assert 128 - aztec_manifest_key: barretenberg-x86_64-linux-clang-assert + command: cond_spot_run_build noir 32 + aztec_manifest_key: noir - barretenberg-x86_64-linux-clang-sol: + noir-arm64: docker: - image: aztecprotocol/alpine-build-image resource_class: small @@ -162,26 +151,22 @@ jobs: - *setup_env - run: name: "Build" - command: cond_spot_run_build barretenberg-x86_64-linux-clang-sol 32 - aztec_manifest_key: barretenberg-x86_64-linux-clang-sol + command: cond_spot_run_build noir 32 arm64 + aztec_manifest_key: noir - barretenberg-docs: + noir-ecr-manifest: machine: image: default - resource_class: large + resource_class: medium steps: - *checkout - *setup_env - run: - name: "Build barretenberg docs" - command: build barretenberg-docs - aztec_manifest_key: barretenberg-docs - - run: - name: "Deploy barretenberg docs" - command: | - barretenberg/cpp/scripts/ci/upload_doxygen_to_s3.sh + name: "Create ECR manifest" + command: create_ecr_manifest noir x86_64,arm64 + aztec_manifest_key: noir - barretenberg-stdlib-tests: + noir-tests: docker: - image: aztecprotocol/alpine-build-image resource_class: small @@ -189,11 +174,11 @@ jobs: - *checkout - *setup_env - run: - name: "Test" - command: cond_spot_run_test barretenberg-x86_64-linux-clang-assert 32 ./scripts/run_tests 1 stdlib-tests - aztec_manifest_key: barretenberg-x86_64-linux-clang-assert + name: "Build" + command: cond_spot_run_build noir-tests 32 + aztec_manifest_key: noir-tests - barretenberg-dsl-tests: + noir-packages: docker: - image: aztecprotocol/alpine-build-image resource_class: small @@ -201,11 +186,11 @@ jobs: - *checkout - *setup_env - run: - name: "Test" - command: cond_spot_run_test barretenberg-x86_64-linux-clang-assert 32 ./scripts/run_tests 1 dsl_tests - aztec_manifest_key: barretenberg-x86_64-linux-clang-assert + name: "Build" + command: cond_spot_run_build noir-packages 32 + aztec_manifest_key: noir-packages - barretenberg-tests: + noir-packages-tests: docker: - image: aztecprotocol/alpine-build-image resource_class: small @@ -213,29 +198,23 @@ jobs: - *checkout - *setup_env - run: - name: "Test" - command: cond_spot_run_test barretenberg-x86_64-linux-clang-assert 32 ./scripts/bb-tests.sh - aztec_manifest_key: barretenberg-x86_64-linux-clang-assert + name: "Build" + command: cond_spot_run_build noir-packages-tests 32 + aztec_manifest_key: noir-packages-tests - barretenberg-bench: - machine: - # NOTE: we usually use alpine build image when making spot images, but - # we are not able to upload to S3 with it - image: default - resource_class: medium + noir-compile-acir-tests: + docker: + - image: aztecprotocol/alpine-build-image + resource_class: small steps: - *checkout - *setup_env - run: - name: "Benchmark" - command: cond_spot_run_build barretenberg-bench 32 - aztec_manifest_key: barretenberg-bench - - run: - name: "Upload" - command: | - barretenberg/cpp/scripts/ci/upload_benchmarks_to_s3.sh + name: "Build" + command: cond_spot_run_build noir-compile-acir-tests 32 + aztec_manifest_key: noir-compile-acir-tests - barretenberg-proof-system-tests: + avm-transpiler: docker: - image: aztecprotocol/alpine-build-image resource_class: small @@ -243,11 +222,11 @@ jobs: - *checkout - *setup_env - run: - name: "Test" - command: cond_spot_run_test barretenberg-x86_64-linux-clang-assert 32 ./scripts/run_tests 1 proof_system_tests - aztec_manifest_key: barretenberg-x86_64-linux-clang-assert + name: "Build" + command: cond_spot_run_build avm-transpiler 32 + aztec_manifest_key: avm-transpiler - barretenberg-stdlib-recursion-ultra-tests: + barretenberg-acir-tests-bb: docker: - image: aztecprotocol/alpine-build-image resource_class: small @@ -255,23 +234,23 @@ jobs: - *checkout - *setup_env - run: - name: "Test" - command: cond_spot_run_test barretenberg-x86_64-linux-clang-assert 32 ./scripts/run_tests 3 stdlib_recursion_tests --gtest_filter=-*turbo* - aztec_manifest_key: barretenberg-x86_64-linux-clang-assert + name: "Build and test" + command: cond_spot_run_build barretenberg-acir-tests-bb 32 + aztec_manifest_key: barretenberg-acir-tests-bb - bb-js: - machine: - image: default - resource_class: large + barretenberg-acir-tests-bb-sol: + docker: + - image: aztecprotocol/alpine-build-image + resource_class: small steps: - *checkout - *setup_env - run: name: "Build and test" - command: build bb.js - aztec_manifest_key: bb.js + command: cond_spot_run_build barretenberg-acir-tests-bb-sol 32 + aztec_manifest_key: barretenberg-acir-tests-bb-sol - bb-js-tests: + bb-js-acir-tests: docker: - image: aztecprotocol/alpine-build-image resource_class: small @@ -280,11 +259,10 @@ jobs: - *setup_env - run: name: "Build and test" - command: cond_spot_run_test bb.js 32 ./scripts/run_tests - aztec_manifest_key: bb.js - - # Noir - noir-x86_64: + command: cond_spot_run_build barretenberg-acir-tests-bb.js 32 + aztec_manifest_key: barretenberg-acir-tests-bb.js + + barretenberg-x86_64-linux-gcc: docker: - image: aztecprotocol/alpine-build-image resource_class: small @@ -293,10 +271,10 @@ jobs: - *setup_env - run: name: "Build" - command: cond_spot_run_build noir 32 - aztec_manifest_key: noir + command: cond_spot_run_build barretenberg-x86_64-linux-gcc 128 + aztec_manifest_key: barretenberg-x86_64-linux-gcc - noir-arm64: + barretenberg-x86_64-linux-clang: docker: - image: aztecprotocol/alpine-build-image resource_class: small @@ -305,22 +283,22 @@ jobs: - *setup_env - run: name: "Build" - command: cond_spot_run_build noir 32 arm64 - aztec_manifest_key: noir + command: cond_spot_run_build barretenberg-x86_64-linux-clang 128 + aztec_manifest_key: barretenberg-x86_64-linux-clang - noir-ecr-manifest: - machine: - image: default - resource_class: medium + barretenberg-x86_64-linux-clang-fuzzing: + docker: + - image: aztecprotocol/alpine-build-image + resource_class: small steps: - *checkout - *setup_env - run: - name: "Create ECR manifest" - command: create_ecr_manifest noir x86_64,arm64 - aztec_manifest_key: noir + name: "Build" + command: cond_spot_run_build barretenberg-x86_64-linux-clang-fuzzing 128 + aztec_manifest_key: barretenberg-x86_64-linux-clang-fuzzing - noir-tests: + barretenberg-x86_64-linux-clang-assert: docker: - image: aztecprotocol/alpine-build-image resource_class: small @@ -329,10 +307,10 @@ jobs: - *setup_env - run: name: "Build" - command: cond_spot_run_build noir-tests 32 - aztec_manifest_key: noir-tests + command: cond_spot_run_build barretenberg-x86_64-linux-clang-assert 128 + aztec_manifest_key: barretenberg-x86_64-linux-clang-assert - noir-packages: + barretenberg-x86_64-linux-clang-sol: docker: - image: aztecprotocol/alpine-build-image resource_class: small @@ -341,22 +319,26 @@ jobs: - *setup_env - run: name: "Build" - command: cond_spot_run_build noir-packages 32 - aztec_manifest_key: noir-packages + command: cond_spot_run_build barretenberg-x86_64-linux-clang-sol 32 + aztec_manifest_key: barretenberg-x86_64-linux-clang-sol - noir-packages-tests: - docker: - - image: aztecprotocol/alpine-build-image - resource_class: small + barretenberg-docs: + machine: + image: default + resource_class: large steps: - *checkout - *setup_env - run: - name: "Build" - command: cond_spot_run_build noir-packages-tests 32 - aztec_manifest_key: noir-packages-tests + name: "Build barretenberg docs" + command: build barretenberg-docs + aztec_manifest_key: barretenberg-docs + - run: + name: "Deploy barretenberg docs" + command: | + barretenberg/cpp/scripts/ci/upload_doxygen_to_s3.sh - noir-compile-acir-tests: + barretenberg-stdlib-tests: docker: - image: aztecprotocol/alpine-build-image resource_class: small @@ -364,11 +346,11 @@ jobs: - *checkout - *setup_env - run: - name: "Build" - command: cond_spot_run_build noir-compile-acir-tests 32 - aztec_manifest_key: noir-compile-acir-tests + name: "Test" + command: cond_spot_run_test barretenberg-x86_64-linux-clang-assert 32 ./scripts/run_tests 1 stdlib-tests + aztec_manifest_key: barretenberg-x86_64-linux-clang-assert - avm-transpiler: + barretenberg-dsl-tests: docker: - image: aztecprotocol/alpine-build-image resource_class: small @@ -376,11 +358,11 @@ jobs: - *checkout - *setup_env - run: - name: "Build" - command: cond_spot_run_build avm-transpiler 32 - aztec_manifest_key: avm-transpiler + name: "Test" + command: cond_spot_run_test barretenberg-x86_64-linux-clang-assert 32 ./scripts/run_tests 1 dsl_tests + aztec_manifest_key: barretenberg-x86_64-linux-clang-assert - barretenberg-acir-tests-bb: + barretenberg-tests: docker: - image: aztecprotocol/alpine-build-image resource_class: small @@ -388,11 +370,29 @@ jobs: - *checkout - *setup_env - run: - name: "Build and test" - command: cond_spot_run_build barretenberg-acir-tests-bb 32 - aztec_manifest_key: barretenberg-acir-tests-bb + name: "Test" + command: cond_spot_run_test barretenberg-x86_64-linux-clang-assert 32 ./scripts/bb-tests.sh + aztec_manifest_key: barretenberg-x86_64-linux-clang-assert - barretenberg-acir-tests-bb-sol: + barretenberg-bench: + machine: + # NOTE: we usually use alpine build image when making spot images, but + # we are not able to upload to S3 with it + image: default + resource_class: medium + steps: + - *checkout + - *setup_env + - run: + name: "Benchmark" + command: cond_spot_run_build barretenberg-bench 32 + aztec_manifest_key: barretenberg-bench + - run: + name: "Upload" + command: | + barretenberg/cpp/scripts/ci/upload_benchmarks_to_s3.sh + + barretenberg-proof-system-tests: docker: - image: aztecprotocol/alpine-build-image resource_class: small @@ -400,11 +400,11 @@ jobs: - *checkout - *setup_env - run: - name: "Build and test" - command: cond_spot_run_build barretenberg-acir-tests-bb-sol 32 - aztec_manifest_key: barretenberg-acir-tests-bb-sol + name: "Test" + command: cond_spot_run_test barretenberg-x86_64-linux-clang-assert 32 ./scripts/run_tests 1 proof_system_tests + aztec_manifest_key: barretenberg-x86_64-linux-clang-assert - bb-js-acir-tests: + barretenberg-stdlib-recursion-ultra-tests: docker: - image: aztecprotocol/alpine-build-image resource_class: small @@ -412,9 +412,9 @@ jobs: - *checkout - *setup_env - run: - name: "Build and test" - command: cond_spot_run_build barretenberg-acir-tests-bb.js 32 - aztec_manifest_key: barretenberg-acir-tests-bb.js + name: "Test" + command: cond_spot_run_test barretenberg-x86_64-linux-clang-assert 32 ./scripts/run_tests 3 stdlib_recursion_tests --gtest_filter=-*turbo* + aztec_manifest_key: barretenberg-x86_64-linux-clang-assert l1-contracts: machine: diff --git a/build_manifest.yml b/build_manifest.yml index 17c72bff2e43..e650233f6d1e 100644 --- a/build_manifest.yml +++ b/build_manifest.yml @@ -39,7 +39,7 @@ noir-packages-tests: dependencies: - noir - bb.js - # - noir-packages + - noir-packages # Builds the brillig to avm transpiler. avm-transpiler: From 8ac7d2c866e75ed60ed6e0dbde3d90757e8af64d Mon Sep 17 00:00:00 2001 From: vezenovm Date: Tue, 12 Mar 2024 19:25:53 +0000 Subject: [PATCH 050/139] move acir tests after bberg in config --- .circleci/config.yml | 72 ++++++++++++++++++++++---------------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 02951a234843..71afe37a7f1c 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -226,42 +226,6 @@ jobs: command: cond_spot_run_build avm-transpiler 32 aztec_manifest_key: avm-transpiler - barretenberg-acir-tests-bb: - docker: - - image: aztecprotocol/alpine-build-image - resource_class: small - steps: - - *checkout - - *setup_env - - run: - name: "Build and test" - command: cond_spot_run_build barretenberg-acir-tests-bb 32 - aztec_manifest_key: barretenberg-acir-tests-bb - - barretenberg-acir-tests-bb-sol: - docker: - - image: aztecprotocol/alpine-build-image - resource_class: small - steps: - - *checkout - - *setup_env - - run: - name: "Build and test" - command: cond_spot_run_build barretenberg-acir-tests-bb-sol 32 - aztec_manifest_key: barretenberg-acir-tests-bb-sol - - bb-js-acir-tests: - docker: - - image: aztecprotocol/alpine-build-image - resource_class: small - steps: - - *checkout - - *setup_env - - run: - name: "Build and test" - command: cond_spot_run_build barretenberg-acir-tests-bb.js 32 - aztec_manifest_key: barretenberg-acir-tests-bb.js - barretenberg-x86_64-linux-gcc: docker: - image: aztecprotocol/alpine-build-image @@ -416,6 +380,42 @@ jobs: command: cond_spot_run_test barretenberg-x86_64-linux-clang-assert 32 ./scripts/run_tests 3 stdlib_recursion_tests --gtest_filter=-*turbo* aztec_manifest_key: barretenberg-x86_64-linux-clang-assert + barretenberg-acir-tests-bb: + docker: + - image: aztecprotocol/alpine-build-image + resource_class: small + steps: + - *checkout + - *setup_env + - run: + name: "Build and test" + command: cond_spot_run_build barretenberg-acir-tests-bb 32 + aztec_manifest_key: barretenberg-acir-tests-bb + + barretenberg-acir-tests-bb-sol: + docker: + - image: aztecprotocol/alpine-build-image + resource_class: small + steps: + - *checkout + - *setup_env + - run: + name: "Build and test" + command: cond_spot_run_build barretenberg-acir-tests-bb-sol 32 + aztec_manifest_key: barretenberg-acir-tests-bb-sol + + bb-js-acir-tests: + docker: + - image: aztecprotocol/alpine-build-image + resource_class: small + steps: + - *checkout + - *setup_env + - run: + name: "Build and test" + command: cond_spot_run_build barretenberg-acir-tests-bb.js 32 + aztec_manifest_key: barretenberg-acir-tests-bb.js + l1-contracts: machine: image: default From a7ce531c6312847b1e36ce8db7c38685fb3538cb Mon Sep 17 00:00:00 2001 From: vezenovm Date: Tue, 12 Mar 2024 19:51:24 +0000 Subject: [PATCH 051/139] bring back test --- .../tooling/noir_js/test/node/e2e.test.ts | 72 +++++++++---------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/noir/noir-repo/tooling/noir_js/test/node/e2e.test.ts b/noir/noir-repo/tooling/noir_js/test/node/e2e.test.ts index 0319a7c83187..8921314e8ea3 100644 --- a/noir/noir-repo/tooling/noir_js/test/node/e2e.test.ts +++ b/noir/noir-repo/tooling/noir_js/test/node/e2e.test.ts @@ -91,39 +91,39 @@ it('end-to-end proving and verification with different instances', async () => { expect(proof_is_valid).to.be.true; }); -// // This bug occurs when we use the same backend to create an inner proof and then an outer proof -// // and then try to verify either one of them. -// // -// // The panic occurs when we try to verify the outer/inner proof that was created. -// // If we only create one type of proof, then this works as expected. -// // -// // If we do not create an inner proof, then this will work as expected. -// it('[BUG] -- bb.js null function or function signature mismatch (outer-inner) ', async () => { -// // Noir.Js part -// const inputs = { -// x: '2', -// y: '3', -// }; - -// const program = new Noir(assert_lt_program); - -// const { witness } = await program.execute(inputs); - -// // bb.js part -// // -// // Proof creation -// // -// const prover = new Backend(assert_lt_program); -// // Create a proof using both proving systems, the majority of the time -// // one would only use outer proofs. -// const proofOuter = await prover.generateProof(witness); -// const _proofInner = await prover.generateProof(witness); - -// // Proof verification -// // -// const isValidOuter = await prover.verifyProof(proofOuter); -// expect(isValidOuter).to.be.true; -// // We can also try verifying an inner proof and it will fail. -// const isValidInner = await prover.verifyProof(_proofInner); -// expect(isValidInner).to.be.true; -// }); +// This bug occurs when we use the same backend to create an inner proof and then an outer proof +// and then try to verify either one of them. +// +// The panic occurs when we try to verify the outer/inner proof that was created. +// If we only create one type of proof, then this works as expected. +// +// If we do not create an inner proof, then this will work as expected. +it('[BUG] -- bb.js null function or function signature mismatch (outer-inner) ', async () => { + // Noir.Js part + const inputs = { + x: '2', + y: '3', + }; + + const program = new Noir(assert_lt_program); + + const { witness } = await program.execute(inputs); + + // bb.js part + // + // Proof creation + // + const prover = new Backend(assert_lt_program); + // Create a proof using both proving systems, the majority of the time + // one would only use outer proofs. + const proofOuter = await prover.generateProof(witness); + const _proofInner = await prover.generateProof(witness); + + // Proof verification + // + const isValidOuter = await prover.verifyProof(proofOuter); + expect(isValidOuter).to.be.true; + // We can also try verifying an inner proof and it will fail. + const isValidInner = await prover.verifyProof(_proofInner); + expect(isValidInner).to.be.true; +}); From ac72a938e5eae0990ac652062a4d2c4ff30da2d7 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Tue, 12 Mar 2024 23:50:13 +0000 Subject: [PATCH 052/139] fix native acvm cli interface --- noir/noir-repo/tooling/acvm_cli/src/cli/execute_cmd.rs | 6 +++--- .../src/block_builder/solo_block_builder.ts | 2 ++ yarn-project/sequencer-client/src/sequencer/sequencer.ts | 2 ++ 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/noir/noir-repo/tooling/acvm_cli/src/cli/execute_cmd.rs b/noir/noir-repo/tooling/acvm_cli/src/cli/execute_cmd.rs index 255b6131fd68..b76d0eccc29c 100644 --- a/noir/noir-repo/tooling/acvm_cli/src/cli/execute_cmd.rs +++ b/noir/noir-repo/tooling/acvm_cli/src/cli/execute_cmd.rs @@ -1,6 +1,6 @@ use std::io::{self, Write}; -use acir::circuit::Circuit; +use acir::circuit::Program; use acir::native_types::WitnessMap; use bn254_blackbox_solver::Bn254BlackBoxSolver; use clap::Args; @@ -66,10 +66,10 @@ pub(crate) fn execute_program_from_witness( foreign_call_resolver_url: Option<&str>, ) -> Result { let blackbox_solver = Bn254BlackBoxSolver::new(); - let circuit: Circuit = Circuit::deserialize_circuit(bytecode) + let program: Program = Program::deserialize_program(bytecode) .map_err(|_| CliError::CircuitDeserializationError())?; execute_circuit( - &circuit, + &program.functions[0], inputs_map.clone(), &blackbox_solver, &mut DefaultForeignCallExecutor::new(true, foreign_call_resolver_url), diff --git a/yarn-project/sequencer-client/src/block_builder/solo_block_builder.ts b/yarn-project/sequencer-client/src/block_builder/solo_block_builder.ts index da3553c64a8c..1f25cb4ba39b 100644 --- a/yarn-project/sequencer-client/src/block_builder/solo_block_builder.ts +++ b/yarn-project/sequencer-client/src/block_builder/solo_block_builder.ts @@ -231,7 +231,9 @@ export class SoloBlockBuilder implements BlockBuilder { ): Promise<[BaseOrMergeRollupPublicInputs, Proof]> { this.debug(`Running base rollup for ${tx.hash}`); const rollupOutput = await this.simulator.baseRollupCircuit(inputs); + this.debug(`Validating partial state`); this.validatePartialState(rollupOutput.end, treeSnapshots); + this.debug(`Getting base rollup proof`); const proof = await this.prover.getBaseRollupProof(inputs, rollupOutput); return [rollupOutput, proof]; } diff --git a/yarn-project/sequencer-client/src/sequencer/sequencer.ts b/yarn-project/sequencer-client/src/sequencer/sequencer.ts index 39f9b12e0581..51461de0d7ed 100644 --- a/yarn-project/sequencer-client/src/sequencer/sequencer.ts +++ b/yarn-project/sequencer-client/src/sequencer/sequencer.ts @@ -230,6 +230,8 @@ export class Sequencer { await this.publishL2Block(block); this.log.info(`Submitted rollup block ${block.number} with ${processedValidTxs.length} transactions`); } catch (err) { + this.log.info(`${err}`); + this.log.info("GOT HERE"); this.log.error(`Rolling back world state DB due to error assembling block`, (err as any).stack); await this.worldState.getLatest().rollback(); } From 1407de43dc3f3a5ff6544c3d8173d7cca0ea0ead Mon Sep 17 00:00:00 2001 From: vezenovm Date: Wed, 13 Mar 2024 00:02:15 +0000 Subject: [PATCH 053/139] empty From 671cb93ba26f465ddd3fc24cfdb0f11613fbcb8b Mon Sep 17 00:00:00 2001 From: vezenovm Date: Wed, 13 Mar 2024 03:03:05 +0000 Subject: [PATCH 054/139] yarn formatting --- .../sequencer-client/src/block_builder/solo_block_builder.ts | 2 -- yarn-project/sequencer-client/src/sequencer/sequencer.ts | 2 -- 2 files changed, 4 deletions(-) diff --git a/yarn-project/sequencer-client/src/block_builder/solo_block_builder.ts b/yarn-project/sequencer-client/src/block_builder/solo_block_builder.ts index 1f25cb4ba39b..da3553c64a8c 100644 --- a/yarn-project/sequencer-client/src/block_builder/solo_block_builder.ts +++ b/yarn-project/sequencer-client/src/block_builder/solo_block_builder.ts @@ -231,9 +231,7 @@ export class SoloBlockBuilder implements BlockBuilder { ): Promise<[BaseOrMergeRollupPublicInputs, Proof]> { this.debug(`Running base rollup for ${tx.hash}`); const rollupOutput = await this.simulator.baseRollupCircuit(inputs); - this.debug(`Validating partial state`); this.validatePartialState(rollupOutput.end, treeSnapshots); - this.debug(`Getting base rollup proof`); const proof = await this.prover.getBaseRollupProof(inputs, rollupOutput); return [rollupOutput, proof]; } diff --git a/yarn-project/sequencer-client/src/sequencer/sequencer.ts b/yarn-project/sequencer-client/src/sequencer/sequencer.ts index 51461de0d7ed..39f9b12e0581 100644 --- a/yarn-project/sequencer-client/src/sequencer/sequencer.ts +++ b/yarn-project/sequencer-client/src/sequencer/sequencer.ts @@ -230,8 +230,6 @@ export class Sequencer { await this.publishL2Block(block); this.log.info(`Submitted rollup block ${block.number} with ${processedValidTxs.length} transactions`); } catch (err) { - this.log.info(`${err}`); - this.log.info("GOT HERE"); this.log.error(`Rolling back world state DB due to error assembling block`, (err as any).stack); await this.worldState.getLatest().rollback(); } From b7f6609651e78bb98a6a84529bef4e5bb3b4c280 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Wed, 13 Mar 2024 03:03:28 +0000 Subject: [PATCH 055/139] acvm cli error update --- noir/noir-repo/tooling/acvm_cli/src/errors.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noir/noir-repo/tooling/acvm_cli/src/errors.rs b/noir/noir-repo/tooling/acvm_cli/src/errors.rs index 035388d05f7e..923046410eac 100644 --- a/noir/noir-repo/tooling/acvm_cli/src/errors.rs +++ b/noir/noir-repo/tooling/acvm_cli/src/errors.rs @@ -32,7 +32,7 @@ pub(crate) enum CliError { FilesystemError(#[from] FilesystemError), /// Error related to circuit deserialization - #[error("Error: failed to deserialize circuit")] + #[error("Error: failed to deserialize circuit in ACVM CLI")] CircuitDeserializationError(), /// Error related to circuit execution From 93505267fc904c5bf6ab30d2b9a716b9aad4f21a Mon Sep 17 00:00:00 2001 From: vezenovm Date: Wed, 13 Mar 2024 14:34:00 +0000 Subject: [PATCH 056/139] yarn lock --- yarn-project/yarn.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/yarn.lock b/yarn-project/yarn.lock index ae278e45d441..543a2887af70 100644 --- a/yarn-project/yarn.lock +++ b/yarn-project/yarn.lock @@ -2787,7 +2787,7 @@ __metadata: version: 0.0.0-use.local resolution: "@noir-lang/noirc_abi@portal:../noir/packages/noirc_abi::locator=%40aztec%2Faztec3-packages%40workspace%3A." dependencies: - "@noir-lang/types": 0.25.0 + "@noir-lang/types": 0.24.0 languageName: node linkType: soft From 52b37738d4c1a20973b17cbb41c1ad5878c448c8 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Wed, 13 Mar 2024 14:43:21 +0000 Subject: [PATCH 057/139] update yarn lock --- yarn-project/yarn.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/yarn.lock b/yarn-project/yarn.lock index 543a2887af70..ae278e45d441 100644 --- a/yarn-project/yarn.lock +++ b/yarn-project/yarn.lock @@ -2787,7 +2787,7 @@ __metadata: version: 0.0.0-use.local resolution: "@noir-lang/noirc_abi@portal:../noir/packages/noirc_abi::locator=%40aztec%2Faztec3-packages%40workspace%3A." dependencies: - "@noir-lang/types": 0.24.0 + "@noir-lang/types": 0.25.0 languageName: node linkType: soft From 6177b62c21ed64f4b3fb8c74d62de3e63ad61a96 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Wed, 13 Mar 2024 15:05:27 +0000 Subject: [PATCH 058/139] update noir-pacakges to be dependent --- build_manifest.yml | 1 + noir/Dockerfile.packages-test | 3 +++ 2 files changed, 4 insertions(+) diff --git a/build_manifest.yml b/build_manifest.yml index c07877468bc0..103828872816 100644 --- a/build_manifest.yml +++ b/build_manifest.yml @@ -36,6 +36,7 @@ noir-packages-tests: rebuildPatterns: .rebuild_patterns_packages dependencies: - noir + - noir-packages # Builds the brillig to avm transpiler. avm-transpiler: diff --git a/noir/Dockerfile.packages-test b/noir/Dockerfile.packages-test index 33fac5120fb4..b9b4ac322671 100644 --- a/noir/Dockerfile.packages-test +++ b/noir/Dockerfile.packages-test @@ -1,6 +1,9 @@ FROM aztecprotocol/noir AS noir +FROM --platform=linux/amd64 aztecprotocol/noir-packages as noir-packages FROM node:20 AS builder +COPY --from=noir-packages /usr/src/noir/packages /usr/src/noir/packages + COPY --from=noir /usr/src/noir/noir-repo/target/release /usr/src/noir/noir-repo/target/release ENV PATH=${PATH}:/usr/src/noir/noir-repo/target/release RUN curl https://sh.rustup.rs -sSf | bash -s -- -y From 4bb76b6799913b89a3b7fc3b09d41182dd41e996 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Wed, 13 Mar 2024 15:35:15 +0000 Subject: [PATCH 059/139] update snapshots --- .../contract/__snapshots__/contract_class.test.ts.snap | 10 +++++----- .../src/gas-token/__snapshots__/index.test.ts.snap | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/yarn-project/circuits.js/src/contract/__snapshots__/contract_class.test.ts.snap b/yarn-project/circuits.js/src/contract/__snapshots__/contract_class.test.ts.snap index be1d429a7c1b..d4f1c3f2060d 100644 --- a/yarn-project/circuits.js/src/contract/__snapshots__/contract_class.test.ts.snap +++ b/yarn-project/circuits.js/src/contract/__snapshots__/contract_class.test.ts.snap @@ -9,18 +9,18 @@ exports[`ContractClass creates a contract class from a contract compilation arti "selector": { "value": 2381782501 }, - "bytecode": "0x1f8b08000000000000ffed9d079454c799ef6fcf0c493dcd30420284080392c8a1a72730e426470990002123230d0c20860c4316306491a364d972daf57a83d7de607bd76b6ff0aec306e7b45edb72ce3ee7f99df7ce79efed396f7775b6aabb3ecf9f9abaedeee156eb6bf8ee39df74dd6fead6f7fbbe5bb76ef5adea5bb120bbfd4a49cca4cb953c1274dee8ff69f399bcb3ad36c2b2923e396325c25956229ce525c25951229cdd4a84b37b8970f62811ce9e25c2d92b424ecd5616dcbe45cd7b9f87b846cd182fb1985696404c132516d3de2510d3aaa034daa83e25c2595d229cf7970867df12e17ca044381f2c11ce7e25c2d9bf4438079408e74325c239b044381f2e11ce4125c239b84438879408e7d012e1ac2911ce6125c239bc44381f2911ce474b84f3b108394701e708f339d27cd2ff469bcf31e673acf91c673ec71b1f2bccfe042513359b925aeb7f2925754aea953498ffd598ff352a99a4a449c9642553944c55324dc974253394cc34becf52325bc91c257395cc53325fc902250b952c52b258c912254b953caee40925cb942c57b242c9934a9e52b252c92a8b65b592a795ac51f28c92b72859abe459256f55b24ec9734a9e57d2ac64bd920d4a5a946c54b249c966252f28d9a2a455c95625db946c57b243c94e25bb94ec56b247c95e256d4af65931dbafe48092834a0e599c87951c51f2a292a34a8e2939aea45dc9092527959c52725ac9192567959c53f29292f34a2e28b9a8e49292cb4aae28b9aae49a92eb4a6e28b9a9e496929795bca2e46d4a5e55f276c34295fd1d4a5e53f24e25ef52f26e25ef51f25e25bfa3e47795bc4fc9ef2979bf92df57f2074afe50c91f29f980923f56f241251f52f2274afe54c99f29f973251f56f211251f55f2174afe52c9c794fc95928f2bf98492bf56f2374afe56c9df29f9a492bf57f20f4a3ea5e4d34a3ea3e4b34afe51c93f29f96725ff62c5fc734a3eafe40b4abe68fe47cfbabea4e4cb26fd15f3f955f3f935f3f975eb986f28f9574bf74d25ff66e9bea5e4db26fd1df3f9baf9fcaef9fc9ef9fcbef9fc81f9fca1f9fc91f9fcb1f9fc89f9fca9f9fc99f9fcb9f9fc85f9fca5f9d4e3a4ef1f904df70c3ab6741051bb53bfb1598f9350b04704b76f3a16e5e67ff45963f415669f3e2976ddcc7e374bdfddec77b7cae969f67b5afa6ab35f6de9fb9afdbe96fe41b3ffa0a5ef6ff6fb833e1ec0f352a3d7ba72a38a818eea6119e8ba05b7c744ebba5371a0eb11dc1e0bada3f3d81d74bd8cae07e8ee33ba9ea08b1b5d2f8a99924aa34b0751d58964b32e371175b9660ca977f4bc1b74b9559e78fb44cfbb51975bed8157d78ffb4d597da0def435ba6ad03d6074f783ee41a3eb0bba7e46f700e8fa1bdd83a033cd54d00f740f195d7fd00d34ba01a07bd8e81e02dd20a31b08bac146f730e88618dd20d00d35bac1a0ab31ba21a01b6674434137dce86a4047f3538681ee51a31b0ebac78cee11d0519bfa28e8a85ff798d1e976e2df0338c6e8cb403792da61d08da2361874a3a9fd05dd186a7b4137166c936e1cb42ba41b6f74d446e9ff359a743a88ea9a4865ae89495197ab4ad6e54e8ebedccc98db94a023ae69b033096235d5a4239cd7538bb66346c80ee92b20bd10f2523e8a07dd67885ddf4f9a4c7a6a8ee31aade31290a7c9e17f3a88d6ffc916cf648b59d7ffe9c0117d9dad4b499dcd7b2bb8ceae86bc76dda33ecfdd5867970087873adbe8a7cea6925267b3cf1c82c05df7a8df7b37d6d9678023fa3adb207536ffade03abb07f2da758fbefbdc8d75763370445f6727354adf20efade03adb0e79edba47df7fefc63abb0f383cd4d9666967f3de0aaeb35720af5df7e859ccdd58674f0147f47576b2a73a5b277536c88e1f0581bbeed173c1bbb1ce5e078ee8ebec8666e91be4bd155c673f0079edba47cfa8efc63afb1ee0f050677d3d9f4d499dcd8e9b0781bbeed178c9dd58673f64d27a9ce12b669c6110e8be6a748341f735a31b02baaf1bdd50f02bfa6ba0a55eae81bcb782af81cf415ebb2ed798f4dd780d7c12383cd4d946a9b3796f05d7d96f415ebbee0d37e9bbb1ce7e11383cd4d926a9b3796f05d7d99f435ebbeed19c86bbb1cebe6ed2babff01d6bbe9bd6bd6e742341f75da31b05baef19dd68d07ddfe8c680ee07463716743f34ba71a0fb91d18d07dd8f8d6e02e87e62741341f753a34b82ee6746570bba9f1b5d0a74bf30ba3ad0fdd2e8ea41f72ba36b303a3d2640f3533e63743dc15e3a88eedcc6c137da62d67e1ad2b57e799209e0415b75d1dbaad3bea782fc7daf039e7a0fbec7c1463e3cf5c0d3103d4fad977b4f327b8e53564ce3602b057e79b84765dab3c6e0f698d23ed94b800eafd5490ec6a6e8195331b04565d37e133092ae0118a92da5eb47b7cd55b10e5e0fd752e6fe8cf6d2c041f62a20cfcc011d79fb1ab64af83fb50195703cb6ad9cea8a66a43ad2587cc654be8c0d16a3a7eb3b13b3068bc7657b8a27db762ca84e4d2982ed26cb76bd651bdb10da72b5f1d8b7f3d0afaef5d467ccb407d34c59d45f273b78df9a0e3188ca27b44dfd75b243fa0a48a7621d79291fc583da1e62d7d7119d4b64b78f9b641d97803c531cfea78368fdb7bf3f4cb59875bb3b12ee091eae87dbbeb351d9b45f0fb19b1a12bb29103bca331274748f68041db5b55406f66fb11df6d15f8a05b7f7a5d3b0dfe0e06e02c60607a3873e662a57db5c0f8ca49b0c3c294f310bfb6e9912db3eea69e6ba241bd457a36b88ec55409ec1e51d7917439be1a37ee2b5405bbedf81a23f4fa9cc77b2fa0278f0dc79e867d77aaa8f49fc3eff46106d5db3dbc47a2b5661dff9931ee287759fcaa67db227ccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccfc99712c0be7f150be06268cf67c285fcff933efaf3265e118d0eb5ee707a532e300147f9a0f30daf2b902f2fc3ad6c1f603981f44ffc7f94eae73e963ae64ae7349f65cf3957c8e37d7593c758e5870b05d1399edd4063fe73795d4ef8fd1ef60abb7cea93d369f79b79ba5d3f5b4a6bcc36f1f637f858e45625b42e928c7f612c083b67c9c1bbcf6ca82dbdb0fbccff89ac7426d358d974fb16c57409eff80f94453e1ffe9a0737b8179a86cda1f0dc74eb5caaef2e76fceb909f83b08fbf718e45b2370ff66fe4f59878fef33694ff7b854a1f3a8b19d8ebe0f909d43902a8027093c3eee639efa3a49ac8f51cf21b0e788b9fa50f66f727cfe1ec6ee07d37eaedff008b3300bb3300bb3300bb3300bb33027ef6c13666116666116666116666116666116e68899358feb1d1494af8e096391e65d64c633e83d4c382e76bdacc3aeef31401a731a63f98cbf5bfd5a5907dbcb265d19749e6b11762e7d8dad859d4bb2e77a0f8aaf31e518d8a2b26b1db1e060bb2632dbd93904d19fdf8e390429eb9cd659e713c7cef11a7a1fd4537b3e453ce83c27c1d3359ef3dc903dbc9670fe0ba5f1b7d93e628df7127b4e11be978ff27cc8c496c6cea36fab53499fed06bdaf84e609a41cbe529e0f43dbf75193c6f9237550d6a71dffa72dd73835c54ffb3c237a9f33e777a6298bceef0c87ed34b04664bb166dc7acb2495f01e94f957566a07850ac895d5f23f8de97b0e3eaade3129067bac3ff74c4fecfb078f01ceb4dd79d8f413dfb34dcff7db549d34362341a6244793cbf3fd0391fd09ed388ed680f2b0f1d8bef45fb3cb4516173575df780699efc0bbb0790bd44d0f9be90cf1cd37b7d8ed8ebd05e4c85ffa7833b9f23f63ad4219ca71558e58f81f289ab47107e6fa13c3fb0eea31ee670e5f57e1cd7f701e2c5396894e7a7d056f53373350bf93ef0667db7737d1fc0e3c27cc77621ea7b23d64764c1f7ab519eff69d5c7a921dc4d8e63ff77c8b1142bfb5d619541e7f8f979cf5ab6bd9961f942d7d474f085f2fcbb75dd44df67caf63f7dbd538efa3ad406d53a7ca53cff09d7da1bd0bfa4f384f7854479e7ffd396abff49f1d33ecf8adee7ccf99d6dcaa2f33bcb617b0eb04664bb166d53ff93ec90be02d295e51d79291fc583624dec95c089ecf67153ace3129027edf03f1db1ffb32c9e591673a6ed8177932560febdafb63a1db863340662f41b7ba0a3fb08be07d4f5acc3d7bd34ac1f87bfdb221db6edfd20a6c5fa4d8dfd4ccfd53f1963f163ffe461c35c65e26ce7b59f55d27151ce59c6df8860bf107f23e2eb3b5222b83d9e098bc3a7ed2acb7655116d575bb6ab8b685b622e31e714734e6b45e0d8541930fab8d7e17d351f46d7fdaf1c187dfd8e2f5500631d30e2fd8e183dbc87b5b6ab6b51605fa71b30faf80d6aa1cfabf11dccf85b6462f4f12efc42df678befb2a6e37a00a38f350e70ad827c185d6b64f4844f0feb61d476f5bdf9b846462f60f4f12efd7870fbfbff7f1b23aee544c7dd078c3ec691e2c1edcfd57e1b23be839d8e8b7b66cc756ff73c1f2455e833089c7f81cfa0284eae792cbe9ed5dbcfc6681f9fd5236fe02f8e39fb4853fdc6228571a72dd73974c5a7b7f98cc3fffd3e4fbc7d8c97caa6fde9c048ba2abf71ccd9d79ce63716298c3b6db9cea12b3e7dcc673ce8bcfe87a7316be71825ede3382ee9aa3df3c42d9edf164717e3fdc038d313e38c02186702231dd71718d39e186716c09806463aee0160f4f0bc3ac3982e80119feb92fe41609ced897156018cb381918eeb078c3e9e3dc7c16e3e8c7380918eeb0f8c733d31ce2980712e30d2710380719e27c6b90530ce03463aee21609cef89715e018cf381918e1b088c0b3c31ce2f80710130d2710f03e3424f8c0b0a605c088c74dc20605ce4897161018c8b80918e1b0c8c8b3d312e2a80713130d2714380718927c6c505302e01463a6e28302ef5c4b8a400c6a5c048c7d59400e3b012601c5e028c8f9400e3a325c0f8580930f62c01c6b1c0f878f48c99efd74b0b607c1c789645cf531f071bf9f02c039e27a2e7a9f5e467667ed6725356d4ef485b61c5ea712b5609c8b31ce2b7c243fc626097caa67db227ccc21cc6ac79a87d22d638e45bca8491744f78e6895b3c7acbd53eaef0cb934c38e2a16d3d19bdad54a1be3f093c2ba3e7c9dcab9e2c806725f03c153d4fad273f33f79455964f4f5a3e25200fb61bab3cf81903bb5436edaf72d8ae09a28dc5ea3c62b1dac1b3bac8b1207b85322f2f41660e71c6b69058e3906f191346d23de599276ef1e82d57fbe8625ce19731d55546cdb326729eec3ba25717c0b306789e8e9c277b4f89decf6c3bfa8ce5d36acba704e4c136e9190f7ec6c02e954dfbcfc0791066611666611666611666611666611666611666611666611666611666611666decc38c640ac71c8b7920923e99ef6cc13b778f4966bdcc1c5b8c22f63aaab8c9a676de43cd9b19a670ae0590b3c6f899c273b5613bd9fd9b19a672d9f9eb17c4a401ebcbe9ff5e0670cec52d9b4ff2c9c0761166661166661166661166661166661166661166661166661166661166661ce6e5c99718c8158e3906f0d1346d2bdc5334fdce2d15bae710717e30abf8ca9ae326a9e75d1f3647eabf96c013ceb80e7add1f3d47af2333356f39ce5d3b3964f09c883d7f7731efc8c815d2a9bf69f83f320ccc2ec62c6368b58e3906f2d1346d2bdd5334fdce2d15bae76ccc5b8c22f63aaab8c9aa739729eec38fd7305f03403cff391f364dbfee8fdccb6fdeb2d9f9eb37c4a401ebcbed77bf0330676a96cda5f0fe7a110e65525c82c71963887314b9c25ce61cc1267897318b3c459e21cc62c71963887314b9c25ce61cc1267897318b3c459e21cc62c71963887314b9cef9d38e31803b1c621df3a268ca47bde334fdce2d15bccda4f43dac5b8c22f63aaab8c9aa725729ebacc58cdfa02785a806743e43cd9b19ae8fdcc8ed56cb47c5a6ff994803cd8266df4e0670cec52d9b4bf11cec3ddcebcaa0499a56e148759ea863087314bdd10e63066a91bc21cc62c754398c398a56e087318b3d40d610e6396ba21cc61cc523784398c59ea863087314bdd10e63066a91bc21cc62c754398c398a56e087318b3d40d610e63e65037708e0eb1c6215f331346d26df0cc13b778f4966bde8e8b71855fc654571935cfe6e87932ef24d95800cf66e0d9143d4fad273f33739d5eb07cda68f994803cd826bde0c1cf18d8a5b269ff05380fc22ccc2e666cb388350ef95a9830926e93679eb8c5a3b75ced988b71855fc6545719354fab279e170ae069059e2dd1f3d47af233d3f66fb57c7ac1f2290179f0fadeeac1cf18d8a5b2697f2b9c875263c66b8958e3906f331346d26d011e0ff5aee036a9d511c71525c0b8bc04187b9500e37d25c01807460ffdf4cc359cb078687fb3dff8a4a2884f25c4896bbb97001e5fe7b0cae2a972c482eb39ec6d3e399fc32ae0f1750eab2d9e6a472cb89ec33ee693f339acf61bc748dafbfb4b80b16f09303e50028c0f960063bf1260ec5f028c034a80f1a112601c58028c0f9700e3a012601c5c028c434a8071680930fa7ea691eb7b6e6b116c877d3f2b86edb0ef15c5b02d3197984bcc25e6127389f99dda96984bcc25e66f7ecc7d3ccbc5e7c6b4e5fa0ee17abeeb7b4c5e18f930ae62ca883cb1e87892e83bdadac6c077622835c65525c0b8bc0418258ed931d4ae306a9e1d9e78b615c0b30378b647cf53ebc9cfcc5cc39d964fdb2c9f129007ebc14e0f7ec6c02e954dfb3be13c941a335e4bc41a877cad4c1849b71d787c5d5f855cef787dedf2c4b3a3009e5dc0e3e37c79f23373bdefb67cda61f994803c78edecf6e0670cec52d9b4bf1bce43a931e3f54eac71c8d7ca8491743b81c7d7f555c8f58ed7d71e4f3cbb0ae0d9033c3ece97273f33d7fb5ecba75d964f09c883d7ce5e0f7ec6c02e954dfb7be13c941a335eefc41a877cad4c1849b71b783cd4bb82bf73ec71c471790930ae2a014689a3c49113a3c4f1de89a3300aa3300ae39bc1580a6db8dc670a7f3680dfc5dba2e7a9c7ef6df9f0b4018f8fef769efccc3c1bd867f9b4c7f2290179b01eecf3e0670cec52d9b4bf0fce83300bb38b19db2c628d43be56268ca4db0b3c1eaeef82dbfe36471c57f8654c759551f3ec8f9ca73e89f5251f9efdc0e3a34ef9f133dbf61fb07c6ab37c4a401ebcbe0f78f0330676a96cda3f00e7a110e65525c82c71963887314b9c25ce61cc1267897318b3c459e21cc62c71963887314b9c25ce61cc1267897318b3c459e21cc62c71963887314b9c25ce61cc1267897318b3c459e21cc62c71963887314b9c25ce61cc1267897318b3c459e21cc62c71963887314b9c25ce61cc1267897318b3c459e21cc62c71ee1a33ce7127d638e46b65c248ba7dc0b3df034fa1f3f0f73be2b8c22f63aaab8c9ae760f43cf5585ff2e139083c3eea94273f33bf153864f9b4dff2290179b04d3ae4c1cf18d8a5b269ff109c874298579520b3c4b96bccd866116b1cf2b5326124dd01e0f1707d17dcf61f74c471855fc654571935cfe1e879eab1bee4c37318787cd4294f7e66dafe23964f072d9f129007dba4231efc8c815d2a9bf68fc0791066617631639b45ac71c8d7ca8491748780c7c3f55d70db7fd811c7157e19535d65d43c2f46ce934a627dc987e745e0f151a7fcf8996dfb8f5a3e1db67c4a401ebcbe8f7af0330676a96cda3f0ae7a110e65525c82c71963887314b9c25ce61cc1267897318b3c459e21cc62c71963887314b9c25ce61cc1267897318b3c459e21cc62c71963887314b9cef9d38e31803b1c6215f2b1346d21d011e0fcfe30b1eab79d111c7157e19535d65d43cc722e7a94b627dc987e718f0f8a8537efccc8ed51cb77c7ad1f2290179b04d3aeec1cf18d8a5b269ff389c87bb9d795509324bdd280eb3d40d610e6396ba21cc61cc523784398c59ea863087314bdd10e63066a91bc21cc62c754398c398a56e087318b3d40d610e6396ba21cc61cc523784398c59ea863087314bdd10e63066a91bc21cc6cca16ee01c1d628d43be56268ca43b0a3cc73cf0143a8fe898238e2bfc32a6bacaa879daa3e7a9c7fa920f4f3bf0f8a8539efccccc753a61f974ccf2290179b04d3ae1c1cf18d8a5b2699fec09b3308731639b45ac71c8d7ca849174c781a7dd034fa1ed6a3b30bada7e0f8ca9ae326a9e93d1f3d4637dc987e724f0f8a8539efcccb4fda72c9fda2d9f129007afef531efc8c815d2a9bf64fc1791066617631639bd56e3ee390af950923e94e008f87ebbbe0b6ffa4238e2bfc32a6bacaa8794e47cf538ff5251f9ed3c0e3a34e79f233d3f69fb17c3a69f994803c787d9ff1e0670cec52d9b47f06ce83300bb38b19db2c628d43be56268ca43b053c1eaeef82dbfed38e38ae2801c6e525c0b8aa04183dc731d55546cd73d613cfe90278ce028f8ff6c3939f99fbfc39cba7d3964f09c883f5e09c073f636097caa6fd73701e4a8d19af25628d43be56268ca43b033cbeaeaf42ae77bcbe5ef2c473b6009e9780c7c7f9f2e467e67a3f6ff974d6f2290179f0da39efc1cf18d8a5b269ff3c9c875263c6eb9d58e390af950923e9ce018fafebab90eb1dafaf0b9e785e2a80e702f0f8385f9efccc5cef172d9f5eb27c4a401ebc762e7af0330676a96cdabf08e7a1d498f17a27d638e46b65c248baf3c0e3a1de15fc9de382238ecb4b80715509304a1c258e9c18258ef74e1c85511885b130c6ad25c028e75a18b932b67a608c197bc843fbad45b05d65d9ae2aa2ed6acb7675116d4bcc25e6127389b9c45c627ea7b625e6127389b9c45c622e31bf53db127389b9c45c622e319798dfa96d89b9c45c622e3197984bccefd4b6c45c626edbf630dfb4e0f9dc1781e782875878f233a9cbbd64ca7a23c2f8e9585db662d56ac52a01792e41fc2e7b889f6bce35ed93bd4299473060f6643bd55b95d10bfc271babac7868fb573cf91ed6e65d2982edb036af18b6c3dabc62d896984bcc25e6f76ecc315d1174fe0d922ee3aa497733fb947f2b1c47793e5199fdac0ae47cfab02dd790c45c622e317f33628e71995f049ec0e20972f0a499f14c61c653cf8c6702339e31cc789a99f1ac61c6b394194f39339e05cc786631e329c6f3ac4278a632e36960c6b39019cf6c663cd398f13432e319c58c27c98c6704339e16663c6b99f12c63c6b38819cf1c663cd399f16c66c63389194f2d339e91cc782a99f12498f12c66c6339719cf0c663c1399f13431e34931e359c78c6725339edecc78aa98f1cc63c6338e19cf4c663c9399f1d431e3e9c38ca79a19cf68663c4b98f18c67c61363c0130f3acf018fc3ff2f82aecc3ab6879293033afe7fcde8cbe098eb265dee28fb1ae8686ed575c7b118a76be04bdaa49377b665e284b6d2b04ff62a81e33a139ef1cc789630e319cd8ca79a194f1f663c75cc782633e399c98c671c339e79cc78aa98f1f466c6b39219cf3a663c29663c4dcc782632e399c18c672e339ec5cc7812cc782a99f18c64c653cb8c6712339ecdcc78a633e399c38c6711339e65cc78d632e36961c63382194f9219cf28663c8dcc78a631e399cd8c6721339e06663c5399f15c64c6338b19cf02663ce5cc789632e359c38ca79919cf18663c1398f1d433e399c28c27cd8c67be83c7d7bac334de4e65d3fe4526b63d9c87cc7be16e78f2e9a629abbb2997f8c95e05e499600662f4f8101e4b5cf6fc08ecdbdc84185df5e44bd8bb21ae16c176d8bb218a61bbdab25d5d44db12f3f098df8cde760ae71cd116b3f6d390c6ebcec75c2d4f7eded6e645fd2ecc5b56acae5ab14a409e1b10bf5b1ee2e76a47699fec15ca3c820133d68b9a20da7af172f43efde61d9b14d797adf8a25faf788a69585bfa4a116c87b5a5c5b01dd69616c3b6c45c622e31bfb763fe36938eb09f91441bfa3b14dd3fde0676df6ed2b108edeab25e3565d13b4189e3edc04379b6c2773aa97f72cddf0b31b7d3f48c027fc7efeb1952d83929c6f3abb073520cdb61e7a418b625e6e1317f8707dbf1e0f6b512f496eb19c53b80e7550f3c9efcccdc6b5fb37cba68f994803cd8f6bde6c1cf18d8a5b269ff35e0a10ddf13eba31ee473ce91e716339e34339e29cc78ea99f14c60c63386194f33339e35cc789632e32967c6b38019cf2c663c5399f13430e359c88c6736339e69cc781a99f18c62c69364c63382194f0b339eb5cc789631e3798519cf22663c7398f14c67c6b39919cf24663cb5cc782a99f12498f12c66c6339719cf0c663c1399f13431e34931e359c78c6725339edecc78aa98f1cc63c6338e19cf4c663c9399f1d431e3e9c38ca79a19cf68663c4b98f18c67c61363c013f69e58faff2dd0d11839be3bf69d26fd2ae8ca1c3668ace635d055983495a1df3b7b7940e7b2314ebee605a0ad34ec933d7c4fec3b99f08c67c6b38419cf68663cd5cc78fa30e3a963c6339919cf4c663ce398f1cc63c653c58ca737339e95cc78d631e34931e36962c6339119cf0c663c7399f12c66c69360c653c98ca79619cf24663c9b99f14c67c6338719cf22663caf30e359c68c672d339e16663c2398f12499f18c62c6d3c88c671a339ed9cc781632e36960c6339519cf2c663c0b98f19433e359ca8c670d339e66663c6398f14c60c653cf8c670a339e34339e5bcc78e63b787cbd9f2eec9d0fb78a603bec9d0fc5b01df6ce8762d8969887c7dcc3bb6e32ef02c5f742eacd9eeb9286b4e7dff7d4c783dbdfabf3db78f0bd1f3eda254f7e66de41f92e5356cf08cbd5b17a77d0b1e972299e38bf8af220c3bbe198887872be4f84ec09b3308731e33b6989d535f7eecd6624dd6bc0e3a3ddd0be8f336551f9fa1d7d893e1d763dbce7bd5ec7c17ecf3b71b8def3beb97f075bb561ab0c3abf0b17d7bac773e97b2d022adbb51601f9836b11f8baefdfb0786e3862f166dabeeec176a17d8eeb0e9e28dfb3896d0cdaf2f1de77edfbb5207fdf5defa18fd0f7da04f0a02d0fef79cfb45d341f97cad7edc3c83e5e635e8fd73db55de32d9f2b20cf1c68bbc6e668bbca828e6b06df535e16747ef7fb1b466f975113c8f7291fb6e53b2ccf987be89b14fc1d16d76388be9f91cab473370ae0b9063c3eeeb79efa53494ff7a4cc77d82b56ac6e58b14a401ecff7ad4cddbe66f1d03ed91366611666611666611666611666611666611666611666611666611666611666fecc381e4cac386e7b8b0923e970ccdac7737eedfb04531695afc746bfd0a7c36ef4e316a924ce51a071db0996cf1590a74fbf0eb6afc0b8ad3daf21ec5cfa5ae73dec5c92bdcaa0f33c149fe3746173608a31465888ed9ac86ca736f839bfa964ef20bbe6f70deb9cde729c4f1f6d05ce9fa22dd758e315e0f130165beb6bee88f6e9b2e5d375cba704e4c1752c2e7bf0d3755fa3fdcbc0431bae93e7eb9e11583c81233eb49531e34933e3e9c98c670a339e7a663c1398f13cca8c670c339e66663c4398f1ac61c6b39419cf00663cf733e3e9c58ca79c19cf02663cb398f14c65c6d3c08ce731663c4399f13cc48c672c339ebecc78ee63c6b390194f05339ed9cc78a631e36964c6338a194f9219cf08663c2dcc786a98f1ac65c6339019cf32663c0f30e38933e359c48ca71b339e39cc78a633e3d9cc8c6712339e5a663c2399f10c63c6f330331edfe3e885f23cc88ca792194f8219cf62663cdd99f1cc65c63383194f13339e89cc7852cc788633e359c78c6710339e95cc78fa31e3e9cd8ca78a194f0f663cf398f18c63c6339319cf64663c75cc781e61c6339819cf4d663cfd99f12c61c6339a194f1f663cd5cc78c633e38931e089079d7feb1187ff5f07dd6593c6dfb39539caa3797a945ff7ab5e1ed0b9ec3247d9571c0c18a74be04bdaa49377b6ddf63b8c982997f6c95e25705c61c2339e194f35339e3ecc784633e359c28ca73f339e9bcc780633e37984194f1d339ec9cc786632e319c78c671e339e1ecc78aa98f1f466c6d38f19cf4a663c8398f1ac63c6339c194f8a19cf44663c4dcc786630e399cb8ca73b339ec5cc7812cc782a99f13cc88ce71a339e8799f10c63c63392194f2d339e49cc783633e399ce8c670e339e6ecc781631e38933e3798019cf32663c0399f1ac65c653c38ca78519cf08663c49663ca398f13432e399c68c6736339e0a663c0b99f1dcc78ca72f339eb1cc781e62c6339419cf63cc781a98f14c65c6338b19cf02663ce5cc787a31e3b99f19cf00663c4b99f1ac61c63384194f33339e31cc781e65c63381194f3d339e29cc787a32e34933e32963c633dfe2c1ffebeff634be7a1974f4ffff6b3a0755c68fcb96bd08fc4886adfde02b66b8a51d31095bfb81034f9a194f4f663c5398f1d433e399c08ce751663c6398f13433e319c28c670d339ea5cc780630e3b99f194f2f663ce5cc781630e399c58c672a339e06663c8f31e319ca8ce721663c6399f1f465c6731f339e85cc782a98f1cc66c6338d194f23339e51cc7892cc785a98f1d430e359cb8c6720339e65cc781e60c61367c6b388194f37663c7398f14c67c6b39919cf24663cb5cc784632e319c68ce761663cd798f13cc88ca792194f8219cf62663cdd99f1cc65c63383194f13339e89cc7852cc788633e359c78c6710339e95cc78fa31e3e9cd8ca78a194f0f663cf398f18c63c6339319cf64663c75cc781e61c6339819cf4d663cfd99f12c61c6339a194f1f663cd5cc78c633e38931e0095b6b81fe5f0eba8b267d1374174cfa1ae8ce9bf465d0bde4d0953958c8de45d0d13c850ba0a3b18df3a0a3e721644bf7e75e1bd099b5cce153b983f582c3a78b8e63f13cd231e920daf388b6d2b04ff62a81e322139ef1cc78aa99f1f461c6339a19cf12663cfd99f1dc64c6339819cf23cc78ea98f14c66c6339319cf38663cf398f1f460c653c58ca737339e7ecc785632e319c48c671d339ee1cc7852cc782632e36962c6338319cf5c663cdd99f12c66c69360c653c98ce741663cd798f13ccc8c6718339e91cc786a99f14c62c6b39919cf74663c7398f17463c6b388194f9c19cf03cc789631e319c88c672d339e1a663c2dcc7892cc784631e36964c6338d19cf6c663c15cc781632e3b98f194f5f663c6399f13cc48c6728339ec798f13430e399ca8c6716339e05cc78ca99f1f462c6733f339e01cc789632e359c38c6708339e66663c6398f13cca8c6702339e7a663c5398f1f464c69366c653c68c67bec583639849d051ba1674944e818ed275a0a3743de828dd003a4a37828ed2934047e926d0517a32e8284dd7483ce8f0bd18efe1275b5436ed5f02469acfecbaa6a702f7254ba7b9cf79e2be6471d3fe396074f9426cd380fb9ca5d3dc673d719fb3b869ff2c30ba7c21b6e9a0a3f40cd0517a26e866823dd2517a16e8283d1b74949e033a4acf051da5e7818ed2f34147e905a0a3f442d0517a11e828bd1874945e023a4a2f359ffa1c9fb574fa1c9f31e97410ed39265b5436ed9f0146d77927b665c07dc6d269eed39eb8cf58dcb47f1a185dbe10db4ae03e6de934f7294fdca72d6eda3f058c2e5f886d0d709fb2749afba427ee531637ed9f0446972fc4b616b84f5a3acd7dc213f7498b9bf64f00a3cb17625b07dc272c9de66ef7c47dc2e2a6fd766074f9426ccdc0dd6ee934f7714fdced1637ed1f0746972fc4d602dcc72d9de63ee689fbb8c54dfbc780b1dde10bb1e17b17377b62bc6931de2ca2edb0be57316c87f59f8a613bac0f540cdb61f7e662d80ebbbf16c376d83db218b6c3ee73c5b01d76af2a86edb0fb4d316cb75bb6db8b685baeb1e25f636f669b7aaf5e636f66bbd66ed96e2fa26de933499fa958b6a5cf247da662d96eb76cb717d1b6b4a9e16daa87e713a938d8a02d66eda7217d0c787c3ce7f1e46752977bd494f54684e5ea58bd68c56ab315ab04e4390af17bd143fc626097caa67db2578acc582f62d1d94ec6c106be23ee08950fbac3265d0bba43269d02dd4193ae03dd0193ae07dd7e936e00dd3e935e0cba36935e02babd267d0e747b4c1ac77b769bf459d0ed32691c5fd969d26740b7c3a4713c63bb499f06dd3693c6f183ad267d0a74ad268dcfebb798f449d0bd60d2f87c7c93499f00dd46936e06dd06936e07dd7a93de0cbae74dfa38e89e33e9a3a07bab493782ee59939e04bab7987413e89e31e9c9a07bdaa4f11d85ab4d1ac7be5799f405d03d65d238d6fca4495f02dd0a93c6b1dde5263d1d744f98f40cd03d6ed23341f7b249a741f78a49cf02dddb4c7a36e85e35e939a07bbb49cf05dd3b4c7a1ee85e33e9f9a07ba7492f00ddbb4c7a21e8de6dd28b40f71e93c67180f79af431d09599f48ba0a3b9a7474047bfa7380c3afa0de521d0d17b130e82ae87491f001dcdc7d90f3a9a63ba0f74f799741be8e226bd17749526bd0774f48e82dda0a3f700ed021dbdab6827e8e87d803b4047ef2cdc0e3a9a87ba0d74f45b86ada0a3df2fb6828ede11b00574f45ea0174047efbadb043a9a6fba1174f41b810da0a3df05ae071dfdf6fe79d0d1fb769e031dbd43eeada0a37993cf828e7e0bf016d0d598f433a01b66d24f836eb849af061dbd2b6e15e868fedf53a0a339ff4f826e8449af00dd48935e0eba5126fd04e8e89d8b8f838ee641be0cbab126fd0ae8c699f4db4047efdc7c1574346ff0eda0a377d5bc0374742f7e0d74742f7e27e8e85efc2ed0d1bdf8dda0a37bf17b4047f7e2f79a4f7dfde9ebf2bad94f07d1f57bb4bd1bc1ed5baebe3731204f947dd904f0a0adab91fb9ecaf49ba9bf5566caa57a70156c5f8edc76b6cf7ec594d5cd947bd9b25d017986f4eb383797e0ff69f0818ec33c5436ed4f80632f596557197faf78f2f7b2c544dc578089f20cefd791f7b326dd138e89902df3fd93ea5a0031c42d0d695c232dfa58a532df07ae15c0730578a2bf4eb2df877dd409bcb6a2fe3e6c3fcbb0eb5a02f25c86f8f99adb79c5e2a17db227ccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccfc99350f8d27e07c1eca779d0923e970accbc7737e1c4bc531af8fc0b88eeff1bdeea6dc8996cf1590e7ffc098d3c74cba12fe4fe72dec5c7a1827cc792ec95e25f88363413ec68b63608bcabeea880507db3591d94e6df0737e53c9de41767cff9a754eaf5be713c7c5f11afa2cd4533ae696f98c437c6e417c3c5ce339cf0dd9c36be92ae8287d03187dc41aef25d41e4c30fb640fc7c5bf6c8d8b47df56a7923edb8d8ba62c7bbc1d7da53cdf80b6ef9b268d7343ae43593f73fc9fb65ce3d4143fedf3f9e87dce9cdf974c59747ecf3b6c9f03d6886cd7a2ed9811b243fa0a48ff14e673d8bf27a25813bbbe46680e26b2dbc7ddb08e4b409e0b0effd341b4fe9fb778ce5bccbaee7c1bead9cfe0feefab4dba1012a3091023ca83fd200ff34c9c6d2471903d9d87ce7f0f2b0ff65928cfafa18dd2be503b4f7ee2dc16bc075cf4e4df75cb3fda277bd837be028cb68fba7e7ca14f07efbd3effebbf3ccefffa2fa843384f2bb0ca9f08e513578f20fcde427962fd3bcaf739bfec9ae533b15c01a6dfe4e9df91779a4917d2d77fb3beb785f5f57dbc13301edcfedd5b6fb9eeef788ff1d1be78f233e9ba775db27c4a409e11e0a7877e4ccedf019e07dbbede034936a80f75d98a4505e4e90fd776ae38e277d52b45f125e5ec0f4e74f84279065bedd44b1e987c9e37ec67e972af3a7ca53cc3a1fd7bd4a4e3709eb02dad73fc9fb65ced01c54ffbece1fd7e99f34bbf01a3f37bc661fb14b04664fbb6dfa4537f9fec90be02d2a9fe1d79eddf9353acf13d7ef45b3964b78fbb6c1d97803c671dfea78368fd0f7b1f00d9d3756724d433aa473edbcdb321319a0831a23cf86c85eeed943fecbeef637e75aefbfe5560b4db4decbbf864bb66b1d9cf505dfd41ca43c7627f7016b4b371475effcf86b37d9b42e6fc7b7e465e1fb3e299063be3414ff593e24cffc33e2ee55962ddcf7cf5592f5bdce4078ee15cb4b82f5971c56751cb81db756dba9e757aea73d6635fccee0f5d0476cab3daea0fd9fdb89b0e5fecfb7459d0f9bbe01b565ebc26731d67a7af5bc7e03303d73359fcadcb0560499b74f24eb6da641299ca1cb148049dbf93b99e33d07580758ecab2af153ab602f26cb4da243b6fe65ed6a7233e741ef159bbab4efa7a8e14f69c85ec6946d7efe8a26fbbeecddf2bf58cacdcc9eb4b718cbba7958ec676aa05ef15b96271d1c1e3eb9966582c2e3a6c47178bc60daefb872b16171c3cbebe6386c5e282c37684b1d8e47ab6e08ac579078fafef1a61b138efb01d5d2c26ddf65c23572c5e72f044ff4c23772c704cac10e60b0c987b5ae9686cd7af778dddb96271cec1e36bec2e2c16e71cb6a38b456da3eb3bbb2b16671d3cbed605098bc55987ede862d134d9f54cc5158b330e1e5feb6784c5e28cc37684f562233e5fcb158bd30e1e5f6b7284c5e2b4c37684fdc3c65ccf0c3116a71c3cbe9efd85c5e294c37684b168d6b64fe6118b930e9e93458ec54987ede862b1be41db3e91472c4e38784e143916271cb6a38b457393b6dd9e472cda1d3ced458e45bbc37684dfa132f5e2781eb138eee0f1b56e4a582c8e3b6c47178b964c5feb581eb138e6e0f1b5164b582c8e396c47178b64e69e7a348f581c75f01c2d722c8e3a6c47582f32df275fcc2316c57cff68582c5e74d88ef03e92a91747f288c51107cf9122c7e288c37674b1d89479fe74388f581c76f01c2e722c0e3b6c47f8cc25532f0ee5118b430e9e43458ec52187ede8625197b9a71ecc2316071d3c078b1c8b830edbd1c56263664cec401eb138e0e03950e4581c70d88eb0df99692ff6e7118bfd0e9efd458ec57e87ed08fb9d99e717fbf288c53e07cfbe22c7629fc376846d67a6dfd996472cda1c3c6d458e459bc37684fdce4c2cf6e6118bbd0e9ebd458ec55e87ed08fb9d99fbc89e3c62b1c7c1b3a7c8b1d8e3b01d61bdc8b49dbbf388c56e07cfee22c762b7c37684cfb5326de7ae3c62b1cbc1b3abc8b1d8e5b01de1f791cc33be9d79c462a78367679163b1d3613bc2b1a24c1f7c471eb1d8e1e0d951e458ec00db3ee699602c682ed6382b161590e701f332769a8b1516472a03e795a12fdb23f7253baf6c5b882fdbc117ca33107ce909fa28993cf99aa9335b4d593437fd86c357ca33744047de61261d87737213ca4a3afe4f5bae3948143fedf396e87dced4d5174c59747eb7386c6f02d6886cd7a26d9a9b4e76485f01e989033af2523e8a07c59ad8f535426b2520bb7ddc0eebb804e46975f89f0ea2f57f8bc5b3c562cefcee01ea19d5233f6d5796a9352446e320469407e7ecddf0c463cf21240eb2a7f3d0f9ef61e5c1399494a709da289c574a7ec683cef326b57f5b3df917b68e1bd94b80ee0a30da3eeafa9180b99fb5c41874e8686d075c83a9d1d2695f2779f2956c51d9b43f091869ad89c6e233a6f2656cb01835cf640f318b835dda72dd2f26034f93071e4f7e66ee43532c9f26593e25200ffeb6718a073f636097caa6fd2960dbc739c758d03d7994158b0ac8b3daea3f86c591cad0f5b7d1e18baf3836583c0d0edbd33dc791caa636717a116c4fb56cd75bb6f5b58d754c6fb9aeeda9c03ccd03b32e7746f4e566ae6d5a238dea33d9a9079fd21083a87c42db31ab6cd257407afb80ce0c140fba7712bbbe8eb0ee841d37d93a2e0179a63bfc4f47ecff0c8b07cfb1de74bf613df42b3d5c0f993a30dde2a0fd7a88dd8c90d84d87d8519e46d0511f670ae8a8af806b0ad2ffb11fd110bdbfceb687f61b809174b84e618383b13e7ac654aeb6b91e1849370d78a67a8ad9348b6794151fbc2ff7b0f2d0b11590a71dee8d71475e5df7ab621d7ed1da8511aef3936957bb7b8817aeab18407c022b86b41143cfa063edc52879ee0b606dc5b69d7b9a376f7c726376e891d02a2c4cfc8c39dc28031da6cb1dba20b87d09c90ad0d11292dd405766850597aea4fcb4a49d8f70613ca8ec0a8bb327b044691b97dfa42d57d5e9013c3eaab2ae3a95a62c53759edeb3a56d23d68f6e166757ea8efe5f798e7c6165513da8f0e03b3251d9b44ff6747c1226bdab79c3d6597b36efdbbe7147db5e84b52f2e4cc7ac20d89fae63b092e0c544e574b382d32bfae0d4e3c56bf305602f0096c0f0f48c9e27535169cdd60dcddbb62ddfb77edb960df3f7edd8d0b665e70e8c680f2b7261d1b62f79bdb99a3acc6be7efeed0d91bae90db0374b4426e4fd091fd5ea0238efbe07ff699f0724d8c80f2a91aebff551887bb1b87a80ad26d48b727fa9ae91d646ffffac95875903d7d7a895dbda4ae5e4257bfc141ffaa5af714f412b87ac95bbdc4ad5ed2562f61ab97acd54bd4d604d925688707d925661f0d3a9690d5db6780572f19abbb1a7a4958bd04ecd820fbb86e7c907db5997e9584eeb2eaafa3ba9ba7bf5ae82e97ee6ae96eadfecaae1fdfe86e8cee22eaee8feeb2e86eb0eefece34b19e15649790d64b46cf0db24b42cf0fb24b3e2f0cb24b3a2f0eb2cba12f0db24bd33e116497335f1e6497b9d5cbdfea6571f5d2e57ac95cbd94ae5e62572f51ae97dfd5cbf2ea65c8f592bd7a295fbdd4b85ee6f7f920bb9cf8fa20bb64704b905d4e583fbad6cb87ebc7f6fa71b67e54ac1f65eae1043d8ca21fb3eae13f3d1caa8787f570b99e3ea0a753e8e9257aba8d9e7ea4a763e9e9697aba9e9ebea8a773eae9ad7abaaf9efedc1e64a7c79f0cb23f9fd03f27d13fafd13f37d23fbf7a29c8fea450ff444fffe454ff04f772907d84aa7fcead87d5f4a353fd18593f5ed58f7af532bd7a595ebd0caf5e76572fb3ab97d5d5cbe8ea6573f532b97a595cbd0cee7b95fc8e92df55f23e25bfa7e4fd4a7e5fc91f28f943257fa4e4034afe58c907957c48c99f28f953257fa6e4cf957c58c947947c54c95f28f94b251f53f2574a3eaee4134afe5ac9df28f95b257fa7e4934afe5ec93f28f994924f07d9faf75925ffa8e49f94fcb3927f51f239259f57f205255f54f225255f56f215255f55f235255f57f20d25ffaae49b4afe4dc9b7947c5bc97794bcaee4bb4abea7e4fb4a7ea0e4874a7ea4e4c74a7ea2e4a74a7ea6e4e74a7ea1e4974a7e15742c038d8dc5ff373bc3cc7e735bdbc6edbbda6ada76d66cdfb7ad6dcbae6d876a0e6c697ba166e7fe8d7b366ddb79000ffea0699e68bdea597bf6341faad9b2a365e3c19a9dfbda6a766eaa59bf73df8e96db6e8e9f33070dea6cb1b9a525dcd877caee80f4fb5d34fa6b731cad04be28b76fffab2b01f97f5d39686079d71cfab8e9dcd1d7aea7b27dbc9abddb76b6d5246b76a8bfea66baf3c0c6960935f8bfbd2ac87bdb6af6b635ef69abd9b467e7f69ada0958eef8de5d70a2b5b71f98c1e65d405daa2a5fead7054ffe47bfae9d8effbc13525a4fbe50a3fdfa77c1c3415d3928dd45c2c5fd43c3b277dffab63dcd1bdac20f5e762707afea8a9b2d5d74b3ef802e187ba82b074d1ad035c2555d3176bc0063c17f03d9f72ad92c930400", + "bytecode": "0x1f8b08000000000000ffed9d0774154796f75b4280f0d3b3088e045b3860c004e9492449c023679325030e801019e3210c382272c618b0c946e0999d4db339cfe69c739cd9303bb333bb3b3b73ce37bb5ffecef1f9aafad51dfd55543ff4e4aec77dd2ed734aaffaaabaefaffe7dab3a5577170599e93b2a15997c0f959e0eee9ee8ff69f35bf9e9a6aa18d755e993b3a840388b0b84b347817096140867cf02e1ec55209cbd0b84b3b44038fbc4c8a9d98a83f653dcbc0f78d0356ec64481695a56009a260b4cd3070b40d3f2a030faa8be05c2d9af4038fb1708e78002e17ca840381f2e10ce470a84f3d102e17cac40381f2f10ce8105c239a84038071708e79002e17ca240389f2c10ce8a02e11c5a209c4f1508e7d305c2f94c81703e1b23e708e01c667e9f33bfc3cd2f9519697e9f37bfa3ccef6853c712333f46a5b19a4da52aeb7f2995aa55aa51699cf5bff12a4d5069a24a93ccff2accff6a55aa53a95ea5c92a4d5169aad1619a4ad3559aa1d24c9566a9345ba5392acd55699e4af3555aa0d2429516a9f4824a8b555aa2d2529596a9b45ca5152aad54a941a546955e546995c5b25aa5352abda4d2cb2abda2d2ab2aad55699d4aeb556a5269834acd2a6d5469934a9b55daa2d25695b6a9b45da51d2abda6d24e955e57e9332aed5269b74a7b54daabd26755daa7d27e95deb0347b53a5b7547a5ba5772cce77553aa0528b4a07553aa4d261958ea87454a5632a1d57e9844a27553aa5d26995cea87456a5732abda7d27995de57e9824a1755baa4d2072a7da8d26595aea87455a56b2a5d57e9864a370d0b35848f54baa552ab4ab755baa3d2c72a7d4ea5cfabf47d2a7d41a5ef57e90754fa41957e48a51f56e98b2afd884a3faad28fa9f4e32afd844a3fa9d24fa9f4d32afd8c4a3fabd2cfa9f4f32afd824a5f52e91755fa25957e59a55f51e95755fa35957e5da5df50e93755fa2d957e5ba5df51e97755fa3d957e5fa53f50e90f55fa234bf33f56e94f54fa5395feccfc8fae83fdb94a7f61f27f697effcafcfeb5f9fd1b6b99bf55e9ef2cdb9755fa8a65fb7b95fec1e4ffd1fcfe93f9fdaaf9fd67f3fb35f3fb75f3fb2fe6f71be6f79be6f75fcdefbf99df7f37bfdf32bfff617ebf6d7ef53dd49b8333f9d2a06d4a0731f54935cdcdfa1e0a893d2c683f692d7a98ffd16f85b1979879fa25ed7a9af99e96bd9799ef65ada7d4cc975af67e66be9f651f60e60758f687cdfcc396fd5133ff28d813015c4b35766deb614c4560a3382c065bcfa0bd26dad68b5607b6de417b2db48db6632fb0f531b6de607bc0d84ac19630b63ea4994a65c6960ee28a89ca757abdc9b8d76bee2f3d183f6f935e6fb927debef1f336ebf5f6f3c0abe3a3bf59575f889b01c6d60f6c0f195b7fb03d6c6c03c0f688b13d04b6478ded61b03d666c8f80ed71637b146c038ded31b00d32b6c7c166babd6020d88618db20b03d616c83c1f6a4b10d015b85b13d01b6a1c6f624d89e32b60ab0d1d895a1607bc6d89e02dbb3c6f634d8a84f7d066c74ccf7acb1e97ea267112c63ecd44785cb503f0cb6e1d407836d04f5bf601b497d2fd89e07df641b05fd0ad9461b1bf551fa7f134d3e1dc4d52652619b9814f77ad59af57aebe25f6f783fae3e68d3350d7e268156934d3ec6313f55e8bbc824f243f612c8cf85b2548ef4a0fd0cb1ebfd49adc94fceb2dc446bb92494a975d43f1dc45bff3a8ba7ce62ee09793f315b9d9298edf09473cc3640593bf6e898a72bc6ec02e0f010b3e325663b3ce51cb31ba0ac1d7b74dcdb15637615707888d9757e62365529319bb9fe1504eed8a3739fae18b39b8023fe981d2731dbf129e7986d81b276ecd1f96f578cd9bdc0117fcc4e5827c7061d9e728ed97350d68e3dba16d31563f630707888d966e9673b3ce51cb337a0ac1d7b745db02bc6ecfbc0117fcc4ef214b3d512b341e65e6610b8638fae5177c598bd051cf1c76c935c9fedf89473ccfe1c94b5638fee9774c598fd2270c41fb31b7c5d9f4d49cc66c67004813bf6e8de5d578cd92f99bcbe37f697e6ded81360fb2b637b126c7f0d630fc8f637c63614eae5a10d4c9436d0e129e736f0b750d68ee5a74cbe2bb6813f020e0f31bb4e62b6c353ce31fb4d286bc71e8d69e88a31fb15e0f010b34d12b31d9e728ed9ff0e65edd8a3f1355d3166697ca83e5ef84773bc301c6cff646c23c0f655631b09b67f36b6e7c1f635631b05b6af1bdb68b0fd8bb18d01db378c6d2cd8be696c9560fb5763ab02dbbf195b0a6cff6e6cd560fb96b1d580ed3f8c6d1cd8be6d6ce3c1f61d639b606cfa3e168da9fa5d632b05ae7410dfb64d8006341559f369c857f9e5a94c020ffaaa8edf57b5ae7b2ae878ddab81a7c643dd13e0a3233c35c0332e7e9e703ce9f8f8d71b6ee394a569027ca5a05e133cd4ab087cd1ba699efc25c1866d7a828331f6fdb3da8f16812f5a37cd4f0446b2611f437d2eb51fdd370f296ae3f5d096c2fd33fa4b0307f92b8132e306b7951d6ad8cae0ffd8df8eb36c9ee2328c0bf245eba679f25706f519977fc65447196b2c465f7d4411f8a275dbbecb205fe9579fac3ce399f8aef5e4dbeed348f3da3cf89e68f9aeb67c63df4953b67ddb4460f6709e52753fce53f0f881c379cacca2b6b2f6f906f5c3b99ea74cb096e3789e3209f6851eda431803b51607cd5783767511dad5827654e639d0ce573f3ec9e2a1f971c043fd37f6679579e6a964e01b8f6169bbe1b9141e07f8da5e951623cdbbb6d74460741dab78389fc97aac52038c64c3eb38294f9a456dd71413df1e6225ec8fc8071d9b53fb257f255066418fb6b26ba1aff41123188f3475f49c37feed940acfc16b72e0c16de7e1bcaaca533c56e2f59b4f827863cdee976a2cada2aef1f8eacb53160fcd933f61166661166661166661166661166661166661166661166661166661166661e6cf8cf79370dc16951bc784d11effe6eb3a7ff88e3db32ebc07f45dafe3c15295381686c6418cb0ea5c0265ca8bdbd8fe078c07b3c712456d4b1f6363b36d4bf287e3c1f2710fb1dae2b17d9739f4c1fbd2a899af3150769f41f3383e8df4ab041e5fedb1cae2b17d639f9162aa59543feb6b6c41549cb9c61356c4e63bd5e4ebbeae7e9f997e27a8bdff1a67691abe6bd4b2e93ee9851e6df5f6719f37d7fbceb8dfa07c9cf77193c083bee2ef6753edc6271407edf71518ebbec66a51bba2b111b596ef122833a4b86ddbd4c1ffd3c1ddfb062c43eba6f911b06c9db5ee727ff5cd3a0ea516b829dfcbaadb78e0a6324fc1befbcf4cded33e3095eb3312b84f8e7fff92192f92ca8107f7773e8e593ced472b311ee31e2f628f83741d2f53191c43ea61fc6ed67d31f91366611666611666611666611666611666611666611666611666611666611666fecc9ac7be878ef77eab9930e6698c4d783f83dec586f7c57eb2b8cdafef7b8074cf69a455677c46398067947fd6b0e1d8077caf946b5bfabab716b52dc91fb7b10f650e7db466750ecdea3d31da7d06cdd70323e957073cbeda63d4bb3b5c7d462553cda2fa591f6317b2c5996b9c42456cbe33e3457cdcd7a5f122f6fecb7eaf118e93201bde078f7a5f589565bbdf7d806b5c1be5f19d0bf1f79ba976f780edb182e40fc7497cc5684be324e2ef0752953ef711d446694c48ca51572af3d5e2b6b25f33791c2b540debfaaee3ff34651b93807dea94f8eb1c6edfa9665db47da7387ca7813526df55e8bbc85a37d94b20ffdf8aef66203d486b62d76d04df6315b55c8db55c12ca4c76d43f1d73fda7583cb88df5a463e71b1067df85633d5f7dd2e4088d46804654c6f37b609de37cedb1cad88ff6b6cad0b2f87ecbff037d54d49874d73ec0d7f142d43e008f17ecfd4247c68e77f7f1807dcc79888ff180b4eef2a0fd98bcc05aff48583f71f50ea2f72ddf3b1787f5fb1cb37eaff75eb9cefd8817c71b5299fe70ee37d3e47339f7bb5fe7f1ae733f5c2eaaeed82fc4bd6fc47844167c5f2495196cc5635d04f744c7b24f462c4b5ad9ef3ec4f3523c4688ffbd9199fe668a55176a5393a12e54e659abddc47fcc9439fef4f58e4c3ad6a13ea8ca51572a3312dada28934fc076c2fd429de3ff34653bfe24fd749da7c55fe770fb4e37eba2ed3bcde17b06b0c6e4bb0a7dd3f127f9217b09e46b617f42e5480fd29ad8cb8013d9ede56aade5925026eda87f3ae6fa4fb378a659cc3a76c6429cd5c1b316befaea74e0d6682468f43d7f6073bdd7d8b58ff1f53c5ad43ea60a18ed7e13f793f97c56cebe7eeb3a3ea132780c4d65e6413f9b7094b5af4bd372718e4fc7e781f0b8109f07f2758e940cdaeb99b4387cfa2eb77c97e7d1773fcb77bf3cfa16cd45734e9a73fae60fee5b8a81d1c779235e1fe90823be8f8096eb018cbe9ed94ce5c0580d8cb8bf23460fef57aeeaec3785f058a72730fa78de38d7ebd5f87e737cc70031fa78463bd7f754e373dbb45c6f60f4f15d23fc865247185ddf3a2a855f0fdf35aaeaec7740f05b477d80d1c7b7411241fbef99dc8b711230d2720f00a38ffb4889a0fd75b57b31e2fd4a5a2ee19931dbbeddf3d89f54aed720f231ae20ea58037d7bb8fe9fc2b1091dd1a2de2f4fd6631ff4ede1fa57a8457dd0712df0fe9c877ba3613b9e9c030fde43a4e5fa03e3544f8c5372609c0a8cb4dc00604c7b629c9a03631a1869b98780d1c375c890319d03235eaf23fbc3c038dd13e3b41c18a703232df70830fab8a69800bf1d619c018cb4dca3c038d313e38c1c186702232df71830cef2c4383307c659c048cb3d0e8cb33d31ceca81713630d2720381718e27c6d93930ce01465a6e1030cef5c4382707c6b9c048cb0d06c6799e18e7e6c0380f1869b921c038df13e3bc1c18e703232df704302ef0c4383f07c605c048cb3d098c0b3d312ec881712130d2721505c038b400189f2a00c6a70b80f19902607cb600184b0b80f179605c143f63789eba3007c645c0f342fc3ca1668b72e079c12f4ff87ec2450e5f8be3f795cab5ee8b816749fc3ce1b6589c030f312461b917fc32a63acba87996c6cf136ab624079ea5a0d91287661e18539d65d43ccbe2e709355b9a03cf32d06ca943330f8ca9ce326a9ee5f1f3849a2dcb81673968b6cca19907c654671935cf8af87942cd96e7c0b302345beed0cc0363aab38c9a6765fc3ca1662b72e059099aad7068e68131d55946cdd3103f4fa8d9ca1c781a40b3950ecd3c30a63acba8791ae3e709356bc881a711346b7068e68131d55946cdf362fc3ca1668d39f0bc089a353a34e3c4883c71bf6fbcd1e16b1583ba130332f62900c6070a8011c720f8e8bfb28d4168f4ab4faab3faf8da5ed9c620a0efd59eb45815745c8bd57e79b28e4140df6b3c69b13ae8b8166b80e7250f5a24c0474778882109cbf52f00c60105c0f85001303e5c008c8f1400e3a305c0f85801303e5e008c030b80715001300e2e00c62105c0f84401303e59008c2f7a66cc76fef25217f71d75aed2d57d479d977475df12e712e7ddc1b7c4b9c47977f02d712e71de1d7c4b9c4b9c7707df12e712e7ddc1b7c4b9c47977f02d712e71cec9f7cb1e7c27c0074dd9aef1134312967b5118bb3423f254c4c7538975475faf30a8fb2b0e9e224f75475faf32a83b31141ae3cb05c0f86201308a8e9931889d61d43c6b3df1bc9a03cf5ae059e789676d0e3ceb80677dfc3c614cadcb81871892b0dc8b05c0f87201308a8ea2232746d1b1fbe8288cc2288cc2783f180ba10f97fd4ce6dca5338c9aa7297e9e50b3f539f0348166b4dc0b7e19539d65d43c1be2e709356bca81670368d6e4d0cc0363aab38c9aa7397e9e50b30d39f03483661b1c9a79604c759651f36c8c9f27d4ac39079e8da059b343330f8ca9ce326a9e4df1f3849a6dcc81671368b6d1a19907c654671935cfe6f87942cd36e5c0b31934dbe4d0cc0363aab38c9a674bfc3ca1669b73e0d9029a6d7668e68131d55946cdb3357e9e50b32d39f06c05cdb63834f3c098ea2ca3e6d9163f4fa8d9d61c78b681665b1d9a71657cb100185f2e0046cf3aa63acba879b67be2d99603cf76e0d9e189677b0e3c3b80e7b5f879c298da91030f312461b9170b80f1e50260141d45474e8ca263f7d1511885511873637ca50018655b0b2357460fe757599f4fd9d1c57d473d9fd2d57d473d9fd2d57d4b9c4b9c7707df12e712e7ddc1b7c4b9c47977f02d712e71de1d7c4b9c4b9c7707df12e712e7ddc1b7c4b9c47977f02d712e71de1d7c4b9c4b9c7707df12e712e7ddc1b7c4b9c47977f02d712e71de1d7c4b9c4b9c7707df12e712e7ddc1b7c4b9c47977f02d712e71de1d7c4b9c4b9c7707df12e712e7ddc1b7c4b9c43927df3be3f79dcaf519d69dc0e3e3995a4ff5acd4eb7dddaceb9318f5d35a7dc6d26a87a55512cabc0efa7dc6837e45e097d64df3e42f57e6610c983df94e3da8d6d107ea4f3e5eb6f4d0fe7779aa7b545fbfab8bfb8eeaebbbbaefa8bebeabfb96389738ef0ebe25ce25cebb836f897389732ebe315f12b41db7d3fb95f43a769b7c4f334fe55f81e5a8ccbcde99dff240da900fdfd286645fd11d7c4b9c4b9c7707df12e712e7ddc1b7c439bf38c7789897079ec0e209b2f0e4e3fe412e3c6398f1cc60c6339919cf04663c55cc784632e3d9cc8ca79919cf7a663c3d98f1cc67c6339319cf4bcc78a630e399c88c27c58c672b339e95cc789631e319cd8c6731339e5799f1cc62c6339519cf1a663c9398f15433e3d9c68c670b339e61cc783632e36962c6b38019cf5a663cb399f1a499f1d432e319ce8ca78619cf76663ccf31e36964c6d3c08c6739339e25cc78ca98f12499f12c64c6338719cf34663c75cc78c631e359c58c6713339e0dcc78d631e319c18ce741663ce5cc78c632e399cb8c673a339e7a663ce399f15432e359cd8c6705339ea5cc78fa32e3e9c78c6711339e51cc788a18f02482bbdf719280ffef045bb1b5ac7e2ceccdc16dffdf63ecc5b0cc5e93efe158f71eb0d1b3667b1dcba24e7ba02e6993affc7453a813fa4ac33cf92b038ebd4c784631e359c48ca71f339ebecc789632e359c18c6735339e4a663ce399f1d433e399ce8c672e339eb1cc78ca99f13cc88c6704339e75cc783630e3d9c48c6715339e71cc78ea98f14c63c6338719cf42663c49663c65cc789630e359ce8ca781194f23339ee798f16c67c653c38c6738339e5a663c69663cb399f1ac65c6b380194f13339e8dcc788631e3d9c28c671b339e6a663c9398f1ac61c6339519cf2c663caf32e359cc8c6734339e65cc785632e3d9ca8c27c58c6722339e29cc785e62c6339319cf7c663c3d98f1ac67c6d3cc8c6733339e91cc78aa98f14c60c6339919cf0c663c6398f1ec64c633cfc1e3e1fb79210f8d57a575d3fc4e26be3d6c87f0bb819ff554a77d665dbdcc7a899ffc954099457d32bf7abc0e2e4b5cf6f8628cd57da0d16e4f75897a27f3ee2eee3bea9dcc5ddd77d43b99bbba6f897389734ebef7c5ef3b85cfa6d05464cda7218ffb171fcff478aa67bb7d7bdcdf04de6f69b5dbd22a09653e0bfaedf7a09feb7881e6c95faeccc31830635c5404f1c6c51bf1d7e97bdf1a265ddfb0f4c57abde949d3a87dc89b5ddc77d43ea4abfb8eda877475df12e712e7ddc1b7c4b9c47977f02d712e71cec9f75b261fe3796325fad0d77ee97ce02df0fb8ec917c5e857afeb6db32efa363271bc033c54e647e05ab4b47969f371f9967d9bc47977f0cd39ceed3cdd43c4f776fbbac71b158bf9b8bf7c3f7d47c56257f71d158b5dddb7c4b9c43927dfefc6ef3bbc87b833683f65bb87f82ef0bced410b4ff50ccf9d0e5875da69d5290965f05cee80877a16815f5a37cd1f80ed5068cc9a87c6b2e3fb19a9dc4b4c18c9f6b65f9eb07dbd14b49fb2b5af03c0e3a11d5479aa67d8be5aac3abde4d09dca60acb678a8a7abedd07c0b6c87960263d63cf4ec1cb126a0dcab4c18c9f6ae5f9eb07dbd1ab49fb2b5af16e0f1d1ff78aa67d8be0e5a757ad5a13b95c1583de8a19eaeb643f3e4af109935cf5a9327d604945bcb84916c07fcf2d424a0ce34656b5f0781a7c5833e9eea19b6af43569dd60677eb4e6530560f79a8a7abedd0fc21d80ec22ccc2e66cdb3cee4d79adf04945bc784916c2d5e796a2a1350679ab2f5638780c7473fef49f7b01f3b6cd5699d43772a83b17ad8433d5d6d87e60fc376c885795f01328bcea27314b3e82c3a47318bcea27314b3e82c3a47318bcea27314b3e82c3a47318bcea27314b3e82c3a47318bcea27314b3e82c3a47318bcea27314b3e82c3a47318bcea27314b3e82c3a47318bcea27314b3e82c3a47318bcea27314b3e82c3a47318bcea27314b3e82c3a47318bce9d63d63ceb4d9e5813506e3d1346b21df4cb133ebfb33e683f1559f369c81f069e431ef4f154cf70dcfb11ab4eeb1dba53196c5f473cd4d3d57668fe086c875c98f71520b3e8dc3966cdd364f2c49a80724d4c18c976c82f4fd88f3505eda76cfdd811e0f1d1cf7baa67d88f1db5ead4e4d09dca60fb3aeaa19eaeb643f347613b08b330bb9835cf069327d60494dbc084916c87bdf2a4c2e7103704eda76cfdd851e0f1d1cf7bd23decc78e5975dae0d09dca60ac1ef3504f57dba1f963b01d7261de5780cca2b3e81cc52c3a8bce51cca2b3e81cc52c3a8bce51cca2b3e81cc52c3a8bce51cca2b3e81cc52c3a8bce51cca2b3e81cc52c3a771f9d354fb3c9136b02ca35336124db11af3cd5e17d87e6a0fd94edbec331e0f1715fc693eee17d87e3569d9a1dba53196c5fc73dd4d3d57668fe386c87aecebcaf00992536f2c32cb121cc51cc121bc21cc52cb121cc51cc121bc21cc52cb121cc51cc121bc21cc52cb121cc51cc121bc21cc52cb121cc51cc121bc21cc52cb121cc51cc121bc21cc52cb121cc51cc121bc21cc5cc213634cf469327d60494dbc884916c47fdf284ef3dd818b49fb28ddb390e3cc73ce8e3a99ee1b89d13569d363a74a732d8be4e78a8a7abedd0fc09d80ec22ccc2e66cdb3c9e4893501e536316124db31bf3c613fb629683f65ebc74e008f8f7ede533dc37eeca455a74d0edda90cc6ea490ff574b51d9a3f09db419885d9c5ac79369b3cb126a0dc66268c643bee9727ecc73607eda76cfdd849e0f1d1cf7baa67d88f9db2eab4d9a13b95c1583de5a19eaeb643f3a7603b08b330bb9835cf169327d60494dbc284916c27fcf2a41250679ab2f563a780c7473fefa99e613f76daaad31687ee540663f5b4877abada0ecd9f86ed5068cc9a67abc9136b02ca6d65c248b6937e79c2f6b535683f656b5fa781c747ffe3a99e61fb3a63d569ab43772a83b17ac6433d5d6d87e6cfc076283466cdb3cde4893501e5b6316124db29bf3c61fbda16b49fb2b5af33c0e3a3fff154cfb07d9db5eab4cda13b95c1583deba19eaeb643f367613b141ab3e6d96ef2c49a8072db993092edb4679e04d499a66cedeb2cf0f8e87f3cd5336c5fe7ac3a6d77e84e65de847a9ef3504f57dba1f973c043d33ce0f1159781c51338f4a1690c339e19cc782633e399c08ca78a19cf48663c3d98f1cc67c6339319cf14663c1399f1a498f1ac64c6b38c19cf68663c6f32e359cc8c6716339ea9cc78d630e399c48ca79a19cf30663c0b98f1cc66c69366c653cb8c6738339e1a663c8dcc781a98f12c67c6b384194f19339e24339e85cc78e630e399c68ca78e19cf38663cab98f18c60c6f320339e72663c6399f1ec67c6339719cf74663cf5cc78c633e3a964c6b39a19cf0a663c4b99f1f465c6d38f19cf22663ca398f11431e04904778fa549c0fff7838dc67c6c07db7b267f066cc50e1f74aff81cd84a4c9ed6d15ba5a383ef5e37eae46b9c0bfa4ac33cf92b038ef798f08c62c6b388194f3f663c7d99f12c65c6b38219cf6a663c95cc78c633e3a967c6339d19cf5c663cfb99f18c65c653ce8ce741663c2398f1ac62c6338e194f1d339e69cc78e630e359c88c27c98ca78c19cf12663ccb99f13430e36964c653c38c6738339e5a663c69663cb399f12c60c6338c194f35339e49cc78d630e399ca8c6716339ec5cc78de64c6339a19cf32663c2b99f1a498f14c64c6338519cf4c663cf399f1f460c63392194f15339e09cc782633e399c18c670c339e790e9efd9e78ece7bc687e3f03df7abe1674d15302fe8fcf81bde98971bfc548f36f0223f2fad6acdce229b734bb9fbe75fde95ec583e617b7173ef7c0617b95e741b37e164f3f4bb3fbe95b6b41f7fe698c0d6e2f1c07cd617be1384d0ffd734dc2e2d15391359f86fc39cffa78aa67258e9bfc24c6f56aadce5b5aedb7b44a4299b3a0df790ffa15815f5a37cd933f6116e62866cd43f7725de379173261241bbe47e5fdf8796a12168f9eb2f58fef7bd6c7533dc37eec42e0d6fd7dd09dca60ac5ef050cf22f04beba6f90b0edf1541bc5a5cec8016171d3c17f3ac05f9cb95f96c013273d059f3d0d875624d40b9454c18c9761e782ec5cf5393b078f494ad7fbce4591f4ff50cfb840f02b7ee9740772a83edeb030ff52c02bfb46e9aff00b6432ecc170a905974ee1cb3e6596cf2c49a80728b993092ed22f07c183b4faa3261f1e8295b3ff6a1677dfcd433d38f5d0edcba7f08ba53196c5f973dd4b308fcd2ba69fe326c076116666116666116666116666116666116666116665d4698855998855998855998f9326b1e7af69c5813506e091346b27d003c5762e7c9dc77401e3d65bbef70c5b33e7eea99b9ef703570eb7e0574a73218ab573dd4b308fcd2ba69fe2a6c0761166661166661166661166661166661166661166661166661166661166661e6cdac79e81b16c49a80724b993092ed32f05c8b9fa72661f1e829db7d876b9ef5f154cff0bec3f5c0adfb35d09dca60ac5ef750cf22f04beba6f9ebb01d8459985dcc9a87de8548ac0928b78c0923d9ae02cf8dd87932f74f91474fd9fab11b9ef5f153cf4c3f763370eb7e0374a73218ab373dd4b308fcd2ba69fe266c875c982f1420b3e82c3a47318bcea27314b3e82c3a47318bcea27314b3e82c3a47318bcea27314b3e82c3a47318bcea27314b3e82c3a47318bcedd4767cd43dfe824d604945bce84916cd781e7a3d879aa2b13168f9eb2dd77f8c8b33e7eea99b9ef702b70ebfe11e84e65b07dddf250cf22f04beba6f95bb01dba3af385026496d8c80fb3c4863047314b6c087314b3c4863047314b6c087314b3c4863047314b6c087314b3c4863047314b6c087314b3c4863047314b6c087314b3c4863047314b6c087314b3c4863047314b6c0873143387d8d03c2b4c9e5813506e051346b2dd049ed6f8796a12168f9eb28ddb69f5ac8fa77a86e3766e076edd5b41772a83edebb6877a16815f5a37cd933f6116e62866cdb3d2e4893501e556326124db2de0b9133f4f2a61f1e8295b3f76c7b33e9eea19f6631f076eddef80ee540663f5630ff52c02bfb46e9aff18b643a1316b9e06936f35bf0928d7c084916cb781c743dc853c498b87e6ef30f0ade71b4dbeccfce2f66a04460edb2b9907cdca2d9e724bb3fbe95bd77f95c93f687e717bad02460edbab3c0f9af5b378fa599add4fdf5a8bd526dfd7fce2f65a0d8c1cb6573fbf3ca984c5a3a76cc71b1f03cfe7e3e709cfe33ece81e7f3c0f3b9f879aa3cd5b352aff7fb803daef56aadbe6069f5b1a55512ca20c3173ce857047e69dd344ffe845998a398b12f24d60494bbc384916c9f031e1ffd86aefb28b32e5a7f4f951eeadfe6b7357ebf35786da197592f7190bf1228f3f2a036b6c70c5b19fc9fb69baecf2dcbe6e999b72ad7755e9a277f6581fb5cdfd735d4568bc7f65de6d0476b76d3a1d90d4f8cf633ad347f03185dd7797d3d2f1a75dd199f17bd63e9c84d337c0ef823e0f1755cdc6af1b43ab4f0d1e6723dbefcc8c1f3497c3c95181be8cb47ac62dfd691babbda4e8c75afc27b58e8cb431b08f753a3cdba68fd7a5f50dbdfabe635d83fd07e6ab455e712283309f65353b2eca78a83bbaf0b57183b95a1ff7f62ecf63a2a82fb7b6da90cf2b5e61763946cb2ff6d7f0fb3d6d2919b66d8ae5b81a7d5134fd43531f287dbb0cea1591d03cdb02de423ceee583cb6ef24e8d2ca54338c333c6ef0d59fddeb5a1e6ec37a8766f50c34e3d89fd55b3a72d3ccd59fa18e0b1ddc0b197073ec53165a3a72d3ccd5a7a08e8b1cdc8b1870736cd78b2c1db96976af76bdd8c1bd980137c776bdd8d2919b66f76ad74b1cdc4b1870736cd74b2c1db96976af76bdd4c1bd940137c776bdd4d2919b66f76ad7cb1cdccb1870736cd7cb2c1db96976af76bddcc1bd9c0137c776bddcd2919b66f76ad72b1cdc2b1870736cd72b2c1db96976af76bdd2c1bd920137c776bdd2d2919b66f76ad70d0eee0606dc1cdb7583a52337cdf27d1f20ea7e13f9c36dd8e8d0ac9181661cfb94464b476e9ae5fb3ec0bdc660e3365ce5d06c1503cd38f667ab2c1db96996effe2cea7e13f9c36db8daa1d96a069a71eccf565b3a72d32caa3f6b8d9f27e7f1f6ad5ef5c97c67b935071e1c33e523a63cc541a5a73155e1787bfbfb15ad9656c9e0ee6f5af81c7b18353e92fc09b3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300b337f667c9eb9d5fce2bb50ef3061241bde93f2719d5fd77d8c5917ad5f3fdb7b6b409bdff8ef5ba42af19e2b3d773cc6aa730994f9bf8fb7b17d6cd8f0fe226db7a86d79bfdead80efa3c07b41f7f37ee7470ecd6e3834bbee89d1ee3368fe3a30daef7fb8dfef9eb863e9c84db3a87ef68e279ea838bbe3f05d119bef5493affbbafa5d847d82bbf75f771c9afa88c35cdf7d81eda2d5038faff75ce83a5db7ea74cbaa5312ca0c837adecfb645d33ce0f1d51f05164fe0d087a662663c3398f18c61c63399194f29339e09cc78aa98f18c64c6f30c339e2798f13cc68ca73f339e3ecc787a30e399cf8c6726339e29cc782632e34931e3799619cf4a663c4f32e359c68ce771663c8b99f10c60c6f300339ed1cc784a98f13ccf8c6716339ea9cc78d630e399c48ca79a194f3eee81e6c2338c194f05339e81cc781e62c6b380194f82194f4f663cb399f1a499f1d432e319ce8ca786194f23339ee798f13430e319ca8c6739339e41cc789630e3799819cf42663c65cc7892cc787a31e399c38c671a339e3a663ce398f1ac62c6f314339ec1cc781e61c6338219cf83cc78ca99f18c65c6d39b19cf5c663cd399f1d433e319cf8ca79219cf6a663c4f33e359c18c6708339edbcc789632e359c48ce751663c7d99f1f463c6338a194f11039e4470f7b34bf8bcdc2db0d13336ad602b76ac8fc6e552797ddc7976f0ddeb2e76acfb86830175ba0675499b7ce5a79bda3d575464d64bf3e4af0c386e30e119c58ca71f339ebecc781e65c6b38819cf52663cb799f10c61c6b38219cfd3cc785633e3a964c6339e194f3d339ee9cc78e632e3e9cd8c672c339e72663c0f32e319c18ce711663c8399f13cc58c6715339e71cc78ea98f14c63c63387194f2f663c49663c65cc781632e3799819cf12663c8398f12c67c63394194f03339ee798f13432e3a961c6339c194f2d339e34339ed9cc787a32e34930e359c08ce721663c0399f15430e319c68ce726339e6a663c9398f1ac61c6339519cf2c663ccf33e32961c6339a19cf03cc780630e359cc8ce771663ccb98f13cc98c6725339e6799f1a498f14c64c6338519cf4c663cf399f1f460c6d387194f7f663c8f31e3798219cf33cc784632e3a962c63381194f29339ec9cc78c630e399c18ca79819cf3c8b07ffafaf35d0f5c5eb60a3ffffa7b9795f6eea71ddf217433d2aa3becde34b339cd20e4da2becdc3816706339e31cc782633e32965c63381194f15339e91cc789e61c6f304339ec798f1f467c6d387194f0f663cf399f1cc64c6338519cf44663c29663ccf32e359c98ce749663ccb98f13cce8c6731339e01cc781e60c6339a194f09339ee799f1cc62c6339519cf1a663c9398f15433e3b9c98ca78219cf40663c0f31e359c08c27c18ca727339ed9cc78d2cc786a99f10c67c653c38ca79119cf73cc781a98f10c65c6b39c19cf20663c4b98f13ccc8c6721339e32663c49663cbd98f1cc61c6338d194f1d339e71cc785631e3798a19cf60663c8f30e319c18ce741663ce5cc78c632e3e9cd8c672e339ee9cc78ea99f18c67c653c98c6735339ea799f1ac60c6338419cf6d663c4b99f12c62c6f328339ebecc78fa31e319c58ca788014fd4b770e8ff3dc076d5e46f83ed8ac9df04db6593bf0eb60f1db662070bf9bb0a361ae772056c74afee32d8e87a11f9d2c7bb1707dfcd5aeca8530f07eb15479dae3a96c5ed48cba48378b723fa4ac33cf9c36ff55c65c2338a194f3f663c7d99f13cca8c6711339ea5cc786e33e319c28c6705339ea799f1ac66c653c98c673c339e7a663cd399f1cc65c6d39b19cf58663ce5cc781e64c6338219cf23cc780633e3798a19cf2a663ce398f1d431e399c68c670e339e5ecc7892cc78ca98f12c64c6f330339e25cc780631e359ce8c6728339e06663ccf31e36964c653c38c6738339e5a663c69663cb399f1f464c69360c6b38019cf43cc780632e3a960c67393194f35339e49cc78d630e399ca8c6716339ee799f19430e319cd8ce701663c0398f12c66c6f338339e65cc789e64c6b39219cfb3cc7852cc782632e399c28c6726339ef9cc787a30e3e9c38ca73f339ec798f13cc18ce719663c2399f15431e399c08ca79419cf64663c6398f1cc60c653cc8c679ec583d7142bc146f92ab0513e0536ca57838df23560a3fc38b0517e3cd8283f016c949f0836ca4f021be5e99e113edf938ff7c2912f5a37cd5f03c6db268fdb84f275c0fd8165d3dc973c717f6071d3fc2560a43a7c0036cad703f745cba6b92f78e2be6871d3fc0560a43a5c041be527838df253c046f9a9609b0afec846f96960a3fc74b0517e06d8283f136c949f0536cacf061be5e7808df273c146f97960a3fc7cb0517e01d828bfd0fcea6dfcbe65d3dbf8bcc9a78378b731f9a275d3fc7960a4edfd3ed828bf08b8dfb36c9afb9c27eef72c6e9a3f078c5487f7c046f9c5c07dd6b269ee339eb8cf5adc347f0618a90e67c146f925c07ddab269ee539eb84f5bdc347f0a18a90ea7c146f9a5c07dd2b269ee139eb84f5adc347f0218a90e27c146f965c07ddcb269ee639eb88f5bdc347f0c18a90ec7c146f9e5c07dd4b269ee239eb88f5adc347f0418a90e47c146f915c07dd8b269ee439eb80f5bdc347f0818a90e87c146f995c07dd0b269ee164fdc072d6e9a6f0146aac341b0511edf47bfc613e36d8bf1b6e51befe3e2b1e501cba619dff5c478c062a4f97781b1c5e40f00cf014f3c2d168fed3b09baac61aa59126c2dc053eb89e79ac573cdd202c7bbe1b9c01acbe673bbaeb11869fe0030b6987c3eda668bc563fb4e822eb54c354b82ad0578ea3cf15cb2782e595ae0732e78ee566bd97c6ed75a8bd1ee2b30ceb0aff0d5365b2c1edb771274a963aa19f6b92dc053ef89e782c573c1d2a20cf278fe5867d97c6ed73a8bd1ee2b30ceb0aff0d5365b2c1edb771274a967aa19f6b92dc0d3e289e7bcc573def28ddb10cff7175a369fdb75a1c548f3d8e7da6da114f271f3d45b3cb6ef24e8d2c25433575bf0d99f9db378ce59be711be2f5994596cde7765d6431d2fc42606c3179dc868b3cf1b4583cb6ef24e852cf5433575b2805b6b879ce583c672c2d70dc1e5e4fabb76c3eb76b54ffb108185b4c3e1f6db3c5e2b17d274197c54c35c363c816e069f1c473cae23965f9c66d88d73f9758369fdb7589c548f3d8e7da6da114f271f32cb6786cdf49d0a585a966aeb6e0b33f3b61f19cb07ce336c4ebd54b2d9bcfedbad462a4f925c0d862f2b80d977ae269b1786cdf49d0653153cd5c6dc1677f76cce23966f9c66d88f7179659369fdb7599c548f34b81d16e0ba5908f9b27aa3f237f49d0a585a966aeb6500a6c71f31cb1788e585a94411eef07b558369fdbb5c562a4f965c0485ab5004f8b279ea838237f49d0653953cd9260cbc77ef390c573c8f28ddb10efdfadb06c3eb7eb0a8b91e65b80d16e0ba5908f9b67b9c563fb4e822e8b996ae66a0ba8630370afb46c3eb55d6971d3fc0a605cecd071a5279ea83e6525e8d860e9c84d33573ca28e8dc0dd60d97c6adb60713758dabae2b114f271f344b5eb06d0b1d1d2919b66ae782c03b655c0bdd8b2f9d436aa1d3500e3724b5b9ffbbda86dbd1874245d1a996a86d735715b13db6ae06eb46c3eb56db4b8ed3683db1adb4ca3279ea86ddd083a922eab986a867d0f9e0ff93aff88badf950fdf51f740f2e13beaba783e7c475d2bcd87efa8fbe8f9f01d754d251fbeef759eedd377d435cb7cf88e3aefcb87efdb96efdb79f41d35fe2d1fbea3c64475f5f62dfb92eeb52fb99ffd5a77dd97487fceb33f5f1dbfef5422687f4ea3a7226b3e0d793c7f59e5410b4ff5acc473c24f625cafebdc7ab9a5159e5be339aaaff3bfd5160fcd93bf4264c6b8288acf77255e87c1ef3bd275914ab0d175b12ab0d175d114d85a4cbe1a6c744fa6066c743f701cd8e85ef47cb0d138880560a3313817c046e3bfde071b8d3d3c0f361af7fa1ed868ccf539b0d178ffb360a3674dce80ed1d933f0db6b74dfe14d8de32f993607bd3e44f80ed0d933f0eb6fd267f0c6cfb4cfe28d83e6bf247c0b6d7e40f836d8fc91f02db6e93c76befbb4c1eafe57cc6e4f15adeeb263f1e6c3b4d7e02d85e33f98960db61f293c0b6dde46f836d9bc95f01db5693c7ef8b6e31f90fc0b6d9e42f816d93c95f04db46939f0cb666939f02b60d263f156c4d269f06db7a939f06b675263f1d6c6b4d7e06d85e35f999607bc5e46781ed65939f0db6974c7e0ed85e34f9b9607bc1e4e781ed63933f08b6cf993c5e072d3679bc7e4fef9bc27b5ef4ce4bbce749ef95c6fbedf4ed8f16b0d1f7b5709c51a9c9e318377aaf148eafa47749e238d584c9e3b8f23293c7671ae8bb1ff86c087d3b0a9f4b2a37797c268ebef979006cf45dd277c146ef9e7a076c034cfe6db0d13b9ddf021b7de7e24db0d1b79bde001b7def733fd8e81d53fbc0f6b8c97f166c034d7e2fd80699fc1eb0d1379a76838dbe13b90b6cf42ea9cf808dde8ff83ad82a4c7e27d8869afc6b607bcae477808dbebfb81d6cf4cea86d60a3f70e6e05db3093df0236fadec166b00d37f94d60a3ef786d041bbd1baa196ccf9bfc06b08d32f926b08d36f9f560a377f3ac03db58935f0b36da67bf0a36da67bf0236da67bf0c36da67bf0436da67bf0836da67bf0036eafb3f061bf5fdd47fe876aadbef2d339f0ee23b8ed2fe5a83f653b6637962409e388f8d93c083be6ec65ef754781cfe915957b1592fc5cb4df07d3d76df9973801b665d3dcd7aaf5bbe4ba04ce9c0b66d730dfe9f863ad0725886d64df36360d96bd6bacb4d7d6f78aaef758b89b86f001395291bd856f64b265f0acbc4c8169ecf52ac05a0214e69c813831fad52e1f9c54739f0dc009ef8db49e6fcda474c60db8afbfcdabe2e63c75a12ca5c07fd7cbd17eb86c543f3e44f98855998855998855998855998855998855998855998855998855998855998f9336b1eba9f40ac0928778b0923d9f05e978febfc78cf15ef79dd1cd8e6d7f7fdbd5e66bd63ad3a9740996f0d6c63bb6df265f07fda6e51dbd2c37dc2acdbf27bf7caa03e782fc8c3b60c796e5a3cb6ef32873e5ab36b0ecdae7a62b4fb0c9ac76fbe907ed780c7577bbc6ef1d8beb1cfb8c154b3a87ed6c7b8846c71e61a8350119bef5493affbba7a2c941ecb61efbf6e599ae21808bc67fe25e89368993be63701fadc017dee671f608f4bc07eaa1518e3ef3753edee0153df3fc6d214c740fc96d196c640c4df0fa42a7dee23a88dda632bb0ae54e6f7613ff787268fe3806ec1babee2f83f4dd9c624609f7a39fe3a87dbf743b32edabe971dbe3f00d6987c57a1ef2293c80fd94b20ffe5816d65edef4c91d6c48edfc242767bb9566bb92494b9e2a87f3a88b7fe972d9ecb16b38e9d3f8138fb0a1cebf9ea93ae4468340634a23278cceb6bfff591c5431ce40ffbd1de56195ab604ca7c1dfa285d17eae75bcd6fd43ec0d7f142d43e008f17ecfd42c251471d1fb706b4f176f7b17eff05fdc535f87f3af8f463fdfe0b62c8755c4aeb1f0beb27aede41f4be85cafc2f6b3feae37c12b7a5ad278e25a432ff0ffaa1d4a04c3e97f3bafb758e1e755ee7e3db9978ae4153b6fd3bee637cf42f9eea59e9da775db3ea948432c3a09e1e8e639cfb2d9abf0cbe7d7d2f957cd031d4754b8b122893346d87fa8e281df1bac48dbcd425e53c1e1ceba80b9519007529057b9c4c3eb71b1e67e9f5de74d495ca3c36a8adec40934fc076c2be7484e3ff3465eb0f483f5de78bf1d739dcbef4dc226ddf8b0edfef036b4cbedbbdbf828ef7c90fd94b203f7c505b59fbdb9da4357e8b959eaf43767bb9ebd672492873c951ff74106ffda3be334bfe74ec0c8138a338f2d96f5e8ad0682c684465f05e817dbd256abfef632c7db6fdfe4d60b4fb4dad696a907f36fb9cc5be5eee3a1ea43278ce426526403f9b7094d5f5f27b1f20736c83f5a27a04565d03abae9e8e5f6b8a2c3dd3e06734d8293e4967fa1f1ee3529969d6feccf7756ce2a67ae0fdbaab16f7354b57bc16351bb875dcdbe716789ceef99cb6068fc5ece3a1abc04e65165ac743f671dc6d475decfd747170f7b9e02756597c3629db7276fe236b19bc66e0ba268b7ddf1560499b7ce5a799aa2a2b91a9d8a185ebbea9ab4fa2768031675f47196dad07afa3acb1fa24bbacee936afbb7e943db11afb5dbd7df3d3d9b16b6b95b56fd6d8d3463abc9e336f4710fa33b3e9b561adb7a27ad2fc4f10ca5563e1edfa90db8afc8a6c555078faf6b9a515a5c75f88e4f8bf14daefd874b8b2b0e1e5fe798515a5c71f88e518b8dae6b0b2e2d2e3b787c9d6b446971d9e13b3e2d26b4bbae914d8b0f1d3cf15fd3c8ae05de13cb85f90a03e6522b1f8fef9af5ae7b772e2d3e70f0f8ba7717a5c5070edff1695135de75ceeed2e29283e7529eb5b8e4f01d9f161327b9aea9b8b4b8e8e0f1707d2dab16171dbe638c8b66bcbe964d8b0b0e9e0b79d6e282c3778cc787e3b35d33442dde77f0f8baf617a5c5fb0edf316ab14efb3edf012dce3b78cee7598bf30edff169b17e9cf6fd5e07b478cfc1f35e9eb578cfe13b3e2dd64dd4becf75408b730e9e7379d6e29cc3778ce750615c9ced8016671d3c67f3acc55987eff8b4d8101e6b9de98016671c3c67f2acc51987eff8b4a80cf7a9a73ba0c56907cfe93c6b71dae13bc6b808cf274f75408b530e9e5379d6e294c3778cfb91302e4e76408b930e9e9379d6e2a4c3777c5a6c0caf3f9de88016271c3c27f2acc50987ef18afb9847171bc035a1c77f01ccfb316c71dbee3d3a23adca71eeb8016c71c3cc7f2acc53187eff8b4680eef891ded8016471d3c47f3acc55187ef188f3bc3fee24807b438e2e03992672d8e387cc778dc195ebf38dc012d0e3b780ee7598bc30edf31f69de171e7a10e6871c8c17328cf5a1c72f88ef1b833d4e26007b438e8e03998672d0e3a7cc778dc19ee475a3aa0458b83a725cf5ab4387cc7181761df79a0035a1c70f01cc8b316071cbe63bcae15f69def76408b771d3cefe6598b771dbe633c1f09aff1bdd3012dde71f0bc93672dde71f88ef15e51780cfe7607b478dbc1f3769eb5781b7cfb1867825ad058ac5196162550e681c1995f1a8b15a523ad039fa1c5babc157b5d32e3cade8ca8cb5b50172ad317ea520af638993cd5358c19fa96028d4d6f75d495ca3c3cb8adeca3269f806d721bd635ccf17f9ab28d4122fd749df7c55fe73056e91b10b47df7397cef05d6987c57a16f1a9b4e7ec85e02f96707b795a572a407694decba8dd0373090dd5eee6d6bb92494d9efa87f3a88b7fefb2c9e7d1673f8dc03c419c5919fbe2bc3b43f42a351a01195c1317bad9e78ec3184c441fe7419dafebdad32b46c099419037d148e2ba57a2682bbc74deafabde1a97ee48bd64df3e42f09b61bc068d751c7c74330f693be0142df07d136fade077ebf6bbc65d3759de0a9aee48bd64df3138091be3f323eff8ca98e328eb31835cf240f9ae1375568cab6bf98043c133df078aa67b81faab5ea34c1aa5312cae0b38db51eea59047e69dd345f0bbe7d6c73d482f6c9c32d2d4aa0cc42ebf8314a475a878edff18ebaf8d2719cc533cee17bb2671d69ddd4274ece83ef3acb778de55bb76d8c313d656bdb75c05cef8159af774afceb0ddbf654b32e8a67f25303754a830671d5097d1759eb267b09e49b06dfcd407ad0be93d8753bc2d8895a6e92b55c12ca4c76d43f1d73fda7583cb88df5a48f1b5e84e34a0fed218c81c91607cdd780765322b49b0cda5119dcf75679d2aedee2a1f92ae0a1e3ab5ab0d1710a7ee392fe9fca03b7ddefd53ab8c986df3cac72308e8f9f313cceaab218697e3c3092ad1e78ea3c69666febe1963e784cd0db2a43cb964099fdb05f4e38ca86cf1d17b5d58bbea5f9498cf5d2ebede5412ffcce6700fa04968634114369d0f62dd038791e08dabef5b97bcfce5deb36352f6bcedcf624b4120b137f8b1cd528061be67b386c41d0fe93a62560a34f9af6045bb1250b7e4a95cad3a7137dc8857ad0ba4b2cce526089d3377e0e96a66ca1d31b787c84b20e1dfa24ac099dc65d5bf634637cf4b4383b133bfa7f3db2948b5a17c5418987ba2313ad9be6c99fd6873e8ffbfabaa66dd3766ddabba3f9b53dbb11d66e5c982fb244b07f5dcb60906063a2f5f4b4c4e913bf3835d8786dbe00fc05c012189ed2f879c240a56f0837addbbe7dc9def5dbb734cddefb5ad39e2d3b5f43457b5bca45a96d37793db9ba3a2c6b97efe5b0d9137eb1b937d8e88bcda56023ff7dc0461c0fc0ffec2de1a54d0c83f55318ebff95980af73215a210a4dd90ee4f749bd1af4dd5bb7ffd8968fd4968bdf9f4dbe2f4279ef5279df5279cf5279bf5279af52799f5db24f413defac8614890f984f29341e615b14383cc2790f5278f9f09da3e69aca7df055efd09637da8a13f51ac3f49fc7c90b954383ac8bc564dbfc6421fb2ea432b7d98a74f6bf421b83e2dd7875efa7281be74a40f63f421a23efcd1872cfa105c1f7a4f355a4f0b329f34d79f309f19643e51ae3f49ae3f413e37c87c627cbe4a0b82cca7b6170599cf07ebcf87ebcf76ebcf79ebcf7cebcfcfebcf82ebcf85ebcf88ebcfcceb4f0feb4fd0af0e329fda7e29c87cb6f89520f399e3b541e6b3c8eb83cc6794370499cf2eebcf31ebcf346f0e329f75d69f7bde16643e0fbd23c87c4e5a7f665a7f7e5a7f965a7fae5a7fc65a7fde5a5f72d7b71af425787d795b5f7ed5b740f4ad1f7d6958dfb2d4b770f52ded962033e4e150901912a38708e921537a08991e527722c80cb9d44350f5905c3d44590fd9d643d8f5907efd88837ee4433f02a31f09d28f48e947c6f42374fa3148fd58a17e4c563f36ac1fa3d6977df523e8fa56a0bedcdb1a642e09df09329f5ffe9c4a9f57e9fb54fa824adfafd20fa8f4832afd904a3facd21755fa11957e54a51f53e9c755fa09957e52a59f52e9a755fa19957e56a59f53e9e755fa0595bea4d22faaf44b2afdb24abfa2d2afaaf46b2afdba4abfa1d26faaf45b2afdb64abf1364e2f1f754fa7d95fe40a53f54e98f54fa6395fe44a53f55e9cf54fa7395fe42a5bf54e9af54fa6b95fe46a5bf55e9ef54fab24a5f51e9ef55fa0795fe51a57f52e9ab2afdb34a5f53e9eb2afd8b4adf50e99b2afdab4affa6d2bfabf42d95fe43a56fabf49da0ed33e5d8790c363dce5033bf6ecf9ee61dafefa9d8b3b362c7deed7bb6bcbefd8d8a7d5bf66caed8f9d9e65d1bb7efdc870b7fd92cfcb8999fb66bd7ba372ab6bcb6a1797fc5cebd7b2a766eac58bf73ef6b1bdaed2cffb75968f0dd1ed76dd810edacb4c7a7202debd139a783cc72f4a5fa79d9ebf6448f4e08f24c67169adbc90acd357b203a0d5b9e39e6abd8bd7de79e8aca8ad7d45fb573ddb9af79c3980afcdf6e25f2ee3d15bbf7acdbb5a762e3ae9d3b2aaac6e07a17f6e94425bed8c70f4c6ff35ea24e85ca6f0eec444dbe36b0739be33f3f0de9ffeca4d3b2419da861ffce2c347e50e708d3832265d9bd77fd9e5deb9af6442f3cebd32cbca033d55cddc96af619dc0967e59d5968f4e0ce112ee88cb37d39380bfe3f2f1967aadc550500", "isInternal": false }, { "selector": { "value": 2603445359 }, - "bytecode": "0x1f8b08000000000000ffed9d79741cc5b5c67b6459963d1acbf2be5bac5e4648a319c9b6b08d65b3181bb3790163360b5b3606db32b60c983d648310080961c90664634908d94312b2ef2464812c2404b213c8bf39efe49d774e4edebb3553f7e853b96bdeb4dc35ae96ef9c7335d557357d7ff7ebdb353dd5dd33a9a0f478832ca5db23c88e0d0e7df0ffbbf573eef01eed31ae2be792339510ce9a84708e4808676d4238472684b32e219ca312c2599f10ced131722ab69a60f0236ede310e748d9b319d304d1b12a06926619a8e4d80a68d4132c6a87109e16c4a08e7f884704e4808e7c484704e4a08e7e484704e4908e7d484704e4b08e7f48470ce4808e7cc8470ce4a08e7ec8470ce4908677342388f4908e7b109e13c2e219cc7c7c8390f384fd0cf27eae7b9fa99fbccd7cf0bf473563fb7e81c6bf5f24964ad646d8acff89f3ad190272b9075e8ff35ebff75922d245b44b698ac8bec64b225644bc996919d42b65ce7bf826c25d9a964a7919d4e7606d92ab233c95693ad213b8b6c2dd9d964e7909d4b761ed9f964ebc8d6936d305836925d407621d926b28bc836935d4c7609d9a56497915d4eb685ac87ec0ab2ad64dbc87ac9b693ed20bb926c27d955645793ed22db4db687ac8f6c2fd93564fbc8f693f51b9a1d20bb96ec3ab2eb0dce83643790dd487613d9cd64b790dd4a761bd99bc86e277b33d95bc8de4af636b2b793dd417627d93bc8ee227b27d9dd64f790bd8bec5eb27793bd87ec3eb2f792dd4ff600d983640f69162ef6f791bd9fec03641f24fb10d9c3648f903d4af661b28f907d94ec63641f277b8cec71b227c89e24fb04d927c99e22fb14d9d3649f26fb0cd967c93e47f679b22f907d91ec4b64cf907d99ec2b645f257b96ec6b645f27fb06d937c9be45f66db2ef907d97ec7b64df27fb01d90fc97e6468fe1cd98fc97e42f6bcfe1fcf21fd94ec67bafd73fdfc0bfdfc827e7ed178cd2fc97e65f87e4df61bc3f712d96f75fb77faf965fdfc7bfdfc8a7e7e553fff413fff513fff493fff593fff453fff553fff4d3fbfa69fffae9f5fd7cfeafc63617ca95d1f0c3cba8398c69d8ede2e75fe81c53e2118fc505a8cd0ffe3e766edafd5cbfcccda8dd4cb230d7f9d5eae33d653af97eb0d7f935e6e32fc13f4f204c33f492f4f32fc53f4f214f0a7039887d47ee51ba15d29f0711dd6806f64305813e5abe3d5816f5430580be5e3ed5807bed1da370a7c63b4af1e7c69ed1bcd9a9135685f7710574de47ad47a3371af579f9b191b3fef56b5de4647bce3e2e7ed55eb6d72c0abea430f17c138a89b09dad704be89da371e7c93b46f02f8266bdf44f04dd1be49e09baa7d93c1374dfba6806fbaf64d05df0ced9b06be99da371d7cb3b46f06f8666bdf4cf0cdd1be59e06bd6bed9e03b46fbe680ef58ed6b06df71da770cf88ed7be63c1c7e3e771e0e363b8e3b54f8d09ff0ae035da5f03be1379cc05df5c1e6fc1378fc75af0cde771167c0b2036fbb23086b0af45fb783c52ff5ba8dbdd415cf59fdfa6d6bb28eef5d29ad57abbe25f6ff1bcd5c9c180aedd10671168b544b763bc36a61d63a7b4711cf6d7427b15f4e57eac07bfa730bb7aef58acdb4bcabc6ea1f1ba0cf4591c927f77106ffe5d064f97c1acea7f2970c45fb38576a9d98a1f916b7623f4356b8f8f6f8663cdae010e0735dbe9a666f339a9d9d2fc421084d71e1fe30ec79add041cf1d76ca7d46ce58fc8357b0df4356b8f3fe70cc79add0e1cf1d7eca24e3936a8f811b9666f85be66edf167dde158b3fdc0e1a066bb649cadf811b966ef86be66edf1bccb70acd9db8123fe9aed7254b305a9d9a074ae2808c26b8fe7008763cdde0b1cf1d7ecd62e3936a8f811b9669f84be66edf17cf470acd98781c341cdba9a9fcd4bcd96ce91074178edf1b991e158b34fe9b63acff0737d9e6126f87ea17db3c0f782f6cd06df8bda3707f28a7f1fd856907da0e247e47de039e86bd672b36e0fc77de01bc0e1a0663ba5662b7e44aed997a0af597bc7eaf670acd9e781c341cd2e929aadf811b9665f83be66edf1f50bc3b1665fd66d75bcf03b7dbc7022f85ed6beb9e0fbbdf6cd03df2bda371f7caf6adf02f0fd41fbb2e0fba3f6b580ef4fda7712f8feac7dade0fb8bf6b581efafda9703dfdfb4af1d7caf695f1e7c7fd7be02f85ed7be0ef0bda17d9ddaa7ce09f0f529dfd3be7ac8a93b886fdb16af4909063f52c67237b45bdcf2e432c1e0ebaa39566bfcb10a2af79382ca736f059e3607b9a72146253c6dc0938b9fa778ed457bfceb2d6ee3930c4dd310eb24c82bef20af14c4e275f332c7cb800fc7837c0863217ec67c0a62f1ba79b9008cecc3f189c757de7fd4d83c3635c0eb605f2abe3f63bc6ee0e078b5d0e785a681bee3355b03fc9fc7800668e3f89d337c8e6ab51dafefe775f3723b30728eb9ea33e62b656c3318eb812d469ea2666d064f5b8816476b6c07637571ffe318bcfff1bec4f16aa1cfffd40cf43d31e5942d1ff57d16eb33fef13f9fc37db3129e3cf0b818631cbdcfe5f0bde93f41bcb5d661689533b4ca409f02e8d7e140bf72ef951c4f98855998855998855998855998855998855998855998855998855998855998fd67c6f3c778be2decdcec9164645f3bf0b898e72f7e27895e17af5f9dd77906ceebc47fde229fc3f38e7c4dd63c23e75ae8f35c6a80edd99073be787eb7d5f039bae6a2b82df19a8b6e58e678780e1aaf0171750e316bf06443b4f02176736cb1f35bdd6cdf7c4e7d2780fa5e9d16639b865d7fb2c0f0a93afd77cd40de2ecefd453d17896309b7e33cb797090ebd76c0cd352ea5f183c7ab9a60f0f881ef339db1c71e7c0e93cf97771ab16ba1cf4ba9816db310fedf1d1c7a5d0ef6e175f3f23c78ed4263dd8deef22d7b6d42277073bbcec8ad05b8b9cf2b309edf0afb8983f7b83c5e1f16006f60e4c40f3c671fff3140e91a827c049e0ee07170bd58bba3639d1cd663dcd7102c34b40a3b86e23e9da05fecd7c3ebfdc33c0ee6658e27ccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccfe33e3fdddcc9a867eed9e3056e9ba8be2f90cfebe0d3c2fb6bb6620aeeb73807cce69be91732df479ba6680ed1add6e080ebdd6c2b62d5d9d5bb36d4b8ed700f9e0b92057f7ac170c9e4288163ec46e8e2d76e91a82f8b7efc0350479639bb61bdb13cf9de33e742bd4a9f91d1769d0a71ad72dd9b60dc7c37da9003e6ee3bdd92eb4c6f712f39a228e87e7ceefd4daf2b9f3f8c7ea7ccee5b8c1df5dc5d709e44372e53ef7c0d877af6ee3f523edb0ae4742fecf8f72e7a959bf23f13d5e18db87eff17ab866a0aff97d5cac75d4eff1ca19aff3f17bbcee833a7b04deff5d8d498b83708de68146dc078f831c5c67123a469ad756aa3ebcfd47197df09885fb3c0e6394eddad5b0ef3e72f0fd7c65bffb88e3e1b17107309a399ad7981eedd7883d03e3c542f87f7770f8d7883d033584d76905c6fae7c3fa996b54607f6fe13ecf1aefa3aef62ddb3568b86f999f079817af41e33edf82b1ea9f709c651efbe3f55ad5f86c67bb3e9ce3e1315594dc715c88fbbd11eb1159381ed6e38f8d7a5c68e16e0d79ed4f2daf65adf89a63fcec64eaa774580cafe98e4587d278d365e4c2fbd462c885fbfcd2d86fe23f662a1d7fc69febe0e3211e830a21b9729fdfc2bef6321c5ff276c2b1f21f21ffe747b9e34fd64fe5bc34fe9c8bdb77995e176fdfa521b14f01d69862b7636c3efee438ecaf85f61bf07ec2fd580fd69ad9d53ec2c770c86ebeaed3785d06fa2c09c9bf3b8837ffa506cf528359d5ceab5067ff80e34f5763f5128b46f34123ee83f744f1fb08f7b7bdc7b8b8deb7dc7b4cd8f743e2d8fe4fa7737ae16ce69c5ed8f109f7e1d7e2f1c97fc3389b0ee96bce55f27b489cd72ce33d225988fbef90b8dd31eb990906eb9931385cc66e3462375631769311bba98ab14573d1dc27cd7dfafe6ffc9eee9a04308e4800636d0218472680b12e018ca312c0589f00c6d109601c9300c634301ec9f77607fae4e3d0a701746a09e176753f7e8bc1687e5742c6e0659e23798ce4eb361cab9f7dde868dc033cc8e3563d986e3f4b3cfdbb0c9ad8eb18cf7e313c03821018c1313c03829018c9313c03825018c5313c0382d018cd313c03823018c3313c0382b018cb313c03827018ccd09603c26018cc72680f1b804301e9f00c61312c09884b9ca056e1987fcf95af138f84dc80efc8c5e098febefd6749467f1fa2cbe8e31eeef48337fd7b1c5d00aef3971fd7bb0a9c0fe5da91c4f9885d9c68c6321fe3e37f7cb7ac218f6ddc30ec68dc8ef29ad6e7906fdf676abdb6d11f9bdcaed6f8296deab8e86df040dbbbf25ecfbdeb90f8e1b47ea3a468cdd1cc4ab4547055a54e91e6c27dfd7df9640665f7e6380c7a7b0df18c87ac258a5df1888fc5e950fd1b1d52d637ea88caeee65c67aa98407bf17c3454db9c9b3fc7739733cfcfe0f1c935c5dd36fde1fc7cb957c6789300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb330fbc18ce718f0bb9cb95fd61346f37b921ccdc7473e57d319a263ab5bc6fc5019f1fbcfe2e3299dab89f23d558b80c7454db9c9b374aec6fcbecd4e2327fcbe4ddcbf5d7d07d92283879717c3761066611666611666611666611666611666611666611666611666611666611666bf99f11c03b3a6a15fd61346f62d041e17bfc714f53cc8a2101d5bdd32e687caa8781cfc865c07d64b253cf8bb1e2e6aca519e837e2b8fd7bdc8c829037d70ff3ed9419ea9c0fefb71f8bb7ac22ccc61cc3866316b1afa653d6164df62e071b07f471efbbb42746c75cb981f2aa3e289ff372c4be7e9bb22f0e06f1ab9a829377996c67ef3b792ccdfeacc401fdcbf1dfc6e56e8ef24f1f252d80e51980b0964169d45671bb3e82c3adb984567d1d9c62c3a8bce3666d15974b6318bcea2b38d5974169d6dcca2b3e86c63169d45671bb3e87cf4e88ce71898350dfdb29e30b2ef64e071301f1ff95ccd92101d5bdd32e687caa87896c5ce53c861bd54c2b30c785cd4949b3c4be76a4e31725a62e494813e38269de220cf14c4e575f3f229b01d863b732181cc521bd56196da10661bb3d48630db98a53684d9c62cb521cc3666a90d61b6314b6d08b38d596a43986dcc521bc26c6396da10661bb3d48630db98a53684d9c62cb521cc3666a90d61b6314b6d08b38dd987dac06b7498350dfdb29e30b26f29f02c73c013f53aa265213ab6ba65cc0f9551f12c8f9fa703eba5129ee5c0e3a2a61ce559bcd6a9dbc86999915306fae098d4ed20cf14c4e57563de81de0eddc22ccc21cc3866316b1afa653d6164df29c0e360ff8e3cf62f0fd1b1d52d637ea88c8a6785239ee5117856004f77fc3ced8ef22c8efd2b8d9c961b3965a00feedf2b1de49982b8bc6e5e5e09db2169ccb82f316b1afa653d61c41a631e077517794c5a11a2636b0218db12c0383a018c6312c09806c6ac03c6948e873cbc9c75ab4f3e0e7d1a40275fc7bd0cf0b8da868d064f638816be6ec3b1fad9e76dd8083caeb66193c1d314a285afdb709c7ef6791b36b9d53196f17e7c02182724807162021827258071720218a72480716a0218a72580717a02186724807166021867258071760218e7248011e7348ee4e7dc23f9f9ec487eae10cd45f3dce13d4473d15c3417cd45f34034cf1dde4334f758f3247c8610c6e1cd58f094117952f1f1e430778cb5d283dc9921698c850430babece48748c85313f5446c5739a239e9511784e039e53e3e769779467f15ac3d38d9c561a3965a00fd6c1e90ef24c415c5e372f9f0edb2169ccb82f316b1afa653d6164dfa9c0e36aff8ab2bfe3fe7586239ed322f09c013c2eb697a33c8bfbfb2a23a7d38c9c32d007f79d550ef24c415c5e372faf82ed903466dcdf99350dfdb29e30b2ef74e071b57f45d9df71ff3ad311cf191178ce041e17dbcb519ec5fd7db591d319464e19e883fbce6a0779a6202eaf9b9757c376481a33eeefcc9a867e594f18d9b70a781cd45de4cf1c6786e8d89600c64202184547d1d12746d1f1e8d1511885511885f1483026610c97f799e87303f8597c4dfc3c1df8b9ad129e35c0e3e2b39da33c8b73036719399d69e494813e58076739c833057179ddbc7c166c076116e630661cb398350dfdb29e30b26f35f038d8bf238ffd6b42746c75cb981f2aa3e2591b3b4f470eeba5129eb5c0e3a2a6dce4591afbcf36725a63e494813eb87f9fed20cf14c4e575f3f2d9b01da2301712c82c3a8bce3666d15974b6318bcea2b38d5974169d6dcca2b3e86c63169d45671bb3e82c3adb984567d1d9c62c3a8bce3666d15974b6318bcea2b38d5974169d6dcca2b3e86c63169d45671bb3e82c3adb984567d1d9c62c3a8bce3666d15974b6318bcea2b38d5974169d6dcca2f3d098150f5f77ceac69e897f584917d6701cf5a073c51afc35f1ba263ab5bc6fc501915cf39f1f37460bd54c2730ef0b8a829477916ef1538d7c869ad915306fae09874ae833c531097d7cdcbe7c27688c25c4820b3e83c34661cb398350dfdb29e30b2ef6ce071b07f471efbcf09d1b1d52d637ea88c8ae7bcf8793ab05e2ae1390f785cd494a33c8b63fff9464ee7183965a00f8e49e73bc833057179ddbc7c3e6c076116e630661cb398350dfdb29e30b2ef5ce071b07f471efbcf0bd1b1d52d637ea88c8a675dec3cf91cd64b253ceb80c7454db9c9b334f6af37723acfc829037d70ff5eef20cf14c4e575f3f27ad80e51980b0964169d45671bb3e82c3adb984567d1d9c62c3a8bce3666d15974b6318bcea2b38d5974169d6dcca2b3e86c63169d45671bb3e87cf4e88ce71898350dfdb29e30b2ef7ce071301f1ff95ccdba101d5bdd32e687caa87836c4ce53c861bd54c2b301785cd4949b3c4be76a361a39ad3372ca401f1c93363ac833057179ddbcbc11b6c370672e2490596aa33acc521bc26c6396da10661bb3d48630db98a53684d9c62cb521cc3666a90d61b6314b6d08b38d596a43986dcc521bc26c6396da10661bb3d48630db98a53684d9c62cb521cc3666a90d61b631fb501b788d0eb3a6a15fd61346f6ad079e0d0e78a25e47b42144c756b78cf9a1322a9e0be2e7e9c07aa984e702e07151538ef22c5eeb74a191d30623a70cf4c131e9420779a6202eaf9b972f84ed20ccc21cc68c6316b3a6a15fd61346f66d041e07fb77e4b1ff82101d5bdd32e687caa87836c5cfd381f55209cf26e07151538ef22c8efd1719395d60e494813eb87f5fe420cf14c4e575f3f245b01d845998c39871cc62d634f4cb7ac2c8be0b81c7c1fe1d79ecdf14a263ab5bc6fc501915cfe6f8793ab05e2ae1d90c3c2e6aca519ec5b1ff6223a74d464e19e883fbf7c50ef24c415c5e372f5f0cdb419885398c19c72c664d43bfac278cecbb08781cecdf91c7fecd213ab62680b12d018c8504303ad6313f5446c57389239ecd11782e011e17e387a33c8beff3971a396d3672ca401fac834b1de49982b8bc6e5ebe14b643d298715f62d634f4cb7ac2c8be8b81c7d5fe15657fc7fdeb32473c9744e0b90c785c6c2f477916f7f7cb8d9c2e3172ca401fdc772e7790670ae2f2ba79f972d80e4963c6fd9d59d3d02feb0923fb2e051e57fb5794fd1df7af2d8e782e8bc0b305785c6c2f477916f7f71e23a7cb8c9c32d007f79d1e0779a6202eaf9b97395e1299717f67d634f4cb7ac2c8becb81678b039ea8fbfb16600cfbcce12b6321018ca2a3e8e813a3e878f4e8288cc2288cd11857248051b6b530faca9875c098d2f1908797b35588dd68c46eac62ec2623765315638be6a2b9682e9a8be6a2f9e1c616cd4573d15c3417cd45f3c38d2d9a8be6a2b9682e9a8be6871b5b3417cd4573d15c3417cd0f37b6682e9a9bb17be28f1df97aee1ee0d9e2400b4779e6d47aafd0ebfa4f8cfa29adb61a5a650dad32d0e70ad06fab03fdc2aeb9e6658e1795f9440f981dc5ce8fa5758c86fc3946c1d043c5dfe62877db98b7ad0ab16d635e3562dbc6bc6ac416cd4573d1fce8d51cdbb5c1a1f720a975f4eaf648bdccfd57c0ebb8cf030da5e7c640b6a78bd8b20f89e6a2b9687e2434475d6aaac013183c41199ed99ef14cf58c67bc673ca33de319e119cf5ccf78e678c633cd339e099ef18cf18ca7d6339ee99ef14cf48c27ed19cf48cf78e679c633c3339ef99ef14cf28ca7c1339e8c673c759ef1ccf48c67b2673c633de369f48c6781673ca33ce3e9f18c6796673c533ce319e7194f93673cf59ef1a43ce04907875e539386fff780afc678ad1aaf268e1ff8ff76edaf81d7ecd0ed1121ebde0e3e3e57b523e4b5a8d376c8a55bb77387f728ea84b1ba6199e33500c70e4f78ea3de369f28c679c673c533ce399e5194f8f673ca33ce359e0194fa3673c633de399ec19cf4ccf78ea3ce3c978c6d3e019cf24cf78e67bc633c3339e799ef18cf48c27ed19cf44cf78a67bc653eb19cf18cf782678c633cd339e399ef1ccf58c6784673ca33de319ef19cf54cf78667bc65313c2d3e38887e72f79ddbcdce3496c07dba178dfe2958e72daa9d755a7d7cbfc1caf16fa3ca43fb8a9f9087c2d7399f3cd38d7b41334ea75948beddae5de2ac4b65dbb5c8dd8b66b97ab115b3417cd4573d15c3d62bca7be53eeb7a89c47eeb728cf23f75b94e799eb198fdc6f519e47eeb728cf23f75b94e791fb2dcaf3c8fd16e5797a3ce391fb3fcaf3c8fd1fe579e4fe8ff23c72ff47791eb9ffa33c8fdcff519e47eeb728cf23f75b94e791fb2d0ee5f9ffeeb7c0fb24f8dc542ff8aed4ed1ef0d584c4e0f5ec045fad6ef33ad4783367fca10c35f09aab42b8ae0c89c771ae0a796d3574c758ddb0ccf1f0fe8dab3ce1a9f78ca7c9339e719ef14cf18c6796673ca33ce359e0194fa3673c633de399ec19cf4ccf78ea3ce3c978c6d3e019cf24cf78e67bc633c3339e1ecf78e679c633d2339eb4673c133de399ee194fad673c633ce399e019cf34cf78e678c633d7339e119ef18cf68c67bc673c533de399ed194f4d084f8f231edb75b43d55886dbb8eb61ab16dd7d15623b6682e9a8be647b7e657c71fbb231d0cfecd36f54819cbddd0be1a785cbcdf39cab378ffdd2ebdae18ef71c829ad761b5af5185a65a0cf2ed06fb703fd521097d7cdcb1c4f9885d9c6ac62ef893f76719cc1d8ac4f60f0f0638f632d1ce5591c0ffa82708d395e06fae036ef7390670ae2f2ba79b92f24767310af167b2bd0626f08cfde2a6bc1f1a232ef4a20b30f3aabd8d7c41e3b9f4b1bb1599fc0e0e1c7358eb570936769dfda17846bccf132d007eb749f833c531097d7cdcbfb603b08b3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3dfcc2af6fed86397e6ef3136eb13183cfcd8ef580b377996e6effb83708d395e06fae036ef7790670ae2f2ba79b91fb683300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb330fbcdac621f883f76f13e1f8ccdfa04060f3f0e38d6c2519ec5f9fb6b83708d395e06fae036bfd6419e2988cbebe6e56b613b08b3308731abd8d7c51ebb743e0f63b33e81c1c38feb1c6be126cfd278707d10ae31c7cb401fdce6d73bc833057179ddbc7c3d6c8728cc7d0964169d45671bb3e82c3adb984567d1d9c62c3a8bce3666d15974b6318bcea2b38d5974169d6dcca2b3e86c63169d45671bb3e87cf4e8ac621f8c3d76a1387f8fb1599fc0e0e1c741c75ab8c9b3347f7f4310ae31c7cb401facd31b1ce49982b8bc6e5ebe01b6c37067ee4b20b3d4467598a53684d9c62cb521cc3666a90d61b6314b6d08b38d596a43986dcc521bc26c6396da10661bb3d48630db98a53684d9c62cb521cc3666a90d61b6314b6d08b38d596a43986dcc521bc26c63f6a13654ec1be38f5dbc9f1d63b33e81c1c38f1b1d6be128cfe2f52f3705e11a73bc0cf4c13abdc9419e2988cbebe6e59b603b08b3308731abd837c71f3b9f3662b33e81c1c38f9b1d6be128cfe278704b10ae31c7cb401fdce6b738c833057179ddbc7c0b6c87a431e3f64bc517bb78dd26c7a8d1cfca77ab6e8f00df6dba5d0bbe37e9f648f0ddaedb75e07bb36e8f02df5b2037f6bd55b71780ef6dbadd03beb7ebf636f0dda1db5783ef4eddde0dbe77e8f61ef0dda5db7bc1f74eddbe067c77ebf63ef0dda3dbfbc1f72eddee07dfbdba7d007cefd6ed6bc1f71eddbe0e7cf7e9f6f5e07baf6e1f04dffdba7d03f81ed0ed1bc1f7a06edf04be87747b17f8dea7dba3c1f77edd1e03be0f409b9f3fa8db0de0fb906e67c0f7b06e8f05df23badd08be47757b1cf83eacdb4de0fb886e8f07df47757b02f83ea6db13c1f771dd9e04bec7747b32f81ed7ed29e07b42b7a782ef49dd9e06be4fe8f674f07d52b76780ef29dd9e09be4fe9f62cf03daddbb3c1f769dd9e03becfe8366edfcfeaf6cde0e371e016f0f138702bf8781cb80d7c3c0ebc097c3c0edc0e3e1e07de0c3e1e07de023eaebbb7828febee6de0e3ba7b3bf8b8eeee001fd7dd9de0e3ba7b07f8b8eeee021fd7dd3bc1c7757737f8b8eeee011fd7ddbbc0c775772ff8b8eede0d3eaebbf7808febee3ef071ddbd177c5c77f7838febee01f071dd3d083eaebb87c0c775f73ef071ddbd1f7c5c77382e34ebf607c1778c6e7f087cc7eaf6c3e03b4eb71f01dff1bafd28f84ed0ed0f83ef44ddfe08f8e6eaf647c1374fb73f06bef9bafd71f0f17bd363e0cbeaf6e3e06bd1ed27c077926e3f09be56ddfe04f8da74fb93e0cbe9f653e06bd7ed4f812fafdb4f83afa0db9f065f876e7f067c9dbacde382daff1a2017ceb301b84f0ae1615f3df07407f11e33712c5e372fe78191756caf3e63be52c69cc1a8783a1c6886b5c18f729f493a80a7e080c7519ec5cf249d464e7923a70cf43911f2ec7490670ae2f2ba79b91362bbd8e6a8459d5eef5c438b5ae8f3867e4353ef7fe574e475a8fa6d0fc9c5958e39832717127bb1631d79dd3c262eae42ec8546ec3623368ee7fc28b76f2f04e6450e98d57abbe25f6f71df3e59af8beb99e3b4414e4b4083b872c2d8296d1c87fdb5d0fedfa681bedc8ff5e0f74e6657fb116f4b64375fd761bc2e037d1687e4df1dc49b7f97c1d36530abe3ffff6a1ae070b03f146b60b1c1c1cb6da05d9745bbc5a01df769071f1fe374828f8f15781d78ac84c7112df1e71b3af6f0720b30b26f2130b68430b6c7cf583cd66931185b42b465df22e059e848b34506cf5c431f7c5f1e65f4e1d7d6429ff1fa835d6330f83304f755b53f363590177f66fe4f10efb85ae7402ffc3c1f803e81a1213f98a13e18f8cc1f27cf9860e033fdfefebe7d3d3b7ad7f5f66c4b015aad8189cfa990346ac087ed1121be20183c7581539e3c7581539e35862c3865c2fdd5472995164f0ff4eeded9bf714fef9eadfb0eeeedefddb6b66f07528f34e891d4960192a28f1ff5c1c0244b7710efc98e3a2356b9e2a987e751f1f3b43bcab3f8c633dac8a9cec829037d46c2ff463bc833057179ddbc3c3a24768c0351518b311568312684674c95b5c0896af6e19ecaffc7931335462eb847634e669dc79a10073c01d69fd270ea7f6a671fa99319150c6c6c1e3dd551a5da086a8653bd6ba9194c7570a686203523a96620d58ca39a6154338a6a0651cd18aa19423523a86600d58c9f9ae153337acd4169c64ecdd0a919b9e381eb7bc0aa3e51ab774735a3a666d0d48c993aaa52effeea48441dfdaa2335f5e94d1d1da84f956a8641bdd3aaa318f50eadde55d5919a3a425347d4ea087329d932b253c8966bad5790ad243b95ec34b2d3c9ce205b457626d96ab235646791ad253b9bec1cb273c9ce233b9f6c1dd97ab20d641bc92e20bb906c13d945649bc92e26bb84ec52b2cbc82e27db1294ce4a5d41b635289d8dea25db4eb683ec4ab29d645705a5b3526ae65d9d8952679ed4d530ea6c933abba4ce26a9b347ea6c913a3ba4ce06a9b33fea6c8f3abba3cee6a8b337ea6c8d9aa95733f36a26feb6a034d3ae66d6d54cba9a395733e56a665ccd84df119466bad5ccf65d4169e65acd54ab99693513ad669ed54cb39a595633c96ae658cd14ab99613513ac667ed54caf9ad95533b96ae656cdd4aa99593513fb68509a695533ab6a2655cd9caa99523533aa66429f084a339d6a6653cd64aa994b3553a96626d54ca49a7954338d9f23fb3cd917c8be48f625b267c8be4cf615b2af923d4bf635b2af937d83ec9b64df22fb36d977c8be1b946af0fb643f20fb21d98fc89e23fb31d94fc89e27fb29d9cfc87e4ef60bb217c85e24fb25d9afc87e4df61bb297c87e4bf63bb297c97e4ff60ad9ab647f20fb23d99fc8fe4cf617b2bf92fd8dec35b2bf93bd4ef6463070c601078adfe8059efdeee9efefddbdb7bfb9bfaf79f7815dfd3bf7ee3ad87cddcefe2b9bfbaeedddb77d57df75f8e23bf4d0c453fb2bf6edeb39d8bc73cfb6deeb9bfb0ef437f76d6fbea2efc09e6dfbf1458fe917cd3c3462cfb66df6605faa390cd2af0e31e873fa757cd26475f9dc9e1f8a202f0ee545ff1a6242f7eb53514bf5f2fad2116df3fe5d7dfdcdb9e63df4b76717bda6775b6b33fe6f3f89bcbfbf797f7fcfbefee6edfbfa7637b7b7e27a1fcc0c2189d79b86f0a2a6f195671efc1f78fc6b863d5f0300", + "bytecode": "0x1f8b08000000000000ffed9d777c1dc5b5c7f74ab25cae2eb66cb937d1dd645d5d755b3632ee0d4cc780c14532186ccbd8a277d2480809e9850478a92421bdf79e90de0b4948200909297fbc7cde7b9ff7f9bc3ff8bc99d59ce87787d945f7b2479ed53dfbf91cdfd9a3b97bbee7ec99d9bd33b3eb4c30b4fd5349c694ab959c143c77a3bff79acffc0bdb5a123c569e93339312ceaa947056a784b326259ce352c2599b12cef129e19c9012ce8909726ab6aaa0784b9a7712435c9366cca62ca6752988692e65313d2105319d1ca4a38f9a9212cefa94704e4d09e7b4947036a484737a4a3867a48473664a3867a58473764a38e7a484736e4a38e7a584737e4a3817a48473614a381b53c279624a384f4a09e7c929e13c2541cec5c079aaf93ccd7c9e6e3e17994faabbc47c2e359fcb8c8f3566bf49c97225cd9acffa9b9e6828286955d266fdad5d4987924e255de66f8de66fdd4a562859a9a447c92a25ab959c6162b146c9994ad62a59a764bd920d4a362ad9a464b3922d4ab62ad9a664bb92b3949cad64879273949cabe43c25e72bb940c9854a2e5272b1c5b253c9254a2e557299925d4a2e57728592dd4af628d9ab649f923e25fd4af62bb952c9554a0e28b95ac9354a0e2a39a4e4b092012547945cabe4a892634a06955ca7e47a253728b9d18ad94d4a6e56728b925b2dcedb94dcaee40e25772ab94bc9dd4a5ea4e4c54a5ea2e4a54a5ea6e41e252f57f20a25f72a79a592fb94bc4ac9ab95dcafe4354a5eabe4754a5eafe40d4adea8e44d4adeace42d4adeaae401256f332cd410deaee441250f297958c97f28798792772a799792772b798f92f72a7944c9fb94bc5fc907943caae4834a3ea4e4c34a3ea2e4a34a3ea6e4e34a3ea1e4934a3ea5e4d34a3ea3e4b34a3ea7e4f34abea0e48b4abea4e4cb4abea2e4ab4abea6e4eb4abea1e49b4abea5e4db4a1e53f21d25df55f23d25dfb762fe03253f54f223253f367fa3f1a59f28f9a929ffcc7cfedc7cfec27cfed2faceaf94fcdad23daee43796eeb74a7e67ca4f98cfdf9bcf3f98cf27cde753e6f38fe6f34fe6f3cfe6f369f3f917f3f957f3f98cf9fc9bf9fcbbf9fc87f9d47393fd0d43e509c1f0d61b24d427b5f5f7e9b9090af6a941f1a663516dfe469f8d465f63f6e9936237ceec8fb3f4b566bfd63ace04b33fc1d2d79bfd7a4b3fcdec4fb3f4d3cdfe744b3fd3eccf047d3680314aa3d7ba6aa3ca808ef2b00a74e382e298685d2d1d0e74e383e258681d9dc75ad04d34baf1a09b647413409735ba891433257546d71b249513f93dfab8b9a48f6be66d4e489e779f3eee6426de29c9f3f6ebe3d633f0eafc986a8e3505f2669ad1d583ce742bc154d04d37ba69a09b61740da09b6974d34137cbe866806eb6d1cd04dd1ca39b05bab946371b74f38c6e0ee8e61bdd5cd02d30ba79a05b6874f341d768740b4077a2d12d04dd4946d708ba938dee44d09d627427818efacf934147f777a7189dee136a32f01da3a7fe28fc0ef5b9a03b9dfa5bd02da2be16748ba99f05dd12b04dbaa5d087906e99d1517fa4ffd665cabd4152f95fe8d3c7ed4efab8eac8fab82b933f6e38a7d5130cc7b517ec7443ac56997282eb665ad076c608d9217d0d9437425daa47f1a06b0ab1eb6bc70a535e15f3bd2eeb7b39a8b3c2e17f6f90acff2b2d9e9516f338f09f27675b5b246747bc959cb317405d3bf7e8fe662ce6ec16e060c8d976c9d9116f25e7ec3ea86be71edde38ec59cbd18381872b69b27670b79c9d9a1b1ae2070e71efdce198b39bb1f3892cfd976c9d9916f25e7ec1d50d7ce3dfaad3b167376103892cfd9ce6eb93718f15672cede0775eddca37197b198b377030743cef6493f3be2ade49c7d00eadab9476380633167ef078ee473b69b29675b256783a179cb2070e71e8d478fc59c7d103892cfd97d323e3bf2ade49cfd34d4b5738fe646c662ce3e0a1cc9e76c1fd7f86c41727668bd4610b8738fe6e9c662ce7ece94f5dcd8cfccdcd802d0fddce81682ee17b0ce8074bf34ba13c12f8636d0296d60c45bc96de05750d7cee5934c792cb681ef030743ce764bce8e782b39679f86ba76eed1fa85b198b3bf010e869cdd2b393be2ade49cfd2fa86be71eada5198b39fb8c29ebfb8527ccfdc222d0fddee81683ee0f46b704744f1add52d03d6574cb40f747a36b02dd9f8c6e39e8fe6c74cda07bdae8f2a0fb8bd1b580eeaf465700dd3346d70ababf195d1be8fe6e74eda0fb87d17580ee9f46d769747a1e8bd6543d667413c0f7de20b9731baea30a8ab78cb5df0be565bc3cf95c50fc9c00d95a9ebcad56ed7b533072df97034f3383ef59b031129e66e0c927cf13fe1e6d49feb8e1396eb2629a055b4de05781c1af0cd8a263d33ed9cb810efb8d8283b13579c642066cd1b169bf15184987fd183d8743ed47f7cdf332c3bc0c6d29bc3ea3bd5ee0207b355027d3305cb7d1b0d5c1dfa90fa88332f6f3794bc794ab61aee0c359bdb0df028ce4637ef4190b23656cb618b9fa8d0cd8a263dbb6eb1cf1d1316b75c4ac8d89b1d562a4fd3660a4f8b58e3e6361a48c76bfc0d427b58cb44fa2b8e4473f66233aaf39d0e1bd5e9b83b13d79c6f0bcb6598cb4df0e8ca42b000fd7f530aabdfa629be33e04f399ae5974fd217b3550a7b57ab8ee26b89e32f4a18552ef4db14f4ffe3c15f2783d1b090ff3b96b61cac73cf69dcf06c9e69adde6f356acb0cd635fced54f46f5e5644f98855998855998855998855998855998855998855998855998855998855998fd678e9a9773ad67389e8ca46b011e8e71fef0dd53e6583807f438cceb243f6f51c8e35c3dad635c64f95c0375fe3733ccf684639d04ce9d2fb7744ceb94c27389eb947a619fece1ba0d5c37c5b0f624e4596af1d8b6eb1cf1f1711d894f6b34a2d669f914b31ce8703d5c13134f549e35396c372666bbb08fa7ed14f2fa3d3ffa5d79d49fd86d04d7be2db174ba4feaa81ef69b23074a9d77c6eb0695939cc7c57c435bc9afb72914ad4fa80a8aaf15784fc1b046a568be9ad646b45bb66bb04e55f0ef73d3017fef0d9ebb4608ebd0b1697f117cb7c33af6643e7f63fbc376e0a672ade5db32e0a63a93aa867dfcac2933ddcf1470fd6c00bc81e5136db83e23f9fbbda1f522851278da808763ed1ad37d6d1ef331e9f5221d56ac5cf7cb54a71de2d7c110bfb8356b644f98855998855998855998855998855998855998855998855998855998855998fd67c6f75f102b3e23dde209e328adb109e733e8bd45382ff640d5b05dee39409a735a6cf98ccf283f5335ccf69029e33b025ccfbbe3b9e49a5b8b3a9764af2e78ee73fa4ce772c4ef7e6873c4acc311b34e2646bbcfa0fd4e60a4f875000f577b6cb7786cdbd867b4791ab3a87e966bfd4a549eb9d6293426667b68bd08c7bc2ead17b1af5f2d564c719d04e9701e1cdfad82ebb17c7bff8bbd7601fb295ca3957cbf59289a03b6d70a923d5c27f175135b5a27917c3f50c8735e23a88dd29a9082c357aaf3185ce7be6bcab856a8058ef5b8e3efb4c5ad49c03e95e15d99e1f9a57737d2f9ed76d85e09ac09d96e41db19236487f43550fe75d5705dfb5d90146b62d76dc47e5fa5eb7b79eb7b39a8d3e5f0bf3748d6ff6e8ba7db62d6b9f303c8b3c7e15e8fab4fea0adc315a0431a23a78cfcbb0a6c8d947da6ba6751d3affe3ad3a787f4a759e823e2a6a4dbaeb3d805cf70b51ef01c4fb05d73d8deda3bd76bcd2d703fe0bfa8b0ef87b6ff0c2d703fe0b72c8755f4ac75f0cc727aef141f4b585eafc8f751de56a5bcff7de2bd76f3fe2c5f58654e7ffa0af5a66d6e546fd8e713d67c1f5bb21eab90fb287f754a5f88efd42d2d746cc4764217b988f3526d6948f1d11dccb1ddf1d1ff15d8a15ad2fc7dfc976fc741c127f47b8e96fba2d5fa84d75812fffbe7e832f3cf74c43f79fc9fb5a7c3f447d50abc357aa3315de05d760ca59384fd8579eecf83b6d71f79ff85ef39ee47d0ecf2fbdbf9bce6f8fc3f66a604dc8760bdaa6fb4fb243fa1a289f543d5c97ea513c28d6c4aedb08ddc321bbfdbd76eb7b39a8b3d2e17f6f90acff3d164f8fc5ac736726e4d9c9f0ac05575fbd3222468b214654079f75b47fffe36f79bcc61cafdff2f8ce4fecdb97414c47eb9da9f6f8adebfe64b11563bc3f69817e36eba86b8f4bd33524c9f5e9f83cd052b08bcf032d658a672e288e67cee2e0b43dd9b23d79146dd75bb6eb47d1b6c45c62ee53cc7dfabf30f0ffaca84a0163750a186b52c0382e058cb529601c9f02c60929609c9802c6492960cc02e3f1bcb633c4a7e0d9fff7147baf81b619dee710c6625930f25834f1f2c4defba06d8677a894fcff0d30ff5f582de5fe5f5839f8ded414304e4b0163430a18a7a78071460a1867a68071560a1867a780714e0a18e7a680715e0a18e7a78071410a1817a680b131058c27a680f1a414309e9c02c65352c0786a0a1827a48071092f63a15c46cdc3f11ecd6c50bc8eebf97898dfeb19be9fd0f50e518eff77b654df99dfe9db52ee3bf070fd02efffa3f8c2ded3c7b13ea1d4f7f4c5fddfd34c8c857219b9d69be0da9691f0b8d6a0e479190be532723ddf81cf1b8e84c7f5ffe0f23e6f3314b37218b9d66395ba5e109fc36b77c48c81b1502e23d79a7e7cde70243caee702f3bc8c857219b9d6be66c1c64878ba20669d8e98313016ca65647a762b8c5957093cf88c539723660c8c85721935cf0aa6987597c0b30262d6ed88994f8cc893f4fbc6bb1db6389e892bd5776240c68929609c9402465c83c0d17fc5ad41e8e68d4fa1dcf8709dafb83508689be1198c3016b8e6fef962d1c3cb13bb06016daf628a053e13f17cb158053c1ccf6864c1c64878882107df9b9a02c66929606c4801e3f41430ce4801e3cc1430ce4a01e3ec1430ce4901e3dc1430ce4b01e3fc14302e4801e3c21430e26f55867bc5d8df2fabc6b8eda8df2a63dd76d4ef92b16e5bf25cf2bc126c4b9e4b9e57826dc973c9f34ab02d792e795e09b625cf25cf2bc1b6e4b9e47925d8963c973cf7c9761ac6f88571ec31224f63723c79f41d6d9de181ef673878324cbea3ad5e0f7ca772da1857a78071450a18258e436b10cb61d43c6b98787a4be059033c6732f1ac2981e74ce0599b3c4f98536796c0430c39f8de8a1430ae4e01a3c451e2e813a3c4b172e2288cc2288cc2783c18d3d087cb7566e8b74b398c9a675df23c61ccd696c0b30e6246dfcbf33216ca65d43ceb93e70963b6ae049ef510b3758e98313016ca65d43c1b92e70963b6be049e0d10b3f58e98313016ca65d43c1b93e70963b6a1049e8d10b30d8e98313016ca65d43c9b92e70963b6b1049e4d10b38d8e98313016ca65d43c9b93e70963b6a9049ecd10b34d8e98313016ca65d43c5b92e70963b6b9049e2d10b3cd8e98313016ca65d43c5b93e70963b6a5049ead10b32d8e98313016ca65d43cdb92e70963b6b5049e6d10b3ad8e98f9cab822058cab53c0c81cc742b98c9a673b13cfb61278b603cf594c3cdb4be0390b78ce4e9e27cca9b34ae021861c7c6f450a1857a78051e22871f48951e258397114466114c6d218cf4801a39c6b61f49591e1f755ecf329678d71db51cfa78c75db51cfa78c75db92e792e795605bf25cf2bc126c4b9e4b9e57826dc973c9f34ab02d792e795e09b625cf25cf2bc1b6e4b9e47925d8963c973caf04db92e792e795605bf25cf2bc126c4b9e4b9e57826dc973c9f34ab02d792e795e09b625cf25cf2bc1b6e4b9e47925d8963c973caf04db92e792e795605bf25cf2bc126c4b9e4b9efb647b47f2b60ba53ec3ba0378ce668805939f797ddc73ccb19e4d307e3a56e75ab13acb8a550eea9c03f13b97217e19b04bc7a67db2572af3691e3033d92e9ca08e3111fc271babad7868fbe731f91ed5d79f37c66d47f5f563dd76545f3fd66d4b9e4b9e57826dc973c9f34ab02d792e79ee8b6d2cd704c3f7edf47e257d8cf34d799cd9a7fa67c0f7a84ecbf8a1cfc981b4210edbd286e45a5109b625cf25cf2bc1b6e4b9e47925d8963cf733cf2f48de76383786bf2ff41637377601f09ccf100b263ff3daa70b2d9fceb37cca411d7c67ed850c7e66c02e1d9bf62f84f3903666cdb3ca9489350bf55679c248baf37979c2f6b52a28dee2dad785c0c3d00e5a98fc0cdbd745964fab1c71a73a98ab1731f8e96a3bb47f119c87b431e7c01eb16683e273ea0323e92ee0e509db576f50bcc5b5af8b8087a3ff61f2336c5f175b3ef53ae24e7530572f66f0d3d57668ff62380f6963d63c6be0ef7acb42bd359e3092ee425e9eb62cf84c5b5cfbba187838fa1f263fc3f6b5d3f2698d23ee5407737527839faeb643fb3be13c08b330bb9835cf99a64cac59a877a6278ca4bb8895a72d9f059f698bebc776020f473fcf14f7b01fbbc4f2e94c47dca90ee6ea250c7ebada0eed5f02e7a114e6d5296496384b9ca39825ce12e7286689b3c4398a59e22c718e6296384b9ca39825ce12e7286689b3c4398a59e22c718e6296384b9ca39825ce12e7286689b3c4398a59e22c718e6296384b9ca39825ce12e7286689b3c4398a59e22c718e6296384b9ca39825ce12e7286689b3c4398a59e22c718e62963897c7ac79d69a32b166a1de5a4f184977312f4ff8fccedaa078cb58fbbd50be04787632c487c9cf70ddfba5964f6b1d71a73ad8be2e65f0d3d57668ff52380fa530af4e21b3c4b93c66cdb3ce9489350bf5d679c248ba9dbc3c613fb62e28dee2fab14b8187a39f67f233ecc72eb37c5ae7883bd5c1f67519839faeb643fb97c17910666176316b9ef5a64cac59a8b7de1346d25dc2ca53089f435c1f146f71fdd865c0c3d1cf33c53decc776593ead77c49dea60aeee62f0d3d576687f179c87529857a79059e22c718e6296384b9ca39825ce12e7286689b3c4398a59e22c718e6296384b9ca39825ce12e7286689b3c4398a59e22c718e629638574e9c35cf065326d62cd4dbe00923e92e65e5690de71d3604c55bdcbcc32ee0e19897618a7b38ef70b9e5d30647dca90eb6afcb19fc74b51ddabf1ccec358675e9d4266c98dd16196dc10e62866c90d618e6296dc10e62866c90d618e6296dc10e62866c90d618e6296dc10e62866c90d618e6296dc10e62866c90d618e6296dc10e62866c90d618e6296dc10e62866c90d618e62f6213734cf465326d62cd4dbe80923e92ee3e509df7bb03128dee2d6ed5c0e3cbb18e2c3e467b86ee70acba78d8eb8531d6c5f5730f8e96a3bb47f059c0761166617b3e6d964cac49a857a9b3c6124dd2e5e9eb01fdb14146f71fdd815c0c3d1cf33f919f663bb2d9f3639e24e7530577733f8e96a3bb4bf1bcec36e61166607b3e6d96ccac49a857a9b3d6124dde5bc3c613fb63928dee2fab1ddc0c3d1cf33f919f6637b2c9f363be24e753057f730f8e96a3bb44ff6845998a39835cf165326d62cd4dbe20923e9aee0e52964c167dae2fab13dc0b39b213e4c7e86fdd85ecba72d8eb8531dccd5bd0c7ebada0eedef85f3903666cdb3d59489350bf5b67ac248baddbc3c61fbda1a146f71ed6b2ff070f43f4c7e86ed6b9fe5d35647dca90ee6ea3e063f5d6d87f6f7c179481bb3e6d966cac49a857adb3c6124dd1e5e9eb07d6d0b8ab7b8f6b50f7838fa1f263fc3f6d567f9b4cd1177aa83b9dac7e0a7abedd07e1f9c87b4316b9eeda64cac59a8b7dd1346d2613f455b15306e67620c2cc6c08a0ff22cf08c6796673c533de399e8194fb5673c4b3de3e9f68ca7cb339e859ef12cf68c67b6673c05cf78a679c6b3dc339e499ef1b47bc653e319cf32cf784ef78c67a5673c733ce369f08c6789673c59cf78c679c6d3e4194f8f673c1d9ef1ccf58ca7d5339ee99ef1347bc653e7194fce339e5acf787678c633cf339e199ef19ce019cf64cf78c67bc6d3e919cf7ccf78da3ce399e9194f8b673c533ce3a9f78c6782673c8b3ce3c978c0930d9ebb6e200b7fdf01ba2aebbbfafab2a161f8ef344f5b05dfe937e56ac7b1fb4047f3bafd8eef629cb8e69ed1562fec93bd3ae0e8f7846791673c133ce3a9f78c678a673c2d9ef1ccf48ca7cd339ef99ef1747ac633de339ec99ef19ce019cf0ccf78e679c6b3c3339e5acf78729ef1d479c6d3ec19cf74cf785a3de399eb194f87673c3d9ef13479c633ce339eac673c4b3ce369f08c678e673c2b3de339dd339e659ef1d478c6d3ee19cf24cf78967bc633cd339e82673cb33de359ec19cf42cf78ba3ce3e9f68c67a9673cd59ef14cf48c67aa673cb33ce359e0194f95836707134fd4b3bb3b3cb1cd701ef2fab8fb997cbad21cabd61c97f8c95e0dd4a937038f7abe01bf4b5cf67c3b8e2d5f0931e27a6f42cee2a1fd7d63dcf664cbf6e40ab15d6fd9aeaf10db92e792e795605bf25cf2bc126c4b9e4b9efb68fbd9e46cb7639e55812d1fd647cbfb93e279e4fd49f13cd59ef1c8fb93e279e4fd49f13cf2fea4781e797f523c8fbc3f299e47de9f14cfe3dbf3f1f23ea7781e799f533c8fbccf299e47dee714cfd3e4198fbccf299e47dee714cf23ef738ae7a9f38c27e7198f6fef7392f727c5f3c8fb93e279e4fd49f13cf2fea4781e797f523c8fbc3f299e6782673c8b3ce3c978c0f37cef4fc2f71ed15acb7da0a3f59c71ef59cac271ae041d8d0fd231f4f5ea9c86e73254c177ae7270ed77d8233b5739be3b1a71475bbdb04ff6f07d4c5779c2b3c8339e099ef1d47bc633c5339e16cf78667ac6d3e619cf7ccf783a3de319ef19cf64cf784ef08c6786673cf33ce3a9f58c27e7194f9d673ccd9ef14cf78ca7d5339eb99ef17478c6d3e3194f93673ce33ce3c97ac6b3c4339e06cf78e678c6b3d2339ed33de359e619cf0ecf786a3ce369f78c6792673ccb3de399e6194fc1339ed99ef12cf68c67a1673c5d9ef1747bc6b3d4339e6acf78267ac633d5339e599ef12cf08ca7cac1c3f54ea45c30bcf5c2fe68bc8fe9f96cebfda51017bd65e1efa3f19ce40e8b91f6719d01f212cf52269ea8e7de977a605bfb4fbfb568ce220b7fc7e770b8726aa9c548fbae9cc27584cb9878a29ed75fe6816d1d8b2653a639ee2cfcbd0918b9726a99c548fbae9caae7e569cb82cfb4c5adedc136c7710e99fccc63fb4bf01d11791dabed56ac9aac58e5a0ce683c2718d51f903d6116e62866cd43632dc48ad7b3d1784e7a248caeeb2b034fd83f2e0f8ab7b8fe713bf0705c3f98fc0cfbb103964fcb1d71a73a98ab0718fc74b51dda3fe0b0dd18241b8bab47108bab1d3c578f722cc85ea9cc3b52c8ec439c350fad9d20565c4fdcec0923e996f2f284fd637350bcc5f58f57030fc7f583c9cfb04fb8c6f2a9d91177aa83edeb1a063f5d6d87f6af81f3500af38114324b9ccb63d63cb4a69a58b350afc51346d26d67e529e4b3e0336d71fdd835c0c3d1cf33c53decc70e5a3eb538e24e75b07d1d64f0d3d57668ff209c0761166661166661166661166661166661166661166661166661166661166661f69b59f3d0b32ac49a857a054f184977352bcfd0bc432128dee2e61d0e020fc7bc0c53dcc3798743964f0547dca90ee6ea21063f5d6d87f60fc1791066611666611666611666611666611666611666611666611666611666611666bf99350fbdd39558b350afd51346d25dc3cb133eb7d51a146f71f30e878087635e86c9cf70dee1b0e553ab23ee540773f530839faeb643fb87e13c08b330bb98350ffd5f0fc49a857a6d9e3092ee202bcfd0fc695b50bcc5f563878187a39f678a7bd88f0d583eb539e24e7530570718fc74b51dda1f80f3500af38114324b9c25ce51cc1267897314b3c459e21cc52c71963847314b9c25ce51cc1267897314b3c459e21cc52c71963847314b9c25ce51cc12e7ca89b3e6a1ffa38a58b350afdd1346d21d62e5690de71dda83e22d6ede61007838e66598e21ece3b1cb17c6a77c49dea60fb3ac2e0a7abedd0fe11380f639df9400a992537468759724398a398253784398a59724398a398253784398a59724398a398253784398a59724398a398253784398a59724398a398253784398a59724398a398253784398a59724398a398253784398ad987dcd03c1da64cac59a8d7e10923e90ef3f284ef3de8088ab7b8753b47806780213e4c7e86eb76aeb57cea70c49dea60fbba96c14f57dba1fd6be13c08b330bb98354fa729136b16ea757ac248ba015e9e42167ca62dae1fbb167838fa79263fc37eeca8e553a723ee540773f528839faeb643fb47e13ca48d59f3749932b166a15e97278ca4c3eb7217134fcee2c9396271bc6cebfd6e53ae339f59f87b373072f5875d1623ed638e232ff17433f14cb678263b6271bc6c6bff579af209e6330b7f5f098c5c39d56d31d2be2ba72603cf4a269e7a8ba7de118be3655bc7a2c794a798cf2cfcbd0718b9726aa5c548fbae9caa079e1e269ea83ea967146c47b5afd1b01d952ba3615b621e1d738676178e0ff404c55bdc7d355e5b38fa2a263ff3aeeb778fe5135ebff11ef5785d9f845998a39899ee73dbb2966d8a4f60f1d0762d732c46f37776b7e5531a7e67c7311f4821b3c4b93c666dfb58f2b6dbb2966d8a4f60f1d0768c39164c7e86fdc160e08e31d9cb411dccd341063f3360978e4dfb83701e4a613e904266897379ccdaf67589db1e7aff30daa6f804160f6dd731c782c7cfa1fee0fac01d63b297833a98a7d733f89901bb746cdabf1ece83300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb330fbcdac6ddf90b8eda1f17bb44df1092c1eda6e608e058f9f43e3f73706ee1893bd1cd4c1737e23839f19b04bc7a6fd1be13c08b3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3dfccdaf64dc9db0e9fc741db149fc0e2a1ed26e65830f9198edfdf1cb8634cf6725007cff9cd0c7e66c02e1d9bf66f86f320ccc2ec62d6b66f49dcf6d07c1edaa6f804160f6db730c782c7cfa1fee0d6c01d63b297833a78ce6f65f0330376e9d8b47f2b9c8752980fa49059e22c718e6296384b9ca39825ce12e7286689b3c4398a59e22c718e6296384b9ca39825ce12e7286689b3c4398a59e22c718e629638574e9cb5eddb12b7dd1a8edfa36d8a4f60f1d0761b732c78fc1c1abfbf3d70c798ece5a00ee6e9ed0c7e66c02e1d9bf66f87f330d6990fa4905972637498253784398a59724398a398253784398a59724398a398253784398a59724398a398253784398a59724398a398253784398a59724398a398253784398a59724398a398253784398a59724398a3987dc80d6dfb8ee46d87cfb3a36d8a4f60f1d07607732c98fc0cd7bfdc19b8634cf6725007f3f44e063f3360978e4dfb77c279b8539885d9c1ac6ddf95bced42d6b24df1092c1edaee628e05939f617f7077e08e31d9cb411d3ce77733f89901bb746cdabf1bce43da98f1fc6592b31daedb241b55e653eb5e64cad5a07bb129d780ee25a63c0e742f35e55ad0bdcc94c783ee1ef08d742f37e525a07b8529f780ee5e535e09ba579a7237e8ee33e52ed0bdca94af05ddab4df928e8ee37e563a07b8d290f82eeb5a67c1de85e67cad783eef5a67c03e8de60ca3782ee8da67c13e8de64ca3783eecda67c0be8de62cab782eeada67c1be81e30e5db41f73653be03746f37e53b41f7a029ef00dd43a63c11740f9bf224d0fd0794e9f31da65c07ba779a720e74ef32e51340f76e539e0cbaf798f214d0bdd794eb41f788294f05ddfb4c791ae8de6fca0da0fb80294f07dda3a63c03741f34e599a0fb9029cf02dd874d7936e83e62ca7340f751539e0bba8f99f23cd07ddc94e783ee13a6bc00749f34e585a0fb9429e3f9fdb429df053aea2fee061df5172f021df5172f061df5172f011df5172f051df5172f031df517f7808ef2eee5a0a3bc7b05e828efee051de5dd2b414779771fe828ef5e053acabb57838ef2ee7ed051debd06749477af051de5ddeb404779f77ad051debd017494776f041de5dd9b404779f766d051debd057494776f051de5dd03a0a3bc7b1be828efde0e3acabb07414779f710e81a4df961d09d68cad87f9c64caef00ddc9a6fc4ed09d62caef02dda9a6fc6ed09d66caef01dde9a6fc5ed02d32e54740b7d894df073aba86bd1f744b4df903a05b66ca8f82aec9943f08bae5a6fc21d0359bf287419737e58f80aec5943f0aba82297f0c74ada6fc71d0b599f22740d76eca9f045d87297f0a749da64cfd876ea7babd91cf148f3af0afc9c14dba09c0dd1b247b0f46b6e8d8b45f00468a77cbe8331646ca98b718354f1b43cc3087688bfb8dd3063cad0c3c4c7e86bf71da2d9f0a964f39a8731af8d9cee06706ecd2b169bf1d6c739c738c45ad39eee9562c6aa0ce2c73f1d2d7c9b838d23174feb6387ce18a63dee2c93b6c7731c7918e4d7d62d728d8eeb06c375bb6b1dfa72dae6d7700732703b33e6e77f2c70ddbf60a732cca67b2d30c3ead841824e513dace18213ba4af817273c3705daa47f1a06b27b1eb7644e712d9edefb559dfcb419d2e87ffbd41b2fe775b3cdd16b3fe9d704ac33007437b0873a0cbe2a0fd66885d7744ecba20765407afbd79a6d8755a3cb49f071ebabf6a071ddda7103fdecf358d02b7ddefb53bb849d7018c79076373f28c85b8eb42333092ae13783a9862669febd3adf8e03dc178ab0e7db706eaac83eb72d65157b7bb799961bfe877fdb341b27d7a2d43bc70cc2180f804560c69238609c1f0b844923c9382e1718763830347f75cd97f6eff9ebe0ca0d55898f89971b851053a2c573b7441503cbc82c3b734bc82c3b7555658705887eaeb9f71da2d1ac2e83f7460f082c3fd87f71dbde9c8607fdfb6812b917a9c458fa4511e2029ea689b100c0f04f506c94edcd45ab6e29267027c8e4f9ea785c9cff0a237d1f2a9d6f2290775c6c1df2632f89901bb746cda9fe8b09d604714c662d2086231c9c1336994638183e9a4c3964a7fc789962acb176cd1e8939de7893a44064f85e3670c9cfe9b6eece38c33e383e1934dbda7bea3d527418fc2eaab961e65d5a3aaba0bd2a3a6fa82a64745f528a81ef5d4a39c7a54538f62ea514b3d4aa94725f528a41e756c0c864615f528a21e353c05b81e0356fd6b5e5f1df5a89f1ee5d3a37afaae4aff5ad37722face5bdf15e8bb017dd7a77fd1ead10d7da5d57731fa0aadafaafa2e51df1deabb797d77ab67b3562959ade40c13eb354ace54b256c93a25eb956c50b251c926259b956c51b255c93625db959ca5e4ec6068b4fe1c25e72a394fc9f94a2e5072a1928b945cac64a7924b945caae43225bb945caee40a25bb95ec51b257c93e257d4afa95ec5772a592ab82a1153c572bb946c9412587941c5632a0e4483034a3a667d0f48c999e21d333627a064ccf78e9192e3da3a567b0f48c959ea1d233527a064acf38dd190ccd2ee8d9043d7ba0670bf4ec809e0dd0a3fff70443a3fb7a34ffde6068b45e8fceebd1783dfaae47dbf5e8ba1e4dd7a3e77ab45c8f8eebd1703dfaad47bbf5e8b61ecdd6a3d77ab45a8f4eebd1683dfafc703034baac4793f5e8b11e2dd6a3c37a34588ffe3e120c8deeead15c3d7aab476bf5e8ac1e8dd5a3af7ab4558faeead1543d7aaa474bf5e8a81e0dd5a39f9f51f259259f53f279255f50f245255f52f265255f51f255255f53f27525df50f24d25df52f2ed602827bfa3e4bb4abea7e4fb4a7ea0e4874a7ea4e4c74a7ea2e4a74a7ea6e4e74a7ea1e4974a7ea5e4d74a1e57f21b25bf55f23b254f28f9bd923f287952c9534afea8e44f4afeace469257f51f25725cf28f99b92bf2bf987927f06c3b324d871d498de8646ecf70c0ef61f3a32d83838d078e8ba8383078e1cbca9f186038357350e5cdf7f74ffc1811bf0cb5f335fa6e98835478feeb9a9f1c0e1befe1b1b07ae1b6c1cd8dfb877e0bac37dc7f04b4f9a2fcd7baec53d7d7dd1c6fef38590fe779946ab4d3f48133d9be37dabad2e232075e57c295f5d9e437973a5a1d9f9f386ee701b8f1d1c186ccc371e56ffee39a8bed3dfb7bc11ff764c05f9d860e3b1c13d47071bf71f1d38d4d8b21c8f3ba5ae0c27663694f1a5b50d23f73cf87fdf1008bb09d50300", "isInternal": false } ], - "packedBytecode": "0x000000028df71de500000036441f8b08000000000000ffed9d079454c799ef6fcf0c493dcd30420284080392c8a1a72730e426470990002123230d0c20860c4316306491a364d972daf57a83d7de607bd76b6ff0aec306e7b45edb72ce3ee7f99df7ce79efed396f7775b6aabb3ecf9f9abaedeee156eb6bf8ee39df74dd6fead6f7fbbe5bb76ef5adea5bb120bbfd4a49cca4cb953c1274dee8ff69f399bcb3ad36c2b2923e396325c25956229ce525c25951229cdd4a84b37b8970f62811ce9e25c2d92b424ecd5616dcbe45cd7b9f87b846cd182fb1985696404c132516d3de2510d3aaa034daa83e25c2595d229cf7970867df12e17ca044381f2c11ce7e25c2d9bf4438079408e74325c239b044381f2e11ce4125c239b84438879408e7d012e1ac2911ce6125c239bc44381f2911ce474b84f3b108394701e708f339d27cd2ff469bcf31e673acf91c673ec71b1f2bccfe042513359b925aeb7f2925754aea953498ffd598ff352a99a4a449c9642553944c55324dc974253394cc34becf52325bc91c257395cc53325fc902250b952c52b258c912254b953caee40925cb942c57b242c9934a9e52b252c92a8b65b592a795ac51f28c92b72859abe459256f55b24ec9734a9e57d2ac64bd920d4a5a946c54b249c966252f28d9a2a455c95625db946c57b243c94e25bb94ec56b247c95e256d4af65931dbafe48092834a0e599c87951c51f2a292a34a8e2939aea45dc9092527959c52725ac9192567959c53f29292f34a2e28b9a8e49292cb4aae28b9aae49a92eb4a6e28b9a9e496929795bca2e46d4a5e55f276c34295fd1d4a5e53f24e25ef52f26e25ef51f25e25bfa3e47795bc4fc9ef2979bf92df57f2074afe50c91f29f980923f56f241251f52f2274afe54c99f29f973251f56f211251f55f2174afe52c9c794fc95928f2bf98492bf56f2374afe56c9df29f9a492bf57f20f4a3ea5e4d34a3ea3e4b34afe51c93f29f96725ff62c5fc734a3eafe40b4abe68fe47cfbabea4e4cb26fd15f3f955f3f935f3f975eb986f28f9574bf74d25ff66e9bea5e4db26fd1df3f9baf9fcaef9fc9ef9fcbef9fc81f9fca1f9fc91f9fcb1f9fc89f9fca9f9fc99f9fcb9f9fc85f9fca5f9d4e3a4ef1f904df70c3ab6741051bb53bfb1598f9350b04704b76f3a16e5e67ff45963f415669f3e2976ddcc7e374bdfddec77b7cae969f67b5afa6ab35f6de9fb9afdbe96fe41b3ffa0a5ef6ff6fb833e1ec0f352a3d7ba72a38a818eea6119e8ba05b7c744ebba5371a0eb11dc1e0bada3f3d81d74bd8cae07e8ee33ba9ea08b1b5d2f8a99924aa34b0751d58964b32e371175b9660ca977f4bc1b74b9559e78fb44cfbb51975bed8157d78ffb4d597da0def435ba6ad03d6074f783ee41a3eb0bba7e46f700e8fa1bdd83a033cd54d00f740f195d7fd00d34ba01a07bd8e81e02dd20a31b08bac146f730e88618dd20d00d35bac1a0ab31ba21a01b6674434137dce86a4047f3538681ee51a31b0ebac78cee11d0519bfa28e8a85ff798d1e976e2df0338c6e8cb403792da61d08da2361874a3a9fd05dd186a7b4137166c936e1cb42ba41b6f74d446e9ff359a743a88ea9a4865ae89495197ab4ad6e54e8ebedccc98db94a023ae69b033096235d5a4239cd7538bb66346c80ee92b20bd10f2523e8a07dd67885ddf4f9a4c7a6a8ee31aade31290a7c9e17f3a88d6ffc916cf648b59d7ffe9c0117d9dad4b499dcd7b2bb8ceae86bc76dda33ecfdd5867970087873adbe8a7cea6925267b3cf1c82c05df7a8df7b37d6d9678023fa3adb207536ffade03abb07f2da758fbefbdc8d75763370445f6727354adf20efade03adb0e79edba47df7fefc63abb0f383cd4d9666967f3de0aaeb35720af5df7e859ccdd58674f0147f47576b2a73a5b277536c88e1f0581bbeed173c1bbb1ce5e078ee8ebec8666e91be4bd155c673f0079edba47cfa8efc63afb1ee0f050677d3d9f4d499dcd8e9b0781bbeed178c9dd58673f64d27a9ce12b669c6110e8be6a748341f735a31b02baaf1bdd50f02bfa6ba0a55eae81bcb782af81cf415ebb2ed798f4dd780d7c12383cd4d946a9b3796f05d7d96f415ebbee0d37e9bbb1ce7e11383cd4d926a9b3796f05d7d99f435ebbeed19c86bbb1cebe6ed2babff01d6bbe9bd6bd6e742341f75da31b05baef19dd68d07ddfe8c680ee07463716743f34ba71a0fb91d18d07dd8f8d6e02e87e62741341f753a34b82ee6746570bba9f1b5d0a74bf30ba3ad0fdd2e8ea41f72ba36b303a3d2640f3533e63743dc15e3a88eedcc6c137da62d67e1ad2b57e799209e0415b75d1dbaad3bea782fc7daf039e7a0fbec7c1463e3cf5c0d3103d4fad977b4f327b8e53564ce3602b057e79b84765dab3c6e0f698d23ed94b800eafd5490ec6a6e8195331b04565d37e133092ae0118a92da5eb47b7cd55b10e5e0fd752e6fe8cf6d2c041f62a20cfcc011d79fb1ab64af83fb50195703cb6ad9cea8a66a43ad2587cc654be8c0d16a3a7eb3b13b3068bc7657b8a27db762ca84e4d2982ed26cb76bd651bdb10da72b5f1d8b7f3d0afaef5d467ccb407d34c59d45f273b78df9a0e3188ca27b44dfd75b243fa0a48a7621d79291fc583da1e62d7d7119d4b64b78f9b641d97803c531cfea78368fdb7bf3f4cb59875bb3b12ee091eae87dbbeb351d9b45f0fb19b1a12bb29103bca331274748f68041db5b55406f66fb11df6d15f8a05b7f7a5d3b0dfe0e06e02c60607a3873e662a57db5c0f8ca49b0c3c294f310bfb6e9912db3eea69e6ba241bd457a36b88ec55409ec1e51d7917439be1a37ee2b5405bbedf81a23f4fa9cc77b2fa0278f0dc79e867d77aaa8f49fc3eff46106d5db3dbc47a2b5661dff9931ee287759fcaa67db227ccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccfc99712c0be7f150be06268cf67c285fcff933efaf3265e118d0eb5ee707a532e300147f9a0f30daf2b902f2fc3ad6c1f603981f44ffc7f94eae73e963ae64ae7349f65cf3957c8e37d7593c758e5870b05d1399edd4063fe73795d4ef8fd1ef60abb7cea93d369f79b79ba5d3f5b4a6bcc36f1f637f858e45625b42e928c7f612c083b67c9c1bbcf6ca82dbdb0fbccff89ac7426d358d974fb16c57409eff80f94453e1ffe9a0737b8179a86cda1f0dc74eb5caaef2e76fceb909f83b08fbf718e45b2370ff66fe4f59878fef33694ff7b854a1f3a8b19d8ebe0f909d43902a8027093c3eee639efa3a49ac8f51cf21b0e788b9fa50f66f727cfe1ec6ee07d37eaedff008b3300bb3300bb3300bb3300bb33027ef6c13666116666116666116666116666116e68899358feb1d1494af8e096391e65d64c633e83d4c382e76bdacc3aeef31401a731a63f98cbf5bfd5a5907dbcb265d19749e6b11762e7d8dad859d4bb2e77a0f8aaf31e518d8a2b26b1db1e060bb2632dbd93904d19fdf8e390429eb9cd659e713c7cef11a7a1fd4537b3e453ce83c27c1d3359ef3dc903dbc9670fe0ba5f1b7d93e628df7127b4e11be978ff27cc8c496c6cea36fab53499fed06bdaf84e609a41cbe529e0f43dbf75193c6f9237550d6a71dffa72dd73835c54ffb3c237a9f33e777a6298bceef0c87ed34b04664bb166dc7acb2495f01e94f957566a07850ac895d5f23f8de97b0e3eaade3129067bac3ff74c4fecfb078f01ceb4dd79d8f413dfb34dcff7db549d34362341a6244793cbf3fd0391fd09ed388ed680f2b0f1d8bef45fb3cb4516173575df780699efc0bbb0790bd44d0f9be90cf1cd37b7d8ed8ebd05e4c85ffa7833b9f23f63ad4219ca71558e58f81f289ab47107e6fa13c3fb0eea31ee670e5f57e1cd7f701e2c5396894e7a7d056f53373350bf93ef0667db7737d1fc0e3c27cc77621ea7b23d64764c1f7ab519eff69d5c7a921dc4d8e63ff77c8b1142bfb5d619541e7f8f979cf5ab6bd9961f942d7d474f085f2fcbb75dd44df67caf63f7dbd538efa3ad406d53a7ca53cff09d7da1bd0bfa4f384f7854479e7ffd396abff49f1d33ecf8adee7ccf99d6dcaa2f33bcb617b0eb04664bb166d53ff93ec90be02d295e51d79291fc583624dec95c089ecf67153ace3129027edf03f1db1ffb32c9e591673a6ed8177932560febdafb63a1db863340662f41b7ba0a3fb08be07d4f5acc3d7bd34ac1f87bfdb221db6edfd20a6c5fa4d8dfd4ccfd53f1963f163ffe461c35c65e26ce7b59f55d27151ce59c6df8860bf107f23e2eb3b5222b83d9e098bc3a7ed2acb7655116d575bb6ab8b685b622e31e714734e6b45e0d8541930fab8d7e17d351f46d7fdaf1c187dfd8e2f5500631d30e2fd8e183dbc87b5b6ab6b51605fa71b30faf80d6aa1cfabf11dccf85b6462f4f12efc42df678befb2a6e37a00a38f350e70ad827c185d6b64f4844f0feb61d476f5bdf9b846462f60f4f12efd7870fbfbff7f1b23aee544c7dd078c3ec691e2c1edcfd57e1b23be839d8e8b7b66cc756ff73c1f2455e833089c7f81cfa0284eae792cbe9ed5dbcfc6681f9fd5236fe02f8e39fb4853fdc6228571a72dd73974c5a7b7f98cc3fffd3e4fbc7d8c97caa6fde9c048ba2abf71ccd9d79ce63716298c3b6db9cea12b3e7dcc673ce8bcfe87a7316be71825ede3382ee9aa3df3c42d9edf164717e3fdc038d313e38c02186702231dd71718d39e186716c09806463aee0160f4f0bc3ac3982e80119feb92fe41609ced897156018cb381918eeb078c3e9e3dc7c16e3e8c7380918eeb0f8c733d31ce2980712e30d2710380719e27c6b90530ce03463aee21609cef89715e018cf381918e1b088c0b3c31ce2f80710130d2710f03e3424f8c0b0a605c088c74dc20605ce4897161018c8b80918e1b0c8c8b3d312e2a80713130d2714380718927c6c505302e01463a6e28302ef5c4b8a400c6a5c048c7d59400e3b012601c5e028c8f9400e3a325c0f8580930f62c01c6b1c0f878f48c99efd74b0b607c1c789645cf531f071bf9f02c039e27a2e7a9f5e467667ed6725356d4ef485b61c5ea712b5609c8b31ce2b7c243fc626097caa67db227ccc21cc6ac79a87d22d638e45bca8491744f78e6895b3c7acbd53eaef0cb934c38e2a16d3d19bdad54a1be3f093c2ba3e7c9dcab9e2c806725f03c153d4fad273f33f79455964f4f5a3e25200fb61bab3cf81903bb5436edaf72d8ae09a28dc5ea3c62b1dac1b3bac8b1207b85322f2f41660e71c6b69058e3906f191346d23de599276ef1e82d57fbe8625ce19731d55546cdb326729eec3ba25717c0b306789e8e9c277b4f89decf6c3bfa8ce5d36acba704e4c136e9190f7ec6c02e954dfbcfc0791066611666611666611666611666611666611666611666611666611666611666decc38c640ac71c8b7920923e99ef6cc13b778f4966bdcc1c5b8c22f63aaab8c9a676de43cd9b19a670ae0590b3c6f899c273b5613bd9fd9b19a672d9f9eb17c4a401ebcbe9ff5e0670cec52d9b4ff2c9c0761166661166661166661166661166661166661166661166661166661166661ce6e5c99718c8158e3906f0d1346d2bdc5334fdce2d15bae710717e30abf8ca9ae326a9e75d1f3647eabf96c013ceb80e7add1f3d47af2333356f39ce5d3b3964f09c883d7f7731efc8c815d2a9bf69f83f320ccc2ec62c6368b58e3906f2d1346d2bdd5334fdce2d15bae76ccc5b8c22f63aaab8c9aa739729eec38fd7305f03403cff391f364dbfee8fdccb6fdeb2d9f9eb37c4a401ebcbed77bf0330676a96cda5f0fe7a110e65525c82c71963887314b9c25ce61cc1267897318b3c459e21cc62c71963887314b9c25ce61cc1267897318b3c459e21cc62c71963887314b9cef9d38e31803b1c621df3a268ca47bde334fdce2d15bccda4f43dac5b8c22f63aaab8c9aa725729ebacc58cdfa02785a806743e43cd9b19ae8fdcc8ed56cb47c5a6ff994803cd8266df4e0670cec52d9b4bf11cec3ddcebcaa0499a56e148759ea863087314bdd10e63066a91bc21cc62c754398c398a56e087318b3d40d610e6396ba21cc61cc523784398c59ea863087314bdd10e63066a91bc21cc62c754398c398a56e087318b3d40d610e63e65037708e0eb1c6215f331346d26df0cc13b778f4966bde8e8b71855fc654571935cfe6e87932ef24d95800cf66e0d9143d4fad273f33739d5eb07cda68f994803cd826bde0c1cf18d8a5b269ff05380fc22ccc2e666cb388350ef95a9830926e93679eb8c5a3b75ced988b71855fc6545719354fab279e170ae069059e2dd1f3d47af233d3f66fb57c7ac1f2290179f0fadeeac1cf18d8a5b2697f2b9c875263c66b8958e3906f331346d26d011e0ff5aee036a9d511c71525c0b8bc04187b9500e37d25c01807460ffdf4cc359cb078687fb3dff8a4a2884f25c4896bbb97001e5fe7b0cae2a972c482eb39ec6d3e399fc32ae0f1750eab2d9e6a472cb89ec33ee693f339acf61bc748dafbfb4b80b16f09303e50028c0f960063bf1260ec5f028c034a80f1a112601c58028c0f9700e3a012601c5c028c434a8071680930fa7ea691eb7b6e6b116c877d3f2b86edb0ef15c5b02d3197984bcc25e6127389f99dda96984bcc25e66f7ecc7d3ccbc5e7c6b4e5fa0ee17abeeb7b4c5e18f930ae62ca883cb1e87892e83bdadac6c077622835c65525c0b8bc0418258ed931d4ae306a9e1d9e78b615c0b30378b647cf53ebc9cfcc5cc39d964fdb2c9f129007ebc14e0f7ec6c02e954dfb3be13c941a335e4bc41a877cad4c1849b71d787c5d5f855cef787dedf2c4b3a3009e5dc0e3e37c79f23373bdefb67cda61f994803c78edecf6e0670cec52d9b4bf1bce43a931e3f54eac71c8d7ca8491743b81c7d7f555c8f58ed7d71e4f3cbb0ae0d9033c3ece97273f33d7fb5ecba75d964f09c883d7ce5e0f7ec6c02e954dfb7be13c941a335eefc41a877cad4c1849b71b783cd4bb82bf73ec71c471790930ae2a014689a3c49113a3c4f1de89a3300aa3300ae39bc1580a6db8dc670a7f3680dfc5dba2e7a9c7ef6df9f0b4018f8fef769efccc3c1bd867f9b4c7f2290179b01eecf3e0670cec52d9b4bf0fce83300bb38b19db2c628d43be56268ca4db0b3c1eaeef82dbfe36471c57f8654c759551f3ec8f9ca73e89f5251f9efdc0e3a34ef9f133dbf61fb07c6ab37c4a401ebcbe0f78f0330676a96cda3f00e7a110e65525c82c71963887314b9c25ce61cc1267897318b3c459e21cc62c71963887314b9c25ce61cc1267897318b3c459e21cc62c71963887314b9c25ce61cc1267897318b3c459e21cc62c71963887314b9c25ce61cc1267897318b3c459e21cc62c71963887314b9c25ce61cc1267897318b3c459e21cc62c71ee1a33ce7127d638e46b65c248ba7dc0b3df034fa1f3f0f73be2b8c22f63aaab8c9ae760f43cf5585ff2e139083c3eea94273f33bf153864f9b4dff2290179b04d3ae4c1cf18d8a5b269ff109c874298579520b3c4b96bccd866116b1cf2b5326124dd01e0f1707d17dcf61f74c471855fc654571935cfe1e879eab1bee4c37318787cd4294f7e66dafe23964f072d9f129007dba4231efc8c815d2a9bf68fc0791066617631639b45ac71c8d7ca8491748780c7c3f55d70db7fd811c7157e19535d65d43c2f46ce934a627dc987e745e0f151a7fcf8996dfb8f5a3e1db67c4a401ebcbe8f7af0330676a96cda3f0ae7a110e65525c82c71963887314b9c25ce61cc1267897318b3c459e21cc62c71963887314b9c25ce61cc1267897318b3c459e21cc62c71963887314b9cef9d38e31803b1c6215f2b1346d21d011e0fcfe30b1eab79d111c7157e19535d65d43cc722e7a94b627dc987e718f0f8a8537efccc8ed51cb77c7ad1f2290179b04d3aeec1cf18d8a5b269ff389c87bb9d795509324bdd280eb3d40d610e6396ba21cc61cc523784398c59ea863087314bdd10e63066a91bc21cc62c754398c398a56e087318b3d40d610e6396ba21cc61cc523784398c59ea863087314bdd10e63066a91bc21cc6cca16ee01c1d628d43be56268ca43b0a3cc73cf0143a8fe898238e2bfc32a6bacaa879daa3e7a9c7fa920f4f3bf0f8a8539efccccc753a61f974ccf2290179b04d3ae1c1cf18d8a5b2699fec09b3308731639b45ac71c8d7ca849174c781a7dd034fa1ed6a3b30bada7e0f8ca9ae326a9e93d1f3d4637dc987e724f0f8a8539efcccb4fda72c9fda2d9f129007afef531efc8c815d2a9bf64fc1791066617631639bd56e3ee390af950923e94e008f87ebbbe0b6ffa4238e2bfc32a6bacaa8794e47cf538ff5251f9ed3c0e3a34e79f233d3f69fb17c3a69f994803c787d9ff1e0670cec52d9b47f06ce83300bb38b19db2c628d43be56268ca43b053c1eaeef82dbfed38e38ae2801c6e525c0b8aa04183dc731d55546cd73d613cfe90278ce028f8ff6c3939f99fbfc39cba7d3964f09c883f5e09c073f636097caa6fd73701e4a8d19af25628d43be56268ca43b033cbeaeaf42ae77bcbe5ef2c473b6009e9780c7c7f9f2e467e67a3f6ff974d6f2290179f0da39efc1cf18d8a5b269ff3c9c875263c6eb9d58e390af950923e9ce018fafebab90eb1dafaf0b9e785e2a80e702f0f8385f9efccc5cef172d9f5eb27c4a401ebc762e7af0330676a96cdabf08e7a1d498f17a27d638e46b65c248baf3c0e3a1de15fc9de382238ecb4b80715509304a1c258e9c18258ef74e1c85511885b130c6ad25c028e75a18b932b67a608c197bc843fbad45b05d65d9ae2aa2ed6acb7675116d4bcc25e6127389b9c45c627ea7b625e6127389b9c45c622e31bf53db127389b9c45c622e319798dfa96d89b9c45c622e3197984bccefd4b6c45c626edbf630dfb4e0f9dc1781e782875878f233a9cbbd64ca7a23c2f8e9585db662d56ac52a01792e41fc2e7b889f6bce35ed93bd4299473060f6643bd55b95d10bfc271babac7868fb573cf91ed6e65d2982edb036af18b6c3dabc62d896984bcc25e6f76ecc315d1174fe0d922ee3aa497733fb947f2b1c47793e5199fdac0ae47cfab02dd790c45c622e317f33628e71995f049ec0e20972f0a499f14c61c653cf8c6702339e31cc789a99f1ac61c6b394194f39339e05cc786631e329c6f3ac4278a632e36960c6b39019cf6c663cd398f13432e319c58c27c98c6704339e16663c6b99f12c63c6b38819cf1c663cd399f16c66c63389194f2d339e91cc782a99f12498f12c66c6339719cf0c663c1399f13431e34931e359c78c6725339edecc78aa98f1cc63c6338e19cf4c663c9399f1d431e3e9c38ca79a19cf68663c4b98f18c67c61363c0130f3acf018fc3ff2f82aecc3ab6879293033afe7fcde8cbe098eb265dee28fb1ae8686ed575c7b118a76be04bdaa49377b665e284b6d2b04ff62a81e33a139ef1cc789630e319cd8ca79a194f1f663c75cc782633e399c98c671c339e79cc78aa98f1f466c6b39219cf3a663c29663c4dcc782632e399c18c672e339ec5cc7812cc782a99f18c64c653cb8c6712339ecdcc78a633e399c38c6711339e65cc78d632e36961c63382194f9219cf28663c8dcc78a631e399cd8c6721339e06663c5399f15c64c6338b19cf02663ce5cc789632e359c38ca79919cf18663c1398f1d433e399c28c27cd8c67be83c7d7bac334de4e65d3fe4526b63d9c87cc7be16e78f2e9a629abbb2997f8c95e05e499600662f4f8101e4b5cf6fc08ecdbdc84185df5e44bd8bb21ae16c176d8bb218a61bbdab25d5d44db12f3f098df8cde760ae71cd116b3f6d390c6ebcec75c2d4f7eded6e645fd2ecc5b56acae5ab14a409e1b10bf5b1ee2e76a47699fec15ca3c820133d68b9a20da7af172f43efde61d9b14d797adf8a25faf788a69585bfa4a116c87b5a5c5b01dd69616c3b6c45c622e31bfb763fe36938eb09f91441bfa3b14dd3fde0676df6ed2b108edeab25e3565d13b4189e3edc04379b6c2773aa97f72cddf0b31b7d3f48c027fc7efeb1952d83929c6f3abb073520cdb61e7a418b625e6e1317f8707dbf1e0f6b512f496eb19c53b80e7550f3c9efcccdc6b5fb37cba68f994803cd8f6bde6c1cf18d8a5b269ff35e0a10ddf13eba31ee473ce91e716339e34339e29cc78ea99f14c60c63386194f33339e35cc789632e32967c6b38019cf2c663c5399f13430e359c88c6736339e69cc781a99f18c62c69364c63382194f0b339eb5cc789631e3798519cf22663c7398f14c67c6b39919cf24663cb5cc782a99f12498f12c66c6339719cf0c663c1399f13431e34931e359c78c6725339edecc78aa98f1cc63c6338e19cf4c663c9399f1d431e3e9c38ca79a19cf68663c4b98f18c67c61363c013f69e58faff2dd0d11839be3bf69d26fd2ae8ca1c3668ace635d055983495a1df3b7b7940e7b2314ebee605a0ad34ec933d7c4fec3b99f08c67c6b38419cf68663cd5cc78fa30e3a963c6339919cf4c663ce398f1cc63c653c58ca737339e95cc78d631e34931e36962c6339119cf0c663c7399f12c66c69360c653c98ca79619cf24663c9b99f14c67c6338719cf22663caf30e359c68c672d339e16663c2398f12499f18c62c6d3c88c671a339ed9cc781632e36960c6339519cf2c663c0b98f19433e359ca8c670d339e66663c6398f14c60c653cf8c670a339e34339e5bcc78e63b787cbd9f2eec9d0fb78a603bec9d0fc5b01df6ce8762d8969887c7dcc3bb6e32ef02c5f742eacd9eeb9286b4e7dff7d4c783dbdfabf3db78f0bd1f3eda254f7e66de41f92e5356cf08cbd5b17a77d0b1e972299e38bf8af220c3bbe198887872be4f84ec09b3308731e33b6989d535f7eecd6624dd6bc0e3a3ddd0be8f336551f9fa1d7d893e1d763dbce7bd5ec7c17ecf3b71b8def3beb97f075bb561ab0c3abf0b17d7bac773e97b2d022adbb51601f9836b11f8baefdfb0786e3862f166dabeeec176a17d8eeb0e9e28dfb3896d0cdaf2f1de77edfbb5207fdf5defa18fd0f7da04f0a02d0fef79cfb45d341f97cad7edc3c83e5e635e8fd73db55de32d9f2b20cf1c68bbc6e668bbca828e6b06df535e16747ef7fb1b466f975113c8f7291fb6e53b2ccf987be89b14fc1d16d76388be9f91cab473370ae0b9063c3eeeb79efa53494ff7a4cc77d82b56ac6e58b14a401ecff7ad4cddbe66f1d03ed91366611666611666611666611666611666611666611666611666611666611666fecc381e4cac386e7b8b0923e970ccdac7737eedfb04531695afc746bfd0a7c36ef4e316a924ce51a071db0996cf1590a74fbf0eb6afc0b8ad3daf21ec5cfa5ae73dec5c92bdcaa0f33c149fe3746173608a31465888ed9ac86ca736f839bfa964ef20bbe6f70deb9cde729c4f1f6d05ce9fa22dd758e315e0f130165beb6bee88f6e9b2e5d375cba704e4c1752c2e7bf0d3755fa3fdcbc0431bae93e7eb9e11583c81233eb49531e34933e3e9c98c670a339e7a663c1398f13cca8c670c339e66663c4398f1ac61c6b39419cf00663cf733e3e9c58ca79c19cf02663cb398f14c65c6d3c08ce731663c4399f13cc48c672c339ebecc78ee63c6b390194f05339ed9cc78a631e36964c6338a194f9219cf08663c2dcc786a98f1ac65c6339019cf32663c0f30e38933e359c48ca71b339e39cc78a633e3d9cc8c6712339e5a663c2399f10c63c6f330331edfe3e885f23cc88ca792194f8219cf62663cdd99f1cc65c63383194f13339e89cc7852cc788633e359c78c6710339e95cc78fa31e3e9cd8ca78a194f0f663cf398f18c63c6339319cf64663c75cc781e61c6339819cf4d663cfd99f12c61c6339a194f1f663cd5cc78c633e38931e089079d7feb1187ff5f07dd6593c6dfb39539caa3797a945ff7ab5e1ed0b9ec3247d9571c0c18a74be04bdaa49377b6ddf63b8c982997f6c95e25705c61c2339e194f35339e3ecc784633e359c28ca73f339e9bcc780633e37984194f1d339ec9cc786632e319c78c671e339e1ecc78aa98f1f466c6d38f19cf4a663c8398f1ac63c6339c194f8a19cf44663c4dcc786630e399cb8ca73b339ec5cc7812cc782a99f13cc88ce71a339e8799f10c63c63392194f2d339e49cc783633e399ce8c670e339e6ecc781631e38933e3798019cf32663c0399f1ac65c653c38ca78519cf08663c49663ca398f13432e399c68c6736339e0a663c0b99f1dcc78ca72f339eb1cc781e62c6339419cf63cc781a98f14c65c6338b19cf02663ce5cc787a31e3b99f19cf00663c4b99f1ac61c63384194f33339e31cc781e65c63381194f3d339e29cc787a32e34933e32963c633dfe2c1ffebeff634be7a1974f4ffff6b3a0755c68fcb96bd08fc4886adfde02b66b8a51d31095bfb81034f9a194f4f663c5398f1d433e399c08ce751663c6398f13433e319c28c670d339ea5cc780630e3b99f194f2f663ce5cc781630e399c58c672a339e06663c8f31e319ca8ce721663c6399f1f465c6731f339e85cc782a98f1cc66c6338d194f23339e51cc7892cc785a98f1d430e359cb8c6720339e65cc781e60c61367c6b388194f37663c7398f14c67c6b39919cf24663cb5cc784632e319c68ce761663cd798f13cc88ca792194f8219cf62663cdd99f1cc65c63383194f13339e89cc7852cc788633e359c78c6710339e95cc78fa31e3e9cd8ca78a194f0f663cf398f18c63c6339319cf64663c75cc781e61c6339819cf4d663cfd99f12c61c6339a194f1f663cd5cc78c633e38931e0095b6b81fe5f0eba8b267d1374174cfa1ae8ce9bf465d0bde4d0953958c8de45d0d13c850ba0a3b18df3a0a3e721644bf7e75e1bd099b5cce153b983f582c3a78b8e63f13cd231e920daf388b6d2b04ff62a81e322139ef1cc78aa99f1f461c6339a19cf12663cfd99f1dc64c6339819cf23cc78ea98f14c66c6339319cf38663cf398f1f460c653c58ca737339e7ecc785632e319c48c671d339ee1cc7852cc782632e36962c6338319cf5c663cdd99f12c66c69360c653c98ce741663cd798f13ccc8c6718339e91cc786a99f14c62c6b39919cf74663c7398f17463c6b388194f9c19cf03cc789631e319c88c672d339e1a663c2dcc7892cc784631e36964c6338d19cf6c663c15cc781632e3b98f194f5f663c6399f13cc48c6728339ec798f13430e399ca8c6716339e05cc78ca99f1f462c6733f339e01cc789632e359c38c6708339e66663c6398f13cca8c6702339e7a663c5398f1f464c69366c653c68c67bec583639849d051ba1674944e818ed275a0a3743de828dd003a4a37828ed2934047e926d0517a32e8284dd7483ce8f0bd18efe1275b5436ed5f02469acfecbaa6a702f7254ba7b9cf79e2be6471d3fe396074f9426cd380fb9ca5d3dc673d719fb3b869ff2c30ba7c21b6e9a0a3f40cd0517a26e866823dd2517a16e8283d1b74949e033a4acf051da5e7818ed2f34147e905a0a3f442d0517a11e828bd1874945e023a4a2f359ffa1c9fb574fa1c9f31e97410ed39265b5436ed9f0146d77927b665c07dc6d269eed39eb8cf58dcb47f1a185dbe10db4ae03e6de934f7294fdca72d6eda3f058c2e5f886d0d709fb2749afba427ee531637ed9f0446972fc4b616b84f5a3acd7dc213f7498b9bf64f00a3cb17625b07dc272c9de66ef7c47dc2e2a6fd766074f9426ccdc0dd6ee934f7714fdced1637ed1f0746972fc4d602dcc72d9de63ee689fbb8c54dfbc780b1dde10bb1e17b17377b62bc6931de2ca2edb0be57316c87f59f8a613bac0f540cdb61f7e662d80ebbbf16c376d83db218b6c3ee73c5b01d76af2a86edb0fb4d316cb75bb6db8b685baeb1e25f636f669b7aaf5e636f66bbd66ed96e2fa26de933499fa958b6a5cf247da662d96eb76cb717d1b6b4a9e16daa87e713a938d8a02d66eda7217d0c787c3ce7f1e46752977bd494f54684e5ea58bd68c56ab315ab04e4390af17bd143fc626097caa67db2578acc582f62d1d94ec6c106be23ee08950fbac3265d0bba43269d02dd4193ae03dd0193ae07dd7e936e00dd3e935e0cba36935e02babd267d0e747b4c1ac77b769bf459d0ed32691c5fd969d26740b7c3a4713c63bb499f06dd3693c6f183ad267d0a74ad268dcfebb798f449d0bd60d2f87c7c93499f00dd46936e06dd06936e07dd7a93de0cbae74dfa38e89e33e9a3a07bab493782ee59939e04bab7987413e89e31e9c9a07bdaa4f11d85ab4d1ac7be5799f405d03d65d238d6fca4495f02dd0a93c6b1dde5263d1d744f98f40cd03d6ed23341f7b249a741f78a49cf02dddb4c7a36e85e35e939a07bbb49cf05dd3b4c7a1ee85e33e9f9a07ba7492f00ddbb4c7a21e8de6dd28b40f71e93c67180f79af431d09599f48ba0a3b9a7474047bfa7380c3afa0de521d0d17b130e82ae87491f001dcdc7d90f3a9a63ba0f74f799741be8e226bd17749526bd0774f48e82dda0a3f700ed021dbdab6827e8e87d803b4047ef2cdc0e3a9a87ba0d74f45b86ada0a3df2fb6828ede11b00574f45ea0174047efbadb043a9a6fba1174f41b810da0a3df05ae071dfdf6fe79d0d1fb769e031dbd43eeada0a37993cf828e7e0bf016d0d598f433a01b66d24f836eb849af061dbd2b6e15e868fedf53a0a339ff4f826e8449af00dd48935e0eba5126fd04e8e89d8b8f838ee641be0cbab126fd0ae8c699f4db4047efdc7c1574346ff0eda0a377d5bc0374742f7e0d74742f7e27e8e85efc2ed0d1bdf8dda0a37bf17b4047f7e2f79a4f7dfde9ebf2bad94f07d1f57bb4bd1bc1ed5baebe3731204f947dd904f0a0adab91fb9ecaf49ba9bf5566caa57a70156c5f8edc76b6cf7ec594d5cd947bd9b25d017986f4eb383797e0ff69f0818ec33c5436ed4f80632f596557197faf78f2f7b2c544dc578089f20cefd791f7b326dd138e89902df3fd93ea5a0031c42d0d695c232dfa58a532df07ae15c0730578a2bf4eb2df877dd409bcb6a2fe3e6c3fcbb0eb5a02f25c86f8f99adb79c5e2a17db227ccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccfc99350f8d27e07c1eca779d0923e970accbc7737e1c4bc531af8fc0b88eeff1bdeea6dc8996cf1590e7ffc098d3c74cba12fe4fe72dec5c7a1827cc792ec95e25f88363413ec68b63608bcabeea880507db3591d94e6df0737e53c9de41767cff9a754eaf5be713c7c5f11afa2cd4533ae696f98c437c6e417c3c5ce339cf0dd9c36be92ae8287d03187dc41aef25d41e4c30fb640fc7c5bf6c8d8b47df56a7923edb8d8ba62c7bbc1d7da53cdf80b6ef9b268d7343ae43593f73fc9fb65ce3d4143fedf3f9e87dce9cdf974c59747ecf3b6c9f03d6886cd7a2ed9811b243fa0a48ff14e673d8bf27a25813bbbe46680e26b2dbc7ddb08e4b409e0b0effd341b4fe9fb778ce5bccbaee7c1bead9cfe0feefab4dba1012a3091023ca83fd200ff34c9c6d2471903d9d87ce7f0f2b0ff65928cfafa18dd2be503b4f7ee2dc16bc075cf4e4df75cb3fda277bd837be028cb68fba7e7ca14f07efbd3effebbf3ccefffa2fa843384f2bb0ca9f08e513578f20fcde427962fd3bcaf739bfec9ae533b15c01a6dfe4e9df91779a4917d2d77fb3beb785f5f57dbc13301edcfedd5b6fb9eeef788ff1d1be78f233e9ba775db27c4a409e11e0a7877e4ccedf019e07dbbede034936a80f75d98a4505e4e90fd776ae38e277d52b45f125e5ec0f4e74f84279065bedd44b1e987c9e37ec67e972af3a7ca53cc3a1fd7bd4a4e3709eb02dad73fc9fb65ced01c54ffbece1fd7e99f34bbf01a3f37bc661fb14b04664fbb6dfa4537f9fec90be02d2a9fe1d79eddf9353acf13d7ef45b3964b78fbb6c1d97803c671dfea78368fd0f7b1f00d9d3756724d433aa473edbcdb321319a0831a23cf86c85eeed943fecbeef637e75aefbfe5560b4db4decbbf864bb66b1d9cf505dfd41ca43c7627f7016b4b371475effcf86b37d9b42e6fc7b7e465e1fb3e299063be3414ff593e24cffc33e2ee55962ddcf7cf5592f5bdce4078ee15cb4b82f5971c56751cb81db756dba9e757aea73d6635fccee0f5d0476cab3daea0fd9fdb89b0e5fecfb7459d0f9bbe01b565ebc26731d67a7af5bc7e03303d73359fcadcb0560499b74f24eb6da641299ca1cb148049dbf93b99e33d07580758ecab2af153ab602f26cb4da243b6fe65ed6a7233e741ef159bbab4efa7a8e14f69c85ec6946d7efe8a26fbbeecddf2bf58cacdcc9eb4b718cbba7958ec676aa05ef15b96271d1c1e3eb9966582c2e3a6c47178bc60daefb872b16171c3cbebe6386c5e282c37684b1d8e47ab6e08ac579078fafef1a61b138efb01d5d2c26ddf65c23572c5e72f044ff4c23772c704cac10e60b0c987b5ae9686cd7af778dddb96271cec1e36bec2e2c16e71cb6a38b456da3eb3bbb2b16671d3cbed605098bc55987ede862d134d9f54cc5158b330e1e5feb6784c5e28cc37684f562233e5fcb158bd30e1e5f6b7284c5e2b4c37684fdc3c65ccf0c3116a71c3cbe9efd85c5e294c37684b168d6b64fe6118b930e9e93458ec54987ede862b1be41db3e91472c4e38784e143916271cb6a38b457393b6dd9e472cda1d3ced458e45bbc37684dfa132f5e2781eb138eee0f1b56e4a582c8e3b6c47178b964c5feb581eb138e6e0f1b5164b582c8e396c47178b64e69e7a348f581c75f01c2d722c8e3a6c47582f32df275fcc2316c57cff68582c5e74d88ef03e92a91747f288c51107cf9122c7e288c37674b1d89479fe74388f581c76f01c2e722c0e3b6c47f8cc25532f0ee5118b430e9e43458ec52187ede8625197b9a71ecc2316071d3c078b1c8b830edbd1c56263664cec401eb138e0e03950e4581c70d88eb0df99692ff6e7118bfd0e9efd458ec57e87ed08fb9d99e717fbf288c53e07cfbe22c7629fc376846d67a6dfd996472cda1c3c6d458e459bc37684fdce4c2cf6e6118bbd0e9ebd458ec55e87ed08fb9d99fbc89e3c62b1c7c1b3a7c8b1d8e3b01d61bdc8b49dbbf388c56e07cfee22c762b7c37684cfb5326de7ae3c62b1cbc1b3abc8b1d8e5b01de1f791cc33be9d79c462a78367679163b1d3613bc2b1a24c1f7c471eb1d8e1e0d951e458ec00db3ee699602c682ed6382b161590e701f332769a8b1516472a03e795a12fdb23f7253baf6c5b882fdbc117ca33107ce909fa28993cf99aa9335b4d593437fd86c357ca33744047de61261d87737213ca4a3afe4f5bae3948143fedf396e87dced4d5174c59747eb7386c6f02d6886cd7a26d9a9b4e76485f01e989033af2523e8a07c59ad8f535426b2520bb7ddc0eebb804e46975f89f0ea2f57f8bc5b3c562cefcee01ea19d5233f6d5796a9352446e320469407e7ecddf0c463cf21240eb2a7f3d0f9ef61e5c1399494a709da289c574a7ec683cef326b57f5b3df917b68e1bd94b80ee0a30da3eeafa9180b99fb5c41874e8686d075c83a9d1d2695f2779f2956c51d9b43f091869ad89c6e233a6f2656cb01835cf640f318b835dda72dd2f26034f93071e4f7e66ee43532c9f26593e25200ffeb6718a073f636097caa6fd2960dbc739c758d03d7994158b0ac8b3daea3f86c591cad0f5b7d1e18baf3836583c0d0edbd33dc791caa636717a116c4fb56cd75bb6f5b58d754c6fb9aeeda9c03ccd03b32e7746f4e566ae6d5a238dea33d9a9079fd21083a87c42db31ab6cd257407afb80ce0c140fba7712bbbe8eb0ee841d37d93a2e0179a63bfc4f47ecff0c8b07cfb1de74bf613df42b3d5c0f993a30dde2a0fd7a88dd8c90d84d87d8519e46d0511f670ae8a8af806b0ad2ffb11fd110bdbfceb687f61b809174b84e618383b13e7ac654aeb6b91e1849370d78a67a8ad9348b6794151fbc2ff7b0f2d0b11590a71dee8d71475e5df7ab621d7ed1da8511aef3936957bb7b8817aeab18407c022b86b41143cfa063edc52879ee0b606dc5b69d7b9a376f7c726376e891d02a2c4cfc8c39dc28031da6cb1dba20b87d09c90ad0d11292dd405766850597aea4fcb4a49d8f70613ca8ec0a8bb327b044691b97dfa42d57d5e9013c3eaab2ae3a95a62c53759edeb3a56d23d68f6e166757ea8efe5f798e7c6165513da8f0e03b3251d9b44ff6747c1226bdab79c3d6597b36efdbbe7147db5e84b52f2e4cc7ac20d89fae63b092e0c544e574b382d32bfae0d4e3c56bf305602f0096c0f0f48c9e27535169cdd60dcddbb62ddfb77edb960df3f7edd8d0b665e70e8c680f2b7261d1b62f79bdb99a3acc6be7efeed0d91bae90db0374b4426e4fd091fd5ea0238efbe07ff699f0724d8c80f2a91aebff551887bb1b87a80ad26d48b727fa9ae91d646ffffac95875903d7d7a895dbda4ae5e4257bfc141ffaa5af714f412b87ac95bbdc4ad5ed2562f61ab97acd54bd4d604d925688707d925661f0d3a9690d5db6780572f19abbb1a7a4958bd04ecd820fbb86e7c907db5997e9584eeb2eaafa3ba9ba7bf5ae82e97ee6ae96eadfecaae1fdfe86e8cee22eaee8feeb2e86eb0eefece34b19e15649790d64b46cf0db24b42cf0fb24b3e2f0cb24b3a2f0eb2cba12f0db24bd33e116497335f1e6497b9d5cbdfea6571f5d2e57ac95cbd94ae5e62572f51ae97dfd5cbf2ea65c8f592bd7a295fbdd4b85ee6f7f920bb9cf8fa20bb64704b905d4e583fbad6cb87ebc7f6fa71b67e54ac1f65eae1043d8ca21fb3eae13f3d1caa8787f570b99e3ea0a753e8e9257aba8d9e7ea4a763e9e9697aba9e9ebea8a773eae9ad7abaaf9efedc1e64a7c79f0cb23f9fd03f27d13fafd13f37d23fbf7a29c8fea450ff444fffe454ff04f772907d84aa7fcead87d5f4a353fd18593f5ed58f7af532bd7a595ebd0caf5e76572fb3ab97d5d5cbe8ea6573f532b97a595cbd0cee7b95fc8e92df55f23e25bfa7e4fd4a7e5fc91f28f943257fa4e4034afe58c907957c48c99f28f953257fa6e4cf957c58c947947c54c95f28f94b251f53f2574a3eaee4134afe5ac9df28f95b257fa7e4934afe5ec93f28f994924f07d9faf75925ffa8e49f94fcb3927f51f239259f57f205255f54f225255f56f215255f55f235255f57f20d25ffaae49b4afe4dc9b7947c5bc97794bcaee4bb4abea7e4fb4a7ea0e4874a7ea4e4c74a7ea2e4a74a7ea6e4e74a7ea1e4974a7e15742c038d8dc5ff373bc3cc7e735bdbc6edbbda6ada76d66cdfb7ad6dcbae6d876a0e6c697ba166e7fe8d7b366ddb79000ffea0699e68bdea597bf6341faad9b2a365e3c19a9dfbda6a766eaa59bf73df8e96db6e8e9f33070dea6cb1b9a525dcd877caee80f4fb5d34fa6b731cad04be28b76fffab2b01f97f5d39686079d71cfab8e9dcd1d7aea7b27dbc9abddb76b6d5246b76a8bfea66baf3c0c6960935f8bfbd2ac87bdb6af6b635ef69abd9b467e7f69ada0958eef8de5d70a2b5b71f98c1e65d405daa2a5fead7054ffe47bfae9d8effbc13525a4fbe50a3fdfa77c1c3415d3928dd45c2c5fd43c3b277dffab63dcd1bdac20f5e762707afea8a9b2d5d74b3ef802e187ba82b074d1ad035c2555d3176bc0063c17f03d9f72ad92c9304009b2d6c6f00000023571f8b08000000000000ffed9d79741cc5b5c67b6459963d1acbf2be5bac5e4648a319c9b6b08d65b3181bb3790163360b5b3606db32b60c983d648310080961c90664634908d94312b2ef2464812c2404b213c8bf39efe49d774e4edebb3553f7e853b96bdeb4dc35ae96ef9c7335d557357d7ff7ebdb353dd5dd33a9a0f478832ca5db23c88e0d0e7df0ffbbf573eef01eed31ae2be792339510ce9a84708e4808676d4238472684b32e219ca312c2599f10ced131722ab69a60f0236ede310e748d9b319d304d1b12a06926619a8e4d80a68d4132c6a87109e16c4a08e7f884704e4808e7c484704e4a08e7e484704e4908e7d484704e4b08e7f48470ce4808e7cc8470ce4a08e7ec8470ce4908677342388f4908e7b109e13c2e219cc7c7c8390f384fd0cf27eae7b9fa99fbccd7cf0bf473563fb7e81c6bf5f24964ad646d8acff89f3ad190272b9075e8ff35ebff75922d245b44b698ac8bec64b225644bc996919d42b65ce7bf826c25d9a964a7919d4e7606d92ab233c95693ad213b8b6c2dd9d964e7909d4b761ed9f964ebc8d6936d305836925d407621d926b28bc836935d4c7609d9a56497915d4eb685ac87ec0ab2ad64dbc87ac9b693ed20bb926c27d955645793ed22db4db687ac8f6c2fd93564fbc8f693f51b9a1d20bb96ec3ab2eb0dce83643790dd487613d9cd64b790dd4a761bd99bc86e277b33d95bc8de4af636b2b793dd417627d93bc8ee227b27d9dd64f790bd8bec5eb27793bd87ec3eb2f792dd4ff600d983640f69162ef6f791bd9fec03641f24fb10d9c3648f903d4af661b28f907d94ec63641f277b8cec71b227c89e24fb04d927c99e22fb14d9d3649f26fb0cd967c93e47f679b22f907d91ec4b64cf907d99ec2b645f257b96ec6b645f27fb06d937c9be45f66db2ef907d97ec7b64df27fb01d90fc97e6468fe1cd98fc97e42f6bcfe1fcf21fd94ec67bafd73fdfc0bfdfc827e7ed178cd2fc97e65f87e4df61bc3f712d96f75fb77faf965fdfc7bfdfc8a7e7e553fff413fff513fff493fff593fff453fff553fff4d3fbfa69fffae9f5fd7cfeafc63617ca95d1f0c3cba8398c69d8ede2e75fe81c53e2118fc505a8cd0ffe3e766edafd5cbfcccda8dd4cb230d7f9d5eae33d653af97eb0d7f935e6e32fc13f4f204c33f492f4f32fc53f4f214f0a7039887d47ee51ba15d29f0711dd6806f64305813e5abe3d5816f5430580be5e3ed5807bed1da370a7c63b4af1e7c69ed1bcd9a9135685f7710574de47ad47a3371af579f9b191b3fef56b5de4647bce3e2e7ed55eb6d72c0abea430f17c138a89b09dad704be89da371e7c93b46f02f8266bdf44f04dd1be49e09baa7d93c1374dfba6806fbaf64d05df0ced9b06be99da371d7cb3b46f06f8666bdf4cf0cdd1be59e06bd6bed9e03b46fbe680ef58ed6b06df71da770cf88ed7be63c1c7e3e771e0e363b8e3b54f8d09ff0ae035da5f03be1379cc05df5c1e6fc1378fc75af0cde771167c0b2036fbb23086b0af45fb783c52ff5ba8dbdd415cf59fdfa6d6bb28eef5d29ad57abbe25f6ff1bcd5c9c180aedd10671168b544b763bc36a61d63a7b4711cf6d7427b15f4e57eac07bfa730bb7aef58acdb4bcabc6ea1f1ba0cf4591c927f77106ffe5d064f97c1acea7f2970c45fb38576a9d98a1f916b7623f4356b8f8f6f8663cdae010e0735dbe9a666f339a9d9d2fc421084d71e1fe30ec79add041cf1d76ca7d46ce58fc8357b0df4356b8f3fe70cc79add0e1cf1d7eca24e3936a8f811b9666f85be66edf167dde158b3fdc0e1a066bb649cadf811b966ef86be66edf1bccb70acd9db8123fe9aed7254b305a9d9a074ae2808c26b8fe7008763cdde0b1cf1d7ecd62e3936a8f811b9669f84be66edf17cf470acd98781c341cdba9a9fcd4bcd96ce91074178edf1b991e158b34fe9b63acff0737d9e6126f87ea17db3c0f782f6cd06df8bda3707f28a7f1fd856907da0e247e47de039e86bd672b36e0fc77de01bc0e1a0663ba5662b7e44aed997a0af597bc7eaf670acd9e781c341cd2e929aadf811b9665f83be66edf1f50bc3b1665fd66d75bcf03b7dbc7022f85ed6beb9e0fbbdf6cd03df2bda371f7caf6adf02f0fd41fbb2e0fba3f6b580ef4fda7712f8feac7dade0fb8bf6b581efafda9703dfdfb4af1d7caf695f1e7c7fd7be02f85ed7be0ef0bda17d9ddaa7ce09f0f529dfd3be7ac8a93b886fdb16af4909063f52c67237b45bdcf2e432c1e0ebaa39566bfcb10a2af79382ca736f059e3607b9a72146253c6dc0938b9fa778ed457bfceb2d6ee3930c4dd310eb24c82bef20af14c4e275f332c7cb800fc7837c0863217ec67c0a62f1ba79b9008cecc3f189c757de7fd4d83c3635c0eb605f2abe3f63bc6ee0e078b5d0e785a681bee3355b03fc9fc7800668e3f89d337c8e6ab51dafefe775f3723b30728eb9ea33e62b656c3318eb812d469ea2666d064f5b8816476b6c07637571ffe318bcfff1bec4f16aa1cfffd40cf43d31e5942d1ff57d16eb33fef13f9fc37db3129e3cf0b818631cbdcfe5f0bde93f41bcb5d661689533b4ca409f02e8d7e140bf72ef951c4f98855998855998855998855998855998855998855998855998855998855998fd67c6f3c778be2decdcec9164645f3bf0b898e72f7e27895e17af5f9dd77906ceebc47fde229fc3f38e7c4dd63c23e75ae8f35c6a80edd99073be787eb7d5f039bae6a2b82df19a8b6e58e678780e1aaf0171750e316bf06443b4f02176736cb1f35bdd6cdf7c4e7d2780fa5e9d16639b865d7fb2c0f0a93afd77cd40de2ecefd453d17896309b7e33cb797090ebd76c0cd352ea5f183c7ab9a60f0f881ef339db1c71e7c0e93cf97771ab16ba1cf4ba9816db310fedf1d1c7a5d0ef6e175f3f23c78ed4263dd8deef22d7b6d42277073bbcec8ad05b8b9cf2b309edf0afb8983f7b83c5e1f16006f60e4c40f3c671fff3140e91a827c049e0ee07170bd58bba3639d1cd663dcd7102c34b40a3b86e23e9da05fecd7c3ebfdc33c0ee6658e27ccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccfe33e3fdddcc9a867eed9e3056e9ba8be2f90cfebe0d3c2fb6bb6620aeeb73807cce69be91732df479ba6680ed1add6e080ebdd6c2b62d5d9d5bb36d4b8ed700f9e0b92057f7ac170c9e4288163ec46e8e2d76e91a82f8b7efc0350479639bb61bdb13cf9de33e742bd4a9f91d1769d0a71ad72dd9b60dc7c37da9003e6ee3bdd92eb4c6f712f39a228e87e7ceefd4daf2b9f3f8c7ea7ccee5b8c1df5dc5d709e44372e53ef7c0d877af6ee3f523edb0ae4742fecf8f72e7a959bf23f13d5e18db87eff17ab866a0aff97d5cac75d4eff1ca19aff3f17bbcee833a7b04deff5d8d498b83708de68146dc078f831c5c67123a469ad756aa3ebcfd47197df09885fb3c0e6394eddad5b0ef3e72f0fd7c65bffb88e3e1b17107309a399ad7981eedd7883d03e3c542f87f7770f8d7883d033584d76905c6fae7c3fa996b54607f6fe13ecf1aefa3aef62ddb3568b86f999f079817af41e33edf82b1ea9f709c651efbe3f55ad5f86c67bb3e9ce3e1315594dc715c88fbbd11eb1159381ed6e38f8d7a5c68e16e0d79ed4f2daf65adf89a63fcec64eaa774580cafe98e4587d278d365e4c2fbd462c885fbfcd2d86fe23f662a1d7fc69febe0e3211e830a21b9729fdfc2bef6321c5ff276c2b1f21f21ffe747b9e34fd64fe5bc34fe9c8bdb77995e176fdfa521b14f01d69862b7636c3efee438ecaf85f61bf07ec2fd580fd69ad9d53ec2c770c86ebeaed3785d06fa2c09c9bf3b8837ffa506cf528359d5ceab5067ff80e34f5763f5128b46f34123ee83f744f1fb08f7b7bdc7b8b8deb7dc7b4cd8f743e2d8fe4fa7737ae16ce69c5ed8f109f7e1d7e2f1c97fc3389b0ee96bce55f27b489cd72ce33d225988fbef90b8dd31eb990906eb9931385cc66e3462375631769311bba98ab14573d1dc27cd7dfafe6ffc9eee9a04308e4800636d0218472680b12e018ca312c0589f00c6d109601c9300c634301ec9f77607fae4e3d0a701746a09e176753f7e8bc1687e5742c6e0659e23798ce4eb361cab9f7dde868dc033cc8e3563d986e3f4b3cfdbb0c9ad8eb18cf7e313c03821018c1313c03829018c9313c03825018c5313c0382d018cd313c03823018c3313c0382b018cb313c03827018ccd09603c26018cc72680f1b804301e9f00c61312c09884b9ca056e1987fcf95af138f84dc80efc8c5e098febefd6749467f1fa2cbe8e31eeef48337fd7b1c5d00aef3971fd7bb0a9c0fe5da91c4f9885d9c68c6321fe3e37f7cb7ac218f6ddc30ec68dc8ef29ad6e7906fdf676abdb6d11f9bdcaed6f8296deab8e86df040dbbbf25ecfbdeb90f8e1b47ea3a468cdd1cc4ab4547055a54e91e6c27dfd7df9640665f7e6380c7a7b0df18c87ac258a5df1888fc5e950fd1b1d52d637ea88caeee65c67aa98407bf17c3454db9c9b3fc7739733cfcfe0f1c935c5dd36fde1fc7cb957c6789300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb330fbc18ce718f0bb9cb95fd61346f37b921ccdc7473e57d319a263ab5bc6fc5019f1fbcfe2e3299dab89f23d558b80c7454db9c9b374aec6fcbecd4e2327fcbe4ddcbf5d7d07d92283879717c3761066611666611666611666611666611666611666611666611666611666611666bf99f11c03b3a6a15fd61346f62d041e17bfc714f53cc8a2101d5bdd32e687caa8781cfc865c07d64b253cf8bb1e2e6aca519e837e2b8fd7bdc8c829037d70ff3ed9419ea9c0fefb71f8bb7ac22ccc61cc3866316b1afa653d6164df62e071b07f471efbbb42746c75cb981f2aa3e289ff372c4be7e9bb22f0e06f1ab9a829377996c67ef3b792ccdfeacc401fdcbf1dfc6e56e8ef24f1f252d80e51980b0964169d45671bb3e82c3adb984567d1d9c62c3a8bce3666d15974b6318bcea2b38d5974169d6dcca2b3e86c63169d45671bb3e87cf4e88ce71898350dfdb29e30b2ef64e071301f1ff95ccd92101d5bdd32e687caa87896c5ce53c861bd54c2b30c785cd4949b3c4be76a4e31725a62e494813e38269de220cf14c4e575f3f229b01d863b732181cc521bd56196da10661bb3d48630db98a53684d9c62cb521cc3666a90d61b6314b6d08b38d596a43986dcc521bc26c6396da10661bb3d48630db98a53684d9c62cb521cc3666a90d61b6314b6d08b38dd987dac06b7498350dfdb29e30b26f29f02c73c013f53aa265213ab6ba65cc0f9551f12c8f9fa703eba5129ee5c0e3a2a61ce559bcd6a9dbc86999915306fae098d4ed20cf14c4e57563de81de0eddc22ccc21cc3866316b1afa653d6164df29c0e360ff8e3cf62f0fd1b1d52d637ea88c8a6785239ee5117856004f77fc3ced8ef22c8efd2b8d9c961b3965a00feedf2b1de49982b8bc6e5e5e09db2169ccb82f316b1afa653d61c41a631e077517794c5a11a2636b0218db12c0383a018c6312c09806c6ac03c6948e873cbc9c75ab4f3e0e7d1a40275fc7bd0cf0b8da868d064f638816be6ec3b1fad9e76dd8083caeb66193c1d314a285afdb709c7ef6791b36b9d53196f17e7c02182724807162021827258071720218a72480716a0218a72580717a02186724807166021867258071760218e7248011e7348ee4e7dc23f9f9ec487eae10cd45f3dce13d4473d15c3417cd45f34034cf1dde4334f758f3247c8610c6e1cd58f094117952f1f1e430778cb5d283dc9921698c850430babece48748c85313f5446c5739a239e9511784e039e53e3e769779467f15ac3d38d9c561a3965a00fd6c1e90ef24c415c5e372f9f0edb2169ccb82f316b1afa653d6164dfa9c0e36aff8ab2bfe3fe7586239ed322f09c013c2eb697a33c8bfbfb2a23a7d38c9c32d007f79d550ef24c415c5e372faf82ed903466dcdf99350dfdb29e30b2ef74e071b57f45d9df71ff3ad311cf191178ce041e17dbcb519ec5fd7db591d319464e19e883fbce6a0779a6202eaf9b9757c376481a33eeefcc9a867e594f18d9b70a781cd45de4cf1c6786e8d89600c64202184547d1d12746d1f1e8d1511885511885f1483026610c97f799e87303f8597c4dfc3c1df8b9ad129e35c0e3e2b39da33c8b73036719399d69e494813e58076739c833057179ddbc7c166c076116e630661cb398350dfdb29e30b26f35f038d8bf238ffd6b42746c75cb981f2aa3e2591b3b4f470eeba5129eb5c0e3a2a6dce4591afbcf36725a63e494813eb87f9fed20cf14c4e575f3f2d9b01da2301712c82c3a8bce3666d15974b6318bcea2b38d5974169d6dcca2b3e86c63169d45671bb3e82c3adb984567d1d9c62c3a8bce3666d15974b6318bcea2b38d5974169d6dcca2b3e86c63169d45671bb3e82c3adb984567d1d9c62c3a8bce3666d15974b6318bcea2b38d5974169d6dcca2f3d098150f5f77ceac69e897f584917d6701cf5a073c51afc35f1ba263ab5bc6fc501915cf39f1f37460bd54c2730ef0b8a829477916ef1538d7c869ad915306fae09874ae833c531097d7cdcbe7c27688c25c4820b3e83c34661cb398350dfdb29e30b2ef6ce071b07f471efbcf09d1b1d52d637ea88c8ae7bcf8793ab05e2ae1390f785cd494a33c8b63fff9464ee7183965a00f8e49e73bc833057179ddbc7c3e6c076116e630661cb398350dfdb29e30b2ef5ce071b07f471efbcf0bd1b1d52d637ea88c8a675dec3cf91cd64b253ceb80c7454db9c9b334f6af37723acfc829037d70ff5eef20cf14c4e575f3f27ad80e51980b0964169d45671bb3e82c3adb984567d1d9c62c3a8bce3666d15974b6318bcea2b38d5974169d6dcca2b3e86c63169d45671bb3e87cf4e88ce71898350dfdb29e30b2ef7ce071301f1ff95ccdba101d5bdd32e687caa87836c4ce53c861bd54c2b301785cd4949b3c4be76a361a39ad3372ca401f1c93363ac833057179ddbcbc11b6c370672e2490596aa33acc521bc26c6396da10661bb3d48630db98a53684d9c62cb521cc3666a90d61b6314b6d08b38d596a43986dcc521bc26c6396da10661bb3d48630db98a53684d9c62cb521cc3666a90d61b631fb501b788d0eb3a6a15fd61346f6ad079e0d0e78a25e47b42144c756b78cf9a1322a9e0be2e7e9c07aa984e702e07151538ef22c5eeb74a191d30623a70cf4c131e9420779a6202eaf9b972f84ed20ccc21cc68c6316b3a6a15fd61346f66d041e07fb77e4b1ff82101d5bdd32e687caa87836c5cfd381f55209cf26e07151538ef22c8efd1719395d60e494813eb87f5fe420cf14c4e575f3f245b01d845998c39871cc62d634f4cb7ac2c8be0b81c7c1fe1d79ecdf14a263ab5bc6fc501915cfe6f8793ab05e2ae1d90c3c2e6aca519ec5b1ff6223a74d464e19e883fbf7c50ef24c415c5e372f5f0cdb419885398c19c72c664d43bfac278cecbb08781cecdf91c7fecd213ab62680b12d018c8504303ad6313f5446c57389239ecd11782e011e17e387a33c8beff3971a396d3672ca401fac834b1de49982b8bc6e5ebe14b643d298715f62d634f4cb7ac2c8be8b81c7d5fe15657fc7fdeb32473c9744e0b90c785c6c2f477916f7f7cb8d9c2e3172ca401fdc772e7790670ae2f2ba79f972d80e4963c6fd9d59d3d02feb0923fb2e051e57fb5794fd1df7af2d8e782e8bc0b305785c6c2f477916f7f71e23a7cb8c9c32d007f79d1e0779a6202eaf9b97395e1299717f67d634f4cb7ac2c8becb81678b039ea8fbfb16600cfbcce12b6321018ca2a3e8e813a3e878f4e8288cc2288cd11857248051b6b530faca9875c098d2f1908797b35588dd68c46eac62ec2623765315638be6a2b9682e9a8be6a2f9e1c616cd4573d15c3417cd45f3c38d2d9a8be6a2b9682e9a8be6871b5b3417cd4573d15c3417cd0f37b6682e9a9bb17be28f1df97aee1ee0d9e2400b4779e6d47aafd0ebfa4f8cfa29adb61a5a650dad32d0e70ad06fab03fdc2aeb9e6658e1795f9440f981dc5ce8fa5758c86fc3946c1d043c5dfe62877db98b7ad0ab16d635e3562dbc6bc6ac416cd4573d1fce8d51cdbb5c1a1f720a975f4eaf648bdccfd57c0ebb8cf030da5e7c640b6a78bd8b20f89e6a2b9687e2434475d6aaac013183c41199ed99ef14cf58c67bc673ca33de319e119cf5ccf78e678c633cd339e099ef18cf18ca7d6339ee99ef14cf48c27ed19cf48cf78e679c633c3339ef99ef14cf28ca7c1339e8c673c759ef1ccf48c67b2673c633de369f48c6781673ca33ce3e9f18c6796673c533ce319e7194f93673cf59ef1a43ce04907875e539386fff780afc678ad1aaf268e1ff8ff76edaf81d7ecd0ed1121ebde0e3e3e57b523e4b5a8d376c8a55bb77387f728ea84b1ba6199e33500c70e4f78ea3de369f28c679c673c533ce399e5194f8f673ca33ce359e0194fa3673c633de399ec19cf4ccf78ea3ce3c978c6d3e019cf24cf78e67bc633c3339e799ef18cf48c27ed19cf44cf78a67bc653eb19cf18cf782678c633cd339e399ef1ccf58c6784673ca33de319ef19cf54cf78667bc65313c2d3e38887e72f79ddbcdce3496c07dba178dfe2958e72daa9d755a7d7cbfc1caf16fa3ca43fb8a9f9087c2d7399f3cd38d7b41334ea75948beddae5de2ac4b65dbb5c8dd8b66b97ab115b3417cd4573d15c3d62bca7be53eeb7a89c47eeb728cf23f75b94e799eb198fdc6f519e47eeb728cf23f75b94e791fb2dcaf3c8fd16e5797a3ce391fb3fcaf3c8fd1fe579e4fe8ff23c72ff47791eb9ffa33c8fdcff519e47eeb728cf23f75b94e791fb2d0ee5f9ffeeb7c0fb24f8dc542ff8aed4ed1ef0d584c4e0f5ec045fad6ef33ad4783367fca10c35f09aab42b8ae0c89c771ae0a796d3574c758ddb0ccf1f0fe8dab3ce1a9f78ca7c9339e719ef14cf18c6796673ca33ce359e0194fa3673c633de399ec19cf4ccf78ea3ce3c978c6d3e019cf24cf78e67bc633c3339e1ecf78e679c633d2339eb4673c133de399ee194fad673c633ce399e019cf34cf78e678c633d7339e119ef18cf68c67bc673c533de399ed194f4d084f8f231edb75b43d55886dbb8eb61ab16dd7d15623b6682e9a8be647b7e657c71fbb231d0cfecd36f54819cbddd0be1a785cbcdf39cab378ffdd2ebdae18ef71c829ad761b5af5185a65a0cf2ed06fb703fd521097d7cdcb1c4f9885d9c6ac62ef893f76719cc1d8ac4f60f0f0638f632d1ce5591c0ffa82708d395e06fae036ef7390670ae2f2ba79b92f24767310af167b2bd0626f08cfde2a6bc1f1a232ef4a20b30f3aabd8d7c41e3b9f4b1bb1599fc0e0e1c7358eb570936769dfda17846bccf132d007eb749f833c531097d7cdcbfb603b08b3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3dfcc2af6fed86397e6ef3136eb13183cfcd8ef580b377996e6effb83708d395e06fae036ef7790670ae2f2ba79b91fb683300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb330fbcdac621f883f76f13e1f8ccdfa04060f3f0e38d6c2519ec5f9fb6b83708d395e06fae036bfd6419e2988cbebe6e56b613b08b3308731abd8d7c51ebb743e0f63b33e81c1c38feb1c6be126cfd278707d10ae31c7cb401fdce6d73bc833057179ddbc7c3d6c8728cc7d0964169d45671bb3e82c3adb984567d1d9c62c3a8bce3666d15974b6318bcea2b38d5974169d6dcca2b3e86c63169d45671bb3e87cf4e8ac621f8c3d76a1387f8fb1599fc0e0e1c741c75ab8c9b3347f7f4310ae31c7cb401facd31b1ce49982b8bc6e5ebe01b6c37067ee4b20b3d4467598a53684d9c62cb521cc3666a90d61b6314b6d08b38d596a43986dcc521bc26c6396da10661bb3d48630db98a53684d9c62cb521cc3666a90d61b6314b6d08b38d596a43986dcc521bc26c63f6a13654ec1be38f5dbc9f1d63b33e81c1c38f1b1d6be128cfe2f52f3705e11a73bc0cf4c13abdc9419e2988cbebe6e59b603b08b3308731abd837c71f3b9f3662b33e81c1c38f9b1d6be128cfe278704b10ae31c7cb401fdce6b738c833057179ddbc7c0b6c87a431e3f64bc517bb78dd26c7a8d1cfca77ab6e8f00df6dba5d0bbe37e9f648f0ddaedb75e07bb36e8f02df5b2037f6bd55b71780ef6dbadd03beb7ebf636f0dda1db5783ef4eddde0dbe77e8f61ef0dda5db7bc1f74eddbe067c77ebf63ef0dda3dbfbc1f72eddee07dfbdba7d007cefd6ed6bc1f71eddbe0e7cf7e9f6f5e07baf6e1f04dffdba7d03f81ed0ed1bc1f7a06edf04be87747b17f8dea7dba3c1f77edd1e03be0f409b9f3fa8db0de0fb906e67c0f7b06e8f05df23badd08be47757b1cf83eacdb4de0fb886e8f07df47757b02f83ea6db13c1f771dd9e04bec7747b32f81ed7ed29e07b42b7a782ef49dd9e06be4fe8f674f07d52b76780ef29dd9e09be4fe9f62cf03daddbb3c1f769dd9e03becfe8366edfcfeaf6cde0e371e016f0f138702bf8781cb80d7c3c0ebc097c3c0edc0e3e1e07de0c3e1e07de023eaebbb7828febee6de0e3ba7b3bf8b8eeee001fd7dd9de0e3ba7b07f8b8eeee021fd7dd3bc1c7757737f8b8eeee011fd7ddbbc0c775772ff8b8eede0d3eaebbf7808febee3ef071ddbd177c5c77f7838febee01f071dd3d083eaebb87c0c775f73ef071ddbd1f7c5c77382e34ebf607c1778c6e7f087cc7eaf6c3e03b4eb71f01dff1bafd28f84ed0ed0f83ef44ddfe08f8e6eaf647c1374fb73f06bef9bafd71f0f17bd363e0cbeaf6e3e06bd1ed27c077926e3f09be56ddfe04f8da74fb93e0cbe9f653e06bd7ed4f812fafdb4f83afa0db9f065f876e7f067c9dbacde382daff1a2017ceb301b84f0ae1615f3df07407f11e33712c5e372fe78191756caf3e63be52c69cc1a8783a1c6886b5c18f729f493a80a7e080c7519ec5cf249d464e7923a70cf43911f2ec7490670ae2f2ba79b91362bbd8e6a8459d5eef5c438b5ae8f3867e4353ef7fe574e475a8fa6d0fc9c5958e39832717127bb1631d79dd3c262eae42ec8546ec3623368ee7fc28b76f2f04e6450e98d57abbe25f6f71df3e59af8beb99e3b4414e4b4083b872c2d8296d1c87fdb5d0fedfa681bedc8ff5e0f74e6657fb116f4b64375fd761bc2e037d1687e4df1dc49b7f97c1d36530abe3ffff6a1ae070b03f146b60b1c1c1cb6da05d9745bbc5a01df769071f1fe374828f8f15781d78ac84c7112df1e71b3af6f0720b30b26f2130b68430b6c7cf583cd66931185b42b465df22e059e848b34506cf5c431f7c5f1e65f4e1d7d6429ff1fa835d6330f83304f755b53f363590177f66fe4f10efb85ae7402ffc3c1f803e81a1213f98a13e18f8cc1f27cf9860e033fdfefebe7d3d3b7ad7f5f66c4b015aad8189cfa990346ac087ed1121be20183c7581539e3c7581539e35862c3865c2fdd5472995164f0ff4eeded9bf714fef9eadfb0eeeedefddb6b66f07528f34e891d4960192a28f1ff5c1c0244b7710efc98e3a2356b9e2a987e751f1f3b43bcab3f8c633dac8a9cec829037d46c2ff463bc833057179ddbc3c3a24768c0351518b311568312684674c95b5c0896af6e19ecaffc7931335462eb847634e669dc79a10073c01d69fd270ea7f6a671fa99319150c6c6c1e3dd551a5da086a8653bd6ba9194c7570a686203523a96620d58ca39a6154338a6a0651cd18aa19423523a86600d58c9f9ae153337acd4169c64ecdd0a919b9e381eb7bc0aa3e51ab774735a3a666d0d48c993aaa52effeea48441dfdaa2335f5e94d1d1da84f956a8641bdd3aaa318f50eadde55d5919a3a425347d4ea087329d932b253c8966bad5790ad243b95ec34b2d3c9ce205b457626d96ab235646791ad253b9bec1cb273c9ce233b9f6c1dd97ab20d641bc92e20bb906c13d945649bc92e26bb84ec52b2cbc82e27db1294ce4a5d41b635289d8dea25db4eb683ec4ab29d645705a5b3526ae65d9d8952679ed4d530ea6c933abba4ce26a9b347ea6c913a3ba4ce06a9b33fea6c8f3abba3cee6a8b337ea6c8d9aa95733f36a26feb6a034d3ae66d6d54cba9a395733e56a665ccd84df119466bad5ccf65d4169e65acd54ab99693513ad669ed54cb39a595633c96ae658cd14ab99613513ac667ed54caf9ad95533b96ae656cdd4aa99593513fb68509a695533ab6a2655cd9caa99523533aa66429f084a339d6a6653cd64aa994b3553a96626d54ca49a7954338d9f23fb3cd917c8be48f625b267c8be4cf615b2af923d4bf635b2af937d83ec9b64df22fb36d977c8be1b946af0fb643f20fb21d98fc89e23fb31d94fc89e27fb29d9cfc87e4ef60bb217c85e24fb25d9afc87e4df61bb297c87e4bf63bb297c97e4ff60ad9ab647f20fb23d99fc8fe4cf617b2bf92fd8dec35b2bf93bd4ef6463070c601078adfe8059efdeee9efefddbdb7bfb9bfaf79f7815dfd3bf7ee3ad87cddcefe2b9bfbaeedddb77d57df75f8e23bf4d0c453fb2bf6edeb39d8bc73cfb6deeb9bfb0ef437f76d6fbea2efc09e6dfbf1458fe917cd3c3462cfb66df6605faa390cd2af0e31e873fa757cd26475f9dc9e1f8a202f0ee545ff1a6242f7eb53514bf5f2fad2116df3fe5d7dfdcdb9e63df4b76717bda6775b6b33fe6f3f89bcbfbf797f7fcfbefee6edfbfa7637b7b7e27a1fcc0c2189d79b86f0a2a6f195671efc1f78fc6b863d5f0300", + "packedBytecode": "0x000000028df71de50000003e071f8b08000000000000ffed9d0774154796f75b4280f0d3b3088e045b3860c004e9492449c023679325030e801019e3210c382272c618b0c946e0999d4db339cfe69c739cd9303bb333bb3b3b73ce37bb5ffecef1f9aafad51dfd55543ff4e4aec77dd2ed734aaffaaabaefaffe7dab3a5577170599e93b2a15997c0f959e0eee9ee8ff69f35bf9e9a6aa18d755e993b3a840388b0b84b347817096140867cf02e1ec55209cbd0b84b3b44038fbc4c8a9d98a83f653dcbc0f78d0356ec64481695a56009a260b4cd3070b40d3f2a030faa8be05c2d9af4038fb1708e78002e17ca840381f2e10ce470a84f3d102e17cac40381f2f10ce8105c239a84038071708e79002e17ca240389f2c10ce8a02e11c5a209c4f1508e7d305c2f94c81703e1b23e708e01c667e9f33bfc3cd2f9519697e9f37bfa3ccef6853c712333f46a5b19a4da52aeb7f2995aa55aa51699cf5bff12a4d5069a24a93ccff2accff6a55aa53a95ea5c92a4d5169aad1619a4ad3559aa1d24c9566a9345ba5392acd55699e4af3555aa0d2429516a9f4824a8b555aa2d2529596a9b45ca5152aad54a941a546955e546995c5b25aa5352abda4d2cb2abda2d2ab2aad55699d4aeb556a5269834acd2a6d5469934a9b55daa2d25695b6a9b45da51d2abda6d24e955e57e9332aed5269b74a7b54daabd26755daa7d27e95deb0347b53a5b7547a5ba5772cce77553aa0528b4a07553aa4d261958ea87454a5632a1d57e9844a27553aa5d26995cea87456a5732abda7d27995de57e9824a1755baa4d2072a7da8d26595aea87455a56b2a5d57e9864a370d0b35848f54baa552ab4ab755baa3d2c72a7d4ea5cfabf47d2a7d41a5ef57e90754fa41957e48a51f56e98b2afd884a3faad28fa9f4e32afd844a3fa9d24fa9f4d32afd8c4a3fabd2cfa9f4f32afd824a5f52e91755fa25957e59a55f51e95755fa35957e5da5df50e93755fa2d957e5ba5df51e97755fa3d957e5fa53f50e90f55fa234bf33f56e94f54fa5395feccfc8fae83fdb94a7f61f27f697effcafcfeb5f9fd1b6b99bf55e9ef2cdb9755fa8a65fb7b95fec1e4ffd1fcfe93f9fdaaf9fd67f3fb35f3fb75f3fb2fe6f71be6f79be6f75fcdefbf99df7f37bfdf32bfff617ebf6d7ef53dd49b8333f9d2a06d4a0731f54935cdcdfa1e0a893d2c683f692d7a98ffd16f85b1979879fa25ed7a9af99e96bd9799ef65ada7d4cc975af67e66be9f651f60e60758f687cdfcc396fd5133ff28d813015c4b35766deb614c4560a3382c065bcfa0bd26dad68b5607b6de417b2db48db6632fb0f531b6de607bc0d84ac19630b63ea4994a65c6960ee28a89ca757abdc9b8d76bee2f3d183f6f935e6fb927debef1f336ebf5f6f3c0abe3a3bf59575f889b01c6d60f6c0f195b7fb03d6c6c03c0f688b13d04b6478ded61b03d666c8f80ed71637b146c038ded31b00d32b6c7c166babd6020d88618db20b03d616c83c1f6a4b10d015b85b13d01b6a1c6f624d89e32b60ab0d1d895a1607bc6d89e02dbb3c6f634d8a84f7d066c74ccf7acb1e97ea267112c63ecd44785cb503f0cb6e1d407836d04f5bf601b497d2fd89e07df641b05fd0ad9461b1bf551fa7f134d3e1dc4d52652619b9814f77ad59af57aebe25f6f783fae3e68d3350d7e268156934d3ec6313f55e8bbc824f243f612c8cf85b2548ef4a0fd0cb1ebfd49adc94fceb2dc446bb92494a975d43f1dc45bff3a8ba7ce62ee09793f315b9d9298edf09473cc3640593bf6e898a72bc6ec02e0f010b3e325663b3ce51cb31ba0ac1d7b74dcdb15637615707888d9757e62365529319bb9fe1504eed8a3739fae18b39b8023fe981d2731dbf129e7986d81b276ecd1f96f578cd9bdc0117fcc4e5827c7061d9e728ed97350d68e3dba16d31563f630707888d966e9673b3ce51cb337a0ac1d7b745db02bc6ecfbc0117fcc4ef214b3d512b341e65e6610b8638fae5177c598bd051cf1c76c935c9fedf89473ccfe1c94b5638fee9774c598fd2270c41fb31b7c5d9f4d49cc66c67004813bf6e8de5d578cd92f99bcbe37f697e6ded81360fb2b637b126c7f0d630fc8f637c63614eae5a10d4c9436d0e129e736f0b750d68ee5a74cbe2bb6813f020e0f31bb4e62b6c353ce31fb4d286bc71e8d69e88a31fb15e0f010b34d12b31d9e728ed9ff0e65edd8a3f1355d3166697ca83e5ef84773bc301c6cff646c23c0f655631b09b67f36b6e7c1f635631b05b6af1bdb68b0fd8bb18d01db378c6d2cd8be696c9560fb5763ab02dbbf195b0a6cff6e6cd560fb96b1d580ed3f8c6d1cd8be6d6ce3c1f61d639b606cfa3e168da9fa5d632b05ae7410dfb64d8006341559f369c857f9e5a94c020ffaaa8edf57b5ae7b2ae878ddab81a7c643dd13e0a3233c35c0332e7e9e703ce9f8f8d71b6ee394a569027ca5a05e133cd4ab087cd1ba699efc25c1866d7a828331f6fdb3da8f16812f5a37cd4f0446b2611f437d2eb51fdd370f296ae3f5d096c2fd33fa4b0307f92b8132e306b7951d6ad8cae0ffd8df8eb36c9ee2328c0bf245eba679f25706f519977fc65447196b2c465f7d4411f8a275dbbecb205fe9579fac3ce399f8aef5e4dbeed348f3da3cf89e68f9aeb67c63df4953b67ddb4460f6709e52753fce53f0f881c379cacca2b6b2f6f906f5c3b99ea74cb096e3789e3209f6851eda431803b51607cd5783767511dad5827654e639d0ce573f3ec9e2a1f971c043fd37f6679579e6a964e01b8f6169bbe1b9141e07f8da5e951623cdbbb6d74460741dab78389fc97aac52038c64c3eb38294f9a456dd71413df1e6225ec8fc8071d9b53fb257f255066418fb6b26ba1aff41123188f3475f49c37feed940acfc16b72e0c16de7e1bcaaca533c56e2f59b4f827863cdee976a2cada2aef1f8eacb53160fcd933f61166661166661166661166661166661166661166661166661166661166661e6cf8cf79370dc16951bc784d11effe6eb3a7ff88e3db32ebc07f45dafe3c15295381686c6418cb0ea5c0265ca8bdbd8fe078c07b3c712456d4b1f6363b36d4bf287e3c1f2710fb1dae2b17d9739f4c1fbd2a899af3150769f41f3383e8df4ab041e5fedb1cae2b17d639f9162aa59543feb6b6c41549cb9c61356c4e63bd5e4ebbeae7e9f997e27a8bdff1a67691abe6bd4b2e93ee9851e6df5f6719f37d7fbceb8dfa07c9cf77193c083bee2ef6753edc6271407edf71518ebbec66a51bba2b111b596ef122833a4b86ddbd4c1ffd3c1ddfb062c43eba6f911b06c9db5ee727ff5cd3a0ea516b829dfcbaadb78e0a6324fc1befbcf4cded33e3095eb3312b84f8e7fff92192f92ca8107f7773e8e593ced472b311ee31e2f628f83741d2f53191c43ea61fc6ed67d31f91366611666611666611666611666611666611666611666611666611666611666fecc9ac7be878ef77eab9930e6698c4d783f83dec586f7c57eb2b8cdafef7b8074cf69a455677c46398067947fd6b0e1d8077caf946b5bfabab716b52dc91fb7b10f650e7db466750ecdea3d31da7d06cdd70323e957073cbeda63d4bb3b5c7d462553cda2fa591f6317b2c5996b9c42456cbe33e3457cdcd7a5f122f6fecb7eaf118e93201bde078f7a5f589565bbdf7d806b5c1be5f19d0bf1f79ba976f780edb182e40fc7497cc5684be324e2ef0752953ef711d446694c48ca51572af3d5e2b6b25f33791c2b540debfaaee3ff34651b93807dea94f8eb1c6edfa9665db47da7387ca7813526df55e8bbc85a37d94b20ffdf8aef66203d486b62d76d04df6315b55c8db55c12ca4c76d43f1d73fda7583cb88df5a463e71b1067df85633d5f7dd2e4088d46804654c6f37b609de37cedb1cad88ff6b6cad0b2f87ecbff037d54d49874d73ec0d7f142d43e008f17ecfd4247c68e77f7f1807dcc79888ff180b4eef2a0fd98bcc05aff48583f71f50ea2f72ddf3b1787f5fb1cb37eaff75eb9cefd8817c71b5299fe70ee37d3e47339f7bb5fe7f1ae733f5c2eaaeed82fc4bd6fc47844167c5f2495196cc5635d04f744c7b24f462c4b5ad9ef3ec4f3523c4688ffbd9199fe668a55176a5393a12e54e659abddc47fcc9439fef4f58e4c3ad6a13ea8ca51572a3312dada28934fc076c2fd429de3ff34653bfe24fd749da7c55fe770fb4e37eba2ed3bcde17b06b0c6e4bb0a7dd3f127f9217b09e46b617f42e5480fd29ad8cb8013d9ede56aade5925026eda87f3ae6fa4fb378a659cc3a76c6429cd5c1b316befaea74e0d6682468f43d7f6073bdd7d8b58ff1f53c5ad43ea60a18ed7e13f793f97c56cebe7eeb3a3ea132780c4d65e6413f9b7094b5af4bd372718e4fc7e781f0b8109f07f2758e940cdaeb99b4387cfa2eb77c97e7d1773fcb77bf3cfa16cd45734e9a73fae60fee5b8a81d1c779235e1fe90823be8f8096eb018cbe9ed94ce5c0580d8cb8bf23460fef57aeeaec3785f058a72730fa78de38d7ebd5f87e737cc70031fa78463bd7f754e373dbb45c6f60f4f15d23fc865247185ddf3a2a855f0fdf35aaeaec7740f05b477d80d1c7b7411241fbef99dc8b711230d2720f00a38ffb4889a0fd75b57b31e2fd4a5a2ee19931dbbeddf3d89f54aed720f231ae20ea58037d7bb8fe9fc2b1091dd1a2de2f4fd6631ff4ede1fa57a8457dd0712df0fe9c877ba3613b9e9c030fde43a4e5fa03e3544f8c5372609c0a8cb4dc00604c7b629c9a03631a1869b98780d1c375c890319d03235eaf23fbc3c038dd13e3b41c18a703232df70830fab8a69800bf1d619c018cb4dca3c038d313e38c1c186702232df71830cef2c4383307c659c048cb3d0e8cb33d31ceca81713630d2720381718e27c6d93930ce01465a6e1030cef5c4382707c6b9c048cb0d06c6799e18e7e6c0380f1869b921c038df13e3bc1c18e703232df704302ef0c4383f07c605c048cb3d098c0b3d312ec881712130d2721505c038b400189f2a00c6a70b80f19902607cb600184b0b80f179605c143f63789eba3007c645c0f342fc3ca1668b72e079c12f4ff87ec2450e5f8be3f795cab5ee8b816749fc3ce1b6589c030f312461b917fc32a63acba87996c6cf136ab624079ea5a0d91287661e18539d65d43ccbe2e709355b9a03cf32d06ca943330f8ca9ce326a9ee5f1f3849a2dcb81673968b6cca19907c654671935cf8af87942cd96e7c0b302345beed0cc0363aab38c9a6765fc3ca1662b72e059099aad7068e68131d55946cdd3103f4fa8d9ca1c781a40b3950ecd3c30a63acba8791ae3e709356bc881a711346b7068e68131d55946cdf362fc3ca1668d39f0bc089a353a34e3c4883c71bf6fbcd1e16b1583ba130332f62900c6070a8011c720f8e8bfb28d4168f4ab4faab3faf8da5ed9c620a0efd59eb45815745c8bd57e79b28e4140df6b3c69b13ae8b8166b80e7250f5a24c0474778882109cbf52f00c60105c0f85001303e5c008c8f1400e3a305c0f85801303e5e008c030b80715001300e2e00c62105c0f84401303e59008c2f7a66cc76fef25217f71d75aed2d57d479d977475df12e712e7ddc1b7c4b9c47977f02d712e71de1d7c4b9c4b9c7707df12e712e7ddc1b7c4b9c47977f02d712e71cec9f7cb1e7c27c0074dd9aef1134312967b5118bb3423f254c4c7538975475faf30a8fb2b0e9e224f75475faf32a83b31141ae3cb05c0f86201308a8e9931889d61d43c6b3df1bc9a03cf5ae059e789676d0e3ceb80677dfc3c614cadcb81871892b0dc8b05c0f87201308a8ea2232746d1b1fbe8288cc2288cc2783f180ba10f97fd4ce6dca5338c9aa7297e9e50b3f539f0348166b4dc0b7e19539d65d43c1be2e709356bca81670368d6e4d0cc0363aab38c9aa7397e9e50b30d39f03483661b1c9a79604c759651f36c8c9f27d4ac39079e8da059b343330f8ca9ce326a9e4df1f3849a6dcc81671368b6d1a19907c654671935cfe6f87942cd36e5c0b31934dbe4d0cc0363aab38c9a674bfc3ca1669b73e0d9029a6d7668e68131d55946cdb3357e9e50b32d39f06c05cdb63834f3c098ea2ca3e6d9163f4fa8d9d61c78b681665b1d9a71657cb100185f2e0046cf3aa63acba879b67be2d99603cf76e0d9e189677b0e3c3b80e7b5f879c298da91030f312461b9170b80f1e50260141d45474e8ca263f7d1511885511873637ca50018655b0b2357460fe757599f4fd9d1c57d473d9fd2d57d473d9fd2d57d4b9c4b9c7707df12e712e7ddc1b7c4b9c47977f02d712e71de1d7c4b9c4b9c7707df12e712e7ddc1b7c4b9c47977f02d712e71de1d7c4b9c4b9c7707df12e712e7ddc1b7c4b9c47977f02d712e71de1d7c4b9c4b9c7707df12e712e7ddc1b7c4b9c47977f02d712e71de1d7c4b9c4b9c7707df12e712e7ddc1b7c4b9c43927df3be3f79dcaf519d69dc0e3e3995a4ff5acd4eb7dddaceb9318f5d35a7dc6d26a87a55512cabc0efa7dc6837e45e097d64df3e42f57e6610c983df94e3da8d6d107ea4f3e5eb6f4d0fe7779aa7b545fbfab8bfb8eeaebbbbaefa8bebeabfb96389738ef0ebe25ce25cebb836f897389732ebe315f12b41db7d3fb95f43a769b7c4f334fe55f81e5a8ccbcde99dff240da900fdfd286645fd11d7c4b9c4b9c7707df12e712e7ddc1b7c439bf38c7789897079ec0e209b2f0e4e3fe412e3c6398f1cc60c6339919cf04663c55cc784632e3d9cc8ca79919cf7a663c3d98f1cc67c6339319cf4bcc78a630e399c88c27c58c672b339e95cc789631e319cd8c6731339e5799f1cc62c6339519cf1a663c9398f15433e3d9c68c670b339e61cc783632e36962c6b38019cf5a663cb399f1a499f1d432e319ce8ca78619cf76663ccf31e36964c6d3c08c6739339e25cc78ca98f12499f12c64c6338719cf34663c75cc78c631e359c58c6713339e0dcc78d631e319c18ce741663ce5cc78c632e399cb8c673a339e7a663ce399f15432e359cd8c6705339ea5cc78fa32e3e9c78c6711339e51cc788a18f02482bbdf719280ffef045bb1b5ac7e2ceccdc16dffdf63ecc5b0cc5e93efe158f71eb0d1b3667b1dcba24e7ba02e6993affc7453a813fa4ac33cf92b038ebd4c784631e359c48ca71f339ebecc789632e359c18c6735339e4a663ce399f1d433e399ce8c672e339eb1cc78ca99f13cc88c6704339e75cc783630e3d9c48c6715339e71cc78ea98f14c63c6338719cf42663c49663c65cc789630e359ce8ca781194f23339ee798f16c67c653c38c6738339e5a663c69663cb399f1ac65c6b380194f13339e8dcc788631e3d9c28c671b339e6a663c9398f1ac61c6339519cf2c663caf32e359cc8c6734339e65cc785632e3d9ca8c27c58c6722339e29cc785e62c6339319cf7c663c3d98f1ac67c6d3cc8c6733339e91cc78aa98f14c60c6339919cf0c663c6398f1ec64c633cfc1e3e1fb79210f8d57a575d3fc4e26be3d6c87f0bb819ff554a77d665dbdcc7a899ffc954099457d32bf7abc0e2e4b5cf6f8628cd57da0d16e4f75897a27f3ee2eee3bea9dcc5ddd77d43b99bbba6f897389734ebef7c5ef3b85cfa6d05464cda7218ffb171fcff478aa67bb7d7bdcdf04de6f69b5dbd22a09653e0bfaedf7a09feb7881e6c95faeccc31830635c5404f1c6c51bf1d7e97bdf1a265ddfb0f4c57abde949d3a87dc89b5ddc77d43ea4abfb8eda877475df12e712e7ddc1b7c4b9c47977f02d712e71cec9f75b261fe3796325fad0d77ee97ce02df0fb8ec917c5e857afeb6db32efa363271bc033c54e647e05ab4b47969f371f9967d9bc47977f0cd39ceed3cdd43c4f776fbbac71b158bf9b8bf7c3f7d47c56257f71d158b5dddb7c4b9c43927dfefc6ef3bbc87b833683f65bb87f82ef0bced410b4ff50ccf9d0e5875da69d5290965f05cee80877a16815f5a37cd1f80ed5068cc9a87c6b2e3fb19a9dc4b4c18c9f6b65f9eb07dbd14b49fb2b5af03c0e3a11d5479aa67d8be5aac3abde4d09dca60acb678a8a7abedd07c0b6c87960263d63cf4ec1cb126a0dcab4c18c9f6ae5f9eb07dbd1ab49fb2b5af16e0f1d1ff78aa67d8be0e5a757ad5a13b95c1583de8a19eaeb643f3e4af109935cf5a9327d604945bcb84916c07fcf2d424a0ce34656b5f0781a7c5833e9eea19b6af43569dd60677eb4e6530560f79a8a7abedd0fc21d80ec22ccc2e66cdb3cee4d79adf04945bc784916c2d5e796a2a1350679ab2f5638780c7473fef49f7b01f3b6cd5699d43772a83b17ad8433d5d6d87e60fc376c885795f01328bcea27314b3e82c3a47318bcea27314b3e82c3a47318bcea27314b3e82c3a47318bcea27314b3e82c3a47318bcea27314b3e82c3a47318bcea27314b3e82c3a47318bcea27314b3e82c3a47318bcea27314b3e82c3a47318bcea27314b3e82c3a47318bcea27314b3e82c3a47318bce9d63d63ceb4d9e5813506e3d1346b21df4cb133ebfb33e683f1559f369c81f069e431ef4f154cf70dcfb11ab4eeb1dba53196c5f473cd4d3d57668fe086c875c98f71520b3e8dc3966cdd364f2c49a80724d4c18c976c82f4fd88f3505eda76cfdd811e0f1d1cf7baa67d88f1db5ead4e4d09dca60fb3aeaa19eaeb643f347613b08b330bb9835cf069327d60494dbc084916c87bdf2a4c2e7103704eda76cfdd851e0f1d1cf7bd23decc78e5975dae0d09dca60ac1ef3504f57dba1f963b01d7261de5780cca2b3e81cc52c3a8bce51cca2b3e81cc52c3a8bce51cca2b3e81cc52c3a8bce51cca2b3e81cc52c3a8bce51cca2b3e81cc52c3a771f9d354fb3c9136b02ca35336124db11af3cd5e17d87e6a0fd94edbec331e0f1715fc693eee17d87e3569d9a1dba53196c5fc73dd4d3d57668fe386c87aecebcaf00992536f2c32cb121cc51cc121bc21cc52cb121cc51cc121bc21cc52cb121cc51cc121bc21cc52cb121cc51cc121bc21cc52cb121cc51cc121bc21cc52cb121cc51cc121bc21cc52cb121cc51cc121bc21cc5cc213634cf469327d60494dbc884916c47fdf284ef3dd818b49fb28ddb390e3cc73ce8e3a99ee1b89d13569d363a74a732d8be4e78a8a7abedd0fc09d80ec22ccc2e66cdb3c9e4893501e536316124db31bf3c613fb629683f65ebc74e008f8f7ede533dc37eeca455a74d0edda90cc6ea490ff574b51d9a3f09db419885d9c5ac79369b3cb126a0dc66268c643bee9727ecc73607eda76cfdd849e0f1d1cf7baa67d88f9db2eab4d9a13b95c1583de5a19eaeb643f3a7603b08b330bb9835cf169327d60494dbc284916c27fcf2a41250679ab2f563a780c7473fefa99e613f76daaad31687ee540663f5b4877abada0ecd9f86ed5068cc9a67abc9136b02ca6d65c248b6937e79c2f6b535683f656b5fa781c747ffe3a99e61fb3a63d569ab43772a83b17ac6433d5d6d87e6cfc076283466cdb3cde4893501e5b6316124db29bf3c61fbda16b49fb2b5af33c0e3a3fff154cfb07d9db5eab4cda13b95c1583deba19eaeb643f367613b141ab3e6d96ef2c49a8072db993092edb4679e04d499a66cedeb2cf0f8e87f3cd5336c5fe7ac3a6d77e84e65de847a9ef3504f57dba1f973c043d33ce0f1159781c51338f4a1690c339e19cc782633e399c08ca78a19cf48663c3d98f1cc67c6339319cf14663c1399f1a498f1ac64c6b38c19cf68663c6f32e359cc8c6716339ea9cc78d630e399c48ca79a19cf30663c0b98f1cc66c69366c653cb8c6738339e1a663c8dcc781a98f12c67c6b384194f19339e24339e85cc78e630e399c68ca78e19cf38663cab98f18c60c6f320339e72663c6399f1ec67c6339719cf74663cf5cc78c633e3a964c6b39a19cf0a663c4b99f1f465c6d38f19cf22663ca398f11431e04904778fa549c0fff7838dc67c6c07db7b267f066cc50e1f74aff81cd84a4c9ed6d15ba5a383ef5e37eae46b9c0bfa4ac33cf92b038ef798f08c62c6b388194f3f663c7d99f12c65c6b38219cf6a663c95cc78c633e3a967c6339d19cf5c663cfb99f18c65c653ce8ce741663c2398f1ac62c6338e194f1d339e69cc78e630e359c88c27c98ca78c19cf12663ccb99f13430e36964c653c38c6738339e5a663c69663cb399f12c60c6338c194f35339e49cc78d630e399ca8c6716339ec5cc78de64c6339a19cf32663c2b99f1a498f14c64c6338519cf4c663cf399f1f460c63392194f15339e09cc782633e399c18c670c339e790e9efd9e78ece7bc687e3f03df7abe1674d15302fe8fcf81bde98971bfc548f36f0223f2fad6acdce229b734bb9fbe75fde95ec583e617b7173ef7c0617b95e741b37e164f3f4bb3fbe95b6b41f7fe698c0d6e2f1c07cd617be1384d0ffd734dc2e2d15391359f86fc39cffa78aa67258e9bfc24c6f56aadce5b5aedb7b44a4299b3a0df790ffa15815f5a37cd933f6116e62866cd43f7725de379173261241bbe47e5fdf8796a12168f9eb2f58fef7bd6c7533dc37eec42e0d6fd7dd09dca60ac5ef050cf22f04beba6f90b0edf1541bc5a5cec8016171d3c17f3ac05f9cb95f96c013273d059f3d0d875624d40b9454c18c9761e782ec5cf5393b078f494ad7fbce4591f4ff50cfb840f02b7ee9740772a83edeb030ff52c02bfb46e9aff00b6432ecc170a905974ee1cb3e6596cf2c49a80728b993092ed22f07c183b4faa3261f1e8295b3ff6a1677dfcd433d38f5d0edcba7f08ba53196c5f973dd4b308fcd2ba69fe326c076116666116666116666116666116666116666116665d4698855998855998855998f9326b1e7af69c5813506e091346b27d003c5762e7c9dc77401e3d65bbef70c5b33e7eea99b9ef703570eb7e0574a73218ab573dd4b308fcd2ba69fe2a6c0761166661166661166661166661166661166661166661166661166661166661e6cdac79e81b16c49a80724b993092ed32f05c8b9fa72661f1e829db7d876b9ef5f154cff0bec3f5c0adfb35d09dca60ac5ef750cf22f04beba6f9ebb01d8459985dcc9a87de8548ac0928b78c0923d9ae02cf8dd87932f74f91474fd9fab11b9ef5f153cf4c3f763370eb7e0374a73218ab373dd4b308fcd2ba69fe266c875c982f1420b3e82c3a47318bcea27314b3e82c3a47318bcea27314b3e82c3a47318bcea27314b3e82c3a47318bcea27314b3e82c3a47318bcedd4767cd43dfe824d604945bce84916cd781e7a3d879aa2b13168f9eb2dd77f8c8b33e7eea99b9ef702b70ebfe11e84e65b07dddf250cf22f04beba6f95bb01dba3af385026496d8c80fb3c4863047314b6c087314b3c4863047314b6c087314b3c4863047314b6c087314b3c4863047314b6c087314b3c4863047314b6c087314b3c4863047314b6c087314b3c4863047314b6c0873143387d8d03c2b4c9e5813506e051346b2dd049ed6f8796a12168f9eb28ddb69f5ac8fa77a86e3766e076edd5b41772a83edebb6877a16815f5a37cd933f6116e62866cdb3d2e4893501e556326124db2de0b9133f4f2a61f1e8295b3f76c7b33e9eea19f6631f076eddef80ee540663f5630ff52c02bfb46e9aff18b643a1316b9e06936f35bf0928d7c084916cb781c743dc853c498b87e6ef30f0ade71b4dbeccfce2f66a04460edb2b9907cdca2d9e724bb3fbe95bd77f95c93f687e717bad02460edbab3c0f9af5b378fa599add4fdf5a8bd526dfd7fce2f65a0d8c1cb6573fbf3ca984c5a3a76cc71b1f03cfe7e3e709cfe33ece81e7f3c0f3b9f879aa3cd5b352aff7fb803daef56aadbe6069f5b1a55512ca20c3173ce857047e69dd344ffe845998a398b12f24d60494bbc384916c9f031e1ffd86aefb28b32e5a7f4f951eeadfe6b7357ebf35786da197592f7190bf1228f3f2a036b6c70c5b19fc9fb69baecf2dcbe6e999b72ad7755e9a277f6581fb5cdfd735d4568bc7f65de6d0476b76d3a1d90d4f8cf633ad347f03185dd7797d3d2f1a75dd199f17bd63e9c84d337c0ef823e0f1755cdc6af1b43ab4f0d1e6723dbefcc8c1f3497c3c95181be8cb47ac62dfd691babbda4e8c75afc27b58e8cb431b08f753a3cdba68fd7a5f50dbdfabe635d83fd07e6ab455e712283309f65353b2eca78a83bbaf0b57183b95a1ff7f62ecf63a2a82fb7b6da90cf2b5e61763946cb2ff6d7f0fb3d6d2919b66d8ae5b81a7d5134fd43531f287dbb0cea1591d03cdb02de423ceee583cb6ef24e8d2ca54338c333c6ef0d59fddeb5a1e6ec37a8766f50c34e3d89fd55b3a72d3ccd59fa18e0b1ddc0b197073ec53165a3a72d3ccd5a7a08e8b1cdc8b1870736cd78b2c1db96976af76bdd8c1bd980137c776bdd8d2919b66f76ad74b1cdc4b1870736cd74b2c1db96976af76bdd4c1bd940137c776bdd4d2919b66f76ad7cb1cdccb1870736cd7cb2c1db96976af76bddcc1bd9c0137c776bddcd2919b66f76ad72b1cdc2b1870736cd72b2c1db96976af76bdd2c1bd920137c776bdd2d2919b66f76ad70d0eee0606dc1cdb7583a52337cdf27d1f20ea7e13f9c36dd8e8d0ac9181661cfb94464b476e9ae5fb3ec0bdc660e3365ce5d06c1503cd38f667ab2c1db96996effe2cea7e13f9c36db8daa1d96a069a71eccf565b3a72d32caa3f6b8d9f27e7f1f6ad5ef5c97c67b935071e1c33e523a63cc541a5a73155e1787bfbfb15ad9656c9e0ee6f5af81c7b18353e92fc09b3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300b337f667c9eb9d5fce2bb50ef3061241bde93f2719d5fd77d8c5917ad5f3fdb7b6b409bdff8ef5ba42af19e2b3d773cc6aa730994f9bf8fb7b17d6cd8f0fe226db7a86d79bfdead80efa3c07b41f7f37ee7470ecd6e3834bbee89d1ee3368fe3a30daef7fb8dfef9eb863e9c84db3a87ef68e279ea838bbe3f05d119bef5493affbbafa5d847d82bbf75f771c9afa88c35cdf7d81eda2d5038faff75ce83a5db7ea74cbaa5312ca0c837adecfb645d33ce0f1d51f05164fe0d087a662663c3398f18c61c63399194f29339e09cc78aa98f18c64c6f30c339e2798f13cc68ca73f339e3ecc787a30e399cf8c6726339e29cc782632e34931e3799619cf4a663c4f32e359c68ce771663c8b99f10c60c6f300339ed1cc784a98f13ccf8c6716339ea9cc78d630e399c48ca79a194f3eee81e6c2338c194f05339e81cc781e62c6b380194f82194f4f663cb399f1a499f1d432e319ce8ca786194f23339ee798f13430e319ca8c6739339e41cc789630e3799819cf42663c65cc7892cc787a31e399c38c671a339e3a663ce398f1ac62c6f314339ec1cc781e61c6338219cf83cc78ca99f18c65c6d39b19cf5c663cd399f1d433e319cf8ca79219cf6a663c4f33e359c18c6708339edbcc789632e359c48ce751663c7d99f1f463c6338a194f11039e4470f7b34bf8bcdc2db0d13336ad602b76ac8fc6e552797ddc7976f0ddeb2e76acfb86830175ba0675499b7ce5a79bda3d575464d64bf3e4af0c386e30e119c58ca71f339ebecc781e65c6b38819cf52663cb799f10c61c6b38219cfd3cc785633e3a964c6339e194f3d339ee9cc78e632e3e9cd8c672c339e72663c0f32e319c18ce711663c8399f13cc58c6715339e71cc78ea98f14c63c63387194f2f663c49663c65cc781632e3799819cf12663c8398f12c67c63394194f03339ee798f13432e3a961c6339c194f2d339e34339ed9cc787a32e34930e359c08ce721663c0399f15430e319c68ce726339e6a663c9398f1ac61c6339519cf2c663ccf33e32961c6339a19cf03cc780630e359cc8ce771663ccb98f13cc98c6725339e6799f1a498f14c64c6338519cf4c663cf399f1f460c6d387194f7f663c8f31e3798219cf33cc784632e3a962c63381194f29339ec9cc78c630e399c18ca79819cf3c8b07ffafaf35d0f5c5eb60a3ffffa7b9795f6eea71ddf217433d2aa3becde34b339cd20e4da2becdc3816706339e31cc782633e32965c63381194f15339e91cc789e61c6f304339ec798f1f467c6d387194f0f663cf399f1cc64c6338519cf44663c29663ccf32e359c98ce749663ccb98f13cce8c6731339e01cc781e60c6339a194f09339ee799f1cc62c6339519cf1a663c9398f15433e3b9c98ca78219cf40663c0f31e359c08c27c18ca727339ed9cc78d2cc786a99f10c67c653c38ca79119cf73cc781a98f10c65c6b39c19cf20663c4b98f13ccc8c6721339e32663c49663cbd98f1cc61c6338d194f1d339e71cc785631e3798a19cf60663c8f30e319c18ce741663ce5cc78c632e3e9cd8c672e339ee9cc78ea99f18c67c653c98c6735339ea799f1ac60c6338419cf6d663c4b99f12c62c6f328339ebecc78fa31e319c58ca788014fd4b770e8ff3dc076d5e46f83ed8ac9df04db6593bf0eb60f1db662070bf9bb0a361ae772056c74afee32d8e87a11f9d2c7bb1707dfcd5aeca8530f07eb15479dae3a96c5ed48cba48378b723fa4ac33cf9c36ff55c65c2338a194f3f663c7d99f13cca8c6711339ea5cc786e33e319c28c6705339ea799f1ac66c653c98c673c339e7a663cd399f1cc65c6d39b19cf58663ce5cc781e64c6338219cf23cc780633e3798a19cf2a663ce398f1d431e399c68c670e339e5ecc7892cc78ca98f12c64c6f330339e25cc780631e359ce8c6728339e06663ccf31e36964c653c38c6738339e5a663c69663cb399f1f464c69360c6b38019cf43cc780632e3a960c67393194f35339e49cc78d630e399ca8c6716339ee799f19430e319cd8ce701663c0398f12c66c6f338339e65cc789e64c6b39219cfb3cc7852cc782632e399c28c6726339ef9cc787a30e3e9c38ca73f339ec798f13cc18ce719663c2399f15431e399c08ca79419cf64663c6398f1cc60c653cc8c679ec583d7142bc146f92ab0513e0536ca57838df23560a3fc38b0517e3cd8283f016c949f0836ca4f021be5e99e113edf938ff7c2912f5a37cd5f03c6db268fdb84f275c0fd8165d3dc973c717f6071d3fc2560a43a7c0036cad703f745cba6b92f78e2be6871d3fc0560a43a5c041be527838df253c046f9a9609b0afec846f96960a3fc74b0517e06d8283f136c949f0536cacf061be5e7808df273c146f97960a3fc7cb0517e01d828bfd0fcea6dfcbe65d3dbf8bcc9a78378b731f9a275d3fc7960a4edfd3ed828bf08b8dfb36c9afb9c27eef72c6e9a3f078c5487f7c046f9c5c07dd6b269ee339eb8cf5adc347f0618a90e67c146f925c07ddab269ee539eb84f5bdc347f0a18a90ea7c146f9a5c07dd2b269ee139eb84f5adc347f0218a90e27c146f965c07ddcb269ee639eb88f5bdc347f0c18a90ec7c146f9e5c07dd4b269ee239eb88f5adc347f0418a90e47c146f915c07dd8b269ee439eb80f5bdc347f0818a90e87c146f995c07dd0b269ee164fdc072d6e9a6f0146aac341b0511edf47bfc613e36d8bf1b6e51befe3e2b1e501cba619dff5c478c062a4f97781b1c5e40f00cf014f3c2d168fed3b09baac61aa59126c2dc053eb89e79ac573cdd202c7bbe1b9c01acbe673bbaeb11869fe0030b6987c3eda668bc563fb4e822eb54c354b82ad0578ea3cf15cb2782e595ae0732e78ee566bd97c6ed75a8bd1ee2b30ceb0aff0d5365b2c1edb771274a963aa19f6b92dc053ef89e782c573c1d2a20cf278fe5867d97c6ed73a8bd1ee2b30ceb0aff0d5365b2c1edb771274a967aa19f6b92dc0d3e289e7bcc573def28ddb10cff7175a369fdb75a1c548f3d8e7da6da114f271f3d45b3cb6ef24e8d2c25433575bf0d99f9db378ce59be711be2f5994596cde7765d6431d2fc42606c3179dc868b3cf1b4583cb6ef24e852cf5433575b2805b6b879ce583c672c2d70dc1e5e4fabb76c3eb76b54ffb108185b4c3e1f6db3c5e2b17d274197c54c35c363c816e069f1c473cae23965f9c66d88d73f9758369fdb7589c548f3d8e7da6da114f271f32cb6786cdf49d0a585a966aeb6e0b33f3b61f19cb07ce336c4ebd54b2d9bcfedbad462a4f925c0d862f2b80d977ae269b1786cdf49d0653153cd5c6dc1677f76cce23966f9c66d88f7179659369fdb7599c548f34b81d16e0ba5908f9b27aa3f237f49d0a585a966aeb6500a6c71f31cb1788e585a94411eef07b558369fdbb5c562a4f965c0485ab5004f8b279ea838237f49d0653953cd9260cbc77ef390c573c8f28ddb10efdfadb06c3eb7eb0a8b91e65b80d16e0ba5908f9b67b9c563fb4e822e8b996ae66a0ba8630370afb46c3eb55d6971d3fc0a605cecd071a5279ea83e6525e8d860e9c84d33573ca28e8dc0dd60d97c6adb60713758dabae2b114f271f344b5eb06d0b1d1d2919b66ae782c03b655c0bdd8b2f9d436aa1d3500e3724b5b9ffbbda86dbd1874245d1a996a86d735715b13db6ae06eb46c3eb56db4b8ed3683db1adb4ca3279ea86ddd083a922eab986a867d0f9e0ff93aff88badf950fdf51f740f2e13beaba783e7c475d2bcd87efa8fbe8f9f01d754d251fbeef759eedd377d435cb7cf88e3aefcb87efdb96efdb79f41d35fe2d1fbea3c64475f5f62dfb92eeb52fb99ffd5a77dd97487fceb33f5f1dbfef5422687f4ea3a7226b3e0d793c7f59e5410b4ff5acc473c24f625cafebdc7ab9a5159e5be339aaaff3bfd5160fcd93bf4264c6b8288acf77255e87c1ef3bd275914ab0d175b12ab0d175d114d85a4cbe1a6c744fa6066c743f701cd8e85ef47cb0d138880560a3313817c046e3bfde071b8d3d3c0f361af7fa1ed868ccf539b0d178ffb360a3674dce80ed1d933f0db6b74dfe14d8de32f993607bd3e44f80ed0d933f0eb6fd267f0c6cfb4cfe28d83e6bf247c0b6d7e40f836d8fc91f02db6e93c76befbb4c1eafe57cc6e4f15adeeb263f1e6c3b4d7e02d85e33f98960db61f293c0b6dde46f836d9bc95f01db5693c7ef8b6e31f90fc0b6d9e42f816d93c95f04db46939f0cb666939f02b60d263f156c4d269f06db7a939f06b675263f1d6c6b4d7e06d85e35f999607bc5e46781ed65939f0db6974c7e0ed85e34f9b9607bc1e4e781ed63933f08b6cf993c5e072d3679bc7e4fef9bc27b5ef4ce4bbce749ef95c6fbedf4ed8f16b0d1f7b5709c51a9c9e318377aaf148eafa47749e238d584c9e3b8f23293c7671ae8bb1ff86c087d3b0a9f4b2a37797c268ebef979006cf45dd277c146ef9e7a076c034cfe6db0d13b9ddf021b7de7e24db0d1b79bde001b7def733fd8e81d53fbc0f6b8c97f166c034d7e2fd80699fc1eb0d1379a76838dbe13b90b6cf42ea9cf808dde8ff83ad82a4c7e27d8869afc6b607bcae477808dbebfb81d6cf4cea86d60a3f70e6e05db3093df0236fadec166b00d37f94d60a3ef786d041bbd1baa196ccf9bfc06b08d32f926b08d36f9f560a377f3ac03db58935f0b36da67bf0a36da67bf0236da67bf0c36da67bf0436da67bf0836da67bf0036eafb3f061bf5fdd47fe876aadbef2d339f0ee23b8ed2fe5a83f653b6637962409e388f8d93c083be6ec65ef754781cfe915957b1592fc5cb4df07d3d76df9973801b665d3dcd7aaf5bbe4ba04ce9c0b66d730dfe9f863ad0725886d64df36360d96bd6bacb4d7d6f78aaef758b89b86f001395291bd856f64b265f0acbc4c8169ecf52ac05a0214e69c813831fad52e1f9c54739f0dc009ef8db49e6fcda474c60db8afbfcdabe2e63c75a12ca5c07fd7cbd17eb86c543f3e44f98855998855998855998855998855998855998855998855998855998855998f9336b1eba9f40ac0928778b0923d9f05e978febfc78cf15ef79dd1cd8e6d7f7fdbd5e66bd63ad3a9740996f0d6c63bb6df265f07fda6e51dbd2c37dc2acdbf27bf7caa03e782fc8c3b60c796e5a3cb6ef32873e5ab36b0ecdae7a62b4fb0c9ac76fbe907ed780c7577bbc6ef1d8beb1cfb8c154b3a87ed6c7b8846c71e61a8350119bef5493affbba7a2c941ecb61efbf6e599ae21808bc67fe25e89368993be63701fadc017dee671f608f4bc07eaa1518e3ef3753edee0153df3fc6d214c740fc96d196c640c4df0fa42a7dee23a88dda632bb0ae54e6f7613ff787268fe3806ec1babee2f83f4dd9c624609f7a39fe3a87dbf743b32edabe971dbe3f00d6987c57a1ef2293c80fd94b20ffe5816d65edef4c91d6c48edfc242767bb9566bb92494b9e2a87f3a88b7fe972d9ecb16b38e9d3f8138fb0a1cebf9ea93ae4468340634a23278cceb6bfff591c5431ce40ffbd1de56195ab604ca7c1dfa285d17eae75bcd6fd43ec0d7f142d43e008f17ecfd42c251471d1fb706b4f176f7b17eff05fdc535f87f3af8f463fdfe0b62c8755c4aeb1f0beb27aede41f4be85cafc2f6b3feae37c12b7a5ad278e25a432ff0ffaa1d4a04c3e97f3bafb758e1e755ee7e3db9978ae4153b6fd3bee637cf42f9eea59e9da775db3ea948432c3a09e1e8e639cfb2d9abf0cbe7d7d2f957cd031d4754b8b122893346d87fa8e281df1bac48dbcd425e53c1e1ceba80b9519007529057b9c4c3eb71b1e67e9f5de74d495ca3c36a8adec40934fc076c2be7484e3ff3465eb0f483f5de78bf1d739dcbef4dc226ddf8b0edfef036b4cbedbbdbf828ef7c90fd94b203f7c505b59fbdb9da4357e8b959eaf43767bb9ebd672492873c951ff74106ffda3be334bfe74ec0c8138a338f2d96f5e8ad0682c684465f05e817dbd256abfef632c7db6fdfe4d60b4fb4dad696a907f36fb9cc5be5eee3a1ea43278ce426526403f9b7094d5f5f27b1f20736c83f5a27a04565d03abae9e8e5f6b8a2c3dd3e06734d8293e4967fa1f1ee3529969d6feccf7756ce2a67ae0fdbaab16f7354b57bc16351bb875dcdbe716789ceef99cb6068fc5ece3a1abc04e65165ac743f671dc6d475decfd747170f7b9e02756597c3629db7276fe236b19bc66e0ba268b7ddf1560499b7ce5a799aa2a2b91a9d8a185ebbea9ab4fa2768031675f47196dad07afa3acb1fa24bbacee936afbb7e943db11afb5dbd7df3d3d9b16b6b95b56fd6d8d3463abc9e336f4710fa33b3e9b561adb7a27ad2fc4f10ca5563e1edfa90db8afc8a6c555078faf6b9a515a5c75f88e4f8bf14daefd874b8b2b0e1e5fe798515a5c71f88e518b8dae6b0b2e2d2e3b787c9d6b446971d9e13b3e2d26b4bbae914d8b0f1d3cf15fd3c8ae05de13cb85f90a03e6522b1f8fef9af5ae7b772e2d3e70f0f8ba7717a5c5070edff1695135de75ceeed2e29283e7529eb5b8e4f01d9f161327b9aea9b8b4b8e8e0f1707d2dab16171dbe638c8b66bcbe964d8b0b0e9e0b79d6e282c3778cc787e3b35d33442dde77f0f8baf617a5c5fb0edf316ab14efb3edf012dce3b78cee7598bf30edff169b17e9cf6fd5e07b478cfc1f35e9eb578cfe13b3e2dd64dd4becf75408b730e9e7379d6e29cc3778ce750615c9ced8016671d3c67f3acc55987eff8b4d8101e6b9de98016671c3c67f2acc51987eff8b4a80cf7a9a73ba0c56907cfe93c6b71dae13bc6b808cf274f75408b530e9e5379d6e294c3778cfb91302e4e76408b930e9e9379d6e2a4c3777c5a6c0caf3f9de88016271c3c27f2acc50987ef18afb9847171bc035a1c77f01ccfb316c71dbee3d3a23adca71eeb8016c71c3cc7f2acc53187eff8b4680eef891ded8016471d3c47f3acc55187ef188f3bc3fee24807b438e2e03992672d8e387cc778dc195ebf38dc012d0e3b780ee7598bc30edf31f69de171e7a10e6871c8c17328cf5a1c72f88ef1b833d4e26007b438e8e03998672d0e3a7cc778dc19ee475a3aa0458b83a725cf5ab4387cc7181761df79a0035a1c70f01cc8b316071cbe63bcae15f69def76408b771d3cefe6598b771dbe633c1f09aff1bdd3012dde71f0bc93672dde71f88ef15e51780cfe7607b478dbc1f3769eb5781b7cfb1867825ad058ac5196162550e681c1995f1a8b15a523ad039fa1c5babc157b5d32e3cade8ca8cb5b50172ad317ea520af638993cd5358c19fa96028d4d6f75d495ca3c3cb8adeca3269f806d721bd635ccf17f9ab28d4122fd749df7c55fe73056e91b10b47df7397cef05d6987c57a16f1a9b4e7ec85e02f96707b795a572a407694decba8dd0373090dd5eee6d6bb92494d9efa87f3a88b7fefb2c9e7d1673f8dc03c419c5919fbe2bc3b43f42a351a01195c1317bad9e78ec3184c441fe7419dafebdad32b46c099419037d148e2ba57a2682bbc74deafabde1a97ee48bd64df3e42f09b61bc068d751c7c74330f693be0142df07d136fade077ebf6bbc65d3759de0a9aee48bd64df3138091be3f323eff8ca98e328eb31835cf240f9ae1375568cab6bf98043c133df078aa67b81faab5ea34c1aa5312cae0b38db51eea59047e69dd345f0bbe7d6c73d482f6c9c32d2d4aa0cc42ebf8314a475a878edff18ebaf8d2719cc533cee17bb2671d69ddd4274ece83ef3acb778de55bb76d8c313d656bdb75c05cef8159af774afceb0ddbf654b32e8a67f25303754a830671d5097d1759eb267b09e49b06dfcd407ad0be93d8753bc2d8895a6e92b55c12ca4c76d43f1d73fda7583cb88df5a48f1b5e84e34a0fed218c81c91607cdd780765322b49b0cda5119dcf75679d2aedee2a1f92ae0a1e3ab5ab0d1710a7ee392fe9fca03b7ddefd53ab8c986df3cac72308e8f9f313cceaab218697e3c3092ad1e78ea3c69666febe1963e784cd0db2a43cb964099fdb05f4e38ca86cf1d17b5d58bbea5f9498cf5d2ebede5412ffcce6700fa04968634114369d0f62dd038791e08dabef5b97bcfce5deb36352f6bcedcf624b4120b137f8b1cd528061be67b386c41d0fe93a62560a34f9af6045bb1250b7e4a95cad3a7137dc8857ad0ba4b2cce526089d3377e0e96a66ca1d31b787c84b20e1dfa24ac099dc65d5bf634637cf4b4383b133bfa7f3db2948b5a17c5418987ba2313ad9be6c99fd6873e8ffbfabaa66dd3766ddabba3f9b53dbb11d66e5c982fb244b07f5dcb60906063a2f5f4b4c4e913bf3835d8786dbe00fc05c012189ed2f879c240a56f0837addbbe7dc9def5dbb734cddefb5ad39e2d3b5f43457b5bca45a96d37793db9ba3a2c6b97efe5b0d9137eb1b937d8e88bcda56023ff7dc0461c0fc0ffec2de1a54d0c83f55318ebff95980af73215a210a4dd90ee4f749bd1af4dd5bb7ffd8968fd4968bdf9f4dbe2f4279ef5279df5279cf5279bf5279af52799f5db24f413defac8614890f984f29341e615b14383cc2790f5278f9f09da3e69aca7df055efd09637da8a13f51ac3f49fc7c90b954383ac8bc564dbfc6421fb2ea432b7d98a74f6bf421b83e2dd7875efa7281be74a40f63f421a23efcd1872cfa105c1f7a4f355a4f0b329f34d79f309f19643e51ae3f49ae3f413e37c87c627cbe4a0b82cca7b6170599cf07ebcf87ebcf76ebcf79ebcf7cebcfcfebcf82ebcf85ebcf88ebcfcceb4f0feb4fd0af0e329fda7e29c87cb6f89520f399e3b541e6b3c8eb83cc6794370499cf2eebcf31ebcf346f0e329f75d69f7bde16643e0fbd23c87c4e5a7f665a7f7e5a7f965a7fae5a7fc65a7fde5a5f72d7b71af425787d795b5f7ed5b740f4ad1f7d6958dfb2d4b770f52ded962033e4e150901912a38708e921537a08991e527722c80cb9d44350f5905c3d44590fd9d643d8f5907efd88837ee4433f02a31f09d28f48e947c6f42374fa3148fd58a17e4c563f36ac1fa3d6977df523e8fa56a0bedcdb1a642e09df09329f5ffe9c4a9f57e9fb54fa824adfafd20fa8f4832afd904a3facd21755fa11957e54a51f53e9c755fa09957e52a59f52e9a755fa19957e56a59f53e9e755fa0595bea4d22faaf44b2afdb24abfa2d2afaaf46b2afdba4abfa1d26faaf45b2afdb64abf1364e2f1f754fa7d95fe40a53f54e98f54fa6395fe44a53f55e9cf54fa7395fe42a5bf54e9af54fa6b95fe46a5bf55e9ef54fab24a5f51e9ef55fa0795fe51a57f52e9ab2afdb34a5f53e9eb2afd8b4adf50e99b2afdab4affa6d2bfabf42d95fe43a56fabf49da0ed33e5d8790c363dce5033bf6ecf9ee61dafefa9d8b3b362c7deed7bb6bcbefd8d8a7d5bf66caed8f9d9e65d1bb7efdc870b7fd92cfcb8999fb66bd7ba372ab6bcb6a1797fc5cebd7b2a766eac58bf73ef6b1bdaed2cffb75968f0dd1ed76dd810edacb4c7a7202debd139a783cc72f4a5fa79d9ebf6448f4e08f24c67169adbc90acd357b203a0d5b9e39e6abd8bd7de79e8aca8ad7d45fb573ddb9af79c3980afcdf6e25f2ee3d15bbf7acdbb5a762e3ae9d3b2aaac6e07a17f6e94425bed8c70f4c6ff35ea24e85ca6f0eec444dbe36b0739be33f3f0de9ffeca4d3b2419da861ffce2c347e50e708d3832265d9bd77fd9e5deb9af6442f3cebd32cbca033d55cddc96af619dc0967e59d5968f4e0ce112ee88cb37d39380bfe3f2f1967aadc5505009b2d6c6f00000027461f8b08000000000000ffed9d777c1dc5b5c7f74ab25cae2eb66cb937d1dd645d5d755b3632ee0d4cc780c14532186ccbd8a277d2480809e9850478a92421bdf79e90de0b4948200909297fbc7cde7b9ff7f9bc3ff8bc99d59ce87787d945f7b2479ed53dfbf91cdfd9a3b97bbee7ec99d9bd33b3eb4c30b4fd5349c694ab959c143c77a3bff79acffc0bdb5a123c569e93339312ceaa947056a784b326259ce352c2599b12cef129e19c9012ce8909726ab6aaa0784b9a7712435c9366cca62ca6752988692e65313d2105319d1ca4a38f9a9212cefa94704e4d09e7b4947036a484737a4a3867a48473664a3867a58473764a38e7a484736e4a38e7a584737e4a3817a48473614a381b53c279624a384f4a09e7c929e13c2541cec5c079aaf93ccd7c9e6e3e17994faabbc47c2e359fcb8c8f3566bf49c97225cd9acffa9b9e6828286955d266fdad5d4987924e255de66f8de66fdd4a562859a9a447c92a25ab959c6162b146c9994ad62a59a764bd920d4a362ad9a464b3922d4ab62ad9a664bb92b3949cad64879273949cabe43c25e72bb940c9854a2e5272b1c5b253c9254a2e557299925d4a2e57728592dd4af628d9ab649f923e25fd4af62bb952c9554a0e28b95ac9354a0e2a39a4e4b092012547945cabe4a892634a06955ca7e47a253728b9d18ad94d4a6e56728b925b2dcedb94dcaee40e25772ab94bc9dd4a5ea4e4c54a5ea2e4a54a5ea6e41e252f57f20a25f72a79a592fb94bc4ac9ab95dcafe4354a5eabe4754a5eafe40d4adea8e44d4adeace42d4adeaae401256f332cd410deaee441250f297958c97f28798792772a799792772b798f92f72a7944c9fb94bc5fc907943caae4834a3ea4e4c34a3ea2e4a34a3ea6e4e34a3ea1e4934a3ea5e4d34a3ea3e4b34a3ea7e4f34abea0e48b4abea4e4cb4abea2e4ab4abea6e4eb4abea1e49b4abea5e4db4a1e53f21d25df55f23d25dfb762fe03253f54f223253f367fa3f1a59f28f9a929ffcc7cfedc7cfec27cfed2faceaf94fcdad23daee43796eeb74a7e67ca4f98cfdf9bcf3f98cf27cde753e6f38fe6f34fe6f3cfe6f369f3f917f3f957f3f98cf9fc9bf9fcbbf9fc87f9d47393fd0d43e509c1f0d61b24d427b5f5f7e9b9090af6a941f1a663516dfe469f8d465f63f6e9936237ceec8fb3f4b566bfd63ace04b33fc1d2d79bfd7a4b3fcdec4fb3f4d3cdfe744b3fd3eccf047d3680314aa3d7ba6aa3ca808ef2b00a74e382e298685d2d1d0e74e383e258681d9dc75ad04d34baf1a09b647413409735ba891433257546d71b249513f93dfab8b9a48f6be66d4e489e779f3eee6426de29c9f3f6ebe3d633f0eafc986a8e3505f2669ad1d583ce742bc154d04d37ba69a09b61740da09b6974d34137cbe866806eb6d1cd04dd1ca39b05bab946371b74f38c6e0ee8e61bdd5cd02d30ba79a05b6874f341d768740b4077a2d12d04dd4946d708ba938dee44d09d627427818efacf934147f777a7189dee136a32f01da3a7fe28fc0ef5b9a03b9dfa5bd02da2be16748ba99f05dd12b04dbaa5d087906e99d1517fa4ffd665cabd4152f95fe8d3c7ed4efab8eac8fab82b933f6e38a7d5130cc7b517ec7443ac56997282eb665ad076c608d9217d0d9437425daa47f1a06b0ab1eb6bc70a535e15f3bd2eeb7b39a8b3c2e17f6f90acff2b2d9e9516f338f09f27675b5b246747bc959cb317405d3bf7e8fe662ce6ec16e060c8d976c9d9116f25e7ec3ea86be71edde38ec59cbd18381872b69b27670b79c9d9a1b1ae2070e71efdce198b39bb1f3892cfd976c9d9916f25e7ec1d50d7ce3dfaad3b167376103892cfd9ce6eb93718f15672cede0775eddca37197b198b377030743cef6493f3be2ade49c7d00eadab9476380633167ef078ee473b69b29675b256783a179cb2070e71e8d478fc59c7d103892cfd97d323e3bf2ade49cfd34d4b5738fe646c662ce3e0a1cc9e76c1fd7f86c41727668bd4610b8738fe6e9c662ce7ece94f5dcd8cfccdcd802d0fddce81682ee17b0ce8074bf34ba13c12f8636d0296d60c45bc96de05750d7cee5934c792cb681ef030743ce764bce8e782b39679f86ba76eed1fa85b198b3bf010e869cdd2b393be2ade49cfd2fa86be71eada5198b39fb8c29ebfb8527ccfdc222d0fddee81683ee0f46b704744f1add52d03d6574cb40f747a36b02dd9f8c6e39e8fe6c74cda07bdae8f2a0fb8bd1b580eeaf465700dd3346d70ababf195d1be8fe6e74eda0fb87d17580ee9f46d769747a1e8bd6543d667413c0f7de20b9731baea30a8ab78cb5df0be565bc3cf95c50fc9c00d95a9ebcad56ed7b533072df97034f3383ef59b031129e66e0c927cf13fe1e6d49feb8e1396eb2629a055b4de05781c1af0cd8a263d33ed9cb810efb8d8283b13579c642066cd1b169bf15184987fd183d8743ed47f7cdf332c3bc0c6d29bc3ea3bd5ee0207b355027d3305cb7d1b0d5c1dfa90fa88332f6f3794bc794ab61aee0c359bdb0df028ce4637ef4190b23656cb618b9fa8d0cd8a263dbb6eb1cf1d1316b75c4ac8d89b1d562a4fd3660a4f8b58e3e6361a48c76bfc0d427b58cb44fa2b8e4473f66233aaf39d0e1bd5e9b83b13d79c6f0bcb6598cb4df0e8ca42b000fd7f530aabdfa629be33e04f399ae5974fd217b3550a7b57ab8ee26b89e32f4a18552ef4db14f4ffe3c15f2783d1b090ff3b96b61cac73cf69dcf06c9e69adde6f356acb0cd635fced54f46f5e5644f98855998855998855998855998855998855998855998855998855998855998fd678e9a9773ad67389e8ca46b011e8e71fef0dd53e6583807f438cceb243f6f51c8e35c3dad635c64f95c0375fe3733ccf684639d04ce9d2fb7744ceb94c27389eb947a619fece1ba0d5c37c5b0f624e4596af1d8b6eb1cf1f1711d894f6b34a2d669f914b31ce8703d5c13134f549e35396c372666bbb08fa7ed14f2fa3d3ffa5d79d49fd86d04d7be2db174ba4feaa81ef69b23074a9d77c6eb0695939cc7c57c435bc9afb72914ad4fa80a8aaf15784fc1b046a568be9ad646b45bb66bb04e55f0ef73d3017fef0d9ebb4608ebd0b1697f117cb7c33af6643e7f63fbc376e0a672ade5db32e0a63a93aa867dfcac2933ddcf1470fd6c00bc81e5136db83e23f9fbbda1f522851278da808763ed1ad37d6d1ef331e9f5221d56ac5cf7cb54a71de2d7c110bfb8356b644f98855998855998855998855998855998855998855998855998855998855998fd67c6f75f102b3e23dde209e328adb109e733e8bd45382ff640d5b05dee39409a735a6cf98ccf283f5335ccf69029e33b025ccfbbe3b9e49a5b8b3a9764af2e78ee73fa4ce772c4ef7e6873c4acc311b34e2646bbcfa0fd4e60a4f875000f577b6cb7786cdbd867b4791ab3a87e966bfd4a549eb9d6293426667b68bd08c7bc2ead17b1af5f2d564c719d04e9701e1cdfad82ebb17c7bff8bbd7601fb295ca3957cbf59289a03b6d70a923d5c27f175135b5a27917c3f50c8735e23a88dd29a9082c357aaf3185ce7be6bcab856a8058ef5b8e3efb4c5ad49c03e95e15d99e1f9a57737d2f9ed76d85e09ac09d96e41db19236487f43550fe75d5705dfb5d90146b62d76dc47e5fa5eb7b79eb7b39a8d3e5f0bf3748d6ff6e8ba7db62d6b9f303c8b3c7e15e8fab4fea0adc315a0431a23a78cfcbb0a6c8d947da6ba6751d3affe3ad3a787f4a759e823e2a6a4dbaeb3d805cf70b51ef01c4fb05d73d8deda3bd76bcd2d703fe0bfa8b0ef87b6ff0c2d703fe0b72c8755f4ac75f0cc727aef141f4b585eafc8f751de56a5bcff7de2bd76f3fe2c5f58654e7ffa0af5a66d6e546fd8e713d67c1f5bb21eab90fb287f754a5f88efd42d2d746cc4764217b988f3526d6948f1d11dccb1ddf1d1ff15d8a15ad2fc7dfc976fc741c127f47b8e96fba2d5fa84d75812fffbe7e832f3cf74c43f79fc9fb5a7c3f447d50abc357aa3315de05d760ca59384fd8579eecf83b6d71f79ff85ef39ee47d0ecf2fbdbf9bce6f8fc3f66a604dc8760bdaa6fb4fb243fa1a289f543d5c97ea513c28d6c4aedb08ddc321bbfdbd76eb7b39a8b3d2e17f6f90acff3d164f8fc5ac736726e4d9c9f0ac05575fbd3222468b214654079f75b47fffe36f79bcc61cafdff2f8ce4fecdb97414c47eb9da9f6f8adebfe64b11563bc3f69817e36eba86b8f4bd33524c9f5e9f83cd052b08bcf032d658a672e288e67cee2e0b43dd9b23d79146dd75bb6eb47d1b6c45c62ee53cc7dfabf30f0ffaca84a0163750a186b52c0382e058cb529601c9f02c60929609c9802c6492960cc02e3f1bcb633c4a7e0d9fff7147baf81b619dee710c6625930f25834f1f2c4defba06d8677a894fcff0d30ff5f582de5fe5f5839f8ded414304e4b0163430a18a7a78071460a1867a68071560a1867a780714e0a18e7a680715e0a18e7a78071410a1817a680b131058c27a680f1a414309e9c02c65352c0786a0a1827a48071092f63a15c46cdc3f11ecd6c50bc8eebf97898dfeb19be9fd0f50e518eff77b654df99dfe9db52ee3bf070fd02efffa3f8c2ded3c7b13ea1d4f7f4c5fddfd34c8c857219b9d69be0da9691f0b8d6a0e479190be532723ddf81cf1b8e84c7f5ffe0f23e6f3314b37218b9d66395ba5e109fc36b77c48c81b1502e23d79a7e7cde70243caee702f3bc8c857219b9d6be66c1c64878ba20669d8e98313016ca65647a762b8c5957093cf88c539723660c8c85721935cf0aa6987597c0b30262d6ed88994f8cc893f4fbc6bb1db6389e892bd5776240c68929609c9402465c83c0d17fc5ad41e8e68d4fa1dcf8709dafb83508689be1198c3016b8e6fef962d1c3cb13bb06016daf628a053e13f17cb158053c1ccf6864c1c64878882107df9b9a02c66929606c4801e3f41430ce4801e3cc1430ce4a01e3ec1430ce4901e3dc1430ce4b01e3fc14302e4801e3c21430e26f55867bc5d8df2fabc6b8eda8df2a63dd76d4ef92b16e5bf25cf2bc126c4b9e4b9e57826dc973c9f34ab02d792e795e09b625cf25cf2bc1b6e4b9e47925d8963c973cf7c9761ac6f88571ec31224f63723c79f41d6d9de181ef673878324cbea3ad5e0f7ca772da1857a78071450a18258e436b10cb61d43c6b98787a4be059033c6732f1ac2981e74ce0599b3c4f98536796c0430c39f8de8a1430ae4e01a3c451e2e813a3c4b172e2288cc2288cc2783c18d3d087cb7566e8b74b398c9a675df23c61ccd696c0b30e6246dfcbf33216ca65d43ceb93e70963b6ae049ef510b3758e98313016ca65d43c1b92e70963b6be049e0d10b3f58e98313016ca65d43c1b93e70963b6a1049e8d10b30d8e98313016ca65d43c9b92e70963b6b1049e4d10b38d8e98313016ca65d43c9b93e70963b6a9049ecd10b34d8e98313016ca65d43c5b92e70963b6b9049e2d10b3cd8e98313016ca65d43c5b93e70963b6a5049ead10b32d8e98313016ca65d43cdb92e70963b6b5049e6d10b3ad8e98f9cab822058cab53c0c81cc742b98c9a673b13cfb61278b603cf594c3cdb4be0390b78ce4e9e27cca9b34ae021861c7c6f450a1857a78051e22871f48951e258397114466114c6d218cf4801a39c6b61f49591e1f755ecf329678d71db51cfa78c75db51cfa78c75db92e792e795605bf25cf2bc126c4b9e4b9e57826dc973c9f34ab02d792e795e09b625cf25cf2bc1b6e4b9e47925d8963c973caf04db92e792e795605bf25cf2bc126c4b9e4b9e57826dc973c9f34ab02d792e795e09b625cf25cf2bc1b6e4b9e47925d8963c973caf04db92e792e795605bf25cf2bc126c4b9e4b9efb647b47f2b60ba53ec3ba0378ce668805939f797ddc73ccb19e4d307e3a56e75ab13acb8a550eea9c03f13b97217e19b04bc7a67db2572af3691e3033d92e9ca08e3111fc271babad7868fbe731f91ed5d79f37c66d47f5f563dd76545f3fd66d4b9e4b9e57826dc973c9f34ab02d792e79ee8b6d2cd704c3f7edf47e257d8cf34d799cd9a7fa67c0f7a84ecbf8a1cfc981b4210edbd286e45a5109b625cf25cf2bc1b6e4b9e47925d8963cf733cf2f48de76383786bf2ff41637377601f09ccf100b263ff3daa70b2d9fceb37cca411d7c67ed850c7e66c02e1d9bf62f84f3903666cdb3ca9489350bf55679c248baf37979c2f6b52a28dee2dad785c0c3d00e5a98fc0cdbd745964fab1c71a73a98ab1731f8e96a3bb47f119c87b431e7c01eb16683e273ea0323e92ee0e509db576f50bcc5b5af8b8087a3ff61f2336c5f175b3ef53ae24e7530572f66f0d3d57668ff62380f6963d63c6be0ef7acb42bd359e3092ee425e9eb62cf84c5b5cfbba187838fa1f263fc3f6b5d3f2698d23ee5407737527839faeb643fb3be13c08b330bb9835cf99a64cac59a877a6278ca4bb8895a72d9f059f698bebc776020f473fcf14f7b01fbbc4f2e94c47dca90ee6ea250c7ebada0eed5f02e7a114e6d5296496384b9ca39825ce12e7286689b3c4398a59e22c718e6296384b9ca39825ce12e7286689b3c4398a59e22c718e6296384b9ca39825ce12e7286689b3c4398a59e22c718e6296384b9ca39825ce12e7286689b3c4398a59e22c718e6296384b9ca39825ce12e7286689b3c4398a59e22c718e62963897c7ac79d69a32b166a1de5a4f184977312f4ff8fccedaa078cb58fbbd50be04787632c487c9cf70ddfba5964f6b1d71a73ad8be2e65f0d3d57668ff52380fa530af4e21b3c4b93c66cdb3ce9489350bf5d679c248ba9dbc3c613fb62e28dee2fab14b8187a39f67f233ecc72eb37c5ae7883bd5c1f67519839faeb643fb97c17910666176316b9ef5a64cac59a8b7de1346d25dc2ca53089f435c1f146f71fdd865c0c3d1cf33c53decc776593ead77c49dea60aeee62f0d3d576687f179c87529857a79059e22c718e6296384b9ca39825ce12e7286689b3c4398a59e22c718e6296384b9ca39825ce12e7286689b3c4398a59e22c718e629638574e9c35cf065326d62cd4dbe00923e92e65e5690de71d3604c55bdcbcc32ee0e19897618a7b38ef70b9e5d30647dca90eb6afcb19fc74b51ddabf1ccec358675e9d4266c98dd16196dc10e62866c90d618e6296dc10e62866c90d618e6296dc10e62866c90d618e6296dc10e62866c90d618e6296dc10e62866c90d618e6296dc10e62866c90d618e6296dc10e62866c90d618e62f6213734cf465326d62cd4dbe80923e92ee3e509df7bb03128dee2d6ed5c0e3cbb18e2c3e467b86ee70acba78d8eb8531d6c5f5730f8e96a3bb47f059c0761166617b3e6d964cac49a857a9b3c6124dd2e5e9eb01fdb14146f71fdd815c0c3d1cf33f919f663bb2d9f3639e24e7530577733f8e96a3bb4bf1bcec36e61166607b3e6d96ccac49a857a9b3d6124dde5bc3c613fb63928dee2fab1ddc0c3d1cf33f919f6637b2c9f363be24e753057f730f8e96a3bb44ff6845998a39835cf165326d62cd4dbe20923e9aee0e52964c167dae2fab13dc0b39b213e4c7e86fdd85ecba72d8eb8531dccd5bd0c7ebada0eedef85f3903666cdb3d59489350bf5b67ac248baddbc3c61fbda1a146f71ed6b2ff070f43f4c7e86ed6b9fe5d35647dca90ee6ea3e063f5d6d87f6f7c179481bb3e6d966cac49a857adb3c6124dd1e5e9eb07d6d0b8ab7b8f6b50f7838fa1f263fc3f6d567f9b4cd1177aa83b9dac7e0a7abedd07e1f9c87b4316b9eeda64cac59a8b7dd1346d2613f455b15306e67620c2cc6c08a0ff22cf08c6796673c533de399e8194fb5673c4b3de3e9f68ca7cb339e859ef12cf68c67b6673c05cf78a679c6b3dc339e499ef1b47bc653e319cf32cf784ef78c67a5673c733ce369f08c6789673c59cf78c679c6d3e4194f8f673c1d9ef1ccf58ca7d5339ee99ef1347bc653e7194fce339e5acf787678c633cf339e199ef19ce019cf64cf78c67bc6d3e919cf7ccf78da3ce399e9194f8b673c533ce3a9f78c6782673c8b3ce3c978c0930d9ebb6e200b7fdf01ba2aebbbfafab2a161f8ef344f5b05dfe937e56ac7b1fb4047f3bafd8eef629cb8e69ed1562fec93bd3ae0e8f7846791673c133ce3a9f78c678a673c2d9ef1ccf48ca7cd339ef99ef1747ac633de339ec99ef19ce019cf0ccf78e679c6b3c3339e5acf78729ef1d479c6d3ec19cf74cf785a3de399eb194f87673c3d9ef13479c633ce339eac673c4b3ce369f08c678e673c2b3de339dd339e659ef1d478c6d3ee19cf24cf78967bc633cd339e82673cb33de359ec19cf42cf78ba3ce3e9f68c67a9673cd59ef14cf48c67aa673cb33ce359e0194f95836707134fd4b3bb3b3cb1cd701ef2fab8fb997cbad21cabd61c97f8c95e0dd4a937038f7abe01bf4b5cf67c3b8e2d5f0931e27a6f42cee2a1fd7d63dcf664cbf6e40ab15d6fd9aeaf10db92e792e795605bf25cf2bc126c4b9e4b9efb68fbd9e46cb7639e55812d1fd647cbfb93e279e4fd49f13cd59ef1c8fb93e279e4fd49f13cf2fea4781e797f523c8fbc3f299e47de9f14cfe3dbf3f1f23ea7781e799f533c8fbccf299e47dee714cfd3e4198fbccf299e47dee714cf23ef738ae7a9f38c27e7198f6fef7392f727c5f3c8fb93e279e4fd49f13cf2fea4781e797f523c8fbc3f299e6782673c8b3ce3c978c0f37cef4fc2f71ed15acb7da0a3f59c71ef59cac271ae041d8d0fd231f4f5ea9c86e73254c177ae7270ed77d8233b5739be3b1a71475bbdb04ff6f07d4c5779c2b3c8339e099ef1d47bc633c5339e16cf78667ac6d3e619cf7ccf783a3de319ef19cf64cf784ef08c6786673cf33ce3a9f58c27e7194f9d673ccd9ef14cf78ca7d5339eb99ef17478c6d3e3194f93673ce33ce3c97ac6b3c4339e06cf78e678c6b3d2339ed33de359e619cf0ecf786a3ce369f78c6792673ccb3de399e6194fc1339ed99ef12cf68c67a1673c5d9ef1747bc6b3d4339e6acf78267ac633d5339e599ef12cf08ca7cac1c3f54ea45c30bcf5c2fe68bc8fe9f96cebfda51017bd65e1efa3f19ce40e8b91f6719d01f212cf52269ea8e7de977a605bfb4fbfb568ce220b7fc7e770b8726aa9c548fbae9cc27584cb9878a29ed75fe6816d1d8b2653a639ee2cfcbd0918b9726a99c548fbae9caae7e569cb82cfb4c5adedc136c7710e99fccc63fb4bf01d11791dabed56ac9aac58e5a0ce683c2718d51f903d6116e62866cd43632dc48ad7b3d1784e7a248caeeb2b034fd83f2e0f8ab7b8fe713bf0705c3f98fc0cfbb103964fcb1d71a73a98ab0718fc74b51dda3fe0b0dd18241b8bab47108bab1d3c578f722cc85ea9cc3b52c8ec439c350fad9d20565c4fdcec0923e996f2f284fd637350bcc5f58f57030fc7f583c9cfb04fb8c6f2a9d91177aa83edeb1a063f5d6d87f6af81f3500af38114324b9ccb63d63cb4a69a58b350afc51346d26d67e529e4b3e0336d71fdd835c0c3d1cf33c53decc70e5a3eb538e24e75b07d1d64f0d3d57668ff209c0761166661166661166661166661166661166661166661166661166661166661f69b59f3d0b32ac49a857a054f184977352bcfd0bc432128dee2e61d0e020fc7bc0c53dcc3798743964f0547dca90ee6ea21063f5d6d87f60fc1791066611666611666611666611666611666611666611666611666611666611666bf99350fbdd39558b350afd51346d25dc3cb133eb7d51a146f71f30e878087635e86c9cf70dee1b0e553ab23ee540773f530839faeb643fb87e13c08b330bb98350ffd5f0fc49a857a6d9e3092ee202bcfd0fc695b50bcc5f563878187a39f678a7bd88f0d583eb539e24e7530570718fc74b51dda1f80f3500af38114324b9c25ce51cc1267897314b3c459e21cc52c71963847314b9c25ce51cc1267897314b3c459e21cc52c71963847314b9c25ce51cc12e7ca89b3e6a1ffa38a58b350afdd1346d21d62e5690de71dda83e22d6ede61007838e66598e21ece3b1cb17c6a77c49dea60fb3ac2e0a7abedd0fe11380f639df9400a992537468759724398a398253784398a59724398a398253784398a59724398a398253784398a59724398a398253784398a59724398a398253784398a59724398a398253784398a59724398a398253784398ad987dcd03c1da64cac59a8d7e10923e90ef3f284ef3de8088ab7b8753b47806780213e4c7e86eb76aeb57cea70c49dea60fbba96c14f57dba1fd6be13c08b330bb98354fa729136b16ea757ac248ba015e9e42167ca62dae1fbb167838fa79263fc37eeca8e553a723ee540773f528839faeb643fb47e13ca48d59f3749932b166a15e97278ca4c3eb7217134fcee2c9396271bc6cebfd6e53ae339f59f87b373072f5875d1623ed638e232ff17433f14cb678263b6271bc6c6bff579af209e6330b7f5f098c5c39d56d31d2be2ba72603cf4a269e7a8ba7de118be3655bc7a2c794a798cf2cfcbd0718b9726aa5c548fbae9caa079e1e269ea83ea967146c47b5afd1b01d952ba3615b621e1d738676178e0ff404c55bdc7d355e5b38fa2a263ff3aeeb778fe5135ebff11ef5785d9f845998a39899ee73dbb2966d8a4f60f1d0762d732c46f37776b7e5531a7e67c7311f4821b3c4b93c666dfb58f2b6dbb2966d8a4f60f1d0768c39164c7e86fdc160e08e31d9cb411dccd341063f3360978e4dfb83701e4a613e904266897379ccdaf67589db1e7aff30daa6f804160f6dd731c782c7cfa1fee0fac01d63b297833a98a7d733f89901bb746cdabf1ece83300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb330fbcdac6ddf90b8eda1f17bb44df1092c1eda6e608e058f9f43e3f73706ee1893bd1cd4c1737e23839f19b04bc7a6fd1be13c08b3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3dfccdaf64dc9db0e9fc741db149fc0e2a1ed26e65830f9198edfdf1cb8634cf6725007cff9cd0c7e66c02e1d9bf66f86f320ccc2ec62d6b66f49dcf6d07c1edaa6f804160f6db730c782c7cfa1fee0d6c01d63b297833a78ce6f65f0330376e9d8b47f2b9c8752980fa49059e22c718e6296384b9ca39825ce12e7286689b3c4398a59e22c718e6296384b9ca39825ce12e7286689b3c4398a59e22c718e629638574e9cb5eddb12b7dd1a8edfa36d8a4f60f1d0761b732c78fc1c1abfbf3d70c798ece5a00ee6e9ed0c7e66c02e1d9bf66f87f330d6990fa4905972637498253784398a59724398a398253784398a59724398a398253784398a59724398a398253784398a59724398a398253784398a59724398a398253784398a59724398a398253784398a59724398a3987dc80d6dfb8ee46d87cfb3a36d8a4f60f1d07607732c98fc0cd7bfdc19b8634cf6725007f3f44e063f3360978e4dfb77c279b8539885d9c1ac6ddf95bced42d6b24df1092c1edaee628e05939f617f7077e08e31d9cb411d3ce77733f89901bb746cdabf1bce43da98f1fc6592b31daedb241b55e653eb5e64cad5a07bb129d780ee25a63c0e742f35e55ad0bdcc94c783ee1ef08d742f37e525a07b8529f780ee5e535e09ba579a7237e8ee33e52ed0bdca94af05ddab4df928e8ee37e563a07b8d290f82eeb5a67c1de85e67cad783eef5a67c03e8de60ca3782ee8da67c13e8de64ca3783eecda67c0be8de62cab782eeada67c1be81e30e5db41f73653be03746f37e53b41f7a029ef00dd43a63c11740f9bf224d0fd0794e9f31da65c07ba779a720e74ef32e51340f76e539e0cbaf798f214d0bdd794eb41f788294f05ddfb4c791ae8de6fca0da0fb80294f07dda3a63c03741f34e599a0fb9029cf02dd874d7936e83e62ca7340f751539e0bba8f99f23cd07ddc94e783ee13a6bc00749f34e585a0fb9429e3f9fdb429df053aea2fee061df5172f021df5172f061df5172f011df5172f051df5172f031df517f7808ef2eee5a0a3bc7b05e828efee051de5dd2b414779771fe828ef5e053acabb57838ef2ee7ed051debd06749477af051de5ddeb404779f77ad051debd017494776f041de5dd9b404779f766d051debd057494776f051de5dd03a0a3bc7b1be828efde0e3acabb07414779f710e81a4df961d09d68cad87f9c64caef00ddc9a6fc4ed09d62caef02dda9a6fc6ed09d66caef01dde9a6fc5ed02d32e54740b7d894df073aba86bd1f744b4df903a05b66ca8f82aec9943f08bae5a6fc21d0359bf287419737e58f80aec5943f0aba82297f0c74ada6fc71d0b599f22740d76eca9f045d87297f0a749da64cfd876ea7babd91cf148f3af0afc9c14dba09c0dd1b247b0f46b6e8d8b45f00468a77cbe8331646ca98b718354f1b43cc3087688bfb8dd3063cad0c3c4c7e86bf71da2d9f0a964f39a8731af8d9cee06706ecd2b169bf1d6c739c738c45ad39eee9562c6aa0ce2c73f1d2d7c9b838d23174feb6387ce18a63dee2c93b6c7731c7918e4d7d62d728d8eeb06c375bb6b1dfa72dae6d7700732703b33e6e77f2c70ddbf60a732cca67b2d30c3ead841824e513dace18213ba4af817273c3705daa47f1a06b27b1eb7644e712d9edefb559dfcb419d2e87ffbd41b2fe775b3cdd16b3fe9d704ac33007437b0873a0cbe2a0fd66885d7744ecba20765407afbd79a6d8755a3cb49f071ebabf6a071ddda7103fdecf358d02b7ddefb53bb849d7018c79076373f28c85b8eb42333092ae13783a9862669febd3adf8e03dc178ab0e7db706eaac83eb72d65157b7bb799961bfe877fdb341b27d7a2d43bc70cc2180f804560c69238609c1f0b844923c9382e1718763830347f75cd97f6eff9ebe0ca0d55898f89971b851053a2c573b7441503cbc82c3b734bc82c3b7555658705887eaeb9f71da2d1ac2e83f7460f082c3fd87f71dbde9c8607fdfb6812b917a9c458fa4511e2029ea689b100c0f04f506c94edcd45ab6e29267027c8e4f9ea785c9cff0a237d1f2a9d6f2290775c6c1df2632f89901bb746cda9fe8b09d604714c662d2086231c9c1336994638183e9a4c3964a7fc789962acb176cd1e8939de7893a44064f85e3670c9cfe9b6eece38c33e383e1934dbda7bea3d527418fc2eaab961e65d5a3aaba0bd2a3a6fa82a64745f528a81ef5d4a39c7a54538f62ea514b3d4aa94725f528a41e756c0c864615f528a21e353c05b81e0356fd6b5e5f1df5a89f1ee5d3a37afaae4aff5ad37722face5bdf15e8bb017dd7a77fd1ead10d7da5d57731fa0aadafaafa2e51df1deabb797d77ab67b3562959ade40c13eb354ace54b256c93a25eb956c50b251c926259b956c51b255c93625db959ca5e4ec6068b4fe1c25e72a394fc9f94a2e5072a1928b945cac64a7924b945caae43225bb945caee40a25bb95ec51b257c93e257d4afa95ec5772a592ab82a1153c572bb946c9412587941c5632a0e4483034a3a667d0f48c999e21d333627a064ccf78e9192e3da3a567b0f48c959ea1d233527a064acf38dd190ccd2ee8d9043d7ba0670bf4ec809e0dd0a3fff70443a3fb7a34ffde6068b45e8fceebd1783dfaae47dbf5e8ba1e4dd7a3e77ab45c8f8eebd1703dfaad47bbf5e8b61ecdd6a3d77ab45a8f4eebd1683dfafc703034baac4793f5e8b11e2dd6a3c37a34588ffe3e120c8deeead15c3d7aab476bf5e8ac1e8dd5a3af7ab4558faeead1543d7aaa474bf5e8a81e0dd5a39f9f51f259259f53f279255f50f245255f52f265255f51f255255f53f27525df50f24d25df52f2ed602827bfa3e4bb4abea7e4fb4a7ea0e4874a7ea4e4c74a7ea2e4a74a7ea6e4e74a7ea1e4974a7ea5e4d74a1e57f21b25bf55f23b254f28f9bd923f287952c9534afea8e44f4afeace469257f51f25725cf28f99b92bf2bf987927f06c3b324d871d498de8646ecf70c0ef61f3a32d83838d078e8ba8383078e1cbca9f186038357350e5cdf7f74ffc1811bf0cb5f335fa6e98835478feeb9a9f1c0e1befe1b1b07ae1b6c1cd8dfb877e0bac37dc7f04b4f9a2fcd7baec53d7d7dd1c6fef38590fe779946ab4d3f48133d9be37dabad2e232075e57c295f5d9e437973a5a1d9f9f386ee701b8f1d1c186ccc371e56ffee39a8bed3dfb7bc11ff764c05f9d860e3b1c13d47071bf71f1d38d4d8b21c8f3ba5ae0c27663694f1a5b50d23f73cf87fdf1008bb09d50300", "privateFunctions": [ { "selector": { @@ -44,8 +44,8 @@ exports[`ContractClass creates a contract class from a contract compilation arti "isInternal": false } ], - "id": "0x0f83595b23cd7c0bb0bfd8793e8d3cef253ed9b79f65eeb030776de21b1504db", + "id": "0x2f5f44c6b443a090e8af4218fbedde76fe59ec3bc04dba0d05617502a0bb04f1", "privateFunctionsRoot": "0x05fa82a96814b6294d557d507151f7ccc12f70522ec4d9d0395a90e87e8087c6", - "publicBytecodeCommitment": "0x0f25b9a08d5ebc9aed312ec2d49bb8d1aaf25fe68cddd97944254875f091191a" + "publicBytecodeCommitment": "0x1dd7a3dc536534a16ec304af13c1cc24bdccb86dd476cb26456c139bfdfa2f29" }" `; diff --git a/yarn-project/protocol-contracts/src/gas-token/__snapshots__/index.test.ts.snap b/yarn-project/protocol-contracts/src/gas-token/__snapshots__/index.test.ts.snap index 7ec7bd797dfa..75502444a15a 100644 --- a/yarn-project/protocol-contracts/src/gas-token/__snapshots__/index.test.ts.snap +++ b/yarn-project/protocol-contracts/src/gas-token/__snapshots__/index.test.ts.snap @@ -2,10 +2,10 @@ exports[`GasToken returns canonical protocol contract 1`] = ` { - "address": AztecAddress<0x297f147bc0e40c476be08162f5a97ea890e8d6396b8fbaf8f71fd95751926b5b>, + "address": AztecAddress<0x1db73bf9f9d1d49b40d40fc5b81a9d917ef267b9860b8601ba5eb9d9594bfd33>, "instance": { - "address": AztecAddress<0x297f147bc0e40c476be08162f5a97ea890e8d6396b8fbaf8f71fd95751926b5b>, - "contractClassId": Fr<0x233c031c6466ffbaffe911450b38aac76414bca3bd9cd6685afecf406038ac63>, + "address": AztecAddress<0x1db73bf9f9d1d49b40d40fc5b81a9d917ef267b9860b8601ba5eb9d9594bfd33>, + "contractClassId": Fr<0x232bbde5f406677a8d090400dd2265fd12d3f40fd1b2de47f0331b2f975ea0f4>, "initializationHash": Fr<0x0bf6e812f14bb029f7cb9c8da8367dd97c068e788d4f21007fd97014eba8cf9f>, "portalContractAddress": EthAddress<0x0000000000000000000000000000000000000000>, "publicKeysHash": Fr<0x27b1d0839a5b23baf12a8d195b18ac288fcf401afb2f70b8a4b529ede5fa9fed>, @@ -18,7 +18,7 @@ exports[`GasToken returns canonical protocol contract 1`] = ` exports[`GasToken returns canonical protocol contract 2`] = ` { "artifactHash": Fr<0x076fb6d7493b075a880eeed90fec7c4c01e0a24d442522449e4d56c26357205f>, - "id": Fr<0x233c031c6466ffbaffe911450b38aac76414bca3bd9cd6685afecf406038ac63>, + "id": Fr<0x232bbde5f406677a8d090400dd2265fd12d3f40fd1b2de47f0331b2f975ea0f4>, "privateFunctions": [ { "isInternal": false, @@ -27,7 +27,7 @@ exports[`GasToken returns canonical protocol contract 2`] = ` }, ], "privateFunctionsRoot": Fr<0x13b29c3f4a96eb14d5d3539a6308ff9736ad5d67e3f61ffbb7da908e14980828>, - "publicBytecodeCommitment": Fr<0x2fa5bdfc9fcec2dbd358a80c1db5084a5c599f4637b5fe71a506d4cb957663a6>, + "publicBytecodeCommitment": Fr<0x0d917c13945d9fc55c69a2d78ddcb38aac8b9f88089f3240fdeb1d90d1accb91>, "version": 1, } `; From 12005970fe082f85b82ffa371f49a7c448264d62 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Wed, 13 Mar 2024 15:48:36 +0000 Subject: [PATCH 060/139] try pinned bb.js-dev --- noir/Dockerfile.packages-test | 2 ++ noir/noir-repo/compiler/integration-tests/package.json | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/noir/Dockerfile.packages-test b/noir/Dockerfile.packages-test index 7c9982384335..a9a609cfe941 100644 --- a/noir/Dockerfile.packages-test +++ b/noir/Dockerfile.packages-test @@ -6,6 +6,8 @@ FROM node:20 AS builder COPY --from=bb.js /usr/src/barretenberg/ts /usr/src/barretenberg/ts COPY --from=noir-packages /usr/src/noir/packages /usr/src/noir/packages +ENV NARGO_BACKEND_PATH=/usr/src/barretenberg/ts/bb.js-dev + WORKDIR /usr/src/barretenberg/ts RUN yarn --immutable diff --git a/noir/noir-repo/compiler/integration-tests/package.json b/noir/noir-repo/compiler/integration-tests/package.json index 511df534110f..798b7c553123 100644 --- a/noir/noir-repo/compiler/integration-tests/package.json +++ b/noir/noir-repo/compiler/integration-tests/package.json @@ -6,7 +6,7 @@ "scripts": { "build": "echo Integration Test build step", "test": "yarn test:browser && yarn test:node", - "test:node": "hardhat test test/node/**/*", + "test:node": "bash ./scripts/codegen-verifiers.sh && hardhat test test/node/**/*", "test:browser": "web-test-runner", "test:integration:browser": "web-test-runner test/browser/**/*.test.ts", "test:integration:browser:watch": "web-test-runner test/browser/**/*.test.ts --watch", From 42485d52c8f8bad7ea668a0eee6fd694493a9f27 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Wed, 13 Mar 2024 15:49:21 +0000 Subject: [PATCH 061/139] try linked bb.js --- noir/Dockerfile.packages-test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noir/Dockerfile.packages-test b/noir/Dockerfile.packages-test index a9a609cfe941..ebde5bdef2a0 100644 --- a/noir/Dockerfile.packages-test +++ b/noir/Dockerfile.packages-test @@ -6,7 +6,7 @@ FROM node:20 AS builder COPY --from=bb.js /usr/src/barretenberg/ts /usr/src/barretenberg/ts COPY --from=noir-packages /usr/src/noir/packages /usr/src/noir/packages -ENV NARGO_BACKEND_PATH=/usr/src/barretenberg/ts/bb.js-dev +ENV NARGO_BACKEND_PATH=bb.js WORKDIR /usr/src/barretenberg/ts RUN yarn --immutable From 25b3f4feccf5227c88016bb089491d730707433f Mon Sep 17 00:00:00 2001 From: vezenovm Date: Wed, 13 Mar 2024 16:28:49 +0000 Subject: [PATCH 062/139] update bb.js path --- noir/Dockerfile.packages-test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noir/Dockerfile.packages-test b/noir/Dockerfile.packages-test index ebde5bdef2a0..a9a609cfe941 100644 --- a/noir/Dockerfile.packages-test +++ b/noir/Dockerfile.packages-test @@ -6,7 +6,7 @@ FROM node:20 AS builder COPY --from=bb.js /usr/src/barretenberg/ts /usr/src/barretenberg/ts COPY --from=noir-packages /usr/src/noir/packages /usr/src/noir/packages -ENV NARGO_BACKEND_PATH=bb.js +ENV NARGO_BACKEND_PATH=/usr/src/barretenberg/ts/bb.js-dev WORKDIR /usr/src/barretenberg/ts RUN yarn --immutable From e02a4bc7c21fcb625d29317d7cb15c5f101bc079 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Wed, 13 Mar 2024 16:58:52 +0000 Subject: [PATCH 063/139] move nargo backend path env set --- barretenberg/cpp/src/barretenberg/dsl/README.md | 0 noir/Dockerfile.packages-test | 4 ++-- .../compiler/integration-tests/scripts/codegen-verifiers.sh | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) create mode 100644 barretenberg/cpp/src/barretenberg/dsl/README.md diff --git a/barretenberg/cpp/src/barretenberg/dsl/README.md b/barretenberg/cpp/src/barretenberg/dsl/README.md new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/noir/Dockerfile.packages-test b/noir/Dockerfile.packages-test index a9a609cfe941..1b5815f6acde 100644 --- a/noir/Dockerfile.packages-test +++ b/noir/Dockerfile.packages-test @@ -6,8 +6,6 @@ FROM node:20 AS builder COPY --from=bb.js /usr/src/barretenberg/ts /usr/src/barretenberg/ts COPY --from=noir-packages /usr/src/noir/packages /usr/src/noir/packages -ENV NARGO_BACKEND_PATH=/usr/src/barretenberg/ts/bb.js-dev - WORKDIR /usr/src/barretenberg/ts RUN yarn --immutable @@ -20,6 +18,8 @@ RUN apt update && apt install -y jq libc++1 ARG COMMIT_HASH ENV COMMIT_HASH=${COMMIT_HASH} +ENV NARGO_BACKEND_PATH=/usr/src/barretenberg/ts/bb.js-dev + WORKDIR /usr/src/noir COPY . . RUN ./scripts/test_js_packages.sh diff --git a/noir/noir-repo/compiler/integration-tests/scripts/codegen-verifiers.sh b/noir/noir-repo/compiler/integration-tests/scripts/codegen-verifiers.sh index e377a3ee3f87..b97b7559a34f 100644 --- a/noir/noir-repo/compiler/integration-tests/scripts/codegen-verifiers.sh +++ b/noir/noir-repo/compiler/integration-tests/scripts/codegen-verifiers.sh @@ -2,6 +2,8 @@ self_path=$(dirname "$(readlink -f "$0")") +echo $NARGO_BACKEND_PATH + repo_root=$self_path/../../.. # Run codegen-verifier for 1_mul From 91802745833e9b59a9fbe97ffe9796afd7f5df76 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Wed, 13 Mar 2024 16:58:57 +0000 Subject: [PATCH 064/139] echo path --- .../compiler/integration-tests/scripts/codegen-verifiers.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/noir/noir-repo/compiler/integration-tests/scripts/codegen-verifiers.sh b/noir/noir-repo/compiler/integration-tests/scripts/codegen-verifiers.sh index b97b7559a34f..df3dbee55bca 100644 --- a/noir/noir-repo/compiler/integration-tests/scripts/codegen-verifiers.sh +++ b/noir/noir-repo/compiler/integration-tests/scripts/codegen-verifiers.sh @@ -2,6 +2,7 @@ self_path=$(dirname "$(readlink -f "$0")") +echo $PATH echo $NARGO_BACKEND_PATH repo_root=$self_path/../../.. From 914af072c0f6f3a1cc0e7f3103e8078bd585bf06 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Wed, 13 Mar 2024 17:22:19 +0000 Subject: [PATCH 065/139] use main.js and some of DSL readme --- .../cpp/src/barretenberg/dsl/README.md | 18 ++++++++++++++++++ noir/Dockerfile.packages-test | 4 ++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/dsl/README.md b/barretenberg/cpp/src/barretenberg/dsl/README.md index e69de29bb2d1..656dd8103801 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/README.md +++ b/barretenberg/cpp/src/barretenberg/dsl/README.md @@ -0,0 +1,18 @@ +# Domain Specific Language + +This package adds support to use [ACIR](https://github.com/noir-lang/noir/tree/master/acvm-repo/acir) with barretenberg. + +## Breaking Changes + +There are two types of breaking changes. One that alters that alters the internal ACIR structure passed to barretenberg, and one that changes the entire structure itself that is passed to barretenberg. + +1. Internal Structure Change + +Go to the ACVM `acir` crate and re-run the [serde reflection test](../../../../../noir/noir-repo/acvm-repo/acir/src/lib.rs#L51). Remember to comment out the hash check to write the updated C++ serde file. Copy that file into the `dsl` package's [serde folder](./acir_format/serde/) where you will see an `acir.hpp` file. + +You will have to update a couple things in the new `acir.hpp`: +- Replace all `throw serde::deserialization_error` with `throw_or_abort` +- The top-level struct (such as `Program`) will still use its own namespace for its internal fields. This extra `Program::` can be removed from the top-level `struct Program { .. }` object, + +2. Full Breaking Change + diff --git a/noir/Dockerfile.packages-test b/noir/Dockerfile.packages-test index 1b5815f6acde..8daab2be841a 100644 --- a/noir/Dockerfile.packages-test +++ b/noir/Dockerfile.packages-test @@ -9,6 +9,8 @@ COPY --from=noir-packages /usr/src/noir/packages /usr/src/noir/packages WORKDIR /usr/src/barretenberg/ts RUN yarn --immutable +ENV NARGO_BACKEND_PATH=/usr/src/barretenberg/ts/dest/node/main.js + COPY --from=noir /usr/src/noir/noir-repo/target/release /usr/src/noir/noir-repo/target/release ENV PATH=${PATH}:/usr/src/noir/noir-repo/target/release RUN curl https://sh.rustup.rs -sSf | bash -s -- -y @@ -18,8 +20,6 @@ RUN apt update && apt install -y jq libc++1 ARG COMMIT_HASH ENV COMMIT_HASH=${COMMIT_HASH} -ENV NARGO_BACKEND_PATH=/usr/src/barretenberg/ts/bb.js-dev - WORKDIR /usr/src/noir COPY . . RUN ./scripts/test_js_packages.sh From c35130069cedac2df48a29c947cd9beeba1c9b81 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Wed, 13 Mar 2024 17:44:31 +0000 Subject: [PATCH 066/139] update gitignore --- noir/Dockerfile.packages-test | 2 ++ noir/noir-repo/compiler/integration-tests/.gitignore | 1 + .../compiler/integration-tests/scripts/codegen-verifiers.sh | 3 --- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/noir/Dockerfile.packages-test b/noir/Dockerfile.packages-test index 8daab2be841a..e4d9b72b4a9a 100644 --- a/noir/Dockerfile.packages-test +++ b/noir/Dockerfile.packages-test @@ -9,6 +9,8 @@ COPY --from=noir-packages /usr/src/noir/packages /usr/src/noir/packages WORKDIR /usr/src/barretenberg/ts RUN yarn --immutable +# Set the nargo backend to use the local bb.js of breaking serialization changes +# We use the backend to write the verification key for smart contract integration tests ENV NARGO_BACKEND_PATH=/usr/src/barretenberg/ts/dest/node/main.js COPY --from=noir /usr/src/noir/noir-repo/target/release /usr/src/noir/noir-repo/target/release diff --git a/noir/noir-repo/compiler/integration-tests/.gitignore b/noir/noir-repo/compiler/integration-tests/.gitignore index d27cc5f16183..40571b83650d 100644 --- a/noir/noir-repo/compiler/integration-tests/.gitignore +++ b/noir/noir-repo/compiler/integration-tests/.gitignore @@ -1,3 +1,4 @@ +contracts crs node_modules diff --git a/noir/noir-repo/compiler/integration-tests/scripts/codegen-verifiers.sh b/noir/noir-repo/compiler/integration-tests/scripts/codegen-verifiers.sh index df3dbee55bca..e377a3ee3f87 100644 --- a/noir/noir-repo/compiler/integration-tests/scripts/codegen-verifiers.sh +++ b/noir/noir-repo/compiler/integration-tests/scripts/codegen-verifiers.sh @@ -2,9 +2,6 @@ self_path=$(dirname "$(readlink -f "$0")") -echo $PATH -echo $NARGO_BACKEND_PATH - repo_root=$self_path/../../.. # Run codegen-verifier for 1_mul From a418cb4a03beb35be4abc50fc98c2ce25078f8ba Mon Sep 17 00:00:00 2001 From: vezenovm Date: Wed, 13 Mar 2024 17:48:59 +0000 Subject: [PATCH 067/139] updated readme --- barretenberg/cpp/src/barretenberg/dsl/README.md | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/dsl/README.md b/barretenberg/cpp/src/barretenberg/dsl/README.md index 656dd8103801..b474c9bbdb27 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/README.md +++ b/barretenberg/cpp/src/barretenberg/dsl/README.md @@ -2,9 +2,9 @@ This package adds support to use [ACIR](https://github.com/noir-lang/noir/tree/master/acvm-repo/acir) with barretenberg. -## Breaking Changes +## Serialization Changes -There are two types of breaking changes. One that alters that alters the internal ACIR structure passed to barretenberg, and one that changes the entire structure itself that is passed to barretenberg. +There are two types of breaking serialization changes. One that alters that alters the internal ACIR structure passed to barretenberg, and one that changes how we serialize the buffer passed to barretenberg. 1. Internal Structure Change @@ -12,7 +12,17 @@ Go to the ACVM `acir` crate and re-run the [serde reflection test](../../../../. You will have to update a couple things in the new `acir.hpp`: - Replace all `throw serde::deserialization_error` with `throw_or_abort` -- The top-level struct (such as `Program`) will still use its own namespace for its internal fields. This extra `Program::` can be removed from the top-level `struct Program { .. }` object, +- The top-level struct (such as `Program`) will still use its own namespace for its internal fields. This extra `Program::` can be removed from the top-level `struct Program { .. }` object. + +The same can then be done for any breaking changes introduced to `witness_stack.hpp`. 2. Full Breaking Change +This type of breaking change is rarely expected to happen, however, due to its nature there are multiple consumers of the pre-existing serialization you should be aware of if you ever need to make this change. + +A full change is when you attempt to change the object whose buffer we are actually deserializing in barretenberg. To give more detail, when [deserializing the constraint buffer](./acir_format/acir_to_constraint_buf.hpp#366) if the object for which we call `bincodeDeserialize` on changes, anything that has pre-existing ACIR using the previous object's `bincodeDeserialize` method will now fail. The serialization is once again determined by the top-level object in the [acir crate](../../../../../noir/noir-repo/acvm-repo/acir/src/circuit/mod.rs). After performing the steps outlined for an internal structure breaking change as listed in (1) above, we need to update all consumers of barretenberg. + +Even if you correctly update all serialization in [acvm_js](../../../../../noir/noir-repo/acvm-repo/acvm_js/README.md) such as during [execution](../../../../../noir/noir-repo/acvm-repo/acvm_js/src/execute.rs#57), there is multiple places the `yarn-project` uses the ACIR top-level serialization. The `yarn-project` sequencer also uses the native `acvm_cli tool` that has an execute method that [expects raw byte code](../../../../../noir/noir-repo/tooling/acvm_cli/src/cli/execute_cmd.rs#63). + +In the context of Aztec we need to regenerate all the artifacts in [noir-projects](../../../../../noir-projects/bootstrap.sh). This regeneration assumes that we have rebuilt the compiler from which we got the original ACIR object from to use the new serialization. After regenerating these artifacts we can bootstrap the yarn-project. There are multiple packages in the yarn-project that rely on pre-computed artifacts such as `yarn-project/circuits.js` and `yarn-project/protocol-contracts`. These can be individually regenerated using `yarn test -u`, however, it is much easier to let the bootstrap scripts handle these updates. + From b665ff7f026fb373c0cf53f9f257f85f053b8c6b Mon Sep 17 00:00:00 2001 From: vezenovm Date: Wed, 13 Mar 2024 17:54:03 +0000 Subject: [PATCH 068/139] remove commitment to contracts --- .../integration-tests/contracts/1_mul.sol | 2869 ----------------- .../contracts/assert_statement.sol | 2869 ----------------- .../integration-tests/contracts/recursion.sol | 2869 ----------------- 3 files changed, 8607 deletions(-) delete mode 100644 noir/noir-repo/compiler/integration-tests/contracts/1_mul.sol delete mode 100644 noir/noir-repo/compiler/integration-tests/contracts/assert_statement.sol delete mode 100644 noir/noir-repo/compiler/integration-tests/contracts/recursion.sol diff --git a/noir/noir-repo/compiler/integration-tests/contracts/1_mul.sol b/noir/noir-repo/compiler/integration-tests/contracts/1_mul.sol deleted file mode 100644 index ff8f36385337..000000000000 --- a/noir/noir-repo/compiler/integration-tests/contracts/1_mul.sol +++ /dev/null @@ -1,2869 +0,0 @@ -// Verification Key Hash: 81dab81c9312ecc480984185bcdeabfb118f294791980be42c247006c29b27de -// SPDX-License-Identifier: Apache-2.0 -// Copyright 2022 Aztec -pragma solidity >=0.8.4; - -library UltraVerificationKey { - function verificationKeyHash() internal pure returns(bytes32) { - return 0x81dab81c9312ecc480984185bcdeabfb118f294791980be42c247006c29b27de; - } - - function loadVerificationKey(uint256 _vk, uint256 _omegaInverseLoc) internal pure { - assembly { - mstore(add(_vk, 0x00), 0x0000000000000000000000000000000000000000000000000000000000001000) // vk.circuit_size - mstore(add(_vk, 0x20), 0x0000000000000000000000000000000000000000000000000000000000000000) // vk.num_inputs - mstore(add(_vk, 0x40), 0x0931d596de2fd10f01ddd073fd5a90a976f169c76f039bb91c4775720042d43a) // vk.work_root - mstore(add(_vk, 0x60), 0x3061482dfa038d0fb5b4c0b226194047a2616509f531d4fa3acdb77496c10001) // vk.domain_inverse - mstore(add(_vk, 0x80), 0x26dff731489360cd9d88e52bad2198f84d36c1439b77c54f95d6eaf0cef94b8f) // vk.Q1.x - mstore(add(_vk, 0xa0), 0x02acb21f0f38895956e06930708b45106e016ebefc0d24dcdb8c7f959967a90c) // vk.Q1.y - mstore(add(_vk, 0xc0), 0x24ef08dff23f2729f6cd70ed8305655ccec1dfb5e70d8e8a2d4190ce1a1d7e81) // vk.Q2.x - mstore(add(_vk, 0xe0), 0x16ae4c218a37acdb580a2f2c2033d4c93ee06633febe6c96d6bc845b1fbbf7db) // vk.Q2.y - mstore(add(_vk, 0x100), 0x02be54ccdfcf358d15e469f7a7a79d4851996cb90ff7e6ae89734c53b5db89b2) // vk.Q3.x - mstore(add(_vk, 0x120), 0x292fefb96ebc59f41b06421baa766e8949eab20ba1ddbe3cdc0d4a130bdc9dac) // vk.Q3.y - mstore(add(_vk, 0x140), 0x019d7129fa4f0cc04801bd9b9065a25c61b3400244190698a17d73f550c3ad01) // vk.Q4.x - mstore(add(_vk, 0x160), 0x106810b16c402a25c417c5603b70b3ee6b41316be80ba38bb2276f8e9427d8b9) // vk.Q4.y - mstore(add(_vk, 0x180), 0x0efb192384fe64f333475e3c441dcb9d8933a2b4a4179d43b66ee1966199de66) // vk.Q_M.x - mstore(add(_vk, 0x1a0), 0x2a56cfd4a9b725326de5171dd6ec6cba64945cde70652768e4aeecb4a92f193a) // vk.Q_M.y - mstore(add(_vk, 0x1c0), 0x24e321e4d1e65f3c26b32903a432217b5d1c03cf5ac13fa055b5d38216bac3f1) // vk.Q_C.x - mstore(add(_vk, 0x1e0), 0x304c9ace458fbf93f3e9d07fea2b48edc40e9d248862871437a044d557b89085) // vk.Q_C.y - mstore(add(_vk, 0x200), 0x040f659b07806f721e8eeb17773c70a7351a0e59a15027c7f87343d5bd2cac01) // vk.Q_ARITHMETIC.x - mstore(add(_vk, 0x220), 0x215a63918831655a2020158099ebd13bbab94febef4febe815bbca0ac5b0b303) // vk.Q_ARITHMETIC.y - mstore(add(_vk, 0x240), 0x0348ad0a2d9d9a94c78f6c20d7ed0ee0a018bc5a3e51a3453f4256430b0d526c) // vk.QSORT.x - mstore(add(_vk, 0x260), 0x0b711c4268e26d19a11f7560fc53828b7d9e6f920ccb8a0129f8d515c66d99ac) // vk.QSORT.y - mstore(add(_vk, 0x280), 0x13982fd0cf8da5082a77561113bb5ee51e2e82380da3da5ad0f24e49e5f32208) // vk.Q_ELLIPTIC.x - mstore(add(_vk, 0x2a0), 0x1aa5ffd5aa4c16d1c66e18c4574a3ab0b25e9b4e4e04ad1280d1a264237717e0) // vk.Q_ELLIPTIC.y - mstore(add(_vk, 0x2c0), 0x1750f44d3f9dfad78a1e2127ef91051ce018f20536fe45ca28dcc7b248389fc0) // vk.Q_AUX.x - mstore(add(_vk, 0x2e0), 0x1a05418f502a965c39994cd3f83e39164b49c0f27d4f5ac4550751cc0a24bb58) // vk.Q_AUX.y - mstore(add(_vk, 0x300), 0x0e79dad980ecbcba02fa09399f492293608ea5ec55655f381851ab2a7fd9d3e4) // vk.SIGMA1.x - mstore(add(_vk, 0x320), 0x20dcf4e6e84362a1fbb32928b49070375f866ce7334fe5d96572d6a885879066) // vk.SIGMA1.y - mstore(add(_vk, 0x340), 0x04700138101e581226ac624463c28d886eedc87159a518f9c59e117b30dd9fc6) // vk.SIGMA2.x - mstore(add(_vk, 0x360), 0x0766d9586e6192576f6eddb0e2c023f9a574f4d736c9480820431f434b235344) // vk.SIGMA2.y - mstore(add(_vk, 0x380), 0x196fd832eb6b30543b949cd2a124bd2d1504133b34fe6b6346f30cc7a3ed2a75) // vk.SIGMA3.x - mstore(add(_vk, 0x3a0), 0x14bfde5cb996c75c818cdf88d9234ccc0e905f27af5503f42a8f38c2892d6e1c) // vk.SIGMA3.y - mstore(add(_vk, 0x3c0), 0x03c8a1592fca76a3959266b015c120e99a764029d1373ce0a9329d8b441f841a) // vk.SIGMA4.x - mstore(add(_vk, 0x3e0), 0x2239ff07c67a2a59139ef012e667a5fb08293af4abc6dc70e1297e45e744355c) // vk.SIGMA4.y - mstore(add(_vk, 0x400), 0x259f452dc7fd2dda4013dba2196852bcf43c285b1d1f7f85341f3615d25fe97b) // vk.TABLE1.x - mstore(add(_vk, 0x420), 0x117500555dd886209c0b10ee8cd10e711e890a1c99a8f689419da8c52d2e8e9d) // vk.TABLE1.y - mstore(add(_vk, 0x440), 0x2577f542178a07dac262fdabad6f55a84fca32b13b92e520bb91a7455f78ccf1) // vk.TABLE2.x - mstore(add(_vk, 0x460), 0x0fc87ae27122e60eaacc070bd59aafe12644a82ee1345497f8c0302e92925c68) // vk.TABLE2.y - mstore(add(_vk, 0x480), 0x1612f501335a4b72ac55dbe2fd1a75e5fe2c041687603b6577581d673d13be50) // vk.TABLE3.x - mstore(add(_vk, 0x4a0), 0x160e8ef7ff5315cb640ec82e965db270846e904bb7d1c7ff02f32823de6c1c71) // vk.TABLE3.y - mstore(add(_vk, 0x4c0), 0x2d540ff1653b38acbcb9cda315442364007633f529476b2f169a0ff131bfb319) // vk.TABLE4.x - mstore(add(_vk, 0x4e0), 0x2198b9feb61f8160e357b8bb7ca329713898655cc94a0ac2d84944c737cf57e5) // vk.TABLE4.y - mstore(add(_vk, 0x500), 0x11c8df52c3ef754f80d11792cea4b7ad74612e486596cbe7f7d6a05f19c69444) // vk.TABLE_TYPE.x - mstore(add(_vk, 0x520), 0x10c8a36cbb2fd9ed8875b5106a37162ac2932f3bd1b6942b132546d2110a63e2) // vk.TABLE_TYPE.y - mstore(add(_vk, 0x540), 0x122470dc810ee1029ff28334364b1b3dd18193defaf51bb09296275700ee6dd0) // vk.ID1.x - mstore(add(_vk, 0x560), 0x018b2c609f8013a95b1e7c3346e2d3febea6791d393777bfc213831f687070b9) // vk.ID1.y - mstore(add(_vk, 0x580), 0x2fd86e853b82a697cfcd347bad53b66a655813df12ba231808bf65f6561e923c) // vk.ID2.x - mstore(add(_vk, 0x5a0), 0x12b82a7864a782e5afc7f9c85f01ee1b233d94da8bcd1fac485cfdd481db8086) // vk.ID2.y - mstore(add(_vk, 0x5c0), 0x23afba4022c9e1a3eb7ab039a120c48ee661a8e06751225fb989b53f0bfe0b34) // vk.ID3.x - mstore(add(_vk, 0x5e0), 0x04f7c94dc819346aae8a76a89d7d1792c1806ed2e76828e60ee05241952773ec) // vk.ID3.y - mstore(add(_vk, 0x600), 0x282ed40f6896050dc339a08a220ddfb4d33a7c766684e2dde14ca6f452da84b0) // vk.ID4.x - mstore(add(_vk, 0x620), 0x2dadeff4061603c87f4dce0e42c6e145f590062d9bf6e6642f997275bb05b6af) // vk.ID4.y - mstore(add(_vk, 0x640), 0x00) // vk.contains_recursive_proof - mstore(add(_vk, 0x660), 0) // vk.recursive_proof_public_input_indices - mstore(add(_vk, 0x680), 0x260e01b251f6f1c7e7ff4e580791dee8ea51d87a358e038b4efe30fac09383c1) // vk.g2_x.X.c1 - mstore(add(_vk, 0x6a0), 0x0118c4d5b837bcc2bc89b5b398b5974e9f5944073b32078b7e231fec938883b0) // vk.g2_x.X.c0 - mstore(add(_vk, 0x6c0), 0x04fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe4) // vk.g2_x.Y.c1 - mstore(add(_vk, 0x6e0), 0x22febda3c0c0632a56475b4214e5615e11e6dd3f96e6cea2854a87d4dacc5e55) // vk.g2_x.Y.c0 - mstore(_omegaInverseLoc, 0x1af864d211b88d9ccf2e371c2ba088d9269d3fdea04e05acb6f70f8dc79e0e57) // vk.work_root_inverse - } - } -} - -/** - * @title Ultra Plonk proof verification contract - * @dev Top level Plonk proof verification contract, which allows Plonk proof to be verified - */ -abstract contract BaseUltraVerifier { - // VERIFICATION KEY MEMORY LOCATIONS - uint256 internal constant N_LOC = 0x380; - uint256 internal constant NUM_INPUTS_LOC = 0x3a0; - uint256 internal constant OMEGA_LOC = 0x3c0; - uint256 internal constant DOMAIN_INVERSE_LOC = 0x3e0; - uint256 internal constant Q1_X_LOC = 0x400; - uint256 internal constant Q1_Y_LOC = 0x420; - uint256 internal constant Q2_X_LOC = 0x440; - uint256 internal constant Q2_Y_LOC = 0x460; - uint256 internal constant Q3_X_LOC = 0x480; - uint256 internal constant Q3_Y_LOC = 0x4a0; - uint256 internal constant Q4_X_LOC = 0x4c0; - uint256 internal constant Q4_Y_LOC = 0x4e0; - uint256 internal constant QM_X_LOC = 0x500; - uint256 internal constant QM_Y_LOC = 0x520; - uint256 internal constant QC_X_LOC = 0x540; - uint256 internal constant QC_Y_LOC = 0x560; - uint256 internal constant QARITH_X_LOC = 0x580; - uint256 internal constant QARITH_Y_LOC = 0x5a0; - uint256 internal constant QSORT_X_LOC = 0x5c0; - uint256 internal constant QSORT_Y_LOC = 0x5e0; - uint256 internal constant QELLIPTIC_X_LOC = 0x600; - uint256 internal constant QELLIPTIC_Y_LOC = 0x620; - uint256 internal constant QAUX_X_LOC = 0x640; - uint256 internal constant QAUX_Y_LOC = 0x660; - uint256 internal constant SIGMA1_X_LOC = 0x680; - uint256 internal constant SIGMA1_Y_LOC = 0x6a0; - uint256 internal constant SIGMA2_X_LOC = 0x6c0; - uint256 internal constant SIGMA2_Y_LOC = 0x6e0; - uint256 internal constant SIGMA3_X_LOC = 0x700; - uint256 internal constant SIGMA3_Y_LOC = 0x720; - uint256 internal constant SIGMA4_X_LOC = 0x740; - uint256 internal constant SIGMA4_Y_LOC = 0x760; - uint256 internal constant TABLE1_X_LOC = 0x780; - uint256 internal constant TABLE1_Y_LOC = 0x7a0; - uint256 internal constant TABLE2_X_LOC = 0x7c0; - uint256 internal constant TABLE2_Y_LOC = 0x7e0; - uint256 internal constant TABLE3_X_LOC = 0x800; - uint256 internal constant TABLE3_Y_LOC = 0x820; - uint256 internal constant TABLE4_X_LOC = 0x840; - uint256 internal constant TABLE4_Y_LOC = 0x860; - uint256 internal constant TABLE_TYPE_X_LOC = 0x880; - uint256 internal constant TABLE_TYPE_Y_LOC = 0x8a0; - uint256 internal constant ID1_X_LOC = 0x8c0; - uint256 internal constant ID1_Y_LOC = 0x8e0; - uint256 internal constant ID2_X_LOC = 0x900; - uint256 internal constant ID2_Y_LOC = 0x920; - uint256 internal constant ID3_X_LOC = 0x940; - uint256 internal constant ID3_Y_LOC = 0x960; - uint256 internal constant ID4_X_LOC = 0x980; - uint256 internal constant ID4_Y_LOC = 0x9a0; - uint256 internal constant CONTAINS_RECURSIVE_PROOF_LOC = 0x9c0; - uint256 internal constant RECURSIVE_PROOF_PUBLIC_INPUT_INDICES_LOC = 0x9e0; - uint256 internal constant G2X_X0_LOC = 0xa00; - uint256 internal constant G2X_X1_LOC = 0xa20; - uint256 internal constant G2X_Y0_LOC = 0xa40; - uint256 internal constant G2X_Y1_LOC = 0xa60; - - // ### PROOF DATA MEMORY LOCATIONS - uint256 internal constant W1_X_LOC = 0x1200; - uint256 internal constant W1_Y_LOC = 0x1220; - uint256 internal constant W2_X_LOC = 0x1240; - uint256 internal constant W2_Y_LOC = 0x1260; - uint256 internal constant W3_X_LOC = 0x1280; - uint256 internal constant W3_Y_LOC = 0x12a0; - uint256 internal constant W4_X_LOC = 0x12c0; - uint256 internal constant W4_Y_LOC = 0x12e0; - uint256 internal constant S_X_LOC = 0x1300; - uint256 internal constant S_Y_LOC = 0x1320; - uint256 internal constant Z_X_LOC = 0x1340; - uint256 internal constant Z_Y_LOC = 0x1360; - uint256 internal constant Z_LOOKUP_X_LOC = 0x1380; - uint256 internal constant Z_LOOKUP_Y_LOC = 0x13a0; - uint256 internal constant T1_X_LOC = 0x13c0; - uint256 internal constant T1_Y_LOC = 0x13e0; - uint256 internal constant T2_X_LOC = 0x1400; - uint256 internal constant T2_Y_LOC = 0x1420; - uint256 internal constant T3_X_LOC = 0x1440; - uint256 internal constant T3_Y_LOC = 0x1460; - uint256 internal constant T4_X_LOC = 0x1480; - uint256 internal constant T4_Y_LOC = 0x14a0; - - uint256 internal constant W1_EVAL_LOC = 0x1600; - uint256 internal constant W2_EVAL_LOC = 0x1620; - uint256 internal constant W3_EVAL_LOC = 0x1640; - uint256 internal constant W4_EVAL_LOC = 0x1660; - uint256 internal constant S_EVAL_LOC = 0x1680; - uint256 internal constant Z_EVAL_LOC = 0x16a0; - uint256 internal constant Z_LOOKUP_EVAL_LOC = 0x16c0; - uint256 internal constant Q1_EVAL_LOC = 0x16e0; - uint256 internal constant Q2_EVAL_LOC = 0x1700; - uint256 internal constant Q3_EVAL_LOC = 0x1720; - uint256 internal constant Q4_EVAL_LOC = 0x1740; - uint256 internal constant QM_EVAL_LOC = 0x1760; - uint256 internal constant QC_EVAL_LOC = 0x1780; - uint256 internal constant QARITH_EVAL_LOC = 0x17a0; - uint256 internal constant QSORT_EVAL_LOC = 0x17c0; - uint256 internal constant QELLIPTIC_EVAL_LOC = 0x17e0; - uint256 internal constant QAUX_EVAL_LOC = 0x1800; - uint256 internal constant TABLE1_EVAL_LOC = 0x1840; - uint256 internal constant TABLE2_EVAL_LOC = 0x1860; - uint256 internal constant TABLE3_EVAL_LOC = 0x1880; - uint256 internal constant TABLE4_EVAL_LOC = 0x18a0; - uint256 internal constant TABLE_TYPE_EVAL_LOC = 0x18c0; - uint256 internal constant ID1_EVAL_LOC = 0x18e0; - uint256 internal constant ID2_EVAL_LOC = 0x1900; - uint256 internal constant ID3_EVAL_LOC = 0x1920; - uint256 internal constant ID4_EVAL_LOC = 0x1940; - uint256 internal constant SIGMA1_EVAL_LOC = 0x1960; - uint256 internal constant SIGMA2_EVAL_LOC = 0x1980; - uint256 internal constant SIGMA3_EVAL_LOC = 0x19a0; - uint256 internal constant SIGMA4_EVAL_LOC = 0x19c0; - uint256 internal constant W1_OMEGA_EVAL_LOC = 0x19e0; - uint256 internal constant W2_OMEGA_EVAL_LOC = 0x2000; - uint256 internal constant W3_OMEGA_EVAL_LOC = 0x2020; - uint256 internal constant W4_OMEGA_EVAL_LOC = 0x2040; - uint256 internal constant S_OMEGA_EVAL_LOC = 0x2060; - uint256 internal constant Z_OMEGA_EVAL_LOC = 0x2080; - uint256 internal constant Z_LOOKUP_OMEGA_EVAL_LOC = 0x20a0; - uint256 internal constant TABLE1_OMEGA_EVAL_LOC = 0x20c0; - uint256 internal constant TABLE2_OMEGA_EVAL_LOC = 0x20e0; - uint256 internal constant TABLE3_OMEGA_EVAL_LOC = 0x2100; - uint256 internal constant TABLE4_OMEGA_EVAL_LOC = 0x2120; - - uint256 internal constant PI_Z_X_LOC = 0x2300; - uint256 internal constant PI_Z_Y_LOC = 0x2320; - uint256 internal constant PI_Z_OMEGA_X_LOC = 0x2340; - uint256 internal constant PI_Z_OMEGA_Y_LOC = 0x2360; - - // Used for elliptic widget. These are alias names for wire + shifted wire evaluations - uint256 internal constant X1_EVAL_LOC = W2_EVAL_LOC; - uint256 internal constant X2_EVAL_LOC = W1_OMEGA_EVAL_LOC; - uint256 internal constant X3_EVAL_LOC = W2_OMEGA_EVAL_LOC; - uint256 internal constant Y1_EVAL_LOC = W3_EVAL_LOC; - uint256 internal constant Y2_EVAL_LOC = W4_OMEGA_EVAL_LOC; - uint256 internal constant Y3_EVAL_LOC = W3_OMEGA_EVAL_LOC; - uint256 internal constant QBETA_LOC = Q3_EVAL_LOC; - uint256 internal constant QBETA_SQR_LOC = Q4_EVAL_LOC; - uint256 internal constant QSIGN_LOC = Q1_EVAL_LOC; - - // ### CHALLENGES MEMORY OFFSETS - - uint256 internal constant C_BETA_LOC = 0x2600; - uint256 internal constant C_GAMMA_LOC = 0x2620; - uint256 internal constant C_ALPHA_LOC = 0x2640; - uint256 internal constant C_ETA_LOC = 0x2660; - uint256 internal constant C_ETA_SQR_LOC = 0x2680; - uint256 internal constant C_ETA_CUBE_LOC = 0x26a0; - - uint256 internal constant C_ZETA_LOC = 0x26c0; - uint256 internal constant C_CURRENT_LOC = 0x26e0; - uint256 internal constant C_V0_LOC = 0x2700; - uint256 internal constant C_V1_LOC = 0x2720; - uint256 internal constant C_V2_LOC = 0x2740; - uint256 internal constant C_V3_LOC = 0x2760; - uint256 internal constant C_V4_LOC = 0x2780; - uint256 internal constant C_V5_LOC = 0x27a0; - uint256 internal constant C_V6_LOC = 0x27c0; - uint256 internal constant C_V7_LOC = 0x27e0; - uint256 internal constant C_V8_LOC = 0x2800; - uint256 internal constant C_V9_LOC = 0x2820; - uint256 internal constant C_V10_LOC = 0x2840; - uint256 internal constant C_V11_LOC = 0x2860; - uint256 internal constant C_V12_LOC = 0x2880; - uint256 internal constant C_V13_LOC = 0x28a0; - uint256 internal constant C_V14_LOC = 0x28c0; - uint256 internal constant C_V15_LOC = 0x28e0; - uint256 internal constant C_V16_LOC = 0x2900; - uint256 internal constant C_V17_LOC = 0x2920; - uint256 internal constant C_V18_LOC = 0x2940; - uint256 internal constant C_V19_LOC = 0x2960; - uint256 internal constant C_V20_LOC = 0x2980; - uint256 internal constant C_V21_LOC = 0x29a0; - uint256 internal constant C_V22_LOC = 0x29c0; - uint256 internal constant C_V23_LOC = 0x29e0; - uint256 internal constant C_V24_LOC = 0x2a00; - uint256 internal constant C_V25_LOC = 0x2a20; - uint256 internal constant C_V26_LOC = 0x2a40; - uint256 internal constant C_V27_LOC = 0x2a60; - uint256 internal constant C_V28_LOC = 0x2a80; - uint256 internal constant C_V29_LOC = 0x2aa0; - uint256 internal constant C_V30_LOC = 0x2ac0; - - uint256 internal constant C_U_LOC = 0x2b00; - - // ### LOCAL VARIABLES MEMORY OFFSETS - uint256 internal constant DELTA_NUMERATOR_LOC = 0x3000; - uint256 internal constant DELTA_DENOMINATOR_LOC = 0x3020; - uint256 internal constant ZETA_POW_N_LOC = 0x3040; - uint256 internal constant PUBLIC_INPUT_DELTA_LOC = 0x3060; - uint256 internal constant ZERO_POLY_LOC = 0x3080; - uint256 internal constant L_START_LOC = 0x30a0; - uint256 internal constant L_END_LOC = 0x30c0; - uint256 internal constant R_ZERO_EVAL_LOC = 0x30e0; - - uint256 internal constant PLOOKUP_DELTA_NUMERATOR_LOC = 0x3100; - uint256 internal constant PLOOKUP_DELTA_DENOMINATOR_LOC = 0x3120; - uint256 internal constant PLOOKUP_DELTA_LOC = 0x3140; - - uint256 internal constant ACCUMULATOR_X_LOC = 0x3160; - uint256 internal constant ACCUMULATOR_Y_LOC = 0x3180; - uint256 internal constant ACCUMULATOR2_X_LOC = 0x31a0; - uint256 internal constant ACCUMULATOR2_Y_LOC = 0x31c0; - uint256 internal constant PAIRING_LHS_X_LOC = 0x31e0; - uint256 internal constant PAIRING_LHS_Y_LOC = 0x3200; - uint256 internal constant PAIRING_RHS_X_LOC = 0x3220; - uint256 internal constant PAIRING_RHS_Y_LOC = 0x3240; - - // misc stuff - uint256 internal constant OMEGA_INVERSE_LOC = 0x3300; - uint256 internal constant C_ALPHA_SQR_LOC = 0x3320; - uint256 internal constant C_ALPHA_CUBE_LOC = 0x3340; - uint256 internal constant C_ALPHA_QUAD_LOC = 0x3360; - uint256 internal constant C_ALPHA_BASE_LOC = 0x3380; - - // ### RECURSION VARIABLE MEMORY LOCATIONS - uint256 internal constant RECURSIVE_P1_X_LOC = 0x3400; - uint256 internal constant RECURSIVE_P1_Y_LOC = 0x3420; - uint256 internal constant RECURSIVE_P2_X_LOC = 0x3440; - uint256 internal constant RECURSIVE_P2_Y_LOC = 0x3460; - uint256 internal constant PUBLIC_INPUTS_HASH_LOCATION = 0x3480; - - // sub-identity storage - uint256 internal constant PERMUTATION_IDENTITY = 0x3500; - uint256 internal constant PLOOKUP_IDENTITY = 0x3520; - uint256 internal constant ARITHMETIC_IDENTITY = 0x3540; - uint256 internal constant SORT_IDENTITY = 0x3560; - uint256 internal constant ELLIPTIC_IDENTITY = 0x3580; - uint256 internal constant AUX_IDENTITY = 0x35a0; - uint256 internal constant AUX_NON_NATIVE_FIELD_EVALUATION = 0x35c0; - uint256 internal constant AUX_LIMB_ACCUMULATOR_EVALUATION = 0x35e0; - uint256 internal constant AUX_RAM_CONSISTENCY_EVALUATION = 0x3600; - uint256 internal constant AUX_ROM_CONSISTENCY_EVALUATION = 0x3620; - uint256 internal constant AUX_MEMORY_EVALUATION = 0x3640; - - uint256 internal constant QUOTIENT_EVAL_LOC = 0x3660; - uint256 internal constant ZERO_POLY_INVERSE_LOC = 0x3680; - - // when hashing public inputs we use memory at NU_CHALLENGE_INPUT_LOC_A, as the hash input size is unknown at compile time - uint256 internal constant NU_CHALLENGE_INPUT_LOC_A = 0x36a0; - uint256 internal constant NU_CHALLENGE_INPUT_LOC_B = 0x36c0; - uint256 internal constant NU_CHALLENGE_INPUT_LOC_C = 0x36e0; - - bytes4 internal constant INVALID_VERIFICATION_KEY_SELECTOR = 0x7e5769bf; - bytes4 internal constant POINT_NOT_ON_CURVE_SELECTOR = 0xa3dad654; - bytes4 internal constant PUBLIC_INPUT_INVALID_BN128_G1_POINT_SELECTOR = 0xeba9f4a6; - bytes4 internal constant PUBLIC_INPUT_GE_P_SELECTOR = 0x374a972f; - bytes4 internal constant MOD_EXP_FAILURE_SELECTOR = 0xf894a7bc; - bytes4 internal constant PAIRING_PREAMBLE_FAILED_SELECTOR = 0x01882d81; - bytes4 internal constant OPENING_COMMITMENT_FAILED_SELECTOR = 0x4e719763; - bytes4 internal constant PAIRING_FAILED_SELECTOR = 0xd71fd263; - - uint256 internal constant ETA_INPUT_LENGTH = 0xc0; // W1, W2, W3 = 6 * 0x20 bytes - - // We need to hash 41 field elements when generating the NU challenge - // w1, w2, w3, w4, s, z, z_lookup, q1, q2, q3, q4, qm, qc, qarith (14) - // qsort, qelliptic, qaux, sigma1, sigma2, sigma, sigma4, (7) - // table1, table2, table3, table4, tabletype, id1, id2, id3, id4, (9) - // w1_omega, w2_omega, w3_omega, w4_omega, s_omega, z_omega, z_lookup_omega, (7) - // table1_omega, table2_omega, table3_omega, table4_omega (4) - uint256 internal constant NU_INPUT_LENGTH = 0x520; // 0x520 = 41 * 0x20 - - // There are ELEVEN G1 group elements added into the transcript in the `beta` round, that we need to skip over - // W1, W2, W3, W4, S, Z, Z_LOOKUP, T1, T2, T3, T4 - uint256 internal constant NU_CALLDATA_SKIP_LENGTH = 0x2c0; // 11 * 0x40 = 0x2c0 - - uint256 internal constant NEGATIVE_INVERSE_OF_2_MODULO_P = - 0x183227397098d014dc2822db40c0ac2e9419f4243cdcb848a1f0fac9f8000000; - uint256 internal constant LIMB_SIZE = 0x100000000000000000; // 2<<68 - uint256 internal constant SUBLIMB_SHIFT = 0x4000; // 2<<14 - - // y^2 = x^3 + ax + b - // for Grumpkin, a = 0 and b = -17. We use b in a custom gate relation that evaluates elliptic curve arithmetic - uint256 internal constant GRUMPKIN_CURVE_B_PARAMETER_NEGATED = 17; - - error INVALID_VERIFICATION_KEY(); - error POINT_NOT_ON_CURVE(); - error PUBLIC_INPUT_COUNT_INVALID(uint256 expected, uint256 actual); - error PUBLIC_INPUT_INVALID_BN128_G1_POINT(); - error PUBLIC_INPUT_GE_P(); - error MOD_EXP_FAILURE(); - error PAIRING_PREAMBLE_FAILED(); - error OPENING_COMMITMENT_FAILED(); - error PAIRING_FAILED(); - - function getVerificationKeyHash() public pure virtual returns (bytes32); - - /** - * @dev We assume that the verification key loaded by this function is constant as we only verify it on deployment - */ - function loadVerificationKey(uint256 _vk, uint256 _omegaInverseLoc) internal pure virtual; - - constructor() { - loadVerificationKey(N_LOC, OMEGA_INVERSE_LOC); - - // We verify that all of the EC points in the verification key lie on the bn128 curve. - assembly { - let q := 21888242871839275222246405745257275088696311157297823662689037894645226208583 // EC group order - - let success := 1 - - // VALIDATE Q1 - { - let x := mload(Q1_X_LOC) - let y := mload(Q1_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE Q2 - { - let x := mload(Q2_X_LOC) - let y := mload(Q2_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE Q3 - { - let x := mload(Q3_X_LOC) - let y := mload(Q3_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE Q4 - { - let x := mload(Q4_X_LOC) - let y := mload(Q4_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - mstore(0x00, x) - mstore(0x20, y) - } - // VALIDATE QM - { - let x := mload(QM_X_LOC) - let y := mload(QM_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE QC - { - let x := mload(QC_X_LOC) - let y := mload(QC_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE QARITH - { - let x := mload(QARITH_X_LOC) - let y := mload(QARITH_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE QSORT - { - let x := mload(QSORT_X_LOC) - let y := mload(QSORT_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE QELLIPTIC - { - let x := mload(QELLIPTIC_X_LOC) - let y := mload(QELLIPTIC_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE QAUX - { - let x := mload(QAUX_X_LOC) - let y := mload(QAUX_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE SIGMA1 - { - let x := mload(SIGMA1_X_LOC) - let y := mload(SIGMA1_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE SIGMA2 - { - let x := mload(SIGMA2_X_LOC) - let y := mload(SIGMA2_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE SIGMA3 - { - let x := mload(SIGMA3_X_LOC) - let y := mload(SIGMA3_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE SIGMA4 - { - let x := mload(SIGMA4_X_LOC) - let y := mload(SIGMA4_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE TABLE1 - { - let x := mload(TABLE1_X_LOC) - let y := mload(TABLE1_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE TABLE2 - { - let x := mload(TABLE2_X_LOC) - let y := mload(TABLE2_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE TABLE3 - { - let x := mload(TABLE3_X_LOC) - let y := mload(TABLE3_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE TABLE4 - { - let x := mload(TABLE4_X_LOC) - let y := mload(TABLE4_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE TABLE_TYPE - { - let x := mload(TABLE_TYPE_X_LOC) - let y := mload(TABLE_TYPE_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE ID1 - { - let x := mload(ID1_X_LOC) - let y := mload(ID1_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE ID2 - { - let x := mload(ID2_X_LOC) - let y := mload(ID2_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE ID3 - { - let x := mload(ID3_X_LOC) - let y := mload(ID3_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE ID4 - { - let x := mload(ID4_X_LOC) - let y := mload(ID4_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - - if iszero(success) { - mstore(0x0, INVALID_VERIFICATION_KEY_SELECTOR) - revert(0x00, 0x04) - } - } - } - - /** - * @notice Verify a Ultra Plonk proof - * @param _proof - The serialized proof - * @param _publicInputs - An array of the public inputs - * @return True if proof is valid, reverts otherwise - */ - function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool) { - loadVerificationKey(N_LOC, OMEGA_INVERSE_LOC); - - uint256 requiredPublicInputCount; - assembly { - requiredPublicInputCount := mload(NUM_INPUTS_LOC) - } - if (requiredPublicInputCount != _publicInputs.length) { - revert PUBLIC_INPUT_COUNT_INVALID(requiredPublicInputCount, _publicInputs.length); - } - - assembly { - let q := 21888242871839275222246405745257275088696311157297823662689037894645226208583 // EC group order - let p := 21888242871839275222246405745257275088548364400416034343698204186575808495617 // Prime field order - - /** - * LOAD PROOF FROM CALLDATA - */ - { - let data_ptr := add(calldataload(0x04), 0x24) - - mstore(W1_Y_LOC, mod(calldataload(data_ptr), q)) - mstore(W1_X_LOC, mod(calldataload(add(data_ptr, 0x20)), q)) - - mstore(W2_Y_LOC, mod(calldataload(add(data_ptr, 0x40)), q)) - mstore(W2_X_LOC, mod(calldataload(add(data_ptr, 0x60)), q)) - - mstore(W3_Y_LOC, mod(calldataload(add(data_ptr, 0x80)), q)) - mstore(W3_X_LOC, mod(calldataload(add(data_ptr, 0xa0)), q)) - - mstore(W4_Y_LOC, mod(calldataload(add(data_ptr, 0xc0)), q)) - mstore(W4_X_LOC, mod(calldataload(add(data_ptr, 0xe0)), q)) - - mstore(S_Y_LOC, mod(calldataload(add(data_ptr, 0x100)), q)) - mstore(S_X_LOC, mod(calldataload(add(data_ptr, 0x120)), q)) - mstore(Z_Y_LOC, mod(calldataload(add(data_ptr, 0x140)), q)) - mstore(Z_X_LOC, mod(calldataload(add(data_ptr, 0x160)), q)) - mstore(Z_LOOKUP_Y_LOC, mod(calldataload(add(data_ptr, 0x180)), q)) - mstore(Z_LOOKUP_X_LOC, mod(calldataload(add(data_ptr, 0x1a0)), q)) - mstore(T1_Y_LOC, mod(calldataload(add(data_ptr, 0x1c0)), q)) - mstore(T1_X_LOC, mod(calldataload(add(data_ptr, 0x1e0)), q)) - - mstore(T2_Y_LOC, mod(calldataload(add(data_ptr, 0x200)), q)) - mstore(T2_X_LOC, mod(calldataload(add(data_ptr, 0x220)), q)) - - mstore(T3_Y_LOC, mod(calldataload(add(data_ptr, 0x240)), q)) - mstore(T3_X_LOC, mod(calldataload(add(data_ptr, 0x260)), q)) - - mstore(T4_Y_LOC, mod(calldataload(add(data_ptr, 0x280)), q)) - mstore(T4_X_LOC, mod(calldataload(add(data_ptr, 0x2a0)), q)) - - mstore(W1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x2c0)), p)) - mstore(W2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x2e0)), p)) - mstore(W3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x300)), p)) - mstore(W4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x320)), p)) - mstore(S_EVAL_LOC, mod(calldataload(add(data_ptr, 0x340)), p)) - mstore(Z_EVAL_LOC, mod(calldataload(add(data_ptr, 0x360)), p)) - mstore(Z_LOOKUP_EVAL_LOC, mod(calldataload(add(data_ptr, 0x380)), p)) - mstore(Q1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x3a0)), p)) - mstore(Q2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x3c0)), p)) - mstore(Q3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x3e0)), p)) - mstore(Q4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x400)), p)) - mstore(QM_EVAL_LOC, mod(calldataload(add(data_ptr, 0x420)), p)) - mstore(QC_EVAL_LOC, mod(calldataload(add(data_ptr, 0x440)), p)) - mstore(QARITH_EVAL_LOC, mod(calldataload(add(data_ptr, 0x460)), p)) - mstore(QSORT_EVAL_LOC, mod(calldataload(add(data_ptr, 0x480)), p)) - mstore(QELLIPTIC_EVAL_LOC, mod(calldataload(add(data_ptr, 0x4a0)), p)) - mstore(QAUX_EVAL_LOC, mod(calldataload(add(data_ptr, 0x4c0)), p)) - - mstore(SIGMA1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x4e0)), p)) - mstore(SIGMA2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x500)), p)) - - mstore(SIGMA3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x520)), p)) - mstore(SIGMA4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x540)), p)) - - mstore(TABLE1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x560)), p)) - mstore(TABLE2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x580)), p)) - mstore(TABLE3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x5a0)), p)) - mstore(TABLE4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x5c0)), p)) - mstore(TABLE_TYPE_EVAL_LOC, mod(calldataload(add(data_ptr, 0x5e0)), p)) - - mstore(ID1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x600)), p)) - mstore(ID2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x620)), p)) - mstore(ID3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x640)), p)) - mstore(ID4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x660)), p)) - - mstore(W1_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x680)), p)) - mstore(W2_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x6a0)), p)) - mstore(W3_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x6c0)), p)) - mstore(W4_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x6e0)), p)) - mstore(S_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x700)), p)) - - mstore(Z_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x720)), p)) - - mstore(Z_LOOKUP_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x740)), p)) - mstore(TABLE1_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x760)), p)) - mstore(TABLE2_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x780)), p)) - mstore(TABLE3_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x7a0)), p)) - mstore(TABLE4_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x7c0)), p)) - - mstore(PI_Z_Y_LOC, mod(calldataload(add(data_ptr, 0x7e0)), q)) - mstore(PI_Z_X_LOC, mod(calldataload(add(data_ptr, 0x800)), q)) - - mstore(PI_Z_OMEGA_Y_LOC, mod(calldataload(add(data_ptr, 0x820)), q)) - mstore(PI_Z_OMEGA_X_LOC, mod(calldataload(add(data_ptr, 0x840)), q)) - } - - /** - * LOAD RECURSIVE PROOF INTO MEMORY - */ - { - if mload(CONTAINS_RECURSIVE_PROOF_LOC) { - let public_inputs_ptr := add(calldataload(0x24), 0x24) - let index_counter := add(shl(5, mload(RECURSIVE_PROOF_PUBLIC_INPUT_INDICES_LOC)), public_inputs_ptr) - - let x0 := calldataload(index_counter) - x0 := add(x0, shl(68, calldataload(add(index_counter, 0x20)))) - x0 := add(x0, shl(136, calldataload(add(index_counter, 0x40)))) - x0 := add(x0, shl(204, calldataload(add(index_counter, 0x60)))) - let y0 := calldataload(add(index_counter, 0x80)) - y0 := add(y0, shl(68, calldataload(add(index_counter, 0xa0)))) - y0 := add(y0, shl(136, calldataload(add(index_counter, 0xc0)))) - y0 := add(y0, shl(204, calldataload(add(index_counter, 0xe0)))) - let x1 := calldataload(add(index_counter, 0x100)) - x1 := add(x1, shl(68, calldataload(add(index_counter, 0x120)))) - x1 := add(x1, shl(136, calldataload(add(index_counter, 0x140)))) - x1 := add(x1, shl(204, calldataload(add(index_counter, 0x160)))) - let y1 := calldataload(add(index_counter, 0x180)) - y1 := add(y1, shl(68, calldataload(add(index_counter, 0x1a0)))) - y1 := add(y1, shl(136, calldataload(add(index_counter, 0x1c0)))) - y1 := add(y1, shl(204, calldataload(add(index_counter, 0x1e0)))) - mstore(RECURSIVE_P1_X_LOC, x0) - mstore(RECURSIVE_P1_Y_LOC, y0) - mstore(RECURSIVE_P2_X_LOC, x1) - mstore(RECURSIVE_P2_Y_LOC, y1) - - // validate these are valid bn128 G1 points - if iszero(and(and(lt(x0, q), lt(x1, q)), and(lt(y0, q), lt(y1, q)))) { - mstore(0x00, PUBLIC_INPUT_INVALID_BN128_G1_POINT_SELECTOR) - revert(0x00, 0x04) - } - } - } - - { - /** - * Generate initial challenge - */ - mstore(0x00, shl(224, mload(N_LOC))) - mstore(0x04, shl(224, mload(NUM_INPUTS_LOC))) - let challenge := keccak256(0x00, 0x08) - - /** - * Generate eta challenge - */ - mstore(PUBLIC_INPUTS_HASH_LOCATION, challenge) - // The public input location is stored at 0x24, we then add 0x24 to skip selector and the length of public inputs - let public_inputs_start := add(calldataload(0x24), 0x24) - // copy the public inputs over - let public_input_size := mul(mload(NUM_INPUTS_LOC), 0x20) - calldatacopy(add(PUBLIC_INPUTS_HASH_LOCATION, 0x20), public_inputs_start, public_input_size) - - // copy W1, W2, W3 into challenge. Each point is 0x40 bytes, so load 0xc0 = 3 * 0x40 bytes (ETA input length) - let w_start := add(calldataload(0x04), 0x24) - calldatacopy(add(add(PUBLIC_INPUTS_HASH_LOCATION, 0x20), public_input_size), w_start, ETA_INPUT_LENGTH) - - // Challenge is the old challenge + public inputs + W1, W2, W3 (0x20 + public_input_size + 0xc0) - let challenge_bytes_size := add(0x20, add(public_input_size, ETA_INPUT_LENGTH)) - - challenge := keccak256(PUBLIC_INPUTS_HASH_LOCATION, challenge_bytes_size) - { - let eta := mod(challenge, p) - mstore(C_ETA_LOC, eta) - mstore(C_ETA_SQR_LOC, mulmod(eta, eta, p)) - mstore(C_ETA_CUBE_LOC, mulmod(mload(C_ETA_SQR_LOC), eta, p)) - } - - /** - * Generate beta challenge - */ - mstore(0x00, challenge) - mstore(0x20, mload(W4_Y_LOC)) - mstore(0x40, mload(W4_X_LOC)) - mstore(0x60, mload(S_Y_LOC)) - mstore(0x80, mload(S_X_LOC)) - challenge := keccak256(0x00, 0xa0) - mstore(C_BETA_LOC, mod(challenge, p)) - - /** - * Generate gamma challenge - */ - mstore(0x00, challenge) - mstore8(0x20, 0x01) - challenge := keccak256(0x00, 0x21) - mstore(C_GAMMA_LOC, mod(challenge, p)) - - /** - * Generate alpha challenge - */ - mstore(0x00, challenge) - mstore(0x20, mload(Z_Y_LOC)) - mstore(0x40, mload(Z_X_LOC)) - mstore(0x60, mload(Z_LOOKUP_Y_LOC)) - mstore(0x80, mload(Z_LOOKUP_X_LOC)) - challenge := keccak256(0x00, 0xa0) - mstore(C_ALPHA_LOC, mod(challenge, p)) - - /** - * Compute and store some powers of alpha for future computations - */ - let alpha := mload(C_ALPHA_LOC) - mstore(C_ALPHA_SQR_LOC, mulmod(alpha, alpha, p)) - mstore(C_ALPHA_CUBE_LOC, mulmod(mload(C_ALPHA_SQR_LOC), alpha, p)) - mstore(C_ALPHA_QUAD_LOC, mulmod(mload(C_ALPHA_CUBE_LOC), alpha, p)) - mstore(C_ALPHA_BASE_LOC, alpha) - - /** - * Generate zeta challenge - */ - mstore(0x00, challenge) - mstore(0x20, mload(T1_Y_LOC)) - mstore(0x40, mload(T1_X_LOC)) - mstore(0x60, mload(T2_Y_LOC)) - mstore(0x80, mload(T2_X_LOC)) - mstore(0xa0, mload(T3_Y_LOC)) - mstore(0xc0, mload(T3_X_LOC)) - mstore(0xe0, mload(T4_Y_LOC)) - mstore(0x100, mload(T4_X_LOC)) - - challenge := keccak256(0x00, 0x120) - - mstore(C_ZETA_LOC, mod(challenge, p)) - mstore(C_CURRENT_LOC, challenge) - } - - /** - * EVALUATE FIELD OPERATIONS - */ - - /** - * COMPUTE PUBLIC INPUT DELTA - * ΔPI = ∏ᵢ∈ℓ(wᵢ + β σ(i) + γ) / ∏ᵢ∈ℓ(wᵢ + β σ'(i) + γ) - */ - { - let beta := mload(C_BETA_LOC) // β - let gamma := mload(C_GAMMA_LOC) // γ - let work_root := mload(OMEGA_LOC) // ω - let numerator_value := 1 - let denominator_value := 1 - - let p_clone := p // move p to the front of the stack - let valid_inputs := true - - // Load the starting point of the public inputs (jump over the selector and the length of public inputs [0x24]) - let public_inputs_ptr := add(calldataload(0x24), 0x24) - - // endpoint_ptr = public_inputs_ptr + num_inputs * 0x20. // every public input is 0x20 bytes - let endpoint_ptr := add(public_inputs_ptr, mul(mload(NUM_INPUTS_LOC), 0x20)) - - // root_1 = β * 0x05 - let root_1 := mulmod(beta, 0x05, p_clone) // k1.β - // root_2 = β * 0x0c - let root_2 := mulmod(beta, 0x0c, p_clone) - // @note 0x05 + 0x07 == 0x0c == external coset generator - - for {} lt(public_inputs_ptr, endpoint_ptr) { public_inputs_ptr := add(public_inputs_ptr, 0x20) } { - /** - * input = public_input[i] - * valid_inputs &= input < p - * temp = input + gamma - * numerator_value *= (β.σ(i) + wᵢ + γ) // σ(i) = 0x05.ωⁱ - * denominator_value *= (β.σ'(i) + wᵢ + γ) // σ'(i) = 0x0c.ωⁱ - * root_1 *= ω - * root_2 *= ω - */ - - let input := calldataload(public_inputs_ptr) - valid_inputs := and(valid_inputs, lt(input, p_clone)) - let temp := addmod(input, gamma, p_clone) - - numerator_value := mulmod(numerator_value, add(root_1, temp), p_clone) - denominator_value := mulmod(denominator_value, add(root_2, temp), p_clone) - - root_1 := mulmod(root_1, work_root, p_clone) - root_2 := mulmod(root_2, work_root, p_clone) - } - - // Revert if not all public inputs are field elements (i.e. < p) - if iszero(valid_inputs) { - mstore(0x00, PUBLIC_INPUT_GE_P_SELECTOR) - revert(0x00, 0x04) - } - - mstore(DELTA_NUMERATOR_LOC, numerator_value) - mstore(DELTA_DENOMINATOR_LOC, denominator_value) - } - - /** - * Compute Plookup delta factor [γ(1 + β)]^{n-k} - * k = num roots cut out of Z_H = 4 - */ - { - let delta_base := mulmod(mload(C_GAMMA_LOC), addmod(mload(C_BETA_LOC), 1, p), p) - let delta_numerator := delta_base - { - let exponent := mload(N_LOC) - let count := 1 - for {} lt(count, exponent) { count := add(count, count) } { - delta_numerator := mulmod(delta_numerator, delta_numerator, p) - } - } - mstore(PLOOKUP_DELTA_NUMERATOR_LOC, delta_numerator) - - let delta_denominator := mulmod(delta_base, delta_base, p) - delta_denominator := mulmod(delta_denominator, delta_denominator, p) - mstore(PLOOKUP_DELTA_DENOMINATOR_LOC, delta_denominator) - } - /** - * Compute lagrange poly and vanishing poly fractions - */ - { - /** - * vanishing_numerator = zeta - * ZETA_POW_N = zeta^n - * vanishing_numerator -= 1 - * accumulating_root = omega_inverse - * work_root = p - accumulating_root - * domain_inverse = domain_inverse - * vanishing_denominator = zeta + work_root - * work_root *= accumulating_root - * vanishing_denominator *= (zeta + work_root) - * work_root *= accumulating_root - * vanishing_denominator *= (zeta + work_root) - * vanishing_denominator *= (zeta + (zeta + accumulating_root)) - * work_root = omega - * lagrange_numerator = vanishing_numerator * domain_inverse - * l_start_denominator = zeta - 1 - * accumulating_root = work_root^2 - * l_end_denominator = accumulating_root^2 * work_root * zeta - 1 - * Note: l_end_denominator term contains a term \omega^5 to cut out 5 roots of unity from vanishing poly - */ - - let zeta := mload(C_ZETA_LOC) - - // compute zeta^n, where n is a power of 2 - let vanishing_numerator := zeta - { - // pow_small - let exponent := mload(N_LOC) - let count := 1 - for {} lt(count, exponent) { count := add(count, count) } { - vanishing_numerator := mulmod(vanishing_numerator, vanishing_numerator, p) - } - } - mstore(ZETA_POW_N_LOC, vanishing_numerator) - vanishing_numerator := addmod(vanishing_numerator, sub(p, 1), p) - - let accumulating_root := mload(OMEGA_INVERSE_LOC) - let work_root := sub(p, accumulating_root) - let domain_inverse := mload(DOMAIN_INVERSE_LOC) - - let vanishing_denominator := addmod(zeta, work_root, p) - work_root := mulmod(work_root, accumulating_root, p) - vanishing_denominator := mulmod(vanishing_denominator, addmod(zeta, work_root, p), p) - work_root := mulmod(work_root, accumulating_root, p) - vanishing_denominator := mulmod(vanishing_denominator, addmod(zeta, work_root, p), p) - vanishing_denominator := - mulmod(vanishing_denominator, addmod(zeta, mulmod(work_root, accumulating_root, p), p), p) - - work_root := mload(OMEGA_LOC) - - let lagrange_numerator := mulmod(vanishing_numerator, domain_inverse, p) - let l_start_denominator := addmod(zeta, sub(p, 1), p) - - accumulating_root := mulmod(work_root, work_root, p) - - let l_end_denominator := - addmod( - mulmod(mulmod(mulmod(accumulating_root, accumulating_root, p), work_root, p), zeta, p), sub(p, 1), p - ) - - /** - * Compute inversions using Montgomery's batch inversion trick - */ - let accumulator := mload(DELTA_DENOMINATOR_LOC) - let t0 := accumulator - accumulator := mulmod(accumulator, vanishing_denominator, p) - let t1 := accumulator - accumulator := mulmod(accumulator, vanishing_numerator, p) - let t2 := accumulator - accumulator := mulmod(accumulator, l_start_denominator, p) - let t3 := accumulator - accumulator := mulmod(accumulator, mload(PLOOKUP_DELTA_DENOMINATOR_LOC), p) - let t4 := accumulator - { - mstore(0, 0x20) - mstore(0x20, 0x20) - mstore(0x40, 0x20) - mstore(0x60, mulmod(accumulator, l_end_denominator, p)) - mstore(0x80, sub(p, 2)) - mstore(0xa0, p) - if iszero(staticcall(gas(), 0x05, 0x00, 0xc0, 0x00, 0x20)) { - mstore(0x0, MOD_EXP_FAILURE_SELECTOR) - revert(0x00, 0x04) - } - accumulator := mload(0x00) - } - - t4 := mulmod(accumulator, t4, p) - accumulator := mulmod(accumulator, l_end_denominator, p) - - t3 := mulmod(accumulator, t3, p) - accumulator := mulmod(accumulator, mload(PLOOKUP_DELTA_DENOMINATOR_LOC), p) - - t2 := mulmod(accumulator, t2, p) - accumulator := mulmod(accumulator, l_start_denominator, p) - - t1 := mulmod(accumulator, t1, p) - accumulator := mulmod(accumulator, vanishing_numerator, p) - - t0 := mulmod(accumulator, t0, p) - accumulator := mulmod(accumulator, vanishing_denominator, p) - - accumulator := mulmod(mulmod(accumulator, accumulator, p), mload(DELTA_DENOMINATOR_LOC), p) - - mstore(PUBLIC_INPUT_DELTA_LOC, mulmod(mload(DELTA_NUMERATOR_LOC), accumulator, p)) - mstore(ZERO_POLY_LOC, mulmod(vanishing_numerator, t0, p)) - mstore(ZERO_POLY_INVERSE_LOC, mulmod(vanishing_denominator, t1, p)) - mstore(L_START_LOC, mulmod(lagrange_numerator, t2, p)) - mstore(PLOOKUP_DELTA_LOC, mulmod(mload(PLOOKUP_DELTA_NUMERATOR_LOC), t3, p)) - mstore(L_END_LOC, mulmod(lagrange_numerator, t4, p)) - } - - /** - * UltraPlonk Widget Ordering: - * - * 1. Permutation widget - * 2. Plookup widget - * 3. Arithmetic widget - * 4. Fixed base widget (?) - * 5. GenPermSort widget - * 6. Elliptic widget - * 7. Auxiliary widget - */ - - /** - * COMPUTE PERMUTATION WIDGET EVALUATION - */ - { - let alpha := mload(C_ALPHA_LOC) - let beta := mload(C_BETA_LOC) - let gamma := mload(C_GAMMA_LOC) - - /** - * t1 = (W1 + gamma + beta * ID1) * (W2 + gamma + beta * ID2) - * t2 = (W3 + gamma + beta * ID3) * (W4 + gamma + beta * ID4) - * result = alpha_base * z_eval * t1 * t2 - * t1 = (W1 + gamma + beta * sigma_1_eval) * (W2 + gamma + beta * sigma_2_eval) - * t2 = (W2 + gamma + beta * sigma_3_eval) * (W3 + gamma + beta * sigma_4_eval) - * result -= (alpha_base * z_omega_eval * t1 * t2) - */ - let t1 := - mulmod( - add(add(mload(W1_EVAL_LOC), gamma), mulmod(beta, mload(ID1_EVAL_LOC), p)), - add(add(mload(W2_EVAL_LOC), gamma), mulmod(beta, mload(ID2_EVAL_LOC), p)), - p - ) - let t2 := - mulmod( - add(add(mload(W3_EVAL_LOC), gamma), mulmod(beta, mload(ID3_EVAL_LOC), p)), - add(add(mload(W4_EVAL_LOC), gamma), mulmod(beta, mload(ID4_EVAL_LOC), p)), - p - ) - let result := mulmod(mload(C_ALPHA_BASE_LOC), mulmod(mload(Z_EVAL_LOC), mulmod(t1, t2, p), p), p) - t1 := - mulmod( - add(add(mload(W1_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA1_EVAL_LOC), p)), - add(add(mload(W2_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA2_EVAL_LOC), p)), - p - ) - t2 := - mulmod( - add(add(mload(W3_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA3_EVAL_LOC), p)), - add(add(mload(W4_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA4_EVAL_LOC), p)), - p - ) - result := - addmod( - result, - sub(p, mulmod(mload(C_ALPHA_BASE_LOC), mulmod(mload(Z_OMEGA_EVAL_LOC), mulmod(t1, t2, p), p), p)), - p - ) - - /** - * alpha_base *= alpha - * result += alpha_base . (L_{n-k}(ʓ) . (z(ʓ.ω) - ∆_{PI})) - * alpha_base *= alpha - * result += alpha_base . (L_1(ʓ)(Z(ʓ) - 1)) - * alpha_Base *= alpha - */ - mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p)) - result := - addmod( - result, - mulmod( - mload(C_ALPHA_BASE_LOC), - mulmod( - mload(L_END_LOC), - addmod(mload(Z_OMEGA_EVAL_LOC), sub(p, mload(PUBLIC_INPUT_DELTA_LOC)), p), - p - ), - p - ), - p - ) - mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p)) - mstore( - PERMUTATION_IDENTITY, - addmod( - result, - mulmod( - mload(C_ALPHA_BASE_LOC), - mulmod(mload(L_START_LOC), addmod(mload(Z_EVAL_LOC), sub(p, 1), p), p), - p - ), - p - ) - ) - mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p)) - } - - /** - * COMPUTE PLOOKUP WIDGET EVALUATION - */ - { - /** - * Goal: f = (w1(z) + q2.w1(zω)) + η(w2(z) + qm.w2(zω)) + η²(w3(z) + qc.w_3(zω)) + q3(z).η³ - * f = η.q3(z) - * f += (w3(z) + qc.w_3(zω)) - * f *= η - * f += (w2(z) + qm.w2(zω)) - * f *= η - * f += (w1(z) + q2.w1(zω)) - */ - let f := mulmod(mload(C_ETA_LOC), mload(Q3_EVAL_LOC), p) - f := - addmod(f, addmod(mload(W3_EVAL_LOC), mulmod(mload(QC_EVAL_LOC), mload(W3_OMEGA_EVAL_LOC), p), p), p) - f := mulmod(f, mload(C_ETA_LOC), p) - f := - addmod(f, addmod(mload(W2_EVAL_LOC), mulmod(mload(QM_EVAL_LOC), mload(W2_OMEGA_EVAL_LOC), p), p), p) - f := mulmod(f, mload(C_ETA_LOC), p) - f := - addmod(f, addmod(mload(W1_EVAL_LOC), mulmod(mload(Q2_EVAL_LOC), mload(W1_OMEGA_EVAL_LOC), p), p), p) - - // t(z) = table4(z).η³ + table3(z).η² + table2(z).η + table1(z) - let t := - addmod( - addmod( - addmod( - mulmod(mload(TABLE4_EVAL_LOC), mload(C_ETA_CUBE_LOC), p), - mulmod(mload(TABLE3_EVAL_LOC), mload(C_ETA_SQR_LOC), p), - p - ), - mulmod(mload(TABLE2_EVAL_LOC), mload(C_ETA_LOC), p), - p - ), - mload(TABLE1_EVAL_LOC), - p - ) - - // t(zw) = table4(zw).η³ + table3(zw).η² + table2(zw).η + table1(zw) - let t_omega := - addmod( - addmod( - addmod( - mulmod(mload(TABLE4_OMEGA_EVAL_LOC), mload(C_ETA_CUBE_LOC), p), - mulmod(mload(TABLE3_OMEGA_EVAL_LOC), mload(C_ETA_SQR_LOC), p), - p - ), - mulmod(mload(TABLE2_OMEGA_EVAL_LOC), mload(C_ETA_LOC), p), - p - ), - mload(TABLE1_OMEGA_EVAL_LOC), - p - ) - - /** - * Goal: numerator = (TABLE_TYPE_EVAL * f(z) + γ) * (t(z) + βt(zω) + γ(β + 1)) * (β + 1) - * gamma_beta_constant = γ(β + 1) - * numerator = f * TABLE_TYPE_EVAL + gamma - * temp0 = t(z) + t(zω) * β + gamma_beta_constant - * numerator *= temp0 - * numerator *= (β + 1) - * temp0 = alpha * l_1 - * numerator += temp0 - * numerator *= z_lookup(z) - * numerator -= temp0 - */ - let gamma_beta_constant := mulmod(mload(C_GAMMA_LOC), addmod(mload(C_BETA_LOC), 1, p), p) - let numerator := addmod(mulmod(f, mload(TABLE_TYPE_EVAL_LOC), p), mload(C_GAMMA_LOC), p) - let temp0 := addmod(addmod(t, mulmod(t_omega, mload(C_BETA_LOC), p), p), gamma_beta_constant, p) - numerator := mulmod(numerator, temp0, p) - numerator := mulmod(numerator, addmod(mload(C_BETA_LOC), 1, p), p) - temp0 := mulmod(mload(C_ALPHA_LOC), mload(L_START_LOC), p) - numerator := addmod(numerator, temp0, p) - numerator := mulmod(numerator, mload(Z_LOOKUP_EVAL_LOC), p) - numerator := addmod(numerator, sub(p, temp0), p) - - /** - * Goal: denominator = z_lookup(zω)*[s(z) + βs(zω) + γ(1 + β)] - [z_lookup(zω) - [γ(1 + β)]^{n-k}]*α²L_end(z) - * note: delta_factor = [γ(1 + β)]^{n-k} - * denominator = s(z) + βs(zω) + γ(β + 1) - * temp1 = α²L_end(z) - * denominator -= temp1 - * denominator *= z_lookup(zω) - * denominator += temp1 * delta_factor - * PLOOKUP_IDENTITY = (numerator - denominator).alpha_base - * alpha_base *= alpha^3 - */ - let denominator := - addmod( - addmod(mload(S_EVAL_LOC), mulmod(mload(S_OMEGA_EVAL_LOC), mload(C_BETA_LOC), p), p), - gamma_beta_constant, - p - ) - let temp1 := mulmod(mload(C_ALPHA_SQR_LOC), mload(L_END_LOC), p) - denominator := addmod(denominator, sub(p, temp1), p) - denominator := mulmod(denominator, mload(Z_LOOKUP_OMEGA_EVAL_LOC), p) - denominator := addmod(denominator, mulmod(temp1, mload(PLOOKUP_DELTA_LOC), p), p) - - mstore(PLOOKUP_IDENTITY, mulmod(addmod(numerator, sub(p, denominator), p), mload(C_ALPHA_BASE_LOC), p)) - - // update alpha - mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_CUBE_LOC), p)) - } - - /** - * COMPUTE ARITHMETIC WIDGET EVALUATION - */ - { - /** - * The basic arithmetic gate identity in standard plonk is as follows. - * (w_1 . w_2 . q_m) + (w_1 . q_1) + (w_2 . q_2) + (w_3 . q_3) + (w_4 . q_4) + q_c = 0 - * However, for Ultraplonk, we extend this to support "passing" wires between rows (shown without alpha scaling below): - * q_arith * ( ( (-1/2) * (q_arith - 3) * q_m * w_1 * w_2 + q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c ) + - * (q_arith - 1)*( α * (q_arith - 2) * (w_1 + w_4 - w_1_omega + q_m) + w_4_omega) ) = 0 - * - * This formula results in several cases depending on q_arith: - * 1. q_arith == 0: Arithmetic gate is completely disabled - * - * 2. q_arith == 1: Everything in the minigate on the right is disabled. The equation is just a standard plonk equation - * with extra wires: q_m * w_1 * w_2 + q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c = 0 - * - * 3. q_arith == 2: The (w_1 + w_4 - ...) term is disabled. THe equation is: - * (1/2) * q_m * w_1 * w_2 + q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c + w_4_omega = 0 - * It allows defining w_4 at next index (w_4_omega) in terms of current wire values - * - * 4. q_arith == 3: The product of w_1 and w_2 is disabled, but a mini addition gate is enabled. α allows us to split - * the equation into two: - * - * q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c + 2 * w_4_omega = 0 - * and - * w_1 + w_4 - w_1_omega + q_m = 0 (we are reusing q_m here) - * - * 5. q_arith > 3: The product of w_1 and w_2 is scaled by (q_arith - 3), while the w_4_omega term is scaled by (q_arith - 1). - * The equation can be split into two: - * - * (q_arith - 3)* q_m * w_1 * w_ 2 + q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c + (q_arith - 1) * w_4_omega = 0 - * and - * w_1 + w_4 - w_1_omega + q_m = 0 - * - * The problem that q_m is used both in both equations can be dealt with by appropriately changing selector values at - * the next gate. Then we can treat (q_arith - 1) as a simulated q_6 selector and scale q_m to handle (q_arith - 3) at - * product. - */ - - let w1q1 := mulmod(mload(W1_EVAL_LOC), mload(Q1_EVAL_LOC), p) - let w2q2 := mulmod(mload(W2_EVAL_LOC), mload(Q2_EVAL_LOC), p) - let w3q3 := mulmod(mload(W3_EVAL_LOC), mload(Q3_EVAL_LOC), p) - let w4q3 := mulmod(mload(W4_EVAL_LOC), mload(Q4_EVAL_LOC), p) - - // @todo - Add a explicit test that hits QARITH == 3 - // w1w2qm := (w_1 . w_2 . q_m . (QARITH_EVAL_LOC - 3)) / 2 - let w1w2qm := - mulmod( - mulmod( - mulmod(mulmod(mload(W1_EVAL_LOC), mload(W2_EVAL_LOC), p), mload(QM_EVAL_LOC), p), - addmod(mload(QARITH_EVAL_LOC), sub(p, 3), p), - p - ), - NEGATIVE_INVERSE_OF_2_MODULO_P, - p - ) - - // (w_1 . w_2 . q_m . (q_arith - 3)) / -2) + (w_1 . q_1) + (w_2 . q_2) + (w_3 . q_3) + (w_4 . q_4) + q_c - let identity := - addmod( - mload(QC_EVAL_LOC), addmod(w4q3, addmod(w3q3, addmod(w2q2, addmod(w1q1, w1w2qm, p), p), p), p), p - ) - - // if q_arith == 3 we evaluate an additional mini addition gate (on top of the regular one), where: - // w_1 + w_4 - w_1_omega + q_m = 0 - // we use this gate to save an addition gate when adding or subtracting non-native field elements - // α * (q_arith - 2) * (w_1 + w_4 - w_1_omega + q_m) - let extra_small_addition_gate_identity := - mulmod( - mload(C_ALPHA_LOC), - mulmod( - addmod(mload(QARITH_EVAL_LOC), sub(p, 2), p), - addmod( - mload(QM_EVAL_LOC), - addmod( - sub(p, mload(W1_OMEGA_EVAL_LOC)), addmod(mload(W1_EVAL_LOC), mload(W4_EVAL_LOC), p), p - ), - p - ), - p - ), - p - ) - - // if q_arith == 2 OR q_arith == 3 we add the 4th wire of the NEXT gate into the arithmetic identity - // N.B. if q_arith > 2, this wire value will be scaled by (q_arith - 1) relative to the other gate wires! - // alpha_base * q_arith * (identity + (q_arith - 1) * (w_4_omega + extra_small_addition_gate_identity)) - mstore( - ARITHMETIC_IDENTITY, - mulmod( - mload(C_ALPHA_BASE_LOC), - mulmod( - mload(QARITH_EVAL_LOC), - addmod( - identity, - mulmod( - addmod(mload(QARITH_EVAL_LOC), sub(p, 1), p), - addmod(mload(W4_OMEGA_EVAL_LOC), extra_small_addition_gate_identity, p), - p - ), - p - ), - p - ), - p - ) - ) - - // update alpha - mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_SQR_LOC), p)) - } - - /** - * COMPUTE GENPERMSORT WIDGET EVALUATION - */ - { - /** - * D1 = (w2 - w1) - * D2 = (w3 - w2) - * D3 = (w4 - w3) - * D4 = (w1_omega - w4) - * - * α_a = alpha_base - * α_b = alpha_base * α - * α_c = alpha_base * α^2 - * α_d = alpha_base * α^3 - * - * range_accumulator = ( - * D1(D1 - 1)(D1 - 2)(D1 - 3).α_a + - * D2(D2 - 1)(D2 - 2)(D2 - 3).α_b + - * D3(D3 - 1)(D3 - 2)(D3 - 3).α_c + - * D4(D4 - 1)(D4 - 2)(D4 - 3).α_d + - * ) . q_sort - */ - let minus_two := sub(p, 2) - let minus_three := sub(p, 3) - let d1 := addmod(mload(W2_EVAL_LOC), sub(p, mload(W1_EVAL_LOC)), p) - let d2 := addmod(mload(W3_EVAL_LOC), sub(p, mload(W2_EVAL_LOC)), p) - let d3 := addmod(mload(W4_EVAL_LOC), sub(p, mload(W3_EVAL_LOC)), p) - let d4 := addmod(mload(W1_OMEGA_EVAL_LOC), sub(p, mload(W4_EVAL_LOC)), p) - - let range_accumulator := - mulmod( - mulmod( - mulmod(addmod(mulmod(d1, d1, p), sub(p, d1), p), addmod(d1, minus_two, p), p), - addmod(d1, minus_three, p), - p - ), - mload(C_ALPHA_BASE_LOC), - p - ) - range_accumulator := - addmod( - range_accumulator, - mulmod( - mulmod( - mulmod(addmod(mulmod(d2, d2, p), sub(p, d2), p), addmod(d2, minus_two, p), p), - addmod(d2, minus_three, p), - p - ), - mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p), - p - ), - p - ) - range_accumulator := - addmod( - range_accumulator, - mulmod( - mulmod( - mulmod(addmod(mulmod(d3, d3, p), sub(p, d3), p), addmod(d3, minus_two, p), p), - addmod(d3, minus_three, p), - p - ), - mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_SQR_LOC), p), - p - ), - p - ) - range_accumulator := - addmod( - range_accumulator, - mulmod( - mulmod( - mulmod(addmod(mulmod(d4, d4, p), sub(p, d4), p), addmod(d4, minus_two, p), p), - addmod(d4, minus_three, p), - p - ), - mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_CUBE_LOC), p), - p - ), - p - ) - range_accumulator := mulmod(range_accumulator, mload(QSORT_EVAL_LOC), p) - - mstore(SORT_IDENTITY, range_accumulator) - - // update alpha - mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_QUAD_LOC), p)) - } - - /** - * COMPUTE ELLIPTIC WIDGET EVALUATION - */ - { - /** - * endo_term = (-x_2) * x_1 * (x_3 * 2 + x_1) * q_beta - * endo_sqr_term = x_2^2 - * endo_sqr_term *= (x_3 - x_1) - * endo_sqr_term *= q_beta^2 - * leftovers = x_2^2 - * leftovers *= x_2 - * leftovers += x_1^2 * (x_3 + x_1) @follow-up Invalid comment in BB widget - * leftovers -= (y_2^2 + y_1^2) - * sign_term = y_2 * y_1 - * sign_term += sign_term - * sign_term *= q_sign - */ - // q_elliptic * (x3 + x2 + x1)(x2 - x1)(x2 - x1) - y2^2 - y1^2 + 2(y2y1)*q_sign = 0 - let x_diff := addmod(mload(X2_EVAL_LOC), sub(p, mload(X1_EVAL_LOC)), p) - let y2_sqr := mulmod(mload(Y2_EVAL_LOC), mload(Y2_EVAL_LOC), p) - let y1_sqr := mulmod(mload(Y1_EVAL_LOC), mload(Y1_EVAL_LOC), p) - let y1y2 := mulmod(mulmod(mload(Y1_EVAL_LOC), mload(Y2_EVAL_LOC), p), mload(QSIGN_LOC), p) - - let x_add_identity := - addmod( - mulmod( - addmod(mload(X3_EVAL_LOC), addmod(mload(X2_EVAL_LOC), mload(X1_EVAL_LOC), p), p), - mulmod(x_diff, x_diff, p), - p - ), - addmod( - sub( - p, - addmod(y2_sqr, y1_sqr, p) - ), - addmod(y1y2, y1y2, p), - p - ), - p - ) - x_add_identity := - mulmod( - mulmod( - x_add_identity, - addmod( - 1, - sub(p, mload(QM_EVAL_LOC)), - p - ), - p - ), - mload(C_ALPHA_BASE_LOC), - p - ) - - // q_elliptic * (x3 + x2 + x1)(x2 - x1)(x2 - x1) - y2^2 - y1^2 + 2(y2y1)*q_sign = 0 - let y1_plus_y3 := addmod( - mload(Y1_EVAL_LOC), - mload(Y3_EVAL_LOC), - p - ) - let y_diff := addmod(mulmod(mload(Y2_EVAL_LOC), mload(QSIGN_LOC), p), sub(p, mload(Y1_EVAL_LOC)), p) - let y_add_identity := - addmod( - mulmod(y1_plus_y3, x_diff, p), - mulmod(addmod(mload(X3_EVAL_LOC), sub(p, mload(X1_EVAL_LOC)), p), y_diff, p), - p - ) - y_add_identity := - mulmod( - mulmod(y_add_identity, addmod(1, sub(p, mload(QM_EVAL_LOC)), p), p), - mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p), - p - ) - - // ELLIPTIC_IDENTITY = (x_identity + y_identity) * Q_ELLIPTIC_EVAL - mstore( - ELLIPTIC_IDENTITY, mulmod(addmod(x_add_identity, y_add_identity, p), mload(QELLIPTIC_EVAL_LOC), p) - ) - } - { - /** - * x_pow_4 = (y_1_sqr - curve_b) * x_1; - * y_1_sqr_mul_4 = y_1_sqr + y_1_sqr; - * y_1_sqr_mul_4 += y_1_sqr_mul_4; - * x_1_pow_4_mul_9 = x_pow_4; - * x_1_pow_4_mul_9 += x_1_pow_4_mul_9; - * x_1_pow_4_mul_9 += x_1_pow_4_mul_9; - * x_1_pow_4_mul_9 += x_1_pow_4_mul_9; - * x_1_pow_4_mul_9 += x_pow_4; - * x_1_sqr_mul_3 = x_1_sqr + x_1_sqr + x_1_sqr; - * x_double_identity = (x_3 + x_1 + x_1) * y_1_sqr_mul_4 - x_1_pow_4_mul_9; - * y_double_identity = x_1_sqr_mul_3 * (x_1 - x_3) - (y_1 + y_1) * (y_1 + y_3); - */ - // (x3 + x1 + x1) (4y1*y1) - 9 * x1 * x1 * x1 * x1 = 0 - let x1_sqr := mulmod(mload(X1_EVAL_LOC), mload(X1_EVAL_LOC), p) - let y1_sqr := mulmod(mload(Y1_EVAL_LOC), mload(Y1_EVAL_LOC), p) - let x_pow_4 := mulmod(addmod(y1_sqr, GRUMPKIN_CURVE_B_PARAMETER_NEGATED, p), mload(X1_EVAL_LOC), p) - let y1_sqr_mul_4 := mulmod(y1_sqr, 4, p) - let x1_pow_4_mul_9 := mulmod(x_pow_4, 9, p) - let x1_sqr_mul_3 := mulmod(x1_sqr, 3, p) - let x_double_identity := - addmod( - mulmod( - addmod(mload(X3_EVAL_LOC), addmod(mload(X1_EVAL_LOC), mload(X1_EVAL_LOC), p), p), - y1_sqr_mul_4, - p - ), - sub(p, x1_pow_4_mul_9), - p - ) - // (y1 + y1) (2y1) - (3 * x1 * x1)(x1 - x3) = 0 - let y_double_identity := - addmod( - mulmod(x1_sqr_mul_3, addmod(mload(X1_EVAL_LOC), sub(p, mload(X3_EVAL_LOC)), p), p), - sub( - p, - mulmod( - addmod(mload(Y1_EVAL_LOC), mload(Y1_EVAL_LOC), p), - addmod(mload(Y1_EVAL_LOC), mload(Y3_EVAL_LOC), p), - p - ) - ), - p - ) - x_double_identity := mulmod(x_double_identity, mload(C_ALPHA_BASE_LOC), p) - y_double_identity := - mulmod(y_double_identity, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p), p) - x_double_identity := mulmod(x_double_identity, mload(QM_EVAL_LOC), p) - y_double_identity := mulmod(y_double_identity, mload(QM_EVAL_LOC), p) - // ELLIPTIC_IDENTITY += (x_double_identity + y_double_identity) * Q_DOUBLE_EVAL - mstore( - ELLIPTIC_IDENTITY, - addmod( - mload(ELLIPTIC_IDENTITY), - mulmod(addmod(x_double_identity, y_double_identity, p), mload(QELLIPTIC_EVAL_LOC), p), - p - ) - ) - - // update alpha - mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_QUAD_LOC), p)) - } - - /** - * COMPUTE AUXILIARY WIDGET EVALUATION - */ - { - { - /** - * Non native field arithmetic gate 2 - * _ _ - * / _ _ _ 14 \ - * q_2 . q_4 | (w_1 . w_2) + (w_1 . w_2) + (w_1 . w_4 + w_2 . w_3 - w_3) . 2 - w_3 - w_4 | - * \_ _/ - * - * limb_subproduct = w_1 . w_2_omega + w_1_omega . w_2 - * non_native_field_gate_2 = w_1 * w_4 + w_4 * w_3 - w_3_omega - * non_native_field_gate_2 = non_native_field_gate_2 * limb_size - * non_native_field_gate_2 -= w_4_omega - * non_native_field_gate_2 += limb_subproduct - * non_native_field_gate_2 *= q_4 - * limb_subproduct *= limb_size - * limb_subproduct += w_1_omega * w_2_omega - * non_native_field_gate_1 = (limb_subproduct + w_3 + w_4) * q_3 - * non_native_field_gate_3 = (limb_subproduct + w_4 - (w_3_omega + w_4_omega)) * q_m - * non_native_field_identity = (non_native_field_gate_1 + non_native_field_gate_2 + non_native_field_gate_3) * q_2 - */ - - let limb_subproduct := - addmod( - mulmod(mload(W1_EVAL_LOC), mload(W2_OMEGA_EVAL_LOC), p), - mulmod(mload(W1_OMEGA_EVAL_LOC), mload(W2_EVAL_LOC), p), - p - ) - - let non_native_field_gate_2 := - addmod( - addmod( - mulmod(mload(W1_EVAL_LOC), mload(W4_EVAL_LOC), p), - mulmod(mload(W2_EVAL_LOC), mload(W3_EVAL_LOC), p), - p - ), - sub(p, mload(W3_OMEGA_EVAL_LOC)), - p - ) - non_native_field_gate_2 := mulmod(non_native_field_gate_2, LIMB_SIZE, p) - non_native_field_gate_2 := addmod(non_native_field_gate_2, sub(p, mload(W4_OMEGA_EVAL_LOC)), p) - non_native_field_gate_2 := addmod(non_native_field_gate_2, limb_subproduct, p) - non_native_field_gate_2 := mulmod(non_native_field_gate_2, mload(Q4_EVAL_LOC), p) - limb_subproduct := mulmod(limb_subproduct, LIMB_SIZE, p) - limb_subproduct := - addmod(limb_subproduct, mulmod(mload(W1_OMEGA_EVAL_LOC), mload(W2_OMEGA_EVAL_LOC), p), p) - let non_native_field_gate_1 := - mulmod( - addmod(limb_subproduct, sub(p, addmod(mload(W3_EVAL_LOC), mload(W4_EVAL_LOC), p)), p), - mload(Q3_EVAL_LOC), - p - ) - let non_native_field_gate_3 := - mulmod( - addmod( - addmod(limb_subproduct, mload(W4_EVAL_LOC), p), - sub(p, addmod(mload(W3_OMEGA_EVAL_LOC), mload(W4_OMEGA_EVAL_LOC), p)), - p - ), - mload(QM_EVAL_LOC), - p - ) - let non_native_field_identity := - mulmod( - addmod(addmod(non_native_field_gate_1, non_native_field_gate_2, p), non_native_field_gate_3, p), - mload(Q2_EVAL_LOC), - p - ) - - mstore(AUX_NON_NATIVE_FIELD_EVALUATION, non_native_field_identity) - } - - { - /** - * limb_accumulator_1 = w_2_omega; - * limb_accumulator_1 *= SUBLIMB_SHIFT; - * limb_accumulator_1 += w_1_omega; - * limb_accumulator_1 *= SUBLIMB_SHIFT; - * limb_accumulator_1 += w_3; - * limb_accumulator_1 *= SUBLIMB_SHIFT; - * limb_accumulator_1 += w_2; - * limb_accumulator_1 *= SUBLIMB_SHIFT; - * limb_accumulator_1 += w_1; - * limb_accumulator_1 -= w_4; - * limb_accumulator_1 *= q_4; - */ - let limb_accumulator_1 := mulmod(mload(W2_OMEGA_EVAL_LOC), SUBLIMB_SHIFT, p) - limb_accumulator_1 := addmod(limb_accumulator_1, mload(W1_OMEGA_EVAL_LOC), p) - limb_accumulator_1 := mulmod(limb_accumulator_1, SUBLIMB_SHIFT, p) - limb_accumulator_1 := addmod(limb_accumulator_1, mload(W3_EVAL_LOC), p) - limb_accumulator_1 := mulmod(limb_accumulator_1, SUBLIMB_SHIFT, p) - limb_accumulator_1 := addmod(limb_accumulator_1, mload(W2_EVAL_LOC), p) - limb_accumulator_1 := mulmod(limb_accumulator_1, SUBLIMB_SHIFT, p) - limb_accumulator_1 := addmod(limb_accumulator_1, mload(W1_EVAL_LOC), p) - limb_accumulator_1 := addmod(limb_accumulator_1, sub(p, mload(W4_EVAL_LOC)), p) - limb_accumulator_1 := mulmod(limb_accumulator_1, mload(Q4_EVAL_LOC), p) - - /** - * limb_accumulator_2 = w_3_omega; - * limb_accumulator_2 *= SUBLIMB_SHIFT; - * limb_accumulator_2 += w_2_omega; - * limb_accumulator_2 *= SUBLIMB_SHIFT; - * limb_accumulator_2 += w_1_omega; - * limb_accumulator_2 *= SUBLIMB_SHIFT; - * limb_accumulator_2 += w_4; - * limb_accumulator_2 *= SUBLIMB_SHIFT; - * limb_accumulator_2 += w_3; - * limb_accumulator_2 -= w_4_omega; - * limb_accumulator_2 *= q_m; - */ - let limb_accumulator_2 := mulmod(mload(W3_OMEGA_EVAL_LOC), SUBLIMB_SHIFT, p) - limb_accumulator_2 := addmod(limb_accumulator_2, mload(W2_OMEGA_EVAL_LOC), p) - limb_accumulator_2 := mulmod(limb_accumulator_2, SUBLIMB_SHIFT, p) - limb_accumulator_2 := addmod(limb_accumulator_2, mload(W1_OMEGA_EVAL_LOC), p) - limb_accumulator_2 := mulmod(limb_accumulator_2, SUBLIMB_SHIFT, p) - limb_accumulator_2 := addmod(limb_accumulator_2, mload(W4_EVAL_LOC), p) - limb_accumulator_2 := mulmod(limb_accumulator_2, SUBLIMB_SHIFT, p) - limb_accumulator_2 := addmod(limb_accumulator_2, mload(W3_EVAL_LOC), p) - limb_accumulator_2 := addmod(limb_accumulator_2, sub(p, mload(W4_OMEGA_EVAL_LOC)), p) - limb_accumulator_2 := mulmod(limb_accumulator_2, mload(QM_EVAL_LOC), p) - - mstore( - AUX_LIMB_ACCUMULATOR_EVALUATION, - mulmod(addmod(limb_accumulator_1, limb_accumulator_2, p), mload(Q3_EVAL_LOC), p) - ) - } - - { - /** - * memory_record_check = w_3; - * memory_record_check *= eta; - * memory_record_check += w_2; - * memory_record_check *= eta; - * memory_record_check += w_1; - * memory_record_check *= eta; - * memory_record_check += q_c; - * - * partial_record_check = memory_record_check; - * - * memory_record_check -= w_4; - */ - - let memory_record_check := mulmod(mload(W3_EVAL_LOC), mload(C_ETA_LOC), p) - memory_record_check := addmod(memory_record_check, mload(W2_EVAL_LOC), p) - memory_record_check := mulmod(memory_record_check, mload(C_ETA_LOC), p) - memory_record_check := addmod(memory_record_check, mload(W1_EVAL_LOC), p) - memory_record_check := mulmod(memory_record_check, mload(C_ETA_LOC), p) - memory_record_check := addmod(memory_record_check, mload(QC_EVAL_LOC), p) - - let partial_record_check := memory_record_check - memory_record_check := addmod(memory_record_check, sub(p, mload(W4_EVAL_LOC)), p) - - mstore(AUX_MEMORY_EVALUATION, memory_record_check) - - // index_delta = w_1_omega - w_1 - let index_delta := addmod(mload(W1_OMEGA_EVAL_LOC), sub(p, mload(W1_EVAL_LOC)), p) - // record_delta = w_4_omega - w_4 - let record_delta := addmod(mload(W4_OMEGA_EVAL_LOC), sub(p, mload(W4_EVAL_LOC)), p) - // index_is_monotonically_increasing = index_delta * (index_delta - 1) - let index_is_monotonically_increasing := mulmod(index_delta, addmod(index_delta, sub(p, 1), p), p) - - // adjacent_values_match_if_adjacent_indices_match = record_delta * (1 - index_delta) - let adjacent_values_match_if_adjacent_indices_match := - mulmod(record_delta, addmod(1, sub(p, index_delta), p), p) - - // AUX_ROM_CONSISTENCY_EVALUATION = ((adjacent_values_match_if_adjacent_indices_match * alpha) + index_is_monotonically_increasing) * alpha + partial_record_check - mstore( - AUX_ROM_CONSISTENCY_EVALUATION, - addmod( - mulmod( - addmod( - mulmod(adjacent_values_match_if_adjacent_indices_match, mload(C_ALPHA_LOC), p), - index_is_monotonically_increasing, - p - ), - mload(C_ALPHA_LOC), - p - ), - memory_record_check, - p - ) - ) - - { - /** - * next_gate_access_type = w_3_omega; - * next_gate_access_type *= eta; - * next_gate_access_type += w_2_omega; - * next_gate_access_type *= eta; - * next_gate_access_type += w_1_omega; - * next_gate_access_type *= eta; - * next_gate_access_type = w_4_omega - next_gate_access_type; - */ - let next_gate_access_type := mulmod(mload(W3_OMEGA_EVAL_LOC), mload(C_ETA_LOC), p) - next_gate_access_type := addmod(next_gate_access_type, mload(W2_OMEGA_EVAL_LOC), p) - next_gate_access_type := mulmod(next_gate_access_type, mload(C_ETA_LOC), p) - next_gate_access_type := addmod(next_gate_access_type, mload(W1_OMEGA_EVAL_LOC), p) - next_gate_access_type := mulmod(next_gate_access_type, mload(C_ETA_LOC), p) - next_gate_access_type := addmod(mload(W4_OMEGA_EVAL_LOC), sub(p, next_gate_access_type), p) - - // value_delta = w_3_omega - w_3 - let value_delta := addmod(mload(W3_OMEGA_EVAL_LOC), sub(p, mload(W3_EVAL_LOC)), p) - // adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation = (1 - index_delta) * value_delta * (1 - next_gate_access_type); - - let adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation := - mulmod( - addmod(1, sub(p, index_delta), p), - mulmod(value_delta, addmod(1, sub(p, next_gate_access_type), p), p), - p - ) - - // AUX_RAM_CONSISTENCY_EVALUATION - - /** - * access_type = w_4 - partial_record_check - * access_check = access_type^2 - access_type - * next_gate_access_type_is_boolean = next_gate_access_type^2 - next_gate_access_type - * RAM_consistency_check_identity = adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation; - * RAM_consistency_check_identity *= alpha; - * RAM_consistency_check_identity += index_is_monotonically_increasing; - * RAM_consistency_check_identity *= alpha; - * RAM_consistency_check_identity += next_gate_access_type_is_boolean; - * RAM_consistency_check_identity *= alpha; - * RAM_consistency_check_identity += access_check; - */ - - let access_type := addmod(mload(W4_EVAL_LOC), sub(p, partial_record_check), p) - let access_check := mulmod(access_type, addmod(access_type, sub(p, 1), p), p) - let next_gate_access_type_is_boolean := - mulmod(next_gate_access_type, addmod(next_gate_access_type, sub(p, 1), p), p) - let RAM_cci := - mulmod( - adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation, - mload(C_ALPHA_LOC), - p - ) - RAM_cci := addmod(RAM_cci, index_is_monotonically_increasing, p) - RAM_cci := mulmod(RAM_cci, mload(C_ALPHA_LOC), p) - RAM_cci := addmod(RAM_cci, next_gate_access_type_is_boolean, p) - RAM_cci := mulmod(RAM_cci, mload(C_ALPHA_LOC), p) - RAM_cci := addmod(RAM_cci, access_check, p) - - mstore(AUX_RAM_CONSISTENCY_EVALUATION, RAM_cci) - } - - { - // timestamp_delta = w_2_omega - w_2 - let timestamp_delta := addmod(mload(W2_OMEGA_EVAL_LOC), sub(p, mload(W2_EVAL_LOC)), p) - - // RAM_timestamp_check_identity = (1 - index_delta) * timestamp_delta - w_3 - let RAM_timestamp_check_identity := - addmod( - mulmod(timestamp_delta, addmod(1, sub(p, index_delta), p), p), sub(p, mload(W3_EVAL_LOC)), p - ) - - /** - * memory_identity = ROM_consistency_check_identity * q_2; - * memory_identity += RAM_timestamp_check_identity * q_4; - * memory_identity += memory_record_check * q_m; - * memory_identity *= q_1; - * memory_identity += (RAM_consistency_check_identity * q_arith); - * - * auxiliary_identity = memory_identity + non_native_field_identity + limb_accumulator_identity; - * auxiliary_identity *= q_aux; - * auxiliary_identity *= alpha_base; - */ - let memory_identity := mulmod(mload(AUX_ROM_CONSISTENCY_EVALUATION), mload(Q2_EVAL_LOC), p) - memory_identity := - addmod(memory_identity, mulmod(RAM_timestamp_check_identity, mload(Q4_EVAL_LOC), p), p) - memory_identity := - addmod(memory_identity, mulmod(mload(AUX_MEMORY_EVALUATION), mload(QM_EVAL_LOC), p), p) - memory_identity := mulmod(memory_identity, mload(Q1_EVAL_LOC), p) - memory_identity := - addmod( - memory_identity, mulmod(mload(AUX_RAM_CONSISTENCY_EVALUATION), mload(QARITH_EVAL_LOC), p), p - ) - - let auxiliary_identity := addmod(memory_identity, mload(AUX_NON_NATIVE_FIELD_EVALUATION), p) - auxiliary_identity := addmod(auxiliary_identity, mload(AUX_LIMB_ACCUMULATOR_EVALUATION), p) - auxiliary_identity := mulmod(auxiliary_identity, mload(QAUX_EVAL_LOC), p) - auxiliary_identity := mulmod(auxiliary_identity, mload(C_ALPHA_BASE_LOC), p) - - mstore(AUX_IDENTITY, auxiliary_identity) - - // update alpha - mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_CUBE_LOC), p)) - } - } - } - - { - /** - * quotient = ARITHMETIC_IDENTITY - * quotient += PERMUTATION_IDENTITY - * quotient += PLOOKUP_IDENTITY - * quotient += SORT_IDENTITY - * quotient += ELLIPTIC_IDENTITY - * quotient += AUX_IDENTITY - * quotient *= ZERO_POLY_INVERSE - */ - mstore( - QUOTIENT_EVAL_LOC, - mulmod( - addmod( - addmod( - addmod( - addmod( - addmod(mload(PERMUTATION_IDENTITY), mload(PLOOKUP_IDENTITY), p), - mload(ARITHMETIC_IDENTITY), - p - ), - mload(SORT_IDENTITY), - p - ), - mload(ELLIPTIC_IDENTITY), - p - ), - mload(AUX_IDENTITY), - p - ), - mload(ZERO_POLY_INVERSE_LOC), - p - ) - ) - } - - /** - * GENERATE NU AND SEPARATOR CHALLENGES - */ - { - let current_challenge := mload(C_CURRENT_LOC) - // get a calldata pointer that points to the start of the data we want to copy - let calldata_ptr := add(calldataload(0x04), 0x24) - - calldata_ptr := add(calldata_ptr, NU_CALLDATA_SKIP_LENGTH) - - mstore(NU_CHALLENGE_INPUT_LOC_A, current_challenge) - mstore(NU_CHALLENGE_INPUT_LOC_B, mload(QUOTIENT_EVAL_LOC)) - calldatacopy(NU_CHALLENGE_INPUT_LOC_C, calldata_ptr, NU_INPUT_LENGTH) - - // hash length = (0x20 + num field elements), we include the previous challenge in the hash - let challenge := keccak256(NU_CHALLENGE_INPUT_LOC_A, add(NU_INPUT_LENGTH, 0x40)) - - mstore(C_V0_LOC, mod(challenge, p)) - // We need THIRTY-ONE independent nu challenges! - mstore(0x00, challenge) - mstore8(0x20, 0x01) - mstore(C_V1_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x02) - mstore(C_V2_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x03) - mstore(C_V3_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x04) - mstore(C_V4_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x05) - mstore(C_V5_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x06) - mstore(C_V6_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x07) - mstore(C_V7_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x08) - mstore(C_V8_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x09) - mstore(C_V9_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x0a) - mstore(C_V10_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x0b) - mstore(C_V11_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x0c) - mstore(C_V12_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x0d) - mstore(C_V13_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x0e) - mstore(C_V14_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x0f) - mstore(C_V15_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x10) - mstore(C_V16_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x11) - mstore(C_V17_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x12) - mstore(C_V18_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x13) - mstore(C_V19_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x14) - mstore(C_V20_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x15) - mstore(C_V21_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x16) - mstore(C_V22_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x17) - mstore(C_V23_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x18) - mstore(C_V24_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x19) - mstore(C_V25_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x1a) - mstore(C_V26_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x1b) - mstore(C_V27_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x1c) - mstore(C_V28_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x1d) - mstore(C_V29_LOC, mod(keccak256(0x00, 0x21), p)) - - // @follow-up - Why are both v29 and v30 using appending 0x1d to the prior challenge and hashing, should it not change? - mstore8(0x20, 0x1d) - challenge := keccak256(0x00, 0x21) - mstore(C_V30_LOC, mod(challenge, p)) - - // separator - mstore(0x00, challenge) - mstore(0x20, mload(PI_Z_Y_LOC)) - mstore(0x40, mload(PI_Z_X_LOC)) - mstore(0x60, mload(PI_Z_OMEGA_Y_LOC)) - mstore(0x80, mload(PI_Z_OMEGA_X_LOC)) - - mstore(C_U_LOC, mod(keccak256(0x00, 0xa0), p)) - } - - let success := 0 - // VALIDATE T1 - { - let x := mload(T1_X_LOC) - let y := mload(T1_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(ACCUMULATOR_X_LOC, x) - mstore(add(ACCUMULATOR_X_LOC, 0x20), y) - } - // VALIDATE T2 - { - let x := mload(T2_X_LOC) // 0x1400 - let y := mload(T2_Y_LOC) // 0x1420 - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(ZETA_POW_N_LOC)) - // accumulator_2 = [T2].zeta^n - success := staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40) - // accumulator = [T1] + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE T3 - { - let x := mload(T3_X_LOC) - let y := mload(T3_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(mload(ZETA_POW_N_LOC), mload(ZETA_POW_N_LOC), p)) - // accumulator_2 = [T3].zeta^{2n} - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE T4 - { - let x := mload(T4_X_LOC) - let y := mload(T4_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(mulmod(mload(ZETA_POW_N_LOC), mload(ZETA_POW_N_LOC), p), mload(ZETA_POW_N_LOC), p)) - // accumulator_2 = [T4].zeta^{3n} - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE W1 - { - let x := mload(W1_X_LOC) - let y := mload(W1_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V0_LOC), p)) - // accumulator_2 = v0.(u + 1).[W1] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE W2 - { - let x := mload(W2_X_LOC) - let y := mload(W2_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V1_LOC), p)) - // accumulator_2 = v1.(u + 1).[W2] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE W3 - { - let x := mload(W3_X_LOC) - let y := mload(W3_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V2_LOC), p)) - // accumulator_2 = v2.(u + 1).[W3] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE W4 - { - let x := mload(W4_X_LOC) - let y := mload(W4_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V3_LOC), p)) - // accumulator_2 = v3.(u + 1).[W4] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE S - { - let x := mload(S_X_LOC) - let y := mload(S_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V4_LOC), p)) - // accumulator_2 = v4.(u + 1).[S] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE Z - { - let x := mload(Z_X_LOC) - let y := mload(Z_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V5_LOC), p)) - // accumulator_2 = v5.(u + 1).[Z] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE Z_LOOKUP - { - let x := mload(Z_LOOKUP_X_LOC) - let y := mload(Z_LOOKUP_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V6_LOC), p)) - // accumulator_2 = v6.(u + 1).[Z_LOOKUP] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE Q1 - { - let x := mload(Q1_X_LOC) - let y := mload(Q1_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V7_LOC)) - // accumulator_2 = v7.[Q1] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE Q2 - { - let x := mload(Q2_X_LOC) - let y := mload(Q2_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V8_LOC)) - // accumulator_2 = v8.[Q2] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE Q3 - { - let x := mload(Q3_X_LOC) - let y := mload(Q3_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V9_LOC)) - // accumulator_2 = v9.[Q3] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE Q4 - { - let x := mload(Q4_X_LOC) - let y := mload(Q4_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V10_LOC)) - // accumulator_2 = v10.[Q4] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE QM - { - let x := mload(QM_X_LOC) - let y := mload(QM_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V11_LOC)) - // accumulator_2 = v11.[Q;] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE QC - { - let x := mload(QC_X_LOC) - let y := mload(QC_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V12_LOC)) - // accumulator_2 = v12.[QC] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE QARITH - { - let x := mload(QARITH_X_LOC) - let y := mload(QARITH_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V13_LOC)) - // accumulator_2 = v13.[QARITH] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE QSORT - { - let x := mload(QSORT_X_LOC) - let y := mload(QSORT_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V14_LOC)) - // accumulator_2 = v14.[QSORT] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE QELLIPTIC - { - let x := mload(QELLIPTIC_X_LOC) - let y := mload(QELLIPTIC_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V15_LOC)) - // accumulator_2 = v15.[QELLIPTIC] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE QAUX - { - let x := mload(QAUX_X_LOC) - let y := mload(QAUX_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V16_LOC)) - // accumulator_2 = v15.[Q_AUX] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE SIGMA1 - { - let x := mload(SIGMA1_X_LOC) - let y := mload(SIGMA1_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V17_LOC)) - // accumulator_2 = v17.[sigma1] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE SIGMA2 - { - let x := mload(SIGMA2_X_LOC) - let y := mload(SIGMA2_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V18_LOC)) - // accumulator_2 = v18.[sigma2] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE SIGMA3 - { - let x := mload(SIGMA3_X_LOC) - let y := mload(SIGMA3_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V19_LOC)) - // accumulator_2 = v19.[sigma3] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE SIGMA4 - { - let x := mload(SIGMA4_X_LOC) - let y := mload(SIGMA4_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V20_LOC)) - // accumulator_2 = v20.[sigma4] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE TABLE1 - { - let x := mload(TABLE1_X_LOC) - let y := mload(TABLE1_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V21_LOC), p)) - // accumulator_2 = u.[table1] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE TABLE2 - { - let x := mload(TABLE2_X_LOC) - let y := mload(TABLE2_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V22_LOC), p)) - // accumulator_2 = u.[table2] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE TABLE3 - { - let x := mload(TABLE3_X_LOC) - let y := mload(TABLE3_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V23_LOC), p)) - // accumulator_2 = u.[table3] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE TABLE4 - { - let x := mload(TABLE4_X_LOC) - let y := mload(TABLE4_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V24_LOC), p)) - // accumulator_2 = u.[table4] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE TABLE_TYPE - { - let x := mload(TABLE_TYPE_X_LOC) - let y := mload(TABLE_TYPE_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V25_LOC)) - // accumulator_2 = v25.[TableType] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE ID1 - { - let x := mload(ID1_X_LOC) - let y := mload(ID1_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V26_LOC)) - // accumulator_2 = v26.[ID1] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE ID2 - { - let x := mload(ID2_X_LOC) - let y := mload(ID2_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V27_LOC)) - // accumulator_2 = v27.[ID2] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE ID3 - { - let x := mload(ID3_X_LOC) - let y := mload(ID3_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V28_LOC)) - // accumulator_2 = v28.[ID3] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE ID4 - { - let x := mload(ID4_X_LOC) - let y := mload(ID4_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V29_LOC)) - // accumulator_2 = v29.[ID4] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - /** - * COMPUTE BATCH EVALUATION SCALAR MULTIPLIER - */ - { - /** - * batch_evaluation = v0 * (w_1_omega * u + w_1_eval) - * batch_evaluation += v1 * (w_2_omega * u + w_2_eval) - * batch_evaluation += v2 * (w_3_omega * u + w_3_eval) - * batch_evaluation += v3 * (w_4_omega * u + w_4_eval) - * batch_evaluation += v4 * (s_omega_eval * u + s_eval) - * batch_evaluation += v5 * (z_omega_eval * u + z_eval) - * batch_evaluation += v6 * (z_lookup_omega_eval * u + z_lookup_eval) - */ - let batch_evaluation := - mulmod( - mload(C_V0_LOC), - addmod(mulmod(mload(W1_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W1_EVAL_LOC), p), - p - ) - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V1_LOC), - addmod(mulmod(mload(W2_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W2_EVAL_LOC), p), - p - ), - p - ) - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V2_LOC), - addmod(mulmod(mload(W3_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W3_EVAL_LOC), p), - p - ), - p - ) - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V3_LOC), - addmod(mulmod(mload(W4_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W4_EVAL_LOC), p), - p - ), - p - ) - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V4_LOC), - addmod(mulmod(mload(S_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(S_EVAL_LOC), p), - p - ), - p - ) - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V5_LOC), - addmod(mulmod(mload(Z_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(Z_EVAL_LOC), p), - p - ), - p - ) - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V6_LOC), - addmod(mulmod(mload(Z_LOOKUP_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(Z_LOOKUP_EVAL_LOC), p), - p - ), - p - ) - - /** - * batch_evaluation += v7 * Q1_EVAL - * batch_evaluation += v8 * Q2_EVAL - * batch_evaluation += v9 * Q3_EVAL - * batch_evaluation += v10 * Q4_EVAL - * batch_evaluation += v11 * QM_EVAL - * batch_evaluation += v12 * QC_EVAL - * batch_evaluation += v13 * QARITH_EVAL - * batch_evaluation += v14 * QSORT_EVAL_LOC - * batch_evaluation += v15 * QELLIPTIC_EVAL_LOC - * batch_evaluation += v16 * QAUX_EVAL_LOC - * batch_evaluation += v17 * SIGMA1_EVAL_LOC - * batch_evaluation += v18 * SIGMA2_EVAL_LOC - * batch_evaluation += v19 * SIGMA3_EVAL_LOC - * batch_evaluation += v20 * SIGMA4_EVAL_LOC - */ - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V7_LOC), mload(Q1_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V8_LOC), mload(Q2_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V9_LOC), mload(Q3_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V10_LOC), mload(Q4_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V11_LOC), mload(QM_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V12_LOC), mload(QC_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V13_LOC), mload(QARITH_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V14_LOC), mload(QSORT_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V15_LOC), mload(QELLIPTIC_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V16_LOC), mload(QAUX_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V17_LOC), mload(SIGMA1_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V18_LOC), mload(SIGMA2_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V19_LOC), mload(SIGMA3_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V20_LOC), mload(SIGMA4_EVAL_LOC), p), p) - - /** - * batch_evaluation += v21 * (table1(zw) * u + table1(z)) - * batch_evaluation += v22 * (table2(zw) * u + table2(z)) - * batch_evaluation += v23 * (table3(zw) * u + table3(z)) - * batch_evaluation += v24 * (table4(zw) * u + table4(z)) - * batch_evaluation += v25 * table_type_eval - * batch_evaluation += v26 * id1_eval - * batch_evaluation += v27 * id2_eval - * batch_evaluation += v28 * id3_eval - * batch_evaluation += v29 * id4_eval - * batch_evaluation += quotient_eval - */ - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V21_LOC), - addmod(mulmod(mload(TABLE1_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE1_EVAL_LOC), p), - p - ), - p - ) - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V22_LOC), - addmod(mulmod(mload(TABLE2_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE2_EVAL_LOC), p), - p - ), - p - ) - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V23_LOC), - addmod(mulmod(mload(TABLE3_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE3_EVAL_LOC), p), - p - ), - p - ) - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V24_LOC), - addmod(mulmod(mload(TABLE4_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE4_EVAL_LOC), p), - p - ), - p - ) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V25_LOC), mload(TABLE_TYPE_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V26_LOC), mload(ID1_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V27_LOC), mload(ID2_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V28_LOC), mload(ID3_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V29_LOC), mload(ID4_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mload(QUOTIENT_EVAL_LOC), p) - - mstore(0x00, 0x01) // [1].x - mstore(0x20, 0x02) // [1].y - mstore(0x40, sub(p, batch_evaluation)) - // accumulator_2 = -[1].(batch_evaluation) - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - if iszero(success) { - mstore(0x0, OPENING_COMMITMENT_FAILED_SELECTOR) - revert(0x00, 0x04) - } - } - - /** - * PERFORM PAIRING PREAMBLE - */ - { - let u := mload(C_U_LOC) - let zeta := mload(C_ZETA_LOC) - // VALIDATE PI_Z - { - let x := mload(PI_Z_X_LOC) - let y := mload(PI_Z_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - // compute zeta.[PI_Z] and add into accumulator - mstore(0x40, zeta) - success := staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE PI_Z_OMEGA - { - let x := mload(PI_Z_OMEGA_X_LOC) - let y := mload(PI_Z_OMEGA_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(mulmod(u, zeta, p), mload(OMEGA_LOC), p)) - // accumulator_2 = u.zeta.omega.[PI_Z_OMEGA] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // PAIRING_RHS = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, PAIRING_RHS_X_LOC, 0x40)) - - mstore(0x00, mload(PI_Z_X_LOC)) - mstore(0x20, mload(PI_Z_Y_LOC)) - mstore(0x40, mload(PI_Z_OMEGA_X_LOC)) - mstore(0x60, mload(PI_Z_OMEGA_Y_LOC)) - mstore(0x80, u) - success := and(success, staticcall(gas(), 7, 0x40, 0x60, 0x40, 0x40)) - // PAIRING_LHS = [PI_Z] + [PI_Z_OMEGA] * u - success := and(success, staticcall(gas(), 6, 0x00, 0x80, PAIRING_LHS_X_LOC, 0x40)) - // negate lhs y-coordinate - mstore(PAIRING_LHS_Y_LOC, sub(q, mload(PAIRING_LHS_Y_LOC))) - - if mload(CONTAINS_RECURSIVE_PROOF_LOC) { - // VALIDATE RECURSIVE P1 - { - let x := mload(RECURSIVE_P1_X_LOC) - let y := mload(RECURSIVE_P1_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - - // compute u.u.[recursive_p1] and write into 0x60 - mstore(0x40, mulmod(u, u, p)) - success := and(success, staticcall(gas(), 7, 0x00, 0x60, 0x60, 0x40)) - // VALIDATE RECURSIVE P2 - { - let x := mload(RECURSIVE_P2_X_LOC) - let y := mload(RECURSIVE_P2_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - // compute u.u.[recursive_p2] and write into 0x00 - // 0x40 still contains u*u - success := and(success, staticcall(gas(), 7, 0x00, 0x60, 0x00, 0x40)) - - // compute u.u.[recursiveP1] + rhs and write into rhs - mstore(0xa0, mload(PAIRING_RHS_X_LOC)) - mstore(0xc0, mload(PAIRING_RHS_Y_LOC)) - success := and(success, staticcall(gas(), 6, 0x60, 0x80, PAIRING_RHS_X_LOC, 0x40)) - - // compute u.u.[recursiveP2] + lhs and write into lhs - mstore(0x40, mload(PAIRING_LHS_X_LOC)) - mstore(0x60, mload(PAIRING_LHS_Y_LOC)) - success := and(success, staticcall(gas(), 6, 0x00, 0x80, PAIRING_LHS_X_LOC, 0x40)) - } - - if iszero(success) { - mstore(0x0, PAIRING_PREAMBLE_FAILED_SELECTOR) - revert(0x00, 0x04) - } - } - - /** - * PERFORM PAIRING - */ - { - // rhs paired with [1]_2 - // lhs paired with [x]_2 - - mstore(0x00, mload(PAIRING_RHS_X_LOC)) - mstore(0x20, mload(PAIRING_RHS_Y_LOC)) - mstore(0x40, 0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2) // this is [1]_2 - mstore(0x60, 0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed) - mstore(0x80, 0x090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b) - mstore(0xa0, 0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa) - - mstore(0xc0, mload(PAIRING_LHS_X_LOC)) - mstore(0xe0, mload(PAIRING_LHS_Y_LOC)) - mstore(0x100, mload(G2X_X0_LOC)) - mstore(0x120, mload(G2X_X1_LOC)) - mstore(0x140, mload(G2X_Y0_LOC)) - mstore(0x160, mload(G2X_Y1_LOC)) - - success := staticcall(gas(), 8, 0x00, 0x180, 0x00, 0x20) - if iszero(and(success, mload(0x00))) { - mstore(0x0, PAIRING_FAILED_SELECTOR) - revert(0x00, 0x04) - } - } - - { - mstore(0x00, 0x01) - return(0x00, 0x20) // Proof succeeded! - } - } - } -} - -contract UltraVerifier is BaseUltraVerifier { - function getVerificationKeyHash() public pure override(BaseUltraVerifier) returns (bytes32) { - return UltraVerificationKey.verificationKeyHash(); - } - - function loadVerificationKey(uint256 vk, uint256 _omegaInverseLoc) internal pure virtual override(BaseUltraVerifier) { - UltraVerificationKey.loadVerificationKey(vk, _omegaInverseLoc); - } -} diff --git a/noir/noir-repo/compiler/integration-tests/contracts/assert_statement.sol b/noir/noir-repo/compiler/integration-tests/contracts/assert_statement.sol deleted file mode 100644 index 6946be8ee4be..000000000000 --- a/noir/noir-repo/compiler/integration-tests/contracts/assert_statement.sol +++ /dev/null @@ -1,2869 +0,0 @@ -// Verification Key Hash: 203c988709ced4125d5c6138661ba4d16a71092c5f4189d2b3baf2596a93311b -// SPDX-License-Identifier: Apache-2.0 -// Copyright 2022 Aztec -pragma solidity >=0.8.4; - -library UltraVerificationKey { - function verificationKeyHash() internal pure returns(bytes32) { - return 0x203c988709ced4125d5c6138661ba4d16a71092c5f4189d2b3baf2596a93311b; - } - - function loadVerificationKey(uint256 _vk, uint256 _omegaInverseLoc) internal pure { - assembly { - mstore(add(_vk, 0x00), 0x0000000000000000000000000000000000000000000000000000000000000008) // vk.circuit_size - mstore(add(_vk, 0x20), 0x0000000000000000000000000000000000000000000000000000000000000001) // vk.num_inputs - mstore(add(_vk, 0x40), 0x2b337de1c8c14f22ec9b9e2f96afef3652627366f8170a0a948dad4ac1bd5e80) // vk.work_root - mstore(add(_vk, 0x60), 0x2a57c4a4850b6c2481463cffb1512d51832d6b3f6a82427f1b65b6e172000001) // vk.domain_inverse - mstore(add(_vk, 0x80), 0x0160ce4e279582f91bde4f03f5e9a292139c61bae1a44f0fc7689507414be688) // vk.Q1.x - mstore(add(_vk, 0xa0), 0x07e3e8a5d98a1177ec85bf88f163a55dc2d37f658c3b2d60f24740eb13b65d79) // vk.Q1.y - mstore(add(_vk, 0xc0), 0x23d08e2817ac16990004ed11d8fc66dc3035fbd7ff16412a8fd7da587a935298) // vk.Q2.x - mstore(add(_vk, 0xe0), 0x0708529196af3c8e16ffa580c26182356a5ad59c646c746a8d09f5d154e47c4f) // vk.Q2.y - mstore(add(_vk, 0x100), 0x13757e15a0905f298303784a161b212ddfe70eb7a1280596e8e4a804f118a6dd) // vk.Q3.x - mstore(add(_vk, 0x120), 0x05775b6c146c4a59856e869fe5a70ea23a729df796935c7824e3a26be794829b) // vk.Q3.y - mstore(add(_vk, 0x140), 0x1d539ccbfc556d0ad59307a218de65eef0c9e088fd2d45aa40311082d1f2809b) // vk.Q4.x - mstore(add(_vk, 0x160), 0x177004deeb1f9d401fd7b1af1a5ac8a2c848beceb6ab7806fd3b88037b8410fc) // vk.Q4.y - mstore(add(_vk, 0x180), 0x0d82d51f2f75d806285fd248c819b82508eb63672a733f20de1a97644be4f540) // vk.Q_M.x - mstore(add(_vk, 0x1a0), 0x06cd3b0e3460533b9e5ea2cdc0fcbbd002f9100cbba8a29f13b11513c53c59d0) // vk.Q_M.y - mstore(add(_vk, 0x1c0), 0x21791de65f9a28ec7024b1a87ab4f3f45ea38a93b2f810c5633ddb54927c1c96) // vk.Q_C.x - mstore(add(_vk, 0x1e0), 0x29fa14a969c5d81ed3abbbfb11220a926511a0439502c86885a8c6f0327aa7ad) // vk.Q_C.y - mstore(add(_vk, 0x200), 0x2a910445cd8fc895e5d235cd8ea185b84c3258e8206f560e5b5b18cbeafef87e) // vk.Q_ARITHMETIC.x - mstore(add(_vk, 0x220), 0x14dc6643d801c3ef27c2066b6e2bb4887e67f15e84bcb8507a5064a363f6043b) // vk.Q_ARITHMETIC.y - mstore(add(_vk, 0x240), 0x20690fd4869db418306046b38161dce38e900b42c314ba803088e8fbf125203f) // vk.QSORT.x - mstore(add(_vk, 0x260), 0x048a85e0bbac7c60ad3d78f601f63c1e2fa856bf7951b8292b1e88185993629c) // vk.QSORT.y - mstore(add(_vk, 0x280), 0x2623ad892dc62b1fa7d0a650f0d4706f457719495073d3666d77a625aeab0c51) // vk.Q_ELLIPTIC.x - mstore(add(_vk, 0x2a0), 0x295f6f10976c37bd9c6f96bb7187d5dbfcc8a467e021c03b13f74a9f79c3a10c) // vk.Q_ELLIPTIC.y - mstore(add(_vk, 0x2c0), 0x03560a3b334e887532f605c9cb7628c13ef9a937cc12420fb38d9ab8e848e85e) // vk.Q_AUX.x - mstore(add(_vk, 0x2e0), 0x15adc8bb1e01c835f48959d1237bd69bcebf08a4599cdda0fb96312d4dc0c7a9) // vk.Q_AUX.y - mstore(add(_vk, 0x300), 0x24e3690cd89b1f74c96a6b0e03032344488741fb4b129e9cbcb31de91fd06ad8) // vk.SIGMA1.x - mstore(add(_vk, 0x320), 0x2c3b3b2783935f54e840bb7502b0ec734cb8ac2419c90514d0d015a974a9b52b) // vk.SIGMA1.y - mstore(add(_vk, 0x340), 0x060d8aa43fdc434d1942263f364d95ab17c6189d67d3bf5dd2f3885de0151b6f) // vk.SIGMA2.x - mstore(add(_vk, 0x360), 0x1a1018a66221883639f2898a66f3455d292333b3adb497f00b4bc32d45229060) // vk.SIGMA2.y - mstore(add(_vk, 0x380), 0x27730cec8ee6eafbd0e5ccffeab20dbd1c781a61196943647af68c4e39985fdc) // vk.SIGMA3.x - mstore(add(_vk, 0x3a0), 0x0766d1f3a85c923ee23cb3fcd89886f19af23a34217779c58eaeceb38cfdf1eb) // vk.SIGMA3.y - mstore(add(_vk, 0x3c0), 0x09ae6c317ff52520ae05150d89a4678f6f5839296a91685a8f562ca95fa36822) // vk.SIGMA4.x - mstore(add(_vk, 0x3e0), 0x0832680695476b91062cfd71c4663f5bd579304b4448ce5ae6eaa6620db20ab1) // vk.SIGMA4.y - mstore(add(_vk, 0x400), 0x1f54baa07558e5fb055bd9ba49c0679c5d6e08a6605ab4513748ac0fa017dd1c) // vk.TABLE1.x - mstore(add(_vk, 0x420), 0x24aec62a9d9763499267dc98c334281e1ee7ee29bbb5e4b080c6091c1433ce62) // vk.TABLE1.y - mstore(add(_vk, 0x440), 0x28cf3e22bcd53782ebc3e0490e27e51a96755946ff16f0d6632365f0eb0ab4d4) // vk.TABLE2.x - mstore(add(_vk, 0x460), 0x234ce541f1f5117dd404cfaf01a22943148d7d8c9ba43f2133fab4201435a364) // vk.TABLE2.y - mstore(add(_vk, 0x480), 0x3016955028b6390f446c3fd0c5b424a7fb95ffb461d9514a1070e2d2403982ef) // vk.TABLE3.x - mstore(add(_vk, 0x4a0), 0x13ef666111b0be56a235983d397d2a08863c3b7cd7cddc20ba79ce915051c56e) // vk.TABLE3.y - mstore(add(_vk, 0x4c0), 0x217f7c4235161e9a3c16c45b6ca499e3993f465fc9f56e93ac769e597b752c1c) // vk.TABLE4.x - mstore(add(_vk, 0x4e0), 0x256467bfcb63d9fdcb5dde397757ad8ffa4cd96bc67b0b7df5678271e1114075) // vk.TABLE4.y - mstore(add(_vk, 0x500), 0x0e52d1bd75812c33c6f3d79ee4b94c54e5eb270bb64bde6e6ececadfd8c3236c) // vk.TABLE_TYPE.x - mstore(add(_vk, 0x520), 0x0ff417d256be43e73c8b1aa85bdda3484a2c641dce55bc2dd64ef0cd790a7fea) // vk.TABLE_TYPE.y - mstore(add(_vk, 0x540), 0x2914765365b4bb5f48a424db02b30c158b9ace6a8786bf33f65c33e87249f995) // vk.ID1.x - mstore(add(_vk, 0x560), 0x2e606ebd09b7686801932b72c9dbe83a6b1ae341f8cb6d52a568b693630f4643) // vk.ID1.y - mstore(add(_vk, 0x580), 0x1b0d1316756ddd16982a7e98b868244fff53c5d4bdc2b70e371c0d08e994cfd5) // vk.ID2.x - mstore(add(_vk, 0x5a0), 0x27f94b1ce85bf25b95857aaa3b82f6a3706170d67e53462bc635491ec3a29f98) // vk.ID2.y - mstore(add(_vk, 0x5c0), 0x26c5c0971d041a6777e4896896f674670e17bb68e92cbb11e605d2d74c077f66) // vk.ID3.x - mstore(add(_vk, 0x5e0), 0x15d5a580649417ff6523c7ec8e2fce5f1f22fef5be2a9fb4fd3004d9c6562efe) // vk.ID3.y - mstore(add(_vk, 0x600), 0x2eea648c8732596b1314fe2a4d2f05363f0c994e91cecad25835338edee2294f) // vk.ID4.x - mstore(add(_vk, 0x620), 0x0ab49886c2b94bd0bd3f6ed1dbbe2cb2671d2ae51d31c1210433c3972bb64578) // vk.ID4.y - mstore(add(_vk, 0x640), 0x00) // vk.contains_recursive_proof - mstore(add(_vk, 0x660), 0) // vk.recursive_proof_public_input_indices - mstore(add(_vk, 0x680), 0x260e01b251f6f1c7e7ff4e580791dee8ea51d87a358e038b4efe30fac09383c1) // vk.g2_x.X.c1 - mstore(add(_vk, 0x6a0), 0x0118c4d5b837bcc2bc89b5b398b5974e9f5944073b32078b7e231fec938883b0) // vk.g2_x.X.c0 - mstore(add(_vk, 0x6c0), 0x04fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe4) // vk.g2_x.Y.c1 - mstore(add(_vk, 0x6e0), 0x22febda3c0c0632a56475b4214e5615e11e6dd3f96e6cea2854a87d4dacc5e55) // vk.g2_x.Y.c0 - mstore(_omegaInverseLoc, 0x130b17119778465cfb3acaee30f81dee20710ead41671f568b11d9ab07b95a9b) // vk.work_root_inverse - } - } -} - -/** - * @title Ultra Plonk proof verification contract - * @dev Top level Plonk proof verification contract, which allows Plonk proof to be verified - */ -abstract contract BaseUltraVerifier { - // VERIFICATION KEY MEMORY LOCATIONS - uint256 internal constant N_LOC = 0x380; - uint256 internal constant NUM_INPUTS_LOC = 0x3a0; - uint256 internal constant OMEGA_LOC = 0x3c0; - uint256 internal constant DOMAIN_INVERSE_LOC = 0x3e0; - uint256 internal constant Q1_X_LOC = 0x400; - uint256 internal constant Q1_Y_LOC = 0x420; - uint256 internal constant Q2_X_LOC = 0x440; - uint256 internal constant Q2_Y_LOC = 0x460; - uint256 internal constant Q3_X_LOC = 0x480; - uint256 internal constant Q3_Y_LOC = 0x4a0; - uint256 internal constant Q4_X_LOC = 0x4c0; - uint256 internal constant Q4_Y_LOC = 0x4e0; - uint256 internal constant QM_X_LOC = 0x500; - uint256 internal constant QM_Y_LOC = 0x520; - uint256 internal constant QC_X_LOC = 0x540; - uint256 internal constant QC_Y_LOC = 0x560; - uint256 internal constant QARITH_X_LOC = 0x580; - uint256 internal constant QARITH_Y_LOC = 0x5a0; - uint256 internal constant QSORT_X_LOC = 0x5c0; - uint256 internal constant QSORT_Y_LOC = 0x5e0; - uint256 internal constant QELLIPTIC_X_LOC = 0x600; - uint256 internal constant QELLIPTIC_Y_LOC = 0x620; - uint256 internal constant QAUX_X_LOC = 0x640; - uint256 internal constant QAUX_Y_LOC = 0x660; - uint256 internal constant SIGMA1_X_LOC = 0x680; - uint256 internal constant SIGMA1_Y_LOC = 0x6a0; - uint256 internal constant SIGMA2_X_LOC = 0x6c0; - uint256 internal constant SIGMA2_Y_LOC = 0x6e0; - uint256 internal constant SIGMA3_X_LOC = 0x700; - uint256 internal constant SIGMA3_Y_LOC = 0x720; - uint256 internal constant SIGMA4_X_LOC = 0x740; - uint256 internal constant SIGMA4_Y_LOC = 0x760; - uint256 internal constant TABLE1_X_LOC = 0x780; - uint256 internal constant TABLE1_Y_LOC = 0x7a0; - uint256 internal constant TABLE2_X_LOC = 0x7c0; - uint256 internal constant TABLE2_Y_LOC = 0x7e0; - uint256 internal constant TABLE3_X_LOC = 0x800; - uint256 internal constant TABLE3_Y_LOC = 0x820; - uint256 internal constant TABLE4_X_LOC = 0x840; - uint256 internal constant TABLE4_Y_LOC = 0x860; - uint256 internal constant TABLE_TYPE_X_LOC = 0x880; - uint256 internal constant TABLE_TYPE_Y_LOC = 0x8a0; - uint256 internal constant ID1_X_LOC = 0x8c0; - uint256 internal constant ID1_Y_LOC = 0x8e0; - uint256 internal constant ID2_X_LOC = 0x900; - uint256 internal constant ID2_Y_LOC = 0x920; - uint256 internal constant ID3_X_LOC = 0x940; - uint256 internal constant ID3_Y_LOC = 0x960; - uint256 internal constant ID4_X_LOC = 0x980; - uint256 internal constant ID4_Y_LOC = 0x9a0; - uint256 internal constant CONTAINS_RECURSIVE_PROOF_LOC = 0x9c0; - uint256 internal constant RECURSIVE_PROOF_PUBLIC_INPUT_INDICES_LOC = 0x9e0; - uint256 internal constant G2X_X0_LOC = 0xa00; - uint256 internal constant G2X_X1_LOC = 0xa20; - uint256 internal constant G2X_Y0_LOC = 0xa40; - uint256 internal constant G2X_Y1_LOC = 0xa60; - - // ### PROOF DATA MEMORY LOCATIONS - uint256 internal constant W1_X_LOC = 0x1200; - uint256 internal constant W1_Y_LOC = 0x1220; - uint256 internal constant W2_X_LOC = 0x1240; - uint256 internal constant W2_Y_LOC = 0x1260; - uint256 internal constant W3_X_LOC = 0x1280; - uint256 internal constant W3_Y_LOC = 0x12a0; - uint256 internal constant W4_X_LOC = 0x12c0; - uint256 internal constant W4_Y_LOC = 0x12e0; - uint256 internal constant S_X_LOC = 0x1300; - uint256 internal constant S_Y_LOC = 0x1320; - uint256 internal constant Z_X_LOC = 0x1340; - uint256 internal constant Z_Y_LOC = 0x1360; - uint256 internal constant Z_LOOKUP_X_LOC = 0x1380; - uint256 internal constant Z_LOOKUP_Y_LOC = 0x13a0; - uint256 internal constant T1_X_LOC = 0x13c0; - uint256 internal constant T1_Y_LOC = 0x13e0; - uint256 internal constant T2_X_LOC = 0x1400; - uint256 internal constant T2_Y_LOC = 0x1420; - uint256 internal constant T3_X_LOC = 0x1440; - uint256 internal constant T3_Y_LOC = 0x1460; - uint256 internal constant T4_X_LOC = 0x1480; - uint256 internal constant T4_Y_LOC = 0x14a0; - - uint256 internal constant W1_EVAL_LOC = 0x1600; - uint256 internal constant W2_EVAL_LOC = 0x1620; - uint256 internal constant W3_EVAL_LOC = 0x1640; - uint256 internal constant W4_EVAL_LOC = 0x1660; - uint256 internal constant S_EVAL_LOC = 0x1680; - uint256 internal constant Z_EVAL_LOC = 0x16a0; - uint256 internal constant Z_LOOKUP_EVAL_LOC = 0x16c0; - uint256 internal constant Q1_EVAL_LOC = 0x16e0; - uint256 internal constant Q2_EVAL_LOC = 0x1700; - uint256 internal constant Q3_EVAL_LOC = 0x1720; - uint256 internal constant Q4_EVAL_LOC = 0x1740; - uint256 internal constant QM_EVAL_LOC = 0x1760; - uint256 internal constant QC_EVAL_LOC = 0x1780; - uint256 internal constant QARITH_EVAL_LOC = 0x17a0; - uint256 internal constant QSORT_EVAL_LOC = 0x17c0; - uint256 internal constant QELLIPTIC_EVAL_LOC = 0x17e0; - uint256 internal constant QAUX_EVAL_LOC = 0x1800; - uint256 internal constant TABLE1_EVAL_LOC = 0x1840; - uint256 internal constant TABLE2_EVAL_LOC = 0x1860; - uint256 internal constant TABLE3_EVAL_LOC = 0x1880; - uint256 internal constant TABLE4_EVAL_LOC = 0x18a0; - uint256 internal constant TABLE_TYPE_EVAL_LOC = 0x18c0; - uint256 internal constant ID1_EVAL_LOC = 0x18e0; - uint256 internal constant ID2_EVAL_LOC = 0x1900; - uint256 internal constant ID3_EVAL_LOC = 0x1920; - uint256 internal constant ID4_EVAL_LOC = 0x1940; - uint256 internal constant SIGMA1_EVAL_LOC = 0x1960; - uint256 internal constant SIGMA2_EVAL_LOC = 0x1980; - uint256 internal constant SIGMA3_EVAL_LOC = 0x19a0; - uint256 internal constant SIGMA4_EVAL_LOC = 0x19c0; - uint256 internal constant W1_OMEGA_EVAL_LOC = 0x19e0; - uint256 internal constant W2_OMEGA_EVAL_LOC = 0x2000; - uint256 internal constant W3_OMEGA_EVAL_LOC = 0x2020; - uint256 internal constant W4_OMEGA_EVAL_LOC = 0x2040; - uint256 internal constant S_OMEGA_EVAL_LOC = 0x2060; - uint256 internal constant Z_OMEGA_EVAL_LOC = 0x2080; - uint256 internal constant Z_LOOKUP_OMEGA_EVAL_LOC = 0x20a0; - uint256 internal constant TABLE1_OMEGA_EVAL_LOC = 0x20c0; - uint256 internal constant TABLE2_OMEGA_EVAL_LOC = 0x20e0; - uint256 internal constant TABLE3_OMEGA_EVAL_LOC = 0x2100; - uint256 internal constant TABLE4_OMEGA_EVAL_LOC = 0x2120; - - uint256 internal constant PI_Z_X_LOC = 0x2300; - uint256 internal constant PI_Z_Y_LOC = 0x2320; - uint256 internal constant PI_Z_OMEGA_X_LOC = 0x2340; - uint256 internal constant PI_Z_OMEGA_Y_LOC = 0x2360; - - // Used for elliptic widget. These are alias names for wire + shifted wire evaluations - uint256 internal constant X1_EVAL_LOC = W2_EVAL_LOC; - uint256 internal constant X2_EVAL_LOC = W1_OMEGA_EVAL_LOC; - uint256 internal constant X3_EVAL_LOC = W2_OMEGA_EVAL_LOC; - uint256 internal constant Y1_EVAL_LOC = W3_EVAL_LOC; - uint256 internal constant Y2_EVAL_LOC = W4_OMEGA_EVAL_LOC; - uint256 internal constant Y3_EVAL_LOC = W3_OMEGA_EVAL_LOC; - uint256 internal constant QBETA_LOC = Q3_EVAL_LOC; - uint256 internal constant QBETA_SQR_LOC = Q4_EVAL_LOC; - uint256 internal constant QSIGN_LOC = Q1_EVAL_LOC; - - // ### CHALLENGES MEMORY OFFSETS - - uint256 internal constant C_BETA_LOC = 0x2600; - uint256 internal constant C_GAMMA_LOC = 0x2620; - uint256 internal constant C_ALPHA_LOC = 0x2640; - uint256 internal constant C_ETA_LOC = 0x2660; - uint256 internal constant C_ETA_SQR_LOC = 0x2680; - uint256 internal constant C_ETA_CUBE_LOC = 0x26a0; - - uint256 internal constant C_ZETA_LOC = 0x26c0; - uint256 internal constant C_CURRENT_LOC = 0x26e0; - uint256 internal constant C_V0_LOC = 0x2700; - uint256 internal constant C_V1_LOC = 0x2720; - uint256 internal constant C_V2_LOC = 0x2740; - uint256 internal constant C_V3_LOC = 0x2760; - uint256 internal constant C_V4_LOC = 0x2780; - uint256 internal constant C_V5_LOC = 0x27a0; - uint256 internal constant C_V6_LOC = 0x27c0; - uint256 internal constant C_V7_LOC = 0x27e0; - uint256 internal constant C_V8_LOC = 0x2800; - uint256 internal constant C_V9_LOC = 0x2820; - uint256 internal constant C_V10_LOC = 0x2840; - uint256 internal constant C_V11_LOC = 0x2860; - uint256 internal constant C_V12_LOC = 0x2880; - uint256 internal constant C_V13_LOC = 0x28a0; - uint256 internal constant C_V14_LOC = 0x28c0; - uint256 internal constant C_V15_LOC = 0x28e0; - uint256 internal constant C_V16_LOC = 0x2900; - uint256 internal constant C_V17_LOC = 0x2920; - uint256 internal constant C_V18_LOC = 0x2940; - uint256 internal constant C_V19_LOC = 0x2960; - uint256 internal constant C_V20_LOC = 0x2980; - uint256 internal constant C_V21_LOC = 0x29a0; - uint256 internal constant C_V22_LOC = 0x29c0; - uint256 internal constant C_V23_LOC = 0x29e0; - uint256 internal constant C_V24_LOC = 0x2a00; - uint256 internal constant C_V25_LOC = 0x2a20; - uint256 internal constant C_V26_LOC = 0x2a40; - uint256 internal constant C_V27_LOC = 0x2a60; - uint256 internal constant C_V28_LOC = 0x2a80; - uint256 internal constant C_V29_LOC = 0x2aa0; - uint256 internal constant C_V30_LOC = 0x2ac0; - - uint256 internal constant C_U_LOC = 0x2b00; - - // ### LOCAL VARIABLES MEMORY OFFSETS - uint256 internal constant DELTA_NUMERATOR_LOC = 0x3000; - uint256 internal constant DELTA_DENOMINATOR_LOC = 0x3020; - uint256 internal constant ZETA_POW_N_LOC = 0x3040; - uint256 internal constant PUBLIC_INPUT_DELTA_LOC = 0x3060; - uint256 internal constant ZERO_POLY_LOC = 0x3080; - uint256 internal constant L_START_LOC = 0x30a0; - uint256 internal constant L_END_LOC = 0x30c0; - uint256 internal constant R_ZERO_EVAL_LOC = 0x30e0; - - uint256 internal constant PLOOKUP_DELTA_NUMERATOR_LOC = 0x3100; - uint256 internal constant PLOOKUP_DELTA_DENOMINATOR_LOC = 0x3120; - uint256 internal constant PLOOKUP_DELTA_LOC = 0x3140; - - uint256 internal constant ACCUMULATOR_X_LOC = 0x3160; - uint256 internal constant ACCUMULATOR_Y_LOC = 0x3180; - uint256 internal constant ACCUMULATOR2_X_LOC = 0x31a0; - uint256 internal constant ACCUMULATOR2_Y_LOC = 0x31c0; - uint256 internal constant PAIRING_LHS_X_LOC = 0x31e0; - uint256 internal constant PAIRING_LHS_Y_LOC = 0x3200; - uint256 internal constant PAIRING_RHS_X_LOC = 0x3220; - uint256 internal constant PAIRING_RHS_Y_LOC = 0x3240; - - // misc stuff - uint256 internal constant OMEGA_INVERSE_LOC = 0x3300; - uint256 internal constant C_ALPHA_SQR_LOC = 0x3320; - uint256 internal constant C_ALPHA_CUBE_LOC = 0x3340; - uint256 internal constant C_ALPHA_QUAD_LOC = 0x3360; - uint256 internal constant C_ALPHA_BASE_LOC = 0x3380; - - // ### RECURSION VARIABLE MEMORY LOCATIONS - uint256 internal constant RECURSIVE_P1_X_LOC = 0x3400; - uint256 internal constant RECURSIVE_P1_Y_LOC = 0x3420; - uint256 internal constant RECURSIVE_P2_X_LOC = 0x3440; - uint256 internal constant RECURSIVE_P2_Y_LOC = 0x3460; - uint256 internal constant PUBLIC_INPUTS_HASH_LOCATION = 0x3480; - - // sub-identity storage - uint256 internal constant PERMUTATION_IDENTITY = 0x3500; - uint256 internal constant PLOOKUP_IDENTITY = 0x3520; - uint256 internal constant ARITHMETIC_IDENTITY = 0x3540; - uint256 internal constant SORT_IDENTITY = 0x3560; - uint256 internal constant ELLIPTIC_IDENTITY = 0x3580; - uint256 internal constant AUX_IDENTITY = 0x35a0; - uint256 internal constant AUX_NON_NATIVE_FIELD_EVALUATION = 0x35c0; - uint256 internal constant AUX_LIMB_ACCUMULATOR_EVALUATION = 0x35e0; - uint256 internal constant AUX_RAM_CONSISTENCY_EVALUATION = 0x3600; - uint256 internal constant AUX_ROM_CONSISTENCY_EVALUATION = 0x3620; - uint256 internal constant AUX_MEMORY_EVALUATION = 0x3640; - - uint256 internal constant QUOTIENT_EVAL_LOC = 0x3660; - uint256 internal constant ZERO_POLY_INVERSE_LOC = 0x3680; - - // when hashing public inputs we use memory at NU_CHALLENGE_INPUT_LOC_A, as the hash input size is unknown at compile time - uint256 internal constant NU_CHALLENGE_INPUT_LOC_A = 0x36a0; - uint256 internal constant NU_CHALLENGE_INPUT_LOC_B = 0x36c0; - uint256 internal constant NU_CHALLENGE_INPUT_LOC_C = 0x36e0; - - bytes4 internal constant INVALID_VERIFICATION_KEY_SELECTOR = 0x7e5769bf; - bytes4 internal constant POINT_NOT_ON_CURVE_SELECTOR = 0xa3dad654; - bytes4 internal constant PUBLIC_INPUT_INVALID_BN128_G1_POINT_SELECTOR = 0xeba9f4a6; - bytes4 internal constant PUBLIC_INPUT_GE_P_SELECTOR = 0x374a972f; - bytes4 internal constant MOD_EXP_FAILURE_SELECTOR = 0xf894a7bc; - bytes4 internal constant PAIRING_PREAMBLE_FAILED_SELECTOR = 0x01882d81; - bytes4 internal constant OPENING_COMMITMENT_FAILED_SELECTOR = 0x4e719763; - bytes4 internal constant PAIRING_FAILED_SELECTOR = 0xd71fd263; - - uint256 internal constant ETA_INPUT_LENGTH = 0xc0; // W1, W2, W3 = 6 * 0x20 bytes - - // We need to hash 41 field elements when generating the NU challenge - // w1, w2, w3, w4, s, z, z_lookup, q1, q2, q3, q4, qm, qc, qarith (14) - // qsort, qelliptic, qaux, sigma1, sigma2, sigma, sigma4, (7) - // table1, table2, table3, table4, tabletype, id1, id2, id3, id4, (9) - // w1_omega, w2_omega, w3_omega, w4_omega, s_omega, z_omega, z_lookup_omega, (7) - // table1_omega, table2_omega, table3_omega, table4_omega (4) - uint256 internal constant NU_INPUT_LENGTH = 0x520; // 0x520 = 41 * 0x20 - - // There are ELEVEN G1 group elements added into the transcript in the `beta` round, that we need to skip over - // W1, W2, W3, W4, S, Z, Z_LOOKUP, T1, T2, T3, T4 - uint256 internal constant NU_CALLDATA_SKIP_LENGTH = 0x2c0; // 11 * 0x40 = 0x2c0 - - uint256 internal constant NEGATIVE_INVERSE_OF_2_MODULO_P = - 0x183227397098d014dc2822db40c0ac2e9419f4243cdcb848a1f0fac9f8000000; - uint256 internal constant LIMB_SIZE = 0x100000000000000000; // 2<<68 - uint256 internal constant SUBLIMB_SHIFT = 0x4000; // 2<<14 - - // y^2 = x^3 + ax + b - // for Grumpkin, a = 0 and b = -17. We use b in a custom gate relation that evaluates elliptic curve arithmetic - uint256 internal constant GRUMPKIN_CURVE_B_PARAMETER_NEGATED = 17; - - error INVALID_VERIFICATION_KEY(); - error POINT_NOT_ON_CURVE(); - error PUBLIC_INPUT_COUNT_INVALID(uint256 expected, uint256 actual); - error PUBLIC_INPUT_INVALID_BN128_G1_POINT(); - error PUBLIC_INPUT_GE_P(); - error MOD_EXP_FAILURE(); - error PAIRING_PREAMBLE_FAILED(); - error OPENING_COMMITMENT_FAILED(); - error PAIRING_FAILED(); - - function getVerificationKeyHash() public pure virtual returns (bytes32); - - /** - * @dev We assume that the verification key loaded by this function is constant as we only verify it on deployment - */ - function loadVerificationKey(uint256 _vk, uint256 _omegaInverseLoc) internal pure virtual; - - constructor() { - loadVerificationKey(N_LOC, OMEGA_INVERSE_LOC); - - // We verify that all of the EC points in the verification key lie on the bn128 curve. - assembly { - let q := 21888242871839275222246405745257275088696311157297823662689037894645226208583 // EC group order - - let success := 1 - - // VALIDATE Q1 - { - let x := mload(Q1_X_LOC) - let y := mload(Q1_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE Q2 - { - let x := mload(Q2_X_LOC) - let y := mload(Q2_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE Q3 - { - let x := mload(Q3_X_LOC) - let y := mload(Q3_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE Q4 - { - let x := mload(Q4_X_LOC) - let y := mload(Q4_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - mstore(0x00, x) - mstore(0x20, y) - } - // VALIDATE QM - { - let x := mload(QM_X_LOC) - let y := mload(QM_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE QC - { - let x := mload(QC_X_LOC) - let y := mload(QC_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE QARITH - { - let x := mload(QARITH_X_LOC) - let y := mload(QARITH_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE QSORT - { - let x := mload(QSORT_X_LOC) - let y := mload(QSORT_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE QELLIPTIC - { - let x := mload(QELLIPTIC_X_LOC) - let y := mload(QELLIPTIC_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE QAUX - { - let x := mload(QAUX_X_LOC) - let y := mload(QAUX_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE SIGMA1 - { - let x := mload(SIGMA1_X_LOC) - let y := mload(SIGMA1_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE SIGMA2 - { - let x := mload(SIGMA2_X_LOC) - let y := mload(SIGMA2_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE SIGMA3 - { - let x := mload(SIGMA3_X_LOC) - let y := mload(SIGMA3_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE SIGMA4 - { - let x := mload(SIGMA4_X_LOC) - let y := mload(SIGMA4_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE TABLE1 - { - let x := mload(TABLE1_X_LOC) - let y := mload(TABLE1_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE TABLE2 - { - let x := mload(TABLE2_X_LOC) - let y := mload(TABLE2_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE TABLE3 - { - let x := mload(TABLE3_X_LOC) - let y := mload(TABLE3_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE TABLE4 - { - let x := mload(TABLE4_X_LOC) - let y := mload(TABLE4_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE TABLE_TYPE - { - let x := mload(TABLE_TYPE_X_LOC) - let y := mload(TABLE_TYPE_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE ID1 - { - let x := mload(ID1_X_LOC) - let y := mload(ID1_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE ID2 - { - let x := mload(ID2_X_LOC) - let y := mload(ID2_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE ID3 - { - let x := mload(ID3_X_LOC) - let y := mload(ID3_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE ID4 - { - let x := mload(ID4_X_LOC) - let y := mload(ID4_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - - if iszero(success) { - mstore(0x0, INVALID_VERIFICATION_KEY_SELECTOR) - revert(0x00, 0x04) - } - } - } - - /** - * @notice Verify a Ultra Plonk proof - * @param _proof - The serialized proof - * @param _publicInputs - An array of the public inputs - * @return True if proof is valid, reverts otherwise - */ - function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool) { - loadVerificationKey(N_LOC, OMEGA_INVERSE_LOC); - - uint256 requiredPublicInputCount; - assembly { - requiredPublicInputCount := mload(NUM_INPUTS_LOC) - } - if (requiredPublicInputCount != _publicInputs.length) { - revert PUBLIC_INPUT_COUNT_INVALID(requiredPublicInputCount, _publicInputs.length); - } - - assembly { - let q := 21888242871839275222246405745257275088696311157297823662689037894645226208583 // EC group order - let p := 21888242871839275222246405745257275088548364400416034343698204186575808495617 // Prime field order - - /** - * LOAD PROOF FROM CALLDATA - */ - { - let data_ptr := add(calldataload(0x04), 0x24) - - mstore(W1_Y_LOC, mod(calldataload(data_ptr), q)) - mstore(W1_X_LOC, mod(calldataload(add(data_ptr, 0x20)), q)) - - mstore(W2_Y_LOC, mod(calldataload(add(data_ptr, 0x40)), q)) - mstore(W2_X_LOC, mod(calldataload(add(data_ptr, 0x60)), q)) - - mstore(W3_Y_LOC, mod(calldataload(add(data_ptr, 0x80)), q)) - mstore(W3_X_LOC, mod(calldataload(add(data_ptr, 0xa0)), q)) - - mstore(W4_Y_LOC, mod(calldataload(add(data_ptr, 0xc0)), q)) - mstore(W4_X_LOC, mod(calldataload(add(data_ptr, 0xe0)), q)) - - mstore(S_Y_LOC, mod(calldataload(add(data_ptr, 0x100)), q)) - mstore(S_X_LOC, mod(calldataload(add(data_ptr, 0x120)), q)) - mstore(Z_Y_LOC, mod(calldataload(add(data_ptr, 0x140)), q)) - mstore(Z_X_LOC, mod(calldataload(add(data_ptr, 0x160)), q)) - mstore(Z_LOOKUP_Y_LOC, mod(calldataload(add(data_ptr, 0x180)), q)) - mstore(Z_LOOKUP_X_LOC, mod(calldataload(add(data_ptr, 0x1a0)), q)) - mstore(T1_Y_LOC, mod(calldataload(add(data_ptr, 0x1c0)), q)) - mstore(T1_X_LOC, mod(calldataload(add(data_ptr, 0x1e0)), q)) - - mstore(T2_Y_LOC, mod(calldataload(add(data_ptr, 0x200)), q)) - mstore(T2_X_LOC, mod(calldataload(add(data_ptr, 0x220)), q)) - - mstore(T3_Y_LOC, mod(calldataload(add(data_ptr, 0x240)), q)) - mstore(T3_X_LOC, mod(calldataload(add(data_ptr, 0x260)), q)) - - mstore(T4_Y_LOC, mod(calldataload(add(data_ptr, 0x280)), q)) - mstore(T4_X_LOC, mod(calldataload(add(data_ptr, 0x2a0)), q)) - - mstore(W1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x2c0)), p)) - mstore(W2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x2e0)), p)) - mstore(W3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x300)), p)) - mstore(W4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x320)), p)) - mstore(S_EVAL_LOC, mod(calldataload(add(data_ptr, 0x340)), p)) - mstore(Z_EVAL_LOC, mod(calldataload(add(data_ptr, 0x360)), p)) - mstore(Z_LOOKUP_EVAL_LOC, mod(calldataload(add(data_ptr, 0x380)), p)) - mstore(Q1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x3a0)), p)) - mstore(Q2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x3c0)), p)) - mstore(Q3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x3e0)), p)) - mstore(Q4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x400)), p)) - mstore(QM_EVAL_LOC, mod(calldataload(add(data_ptr, 0x420)), p)) - mstore(QC_EVAL_LOC, mod(calldataload(add(data_ptr, 0x440)), p)) - mstore(QARITH_EVAL_LOC, mod(calldataload(add(data_ptr, 0x460)), p)) - mstore(QSORT_EVAL_LOC, mod(calldataload(add(data_ptr, 0x480)), p)) - mstore(QELLIPTIC_EVAL_LOC, mod(calldataload(add(data_ptr, 0x4a0)), p)) - mstore(QAUX_EVAL_LOC, mod(calldataload(add(data_ptr, 0x4c0)), p)) - - mstore(SIGMA1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x4e0)), p)) - mstore(SIGMA2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x500)), p)) - - mstore(SIGMA3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x520)), p)) - mstore(SIGMA4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x540)), p)) - - mstore(TABLE1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x560)), p)) - mstore(TABLE2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x580)), p)) - mstore(TABLE3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x5a0)), p)) - mstore(TABLE4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x5c0)), p)) - mstore(TABLE_TYPE_EVAL_LOC, mod(calldataload(add(data_ptr, 0x5e0)), p)) - - mstore(ID1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x600)), p)) - mstore(ID2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x620)), p)) - mstore(ID3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x640)), p)) - mstore(ID4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x660)), p)) - - mstore(W1_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x680)), p)) - mstore(W2_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x6a0)), p)) - mstore(W3_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x6c0)), p)) - mstore(W4_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x6e0)), p)) - mstore(S_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x700)), p)) - - mstore(Z_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x720)), p)) - - mstore(Z_LOOKUP_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x740)), p)) - mstore(TABLE1_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x760)), p)) - mstore(TABLE2_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x780)), p)) - mstore(TABLE3_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x7a0)), p)) - mstore(TABLE4_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x7c0)), p)) - - mstore(PI_Z_Y_LOC, mod(calldataload(add(data_ptr, 0x7e0)), q)) - mstore(PI_Z_X_LOC, mod(calldataload(add(data_ptr, 0x800)), q)) - - mstore(PI_Z_OMEGA_Y_LOC, mod(calldataload(add(data_ptr, 0x820)), q)) - mstore(PI_Z_OMEGA_X_LOC, mod(calldataload(add(data_ptr, 0x840)), q)) - } - - /** - * LOAD RECURSIVE PROOF INTO MEMORY - */ - { - if mload(CONTAINS_RECURSIVE_PROOF_LOC) { - let public_inputs_ptr := add(calldataload(0x24), 0x24) - let index_counter := add(shl(5, mload(RECURSIVE_PROOF_PUBLIC_INPUT_INDICES_LOC)), public_inputs_ptr) - - let x0 := calldataload(index_counter) - x0 := add(x0, shl(68, calldataload(add(index_counter, 0x20)))) - x0 := add(x0, shl(136, calldataload(add(index_counter, 0x40)))) - x0 := add(x0, shl(204, calldataload(add(index_counter, 0x60)))) - let y0 := calldataload(add(index_counter, 0x80)) - y0 := add(y0, shl(68, calldataload(add(index_counter, 0xa0)))) - y0 := add(y0, shl(136, calldataload(add(index_counter, 0xc0)))) - y0 := add(y0, shl(204, calldataload(add(index_counter, 0xe0)))) - let x1 := calldataload(add(index_counter, 0x100)) - x1 := add(x1, shl(68, calldataload(add(index_counter, 0x120)))) - x1 := add(x1, shl(136, calldataload(add(index_counter, 0x140)))) - x1 := add(x1, shl(204, calldataload(add(index_counter, 0x160)))) - let y1 := calldataload(add(index_counter, 0x180)) - y1 := add(y1, shl(68, calldataload(add(index_counter, 0x1a0)))) - y1 := add(y1, shl(136, calldataload(add(index_counter, 0x1c0)))) - y1 := add(y1, shl(204, calldataload(add(index_counter, 0x1e0)))) - mstore(RECURSIVE_P1_X_LOC, x0) - mstore(RECURSIVE_P1_Y_LOC, y0) - mstore(RECURSIVE_P2_X_LOC, x1) - mstore(RECURSIVE_P2_Y_LOC, y1) - - // validate these are valid bn128 G1 points - if iszero(and(and(lt(x0, q), lt(x1, q)), and(lt(y0, q), lt(y1, q)))) { - mstore(0x00, PUBLIC_INPUT_INVALID_BN128_G1_POINT_SELECTOR) - revert(0x00, 0x04) - } - } - } - - { - /** - * Generate initial challenge - */ - mstore(0x00, shl(224, mload(N_LOC))) - mstore(0x04, shl(224, mload(NUM_INPUTS_LOC))) - let challenge := keccak256(0x00, 0x08) - - /** - * Generate eta challenge - */ - mstore(PUBLIC_INPUTS_HASH_LOCATION, challenge) - // The public input location is stored at 0x24, we then add 0x24 to skip selector and the length of public inputs - let public_inputs_start := add(calldataload(0x24), 0x24) - // copy the public inputs over - let public_input_size := mul(mload(NUM_INPUTS_LOC), 0x20) - calldatacopy(add(PUBLIC_INPUTS_HASH_LOCATION, 0x20), public_inputs_start, public_input_size) - - // copy W1, W2, W3 into challenge. Each point is 0x40 bytes, so load 0xc0 = 3 * 0x40 bytes (ETA input length) - let w_start := add(calldataload(0x04), 0x24) - calldatacopy(add(add(PUBLIC_INPUTS_HASH_LOCATION, 0x20), public_input_size), w_start, ETA_INPUT_LENGTH) - - // Challenge is the old challenge + public inputs + W1, W2, W3 (0x20 + public_input_size + 0xc0) - let challenge_bytes_size := add(0x20, add(public_input_size, ETA_INPUT_LENGTH)) - - challenge := keccak256(PUBLIC_INPUTS_HASH_LOCATION, challenge_bytes_size) - { - let eta := mod(challenge, p) - mstore(C_ETA_LOC, eta) - mstore(C_ETA_SQR_LOC, mulmod(eta, eta, p)) - mstore(C_ETA_CUBE_LOC, mulmod(mload(C_ETA_SQR_LOC), eta, p)) - } - - /** - * Generate beta challenge - */ - mstore(0x00, challenge) - mstore(0x20, mload(W4_Y_LOC)) - mstore(0x40, mload(W4_X_LOC)) - mstore(0x60, mload(S_Y_LOC)) - mstore(0x80, mload(S_X_LOC)) - challenge := keccak256(0x00, 0xa0) - mstore(C_BETA_LOC, mod(challenge, p)) - - /** - * Generate gamma challenge - */ - mstore(0x00, challenge) - mstore8(0x20, 0x01) - challenge := keccak256(0x00, 0x21) - mstore(C_GAMMA_LOC, mod(challenge, p)) - - /** - * Generate alpha challenge - */ - mstore(0x00, challenge) - mstore(0x20, mload(Z_Y_LOC)) - mstore(0x40, mload(Z_X_LOC)) - mstore(0x60, mload(Z_LOOKUP_Y_LOC)) - mstore(0x80, mload(Z_LOOKUP_X_LOC)) - challenge := keccak256(0x00, 0xa0) - mstore(C_ALPHA_LOC, mod(challenge, p)) - - /** - * Compute and store some powers of alpha for future computations - */ - let alpha := mload(C_ALPHA_LOC) - mstore(C_ALPHA_SQR_LOC, mulmod(alpha, alpha, p)) - mstore(C_ALPHA_CUBE_LOC, mulmod(mload(C_ALPHA_SQR_LOC), alpha, p)) - mstore(C_ALPHA_QUAD_LOC, mulmod(mload(C_ALPHA_CUBE_LOC), alpha, p)) - mstore(C_ALPHA_BASE_LOC, alpha) - - /** - * Generate zeta challenge - */ - mstore(0x00, challenge) - mstore(0x20, mload(T1_Y_LOC)) - mstore(0x40, mload(T1_X_LOC)) - mstore(0x60, mload(T2_Y_LOC)) - mstore(0x80, mload(T2_X_LOC)) - mstore(0xa0, mload(T3_Y_LOC)) - mstore(0xc0, mload(T3_X_LOC)) - mstore(0xe0, mload(T4_Y_LOC)) - mstore(0x100, mload(T4_X_LOC)) - - challenge := keccak256(0x00, 0x120) - - mstore(C_ZETA_LOC, mod(challenge, p)) - mstore(C_CURRENT_LOC, challenge) - } - - /** - * EVALUATE FIELD OPERATIONS - */ - - /** - * COMPUTE PUBLIC INPUT DELTA - * ΔPI = ∏ᵢ∈ℓ(wᵢ + β σ(i) + γ) / ∏ᵢ∈ℓ(wᵢ + β σ'(i) + γ) - */ - { - let beta := mload(C_BETA_LOC) // β - let gamma := mload(C_GAMMA_LOC) // γ - let work_root := mload(OMEGA_LOC) // ω - let numerator_value := 1 - let denominator_value := 1 - - let p_clone := p // move p to the front of the stack - let valid_inputs := true - - // Load the starting point of the public inputs (jump over the selector and the length of public inputs [0x24]) - let public_inputs_ptr := add(calldataload(0x24), 0x24) - - // endpoint_ptr = public_inputs_ptr + num_inputs * 0x20. // every public input is 0x20 bytes - let endpoint_ptr := add(public_inputs_ptr, mul(mload(NUM_INPUTS_LOC), 0x20)) - - // root_1 = β * 0x05 - let root_1 := mulmod(beta, 0x05, p_clone) // k1.β - // root_2 = β * 0x0c - let root_2 := mulmod(beta, 0x0c, p_clone) - // @note 0x05 + 0x07 == 0x0c == external coset generator - - for {} lt(public_inputs_ptr, endpoint_ptr) { public_inputs_ptr := add(public_inputs_ptr, 0x20) } { - /** - * input = public_input[i] - * valid_inputs &= input < p - * temp = input + gamma - * numerator_value *= (β.σ(i) + wᵢ + γ) // σ(i) = 0x05.ωⁱ - * denominator_value *= (β.σ'(i) + wᵢ + γ) // σ'(i) = 0x0c.ωⁱ - * root_1 *= ω - * root_2 *= ω - */ - - let input := calldataload(public_inputs_ptr) - valid_inputs := and(valid_inputs, lt(input, p_clone)) - let temp := addmod(input, gamma, p_clone) - - numerator_value := mulmod(numerator_value, add(root_1, temp), p_clone) - denominator_value := mulmod(denominator_value, add(root_2, temp), p_clone) - - root_1 := mulmod(root_1, work_root, p_clone) - root_2 := mulmod(root_2, work_root, p_clone) - } - - // Revert if not all public inputs are field elements (i.e. < p) - if iszero(valid_inputs) { - mstore(0x00, PUBLIC_INPUT_GE_P_SELECTOR) - revert(0x00, 0x04) - } - - mstore(DELTA_NUMERATOR_LOC, numerator_value) - mstore(DELTA_DENOMINATOR_LOC, denominator_value) - } - - /** - * Compute Plookup delta factor [γ(1 + β)]^{n-k} - * k = num roots cut out of Z_H = 4 - */ - { - let delta_base := mulmod(mload(C_GAMMA_LOC), addmod(mload(C_BETA_LOC), 1, p), p) - let delta_numerator := delta_base - { - let exponent := mload(N_LOC) - let count := 1 - for {} lt(count, exponent) { count := add(count, count) } { - delta_numerator := mulmod(delta_numerator, delta_numerator, p) - } - } - mstore(PLOOKUP_DELTA_NUMERATOR_LOC, delta_numerator) - - let delta_denominator := mulmod(delta_base, delta_base, p) - delta_denominator := mulmod(delta_denominator, delta_denominator, p) - mstore(PLOOKUP_DELTA_DENOMINATOR_LOC, delta_denominator) - } - /** - * Compute lagrange poly and vanishing poly fractions - */ - { - /** - * vanishing_numerator = zeta - * ZETA_POW_N = zeta^n - * vanishing_numerator -= 1 - * accumulating_root = omega_inverse - * work_root = p - accumulating_root - * domain_inverse = domain_inverse - * vanishing_denominator = zeta + work_root - * work_root *= accumulating_root - * vanishing_denominator *= (zeta + work_root) - * work_root *= accumulating_root - * vanishing_denominator *= (zeta + work_root) - * vanishing_denominator *= (zeta + (zeta + accumulating_root)) - * work_root = omega - * lagrange_numerator = vanishing_numerator * domain_inverse - * l_start_denominator = zeta - 1 - * accumulating_root = work_root^2 - * l_end_denominator = accumulating_root^2 * work_root * zeta - 1 - * Note: l_end_denominator term contains a term \omega^5 to cut out 5 roots of unity from vanishing poly - */ - - let zeta := mload(C_ZETA_LOC) - - // compute zeta^n, where n is a power of 2 - let vanishing_numerator := zeta - { - // pow_small - let exponent := mload(N_LOC) - let count := 1 - for {} lt(count, exponent) { count := add(count, count) } { - vanishing_numerator := mulmod(vanishing_numerator, vanishing_numerator, p) - } - } - mstore(ZETA_POW_N_LOC, vanishing_numerator) - vanishing_numerator := addmod(vanishing_numerator, sub(p, 1), p) - - let accumulating_root := mload(OMEGA_INVERSE_LOC) - let work_root := sub(p, accumulating_root) - let domain_inverse := mload(DOMAIN_INVERSE_LOC) - - let vanishing_denominator := addmod(zeta, work_root, p) - work_root := mulmod(work_root, accumulating_root, p) - vanishing_denominator := mulmod(vanishing_denominator, addmod(zeta, work_root, p), p) - work_root := mulmod(work_root, accumulating_root, p) - vanishing_denominator := mulmod(vanishing_denominator, addmod(zeta, work_root, p), p) - vanishing_denominator := - mulmod(vanishing_denominator, addmod(zeta, mulmod(work_root, accumulating_root, p), p), p) - - work_root := mload(OMEGA_LOC) - - let lagrange_numerator := mulmod(vanishing_numerator, domain_inverse, p) - let l_start_denominator := addmod(zeta, sub(p, 1), p) - - accumulating_root := mulmod(work_root, work_root, p) - - let l_end_denominator := - addmod( - mulmod(mulmod(mulmod(accumulating_root, accumulating_root, p), work_root, p), zeta, p), sub(p, 1), p - ) - - /** - * Compute inversions using Montgomery's batch inversion trick - */ - let accumulator := mload(DELTA_DENOMINATOR_LOC) - let t0 := accumulator - accumulator := mulmod(accumulator, vanishing_denominator, p) - let t1 := accumulator - accumulator := mulmod(accumulator, vanishing_numerator, p) - let t2 := accumulator - accumulator := mulmod(accumulator, l_start_denominator, p) - let t3 := accumulator - accumulator := mulmod(accumulator, mload(PLOOKUP_DELTA_DENOMINATOR_LOC), p) - let t4 := accumulator - { - mstore(0, 0x20) - mstore(0x20, 0x20) - mstore(0x40, 0x20) - mstore(0x60, mulmod(accumulator, l_end_denominator, p)) - mstore(0x80, sub(p, 2)) - mstore(0xa0, p) - if iszero(staticcall(gas(), 0x05, 0x00, 0xc0, 0x00, 0x20)) { - mstore(0x0, MOD_EXP_FAILURE_SELECTOR) - revert(0x00, 0x04) - } - accumulator := mload(0x00) - } - - t4 := mulmod(accumulator, t4, p) - accumulator := mulmod(accumulator, l_end_denominator, p) - - t3 := mulmod(accumulator, t3, p) - accumulator := mulmod(accumulator, mload(PLOOKUP_DELTA_DENOMINATOR_LOC), p) - - t2 := mulmod(accumulator, t2, p) - accumulator := mulmod(accumulator, l_start_denominator, p) - - t1 := mulmod(accumulator, t1, p) - accumulator := mulmod(accumulator, vanishing_numerator, p) - - t0 := mulmod(accumulator, t0, p) - accumulator := mulmod(accumulator, vanishing_denominator, p) - - accumulator := mulmod(mulmod(accumulator, accumulator, p), mload(DELTA_DENOMINATOR_LOC), p) - - mstore(PUBLIC_INPUT_DELTA_LOC, mulmod(mload(DELTA_NUMERATOR_LOC), accumulator, p)) - mstore(ZERO_POLY_LOC, mulmod(vanishing_numerator, t0, p)) - mstore(ZERO_POLY_INVERSE_LOC, mulmod(vanishing_denominator, t1, p)) - mstore(L_START_LOC, mulmod(lagrange_numerator, t2, p)) - mstore(PLOOKUP_DELTA_LOC, mulmod(mload(PLOOKUP_DELTA_NUMERATOR_LOC), t3, p)) - mstore(L_END_LOC, mulmod(lagrange_numerator, t4, p)) - } - - /** - * UltraPlonk Widget Ordering: - * - * 1. Permutation widget - * 2. Plookup widget - * 3. Arithmetic widget - * 4. Fixed base widget (?) - * 5. GenPermSort widget - * 6. Elliptic widget - * 7. Auxiliary widget - */ - - /** - * COMPUTE PERMUTATION WIDGET EVALUATION - */ - { - let alpha := mload(C_ALPHA_LOC) - let beta := mload(C_BETA_LOC) - let gamma := mload(C_GAMMA_LOC) - - /** - * t1 = (W1 + gamma + beta * ID1) * (W2 + gamma + beta * ID2) - * t2 = (W3 + gamma + beta * ID3) * (W4 + gamma + beta * ID4) - * result = alpha_base * z_eval * t1 * t2 - * t1 = (W1 + gamma + beta * sigma_1_eval) * (W2 + gamma + beta * sigma_2_eval) - * t2 = (W2 + gamma + beta * sigma_3_eval) * (W3 + gamma + beta * sigma_4_eval) - * result -= (alpha_base * z_omega_eval * t1 * t2) - */ - let t1 := - mulmod( - add(add(mload(W1_EVAL_LOC), gamma), mulmod(beta, mload(ID1_EVAL_LOC), p)), - add(add(mload(W2_EVAL_LOC), gamma), mulmod(beta, mload(ID2_EVAL_LOC), p)), - p - ) - let t2 := - mulmod( - add(add(mload(W3_EVAL_LOC), gamma), mulmod(beta, mload(ID3_EVAL_LOC), p)), - add(add(mload(W4_EVAL_LOC), gamma), mulmod(beta, mload(ID4_EVAL_LOC), p)), - p - ) - let result := mulmod(mload(C_ALPHA_BASE_LOC), mulmod(mload(Z_EVAL_LOC), mulmod(t1, t2, p), p), p) - t1 := - mulmod( - add(add(mload(W1_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA1_EVAL_LOC), p)), - add(add(mload(W2_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA2_EVAL_LOC), p)), - p - ) - t2 := - mulmod( - add(add(mload(W3_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA3_EVAL_LOC), p)), - add(add(mload(W4_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA4_EVAL_LOC), p)), - p - ) - result := - addmod( - result, - sub(p, mulmod(mload(C_ALPHA_BASE_LOC), mulmod(mload(Z_OMEGA_EVAL_LOC), mulmod(t1, t2, p), p), p)), - p - ) - - /** - * alpha_base *= alpha - * result += alpha_base . (L_{n-k}(ʓ) . (z(ʓ.ω) - ∆_{PI})) - * alpha_base *= alpha - * result += alpha_base . (L_1(ʓ)(Z(ʓ) - 1)) - * alpha_Base *= alpha - */ - mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p)) - result := - addmod( - result, - mulmod( - mload(C_ALPHA_BASE_LOC), - mulmod( - mload(L_END_LOC), - addmod(mload(Z_OMEGA_EVAL_LOC), sub(p, mload(PUBLIC_INPUT_DELTA_LOC)), p), - p - ), - p - ), - p - ) - mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p)) - mstore( - PERMUTATION_IDENTITY, - addmod( - result, - mulmod( - mload(C_ALPHA_BASE_LOC), - mulmod(mload(L_START_LOC), addmod(mload(Z_EVAL_LOC), sub(p, 1), p), p), - p - ), - p - ) - ) - mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p)) - } - - /** - * COMPUTE PLOOKUP WIDGET EVALUATION - */ - { - /** - * Goal: f = (w1(z) + q2.w1(zω)) + η(w2(z) + qm.w2(zω)) + η²(w3(z) + qc.w_3(zω)) + q3(z).η³ - * f = η.q3(z) - * f += (w3(z) + qc.w_3(zω)) - * f *= η - * f += (w2(z) + qm.w2(zω)) - * f *= η - * f += (w1(z) + q2.w1(zω)) - */ - let f := mulmod(mload(C_ETA_LOC), mload(Q3_EVAL_LOC), p) - f := - addmod(f, addmod(mload(W3_EVAL_LOC), mulmod(mload(QC_EVAL_LOC), mload(W3_OMEGA_EVAL_LOC), p), p), p) - f := mulmod(f, mload(C_ETA_LOC), p) - f := - addmod(f, addmod(mload(W2_EVAL_LOC), mulmod(mload(QM_EVAL_LOC), mload(W2_OMEGA_EVAL_LOC), p), p), p) - f := mulmod(f, mload(C_ETA_LOC), p) - f := - addmod(f, addmod(mload(W1_EVAL_LOC), mulmod(mload(Q2_EVAL_LOC), mload(W1_OMEGA_EVAL_LOC), p), p), p) - - // t(z) = table4(z).η³ + table3(z).η² + table2(z).η + table1(z) - let t := - addmod( - addmod( - addmod( - mulmod(mload(TABLE4_EVAL_LOC), mload(C_ETA_CUBE_LOC), p), - mulmod(mload(TABLE3_EVAL_LOC), mload(C_ETA_SQR_LOC), p), - p - ), - mulmod(mload(TABLE2_EVAL_LOC), mload(C_ETA_LOC), p), - p - ), - mload(TABLE1_EVAL_LOC), - p - ) - - // t(zw) = table4(zw).η³ + table3(zw).η² + table2(zw).η + table1(zw) - let t_omega := - addmod( - addmod( - addmod( - mulmod(mload(TABLE4_OMEGA_EVAL_LOC), mload(C_ETA_CUBE_LOC), p), - mulmod(mload(TABLE3_OMEGA_EVAL_LOC), mload(C_ETA_SQR_LOC), p), - p - ), - mulmod(mload(TABLE2_OMEGA_EVAL_LOC), mload(C_ETA_LOC), p), - p - ), - mload(TABLE1_OMEGA_EVAL_LOC), - p - ) - - /** - * Goal: numerator = (TABLE_TYPE_EVAL * f(z) + γ) * (t(z) + βt(zω) + γ(β + 1)) * (β + 1) - * gamma_beta_constant = γ(β + 1) - * numerator = f * TABLE_TYPE_EVAL + gamma - * temp0 = t(z) + t(zω) * β + gamma_beta_constant - * numerator *= temp0 - * numerator *= (β + 1) - * temp0 = alpha * l_1 - * numerator += temp0 - * numerator *= z_lookup(z) - * numerator -= temp0 - */ - let gamma_beta_constant := mulmod(mload(C_GAMMA_LOC), addmod(mload(C_BETA_LOC), 1, p), p) - let numerator := addmod(mulmod(f, mload(TABLE_TYPE_EVAL_LOC), p), mload(C_GAMMA_LOC), p) - let temp0 := addmod(addmod(t, mulmod(t_omega, mload(C_BETA_LOC), p), p), gamma_beta_constant, p) - numerator := mulmod(numerator, temp0, p) - numerator := mulmod(numerator, addmod(mload(C_BETA_LOC), 1, p), p) - temp0 := mulmod(mload(C_ALPHA_LOC), mload(L_START_LOC), p) - numerator := addmod(numerator, temp0, p) - numerator := mulmod(numerator, mload(Z_LOOKUP_EVAL_LOC), p) - numerator := addmod(numerator, sub(p, temp0), p) - - /** - * Goal: denominator = z_lookup(zω)*[s(z) + βs(zω) + γ(1 + β)] - [z_lookup(zω) - [γ(1 + β)]^{n-k}]*α²L_end(z) - * note: delta_factor = [γ(1 + β)]^{n-k} - * denominator = s(z) + βs(zω) + γ(β + 1) - * temp1 = α²L_end(z) - * denominator -= temp1 - * denominator *= z_lookup(zω) - * denominator += temp1 * delta_factor - * PLOOKUP_IDENTITY = (numerator - denominator).alpha_base - * alpha_base *= alpha^3 - */ - let denominator := - addmod( - addmod(mload(S_EVAL_LOC), mulmod(mload(S_OMEGA_EVAL_LOC), mload(C_BETA_LOC), p), p), - gamma_beta_constant, - p - ) - let temp1 := mulmod(mload(C_ALPHA_SQR_LOC), mload(L_END_LOC), p) - denominator := addmod(denominator, sub(p, temp1), p) - denominator := mulmod(denominator, mload(Z_LOOKUP_OMEGA_EVAL_LOC), p) - denominator := addmod(denominator, mulmod(temp1, mload(PLOOKUP_DELTA_LOC), p), p) - - mstore(PLOOKUP_IDENTITY, mulmod(addmod(numerator, sub(p, denominator), p), mload(C_ALPHA_BASE_LOC), p)) - - // update alpha - mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_CUBE_LOC), p)) - } - - /** - * COMPUTE ARITHMETIC WIDGET EVALUATION - */ - { - /** - * The basic arithmetic gate identity in standard plonk is as follows. - * (w_1 . w_2 . q_m) + (w_1 . q_1) + (w_2 . q_2) + (w_3 . q_3) + (w_4 . q_4) + q_c = 0 - * However, for Ultraplonk, we extend this to support "passing" wires between rows (shown without alpha scaling below): - * q_arith * ( ( (-1/2) * (q_arith - 3) * q_m * w_1 * w_2 + q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c ) + - * (q_arith - 1)*( α * (q_arith - 2) * (w_1 + w_4 - w_1_omega + q_m) + w_4_omega) ) = 0 - * - * This formula results in several cases depending on q_arith: - * 1. q_arith == 0: Arithmetic gate is completely disabled - * - * 2. q_arith == 1: Everything in the minigate on the right is disabled. The equation is just a standard plonk equation - * with extra wires: q_m * w_1 * w_2 + q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c = 0 - * - * 3. q_arith == 2: The (w_1 + w_4 - ...) term is disabled. THe equation is: - * (1/2) * q_m * w_1 * w_2 + q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c + w_4_omega = 0 - * It allows defining w_4 at next index (w_4_omega) in terms of current wire values - * - * 4. q_arith == 3: The product of w_1 and w_2 is disabled, but a mini addition gate is enabled. α allows us to split - * the equation into two: - * - * q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c + 2 * w_4_omega = 0 - * and - * w_1 + w_4 - w_1_omega + q_m = 0 (we are reusing q_m here) - * - * 5. q_arith > 3: The product of w_1 and w_2 is scaled by (q_arith - 3), while the w_4_omega term is scaled by (q_arith - 1). - * The equation can be split into two: - * - * (q_arith - 3)* q_m * w_1 * w_ 2 + q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c + (q_arith - 1) * w_4_omega = 0 - * and - * w_1 + w_4 - w_1_omega + q_m = 0 - * - * The problem that q_m is used both in both equations can be dealt with by appropriately changing selector values at - * the next gate. Then we can treat (q_arith - 1) as a simulated q_6 selector and scale q_m to handle (q_arith - 3) at - * product. - */ - - let w1q1 := mulmod(mload(W1_EVAL_LOC), mload(Q1_EVAL_LOC), p) - let w2q2 := mulmod(mload(W2_EVAL_LOC), mload(Q2_EVAL_LOC), p) - let w3q3 := mulmod(mload(W3_EVAL_LOC), mload(Q3_EVAL_LOC), p) - let w4q3 := mulmod(mload(W4_EVAL_LOC), mload(Q4_EVAL_LOC), p) - - // @todo - Add a explicit test that hits QARITH == 3 - // w1w2qm := (w_1 . w_2 . q_m . (QARITH_EVAL_LOC - 3)) / 2 - let w1w2qm := - mulmod( - mulmod( - mulmod(mulmod(mload(W1_EVAL_LOC), mload(W2_EVAL_LOC), p), mload(QM_EVAL_LOC), p), - addmod(mload(QARITH_EVAL_LOC), sub(p, 3), p), - p - ), - NEGATIVE_INVERSE_OF_2_MODULO_P, - p - ) - - // (w_1 . w_2 . q_m . (q_arith - 3)) / -2) + (w_1 . q_1) + (w_2 . q_2) + (w_3 . q_3) + (w_4 . q_4) + q_c - let identity := - addmod( - mload(QC_EVAL_LOC), addmod(w4q3, addmod(w3q3, addmod(w2q2, addmod(w1q1, w1w2qm, p), p), p), p), p - ) - - // if q_arith == 3 we evaluate an additional mini addition gate (on top of the regular one), where: - // w_1 + w_4 - w_1_omega + q_m = 0 - // we use this gate to save an addition gate when adding or subtracting non-native field elements - // α * (q_arith - 2) * (w_1 + w_4 - w_1_omega + q_m) - let extra_small_addition_gate_identity := - mulmod( - mload(C_ALPHA_LOC), - mulmod( - addmod(mload(QARITH_EVAL_LOC), sub(p, 2), p), - addmod( - mload(QM_EVAL_LOC), - addmod( - sub(p, mload(W1_OMEGA_EVAL_LOC)), addmod(mload(W1_EVAL_LOC), mload(W4_EVAL_LOC), p), p - ), - p - ), - p - ), - p - ) - - // if q_arith == 2 OR q_arith == 3 we add the 4th wire of the NEXT gate into the arithmetic identity - // N.B. if q_arith > 2, this wire value will be scaled by (q_arith - 1) relative to the other gate wires! - // alpha_base * q_arith * (identity + (q_arith - 1) * (w_4_omega + extra_small_addition_gate_identity)) - mstore( - ARITHMETIC_IDENTITY, - mulmod( - mload(C_ALPHA_BASE_LOC), - mulmod( - mload(QARITH_EVAL_LOC), - addmod( - identity, - mulmod( - addmod(mload(QARITH_EVAL_LOC), sub(p, 1), p), - addmod(mload(W4_OMEGA_EVAL_LOC), extra_small_addition_gate_identity, p), - p - ), - p - ), - p - ), - p - ) - ) - - // update alpha - mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_SQR_LOC), p)) - } - - /** - * COMPUTE GENPERMSORT WIDGET EVALUATION - */ - { - /** - * D1 = (w2 - w1) - * D2 = (w3 - w2) - * D3 = (w4 - w3) - * D4 = (w1_omega - w4) - * - * α_a = alpha_base - * α_b = alpha_base * α - * α_c = alpha_base * α^2 - * α_d = alpha_base * α^3 - * - * range_accumulator = ( - * D1(D1 - 1)(D1 - 2)(D1 - 3).α_a + - * D2(D2 - 1)(D2 - 2)(D2 - 3).α_b + - * D3(D3 - 1)(D3 - 2)(D3 - 3).α_c + - * D4(D4 - 1)(D4 - 2)(D4 - 3).α_d + - * ) . q_sort - */ - let minus_two := sub(p, 2) - let minus_three := sub(p, 3) - let d1 := addmod(mload(W2_EVAL_LOC), sub(p, mload(W1_EVAL_LOC)), p) - let d2 := addmod(mload(W3_EVAL_LOC), sub(p, mload(W2_EVAL_LOC)), p) - let d3 := addmod(mload(W4_EVAL_LOC), sub(p, mload(W3_EVAL_LOC)), p) - let d4 := addmod(mload(W1_OMEGA_EVAL_LOC), sub(p, mload(W4_EVAL_LOC)), p) - - let range_accumulator := - mulmod( - mulmod( - mulmod(addmod(mulmod(d1, d1, p), sub(p, d1), p), addmod(d1, minus_two, p), p), - addmod(d1, minus_three, p), - p - ), - mload(C_ALPHA_BASE_LOC), - p - ) - range_accumulator := - addmod( - range_accumulator, - mulmod( - mulmod( - mulmod(addmod(mulmod(d2, d2, p), sub(p, d2), p), addmod(d2, minus_two, p), p), - addmod(d2, minus_three, p), - p - ), - mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p), - p - ), - p - ) - range_accumulator := - addmod( - range_accumulator, - mulmod( - mulmod( - mulmod(addmod(mulmod(d3, d3, p), sub(p, d3), p), addmod(d3, minus_two, p), p), - addmod(d3, minus_three, p), - p - ), - mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_SQR_LOC), p), - p - ), - p - ) - range_accumulator := - addmod( - range_accumulator, - mulmod( - mulmod( - mulmod(addmod(mulmod(d4, d4, p), sub(p, d4), p), addmod(d4, minus_two, p), p), - addmod(d4, minus_three, p), - p - ), - mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_CUBE_LOC), p), - p - ), - p - ) - range_accumulator := mulmod(range_accumulator, mload(QSORT_EVAL_LOC), p) - - mstore(SORT_IDENTITY, range_accumulator) - - // update alpha - mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_QUAD_LOC), p)) - } - - /** - * COMPUTE ELLIPTIC WIDGET EVALUATION - */ - { - /** - * endo_term = (-x_2) * x_1 * (x_3 * 2 + x_1) * q_beta - * endo_sqr_term = x_2^2 - * endo_sqr_term *= (x_3 - x_1) - * endo_sqr_term *= q_beta^2 - * leftovers = x_2^2 - * leftovers *= x_2 - * leftovers += x_1^2 * (x_3 + x_1) @follow-up Invalid comment in BB widget - * leftovers -= (y_2^2 + y_1^2) - * sign_term = y_2 * y_1 - * sign_term += sign_term - * sign_term *= q_sign - */ - // q_elliptic * (x3 + x2 + x1)(x2 - x1)(x2 - x1) - y2^2 - y1^2 + 2(y2y1)*q_sign = 0 - let x_diff := addmod(mload(X2_EVAL_LOC), sub(p, mload(X1_EVAL_LOC)), p) - let y2_sqr := mulmod(mload(Y2_EVAL_LOC), mload(Y2_EVAL_LOC), p) - let y1_sqr := mulmod(mload(Y1_EVAL_LOC), mload(Y1_EVAL_LOC), p) - let y1y2 := mulmod(mulmod(mload(Y1_EVAL_LOC), mload(Y2_EVAL_LOC), p), mload(QSIGN_LOC), p) - - let x_add_identity := - addmod( - mulmod( - addmod(mload(X3_EVAL_LOC), addmod(mload(X2_EVAL_LOC), mload(X1_EVAL_LOC), p), p), - mulmod(x_diff, x_diff, p), - p - ), - addmod( - sub( - p, - addmod(y2_sqr, y1_sqr, p) - ), - addmod(y1y2, y1y2, p), - p - ), - p - ) - x_add_identity := - mulmod( - mulmod( - x_add_identity, - addmod( - 1, - sub(p, mload(QM_EVAL_LOC)), - p - ), - p - ), - mload(C_ALPHA_BASE_LOC), - p - ) - - // q_elliptic * (x3 + x2 + x1)(x2 - x1)(x2 - x1) - y2^2 - y1^2 + 2(y2y1)*q_sign = 0 - let y1_plus_y3 := addmod( - mload(Y1_EVAL_LOC), - mload(Y3_EVAL_LOC), - p - ) - let y_diff := addmod(mulmod(mload(Y2_EVAL_LOC), mload(QSIGN_LOC), p), sub(p, mload(Y1_EVAL_LOC)), p) - let y_add_identity := - addmod( - mulmod(y1_plus_y3, x_diff, p), - mulmod(addmod(mload(X3_EVAL_LOC), sub(p, mload(X1_EVAL_LOC)), p), y_diff, p), - p - ) - y_add_identity := - mulmod( - mulmod(y_add_identity, addmod(1, sub(p, mload(QM_EVAL_LOC)), p), p), - mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p), - p - ) - - // ELLIPTIC_IDENTITY = (x_identity + y_identity) * Q_ELLIPTIC_EVAL - mstore( - ELLIPTIC_IDENTITY, mulmod(addmod(x_add_identity, y_add_identity, p), mload(QELLIPTIC_EVAL_LOC), p) - ) - } - { - /** - * x_pow_4 = (y_1_sqr - curve_b) * x_1; - * y_1_sqr_mul_4 = y_1_sqr + y_1_sqr; - * y_1_sqr_mul_4 += y_1_sqr_mul_4; - * x_1_pow_4_mul_9 = x_pow_4; - * x_1_pow_4_mul_9 += x_1_pow_4_mul_9; - * x_1_pow_4_mul_9 += x_1_pow_4_mul_9; - * x_1_pow_4_mul_9 += x_1_pow_4_mul_9; - * x_1_pow_4_mul_9 += x_pow_4; - * x_1_sqr_mul_3 = x_1_sqr + x_1_sqr + x_1_sqr; - * x_double_identity = (x_3 + x_1 + x_1) * y_1_sqr_mul_4 - x_1_pow_4_mul_9; - * y_double_identity = x_1_sqr_mul_3 * (x_1 - x_3) - (y_1 + y_1) * (y_1 + y_3); - */ - // (x3 + x1 + x1) (4y1*y1) - 9 * x1 * x1 * x1 * x1 = 0 - let x1_sqr := mulmod(mload(X1_EVAL_LOC), mload(X1_EVAL_LOC), p) - let y1_sqr := mulmod(mload(Y1_EVAL_LOC), mload(Y1_EVAL_LOC), p) - let x_pow_4 := mulmod(addmod(y1_sqr, GRUMPKIN_CURVE_B_PARAMETER_NEGATED, p), mload(X1_EVAL_LOC), p) - let y1_sqr_mul_4 := mulmod(y1_sqr, 4, p) - let x1_pow_4_mul_9 := mulmod(x_pow_4, 9, p) - let x1_sqr_mul_3 := mulmod(x1_sqr, 3, p) - let x_double_identity := - addmod( - mulmod( - addmod(mload(X3_EVAL_LOC), addmod(mload(X1_EVAL_LOC), mload(X1_EVAL_LOC), p), p), - y1_sqr_mul_4, - p - ), - sub(p, x1_pow_4_mul_9), - p - ) - // (y1 + y1) (2y1) - (3 * x1 * x1)(x1 - x3) = 0 - let y_double_identity := - addmod( - mulmod(x1_sqr_mul_3, addmod(mload(X1_EVAL_LOC), sub(p, mload(X3_EVAL_LOC)), p), p), - sub( - p, - mulmod( - addmod(mload(Y1_EVAL_LOC), mload(Y1_EVAL_LOC), p), - addmod(mload(Y1_EVAL_LOC), mload(Y3_EVAL_LOC), p), - p - ) - ), - p - ) - x_double_identity := mulmod(x_double_identity, mload(C_ALPHA_BASE_LOC), p) - y_double_identity := - mulmod(y_double_identity, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p), p) - x_double_identity := mulmod(x_double_identity, mload(QM_EVAL_LOC), p) - y_double_identity := mulmod(y_double_identity, mload(QM_EVAL_LOC), p) - // ELLIPTIC_IDENTITY += (x_double_identity + y_double_identity) * Q_DOUBLE_EVAL - mstore( - ELLIPTIC_IDENTITY, - addmod( - mload(ELLIPTIC_IDENTITY), - mulmod(addmod(x_double_identity, y_double_identity, p), mload(QELLIPTIC_EVAL_LOC), p), - p - ) - ) - - // update alpha - mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_QUAD_LOC), p)) - } - - /** - * COMPUTE AUXILIARY WIDGET EVALUATION - */ - { - { - /** - * Non native field arithmetic gate 2 - * _ _ - * / _ _ _ 14 \ - * q_2 . q_4 | (w_1 . w_2) + (w_1 . w_2) + (w_1 . w_4 + w_2 . w_3 - w_3) . 2 - w_3 - w_4 | - * \_ _/ - * - * limb_subproduct = w_1 . w_2_omega + w_1_omega . w_2 - * non_native_field_gate_2 = w_1 * w_4 + w_4 * w_3 - w_3_omega - * non_native_field_gate_2 = non_native_field_gate_2 * limb_size - * non_native_field_gate_2 -= w_4_omega - * non_native_field_gate_2 += limb_subproduct - * non_native_field_gate_2 *= q_4 - * limb_subproduct *= limb_size - * limb_subproduct += w_1_omega * w_2_omega - * non_native_field_gate_1 = (limb_subproduct + w_3 + w_4) * q_3 - * non_native_field_gate_3 = (limb_subproduct + w_4 - (w_3_omega + w_4_omega)) * q_m - * non_native_field_identity = (non_native_field_gate_1 + non_native_field_gate_2 + non_native_field_gate_3) * q_2 - */ - - let limb_subproduct := - addmod( - mulmod(mload(W1_EVAL_LOC), mload(W2_OMEGA_EVAL_LOC), p), - mulmod(mload(W1_OMEGA_EVAL_LOC), mload(W2_EVAL_LOC), p), - p - ) - - let non_native_field_gate_2 := - addmod( - addmod( - mulmod(mload(W1_EVAL_LOC), mload(W4_EVAL_LOC), p), - mulmod(mload(W2_EVAL_LOC), mload(W3_EVAL_LOC), p), - p - ), - sub(p, mload(W3_OMEGA_EVAL_LOC)), - p - ) - non_native_field_gate_2 := mulmod(non_native_field_gate_2, LIMB_SIZE, p) - non_native_field_gate_2 := addmod(non_native_field_gate_2, sub(p, mload(W4_OMEGA_EVAL_LOC)), p) - non_native_field_gate_2 := addmod(non_native_field_gate_2, limb_subproduct, p) - non_native_field_gate_2 := mulmod(non_native_field_gate_2, mload(Q4_EVAL_LOC), p) - limb_subproduct := mulmod(limb_subproduct, LIMB_SIZE, p) - limb_subproduct := - addmod(limb_subproduct, mulmod(mload(W1_OMEGA_EVAL_LOC), mload(W2_OMEGA_EVAL_LOC), p), p) - let non_native_field_gate_1 := - mulmod( - addmod(limb_subproduct, sub(p, addmod(mload(W3_EVAL_LOC), mload(W4_EVAL_LOC), p)), p), - mload(Q3_EVAL_LOC), - p - ) - let non_native_field_gate_3 := - mulmod( - addmod( - addmod(limb_subproduct, mload(W4_EVAL_LOC), p), - sub(p, addmod(mload(W3_OMEGA_EVAL_LOC), mload(W4_OMEGA_EVAL_LOC), p)), - p - ), - mload(QM_EVAL_LOC), - p - ) - let non_native_field_identity := - mulmod( - addmod(addmod(non_native_field_gate_1, non_native_field_gate_2, p), non_native_field_gate_3, p), - mload(Q2_EVAL_LOC), - p - ) - - mstore(AUX_NON_NATIVE_FIELD_EVALUATION, non_native_field_identity) - } - - { - /** - * limb_accumulator_1 = w_2_omega; - * limb_accumulator_1 *= SUBLIMB_SHIFT; - * limb_accumulator_1 += w_1_omega; - * limb_accumulator_1 *= SUBLIMB_SHIFT; - * limb_accumulator_1 += w_3; - * limb_accumulator_1 *= SUBLIMB_SHIFT; - * limb_accumulator_1 += w_2; - * limb_accumulator_1 *= SUBLIMB_SHIFT; - * limb_accumulator_1 += w_1; - * limb_accumulator_1 -= w_4; - * limb_accumulator_1 *= q_4; - */ - let limb_accumulator_1 := mulmod(mload(W2_OMEGA_EVAL_LOC), SUBLIMB_SHIFT, p) - limb_accumulator_1 := addmod(limb_accumulator_1, mload(W1_OMEGA_EVAL_LOC), p) - limb_accumulator_1 := mulmod(limb_accumulator_1, SUBLIMB_SHIFT, p) - limb_accumulator_1 := addmod(limb_accumulator_1, mload(W3_EVAL_LOC), p) - limb_accumulator_1 := mulmod(limb_accumulator_1, SUBLIMB_SHIFT, p) - limb_accumulator_1 := addmod(limb_accumulator_1, mload(W2_EVAL_LOC), p) - limb_accumulator_1 := mulmod(limb_accumulator_1, SUBLIMB_SHIFT, p) - limb_accumulator_1 := addmod(limb_accumulator_1, mload(W1_EVAL_LOC), p) - limb_accumulator_1 := addmod(limb_accumulator_1, sub(p, mload(W4_EVAL_LOC)), p) - limb_accumulator_1 := mulmod(limb_accumulator_1, mload(Q4_EVAL_LOC), p) - - /** - * limb_accumulator_2 = w_3_omega; - * limb_accumulator_2 *= SUBLIMB_SHIFT; - * limb_accumulator_2 += w_2_omega; - * limb_accumulator_2 *= SUBLIMB_SHIFT; - * limb_accumulator_2 += w_1_omega; - * limb_accumulator_2 *= SUBLIMB_SHIFT; - * limb_accumulator_2 += w_4; - * limb_accumulator_2 *= SUBLIMB_SHIFT; - * limb_accumulator_2 += w_3; - * limb_accumulator_2 -= w_4_omega; - * limb_accumulator_2 *= q_m; - */ - let limb_accumulator_2 := mulmod(mload(W3_OMEGA_EVAL_LOC), SUBLIMB_SHIFT, p) - limb_accumulator_2 := addmod(limb_accumulator_2, mload(W2_OMEGA_EVAL_LOC), p) - limb_accumulator_2 := mulmod(limb_accumulator_2, SUBLIMB_SHIFT, p) - limb_accumulator_2 := addmod(limb_accumulator_2, mload(W1_OMEGA_EVAL_LOC), p) - limb_accumulator_2 := mulmod(limb_accumulator_2, SUBLIMB_SHIFT, p) - limb_accumulator_2 := addmod(limb_accumulator_2, mload(W4_EVAL_LOC), p) - limb_accumulator_2 := mulmod(limb_accumulator_2, SUBLIMB_SHIFT, p) - limb_accumulator_2 := addmod(limb_accumulator_2, mload(W3_EVAL_LOC), p) - limb_accumulator_2 := addmod(limb_accumulator_2, sub(p, mload(W4_OMEGA_EVAL_LOC)), p) - limb_accumulator_2 := mulmod(limb_accumulator_2, mload(QM_EVAL_LOC), p) - - mstore( - AUX_LIMB_ACCUMULATOR_EVALUATION, - mulmod(addmod(limb_accumulator_1, limb_accumulator_2, p), mload(Q3_EVAL_LOC), p) - ) - } - - { - /** - * memory_record_check = w_3; - * memory_record_check *= eta; - * memory_record_check += w_2; - * memory_record_check *= eta; - * memory_record_check += w_1; - * memory_record_check *= eta; - * memory_record_check += q_c; - * - * partial_record_check = memory_record_check; - * - * memory_record_check -= w_4; - */ - - let memory_record_check := mulmod(mload(W3_EVAL_LOC), mload(C_ETA_LOC), p) - memory_record_check := addmod(memory_record_check, mload(W2_EVAL_LOC), p) - memory_record_check := mulmod(memory_record_check, mload(C_ETA_LOC), p) - memory_record_check := addmod(memory_record_check, mload(W1_EVAL_LOC), p) - memory_record_check := mulmod(memory_record_check, mload(C_ETA_LOC), p) - memory_record_check := addmod(memory_record_check, mload(QC_EVAL_LOC), p) - - let partial_record_check := memory_record_check - memory_record_check := addmod(memory_record_check, sub(p, mload(W4_EVAL_LOC)), p) - - mstore(AUX_MEMORY_EVALUATION, memory_record_check) - - // index_delta = w_1_omega - w_1 - let index_delta := addmod(mload(W1_OMEGA_EVAL_LOC), sub(p, mload(W1_EVAL_LOC)), p) - // record_delta = w_4_omega - w_4 - let record_delta := addmod(mload(W4_OMEGA_EVAL_LOC), sub(p, mload(W4_EVAL_LOC)), p) - // index_is_monotonically_increasing = index_delta * (index_delta - 1) - let index_is_monotonically_increasing := mulmod(index_delta, addmod(index_delta, sub(p, 1), p), p) - - // adjacent_values_match_if_adjacent_indices_match = record_delta * (1 - index_delta) - let adjacent_values_match_if_adjacent_indices_match := - mulmod(record_delta, addmod(1, sub(p, index_delta), p), p) - - // AUX_ROM_CONSISTENCY_EVALUATION = ((adjacent_values_match_if_adjacent_indices_match * alpha) + index_is_monotonically_increasing) * alpha + partial_record_check - mstore( - AUX_ROM_CONSISTENCY_EVALUATION, - addmod( - mulmod( - addmod( - mulmod(adjacent_values_match_if_adjacent_indices_match, mload(C_ALPHA_LOC), p), - index_is_monotonically_increasing, - p - ), - mload(C_ALPHA_LOC), - p - ), - memory_record_check, - p - ) - ) - - { - /** - * next_gate_access_type = w_3_omega; - * next_gate_access_type *= eta; - * next_gate_access_type += w_2_omega; - * next_gate_access_type *= eta; - * next_gate_access_type += w_1_omega; - * next_gate_access_type *= eta; - * next_gate_access_type = w_4_omega - next_gate_access_type; - */ - let next_gate_access_type := mulmod(mload(W3_OMEGA_EVAL_LOC), mload(C_ETA_LOC), p) - next_gate_access_type := addmod(next_gate_access_type, mload(W2_OMEGA_EVAL_LOC), p) - next_gate_access_type := mulmod(next_gate_access_type, mload(C_ETA_LOC), p) - next_gate_access_type := addmod(next_gate_access_type, mload(W1_OMEGA_EVAL_LOC), p) - next_gate_access_type := mulmod(next_gate_access_type, mload(C_ETA_LOC), p) - next_gate_access_type := addmod(mload(W4_OMEGA_EVAL_LOC), sub(p, next_gate_access_type), p) - - // value_delta = w_3_omega - w_3 - let value_delta := addmod(mload(W3_OMEGA_EVAL_LOC), sub(p, mload(W3_EVAL_LOC)), p) - // adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation = (1 - index_delta) * value_delta * (1 - next_gate_access_type); - - let adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation := - mulmod( - addmod(1, sub(p, index_delta), p), - mulmod(value_delta, addmod(1, sub(p, next_gate_access_type), p), p), - p - ) - - // AUX_RAM_CONSISTENCY_EVALUATION - - /** - * access_type = w_4 - partial_record_check - * access_check = access_type^2 - access_type - * next_gate_access_type_is_boolean = next_gate_access_type^2 - next_gate_access_type - * RAM_consistency_check_identity = adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation; - * RAM_consistency_check_identity *= alpha; - * RAM_consistency_check_identity += index_is_monotonically_increasing; - * RAM_consistency_check_identity *= alpha; - * RAM_consistency_check_identity += next_gate_access_type_is_boolean; - * RAM_consistency_check_identity *= alpha; - * RAM_consistency_check_identity += access_check; - */ - - let access_type := addmod(mload(W4_EVAL_LOC), sub(p, partial_record_check), p) - let access_check := mulmod(access_type, addmod(access_type, sub(p, 1), p), p) - let next_gate_access_type_is_boolean := - mulmod(next_gate_access_type, addmod(next_gate_access_type, sub(p, 1), p), p) - let RAM_cci := - mulmod( - adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation, - mload(C_ALPHA_LOC), - p - ) - RAM_cci := addmod(RAM_cci, index_is_monotonically_increasing, p) - RAM_cci := mulmod(RAM_cci, mload(C_ALPHA_LOC), p) - RAM_cci := addmod(RAM_cci, next_gate_access_type_is_boolean, p) - RAM_cci := mulmod(RAM_cci, mload(C_ALPHA_LOC), p) - RAM_cci := addmod(RAM_cci, access_check, p) - - mstore(AUX_RAM_CONSISTENCY_EVALUATION, RAM_cci) - } - - { - // timestamp_delta = w_2_omega - w_2 - let timestamp_delta := addmod(mload(W2_OMEGA_EVAL_LOC), sub(p, mload(W2_EVAL_LOC)), p) - - // RAM_timestamp_check_identity = (1 - index_delta) * timestamp_delta - w_3 - let RAM_timestamp_check_identity := - addmod( - mulmod(timestamp_delta, addmod(1, sub(p, index_delta), p), p), sub(p, mload(W3_EVAL_LOC)), p - ) - - /** - * memory_identity = ROM_consistency_check_identity * q_2; - * memory_identity += RAM_timestamp_check_identity * q_4; - * memory_identity += memory_record_check * q_m; - * memory_identity *= q_1; - * memory_identity += (RAM_consistency_check_identity * q_arith); - * - * auxiliary_identity = memory_identity + non_native_field_identity + limb_accumulator_identity; - * auxiliary_identity *= q_aux; - * auxiliary_identity *= alpha_base; - */ - let memory_identity := mulmod(mload(AUX_ROM_CONSISTENCY_EVALUATION), mload(Q2_EVAL_LOC), p) - memory_identity := - addmod(memory_identity, mulmod(RAM_timestamp_check_identity, mload(Q4_EVAL_LOC), p), p) - memory_identity := - addmod(memory_identity, mulmod(mload(AUX_MEMORY_EVALUATION), mload(QM_EVAL_LOC), p), p) - memory_identity := mulmod(memory_identity, mload(Q1_EVAL_LOC), p) - memory_identity := - addmod( - memory_identity, mulmod(mload(AUX_RAM_CONSISTENCY_EVALUATION), mload(QARITH_EVAL_LOC), p), p - ) - - let auxiliary_identity := addmod(memory_identity, mload(AUX_NON_NATIVE_FIELD_EVALUATION), p) - auxiliary_identity := addmod(auxiliary_identity, mload(AUX_LIMB_ACCUMULATOR_EVALUATION), p) - auxiliary_identity := mulmod(auxiliary_identity, mload(QAUX_EVAL_LOC), p) - auxiliary_identity := mulmod(auxiliary_identity, mload(C_ALPHA_BASE_LOC), p) - - mstore(AUX_IDENTITY, auxiliary_identity) - - // update alpha - mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_CUBE_LOC), p)) - } - } - } - - { - /** - * quotient = ARITHMETIC_IDENTITY - * quotient += PERMUTATION_IDENTITY - * quotient += PLOOKUP_IDENTITY - * quotient += SORT_IDENTITY - * quotient += ELLIPTIC_IDENTITY - * quotient += AUX_IDENTITY - * quotient *= ZERO_POLY_INVERSE - */ - mstore( - QUOTIENT_EVAL_LOC, - mulmod( - addmod( - addmod( - addmod( - addmod( - addmod(mload(PERMUTATION_IDENTITY), mload(PLOOKUP_IDENTITY), p), - mload(ARITHMETIC_IDENTITY), - p - ), - mload(SORT_IDENTITY), - p - ), - mload(ELLIPTIC_IDENTITY), - p - ), - mload(AUX_IDENTITY), - p - ), - mload(ZERO_POLY_INVERSE_LOC), - p - ) - ) - } - - /** - * GENERATE NU AND SEPARATOR CHALLENGES - */ - { - let current_challenge := mload(C_CURRENT_LOC) - // get a calldata pointer that points to the start of the data we want to copy - let calldata_ptr := add(calldataload(0x04), 0x24) - - calldata_ptr := add(calldata_ptr, NU_CALLDATA_SKIP_LENGTH) - - mstore(NU_CHALLENGE_INPUT_LOC_A, current_challenge) - mstore(NU_CHALLENGE_INPUT_LOC_B, mload(QUOTIENT_EVAL_LOC)) - calldatacopy(NU_CHALLENGE_INPUT_LOC_C, calldata_ptr, NU_INPUT_LENGTH) - - // hash length = (0x20 + num field elements), we include the previous challenge in the hash - let challenge := keccak256(NU_CHALLENGE_INPUT_LOC_A, add(NU_INPUT_LENGTH, 0x40)) - - mstore(C_V0_LOC, mod(challenge, p)) - // We need THIRTY-ONE independent nu challenges! - mstore(0x00, challenge) - mstore8(0x20, 0x01) - mstore(C_V1_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x02) - mstore(C_V2_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x03) - mstore(C_V3_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x04) - mstore(C_V4_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x05) - mstore(C_V5_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x06) - mstore(C_V6_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x07) - mstore(C_V7_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x08) - mstore(C_V8_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x09) - mstore(C_V9_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x0a) - mstore(C_V10_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x0b) - mstore(C_V11_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x0c) - mstore(C_V12_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x0d) - mstore(C_V13_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x0e) - mstore(C_V14_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x0f) - mstore(C_V15_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x10) - mstore(C_V16_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x11) - mstore(C_V17_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x12) - mstore(C_V18_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x13) - mstore(C_V19_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x14) - mstore(C_V20_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x15) - mstore(C_V21_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x16) - mstore(C_V22_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x17) - mstore(C_V23_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x18) - mstore(C_V24_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x19) - mstore(C_V25_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x1a) - mstore(C_V26_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x1b) - mstore(C_V27_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x1c) - mstore(C_V28_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x1d) - mstore(C_V29_LOC, mod(keccak256(0x00, 0x21), p)) - - // @follow-up - Why are both v29 and v30 using appending 0x1d to the prior challenge and hashing, should it not change? - mstore8(0x20, 0x1d) - challenge := keccak256(0x00, 0x21) - mstore(C_V30_LOC, mod(challenge, p)) - - // separator - mstore(0x00, challenge) - mstore(0x20, mload(PI_Z_Y_LOC)) - mstore(0x40, mload(PI_Z_X_LOC)) - mstore(0x60, mload(PI_Z_OMEGA_Y_LOC)) - mstore(0x80, mload(PI_Z_OMEGA_X_LOC)) - - mstore(C_U_LOC, mod(keccak256(0x00, 0xa0), p)) - } - - let success := 0 - // VALIDATE T1 - { - let x := mload(T1_X_LOC) - let y := mload(T1_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(ACCUMULATOR_X_LOC, x) - mstore(add(ACCUMULATOR_X_LOC, 0x20), y) - } - // VALIDATE T2 - { - let x := mload(T2_X_LOC) // 0x1400 - let y := mload(T2_Y_LOC) // 0x1420 - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(ZETA_POW_N_LOC)) - // accumulator_2 = [T2].zeta^n - success := staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40) - // accumulator = [T1] + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE T3 - { - let x := mload(T3_X_LOC) - let y := mload(T3_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(mload(ZETA_POW_N_LOC), mload(ZETA_POW_N_LOC), p)) - // accumulator_2 = [T3].zeta^{2n} - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE T4 - { - let x := mload(T4_X_LOC) - let y := mload(T4_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(mulmod(mload(ZETA_POW_N_LOC), mload(ZETA_POW_N_LOC), p), mload(ZETA_POW_N_LOC), p)) - // accumulator_2 = [T4].zeta^{3n} - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE W1 - { - let x := mload(W1_X_LOC) - let y := mload(W1_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V0_LOC), p)) - // accumulator_2 = v0.(u + 1).[W1] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE W2 - { - let x := mload(W2_X_LOC) - let y := mload(W2_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V1_LOC), p)) - // accumulator_2 = v1.(u + 1).[W2] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE W3 - { - let x := mload(W3_X_LOC) - let y := mload(W3_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V2_LOC), p)) - // accumulator_2 = v2.(u + 1).[W3] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE W4 - { - let x := mload(W4_X_LOC) - let y := mload(W4_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V3_LOC), p)) - // accumulator_2 = v3.(u + 1).[W4] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE S - { - let x := mload(S_X_LOC) - let y := mload(S_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V4_LOC), p)) - // accumulator_2 = v4.(u + 1).[S] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE Z - { - let x := mload(Z_X_LOC) - let y := mload(Z_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V5_LOC), p)) - // accumulator_2 = v5.(u + 1).[Z] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE Z_LOOKUP - { - let x := mload(Z_LOOKUP_X_LOC) - let y := mload(Z_LOOKUP_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V6_LOC), p)) - // accumulator_2 = v6.(u + 1).[Z_LOOKUP] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE Q1 - { - let x := mload(Q1_X_LOC) - let y := mload(Q1_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V7_LOC)) - // accumulator_2 = v7.[Q1] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE Q2 - { - let x := mload(Q2_X_LOC) - let y := mload(Q2_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V8_LOC)) - // accumulator_2 = v8.[Q2] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE Q3 - { - let x := mload(Q3_X_LOC) - let y := mload(Q3_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V9_LOC)) - // accumulator_2 = v9.[Q3] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE Q4 - { - let x := mload(Q4_X_LOC) - let y := mload(Q4_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V10_LOC)) - // accumulator_2 = v10.[Q4] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE QM - { - let x := mload(QM_X_LOC) - let y := mload(QM_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V11_LOC)) - // accumulator_2 = v11.[Q;] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE QC - { - let x := mload(QC_X_LOC) - let y := mload(QC_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V12_LOC)) - // accumulator_2 = v12.[QC] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE QARITH - { - let x := mload(QARITH_X_LOC) - let y := mload(QARITH_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V13_LOC)) - // accumulator_2 = v13.[QARITH] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE QSORT - { - let x := mload(QSORT_X_LOC) - let y := mload(QSORT_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V14_LOC)) - // accumulator_2 = v14.[QSORT] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE QELLIPTIC - { - let x := mload(QELLIPTIC_X_LOC) - let y := mload(QELLIPTIC_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V15_LOC)) - // accumulator_2 = v15.[QELLIPTIC] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE QAUX - { - let x := mload(QAUX_X_LOC) - let y := mload(QAUX_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V16_LOC)) - // accumulator_2 = v15.[Q_AUX] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE SIGMA1 - { - let x := mload(SIGMA1_X_LOC) - let y := mload(SIGMA1_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V17_LOC)) - // accumulator_2 = v17.[sigma1] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE SIGMA2 - { - let x := mload(SIGMA2_X_LOC) - let y := mload(SIGMA2_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V18_LOC)) - // accumulator_2 = v18.[sigma2] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE SIGMA3 - { - let x := mload(SIGMA3_X_LOC) - let y := mload(SIGMA3_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V19_LOC)) - // accumulator_2 = v19.[sigma3] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE SIGMA4 - { - let x := mload(SIGMA4_X_LOC) - let y := mload(SIGMA4_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V20_LOC)) - // accumulator_2 = v20.[sigma4] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE TABLE1 - { - let x := mload(TABLE1_X_LOC) - let y := mload(TABLE1_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V21_LOC), p)) - // accumulator_2 = u.[table1] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE TABLE2 - { - let x := mload(TABLE2_X_LOC) - let y := mload(TABLE2_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V22_LOC), p)) - // accumulator_2 = u.[table2] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE TABLE3 - { - let x := mload(TABLE3_X_LOC) - let y := mload(TABLE3_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V23_LOC), p)) - // accumulator_2 = u.[table3] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE TABLE4 - { - let x := mload(TABLE4_X_LOC) - let y := mload(TABLE4_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V24_LOC), p)) - // accumulator_2 = u.[table4] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE TABLE_TYPE - { - let x := mload(TABLE_TYPE_X_LOC) - let y := mload(TABLE_TYPE_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V25_LOC)) - // accumulator_2 = v25.[TableType] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE ID1 - { - let x := mload(ID1_X_LOC) - let y := mload(ID1_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V26_LOC)) - // accumulator_2 = v26.[ID1] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE ID2 - { - let x := mload(ID2_X_LOC) - let y := mload(ID2_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V27_LOC)) - // accumulator_2 = v27.[ID2] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE ID3 - { - let x := mload(ID3_X_LOC) - let y := mload(ID3_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V28_LOC)) - // accumulator_2 = v28.[ID3] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE ID4 - { - let x := mload(ID4_X_LOC) - let y := mload(ID4_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V29_LOC)) - // accumulator_2 = v29.[ID4] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - /** - * COMPUTE BATCH EVALUATION SCALAR MULTIPLIER - */ - { - /** - * batch_evaluation = v0 * (w_1_omega * u + w_1_eval) - * batch_evaluation += v1 * (w_2_omega * u + w_2_eval) - * batch_evaluation += v2 * (w_3_omega * u + w_3_eval) - * batch_evaluation += v3 * (w_4_omega * u + w_4_eval) - * batch_evaluation += v4 * (s_omega_eval * u + s_eval) - * batch_evaluation += v5 * (z_omega_eval * u + z_eval) - * batch_evaluation += v6 * (z_lookup_omega_eval * u + z_lookup_eval) - */ - let batch_evaluation := - mulmod( - mload(C_V0_LOC), - addmod(mulmod(mload(W1_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W1_EVAL_LOC), p), - p - ) - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V1_LOC), - addmod(mulmod(mload(W2_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W2_EVAL_LOC), p), - p - ), - p - ) - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V2_LOC), - addmod(mulmod(mload(W3_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W3_EVAL_LOC), p), - p - ), - p - ) - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V3_LOC), - addmod(mulmod(mload(W4_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W4_EVAL_LOC), p), - p - ), - p - ) - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V4_LOC), - addmod(mulmod(mload(S_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(S_EVAL_LOC), p), - p - ), - p - ) - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V5_LOC), - addmod(mulmod(mload(Z_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(Z_EVAL_LOC), p), - p - ), - p - ) - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V6_LOC), - addmod(mulmod(mload(Z_LOOKUP_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(Z_LOOKUP_EVAL_LOC), p), - p - ), - p - ) - - /** - * batch_evaluation += v7 * Q1_EVAL - * batch_evaluation += v8 * Q2_EVAL - * batch_evaluation += v9 * Q3_EVAL - * batch_evaluation += v10 * Q4_EVAL - * batch_evaluation += v11 * QM_EVAL - * batch_evaluation += v12 * QC_EVAL - * batch_evaluation += v13 * QARITH_EVAL - * batch_evaluation += v14 * QSORT_EVAL_LOC - * batch_evaluation += v15 * QELLIPTIC_EVAL_LOC - * batch_evaluation += v16 * QAUX_EVAL_LOC - * batch_evaluation += v17 * SIGMA1_EVAL_LOC - * batch_evaluation += v18 * SIGMA2_EVAL_LOC - * batch_evaluation += v19 * SIGMA3_EVAL_LOC - * batch_evaluation += v20 * SIGMA4_EVAL_LOC - */ - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V7_LOC), mload(Q1_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V8_LOC), mload(Q2_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V9_LOC), mload(Q3_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V10_LOC), mload(Q4_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V11_LOC), mload(QM_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V12_LOC), mload(QC_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V13_LOC), mload(QARITH_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V14_LOC), mload(QSORT_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V15_LOC), mload(QELLIPTIC_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V16_LOC), mload(QAUX_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V17_LOC), mload(SIGMA1_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V18_LOC), mload(SIGMA2_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V19_LOC), mload(SIGMA3_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V20_LOC), mload(SIGMA4_EVAL_LOC), p), p) - - /** - * batch_evaluation += v21 * (table1(zw) * u + table1(z)) - * batch_evaluation += v22 * (table2(zw) * u + table2(z)) - * batch_evaluation += v23 * (table3(zw) * u + table3(z)) - * batch_evaluation += v24 * (table4(zw) * u + table4(z)) - * batch_evaluation += v25 * table_type_eval - * batch_evaluation += v26 * id1_eval - * batch_evaluation += v27 * id2_eval - * batch_evaluation += v28 * id3_eval - * batch_evaluation += v29 * id4_eval - * batch_evaluation += quotient_eval - */ - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V21_LOC), - addmod(mulmod(mload(TABLE1_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE1_EVAL_LOC), p), - p - ), - p - ) - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V22_LOC), - addmod(mulmod(mload(TABLE2_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE2_EVAL_LOC), p), - p - ), - p - ) - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V23_LOC), - addmod(mulmod(mload(TABLE3_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE3_EVAL_LOC), p), - p - ), - p - ) - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V24_LOC), - addmod(mulmod(mload(TABLE4_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE4_EVAL_LOC), p), - p - ), - p - ) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V25_LOC), mload(TABLE_TYPE_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V26_LOC), mload(ID1_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V27_LOC), mload(ID2_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V28_LOC), mload(ID3_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V29_LOC), mload(ID4_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mload(QUOTIENT_EVAL_LOC), p) - - mstore(0x00, 0x01) // [1].x - mstore(0x20, 0x02) // [1].y - mstore(0x40, sub(p, batch_evaluation)) - // accumulator_2 = -[1].(batch_evaluation) - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - if iszero(success) { - mstore(0x0, OPENING_COMMITMENT_FAILED_SELECTOR) - revert(0x00, 0x04) - } - } - - /** - * PERFORM PAIRING PREAMBLE - */ - { - let u := mload(C_U_LOC) - let zeta := mload(C_ZETA_LOC) - // VALIDATE PI_Z - { - let x := mload(PI_Z_X_LOC) - let y := mload(PI_Z_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - // compute zeta.[PI_Z] and add into accumulator - mstore(0x40, zeta) - success := staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE PI_Z_OMEGA - { - let x := mload(PI_Z_OMEGA_X_LOC) - let y := mload(PI_Z_OMEGA_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(mulmod(u, zeta, p), mload(OMEGA_LOC), p)) - // accumulator_2 = u.zeta.omega.[PI_Z_OMEGA] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // PAIRING_RHS = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, PAIRING_RHS_X_LOC, 0x40)) - - mstore(0x00, mload(PI_Z_X_LOC)) - mstore(0x20, mload(PI_Z_Y_LOC)) - mstore(0x40, mload(PI_Z_OMEGA_X_LOC)) - mstore(0x60, mload(PI_Z_OMEGA_Y_LOC)) - mstore(0x80, u) - success := and(success, staticcall(gas(), 7, 0x40, 0x60, 0x40, 0x40)) - // PAIRING_LHS = [PI_Z] + [PI_Z_OMEGA] * u - success := and(success, staticcall(gas(), 6, 0x00, 0x80, PAIRING_LHS_X_LOC, 0x40)) - // negate lhs y-coordinate - mstore(PAIRING_LHS_Y_LOC, sub(q, mload(PAIRING_LHS_Y_LOC))) - - if mload(CONTAINS_RECURSIVE_PROOF_LOC) { - // VALIDATE RECURSIVE P1 - { - let x := mload(RECURSIVE_P1_X_LOC) - let y := mload(RECURSIVE_P1_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - - // compute u.u.[recursive_p1] and write into 0x60 - mstore(0x40, mulmod(u, u, p)) - success := and(success, staticcall(gas(), 7, 0x00, 0x60, 0x60, 0x40)) - // VALIDATE RECURSIVE P2 - { - let x := mload(RECURSIVE_P2_X_LOC) - let y := mload(RECURSIVE_P2_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - // compute u.u.[recursive_p2] and write into 0x00 - // 0x40 still contains u*u - success := and(success, staticcall(gas(), 7, 0x00, 0x60, 0x00, 0x40)) - - // compute u.u.[recursiveP1] + rhs and write into rhs - mstore(0xa0, mload(PAIRING_RHS_X_LOC)) - mstore(0xc0, mload(PAIRING_RHS_Y_LOC)) - success := and(success, staticcall(gas(), 6, 0x60, 0x80, PAIRING_RHS_X_LOC, 0x40)) - - // compute u.u.[recursiveP2] + lhs and write into lhs - mstore(0x40, mload(PAIRING_LHS_X_LOC)) - mstore(0x60, mload(PAIRING_LHS_Y_LOC)) - success := and(success, staticcall(gas(), 6, 0x00, 0x80, PAIRING_LHS_X_LOC, 0x40)) - } - - if iszero(success) { - mstore(0x0, PAIRING_PREAMBLE_FAILED_SELECTOR) - revert(0x00, 0x04) - } - } - - /** - * PERFORM PAIRING - */ - { - // rhs paired with [1]_2 - // lhs paired with [x]_2 - - mstore(0x00, mload(PAIRING_RHS_X_LOC)) - mstore(0x20, mload(PAIRING_RHS_Y_LOC)) - mstore(0x40, 0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2) // this is [1]_2 - mstore(0x60, 0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed) - mstore(0x80, 0x090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b) - mstore(0xa0, 0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa) - - mstore(0xc0, mload(PAIRING_LHS_X_LOC)) - mstore(0xe0, mload(PAIRING_LHS_Y_LOC)) - mstore(0x100, mload(G2X_X0_LOC)) - mstore(0x120, mload(G2X_X1_LOC)) - mstore(0x140, mload(G2X_Y0_LOC)) - mstore(0x160, mload(G2X_Y1_LOC)) - - success := staticcall(gas(), 8, 0x00, 0x180, 0x00, 0x20) - if iszero(and(success, mload(0x00))) { - mstore(0x0, PAIRING_FAILED_SELECTOR) - revert(0x00, 0x04) - } - } - - { - mstore(0x00, 0x01) - return(0x00, 0x20) // Proof succeeded! - } - } - } -} - -contract UltraVerifier is BaseUltraVerifier { - function getVerificationKeyHash() public pure override(BaseUltraVerifier) returns (bytes32) { - return UltraVerificationKey.verificationKeyHash(); - } - - function loadVerificationKey(uint256 vk, uint256 _omegaInverseLoc) internal pure virtual override(BaseUltraVerifier) { - UltraVerificationKey.loadVerificationKey(vk, _omegaInverseLoc); - } -} diff --git a/noir/noir-repo/compiler/integration-tests/contracts/recursion.sol b/noir/noir-repo/compiler/integration-tests/contracts/recursion.sol deleted file mode 100644 index abb5529f12ed..000000000000 --- a/noir/noir-repo/compiler/integration-tests/contracts/recursion.sol +++ /dev/null @@ -1,2869 +0,0 @@ -// Verification Key Hash: e0328cb05dead618095601e226cdeb6dbc39366658b78fabcb8b4d79b64150fe -// SPDX-License-Identifier: Apache-2.0 -// Copyright 2022 Aztec -pragma solidity >=0.8.4; - -library UltraVerificationKey { - function verificationKeyHash() internal pure returns(bytes32) { - return 0xe0328cb05dead618095601e226cdeb6dbc39366658b78fabcb8b4d79b64150fe; - } - - function loadVerificationKey(uint256 _vk, uint256 _omegaInverseLoc) internal pure { - assembly { - mstore(add(_vk, 0x00), 0x0000000000000000000000000000000000000000000000000000000000040000) // vk.circuit_size - mstore(add(_vk, 0x20), 0x0000000000000000000000000000000000000000000000000000000000000010) // vk.num_inputs - mstore(add(_vk, 0x40), 0x19ddbcaf3a8d46c15c0176fbb5b95e4dc57088ff13f4d1bd84c6bfa57dcdc0e0) // vk.work_root - mstore(add(_vk, 0x60), 0x30644259cd94e7dd5045d7a27013b7fcd21c9e3b7fa75222e7bda49b729b0401) // vk.domain_inverse - mstore(add(_vk, 0x80), 0x296cf46c4f739702b3432a7e00d817fd408d994c86c7b2a3d111e60216220ff4) // vk.Q1.x - mstore(add(_vk, 0xa0), 0x23eb5e8befe06db56c45cacc7f6ebe1c5a6d564eacd9ce398f5512f78716db2f) // vk.Q1.y - mstore(add(_vk, 0xc0), 0x1343a11edd4c8f943d25b149f25ce46f3f3d778986116e54e46f19ecea6f222c) // vk.Q2.x - mstore(add(_vk, 0xe0), 0x21465130765a50d22ae703a7f04f1c56d702a1fd8e60ef7ab8643e7d65400d4a) // vk.Q2.y - mstore(add(_vk, 0x100), 0x14ca6d2277d046bfec277680aaef68c036229345162dc5898d4c59c48af3050c) // vk.Q3.x - mstore(add(_vk, 0x120), 0x0193076249ef903f84326def1f71f3e0f8964d6ad9b8169b10373534c5d8ce3a) // vk.Q3.y - mstore(add(_vk, 0x140), 0x19b321f51f228bda6233253f630bd7a4ef8886b0b0b04b8aa5dae7de26262741) // vk.Q4.x - mstore(add(_vk, 0x160), 0x29e642b2b28bb28117bf91a05f4072be4aa7b9e461a30a8b512c9ce550b8bd11) // vk.Q4.y - mstore(add(_vk, 0x180), 0x135c2b4ca117cad1e6de43b35922898f10a215ca4bd212fb235b11f749747a40) // vk.Q_M.x - mstore(add(_vk, 0x1a0), 0x1b5898cbfad83193f396baa1b97d270788e813afeb2a55342f4e01118d7c8d52) // vk.Q_M.y - mstore(add(_vk, 0x1c0), 0x22b15c7b21212709f0670cb679b2f9983b0624880388177e34194a86a8beeec4) // vk.Q_C.x - mstore(add(_vk, 0x1e0), 0x23abf1bb3ae5b994d972821a588c2a181d6f73b19cd63eb97ba3d279280c8d89) // vk.Q_C.y - mstore(add(_vk, 0x200), 0x113b6d3105a628cbad57a3e0d3af01035264182e3730b1e09ec465456c93e237) // vk.Q_ARITHMETIC.x - mstore(add(_vk, 0x220), 0x144c2223ed41c781c7e91e392a785122901565726d0733d1f85d715cf72f46c7) // vk.Q_ARITHMETIC.y - mstore(add(_vk, 0x240), 0x2ef5ddac9f6900407cb286d52468a09ed415e365b5086f5c9b74b4f281c61054) // vk.QSORT.x - mstore(add(_vk, 0x260), 0x010674e24f29b69a54da15ac59911e89cf3fa787ed2cad6a44daa63c67d00fd7) // vk.QSORT.y - mstore(add(_vk, 0x280), 0x26ba1f4d0e050a78621b511228a9c6983f7868dde8d03a3206ba8ecb4745228c) // vk.Q_ELLIPTIC.x - mstore(add(_vk, 0x2a0), 0x00e496fbcd18c30efca8bbab288382270e7c1ca730a6de1c97f1fdb8e8cbb8ae) // vk.Q_ELLIPTIC.y - mstore(add(_vk, 0x2c0), 0x12f33eb7f1ef14f7b9c5eef6fda9e8b915b1505a9fc4fddbe85273bab940215d) // vk.Q_AUX.x - mstore(add(_vk, 0x2e0), 0x0243ce5ba21f31b237dca7bb13bb6552da8e193324813b7269b144f5fc4bb571) // vk.Q_AUX.y - mstore(add(_vk, 0x300), 0x08ba0b0a65af34cf8d99b68d5a1f8ff614a3d2f2b79feeb798b1167cc9a38cc9) // vk.SIGMA1.x - mstore(add(_vk, 0x320), 0x150a1dbd173563cdd0503776c3d59e91d6e78c1f1e6d23785f9da5843b27fc60) // vk.SIGMA1.y - mstore(add(_vk, 0x340), 0x2495d18a5ab5b8e3a2f6f9888d92d349362dde30734049dccc6fa6e07d903231) // vk.SIGMA2.x - mstore(add(_vk, 0x360), 0x0823530dc06e55a763f9a51db768d4bc53ebec26334b3e9d248235e7972624c6) // vk.SIGMA2.y - mstore(add(_vk, 0x380), 0x15b6c07df0304bc78711f6f924f040f63c0a1e6174d1bc4bb20c5cf93444d239) // vk.SIGMA3.x - mstore(add(_vk, 0x3a0), 0x1c7932ed2c40d035d67e80599df3f127fd408c30af2f5dd14805dd5816715881) // vk.SIGMA3.y - mstore(add(_vk, 0x3c0), 0x2644c0b211b5bc8160034e9b4948392266e615c101df2306a82bc2f99ceb2357) // vk.SIGMA4.x - mstore(add(_vk, 0x3e0), 0x245551ceeed8c044a968549997e4d89071e9d65cd887afe82835c4b05394c8dd) // vk.SIGMA4.y - mstore(add(_vk, 0x400), 0x09796190fd3ba909c6530c89811df9b5b4f5f2fe6501ec21dd864b20673fc02c) // vk.TABLE1.x - mstore(add(_vk, 0x420), 0x00b9c2423e310caa43e1eb83b55f53977fccbed85422df8935635d77d146bf39) // vk.TABLE1.y - mstore(add(_vk, 0x440), 0x217dad26ccc0c543ec5750513e9365a5cae8164b08d364efcf4b5890ff05f334) // vk.TABLE2.x - mstore(add(_vk, 0x460), 0x1db28433f6bde424423f3587787f81c48101d2dc6e54b431332cb275f8518c62) // vk.TABLE2.y - mstore(add(_vk, 0x480), 0x2cc2d90f2da7f4ec16b7fe61babd4fb9b580ecff03c471764dd67a8c433afab5) // vk.TABLE3.x - mstore(add(_vk, 0x4a0), 0x3032b9ff096a43ce326cc63ffc6a86dcb913fb1f7700939f5304f6c6beb24574) // vk.TABLE3.y - mstore(add(_vk, 0x4c0), 0x1f4c58502ca713ed0bffb4ff31ed55e557e83a37d31b8e703aa9219d6158e2d2) // vk.TABLE4.x - mstore(add(_vk, 0x4e0), 0x0b0d5ed5432c5e7b56344c1d26ce0d9f632e8f8aa52505d6c89f6da89f357fa8) // vk.TABLE4.y - mstore(add(_vk, 0x500), 0x18f58f41d54253e53e11e950a30712a53ac21c410a53424cf08b5c866aa18ef7) // vk.TABLE_TYPE.x - mstore(add(_vk, 0x520), 0x085b844a9b90e6d79f01271644b9cbc23f81cccb1679ddb7c4cf28f525ff41ad) // vk.TABLE_TYPE.y - mstore(add(_vk, 0x540), 0x1409fc0d97f2c216efc3538236ffa767e74c140c918e041cd17029a30a4a9d44) // vk.ID1.x - mstore(add(_vk, 0x560), 0x26c5c627007675f6a57449fe0df318783b14e9abcf70ff93026059d76f6b9cd7) // vk.ID1.y - mstore(add(_vk, 0x580), 0x2c14b2eb3d66e1ad2ab2f3f572c788cc7fc3c5de27f10dc4b03fb8d24d99a100) // vk.ID2.x - mstore(add(_vk, 0x5a0), 0x12fb35d49297144b9c18d4fedadb24ecaf825a0b16f15429880254c021b848d3) // vk.ID2.y - mstore(add(_vk, 0x5c0), 0x09cd56d13b51b36941752c549fcbf0f91175759cd433aa663380ff74eea969bb) // vk.ID3.x - mstore(add(_vk, 0x5e0), 0x0a8120bced78e668891c2b79e4098b73357660d7ac5d18c38692b82fae92ceae) // vk.ID3.y - mstore(add(_vk, 0x600), 0x23a22f97c87c77b7ec20064f688ad1d82994517560d78cc0366cbaa3ad0fe931) // vk.ID4.x - mstore(add(_vk, 0x620), 0x08d8108812baa0e234edc5109ec726f19dc6efd247eea7d61930f0857844dba1) // vk.ID4.y - mstore(add(_vk, 0x640), 0x01) // vk.contains_recursive_proof - mstore(add(_vk, 0x660), 0) // vk.recursive_proof_public_input_indices - mstore(add(_vk, 0x680), 0x260e01b251f6f1c7e7ff4e580791dee8ea51d87a358e038b4efe30fac09383c1) // vk.g2_x.X.c1 - mstore(add(_vk, 0x6a0), 0x0118c4d5b837bcc2bc89b5b398b5974e9f5944073b32078b7e231fec938883b0) // vk.g2_x.X.c0 - mstore(add(_vk, 0x6c0), 0x04fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe4) // vk.g2_x.Y.c1 - mstore(add(_vk, 0x6e0), 0x22febda3c0c0632a56475b4214e5615e11e6dd3f96e6cea2854a87d4dacc5e55) // vk.g2_x.Y.c0 - mstore(_omegaInverseLoc, 0x036853f083780e87f8d7c71d111119c57dbe118c22d5ad707a82317466c5174c) // vk.work_root_inverse - } - } -} - -/** - * @title Ultra Plonk proof verification contract - * @dev Top level Plonk proof verification contract, which allows Plonk proof to be verified - */ -abstract contract BaseUltraVerifier { - // VERIFICATION KEY MEMORY LOCATIONS - uint256 internal constant N_LOC = 0x380; - uint256 internal constant NUM_INPUTS_LOC = 0x3a0; - uint256 internal constant OMEGA_LOC = 0x3c0; - uint256 internal constant DOMAIN_INVERSE_LOC = 0x3e0; - uint256 internal constant Q1_X_LOC = 0x400; - uint256 internal constant Q1_Y_LOC = 0x420; - uint256 internal constant Q2_X_LOC = 0x440; - uint256 internal constant Q2_Y_LOC = 0x460; - uint256 internal constant Q3_X_LOC = 0x480; - uint256 internal constant Q3_Y_LOC = 0x4a0; - uint256 internal constant Q4_X_LOC = 0x4c0; - uint256 internal constant Q4_Y_LOC = 0x4e0; - uint256 internal constant QM_X_LOC = 0x500; - uint256 internal constant QM_Y_LOC = 0x520; - uint256 internal constant QC_X_LOC = 0x540; - uint256 internal constant QC_Y_LOC = 0x560; - uint256 internal constant QARITH_X_LOC = 0x580; - uint256 internal constant QARITH_Y_LOC = 0x5a0; - uint256 internal constant QSORT_X_LOC = 0x5c0; - uint256 internal constant QSORT_Y_LOC = 0x5e0; - uint256 internal constant QELLIPTIC_X_LOC = 0x600; - uint256 internal constant QELLIPTIC_Y_LOC = 0x620; - uint256 internal constant QAUX_X_LOC = 0x640; - uint256 internal constant QAUX_Y_LOC = 0x660; - uint256 internal constant SIGMA1_X_LOC = 0x680; - uint256 internal constant SIGMA1_Y_LOC = 0x6a0; - uint256 internal constant SIGMA2_X_LOC = 0x6c0; - uint256 internal constant SIGMA2_Y_LOC = 0x6e0; - uint256 internal constant SIGMA3_X_LOC = 0x700; - uint256 internal constant SIGMA3_Y_LOC = 0x720; - uint256 internal constant SIGMA4_X_LOC = 0x740; - uint256 internal constant SIGMA4_Y_LOC = 0x760; - uint256 internal constant TABLE1_X_LOC = 0x780; - uint256 internal constant TABLE1_Y_LOC = 0x7a0; - uint256 internal constant TABLE2_X_LOC = 0x7c0; - uint256 internal constant TABLE2_Y_LOC = 0x7e0; - uint256 internal constant TABLE3_X_LOC = 0x800; - uint256 internal constant TABLE3_Y_LOC = 0x820; - uint256 internal constant TABLE4_X_LOC = 0x840; - uint256 internal constant TABLE4_Y_LOC = 0x860; - uint256 internal constant TABLE_TYPE_X_LOC = 0x880; - uint256 internal constant TABLE_TYPE_Y_LOC = 0x8a0; - uint256 internal constant ID1_X_LOC = 0x8c0; - uint256 internal constant ID1_Y_LOC = 0x8e0; - uint256 internal constant ID2_X_LOC = 0x900; - uint256 internal constant ID2_Y_LOC = 0x920; - uint256 internal constant ID3_X_LOC = 0x940; - uint256 internal constant ID3_Y_LOC = 0x960; - uint256 internal constant ID4_X_LOC = 0x980; - uint256 internal constant ID4_Y_LOC = 0x9a0; - uint256 internal constant CONTAINS_RECURSIVE_PROOF_LOC = 0x9c0; - uint256 internal constant RECURSIVE_PROOF_PUBLIC_INPUT_INDICES_LOC = 0x9e0; - uint256 internal constant G2X_X0_LOC = 0xa00; - uint256 internal constant G2X_X1_LOC = 0xa20; - uint256 internal constant G2X_Y0_LOC = 0xa40; - uint256 internal constant G2X_Y1_LOC = 0xa60; - - // ### PROOF DATA MEMORY LOCATIONS - uint256 internal constant W1_X_LOC = 0x1200; - uint256 internal constant W1_Y_LOC = 0x1220; - uint256 internal constant W2_X_LOC = 0x1240; - uint256 internal constant W2_Y_LOC = 0x1260; - uint256 internal constant W3_X_LOC = 0x1280; - uint256 internal constant W3_Y_LOC = 0x12a0; - uint256 internal constant W4_X_LOC = 0x12c0; - uint256 internal constant W4_Y_LOC = 0x12e0; - uint256 internal constant S_X_LOC = 0x1300; - uint256 internal constant S_Y_LOC = 0x1320; - uint256 internal constant Z_X_LOC = 0x1340; - uint256 internal constant Z_Y_LOC = 0x1360; - uint256 internal constant Z_LOOKUP_X_LOC = 0x1380; - uint256 internal constant Z_LOOKUP_Y_LOC = 0x13a0; - uint256 internal constant T1_X_LOC = 0x13c0; - uint256 internal constant T1_Y_LOC = 0x13e0; - uint256 internal constant T2_X_LOC = 0x1400; - uint256 internal constant T2_Y_LOC = 0x1420; - uint256 internal constant T3_X_LOC = 0x1440; - uint256 internal constant T3_Y_LOC = 0x1460; - uint256 internal constant T4_X_LOC = 0x1480; - uint256 internal constant T4_Y_LOC = 0x14a0; - - uint256 internal constant W1_EVAL_LOC = 0x1600; - uint256 internal constant W2_EVAL_LOC = 0x1620; - uint256 internal constant W3_EVAL_LOC = 0x1640; - uint256 internal constant W4_EVAL_LOC = 0x1660; - uint256 internal constant S_EVAL_LOC = 0x1680; - uint256 internal constant Z_EVAL_LOC = 0x16a0; - uint256 internal constant Z_LOOKUP_EVAL_LOC = 0x16c0; - uint256 internal constant Q1_EVAL_LOC = 0x16e0; - uint256 internal constant Q2_EVAL_LOC = 0x1700; - uint256 internal constant Q3_EVAL_LOC = 0x1720; - uint256 internal constant Q4_EVAL_LOC = 0x1740; - uint256 internal constant QM_EVAL_LOC = 0x1760; - uint256 internal constant QC_EVAL_LOC = 0x1780; - uint256 internal constant QARITH_EVAL_LOC = 0x17a0; - uint256 internal constant QSORT_EVAL_LOC = 0x17c0; - uint256 internal constant QELLIPTIC_EVAL_LOC = 0x17e0; - uint256 internal constant QAUX_EVAL_LOC = 0x1800; - uint256 internal constant TABLE1_EVAL_LOC = 0x1840; - uint256 internal constant TABLE2_EVAL_LOC = 0x1860; - uint256 internal constant TABLE3_EVAL_LOC = 0x1880; - uint256 internal constant TABLE4_EVAL_LOC = 0x18a0; - uint256 internal constant TABLE_TYPE_EVAL_LOC = 0x18c0; - uint256 internal constant ID1_EVAL_LOC = 0x18e0; - uint256 internal constant ID2_EVAL_LOC = 0x1900; - uint256 internal constant ID3_EVAL_LOC = 0x1920; - uint256 internal constant ID4_EVAL_LOC = 0x1940; - uint256 internal constant SIGMA1_EVAL_LOC = 0x1960; - uint256 internal constant SIGMA2_EVAL_LOC = 0x1980; - uint256 internal constant SIGMA3_EVAL_LOC = 0x19a0; - uint256 internal constant SIGMA4_EVAL_LOC = 0x19c0; - uint256 internal constant W1_OMEGA_EVAL_LOC = 0x19e0; - uint256 internal constant W2_OMEGA_EVAL_LOC = 0x2000; - uint256 internal constant W3_OMEGA_EVAL_LOC = 0x2020; - uint256 internal constant W4_OMEGA_EVAL_LOC = 0x2040; - uint256 internal constant S_OMEGA_EVAL_LOC = 0x2060; - uint256 internal constant Z_OMEGA_EVAL_LOC = 0x2080; - uint256 internal constant Z_LOOKUP_OMEGA_EVAL_LOC = 0x20a0; - uint256 internal constant TABLE1_OMEGA_EVAL_LOC = 0x20c0; - uint256 internal constant TABLE2_OMEGA_EVAL_LOC = 0x20e0; - uint256 internal constant TABLE3_OMEGA_EVAL_LOC = 0x2100; - uint256 internal constant TABLE4_OMEGA_EVAL_LOC = 0x2120; - - uint256 internal constant PI_Z_X_LOC = 0x2300; - uint256 internal constant PI_Z_Y_LOC = 0x2320; - uint256 internal constant PI_Z_OMEGA_X_LOC = 0x2340; - uint256 internal constant PI_Z_OMEGA_Y_LOC = 0x2360; - - // Used for elliptic widget. These are alias names for wire + shifted wire evaluations - uint256 internal constant X1_EVAL_LOC = W2_EVAL_LOC; - uint256 internal constant X2_EVAL_LOC = W1_OMEGA_EVAL_LOC; - uint256 internal constant X3_EVAL_LOC = W2_OMEGA_EVAL_LOC; - uint256 internal constant Y1_EVAL_LOC = W3_EVAL_LOC; - uint256 internal constant Y2_EVAL_LOC = W4_OMEGA_EVAL_LOC; - uint256 internal constant Y3_EVAL_LOC = W3_OMEGA_EVAL_LOC; - uint256 internal constant QBETA_LOC = Q3_EVAL_LOC; - uint256 internal constant QBETA_SQR_LOC = Q4_EVAL_LOC; - uint256 internal constant QSIGN_LOC = Q1_EVAL_LOC; - - // ### CHALLENGES MEMORY OFFSETS - - uint256 internal constant C_BETA_LOC = 0x2600; - uint256 internal constant C_GAMMA_LOC = 0x2620; - uint256 internal constant C_ALPHA_LOC = 0x2640; - uint256 internal constant C_ETA_LOC = 0x2660; - uint256 internal constant C_ETA_SQR_LOC = 0x2680; - uint256 internal constant C_ETA_CUBE_LOC = 0x26a0; - - uint256 internal constant C_ZETA_LOC = 0x26c0; - uint256 internal constant C_CURRENT_LOC = 0x26e0; - uint256 internal constant C_V0_LOC = 0x2700; - uint256 internal constant C_V1_LOC = 0x2720; - uint256 internal constant C_V2_LOC = 0x2740; - uint256 internal constant C_V3_LOC = 0x2760; - uint256 internal constant C_V4_LOC = 0x2780; - uint256 internal constant C_V5_LOC = 0x27a0; - uint256 internal constant C_V6_LOC = 0x27c0; - uint256 internal constant C_V7_LOC = 0x27e0; - uint256 internal constant C_V8_LOC = 0x2800; - uint256 internal constant C_V9_LOC = 0x2820; - uint256 internal constant C_V10_LOC = 0x2840; - uint256 internal constant C_V11_LOC = 0x2860; - uint256 internal constant C_V12_LOC = 0x2880; - uint256 internal constant C_V13_LOC = 0x28a0; - uint256 internal constant C_V14_LOC = 0x28c0; - uint256 internal constant C_V15_LOC = 0x28e0; - uint256 internal constant C_V16_LOC = 0x2900; - uint256 internal constant C_V17_LOC = 0x2920; - uint256 internal constant C_V18_LOC = 0x2940; - uint256 internal constant C_V19_LOC = 0x2960; - uint256 internal constant C_V20_LOC = 0x2980; - uint256 internal constant C_V21_LOC = 0x29a0; - uint256 internal constant C_V22_LOC = 0x29c0; - uint256 internal constant C_V23_LOC = 0x29e0; - uint256 internal constant C_V24_LOC = 0x2a00; - uint256 internal constant C_V25_LOC = 0x2a20; - uint256 internal constant C_V26_LOC = 0x2a40; - uint256 internal constant C_V27_LOC = 0x2a60; - uint256 internal constant C_V28_LOC = 0x2a80; - uint256 internal constant C_V29_LOC = 0x2aa0; - uint256 internal constant C_V30_LOC = 0x2ac0; - - uint256 internal constant C_U_LOC = 0x2b00; - - // ### LOCAL VARIABLES MEMORY OFFSETS - uint256 internal constant DELTA_NUMERATOR_LOC = 0x3000; - uint256 internal constant DELTA_DENOMINATOR_LOC = 0x3020; - uint256 internal constant ZETA_POW_N_LOC = 0x3040; - uint256 internal constant PUBLIC_INPUT_DELTA_LOC = 0x3060; - uint256 internal constant ZERO_POLY_LOC = 0x3080; - uint256 internal constant L_START_LOC = 0x30a0; - uint256 internal constant L_END_LOC = 0x30c0; - uint256 internal constant R_ZERO_EVAL_LOC = 0x30e0; - - uint256 internal constant PLOOKUP_DELTA_NUMERATOR_LOC = 0x3100; - uint256 internal constant PLOOKUP_DELTA_DENOMINATOR_LOC = 0x3120; - uint256 internal constant PLOOKUP_DELTA_LOC = 0x3140; - - uint256 internal constant ACCUMULATOR_X_LOC = 0x3160; - uint256 internal constant ACCUMULATOR_Y_LOC = 0x3180; - uint256 internal constant ACCUMULATOR2_X_LOC = 0x31a0; - uint256 internal constant ACCUMULATOR2_Y_LOC = 0x31c0; - uint256 internal constant PAIRING_LHS_X_LOC = 0x31e0; - uint256 internal constant PAIRING_LHS_Y_LOC = 0x3200; - uint256 internal constant PAIRING_RHS_X_LOC = 0x3220; - uint256 internal constant PAIRING_RHS_Y_LOC = 0x3240; - - // misc stuff - uint256 internal constant OMEGA_INVERSE_LOC = 0x3300; - uint256 internal constant C_ALPHA_SQR_LOC = 0x3320; - uint256 internal constant C_ALPHA_CUBE_LOC = 0x3340; - uint256 internal constant C_ALPHA_QUAD_LOC = 0x3360; - uint256 internal constant C_ALPHA_BASE_LOC = 0x3380; - - // ### RECURSION VARIABLE MEMORY LOCATIONS - uint256 internal constant RECURSIVE_P1_X_LOC = 0x3400; - uint256 internal constant RECURSIVE_P1_Y_LOC = 0x3420; - uint256 internal constant RECURSIVE_P2_X_LOC = 0x3440; - uint256 internal constant RECURSIVE_P2_Y_LOC = 0x3460; - uint256 internal constant PUBLIC_INPUTS_HASH_LOCATION = 0x3480; - - // sub-identity storage - uint256 internal constant PERMUTATION_IDENTITY = 0x3500; - uint256 internal constant PLOOKUP_IDENTITY = 0x3520; - uint256 internal constant ARITHMETIC_IDENTITY = 0x3540; - uint256 internal constant SORT_IDENTITY = 0x3560; - uint256 internal constant ELLIPTIC_IDENTITY = 0x3580; - uint256 internal constant AUX_IDENTITY = 0x35a0; - uint256 internal constant AUX_NON_NATIVE_FIELD_EVALUATION = 0x35c0; - uint256 internal constant AUX_LIMB_ACCUMULATOR_EVALUATION = 0x35e0; - uint256 internal constant AUX_RAM_CONSISTENCY_EVALUATION = 0x3600; - uint256 internal constant AUX_ROM_CONSISTENCY_EVALUATION = 0x3620; - uint256 internal constant AUX_MEMORY_EVALUATION = 0x3640; - - uint256 internal constant QUOTIENT_EVAL_LOC = 0x3660; - uint256 internal constant ZERO_POLY_INVERSE_LOC = 0x3680; - - // when hashing public inputs we use memory at NU_CHALLENGE_INPUT_LOC_A, as the hash input size is unknown at compile time - uint256 internal constant NU_CHALLENGE_INPUT_LOC_A = 0x36a0; - uint256 internal constant NU_CHALLENGE_INPUT_LOC_B = 0x36c0; - uint256 internal constant NU_CHALLENGE_INPUT_LOC_C = 0x36e0; - - bytes4 internal constant INVALID_VERIFICATION_KEY_SELECTOR = 0x7e5769bf; - bytes4 internal constant POINT_NOT_ON_CURVE_SELECTOR = 0xa3dad654; - bytes4 internal constant PUBLIC_INPUT_INVALID_BN128_G1_POINT_SELECTOR = 0xeba9f4a6; - bytes4 internal constant PUBLIC_INPUT_GE_P_SELECTOR = 0x374a972f; - bytes4 internal constant MOD_EXP_FAILURE_SELECTOR = 0xf894a7bc; - bytes4 internal constant PAIRING_PREAMBLE_FAILED_SELECTOR = 0x01882d81; - bytes4 internal constant OPENING_COMMITMENT_FAILED_SELECTOR = 0x4e719763; - bytes4 internal constant PAIRING_FAILED_SELECTOR = 0xd71fd263; - - uint256 internal constant ETA_INPUT_LENGTH = 0xc0; // W1, W2, W3 = 6 * 0x20 bytes - - // We need to hash 41 field elements when generating the NU challenge - // w1, w2, w3, w4, s, z, z_lookup, q1, q2, q3, q4, qm, qc, qarith (14) - // qsort, qelliptic, qaux, sigma1, sigma2, sigma, sigma4, (7) - // table1, table2, table3, table4, tabletype, id1, id2, id3, id4, (9) - // w1_omega, w2_omega, w3_omega, w4_omega, s_omega, z_omega, z_lookup_omega, (7) - // table1_omega, table2_omega, table3_omega, table4_omega (4) - uint256 internal constant NU_INPUT_LENGTH = 0x520; // 0x520 = 41 * 0x20 - - // There are ELEVEN G1 group elements added into the transcript in the `beta` round, that we need to skip over - // W1, W2, W3, W4, S, Z, Z_LOOKUP, T1, T2, T3, T4 - uint256 internal constant NU_CALLDATA_SKIP_LENGTH = 0x2c0; // 11 * 0x40 = 0x2c0 - - uint256 internal constant NEGATIVE_INVERSE_OF_2_MODULO_P = - 0x183227397098d014dc2822db40c0ac2e9419f4243cdcb848a1f0fac9f8000000; - uint256 internal constant LIMB_SIZE = 0x100000000000000000; // 2<<68 - uint256 internal constant SUBLIMB_SHIFT = 0x4000; // 2<<14 - - // y^2 = x^3 + ax + b - // for Grumpkin, a = 0 and b = -17. We use b in a custom gate relation that evaluates elliptic curve arithmetic - uint256 internal constant GRUMPKIN_CURVE_B_PARAMETER_NEGATED = 17; - - error INVALID_VERIFICATION_KEY(); - error POINT_NOT_ON_CURVE(); - error PUBLIC_INPUT_COUNT_INVALID(uint256 expected, uint256 actual); - error PUBLIC_INPUT_INVALID_BN128_G1_POINT(); - error PUBLIC_INPUT_GE_P(); - error MOD_EXP_FAILURE(); - error PAIRING_PREAMBLE_FAILED(); - error OPENING_COMMITMENT_FAILED(); - error PAIRING_FAILED(); - - function getVerificationKeyHash() public pure virtual returns (bytes32); - - /** - * @dev We assume that the verification key loaded by this function is constant as we only verify it on deployment - */ - function loadVerificationKey(uint256 _vk, uint256 _omegaInverseLoc) internal pure virtual; - - constructor() { - loadVerificationKey(N_LOC, OMEGA_INVERSE_LOC); - - // We verify that all of the EC points in the verification key lie on the bn128 curve. - assembly { - let q := 21888242871839275222246405745257275088696311157297823662689037894645226208583 // EC group order - - let success := 1 - - // VALIDATE Q1 - { - let x := mload(Q1_X_LOC) - let y := mload(Q1_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE Q2 - { - let x := mload(Q2_X_LOC) - let y := mload(Q2_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE Q3 - { - let x := mload(Q3_X_LOC) - let y := mload(Q3_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE Q4 - { - let x := mload(Q4_X_LOC) - let y := mload(Q4_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - mstore(0x00, x) - mstore(0x20, y) - } - // VALIDATE QM - { - let x := mload(QM_X_LOC) - let y := mload(QM_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE QC - { - let x := mload(QC_X_LOC) - let y := mload(QC_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE QARITH - { - let x := mload(QARITH_X_LOC) - let y := mload(QARITH_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE QSORT - { - let x := mload(QSORT_X_LOC) - let y := mload(QSORT_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE QELLIPTIC - { - let x := mload(QELLIPTIC_X_LOC) - let y := mload(QELLIPTIC_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE QAUX - { - let x := mload(QAUX_X_LOC) - let y := mload(QAUX_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE SIGMA1 - { - let x := mload(SIGMA1_X_LOC) - let y := mload(SIGMA1_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE SIGMA2 - { - let x := mload(SIGMA2_X_LOC) - let y := mload(SIGMA2_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE SIGMA3 - { - let x := mload(SIGMA3_X_LOC) - let y := mload(SIGMA3_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE SIGMA4 - { - let x := mload(SIGMA4_X_LOC) - let y := mload(SIGMA4_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE TABLE1 - { - let x := mload(TABLE1_X_LOC) - let y := mload(TABLE1_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE TABLE2 - { - let x := mload(TABLE2_X_LOC) - let y := mload(TABLE2_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE TABLE3 - { - let x := mload(TABLE3_X_LOC) - let y := mload(TABLE3_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE TABLE4 - { - let x := mload(TABLE4_X_LOC) - let y := mload(TABLE4_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE TABLE_TYPE - { - let x := mload(TABLE_TYPE_X_LOC) - let y := mload(TABLE_TYPE_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE ID1 - { - let x := mload(ID1_X_LOC) - let y := mload(ID1_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE ID2 - { - let x := mload(ID2_X_LOC) - let y := mload(ID2_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE ID3 - { - let x := mload(ID3_X_LOC) - let y := mload(ID3_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - // VALIDATE ID4 - { - let x := mload(ID4_X_LOC) - let y := mload(ID4_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) - } - - if iszero(success) { - mstore(0x0, INVALID_VERIFICATION_KEY_SELECTOR) - revert(0x00, 0x04) - } - } - } - - /** - * @notice Verify a Ultra Plonk proof - * @param _proof - The serialized proof - * @param _publicInputs - An array of the public inputs - * @return True if proof is valid, reverts otherwise - */ - function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool) { - loadVerificationKey(N_LOC, OMEGA_INVERSE_LOC); - - uint256 requiredPublicInputCount; - assembly { - requiredPublicInputCount := mload(NUM_INPUTS_LOC) - } - if (requiredPublicInputCount != _publicInputs.length) { - revert PUBLIC_INPUT_COUNT_INVALID(requiredPublicInputCount, _publicInputs.length); - } - - assembly { - let q := 21888242871839275222246405745257275088696311157297823662689037894645226208583 // EC group order - let p := 21888242871839275222246405745257275088548364400416034343698204186575808495617 // Prime field order - - /** - * LOAD PROOF FROM CALLDATA - */ - { - let data_ptr := add(calldataload(0x04), 0x24) - - mstore(W1_Y_LOC, mod(calldataload(data_ptr), q)) - mstore(W1_X_LOC, mod(calldataload(add(data_ptr, 0x20)), q)) - - mstore(W2_Y_LOC, mod(calldataload(add(data_ptr, 0x40)), q)) - mstore(W2_X_LOC, mod(calldataload(add(data_ptr, 0x60)), q)) - - mstore(W3_Y_LOC, mod(calldataload(add(data_ptr, 0x80)), q)) - mstore(W3_X_LOC, mod(calldataload(add(data_ptr, 0xa0)), q)) - - mstore(W4_Y_LOC, mod(calldataload(add(data_ptr, 0xc0)), q)) - mstore(W4_X_LOC, mod(calldataload(add(data_ptr, 0xe0)), q)) - - mstore(S_Y_LOC, mod(calldataload(add(data_ptr, 0x100)), q)) - mstore(S_X_LOC, mod(calldataload(add(data_ptr, 0x120)), q)) - mstore(Z_Y_LOC, mod(calldataload(add(data_ptr, 0x140)), q)) - mstore(Z_X_LOC, mod(calldataload(add(data_ptr, 0x160)), q)) - mstore(Z_LOOKUP_Y_LOC, mod(calldataload(add(data_ptr, 0x180)), q)) - mstore(Z_LOOKUP_X_LOC, mod(calldataload(add(data_ptr, 0x1a0)), q)) - mstore(T1_Y_LOC, mod(calldataload(add(data_ptr, 0x1c0)), q)) - mstore(T1_X_LOC, mod(calldataload(add(data_ptr, 0x1e0)), q)) - - mstore(T2_Y_LOC, mod(calldataload(add(data_ptr, 0x200)), q)) - mstore(T2_X_LOC, mod(calldataload(add(data_ptr, 0x220)), q)) - - mstore(T3_Y_LOC, mod(calldataload(add(data_ptr, 0x240)), q)) - mstore(T3_X_LOC, mod(calldataload(add(data_ptr, 0x260)), q)) - - mstore(T4_Y_LOC, mod(calldataload(add(data_ptr, 0x280)), q)) - mstore(T4_X_LOC, mod(calldataload(add(data_ptr, 0x2a0)), q)) - - mstore(W1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x2c0)), p)) - mstore(W2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x2e0)), p)) - mstore(W3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x300)), p)) - mstore(W4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x320)), p)) - mstore(S_EVAL_LOC, mod(calldataload(add(data_ptr, 0x340)), p)) - mstore(Z_EVAL_LOC, mod(calldataload(add(data_ptr, 0x360)), p)) - mstore(Z_LOOKUP_EVAL_LOC, mod(calldataload(add(data_ptr, 0x380)), p)) - mstore(Q1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x3a0)), p)) - mstore(Q2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x3c0)), p)) - mstore(Q3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x3e0)), p)) - mstore(Q4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x400)), p)) - mstore(QM_EVAL_LOC, mod(calldataload(add(data_ptr, 0x420)), p)) - mstore(QC_EVAL_LOC, mod(calldataload(add(data_ptr, 0x440)), p)) - mstore(QARITH_EVAL_LOC, mod(calldataload(add(data_ptr, 0x460)), p)) - mstore(QSORT_EVAL_LOC, mod(calldataload(add(data_ptr, 0x480)), p)) - mstore(QELLIPTIC_EVAL_LOC, mod(calldataload(add(data_ptr, 0x4a0)), p)) - mstore(QAUX_EVAL_LOC, mod(calldataload(add(data_ptr, 0x4c0)), p)) - - mstore(SIGMA1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x4e0)), p)) - mstore(SIGMA2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x500)), p)) - - mstore(SIGMA3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x520)), p)) - mstore(SIGMA4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x540)), p)) - - mstore(TABLE1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x560)), p)) - mstore(TABLE2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x580)), p)) - mstore(TABLE3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x5a0)), p)) - mstore(TABLE4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x5c0)), p)) - mstore(TABLE_TYPE_EVAL_LOC, mod(calldataload(add(data_ptr, 0x5e0)), p)) - - mstore(ID1_EVAL_LOC, mod(calldataload(add(data_ptr, 0x600)), p)) - mstore(ID2_EVAL_LOC, mod(calldataload(add(data_ptr, 0x620)), p)) - mstore(ID3_EVAL_LOC, mod(calldataload(add(data_ptr, 0x640)), p)) - mstore(ID4_EVAL_LOC, mod(calldataload(add(data_ptr, 0x660)), p)) - - mstore(W1_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x680)), p)) - mstore(W2_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x6a0)), p)) - mstore(W3_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x6c0)), p)) - mstore(W4_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x6e0)), p)) - mstore(S_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x700)), p)) - - mstore(Z_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x720)), p)) - - mstore(Z_LOOKUP_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x740)), p)) - mstore(TABLE1_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x760)), p)) - mstore(TABLE2_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x780)), p)) - mstore(TABLE3_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x7a0)), p)) - mstore(TABLE4_OMEGA_EVAL_LOC, mod(calldataload(add(data_ptr, 0x7c0)), p)) - - mstore(PI_Z_Y_LOC, mod(calldataload(add(data_ptr, 0x7e0)), q)) - mstore(PI_Z_X_LOC, mod(calldataload(add(data_ptr, 0x800)), q)) - - mstore(PI_Z_OMEGA_Y_LOC, mod(calldataload(add(data_ptr, 0x820)), q)) - mstore(PI_Z_OMEGA_X_LOC, mod(calldataload(add(data_ptr, 0x840)), q)) - } - - /** - * LOAD RECURSIVE PROOF INTO MEMORY - */ - { - if mload(CONTAINS_RECURSIVE_PROOF_LOC) { - let public_inputs_ptr := add(calldataload(0x24), 0x24) - let index_counter := add(shl(5, mload(RECURSIVE_PROOF_PUBLIC_INPUT_INDICES_LOC)), public_inputs_ptr) - - let x0 := calldataload(index_counter) - x0 := add(x0, shl(68, calldataload(add(index_counter, 0x20)))) - x0 := add(x0, shl(136, calldataload(add(index_counter, 0x40)))) - x0 := add(x0, shl(204, calldataload(add(index_counter, 0x60)))) - let y0 := calldataload(add(index_counter, 0x80)) - y0 := add(y0, shl(68, calldataload(add(index_counter, 0xa0)))) - y0 := add(y0, shl(136, calldataload(add(index_counter, 0xc0)))) - y0 := add(y0, shl(204, calldataload(add(index_counter, 0xe0)))) - let x1 := calldataload(add(index_counter, 0x100)) - x1 := add(x1, shl(68, calldataload(add(index_counter, 0x120)))) - x1 := add(x1, shl(136, calldataload(add(index_counter, 0x140)))) - x1 := add(x1, shl(204, calldataload(add(index_counter, 0x160)))) - let y1 := calldataload(add(index_counter, 0x180)) - y1 := add(y1, shl(68, calldataload(add(index_counter, 0x1a0)))) - y1 := add(y1, shl(136, calldataload(add(index_counter, 0x1c0)))) - y1 := add(y1, shl(204, calldataload(add(index_counter, 0x1e0)))) - mstore(RECURSIVE_P1_X_LOC, x0) - mstore(RECURSIVE_P1_Y_LOC, y0) - mstore(RECURSIVE_P2_X_LOC, x1) - mstore(RECURSIVE_P2_Y_LOC, y1) - - // validate these are valid bn128 G1 points - if iszero(and(and(lt(x0, q), lt(x1, q)), and(lt(y0, q), lt(y1, q)))) { - mstore(0x00, PUBLIC_INPUT_INVALID_BN128_G1_POINT_SELECTOR) - revert(0x00, 0x04) - } - } - } - - { - /** - * Generate initial challenge - */ - mstore(0x00, shl(224, mload(N_LOC))) - mstore(0x04, shl(224, mload(NUM_INPUTS_LOC))) - let challenge := keccak256(0x00, 0x08) - - /** - * Generate eta challenge - */ - mstore(PUBLIC_INPUTS_HASH_LOCATION, challenge) - // The public input location is stored at 0x24, we then add 0x24 to skip selector and the length of public inputs - let public_inputs_start := add(calldataload(0x24), 0x24) - // copy the public inputs over - let public_input_size := mul(mload(NUM_INPUTS_LOC), 0x20) - calldatacopy(add(PUBLIC_INPUTS_HASH_LOCATION, 0x20), public_inputs_start, public_input_size) - - // copy W1, W2, W3 into challenge. Each point is 0x40 bytes, so load 0xc0 = 3 * 0x40 bytes (ETA input length) - let w_start := add(calldataload(0x04), 0x24) - calldatacopy(add(add(PUBLIC_INPUTS_HASH_LOCATION, 0x20), public_input_size), w_start, ETA_INPUT_LENGTH) - - // Challenge is the old challenge + public inputs + W1, W2, W3 (0x20 + public_input_size + 0xc0) - let challenge_bytes_size := add(0x20, add(public_input_size, ETA_INPUT_LENGTH)) - - challenge := keccak256(PUBLIC_INPUTS_HASH_LOCATION, challenge_bytes_size) - { - let eta := mod(challenge, p) - mstore(C_ETA_LOC, eta) - mstore(C_ETA_SQR_LOC, mulmod(eta, eta, p)) - mstore(C_ETA_CUBE_LOC, mulmod(mload(C_ETA_SQR_LOC), eta, p)) - } - - /** - * Generate beta challenge - */ - mstore(0x00, challenge) - mstore(0x20, mload(W4_Y_LOC)) - mstore(0x40, mload(W4_X_LOC)) - mstore(0x60, mload(S_Y_LOC)) - mstore(0x80, mload(S_X_LOC)) - challenge := keccak256(0x00, 0xa0) - mstore(C_BETA_LOC, mod(challenge, p)) - - /** - * Generate gamma challenge - */ - mstore(0x00, challenge) - mstore8(0x20, 0x01) - challenge := keccak256(0x00, 0x21) - mstore(C_GAMMA_LOC, mod(challenge, p)) - - /** - * Generate alpha challenge - */ - mstore(0x00, challenge) - mstore(0x20, mload(Z_Y_LOC)) - mstore(0x40, mload(Z_X_LOC)) - mstore(0x60, mload(Z_LOOKUP_Y_LOC)) - mstore(0x80, mload(Z_LOOKUP_X_LOC)) - challenge := keccak256(0x00, 0xa0) - mstore(C_ALPHA_LOC, mod(challenge, p)) - - /** - * Compute and store some powers of alpha for future computations - */ - let alpha := mload(C_ALPHA_LOC) - mstore(C_ALPHA_SQR_LOC, mulmod(alpha, alpha, p)) - mstore(C_ALPHA_CUBE_LOC, mulmod(mload(C_ALPHA_SQR_LOC), alpha, p)) - mstore(C_ALPHA_QUAD_LOC, mulmod(mload(C_ALPHA_CUBE_LOC), alpha, p)) - mstore(C_ALPHA_BASE_LOC, alpha) - - /** - * Generate zeta challenge - */ - mstore(0x00, challenge) - mstore(0x20, mload(T1_Y_LOC)) - mstore(0x40, mload(T1_X_LOC)) - mstore(0x60, mload(T2_Y_LOC)) - mstore(0x80, mload(T2_X_LOC)) - mstore(0xa0, mload(T3_Y_LOC)) - mstore(0xc0, mload(T3_X_LOC)) - mstore(0xe0, mload(T4_Y_LOC)) - mstore(0x100, mload(T4_X_LOC)) - - challenge := keccak256(0x00, 0x120) - - mstore(C_ZETA_LOC, mod(challenge, p)) - mstore(C_CURRENT_LOC, challenge) - } - - /** - * EVALUATE FIELD OPERATIONS - */ - - /** - * COMPUTE PUBLIC INPUT DELTA - * ΔPI = ∏ᵢ∈ℓ(wᵢ + β σ(i) + γ) / ∏ᵢ∈ℓ(wᵢ + β σ'(i) + γ) - */ - { - let beta := mload(C_BETA_LOC) // β - let gamma := mload(C_GAMMA_LOC) // γ - let work_root := mload(OMEGA_LOC) // ω - let numerator_value := 1 - let denominator_value := 1 - - let p_clone := p // move p to the front of the stack - let valid_inputs := true - - // Load the starting point of the public inputs (jump over the selector and the length of public inputs [0x24]) - let public_inputs_ptr := add(calldataload(0x24), 0x24) - - // endpoint_ptr = public_inputs_ptr + num_inputs * 0x20. // every public input is 0x20 bytes - let endpoint_ptr := add(public_inputs_ptr, mul(mload(NUM_INPUTS_LOC), 0x20)) - - // root_1 = β * 0x05 - let root_1 := mulmod(beta, 0x05, p_clone) // k1.β - // root_2 = β * 0x0c - let root_2 := mulmod(beta, 0x0c, p_clone) - // @note 0x05 + 0x07 == 0x0c == external coset generator - - for {} lt(public_inputs_ptr, endpoint_ptr) { public_inputs_ptr := add(public_inputs_ptr, 0x20) } { - /** - * input = public_input[i] - * valid_inputs &= input < p - * temp = input + gamma - * numerator_value *= (β.σ(i) + wᵢ + γ) // σ(i) = 0x05.ωⁱ - * denominator_value *= (β.σ'(i) + wᵢ + γ) // σ'(i) = 0x0c.ωⁱ - * root_1 *= ω - * root_2 *= ω - */ - - let input := calldataload(public_inputs_ptr) - valid_inputs := and(valid_inputs, lt(input, p_clone)) - let temp := addmod(input, gamma, p_clone) - - numerator_value := mulmod(numerator_value, add(root_1, temp), p_clone) - denominator_value := mulmod(denominator_value, add(root_2, temp), p_clone) - - root_1 := mulmod(root_1, work_root, p_clone) - root_2 := mulmod(root_2, work_root, p_clone) - } - - // Revert if not all public inputs are field elements (i.e. < p) - if iszero(valid_inputs) { - mstore(0x00, PUBLIC_INPUT_GE_P_SELECTOR) - revert(0x00, 0x04) - } - - mstore(DELTA_NUMERATOR_LOC, numerator_value) - mstore(DELTA_DENOMINATOR_LOC, denominator_value) - } - - /** - * Compute Plookup delta factor [γ(1 + β)]^{n-k} - * k = num roots cut out of Z_H = 4 - */ - { - let delta_base := mulmod(mload(C_GAMMA_LOC), addmod(mload(C_BETA_LOC), 1, p), p) - let delta_numerator := delta_base - { - let exponent := mload(N_LOC) - let count := 1 - for {} lt(count, exponent) { count := add(count, count) } { - delta_numerator := mulmod(delta_numerator, delta_numerator, p) - } - } - mstore(PLOOKUP_DELTA_NUMERATOR_LOC, delta_numerator) - - let delta_denominator := mulmod(delta_base, delta_base, p) - delta_denominator := mulmod(delta_denominator, delta_denominator, p) - mstore(PLOOKUP_DELTA_DENOMINATOR_LOC, delta_denominator) - } - /** - * Compute lagrange poly and vanishing poly fractions - */ - { - /** - * vanishing_numerator = zeta - * ZETA_POW_N = zeta^n - * vanishing_numerator -= 1 - * accumulating_root = omega_inverse - * work_root = p - accumulating_root - * domain_inverse = domain_inverse - * vanishing_denominator = zeta + work_root - * work_root *= accumulating_root - * vanishing_denominator *= (zeta + work_root) - * work_root *= accumulating_root - * vanishing_denominator *= (zeta + work_root) - * vanishing_denominator *= (zeta + (zeta + accumulating_root)) - * work_root = omega - * lagrange_numerator = vanishing_numerator * domain_inverse - * l_start_denominator = zeta - 1 - * accumulating_root = work_root^2 - * l_end_denominator = accumulating_root^2 * work_root * zeta - 1 - * Note: l_end_denominator term contains a term \omega^5 to cut out 5 roots of unity from vanishing poly - */ - - let zeta := mload(C_ZETA_LOC) - - // compute zeta^n, where n is a power of 2 - let vanishing_numerator := zeta - { - // pow_small - let exponent := mload(N_LOC) - let count := 1 - for {} lt(count, exponent) { count := add(count, count) } { - vanishing_numerator := mulmod(vanishing_numerator, vanishing_numerator, p) - } - } - mstore(ZETA_POW_N_LOC, vanishing_numerator) - vanishing_numerator := addmod(vanishing_numerator, sub(p, 1), p) - - let accumulating_root := mload(OMEGA_INVERSE_LOC) - let work_root := sub(p, accumulating_root) - let domain_inverse := mload(DOMAIN_INVERSE_LOC) - - let vanishing_denominator := addmod(zeta, work_root, p) - work_root := mulmod(work_root, accumulating_root, p) - vanishing_denominator := mulmod(vanishing_denominator, addmod(zeta, work_root, p), p) - work_root := mulmod(work_root, accumulating_root, p) - vanishing_denominator := mulmod(vanishing_denominator, addmod(zeta, work_root, p), p) - vanishing_denominator := - mulmod(vanishing_denominator, addmod(zeta, mulmod(work_root, accumulating_root, p), p), p) - - work_root := mload(OMEGA_LOC) - - let lagrange_numerator := mulmod(vanishing_numerator, domain_inverse, p) - let l_start_denominator := addmod(zeta, sub(p, 1), p) - - accumulating_root := mulmod(work_root, work_root, p) - - let l_end_denominator := - addmod( - mulmod(mulmod(mulmod(accumulating_root, accumulating_root, p), work_root, p), zeta, p), sub(p, 1), p - ) - - /** - * Compute inversions using Montgomery's batch inversion trick - */ - let accumulator := mload(DELTA_DENOMINATOR_LOC) - let t0 := accumulator - accumulator := mulmod(accumulator, vanishing_denominator, p) - let t1 := accumulator - accumulator := mulmod(accumulator, vanishing_numerator, p) - let t2 := accumulator - accumulator := mulmod(accumulator, l_start_denominator, p) - let t3 := accumulator - accumulator := mulmod(accumulator, mload(PLOOKUP_DELTA_DENOMINATOR_LOC), p) - let t4 := accumulator - { - mstore(0, 0x20) - mstore(0x20, 0x20) - mstore(0x40, 0x20) - mstore(0x60, mulmod(accumulator, l_end_denominator, p)) - mstore(0x80, sub(p, 2)) - mstore(0xa0, p) - if iszero(staticcall(gas(), 0x05, 0x00, 0xc0, 0x00, 0x20)) { - mstore(0x0, MOD_EXP_FAILURE_SELECTOR) - revert(0x00, 0x04) - } - accumulator := mload(0x00) - } - - t4 := mulmod(accumulator, t4, p) - accumulator := mulmod(accumulator, l_end_denominator, p) - - t3 := mulmod(accumulator, t3, p) - accumulator := mulmod(accumulator, mload(PLOOKUP_DELTA_DENOMINATOR_LOC), p) - - t2 := mulmod(accumulator, t2, p) - accumulator := mulmod(accumulator, l_start_denominator, p) - - t1 := mulmod(accumulator, t1, p) - accumulator := mulmod(accumulator, vanishing_numerator, p) - - t0 := mulmod(accumulator, t0, p) - accumulator := mulmod(accumulator, vanishing_denominator, p) - - accumulator := mulmod(mulmod(accumulator, accumulator, p), mload(DELTA_DENOMINATOR_LOC), p) - - mstore(PUBLIC_INPUT_DELTA_LOC, mulmod(mload(DELTA_NUMERATOR_LOC), accumulator, p)) - mstore(ZERO_POLY_LOC, mulmod(vanishing_numerator, t0, p)) - mstore(ZERO_POLY_INVERSE_LOC, mulmod(vanishing_denominator, t1, p)) - mstore(L_START_LOC, mulmod(lagrange_numerator, t2, p)) - mstore(PLOOKUP_DELTA_LOC, mulmod(mload(PLOOKUP_DELTA_NUMERATOR_LOC), t3, p)) - mstore(L_END_LOC, mulmod(lagrange_numerator, t4, p)) - } - - /** - * UltraPlonk Widget Ordering: - * - * 1. Permutation widget - * 2. Plookup widget - * 3. Arithmetic widget - * 4. Fixed base widget (?) - * 5. GenPermSort widget - * 6. Elliptic widget - * 7. Auxiliary widget - */ - - /** - * COMPUTE PERMUTATION WIDGET EVALUATION - */ - { - let alpha := mload(C_ALPHA_LOC) - let beta := mload(C_BETA_LOC) - let gamma := mload(C_GAMMA_LOC) - - /** - * t1 = (W1 + gamma + beta * ID1) * (W2 + gamma + beta * ID2) - * t2 = (W3 + gamma + beta * ID3) * (W4 + gamma + beta * ID4) - * result = alpha_base * z_eval * t1 * t2 - * t1 = (W1 + gamma + beta * sigma_1_eval) * (W2 + gamma + beta * sigma_2_eval) - * t2 = (W2 + gamma + beta * sigma_3_eval) * (W3 + gamma + beta * sigma_4_eval) - * result -= (alpha_base * z_omega_eval * t1 * t2) - */ - let t1 := - mulmod( - add(add(mload(W1_EVAL_LOC), gamma), mulmod(beta, mload(ID1_EVAL_LOC), p)), - add(add(mload(W2_EVAL_LOC), gamma), mulmod(beta, mload(ID2_EVAL_LOC), p)), - p - ) - let t2 := - mulmod( - add(add(mload(W3_EVAL_LOC), gamma), mulmod(beta, mload(ID3_EVAL_LOC), p)), - add(add(mload(W4_EVAL_LOC), gamma), mulmod(beta, mload(ID4_EVAL_LOC), p)), - p - ) - let result := mulmod(mload(C_ALPHA_BASE_LOC), mulmod(mload(Z_EVAL_LOC), mulmod(t1, t2, p), p), p) - t1 := - mulmod( - add(add(mload(W1_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA1_EVAL_LOC), p)), - add(add(mload(W2_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA2_EVAL_LOC), p)), - p - ) - t2 := - mulmod( - add(add(mload(W3_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA3_EVAL_LOC), p)), - add(add(mload(W4_EVAL_LOC), gamma), mulmod(beta, mload(SIGMA4_EVAL_LOC), p)), - p - ) - result := - addmod( - result, - sub(p, mulmod(mload(C_ALPHA_BASE_LOC), mulmod(mload(Z_OMEGA_EVAL_LOC), mulmod(t1, t2, p), p), p)), - p - ) - - /** - * alpha_base *= alpha - * result += alpha_base . (L_{n-k}(ʓ) . (z(ʓ.ω) - ∆_{PI})) - * alpha_base *= alpha - * result += alpha_base . (L_1(ʓ)(Z(ʓ) - 1)) - * alpha_Base *= alpha - */ - mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p)) - result := - addmod( - result, - mulmod( - mload(C_ALPHA_BASE_LOC), - mulmod( - mload(L_END_LOC), - addmod(mload(Z_OMEGA_EVAL_LOC), sub(p, mload(PUBLIC_INPUT_DELTA_LOC)), p), - p - ), - p - ), - p - ) - mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p)) - mstore( - PERMUTATION_IDENTITY, - addmod( - result, - mulmod( - mload(C_ALPHA_BASE_LOC), - mulmod(mload(L_START_LOC), addmod(mload(Z_EVAL_LOC), sub(p, 1), p), p), - p - ), - p - ) - ) - mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p)) - } - - /** - * COMPUTE PLOOKUP WIDGET EVALUATION - */ - { - /** - * Goal: f = (w1(z) + q2.w1(zω)) + η(w2(z) + qm.w2(zω)) + η²(w3(z) + qc.w_3(zω)) + q3(z).η³ - * f = η.q3(z) - * f += (w3(z) + qc.w_3(zω)) - * f *= η - * f += (w2(z) + qm.w2(zω)) - * f *= η - * f += (w1(z) + q2.w1(zω)) - */ - let f := mulmod(mload(C_ETA_LOC), mload(Q3_EVAL_LOC), p) - f := - addmod(f, addmod(mload(W3_EVAL_LOC), mulmod(mload(QC_EVAL_LOC), mload(W3_OMEGA_EVAL_LOC), p), p), p) - f := mulmod(f, mload(C_ETA_LOC), p) - f := - addmod(f, addmod(mload(W2_EVAL_LOC), mulmod(mload(QM_EVAL_LOC), mload(W2_OMEGA_EVAL_LOC), p), p), p) - f := mulmod(f, mload(C_ETA_LOC), p) - f := - addmod(f, addmod(mload(W1_EVAL_LOC), mulmod(mload(Q2_EVAL_LOC), mload(W1_OMEGA_EVAL_LOC), p), p), p) - - // t(z) = table4(z).η³ + table3(z).η² + table2(z).η + table1(z) - let t := - addmod( - addmod( - addmod( - mulmod(mload(TABLE4_EVAL_LOC), mload(C_ETA_CUBE_LOC), p), - mulmod(mload(TABLE3_EVAL_LOC), mload(C_ETA_SQR_LOC), p), - p - ), - mulmod(mload(TABLE2_EVAL_LOC), mload(C_ETA_LOC), p), - p - ), - mload(TABLE1_EVAL_LOC), - p - ) - - // t(zw) = table4(zw).η³ + table3(zw).η² + table2(zw).η + table1(zw) - let t_omega := - addmod( - addmod( - addmod( - mulmod(mload(TABLE4_OMEGA_EVAL_LOC), mload(C_ETA_CUBE_LOC), p), - mulmod(mload(TABLE3_OMEGA_EVAL_LOC), mload(C_ETA_SQR_LOC), p), - p - ), - mulmod(mload(TABLE2_OMEGA_EVAL_LOC), mload(C_ETA_LOC), p), - p - ), - mload(TABLE1_OMEGA_EVAL_LOC), - p - ) - - /** - * Goal: numerator = (TABLE_TYPE_EVAL * f(z) + γ) * (t(z) + βt(zω) + γ(β + 1)) * (β + 1) - * gamma_beta_constant = γ(β + 1) - * numerator = f * TABLE_TYPE_EVAL + gamma - * temp0 = t(z) + t(zω) * β + gamma_beta_constant - * numerator *= temp0 - * numerator *= (β + 1) - * temp0 = alpha * l_1 - * numerator += temp0 - * numerator *= z_lookup(z) - * numerator -= temp0 - */ - let gamma_beta_constant := mulmod(mload(C_GAMMA_LOC), addmod(mload(C_BETA_LOC), 1, p), p) - let numerator := addmod(mulmod(f, mload(TABLE_TYPE_EVAL_LOC), p), mload(C_GAMMA_LOC), p) - let temp0 := addmod(addmod(t, mulmod(t_omega, mload(C_BETA_LOC), p), p), gamma_beta_constant, p) - numerator := mulmod(numerator, temp0, p) - numerator := mulmod(numerator, addmod(mload(C_BETA_LOC), 1, p), p) - temp0 := mulmod(mload(C_ALPHA_LOC), mload(L_START_LOC), p) - numerator := addmod(numerator, temp0, p) - numerator := mulmod(numerator, mload(Z_LOOKUP_EVAL_LOC), p) - numerator := addmod(numerator, sub(p, temp0), p) - - /** - * Goal: denominator = z_lookup(zω)*[s(z) + βs(zω) + γ(1 + β)] - [z_lookup(zω) - [γ(1 + β)]^{n-k}]*α²L_end(z) - * note: delta_factor = [γ(1 + β)]^{n-k} - * denominator = s(z) + βs(zω) + γ(β + 1) - * temp1 = α²L_end(z) - * denominator -= temp1 - * denominator *= z_lookup(zω) - * denominator += temp1 * delta_factor - * PLOOKUP_IDENTITY = (numerator - denominator).alpha_base - * alpha_base *= alpha^3 - */ - let denominator := - addmod( - addmod(mload(S_EVAL_LOC), mulmod(mload(S_OMEGA_EVAL_LOC), mload(C_BETA_LOC), p), p), - gamma_beta_constant, - p - ) - let temp1 := mulmod(mload(C_ALPHA_SQR_LOC), mload(L_END_LOC), p) - denominator := addmod(denominator, sub(p, temp1), p) - denominator := mulmod(denominator, mload(Z_LOOKUP_OMEGA_EVAL_LOC), p) - denominator := addmod(denominator, mulmod(temp1, mload(PLOOKUP_DELTA_LOC), p), p) - - mstore(PLOOKUP_IDENTITY, mulmod(addmod(numerator, sub(p, denominator), p), mload(C_ALPHA_BASE_LOC), p)) - - // update alpha - mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_CUBE_LOC), p)) - } - - /** - * COMPUTE ARITHMETIC WIDGET EVALUATION - */ - { - /** - * The basic arithmetic gate identity in standard plonk is as follows. - * (w_1 . w_2 . q_m) + (w_1 . q_1) + (w_2 . q_2) + (w_3 . q_3) + (w_4 . q_4) + q_c = 0 - * However, for Ultraplonk, we extend this to support "passing" wires between rows (shown without alpha scaling below): - * q_arith * ( ( (-1/2) * (q_arith - 3) * q_m * w_1 * w_2 + q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c ) + - * (q_arith - 1)*( α * (q_arith - 2) * (w_1 + w_4 - w_1_omega + q_m) + w_4_omega) ) = 0 - * - * This formula results in several cases depending on q_arith: - * 1. q_arith == 0: Arithmetic gate is completely disabled - * - * 2. q_arith == 1: Everything in the minigate on the right is disabled. The equation is just a standard plonk equation - * with extra wires: q_m * w_1 * w_2 + q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c = 0 - * - * 3. q_arith == 2: The (w_1 + w_4 - ...) term is disabled. THe equation is: - * (1/2) * q_m * w_1 * w_2 + q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c + w_4_omega = 0 - * It allows defining w_4 at next index (w_4_omega) in terms of current wire values - * - * 4. q_arith == 3: The product of w_1 and w_2 is disabled, but a mini addition gate is enabled. α allows us to split - * the equation into two: - * - * q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c + 2 * w_4_omega = 0 - * and - * w_1 + w_4 - w_1_omega + q_m = 0 (we are reusing q_m here) - * - * 5. q_arith > 3: The product of w_1 and w_2 is scaled by (q_arith - 3), while the w_4_omega term is scaled by (q_arith - 1). - * The equation can be split into two: - * - * (q_arith - 3)* q_m * w_1 * w_ 2 + q_1 * w_1 + q_2 * w_2 + q_3 * w_3 + q_4 * w_4 + q_c + (q_arith - 1) * w_4_omega = 0 - * and - * w_1 + w_4 - w_1_omega + q_m = 0 - * - * The problem that q_m is used both in both equations can be dealt with by appropriately changing selector values at - * the next gate. Then we can treat (q_arith - 1) as a simulated q_6 selector and scale q_m to handle (q_arith - 3) at - * product. - */ - - let w1q1 := mulmod(mload(W1_EVAL_LOC), mload(Q1_EVAL_LOC), p) - let w2q2 := mulmod(mload(W2_EVAL_LOC), mload(Q2_EVAL_LOC), p) - let w3q3 := mulmod(mload(W3_EVAL_LOC), mload(Q3_EVAL_LOC), p) - let w4q3 := mulmod(mload(W4_EVAL_LOC), mload(Q4_EVAL_LOC), p) - - // @todo - Add a explicit test that hits QARITH == 3 - // w1w2qm := (w_1 . w_2 . q_m . (QARITH_EVAL_LOC - 3)) / 2 - let w1w2qm := - mulmod( - mulmod( - mulmod(mulmod(mload(W1_EVAL_LOC), mload(W2_EVAL_LOC), p), mload(QM_EVAL_LOC), p), - addmod(mload(QARITH_EVAL_LOC), sub(p, 3), p), - p - ), - NEGATIVE_INVERSE_OF_2_MODULO_P, - p - ) - - // (w_1 . w_2 . q_m . (q_arith - 3)) / -2) + (w_1 . q_1) + (w_2 . q_2) + (w_3 . q_3) + (w_4 . q_4) + q_c - let identity := - addmod( - mload(QC_EVAL_LOC), addmod(w4q3, addmod(w3q3, addmod(w2q2, addmod(w1q1, w1w2qm, p), p), p), p), p - ) - - // if q_arith == 3 we evaluate an additional mini addition gate (on top of the regular one), where: - // w_1 + w_4 - w_1_omega + q_m = 0 - // we use this gate to save an addition gate when adding or subtracting non-native field elements - // α * (q_arith - 2) * (w_1 + w_4 - w_1_omega + q_m) - let extra_small_addition_gate_identity := - mulmod( - mload(C_ALPHA_LOC), - mulmod( - addmod(mload(QARITH_EVAL_LOC), sub(p, 2), p), - addmod( - mload(QM_EVAL_LOC), - addmod( - sub(p, mload(W1_OMEGA_EVAL_LOC)), addmod(mload(W1_EVAL_LOC), mload(W4_EVAL_LOC), p), p - ), - p - ), - p - ), - p - ) - - // if q_arith == 2 OR q_arith == 3 we add the 4th wire of the NEXT gate into the arithmetic identity - // N.B. if q_arith > 2, this wire value will be scaled by (q_arith - 1) relative to the other gate wires! - // alpha_base * q_arith * (identity + (q_arith - 1) * (w_4_omega + extra_small_addition_gate_identity)) - mstore( - ARITHMETIC_IDENTITY, - mulmod( - mload(C_ALPHA_BASE_LOC), - mulmod( - mload(QARITH_EVAL_LOC), - addmod( - identity, - mulmod( - addmod(mload(QARITH_EVAL_LOC), sub(p, 1), p), - addmod(mload(W4_OMEGA_EVAL_LOC), extra_small_addition_gate_identity, p), - p - ), - p - ), - p - ), - p - ) - ) - - // update alpha - mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_SQR_LOC), p)) - } - - /** - * COMPUTE GENPERMSORT WIDGET EVALUATION - */ - { - /** - * D1 = (w2 - w1) - * D2 = (w3 - w2) - * D3 = (w4 - w3) - * D4 = (w1_omega - w4) - * - * α_a = alpha_base - * α_b = alpha_base * α - * α_c = alpha_base * α^2 - * α_d = alpha_base * α^3 - * - * range_accumulator = ( - * D1(D1 - 1)(D1 - 2)(D1 - 3).α_a + - * D2(D2 - 1)(D2 - 2)(D2 - 3).α_b + - * D3(D3 - 1)(D3 - 2)(D3 - 3).α_c + - * D4(D4 - 1)(D4 - 2)(D4 - 3).α_d + - * ) . q_sort - */ - let minus_two := sub(p, 2) - let minus_three := sub(p, 3) - let d1 := addmod(mload(W2_EVAL_LOC), sub(p, mload(W1_EVAL_LOC)), p) - let d2 := addmod(mload(W3_EVAL_LOC), sub(p, mload(W2_EVAL_LOC)), p) - let d3 := addmod(mload(W4_EVAL_LOC), sub(p, mload(W3_EVAL_LOC)), p) - let d4 := addmod(mload(W1_OMEGA_EVAL_LOC), sub(p, mload(W4_EVAL_LOC)), p) - - let range_accumulator := - mulmod( - mulmod( - mulmod(addmod(mulmod(d1, d1, p), sub(p, d1), p), addmod(d1, minus_two, p), p), - addmod(d1, minus_three, p), - p - ), - mload(C_ALPHA_BASE_LOC), - p - ) - range_accumulator := - addmod( - range_accumulator, - mulmod( - mulmod( - mulmod(addmod(mulmod(d2, d2, p), sub(p, d2), p), addmod(d2, minus_two, p), p), - addmod(d2, minus_three, p), - p - ), - mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p), - p - ), - p - ) - range_accumulator := - addmod( - range_accumulator, - mulmod( - mulmod( - mulmod(addmod(mulmod(d3, d3, p), sub(p, d3), p), addmod(d3, minus_two, p), p), - addmod(d3, minus_three, p), - p - ), - mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_SQR_LOC), p), - p - ), - p - ) - range_accumulator := - addmod( - range_accumulator, - mulmod( - mulmod( - mulmod(addmod(mulmod(d4, d4, p), sub(p, d4), p), addmod(d4, minus_two, p), p), - addmod(d4, minus_three, p), - p - ), - mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_CUBE_LOC), p), - p - ), - p - ) - range_accumulator := mulmod(range_accumulator, mload(QSORT_EVAL_LOC), p) - - mstore(SORT_IDENTITY, range_accumulator) - - // update alpha - mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_QUAD_LOC), p)) - } - - /** - * COMPUTE ELLIPTIC WIDGET EVALUATION - */ - { - /** - * endo_term = (-x_2) * x_1 * (x_3 * 2 + x_1) * q_beta - * endo_sqr_term = x_2^2 - * endo_sqr_term *= (x_3 - x_1) - * endo_sqr_term *= q_beta^2 - * leftovers = x_2^2 - * leftovers *= x_2 - * leftovers += x_1^2 * (x_3 + x_1) @follow-up Invalid comment in BB widget - * leftovers -= (y_2^2 + y_1^2) - * sign_term = y_2 * y_1 - * sign_term += sign_term - * sign_term *= q_sign - */ - // q_elliptic * (x3 + x2 + x1)(x2 - x1)(x2 - x1) - y2^2 - y1^2 + 2(y2y1)*q_sign = 0 - let x_diff := addmod(mload(X2_EVAL_LOC), sub(p, mload(X1_EVAL_LOC)), p) - let y2_sqr := mulmod(mload(Y2_EVAL_LOC), mload(Y2_EVAL_LOC), p) - let y1_sqr := mulmod(mload(Y1_EVAL_LOC), mload(Y1_EVAL_LOC), p) - let y1y2 := mulmod(mulmod(mload(Y1_EVAL_LOC), mload(Y2_EVAL_LOC), p), mload(QSIGN_LOC), p) - - let x_add_identity := - addmod( - mulmod( - addmod(mload(X3_EVAL_LOC), addmod(mload(X2_EVAL_LOC), mload(X1_EVAL_LOC), p), p), - mulmod(x_diff, x_diff, p), - p - ), - addmod( - sub( - p, - addmod(y2_sqr, y1_sqr, p) - ), - addmod(y1y2, y1y2, p), - p - ), - p - ) - x_add_identity := - mulmod( - mulmod( - x_add_identity, - addmod( - 1, - sub(p, mload(QM_EVAL_LOC)), - p - ), - p - ), - mload(C_ALPHA_BASE_LOC), - p - ) - - // q_elliptic * (x3 + x2 + x1)(x2 - x1)(x2 - x1) - y2^2 - y1^2 + 2(y2y1)*q_sign = 0 - let y1_plus_y3 := addmod( - mload(Y1_EVAL_LOC), - mload(Y3_EVAL_LOC), - p - ) - let y_diff := addmod(mulmod(mload(Y2_EVAL_LOC), mload(QSIGN_LOC), p), sub(p, mload(Y1_EVAL_LOC)), p) - let y_add_identity := - addmod( - mulmod(y1_plus_y3, x_diff, p), - mulmod(addmod(mload(X3_EVAL_LOC), sub(p, mload(X1_EVAL_LOC)), p), y_diff, p), - p - ) - y_add_identity := - mulmod( - mulmod(y_add_identity, addmod(1, sub(p, mload(QM_EVAL_LOC)), p), p), - mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p), - p - ) - - // ELLIPTIC_IDENTITY = (x_identity + y_identity) * Q_ELLIPTIC_EVAL - mstore( - ELLIPTIC_IDENTITY, mulmod(addmod(x_add_identity, y_add_identity, p), mload(QELLIPTIC_EVAL_LOC), p) - ) - } - { - /** - * x_pow_4 = (y_1_sqr - curve_b) * x_1; - * y_1_sqr_mul_4 = y_1_sqr + y_1_sqr; - * y_1_sqr_mul_4 += y_1_sqr_mul_4; - * x_1_pow_4_mul_9 = x_pow_4; - * x_1_pow_4_mul_9 += x_1_pow_4_mul_9; - * x_1_pow_4_mul_9 += x_1_pow_4_mul_9; - * x_1_pow_4_mul_9 += x_1_pow_4_mul_9; - * x_1_pow_4_mul_9 += x_pow_4; - * x_1_sqr_mul_3 = x_1_sqr + x_1_sqr + x_1_sqr; - * x_double_identity = (x_3 + x_1 + x_1) * y_1_sqr_mul_4 - x_1_pow_4_mul_9; - * y_double_identity = x_1_sqr_mul_3 * (x_1 - x_3) - (y_1 + y_1) * (y_1 + y_3); - */ - // (x3 + x1 + x1) (4y1*y1) - 9 * x1 * x1 * x1 * x1 = 0 - let x1_sqr := mulmod(mload(X1_EVAL_LOC), mload(X1_EVAL_LOC), p) - let y1_sqr := mulmod(mload(Y1_EVAL_LOC), mload(Y1_EVAL_LOC), p) - let x_pow_4 := mulmod(addmod(y1_sqr, GRUMPKIN_CURVE_B_PARAMETER_NEGATED, p), mload(X1_EVAL_LOC), p) - let y1_sqr_mul_4 := mulmod(y1_sqr, 4, p) - let x1_pow_4_mul_9 := mulmod(x_pow_4, 9, p) - let x1_sqr_mul_3 := mulmod(x1_sqr, 3, p) - let x_double_identity := - addmod( - mulmod( - addmod(mload(X3_EVAL_LOC), addmod(mload(X1_EVAL_LOC), mload(X1_EVAL_LOC), p), p), - y1_sqr_mul_4, - p - ), - sub(p, x1_pow_4_mul_9), - p - ) - // (y1 + y1) (2y1) - (3 * x1 * x1)(x1 - x3) = 0 - let y_double_identity := - addmod( - mulmod(x1_sqr_mul_3, addmod(mload(X1_EVAL_LOC), sub(p, mload(X3_EVAL_LOC)), p), p), - sub( - p, - mulmod( - addmod(mload(Y1_EVAL_LOC), mload(Y1_EVAL_LOC), p), - addmod(mload(Y1_EVAL_LOC), mload(Y3_EVAL_LOC), p), - p - ) - ), - p - ) - x_double_identity := mulmod(x_double_identity, mload(C_ALPHA_BASE_LOC), p) - y_double_identity := - mulmod(y_double_identity, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_LOC), p), p) - x_double_identity := mulmod(x_double_identity, mload(QM_EVAL_LOC), p) - y_double_identity := mulmod(y_double_identity, mload(QM_EVAL_LOC), p) - // ELLIPTIC_IDENTITY += (x_double_identity + y_double_identity) * Q_DOUBLE_EVAL - mstore( - ELLIPTIC_IDENTITY, - addmod( - mload(ELLIPTIC_IDENTITY), - mulmod(addmod(x_double_identity, y_double_identity, p), mload(QELLIPTIC_EVAL_LOC), p), - p - ) - ) - - // update alpha - mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_QUAD_LOC), p)) - } - - /** - * COMPUTE AUXILIARY WIDGET EVALUATION - */ - { - { - /** - * Non native field arithmetic gate 2 - * _ _ - * / _ _ _ 14 \ - * q_2 . q_4 | (w_1 . w_2) + (w_1 . w_2) + (w_1 . w_4 + w_2 . w_3 - w_3) . 2 - w_3 - w_4 | - * \_ _/ - * - * limb_subproduct = w_1 . w_2_omega + w_1_omega . w_2 - * non_native_field_gate_2 = w_1 * w_4 + w_4 * w_3 - w_3_omega - * non_native_field_gate_2 = non_native_field_gate_2 * limb_size - * non_native_field_gate_2 -= w_4_omega - * non_native_field_gate_2 += limb_subproduct - * non_native_field_gate_2 *= q_4 - * limb_subproduct *= limb_size - * limb_subproduct += w_1_omega * w_2_omega - * non_native_field_gate_1 = (limb_subproduct + w_3 + w_4) * q_3 - * non_native_field_gate_3 = (limb_subproduct + w_4 - (w_3_omega + w_4_omega)) * q_m - * non_native_field_identity = (non_native_field_gate_1 + non_native_field_gate_2 + non_native_field_gate_3) * q_2 - */ - - let limb_subproduct := - addmod( - mulmod(mload(W1_EVAL_LOC), mload(W2_OMEGA_EVAL_LOC), p), - mulmod(mload(W1_OMEGA_EVAL_LOC), mload(W2_EVAL_LOC), p), - p - ) - - let non_native_field_gate_2 := - addmod( - addmod( - mulmod(mload(W1_EVAL_LOC), mload(W4_EVAL_LOC), p), - mulmod(mload(W2_EVAL_LOC), mload(W3_EVAL_LOC), p), - p - ), - sub(p, mload(W3_OMEGA_EVAL_LOC)), - p - ) - non_native_field_gate_2 := mulmod(non_native_field_gate_2, LIMB_SIZE, p) - non_native_field_gate_2 := addmod(non_native_field_gate_2, sub(p, mload(W4_OMEGA_EVAL_LOC)), p) - non_native_field_gate_2 := addmod(non_native_field_gate_2, limb_subproduct, p) - non_native_field_gate_2 := mulmod(non_native_field_gate_2, mload(Q4_EVAL_LOC), p) - limb_subproduct := mulmod(limb_subproduct, LIMB_SIZE, p) - limb_subproduct := - addmod(limb_subproduct, mulmod(mload(W1_OMEGA_EVAL_LOC), mload(W2_OMEGA_EVAL_LOC), p), p) - let non_native_field_gate_1 := - mulmod( - addmod(limb_subproduct, sub(p, addmod(mload(W3_EVAL_LOC), mload(W4_EVAL_LOC), p)), p), - mload(Q3_EVAL_LOC), - p - ) - let non_native_field_gate_3 := - mulmod( - addmod( - addmod(limb_subproduct, mload(W4_EVAL_LOC), p), - sub(p, addmod(mload(W3_OMEGA_EVAL_LOC), mload(W4_OMEGA_EVAL_LOC), p)), - p - ), - mload(QM_EVAL_LOC), - p - ) - let non_native_field_identity := - mulmod( - addmod(addmod(non_native_field_gate_1, non_native_field_gate_2, p), non_native_field_gate_3, p), - mload(Q2_EVAL_LOC), - p - ) - - mstore(AUX_NON_NATIVE_FIELD_EVALUATION, non_native_field_identity) - } - - { - /** - * limb_accumulator_1 = w_2_omega; - * limb_accumulator_1 *= SUBLIMB_SHIFT; - * limb_accumulator_1 += w_1_omega; - * limb_accumulator_1 *= SUBLIMB_SHIFT; - * limb_accumulator_1 += w_3; - * limb_accumulator_1 *= SUBLIMB_SHIFT; - * limb_accumulator_1 += w_2; - * limb_accumulator_1 *= SUBLIMB_SHIFT; - * limb_accumulator_1 += w_1; - * limb_accumulator_1 -= w_4; - * limb_accumulator_1 *= q_4; - */ - let limb_accumulator_1 := mulmod(mload(W2_OMEGA_EVAL_LOC), SUBLIMB_SHIFT, p) - limb_accumulator_1 := addmod(limb_accumulator_1, mload(W1_OMEGA_EVAL_LOC), p) - limb_accumulator_1 := mulmod(limb_accumulator_1, SUBLIMB_SHIFT, p) - limb_accumulator_1 := addmod(limb_accumulator_1, mload(W3_EVAL_LOC), p) - limb_accumulator_1 := mulmod(limb_accumulator_1, SUBLIMB_SHIFT, p) - limb_accumulator_1 := addmod(limb_accumulator_1, mload(W2_EVAL_LOC), p) - limb_accumulator_1 := mulmod(limb_accumulator_1, SUBLIMB_SHIFT, p) - limb_accumulator_1 := addmod(limb_accumulator_1, mload(W1_EVAL_LOC), p) - limb_accumulator_1 := addmod(limb_accumulator_1, sub(p, mload(W4_EVAL_LOC)), p) - limb_accumulator_1 := mulmod(limb_accumulator_1, mload(Q4_EVAL_LOC), p) - - /** - * limb_accumulator_2 = w_3_omega; - * limb_accumulator_2 *= SUBLIMB_SHIFT; - * limb_accumulator_2 += w_2_omega; - * limb_accumulator_2 *= SUBLIMB_SHIFT; - * limb_accumulator_2 += w_1_omega; - * limb_accumulator_2 *= SUBLIMB_SHIFT; - * limb_accumulator_2 += w_4; - * limb_accumulator_2 *= SUBLIMB_SHIFT; - * limb_accumulator_2 += w_3; - * limb_accumulator_2 -= w_4_omega; - * limb_accumulator_2 *= q_m; - */ - let limb_accumulator_2 := mulmod(mload(W3_OMEGA_EVAL_LOC), SUBLIMB_SHIFT, p) - limb_accumulator_2 := addmod(limb_accumulator_2, mload(W2_OMEGA_EVAL_LOC), p) - limb_accumulator_2 := mulmod(limb_accumulator_2, SUBLIMB_SHIFT, p) - limb_accumulator_2 := addmod(limb_accumulator_2, mload(W1_OMEGA_EVAL_LOC), p) - limb_accumulator_2 := mulmod(limb_accumulator_2, SUBLIMB_SHIFT, p) - limb_accumulator_2 := addmod(limb_accumulator_2, mload(W4_EVAL_LOC), p) - limb_accumulator_2 := mulmod(limb_accumulator_2, SUBLIMB_SHIFT, p) - limb_accumulator_2 := addmod(limb_accumulator_2, mload(W3_EVAL_LOC), p) - limb_accumulator_2 := addmod(limb_accumulator_2, sub(p, mload(W4_OMEGA_EVAL_LOC)), p) - limb_accumulator_2 := mulmod(limb_accumulator_2, mload(QM_EVAL_LOC), p) - - mstore( - AUX_LIMB_ACCUMULATOR_EVALUATION, - mulmod(addmod(limb_accumulator_1, limb_accumulator_2, p), mload(Q3_EVAL_LOC), p) - ) - } - - { - /** - * memory_record_check = w_3; - * memory_record_check *= eta; - * memory_record_check += w_2; - * memory_record_check *= eta; - * memory_record_check += w_1; - * memory_record_check *= eta; - * memory_record_check += q_c; - * - * partial_record_check = memory_record_check; - * - * memory_record_check -= w_4; - */ - - let memory_record_check := mulmod(mload(W3_EVAL_LOC), mload(C_ETA_LOC), p) - memory_record_check := addmod(memory_record_check, mload(W2_EVAL_LOC), p) - memory_record_check := mulmod(memory_record_check, mload(C_ETA_LOC), p) - memory_record_check := addmod(memory_record_check, mload(W1_EVAL_LOC), p) - memory_record_check := mulmod(memory_record_check, mload(C_ETA_LOC), p) - memory_record_check := addmod(memory_record_check, mload(QC_EVAL_LOC), p) - - let partial_record_check := memory_record_check - memory_record_check := addmod(memory_record_check, sub(p, mload(W4_EVAL_LOC)), p) - - mstore(AUX_MEMORY_EVALUATION, memory_record_check) - - // index_delta = w_1_omega - w_1 - let index_delta := addmod(mload(W1_OMEGA_EVAL_LOC), sub(p, mload(W1_EVAL_LOC)), p) - // record_delta = w_4_omega - w_4 - let record_delta := addmod(mload(W4_OMEGA_EVAL_LOC), sub(p, mload(W4_EVAL_LOC)), p) - // index_is_monotonically_increasing = index_delta * (index_delta - 1) - let index_is_monotonically_increasing := mulmod(index_delta, addmod(index_delta, sub(p, 1), p), p) - - // adjacent_values_match_if_adjacent_indices_match = record_delta * (1 - index_delta) - let adjacent_values_match_if_adjacent_indices_match := - mulmod(record_delta, addmod(1, sub(p, index_delta), p), p) - - // AUX_ROM_CONSISTENCY_EVALUATION = ((adjacent_values_match_if_adjacent_indices_match * alpha) + index_is_monotonically_increasing) * alpha + partial_record_check - mstore( - AUX_ROM_CONSISTENCY_EVALUATION, - addmod( - mulmod( - addmod( - mulmod(adjacent_values_match_if_adjacent_indices_match, mload(C_ALPHA_LOC), p), - index_is_monotonically_increasing, - p - ), - mload(C_ALPHA_LOC), - p - ), - memory_record_check, - p - ) - ) - - { - /** - * next_gate_access_type = w_3_omega; - * next_gate_access_type *= eta; - * next_gate_access_type += w_2_omega; - * next_gate_access_type *= eta; - * next_gate_access_type += w_1_omega; - * next_gate_access_type *= eta; - * next_gate_access_type = w_4_omega - next_gate_access_type; - */ - let next_gate_access_type := mulmod(mload(W3_OMEGA_EVAL_LOC), mload(C_ETA_LOC), p) - next_gate_access_type := addmod(next_gate_access_type, mload(W2_OMEGA_EVAL_LOC), p) - next_gate_access_type := mulmod(next_gate_access_type, mload(C_ETA_LOC), p) - next_gate_access_type := addmod(next_gate_access_type, mload(W1_OMEGA_EVAL_LOC), p) - next_gate_access_type := mulmod(next_gate_access_type, mload(C_ETA_LOC), p) - next_gate_access_type := addmod(mload(W4_OMEGA_EVAL_LOC), sub(p, next_gate_access_type), p) - - // value_delta = w_3_omega - w_3 - let value_delta := addmod(mload(W3_OMEGA_EVAL_LOC), sub(p, mload(W3_EVAL_LOC)), p) - // adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation = (1 - index_delta) * value_delta * (1 - next_gate_access_type); - - let adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation := - mulmod( - addmod(1, sub(p, index_delta), p), - mulmod(value_delta, addmod(1, sub(p, next_gate_access_type), p), p), - p - ) - - // AUX_RAM_CONSISTENCY_EVALUATION - - /** - * access_type = w_4 - partial_record_check - * access_check = access_type^2 - access_type - * next_gate_access_type_is_boolean = next_gate_access_type^2 - next_gate_access_type - * RAM_consistency_check_identity = adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation; - * RAM_consistency_check_identity *= alpha; - * RAM_consistency_check_identity += index_is_monotonically_increasing; - * RAM_consistency_check_identity *= alpha; - * RAM_consistency_check_identity += next_gate_access_type_is_boolean; - * RAM_consistency_check_identity *= alpha; - * RAM_consistency_check_identity += access_check; - */ - - let access_type := addmod(mload(W4_EVAL_LOC), sub(p, partial_record_check), p) - let access_check := mulmod(access_type, addmod(access_type, sub(p, 1), p), p) - let next_gate_access_type_is_boolean := - mulmod(next_gate_access_type, addmod(next_gate_access_type, sub(p, 1), p), p) - let RAM_cci := - mulmod( - adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation, - mload(C_ALPHA_LOC), - p - ) - RAM_cci := addmod(RAM_cci, index_is_monotonically_increasing, p) - RAM_cci := mulmod(RAM_cci, mload(C_ALPHA_LOC), p) - RAM_cci := addmod(RAM_cci, next_gate_access_type_is_boolean, p) - RAM_cci := mulmod(RAM_cci, mload(C_ALPHA_LOC), p) - RAM_cci := addmod(RAM_cci, access_check, p) - - mstore(AUX_RAM_CONSISTENCY_EVALUATION, RAM_cci) - } - - { - // timestamp_delta = w_2_omega - w_2 - let timestamp_delta := addmod(mload(W2_OMEGA_EVAL_LOC), sub(p, mload(W2_EVAL_LOC)), p) - - // RAM_timestamp_check_identity = (1 - index_delta) * timestamp_delta - w_3 - let RAM_timestamp_check_identity := - addmod( - mulmod(timestamp_delta, addmod(1, sub(p, index_delta), p), p), sub(p, mload(W3_EVAL_LOC)), p - ) - - /** - * memory_identity = ROM_consistency_check_identity * q_2; - * memory_identity += RAM_timestamp_check_identity * q_4; - * memory_identity += memory_record_check * q_m; - * memory_identity *= q_1; - * memory_identity += (RAM_consistency_check_identity * q_arith); - * - * auxiliary_identity = memory_identity + non_native_field_identity + limb_accumulator_identity; - * auxiliary_identity *= q_aux; - * auxiliary_identity *= alpha_base; - */ - let memory_identity := mulmod(mload(AUX_ROM_CONSISTENCY_EVALUATION), mload(Q2_EVAL_LOC), p) - memory_identity := - addmod(memory_identity, mulmod(RAM_timestamp_check_identity, mload(Q4_EVAL_LOC), p), p) - memory_identity := - addmod(memory_identity, mulmod(mload(AUX_MEMORY_EVALUATION), mload(QM_EVAL_LOC), p), p) - memory_identity := mulmod(memory_identity, mload(Q1_EVAL_LOC), p) - memory_identity := - addmod( - memory_identity, mulmod(mload(AUX_RAM_CONSISTENCY_EVALUATION), mload(QARITH_EVAL_LOC), p), p - ) - - let auxiliary_identity := addmod(memory_identity, mload(AUX_NON_NATIVE_FIELD_EVALUATION), p) - auxiliary_identity := addmod(auxiliary_identity, mload(AUX_LIMB_ACCUMULATOR_EVALUATION), p) - auxiliary_identity := mulmod(auxiliary_identity, mload(QAUX_EVAL_LOC), p) - auxiliary_identity := mulmod(auxiliary_identity, mload(C_ALPHA_BASE_LOC), p) - - mstore(AUX_IDENTITY, auxiliary_identity) - - // update alpha - mstore(C_ALPHA_BASE_LOC, mulmod(mload(C_ALPHA_BASE_LOC), mload(C_ALPHA_CUBE_LOC), p)) - } - } - } - - { - /** - * quotient = ARITHMETIC_IDENTITY - * quotient += PERMUTATION_IDENTITY - * quotient += PLOOKUP_IDENTITY - * quotient += SORT_IDENTITY - * quotient += ELLIPTIC_IDENTITY - * quotient += AUX_IDENTITY - * quotient *= ZERO_POLY_INVERSE - */ - mstore( - QUOTIENT_EVAL_LOC, - mulmod( - addmod( - addmod( - addmod( - addmod( - addmod(mload(PERMUTATION_IDENTITY), mload(PLOOKUP_IDENTITY), p), - mload(ARITHMETIC_IDENTITY), - p - ), - mload(SORT_IDENTITY), - p - ), - mload(ELLIPTIC_IDENTITY), - p - ), - mload(AUX_IDENTITY), - p - ), - mload(ZERO_POLY_INVERSE_LOC), - p - ) - ) - } - - /** - * GENERATE NU AND SEPARATOR CHALLENGES - */ - { - let current_challenge := mload(C_CURRENT_LOC) - // get a calldata pointer that points to the start of the data we want to copy - let calldata_ptr := add(calldataload(0x04), 0x24) - - calldata_ptr := add(calldata_ptr, NU_CALLDATA_SKIP_LENGTH) - - mstore(NU_CHALLENGE_INPUT_LOC_A, current_challenge) - mstore(NU_CHALLENGE_INPUT_LOC_B, mload(QUOTIENT_EVAL_LOC)) - calldatacopy(NU_CHALLENGE_INPUT_LOC_C, calldata_ptr, NU_INPUT_LENGTH) - - // hash length = (0x20 + num field elements), we include the previous challenge in the hash - let challenge := keccak256(NU_CHALLENGE_INPUT_LOC_A, add(NU_INPUT_LENGTH, 0x40)) - - mstore(C_V0_LOC, mod(challenge, p)) - // We need THIRTY-ONE independent nu challenges! - mstore(0x00, challenge) - mstore8(0x20, 0x01) - mstore(C_V1_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x02) - mstore(C_V2_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x03) - mstore(C_V3_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x04) - mstore(C_V4_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x05) - mstore(C_V5_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x06) - mstore(C_V6_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x07) - mstore(C_V7_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x08) - mstore(C_V8_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x09) - mstore(C_V9_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x0a) - mstore(C_V10_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x0b) - mstore(C_V11_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x0c) - mstore(C_V12_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x0d) - mstore(C_V13_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x0e) - mstore(C_V14_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x0f) - mstore(C_V15_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x10) - mstore(C_V16_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x11) - mstore(C_V17_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x12) - mstore(C_V18_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x13) - mstore(C_V19_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x14) - mstore(C_V20_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x15) - mstore(C_V21_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x16) - mstore(C_V22_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x17) - mstore(C_V23_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x18) - mstore(C_V24_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x19) - mstore(C_V25_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x1a) - mstore(C_V26_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x1b) - mstore(C_V27_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x1c) - mstore(C_V28_LOC, mod(keccak256(0x00, 0x21), p)) - mstore8(0x20, 0x1d) - mstore(C_V29_LOC, mod(keccak256(0x00, 0x21), p)) - - // @follow-up - Why are both v29 and v30 using appending 0x1d to the prior challenge and hashing, should it not change? - mstore8(0x20, 0x1d) - challenge := keccak256(0x00, 0x21) - mstore(C_V30_LOC, mod(challenge, p)) - - // separator - mstore(0x00, challenge) - mstore(0x20, mload(PI_Z_Y_LOC)) - mstore(0x40, mload(PI_Z_X_LOC)) - mstore(0x60, mload(PI_Z_OMEGA_Y_LOC)) - mstore(0x80, mload(PI_Z_OMEGA_X_LOC)) - - mstore(C_U_LOC, mod(keccak256(0x00, 0xa0), p)) - } - - let success := 0 - // VALIDATE T1 - { - let x := mload(T1_X_LOC) - let y := mload(T1_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(ACCUMULATOR_X_LOC, x) - mstore(add(ACCUMULATOR_X_LOC, 0x20), y) - } - // VALIDATE T2 - { - let x := mload(T2_X_LOC) // 0x1400 - let y := mload(T2_Y_LOC) // 0x1420 - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(ZETA_POW_N_LOC)) - // accumulator_2 = [T2].zeta^n - success := staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40) - // accumulator = [T1] + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE T3 - { - let x := mload(T3_X_LOC) - let y := mload(T3_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(mload(ZETA_POW_N_LOC), mload(ZETA_POW_N_LOC), p)) - // accumulator_2 = [T3].zeta^{2n} - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE T4 - { - let x := mload(T4_X_LOC) - let y := mload(T4_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(mulmod(mload(ZETA_POW_N_LOC), mload(ZETA_POW_N_LOC), p), mload(ZETA_POW_N_LOC), p)) - // accumulator_2 = [T4].zeta^{3n} - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE W1 - { - let x := mload(W1_X_LOC) - let y := mload(W1_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V0_LOC), p)) - // accumulator_2 = v0.(u + 1).[W1] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE W2 - { - let x := mload(W2_X_LOC) - let y := mload(W2_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V1_LOC), p)) - // accumulator_2 = v1.(u + 1).[W2] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE W3 - { - let x := mload(W3_X_LOC) - let y := mload(W3_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V2_LOC), p)) - // accumulator_2 = v2.(u + 1).[W3] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE W4 - { - let x := mload(W4_X_LOC) - let y := mload(W4_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V3_LOC), p)) - // accumulator_2 = v3.(u + 1).[W4] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE S - { - let x := mload(S_X_LOC) - let y := mload(S_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V4_LOC), p)) - // accumulator_2 = v4.(u + 1).[S] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE Z - { - let x := mload(Z_X_LOC) - let y := mload(Z_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V5_LOC), p)) - // accumulator_2 = v5.(u + 1).[Z] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE Z_LOOKUP - { - let x := mload(Z_LOOKUP_X_LOC) - let y := mload(Z_LOOKUP_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V6_LOC), p)) - // accumulator_2 = v6.(u + 1).[Z_LOOKUP] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE Q1 - { - let x := mload(Q1_X_LOC) - let y := mload(Q1_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V7_LOC)) - // accumulator_2 = v7.[Q1] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE Q2 - { - let x := mload(Q2_X_LOC) - let y := mload(Q2_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V8_LOC)) - // accumulator_2 = v8.[Q2] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE Q3 - { - let x := mload(Q3_X_LOC) - let y := mload(Q3_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V9_LOC)) - // accumulator_2 = v9.[Q3] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE Q4 - { - let x := mload(Q4_X_LOC) - let y := mload(Q4_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V10_LOC)) - // accumulator_2 = v10.[Q4] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE QM - { - let x := mload(QM_X_LOC) - let y := mload(QM_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V11_LOC)) - // accumulator_2 = v11.[Q;] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE QC - { - let x := mload(QC_X_LOC) - let y := mload(QC_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V12_LOC)) - // accumulator_2 = v12.[QC] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE QARITH - { - let x := mload(QARITH_X_LOC) - let y := mload(QARITH_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V13_LOC)) - // accumulator_2 = v13.[QARITH] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE QSORT - { - let x := mload(QSORT_X_LOC) - let y := mload(QSORT_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V14_LOC)) - // accumulator_2 = v14.[QSORT] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE QELLIPTIC - { - let x := mload(QELLIPTIC_X_LOC) - let y := mload(QELLIPTIC_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V15_LOC)) - // accumulator_2 = v15.[QELLIPTIC] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE QAUX - { - let x := mload(QAUX_X_LOC) - let y := mload(QAUX_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V16_LOC)) - // accumulator_2 = v15.[Q_AUX] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE SIGMA1 - { - let x := mload(SIGMA1_X_LOC) - let y := mload(SIGMA1_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V17_LOC)) - // accumulator_2 = v17.[sigma1] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE SIGMA2 - { - let x := mload(SIGMA2_X_LOC) - let y := mload(SIGMA2_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V18_LOC)) - // accumulator_2 = v18.[sigma2] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE SIGMA3 - { - let x := mload(SIGMA3_X_LOC) - let y := mload(SIGMA3_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V19_LOC)) - // accumulator_2 = v19.[sigma3] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE SIGMA4 - { - let x := mload(SIGMA4_X_LOC) - let y := mload(SIGMA4_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V20_LOC)) - // accumulator_2 = v20.[sigma4] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE TABLE1 - { - let x := mload(TABLE1_X_LOC) - let y := mload(TABLE1_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V21_LOC), p)) - // accumulator_2 = u.[table1] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE TABLE2 - { - let x := mload(TABLE2_X_LOC) - let y := mload(TABLE2_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V22_LOC), p)) - // accumulator_2 = u.[table2] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE TABLE3 - { - let x := mload(TABLE3_X_LOC) - let y := mload(TABLE3_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V23_LOC), p)) - // accumulator_2 = u.[table3] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE TABLE4 - { - let x := mload(TABLE4_X_LOC) - let y := mload(TABLE4_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(addmod(mload(C_U_LOC), 0x1, p), mload(C_V24_LOC), p)) - // accumulator_2 = u.[table4] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE TABLE_TYPE - { - let x := mload(TABLE_TYPE_X_LOC) - let y := mload(TABLE_TYPE_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V25_LOC)) - // accumulator_2 = v25.[TableType] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE ID1 - { - let x := mload(ID1_X_LOC) - let y := mload(ID1_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V26_LOC)) - // accumulator_2 = v26.[ID1] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE ID2 - { - let x := mload(ID2_X_LOC) - let y := mload(ID2_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V27_LOC)) - // accumulator_2 = v27.[ID2] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE ID3 - { - let x := mload(ID3_X_LOC) - let y := mload(ID3_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V28_LOC)) - // accumulator_2 = v28.[ID3] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE ID4 - { - let x := mload(ID4_X_LOC) - let y := mload(ID4_Y_LOC) - let xx := mulmod(x, x, q) - // Verification key fields verified to be on curve at contract deployment - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mload(C_V29_LOC)) - // accumulator_2 = v29.[ID4] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - /** - * COMPUTE BATCH EVALUATION SCALAR MULTIPLIER - */ - { - /** - * batch_evaluation = v0 * (w_1_omega * u + w_1_eval) - * batch_evaluation += v1 * (w_2_omega * u + w_2_eval) - * batch_evaluation += v2 * (w_3_omega * u + w_3_eval) - * batch_evaluation += v3 * (w_4_omega * u + w_4_eval) - * batch_evaluation += v4 * (s_omega_eval * u + s_eval) - * batch_evaluation += v5 * (z_omega_eval * u + z_eval) - * batch_evaluation += v6 * (z_lookup_omega_eval * u + z_lookup_eval) - */ - let batch_evaluation := - mulmod( - mload(C_V0_LOC), - addmod(mulmod(mload(W1_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W1_EVAL_LOC), p), - p - ) - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V1_LOC), - addmod(mulmod(mload(W2_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W2_EVAL_LOC), p), - p - ), - p - ) - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V2_LOC), - addmod(mulmod(mload(W3_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W3_EVAL_LOC), p), - p - ), - p - ) - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V3_LOC), - addmod(mulmod(mload(W4_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(W4_EVAL_LOC), p), - p - ), - p - ) - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V4_LOC), - addmod(mulmod(mload(S_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(S_EVAL_LOC), p), - p - ), - p - ) - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V5_LOC), - addmod(mulmod(mload(Z_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(Z_EVAL_LOC), p), - p - ), - p - ) - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V6_LOC), - addmod(mulmod(mload(Z_LOOKUP_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(Z_LOOKUP_EVAL_LOC), p), - p - ), - p - ) - - /** - * batch_evaluation += v7 * Q1_EVAL - * batch_evaluation += v8 * Q2_EVAL - * batch_evaluation += v9 * Q3_EVAL - * batch_evaluation += v10 * Q4_EVAL - * batch_evaluation += v11 * QM_EVAL - * batch_evaluation += v12 * QC_EVAL - * batch_evaluation += v13 * QARITH_EVAL - * batch_evaluation += v14 * QSORT_EVAL_LOC - * batch_evaluation += v15 * QELLIPTIC_EVAL_LOC - * batch_evaluation += v16 * QAUX_EVAL_LOC - * batch_evaluation += v17 * SIGMA1_EVAL_LOC - * batch_evaluation += v18 * SIGMA2_EVAL_LOC - * batch_evaluation += v19 * SIGMA3_EVAL_LOC - * batch_evaluation += v20 * SIGMA4_EVAL_LOC - */ - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V7_LOC), mload(Q1_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V8_LOC), mload(Q2_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V9_LOC), mload(Q3_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V10_LOC), mload(Q4_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V11_LOC), mload(QM_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V12_LOC), mload(QC_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V13_LOC), mload(QARITH_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V14_LOC), mload(QSORT_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V15_LOC), mload(QELLIPTIC_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V16_LOC), mload(QAUX_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V17_LOC), mload(SIGMA1_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V18_LOC), mload(SIGMA2_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V19_LOC), mload(SIGMA3_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V20_LOC), mload(SIGMA4_EVAL_LOC), p), p) - - /** - * batch_evaluation += v21 * (table1(zw) * u + table1(z)) - * batch_evaluation += v22 * (table2(zw) * u + table2(z)) - * batch_evaluation += v23 * (table3(zw) * u + table3(z)) - * batch_evaluation += v24 * (table4(zw) * u + table4(z)) - * batch_evaluation += v25 * table_type_eval - * batch_evaluation += v26 * id1_eval - * batch_evaluation += v27 * id2_eval - * batch_evaluation += v28 * id3_eval - * batch_evaluation += v29 * id4_eval - * batch_evaluation += quotient_eval - */ - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V21_LOC), - addmod(mulmod(mload(TABLE1_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE1_EVAL_LOC), p), - p - ), - p - ) - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V22_LOC), - addmod(mulmod(mload(TABLE2_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE2_EVAL_LOC), p), - p - ), - p - ) - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V23_LOC), - addmod(mulmod(mload(TABLE3_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE3_EVAL_LOC), p), - p - ), - p - ) - batch_evaluation := - addmod( - batch_evaluation, - mulmod( - mload(C_V24_LOC), - addmod(mulmod(mload(TABLE4_OMEGA_EVAL_LOC), mload(C_U_LOC), p), mload(TABLE4_EVAL_LOC), p), - p - ), - p - ) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V25_LOC), mload(TABLE_TYPE_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V26_LOC), mload(ID1_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V27_LOC), mload(ID2_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V28_LOC), mload(ID3_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mulmod(mload(C_V29_LOC), mload(ID4_EVAL_LOC), p), p) - batch_evaluation := addmod(batch_evaluation, mload(QUOTIENT_EVAL_LOC), p) - - mstore(0x00, 0x01) // [1].x - mstore(0x20, 0x02) // [1].y - mstore(0x40, sub(p, batch_evaluation)) - // accumulator_2 = -[1].(batch_evaluation) - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - if iszero(success) { - mstore(0x0, OPENING_COMMITMENT_FAILED_SELECTOR) - revert(0x00, 0x04) - } - } - - /** - * PERFORM PAIRING PREAMBLE - */ - { - let u := mload(C_U_LOC) - let zeta := mload(C_ZETA_LOC) - // VALIDATE PI_Z - { - let x := mload(PI_Z_X_LOC) - let y := mload(PI_Z_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - // compute zeta.[PI_Z] and add into accumulator - mstore(0x40, zeta) - success := staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40) - // accumulator = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - - // VALIDATE PI_Z_OMEGA - { - let x := mload(PI_Z_OMEGA_X_LOC) - let y := mload(PI_Z_OMEGA_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - mstore(0x40, mulmod(mulmod(u, zeta, p), mload(OMEGA_LOC), p)) - // accumulator_2 = u.zeta.omega.[PI_Z_OMEGA] - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) - // PAIRING_RHS = accumulator + accumulator_2 - success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, PAIRING_RHS_X_LOC, 0x40)) - - mstore(0x00, mload(PI_Z_X_LOC)) - mstore(0x20, mload(PI_Z_Y_LOC)) - mstore(0x40, mload(PI_Z_OMEGA_X_LOC)) - mstore(0x60, mload(PI_Z_OMEGA_Y_LOC)) - mstore(0x80, u) - success := and(success, staticcall(gas(), 7, 0x40, 0x60, 0x40, 0x40)) - // PAIRING_LHS = [PI_Z] + [PI_Z_OMEGA] * u - success := and(success, staticcall(gas(), 6, 0x00, 0x80, PAIRING_LHS_X_LOC, 0x40)) - // negate lhs y-coordinate - mstore(PAIRING_LHS_Y_LOC, sub(q, mload(PAIRING_LHS_Y_LOC))) - - if mload(CONTAINS_RECURSIVE_PROOF_LOC) { - // VALIDATE RECURSIVE P1 - { - let x := mload(RECURSIVE_P1_X_LOC) - let y := mload(RECURSIVE_P1_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - - // compute u.u.[recursive_p1] and write into 0x60 - mstore(0x40, mulmod(u, u, p)) - success := and(success, staticcall(gas(), 7, 0x00, 0x60, 0x60, 0x40)) - // VALIDATE RECURSIVE P2 - { - let x := mload(RECURSIVE_P2_X_LOC) - let y := mload(RECURSIVE_P2_Y_LOC) - let xx := mulmod(x, x, q) - // validate on curve - if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { - mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) - revert(0x00, 0x04) - } - mstore(0x00, x) - mstore(0x20, y) - } - // compute u.u.[recursive_p2] and write into 0x00 - // 0x40 still contains u*u - success := and(success, staticcall(gas(), 7, 0x00, 0x60, 0x00, 0x40)) - - // compute u.u.[recursiveP1] + rhs and write into rhs - mstore(0xa0, mload(PAIRING_RHS_X_LOC)) - mstore(0xc0, mload(PAIRING_RHS_Y_LOC)) - success := and(success, staticcall(gas(), 6, 0x60, 0x80, PAIRING_RHS_X_LOC, 0x40)) - - // compute u.u.[recursiveP2] + lhs and write into lhs - mstore(0x40, mload(PAIRING_LHS_X_LOC)) - mstore(0x60, mload(PAIRING_LHS_Y_LOC)) - success := and(success, staticcall(gas(), 6, 0x00, 0x80, PAIRING_LHS_X_LOC, 0x40)) - } - - if iszero(success) { - mstore(0x0, PAIRING_PREAMBLE_FAILED_SELECTOR) - revert(0x00, 0x04) - } - } - - /** - * PERFORM PAIRING - */ - { - // rhs paired with [1]_2 - // lhs paired with [x]_2 - - mstore(0x00, mload(PAIRING_RHS_X_LOC)) - mstore(0x20, mload(PAIRING_RHS_Y_LOC)) - mstore(0x40, 0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2) // this is [1]_2 - mstore(0x60, 0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed) - mstore(0x80, 0x090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b) - mstore(0xa0, 0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa) - - mstore(0xc0, mload(PAIRING_LHS_X_LOC)) - mstore(0xe0, mload(PAIRING_LHS_Y_LOC)) - mstore(0x100, mload(G2X_X0_LOC)) - mstore(0x120, mload(G2X_X1_LOC)) - mstore(0x140, mload(G2X_Y0_LOC)) - mstore(0x160, mload(G2X_Y1_LOC)) - - success := staticcall(gas(), 8, 0x00, 0x180, 0x00, 0x20) - if iszero(and(success, mload(0x00))) { - mstore(0x0, PAIRING_FAILED_SELECTOR) - revert(0x00, 0x04) - } - } - - { - mstore(0x00, 0x01) - return(0x00, 0x20) // Proof succeeded! - } - } - } -} - -contract UltraVerifier is BaseUltraVerifier { - function getVerificationKeyHash() public pure override(BaseUltraVerifier) returns (bytes32) { - return UltraVerificationKey.verificationKeyHash(); - } - - function loadVerificationKey(uint256 vk, uint256 _omegaInverseLoc) internal pure virtual override(BaseUltraVerifier) { - UltraVerificationKey.loadVerificationKey(vk, _omegaInverseLoc); - } -} From 90cd0cfa8f60f087e81656b9989e57747bc1ec9f Mon Sep 17 00:00:00 2001 From: vezenovm Date: Wed, 13 Mar 2024 18:10:01 +0000 Subject: [PATCH 069/139] cleanup --- barretenberg/acir_tests/run_acir_tests.sh | 2 +- .../acvm-repo/acir/src/circuit/mod.rs | 72 ++++--------------- .../execution_success/recursion/Nargo.toml | 7 -- .../execution_success/recursion/Prover.toml | 4 -- .../execution_success/recursion/src/main.nr | 16 ----- .../backend_interface/src/proof_system.rs | 8 +-- .../backend_interface/src/smart_contract.rs | 1 - 7 files changed, 19 insertions(+), 91 deletions(-) delete mode 100644 noir/noir-repo/test_programs/execution_success/recursion/Nargo.toml delete mode 100644 noir/noir-repo/test_programs/execution_success/recursion/Prover.toml delete mode 100644 noir/noir-repo/test_programs/execution_success/recursion/src/main.nr diff --git a/barretenberg/acir_tests/run_acir_tests.sh b/barretenberg/acir_tests/run_acir_tests.sh index 4203d9448f91..88189a434380 100755 --- a/barretenberg/acir_tests/run_acir_tests.sh +++ b/barretenberg/acir_tests/run_acir_tests.sh @@ -35,7 +35,7 @@ export BIN CRS_PATH VERBOSE BRANCH cd acir_tests # Convert them to array -SKIP_ARRAY=(diamond_deps_0 workspace workspace_default_member recursion) +SKIP_ARRAY=(diamond_deps_0 workspace workspace_default_member) function test() { cd $1 diff --git a/noir/noir-repo/acvm-repo/acir/src/circuit/mod.rs b/noir/noir-repo/acvm-repo/acir/src/circuit/mod.rs index 3d4d62969815..b5d6348d34f6 100644 --- a/noir/noir-repo/acvm-repo/acir/src/circuit/mod.rs +++ b/noir/noir-repo/acvm-repo/acir/src/circuit/mod.rs @@ -159,55 +159,6 @@ impl Circuit { self.public_parameters.0.union(&self.return_values.0).cloned().collect(); PublicInputs(public_inputs) } - - fn write(&self, writer: W) -> std::io::Result<()> { - let buf = bincode::serialize(self).unwrap(); - let mut encoder = flate2::write::GzEncoder::new(writer, Compression::default()); - encoder.write_all(&buf)?; - encoder.finish()?; - Ok(()) - } - - fn read(reader: R) -> std::io::Result { - let mut gz_decoder = flate2::read::GzDecoder::new(reader); - let mut buf_d = Vec::new(); - gz_decoder.read_to_end(&mut buf_d)?; - bincode::deserialize(&buf_d) - .map_err(|err| std::io::Error::new(std::io::ErrorKind::InvalidInput, err)) - } - - pub fn serialize_circuit(circuit: &Circuit) -> Vec { - let mut circuit_bytes: Vec = Vec::new(); - circuit.write(&mut circuit_bytes).expect("expected circuit to be serializable"); - circuit_bytes - } - - pub fn deserialize_circuit(serialized_circuit: &[u8]) -> std::io::Result { - Circuit::read(serialized_circuit) - } - - // Serialize and base64 encode circuit - pub fn serialize_circuit_base64(circuit: &Circuit, s: S) -> Result - where - S: Serializer, - { - let circuit_bytes = Circuit::serialize_circuit(circuit); - let encoded_b64 = base64::engine::general_purpose::STANDARD.encode(circuit_bytes); - s.serialize_str(&encoded_b64) - } - - // Deserialize and base64 decode circuit - pub fn deserialize_circuit_base64<'de, D>(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - let bytecode_b64: String = serde::Deserialize::deserialize(deserializer)?; - let circuit_bytes = base64::engine::general_purpose::STANDARD - .decode(bytecode_b64) - .map_err(D::Error::custom)?; - let circuit = Self::deserialize_circuit(&circuit_bytes).map_err(D::Error::custom)?; - Ok(circuit) - } } impl Program { @@ -336,7 +287,10 @@ mod tests { opcodes::{BlackBoxFuncCall, FunctionInput}, Circuit, Compression, Opcode, PublicInputs, }; - use crate::{circuit::ExpressionWidth, native_types::Witness}; + use crate::{ + circuit::{ExpressionWidth, Program}, + native_types::Witness, + }; use acir_field::FieldElement; fn and_opcode() -> Opcode { @@ -422,14 +376,15 @@ mod tests { assert_messages: Default::default(), recursive: false, }; + let program = Program { functions: vec![circuit] }; - fn read_write(circuit: Circuit) -> (Circuit, Circuit) { - let bytes = Circuit::serialize_circuit(&circuit); - let got_circuit = Circuit::deserialize_circuit(&bytes).unwrap(); - (circuit, got_circuit) + fn read_write(program: Program) -> (Program, Program) { + let bytes = Program::serialize_program(&program); + let got_program = Program::deserialize_program(&bytes).unwrap(); + (program, got_program) } - let (circ, got_circ) = read_write(circuit); + let (circ, got_circ) = read_write(program); assert_eq!(circ, got_circ); } @@ -454,11 +409,12 @@ mod tests { assert_messages: Default::default(), recursive: false, }; + let program = Program { functions: vec![circuit] }; - let json = serde_json::to_string_pretty(&circuit).unwrap(); + let json = serde_json::to_string_pretty(&program).unwrap(); let deserialized = serde_json::from_str(&json).unwrap(); - assert_eq!(circuit, deserialized); + assert_eq!(program, deserialized); } #[test] @@ -474,7 +430,7 @@ mod tests { encoder.write_all(bad_circuit).unwrap(); encoder.finish().unwrap(); - let deserialization_result = Circuit::deserialize_circuit(&zipped_bad_circuit); + let deserialization_result = Program::deserialize_program(&zipped_bad_circuit); assert!(deserialization_result.is_err()); } } diff --git a/noir/noir-repo/test_programs/execution_success/recursion/Nargo.toml b/noir/noir-repo/test_programs/execution_success/recursion/Nargo.toml deleted file mode 100644 index fe1ba8b1ce62..000000000000 --- a/noir/noir-repo/test_programs/execution_success/recursion/Nargo.toml +++ /dev/null @@ -1,7 +0,0 @@ -[package] -name = "recursion" -type = "bin" -authors = [""] -compiler_version = ">=0.24.0" - -[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/execution_success/recursion/Prover.toml b/noir/noir-repo/test_programs/execution_success/recursion/Prover.toml deleted file mode 100644 index b00cd8661d8f..000000000000 --- a/noir/noir-repo/test_programs/execution_success/recursion/Prover.toml +++ /dev/null @@ -1,4 +0,0 @@ -key_hash = "0" -public_inputs = ["0"] -verification_key = ['0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'] -proof = ['0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/execution_success/recursion/src/main.nr b/noir/noir-repo/test_programs/execution_success/recursion/src/main.nr deleted file mode 100644 index f1b3875e1d4c..000000000000 --- a/noir/noir-repo/test_programs/execution_success/recursion/src/main.nr +++ /dev/null @@ -1,16 +0,0 @@ -use dep::std; - -// This test is used to generate artifacts for the compiler `integration-tests` -fn main( - verification_key: [Field; 114], - proof: [Field; 93], - public_inputs: [Field; 1], - key_hash: Field -) { - std::verify_proof( - verification_key.as_slice(), - proof.as_slice(), - public_inputs.as_slice(), - key_hash - ) -} diff --git a/noir/noir-repo/tooling/backend_interface/src/proof_system.rs b/noir/noir-repo/tooling/backend_interface/src/proof_system.rs index 83ee04f90428..c3c138095ee7 100644 --- a/noir/noir-repo/tooling/backend_interface/src/proof_system.rs +++ b/noir/noir-repo/tooling/backend_interface/src/proof_system.rs @@ -129,7 +129,7 @@ impl Backend { pub fn get_intermediate_proof_artifacts( &self, - circuit: &Circuit, + program: &Program, proof: &[u8], public_inputs: WitnessMap, ) -> Result<(Vec, FieldElement, Vec), BackendError> { @@ -141,9 +141,9 @@ impl Backend { // Create a temporary file for the circuit // - let bytecode_path = temp_directory.join("circuit").with_extension("bytecode"); - let serialized_circuit = Circuit::serialize_circuit(circuit); - write_to_file(&serialized_circuit, &bytecode_path); + let bytecode_path = temp_directory.join("program").with_extension("bytecode"); + let serialized_program = Program::serialize_program(program); + write_to_file(&serialized_program, &bytecode_path); // Create the verification key and write it to the specified path let vk_path = temp_directory.join("vk"); diff --git a/noir/noir-repo/tooling/backend_interface/src/smart_contract.rs b/noir/noir-repo/tooling/backend_interface/src/smart_contract.rs index 3b0d6bc9efb4..f6beeeb09d99 100644 --- a/noir/noir-repo/tooling/backend_interface/src/smart_contract.rs +++ b/noir/noir-repo/tooling/backend_interface/src/smart_contract.rs @@ -17,7 +17,6 @@ impl Backend { // Create a temporary file for the circuit let bytecode_path = temp_directory_path.join("program").with_extension("bytecode"); let serialized_program = Program::serialize_program(program); - // let serialized_program = Circuit::serialize_circuit(&program.functions[0]); write_to_file(&serialized_program, &bytecode_path); // Create the verification key and write it to the specified path From a4d7ace9e24ef9b0a349cae37ff4b6e902e941fa Mon Sep 17 00:00:00 2001 From: vezenovm Date: Wed, 13 Mar 2024 18:13:21 +0000 Subject: [PATCH 070/139] clippy --- noir/noir-repo/tooling/backend_interface/src/proof_system.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noir/noir-repo/tooling/backend_interface/src/proof_system.rs b/noir/noir-repo/tooling/backend_interface/src/proof_system.rs index c3c138095ee7..211708aa846c 100644 --- a/noir/noir-repo/tooling/backend_interface/src/proof_system.rs +++ b/noir/noir-repo/tooling/backend_interface/src/proof_system.rs @@ -3,7 +3,7 @@ use std::io::Write; use std::path::Path; use acvm::acir::{ - circuit::{Circuit, ExpressionWidth, Program}, + circuit::{ExpressionWidth, Program}, native_types::WitnessMap, }; use acvm::FieldElement; From accc62abba8d26de9b154573e4281b9634649dde Mon Sep 17 00:00:00 2001 From: vezenovm Date: Wed, 13 Mar 2024 18:55:16 +0000 Subject: [PATCH 071/139] empty From c9d5fa671794dc9b27e13a3bf9be4c70dc7b1bce Mon Sep 17 00:00:00 2001 From: vezenovm Date: Wed, 13 Mar 2024 19:30:44 +0000 Subject: [PATCH 072/139] empty From c786c7d01f072e4bd5bccc0ff011bf980537e7c7 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Wed, 13 Mar 2024 19:41:41 +0000 Subject: [PATCH 073/139] build all bb in config before noir-packages --- .circleci/config.yml | 232 +++++++++++++++++++++---------------------- 1 file changed, 116 insertions(+), 116 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 71afe37a7f1c..024745701485 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -105,19 +105,19 @@ jobs: command: cond_spot_run_build barretenberg-wasm-linux-clang 128 aztec_manifest_key: barretenberg-wasm-linux-clang - bb-js: - machine: - image: default - resource_class: large + barretenberg-x86_64-linux-gcc: + docker: + - image: aztecprotocol/alpine-build-image + resource_class: small steps: - *checkout - *setup_env - run: - name: "Build and test" - command: build bb.js - aztec_manifest_key: bb.js + name: "Build" + command: cond_spot_run_build barretenberg-x86_64-linux-gcc 128 + aztec_manifest_key: barretenberg-x86_64-linux-gcc - bb-js-tests: + barretenberg-x86_64-linux-clang: docker: - image: aztecprotocol/alpine-build-image resource_class: small @@ -125,12 +125,11 @@ jobs: - *checkout - *setup_env - run: - name: "Build and test" - command: cond_spot_run_test bb.js 32 ./scripts/run_tests - aztec_manifest_key: bb.js - - # Noir - noir-x86_64: + name: "Build" + command: cond_spot_run_build barretenberg-x86_64-linux-clang 128 + aztec_manifest_key: barretenberg-x86_64-linux-clang + + barretenberg-x86_64-linux-clang-fuzzing: docker: - image: aztecprotocol/alpine-build-image resource_class: small @@ -139,10 +138,10 @@ jobs: - *setup_env - run: name: "Build" - command: cond_spot_run_build noir 32 - aztec_manifest_key: noir + command: cond_spot_run_build barretenberg-x86_64-linux-clang-fuzzing 128 + aztec_manifest_key: barretenberg-x86_64-linux-clang-fuzzing - noir-arm64: + barretenberg-x86_64-linux-clang-assert: docker: - image: aztecprotocol/alpine-build-image resource_class: small @@ -151,22 +150,38 @@ jobs: - *setup_env - run: name: "Build" - command: cond_spot_run_build noir 32 arm64 - aztec_manifest_key: noir + command: cond_spot_run_build barretenberg-x86_64-linux-clang-assert 128 + aztec_manifest_key: barretenberg-x86_64-linux-clang-assert - noir-ecr-manifest: + barretenberg-x86_64-linux-clang-sol: + docker: + - image: aztecprotocol/alpine-build-image + resource_class: small + steps: + - *checkout + - *setup_env + - run: + name: "Build" + command: cond_spot_run_build barretenberg-x86_64-linux-clang-sol 32 + aztec_manifest_key: barretenberg-x86_64-linux-clang-sol + + barretenberg-docs: machine: image: default - resource_class: medium + resource_class: large steps: - *checkout - *setup_env - run: - name: "Create ECR manifest" - command: create_ecr_manifest noir x86_64,arm64 - aztec_manifest_key: noir + name: "Build barretenberg docs" + command: build barretenberg-docs + aztec_manifest_key: barretenberg-docs + - run: + name: "Deploy barretenberg docs" + command: | + barretenberg/cpp/scripts/ci/upload_doxygen_to_s3.sh - noir-tests: + barretenberg-stdlib-tests: docker: - image: aztecprotocol/alpine-build-image resource_class: small @@ -174,11 +189,11 @@ jobs: - *checkout - *setup_env - run: - name: "Build" - command: cond_spot_run_build noir-tests 32 - aztec_manifest_key: noir-tests + name: "Test" + command: cond_spot_run_test barretenberg-x86_64-linux-clang-assert 32 ./scripts/run_tests 1 stdlib-tests + aztec_manifest_key: barretenberg-x86_64-linux-clang-assert - noir-packages: + barretenberg-dsl-tests: docker: - image: aztecprotocol/alpine-build-image resource_class: small @@ -186,11 +201,11 @@ jobs: - *checkout - *setup_env - run: - name: "Build" - command: cond_spot_run_build noir-packages 32 - aztec_manifest_key: noir-packages + name: "Test" + command: cond_spot_run_test barretenberg-x86_64-linux-clang-assert 32 ./scripts/run_tests 1 dsl_tests + aztec_manifest_key: barretenberg-x86_64-linux-clang-assert - noir-packages-tests: + barretenberg-tests: docker: - image: aztecprotocol/alpine-build-image resource_class: small @@ -198,23 +213,29 @@ jobs: - *checkout - *setup_env - run: - name: "Build" - command: cond_spot_run_build noir-packages-tests 32 - aztec_manifest_key: noir-packages-tests + name: "Test" + command: cond_spot_run_test barretenberg-x86_64-linux-clang-assert 32 ./scripts/bb-tests.sh + aztec_manifest_key: barretenberg-x86_64-linux-clang-assert - noir-compile-acir-tests: - docker: - - image: aztecprotocol/alpine-build-image - resource_class: small + barretenberg-bench: + machine: + # NOTE: we usually use alpine build image when making spot images, but + # we are not able to upload to S3 with it + image: default + resource_class: medium steps: - *checkout - *setup_env - run: - name: "Build" - command: cond_spot_run_build noir-compile-acir-tests 32 - aztec_manifest_key: noir-compile-acir-tests + name: "Benchmark" + command: cond_spot_run_build barretenberg-bench 32 + aztec_manifest_key: barretenberg-bench + - run: + name: "Upload" + command: | + barretenberg/cpp/scripts/ci/upload_benchmarks_to_s3.sh - avm-transpiler: + barretenberg-proof-system-tests: docker: - image: aztecprotocol/alpine-build-image resource_class: small @@ -222,11 +243,11 @@ jobs: - *checkout - *setup_env - run: - name: "Build" - command: cond_spot_run_build avm-transpiler 32 - aztec_manifest_key: avm-transpiler + name: "Test" + command: cond_spot_run_test barretenberg-x86_64-linux-clang-assert 32 ./scripts/run_tests 1 proof_system_tests + aztec_manifest_key: barretenberg-x86_64-linux-clang-assert - barretenberg-x86_64-linux-gcc: + barretenberg-stdlib-recursion-ultra-tests: docker: - image: aztecprotocol/alpine-build-image resource_class: small @@ -234,23 +255,23 @@ jobs: - *checkout - *setup_env - run: - name: "Build" - command: cond_spot_run_build barretenberg-x86_64-linux-gcc 128 - aztec_manifest_key: barretenberg-x86_64-linux-gcc + name: "Test" + command: cond_spot_run_test barretenberg-x86_64-linux-clang-assert 32 ./scripts/run_tests 3 stdlib_recursion_tests --gtest_filter=-*turbo* + aztec_manifest_key: barretenberg-x86_64-linux-clang-assert - barretenberg-x86_64-linux-clang: - docker: - - image: aztecprotocol/alpine-build-image - resource_class: small + bb-js: + machine: + image: default + resource_class: large steps: - *checkout - *setup_env - run: - name: "Build" - command: cond_spot_run_build barretenberg-x86_64-linux-clang 128 - aztec_manifest_key: barretenberg-x86_64-linux-clang + name: "Build and test" + command: build bb.js + aztec_manifest_key: bb.js - barretenberg-x86_64-linux-clang-fuzzing: + bb-js-tests: docker: - image: aztecprotocol/alpine-build-image resource_class: small @@ -258,11 +279,12 @@ jobs: - *checkout - *setup_env - run: - name: "Build" - command: cond_spot_run_build barretenberg-x86_64-linux-clang-fuzzing 128 - aztec_manifest_key: barretenberg-x86_64-linux-clang-fuzzing - - barretenberg-x86_64-linux-clang-assert: + name: "Build and test" + command: cond_spot_run_test bb.js 32 ./scripts/run_tests + aztec_manifest_key: bb.js + + # Noir + noir-x86_64: docker: - image: aztecprotocol/alpine-build-image resource_class: small @@ -271,10 +293,10 @@ jobs: - *setup_env - run: name: "Build" - command: cond_spot_run_build barretenberg-x86_64-linux-clang-assert 128 - aztec_manifest_key: barretenberg-x86_64-linux-clang-assert + command: cond_spot_run_build noir 32 + aztec_manifest_key: noir - barretenberg-x86_64-linux-clang-sol: + noir-arm64: docker: - image: aztecprotocol/alpine-build-image resource_class: small @@ -283,26 +305,22 @@ jobs: - *setup_env - run: name: "Build" - command: cond_spot_run_build barretenberg-x86_64-linux-clang-sol 32 - aztec_manifest_key: barretenberg-x86_64-linux-clang-sol + command: cond_spot_run_build noir 32 arm64 + aztec_manifest_key: noir - barretenberg-docs: + noir-ecr-manifest: machine: image: default - resource_class: large + resource_class: medium steps: - *checkout - *setup_env - run: - name: "Build barretenberg docs" - command: build barretenberg-docs - aztec_manifest_key: barretenberg-docs - - run: - name: "Deploy barretenberg docs" - command: | - barretenberg/cpp/scripts/ci/upload_doxygen_to_s3.sh + name: "Create ECR manifest" + command: create_ecr_manifest noir x86_64,arm64 + aztec_manifest_key: noir - barretenberg-stdlib-tests: + noir-tests: docker: - image: aztecprotocol/alpine-build-image resource_class: small @@ -310,11 +328,11 @@ jobs: - *checkout - *setup_env - run: - name: "Test" - command: cond_spot_run_test barretenberg-x86_64-linux-clang-assert 32 ./scripts/run_tests 1 stdlib-tests - aztec_manifest_key: barretenberg-x86_64-linux-clang-assert + name: "Build" + command: cond_spot_run_build noir-tests 32 + aztec_manifest_key: noir-tests - barretenberg-dsl-tests: + noir-packages: docker: - image: aztecprotocol/alpine-build-image resource_class: small @@ -322,11 +340,11 @@ jobs: - *checkout - *setup_env - run: - name: "Test" - command: cond_spot_run_test barretenberg-x86_64-linux-clang-assert 32 ./scripts/run_tests 1 dsl_tests - aztec_manifest_key: barretenberg-x86_64-linux-clang-assert + name: "Build" + command: cond_spot_run_build noir-packages 32 + aztec_manifest_key: noir-packages - barretenberg-tests: + noir-packages-tests: docker: - image: aztecprotocol/alpine-build-image resource_class: small @@ -334,29 +352,11 @@ jobs: - *checkout - *setup_env - run: - name: "Test" - command: cond_spot_run_test barretenberg-x86_64-linux-clang-assert 32 ./scripts/bb-tests.sh - aztec_manifest_key: barretenberg-x86_64-linux-clang-assert - - barretenberg-bench: - machine: - # NOTE: we usually use alpine build image when making spot images, but - # we are not able to upload to S3 with it - image: default - resource_class: medium - steps: - - *checkout - - *setup_env - - run: - name: "Benchmark" - command: cond_spot_run_build barretenberg-bench 32 - aztec_manifest_key: barretenberg-bench - - run: - name: "Upload" - command: | - barretenberg/cpp/scripts/ci/upload_benchmarks_to_s3.sh + name: "Build" + command: cond_spot_run_build noir-packages-tests 32 + aztec_manifest_key: noir-packages-tests - barretenberg-proof-system-tests: + noir-compile-acir-tests: docker: - image: aztecprotocol/alpine-build-image resource_class: small @@ -364,11 +364,11 @@ jobs: - *checkout - *setup_env - run: - name: "Test" - command: cond_spot_run_test barretenberg-x86_64-linux-clang-assert 32 ./scripts/run_tests 1 proof_system_tests - aztec_manifest_key: barretenberg-x86_64-linux-clang-assert + name: "Build" + command: cond_spot_run_build noir-compile-acir-tests 32 + aztec_manifest_key: noir-compile-acir-tests - barretenberg-stdlib-recursion-ultra-tests: + avm-transpiler: docker: - image: aztecprotocol/alpine-build-image resource_class: small @@ -376,9 +376,9 @@ jobs: - *checkout - *setup_env - run: - name: "Test" - command: cond_spot_run_test barretenberg-x86_64-linux-clang-assert 32 ./scripts/run_tests 3 stdlib_recursion_tests --gtest_filter=-*turbo* - aztec_manifest_key: barretenberg-x86_64-linux-clang-assert + name: "Build" + command: cond_spot_run_build avm-transpiler 32 + aztec_manifest_key: avm-transpiler barretenberg-acir-tests-bb: docker: From bc13ebe85b0605c544c93cd56a31190ae5475e29 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Wed, 13 Mar 2024 19:42:24 +0000 Subject: [PATCH 074/139] fix yml indent --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 024745701485..e1ac8fdf4326 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -105,7 +105,7 @@ jobs: command: cond_spot_run_build barretenberg-wasm-linux-clang 128 aztec_manifest_key: barretenberg-wasm-linux-clang - barretenberg-x86_64-linux-gcc: + barretenberg-x86_64-linux-gcc: docker: - image: aztecprotocol/alpine-build-image resource_class: small From 1e59a4ca3e387b0f0b69d6d1d790b5dbe4ab9a75 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Wed, 13 Mar 2024 20:13:52 +0000 Subject: [PATCH 075/139] update snapshots in yarn project --- .../contract/__snapshots__/contract_class.test.ts.snap | 10 +++++----- .../src/gas-token/__snapshots__/index.test.ts.snap | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/yarn-project/circuits.js/src/contract/__snapshots__/contract_class.test.ts.snap b/yarn-project/circuits.js/src/contract/__snapshots__/contract_class.test.ts.snap index 0c8262f95ee6..117c25a7cb84 100644 --- a/yarn-project/circuits.js/src/contract/__snapshots__/contract_class.test.ts.snap +++ b/yarn-project/circuits.js/src/contract/__snapshots__/contract_class.test.ts.snap @@ -9,18 +9,18 @@ exports[`ContractClass creates a contract class from a contract compilation arti "selector": { "value": 2381782501 }, - "bytecode": "0x1f8b08000000000000ffed9d0774154796f75b4280f0d3b3088e045b3860c004e9492449c023679325030e801019e3210c382272c618b0c946e0999d4db339cfe69c739cd9303bb333bb3b3b73ce37bb5ffecef1f9aafad51dfd55543ff4e4aec77dd2ed734aaffaaabaefaffe7dab3a55777f270882a22033f550e9e9e0ee89fe9f36bf959f6eaa8a715d953e398b0a84b3b840387b140867498170f62c10ce5e05c2d9bb40384b0b84b34f8c9c9aad38683fc5cdfb80075de3664c1498a66505a069b2c0347db000342d0f0aa38fea5b209cfd0a84b37f81700e2810ce870a84f3e102e17ca440381f2d10cec70a84f3f102e11c58209c830a84737081700e2910ce270a84f3c902e1ac2810cea105c2f95481703e5d209ccf1408e7b331728e00ce61e6f739f33bdcfc529991e6f779f33bcafc8e36752c31f363541aabd954aab2fe9752a95aa51a95c659ff1bafd2049526aa34c9fcafc2fcaf56a53a95ea559aacd21495a61a1da6a9345da5192acd5469964ab3559aa3d25c95e6a9345fa5052a2d5469914a2fa8b458a5252a2d5569994acb555aa1d24a951a546a54e9459556592cab555aa3d24b2abdacd22b2abdaad25a95d6a9b45ea5269536a8d4acd2469536a9b459a52d2a6d55699b4adb55daa1d26b2aed54e975953ea3d22e9576abb447a5bd2a7d56a57d2aed57e90d4bb337557a4ba5b7557ac7e27c57a5032ab5a87450a5432a1d56e9884a47553aa6d271954ea87452a5532a9d56e98c4a67553aa7d27b2a9d57e97d952ea87451a54b2a7da0d2872a5d56e98a4a5755baa6d275956ea874d3b05043f848a55b2ab5aa745ba53b2a7dacd2e754fabc4adfa7d21754fa7e957e40a51f54e98754fa6195bea8d28fa8f4a32afd984a3faed24fa8f4932afd944a3fadd2cfa8f4b32afd9c4a3fafd22fa8f425957e51a55f52e99755fa15957e55a55f53e9d755fa0d957e53a5df52e9b755fa1d957e57a5df53e9f755fa0395fe50a53fb234ff6395fe44a53f55e9cfccffe83ad89fabf41726ff97e6f7afccef5f9bdfbfb196f95b95feceb27d59a5af58b6bf57e91f4cfe1fcdef3f99dfaf9adf7f36bf5f33bf5f37bfff627ebf617ebf697effd5fcfe9bf9fd77f3fb2df3fb1fe6f7dbe6f73b2add1c9cc997066d533a88a94faa696ed6f75048ec6141fb496bd1c3fc8f7e2b8cbdc4ccd32f69d7d3ccf7b4ecbdcc7c2f6b3da566bed4b2f733f3fd2cfb00333fc0b23f6ce61fb6ec8f9af947c19e08e05aaab16b5b0f632a021bc56131d87a06ed35d1b65eb43ab0f50eda6ba16db41d7b81ad8fb1f506db03c6560ab684b1f521cd542a33b67410574c54aed3eb4dc6bd5e737fe9c1f8799bf47acb3df1f68d9fb759afb79f075e1d1ffdcdbafa42dc0c30b67e607bc8d8fa83ed61631b00b6478ced21b03d6a6c0f83ed31637b046c8f1bdba3601b686c8f816d90b13d0e36d3ed0503c136c4d80681ed09631b0cb6278d6d08d82a8ced09b00d35b627c1f694b155808dc6ae0c05db33c6f614d89e35b6a7c1467dea3360a363be678d4df7133d8b601963a73e2a5c86fa61b00da73e186c23a8ff05db48ea7bc1f63cf826db28e857c836dad8a88fd2ff9b68f2e920ae36910adbc4a4b8d7abd6acd75b17ff7ac3fb71f5419bae69f03309b49a6cf2318ef9a942df4526911fb297407e2e94a572a407ed67885def4f6a4d7e7296e5265acb25a14cada3fee920defad7593c7516734fc8fb89d9ea94c46c87a79c63b601cadab147c73c5d316617008787981d2f31dbe129e798dd0065edd8a3e3deae18b3ab80c343ccaef313b3a94a89d9ccf5af2070c71e9dfb74c598dd041cf1c7ec3889d98e4f39c76c0b94b5638fce7fbb62ccee058ef86376c23a3936e8f09473cc9e83b276ecd1b598ae18b38781c343cc364b3fdbe129e798bd0165edd8a3eb825d3166df078ef8637692a798ad96980d32f73283c01d7b748dba2bc6ec2de0883f669be4fa6cc7a79c63f6e7a0ac1d7b74bfa42bc6ec178123fe98dde0ebfa6c4a623633862308dcb147f7eeba62cc7ec9e4f5bdb1bf34f7c69e00db5f19db9360fb6b187b40b6bf31b6a1502f0f6d60a2b4810e4f39b781bf85b2762c3f65f25db10dfc11707888d97512b31d9e728ed96f42593bf6684c43578cd9af008787986d9298edf09473ccfe77286bc71e8dafe98a314be343f5f1c23f9ae385e160fb27631b01b6af1adb48b0fdb3b13d0fb6af19db28b07dddd84683ed5f8c6d0cd8be616c63c1f64d63ab04dbbf1a5b15d8fecdd85260fb7763ab06dbb78cad066cff616ce3c0f66d631b0fb6ef18db0463d3f7b1684cd5ef1a5b2970a583f8b66d0234a0a9c89a4f43beca2f4f651278d05775fcbeaa75dd5341c7eb5e0d3c351eea9e001f1de1a9019e71f1f384e349c7c7bfde701ba72c4d13e02b05f59ae0a15e45e08bd64df3e42f09366cd3131c8cb1ef9fd57eb4087cd1ba697e2230920dfb18ea73a9fde8be7948511baf87b614ee9fd15f1a38c85f09941937b8adec50c35606ffc7fe769c65f31497615c902f5a37cd93bf32a8cfb8fc33a63aca586331faea238ac017addbf65d06f94abffa64e519cfc477ad27df769f469ad7e6c1f744cb77b5e51bfb4e9ab2eddb2602b387f394aafb719e82c70f1cce536616b595b5cf37a81fcef53c6582b51cc7f39449b02ff4d01ec218a8b53868be1ab4ab8bd0ae16b4a332cf8176befaf149160fcd8f031eeabfb13fabcc334f2503df780c4bdb0dcfa5f038c0d7f6aab41869deb5bd2602a3eb58c5c3f94cd663951a60241b5ec74979d22c6abba698f8f6102b617f443ee8d89cda2ff92b81320b7ab4955d0b7da58f18c178a4a9a3e7bcf16fa754780e5e93030f6e3b0fe755559ee2b112afdf7c12c41b6b76bf54636915758dc7575f9eb278689efc09b3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300b337f66bc9f84e3b6a8dc38268cf6f8375fd7f9c377ec9975e13da0ef7a1d0f96aac4b130340e628455e71228535edcc6f63f603c983d96286a5bfa181b9b6d5b923f1c0f968f7b88d5168fedbbcca10fde9746cd7c8d81b2fb0c9ac7f169a45f25f0f86a8f55168fed1bfb8c1453cda2fa595f630ba2e2cc359eb02236dfa9265ff775f5fbccf43b41edfdd7384bd3f05da3964df7492ff468abb78ffbbcb9de77c6fd06e5e3bc8f9b041ef4157f3f9b6a373ea13868bfafc058f735568bda158d8da8b57c97409921c56ddba60efe9f0eeede3760195a37cd8f8065ebac7597fbab6fd67128b5c04df95e56ddc6033795790af6dd7f66f29ef681a95c9f91c07d72fcfb97cc7891540e3cb8bff371cce2693f5a89f118f778117b1ca4eb7899cae018520fe377b3ee8bc99f300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb330f367d63cf63d74bcf75bcd84314f636cc2fb19f42e36bc2ff693c56d7e7ddf03a47b4e23ad3ae333ca013ca3fcb3860dc73ee07ba55cdbd2d7bdb5a86d49feb88d7d2873e8a335ab736856ef89d1ee3368be1e1849bf3ae0f1d51ea3dedde1ea332a996a16d5cffa18bb902dce5ce3142a62f39d192fe2e3be2e8d17b1f75ff67b8d709c04d9f03e78d4fbc2aa2cdbfdee035ce3da288fef5c88bfdf4cb5bb076c8f15247f384ee22b465b1a27117f3f90aaf4b98fa0364a6342528eba5299af16b795fd9ac9e358a16a58d7771dffa729db9804ec53a7c45fe770fb4e35eba2ed3bc5e13b0dac31f9ae42df45d6bac95e02f9ff567c3703e9415a13bb6e23f81eaba8e56aace5925066b2a3fee998eb3fc5e2c16dac271d3bdf8038fb2e1cebf9ea93264768340234a2329edf03eb1ce76b8f55c67eb4b7558696c5f75bfe1fe8a3a2c6a4bbf601be8e17a2f60178bc60ef173a3276bcbb8f07ec63ce437c8c07a4759707edc7e405d6fa47c2fa89ab7710bd6ff9deb938acdfe798f57bbdf7ca75ee47bc38de90caf48773bf99269fcbb9dffd3a8f779dfbe1725175c77e21ee7d23c623b2e0fb22a9cc602b1eeb22b8273a967d326259d2ca7ef7219e97e23142fcef8dccf43753acba509b9a0c75a132cf5aed26fe63a6ccf1a7af7764d2b10ef541558eba529991d0d646997c02b613ee17ea1cffa729dbf127e9a7eb3c2dfe3a87db77ba59176ddf690edf33803526df55e89b8e3fc90fd94b205f0bfb132a477a90d6c45e069cc86e2f576b2d9784326947fdd331d77f9ac533cd62d6b13316e2ac0e9eb5f0d557a703b7462341a3eff9039bebbdc6ae7d8cafe7d1a2f63155c068f79bb89fcce7b372f6f55bd7f10995c163682a330ffad984a3ac7d5d9a968b737c3a3e0f84c785f83c90af73a464d05ecfa4c5e1d377b9e5bb3c8fbefb59befbe5d1b7682e9a73d29cd3377f70df520c8c3ece1bf1fa484718f17d04b45c0f60f4f5cc662a07c66a60c4fd1d317a78bf725567bf2984c73a3d81d1c7f3c6b95eafc6f79be33b0688d1c733dab9bea71a9fdba6e57a03a38fef1ae137943ac2e8fad65129fc7af8ae515567bf0382df3aea038c3ebe0d9208da7fcfe45e8c938091967b00187ddc474a04edafabdd8b11ef57d27209cf8cd9f6ed9ec7fea472bd06918f710551c71ae8dbc3f5ff148e4de88816f57e79b21efba06f0fd7bf422dea838e6b81f7e73cdc1b0ddbf1e41c78f01e222dd71f18a77a629c9203e35460a4e5060063da13e3d41c18d3c048cb3d048c1eae43868ce91c18f17a1dd91f06c6e99e18a7e5c0381d1869b94780d1c735c504f8ed08e30c60a4e51e05c6999e1867e4c038131869b9c780719627c6993930ce02465aee71609ced8971560e8cb38191961b088c733c31cece81710e30d272838071ae27c6393930ce05465a6e3030cef3c4383707c679c048cb0d01c6f99e18e7e5c0381f1869b92780718127c6f939302e00465aee49605ce88971410e8c0b819196ab2800c6a105c0f85401303e5d008ccf1400e3b305c0585a008ccf03e3a2f819c3f3d48539302e029e17e2e709355b9403cf0b7e79c2f7132e72f85a1cbfaf54ae755f0c3c4be2e709b7c5e21c78882109cbbde09731d55946cdb3347e9e50b32539f02c05cd963834f3c098ea2ca3e659163f4fa8d9d21c789681664b1d9a79604c759651f32c8f9f27d46c590e3ccb41b3650ecd3c30a63acba87956c4cf136ab63c079e15a0d97287661e18539d65d43c2be3e709355b9103cf4ad06c8543330f8ca9ce326a9e86f87942cd56e6c0d3009aad7468e68131d55946cdd3183f4fa859430e3c8da0598343330f8ca9ce326a9e17e3e709356bcc81e745d0acd1a1192746e489fb7de38d0e5fab18d49d1890b14f01303e50008c3806c147ff956d0c42a35f7d529dd5c7d7f6ca3606017daff6a4c5aaa0e35aacf6cb93750c02fa5ee3498bd541c7b558033c2f79d022013e3ac2430c4958ae7f01300e2800c6870a80f1e102607ca400181f2d00c6c70a80f1f102601c58008c830a80717001300e2900c6270a80f1c902607cd13363b6f39797bab8efa87395aeee3beabca4abfb96389738ef0ebe25ce25cebb836f897389f3eee05be25ce2bc3bf896389738ef0ebe25ce25cebb836f897389734ebe5ff6e03b013e68ca768d9f1892b0dc8bc2d8a51991a7223e9e4aac3bfa7a8541dd5f71f01479aa3bfa7a9541dd89a1d0185f2e00c6170b805174cc8c41ec0ca3e659eb89e7d51c78d602cf3a4f3c6b73e059073cebe3e709636a5d0e3cc49084e55e2c00c6970b805174141d39318a8edd47476114466114c6fbc158087db8ec6732e72e9d61d43c4df1f3849aadcf81a70934a3e55ef0cb98ea2ca3e6d9103f4fa859530e3c1b40b32687661e18539d65d43ccdf1f3849a6dc881a71934dbe0d0cc0363aab38c9a6763fc3ca166cd39f06c04cd9a1d9a79604c759651f36c8a9f27d46c630e3c9b40b38d0ecd3c30a63acba87936c7cf136ab629079ecda0d92687661e18539d65d43c5be2e70935db9c03cf16d06cb343330f8ca9ce326a9eadf1f3849a6dc981672b68b6c5a19907c654671935cfb6f87942cdb6e6c0b30d34dbead08c2be38b05c0f87201307ad631d55946cdb3dd13cfb61c78b603cf0e4f3cdb73e0d9013cafc5cf13c6d48e1c78882109cbbd58008c2f1700a3e8283a7262141dbb8f8ec2288cc2981be32b05c028db5a18b9327a38bfcafa7cca8e2eee3beaf994aeee3beaf994aeee5be25ce2bc3bf896389738ef0ebe25ce25cebb836f897389f3eee05be25ce2bc3bf896389738ef0ebe25ce25cebb836f897389f3eee05be25ce2bc3bf896389738ef0ebe25ce25cebb836f897389f3eee05be25ce2bc3bf896389738ef0ebe25ce25cebb836f897389f3eee05be25ce2bc3bf896389738ef0ebe25ce25ce39f9de19bfef54aecfb0ee041e1fcfd47aaa67a55eefeb665d9fc4a89fd6ea3396563b2cad9250e675d0ef331ef42b02bfb46e9a277fb9320f63c0ecc977ea41b58e3e507ff2f1b2a587f6bfcb53dda3fafa5d5ddc77545fdfd57d47f5f55dddb7c4b9c47977f02d712e71de1d7c4b9c4b9c73f18df992a0edb89ddeafa4d7b1dbe47b9a792aff0a2c4765e6f5cefc9607d2867cf8963624fb8aeee05be25ce2bc3bf896389738ef0ebe25cef9c539c6c3bc3cf004164f9085271ff70f72e119c38c6706339ec9cc782630e3a962c6339219cf66663ccdcc78d633e3e9c18c673e339e99cc785e62c6338519cf44663c29663c5b99f1ac64c6b38c19cf68663c8b99f1bcca8c6716339ea9cc78d630e399c48ca79a19cf36663c5b98f10c63c6b391194f13339e05cc78d632e399cd8c27cd8ca79619cf70663c35cc78b633e3798e194f23339e06663ccb99f12c61c653c68c27c98c6721339e39cc78a631e3a963c6338e19cf2a663c9b98f16c60c6b38e19cf08663c0f32e32967c6339619cf5c663cd399f1d433e319cf8ca79219cf6a663c2b98f12c65c6d397194f3f663c8b98f18c62c653c4802711dcfd8e9304fc7f27d88aad65f563616f0e6efbff1e632f8665f69a7c0fc7baf7808d9e35dbeb581675da0375499b7ce5a79b429dd0571ae6c95f1970ec65c2338a19cf22663cfd98f1f465c6b39419cf0a663cab99f15432e319cf8ca79e19cf74663c7399f18c65c653ce8ce741663c2398f1ac63c6b38119cf26663cab98f18c63c653c78c671a339e39cc781632e34932e32963c6b38419cf72663c0dcc781a99f13cc78c673b339e1a663cc399f1d432e34933e399cd8c672d339e05cc789a98f16c64c6338c19cf16663cdb98f15433e399c48c670d339ea9cc786631e3799519cf62663ca399f12c63c6b39219cf56663c29663c1399f14c61c6f312339e99cc78e633e3e9c18c673d339e66663c9b99f18c64c653c58c6702339ec9cc786630e319c38c6727339e790e1e0fdfcf0b7968bc2aad9be67732f1ed613b84df0dfcaca73aed33ebea65d64bfce4af04ca2cea93f9d5e3757059e2b2c71763acee038d767baa4bd43b99777771df51ef64eeeabea3dec9dcd57d4b9c4b9c73f2bd2f7edf297c3685a6226b3e0d79dcbff878a6c7533ddbeddbe3fe26f07e4babdd96564928f359d06fbf07fd5cc70b344ffe72651ec68019e3a22288372ede88bf4edffbd630e9fa86a52fd6eb4d4f9a46ed43deece2bea3f6215ddd77d43ea4abfb96389738ef0ebe25ce25cebb836f897389734ebedf32f918cf1b2bd187bef64be7036f81df774cbe2846bf7a5d6f9b75d1b79189e31de0a1323f02d7a2a5cd4b9b8fcbb7ecdb24cebb836fce716ee7e91e22beb7dbd73ddea858ccc7fde5fbe93b2a16bbbaefa858eceabe25ce25ce39f97e377edfe13dc49d41fb29db3dc47781e76d0f5a78aa6778ee74c0aad34eab4e492883e772073cd4b308fcd2ba69fe006c874263d63c34961ddfcf48e55e62c248b6b7fdf284edeba5a0fd94ad7d1d001e0feda0ca533dc3f6d562d5e92587ee540663b5c5433d5d6d87e65b603bb41418b3e6a167e7883501e55e65c248b677fdf284edebd5a0fd94ad7db5008f8ffec7533dc3f675d0aad3ab0edda90cc6ea410ff574b51d9a277f85c8ac79d69a3cb126a0dc5a268c643be097a7260175a6295bfb3a083c2d1ef4f154cfb07d1db2eab436b85b772a83b17ac8433d5d6d87e60fc17610666176316b9e7526bfd6fc26a0dc3a268c646bf1ca535399803ad394ad1f3b043c3efa794fba87fdd861ab4eeb1cba53198cd5c31eeae96a3b347f18b6432eccfb0a905974169da3984567d1398a5974169da3984567d1398a5974169da3984567d1398a5974169da3984567d1398a5974169da3984567d1398a5974169da3984567d1398a5974169da3984567d1398a5974169da3984567d1398a5974169da3984567d1398a5974169da3984567d1398a5974ee1cb3e6596ff2c49a8072eb993092eda05f9ef0f99df541fba9c89a4f43fe30f01cf2a08fa77a86e3de8f58755aefd09dca60fb3ae2a19eaeb643f347603be4c2bcaf009945e7ce316b9e269327d604946b62c248b6437e79c27eac29683f65ebc78e008f8f7ede533dc37eeca855a72687ee5406dbd7510ff574b51d9a3f0adb419885d9c5ac7936983cb126a0dc06268c643bec9527153e87b821683f65ebc78e028f8f7ede93ee613f76ccaad30687ee540663f598877abada0ecd1f83ed900bf3be0264169d45e72866d159748e62169d45e72866d159748e62169d45e72866d159748e62169d45e72866d159748e62169d45e72866d1b9fbe8ac799a4d9e581350ae990923d98e78e5a90eef3b3407eda76cf71d8e018f8ffb329e740fef3b1cb7ead4ecd09dca60fb3aeea19eaeb643f3c7613b7475e67d05c82cb1911f66890d618e6296d810e62866890d618e6296d810e62866890d618e6296d810e62866890d618e6296d810e62866890d618e6296d810e62866890d618e6296d810e62866890d618e6296d810e628660eb1a179369a3cb126a0dc46268c643bea97277cefc1c6a0fd946ddcce71e039e6411f4ff50cc7ed9cb0eab4d1a13b95c1f675c2433d5d6d87e64fc07610666176316b9e4d264fac0928b7890923d98ef9e509fbb14d41fb295b3f7602787cf4f39eea19f66327ad3a6d72e84e6530564f7aa8a7abedd0fc49d80ec22ccc2e66cdb3d9e4893501e536336124db71bf3c613fb639683f65ebc74e028f8f7ede533dc37eec9455a7cd0edda90cc6ea290ff574b51d9a3f05db419885d9c5ac79b6983cb126a0dc16268c643be1972795803ad394ad1f3b053c3efa794ff50cfbb1d3569db63874a73218aba73dd4d3d57668fe346c874263d63c5b4d9e5813506e2b1346b29df4cb13b6afad41fb295bfb3a0d3c3efa1f4ff50cdbd719ab4e5b1dba53198cd5331eeae96a3b347f06b643a1316b9e6d264fac0928b78d0923d94ef9e509dbd7b6a0fd94ad7d9d011e1ffd8fa77a86edebac55a76d0edda90cc6ea590ff574b51d9a3f0bdba1d09835cf769327d60494dbce84916ca73df324a0ce34656b5f6781c747ffe3a99e61fb3a67d569bb43772af326d4f39c877abada0ecd9f031e9ae6018fafb80c2c9ec0a10f4d6398f1cc60c6339919cf04663c55cc784632e3e9c18c673e339e99cc78a630e399c88c27c58c6725339e65cc784633e3799319cf62663cb398f14c65c6b38619cf24663cd5cc788631e359c08c6736339e34339e5a663cc399f1d430e36964c6d3c08c6739339e25cc78ca98f12499f12c64c6338719cf34663c75cc78c631e359c58c6704339e0799f19433e319cb8c673f339eb9cc78a633e3a967c6339e194f25339ed5cc785630e359ca8ca72f339e7ecc781631e319c58ca788014f22b87b2c4d02febf1f6c34e6633bd8de33f933602b76f8a07bc5e7c05662f2b48ede2a1d1d7cf7ba51275fe35cd0571ae6c95f1970bcc7846714339e45cc78fa31e3e9cb8c6729339e15cc785633e3a964c6339e194f3d339ee9cc78e632e3d9cf8c672c339e72663c0f32e319c18c6715339e71cc78ea98f14c63c6338719cf42663c49663c65cc789630e359ce8ca781194f23339e1a663cc399f1d432e34933e399cd8c6701339e61cc78aa99f14c62c6b38619cf54663cb398f12c66c6f326339ed1cc789631e359c98c27c58c6722339e29cc786632e399cf8ca707339e91cc78aa98f14c60c6339919cf0c663c6398f1cc73f0ecf7c4633fe745f3fb19f8d6f3b5a08b9e12f07f7c0eec4d4f8cfb2d469a7f131891d7b766e5164fb9a5d9fdf4adeb4ff72a1e34bfb8bdf0b9070edbab3c0f9af5b378fa599add4fdf5a0bbaf74f636c707be138680edb0bc7697ae89f6b12168f9e8aacf934e4cf79d6c7533d2b71dce42731ae576b75ded26abfa55512ca9c05fdce7bd0af08fcd2ba699efc09b33047316b1eba97eb1acfbb900923d9f03d2aefc7cf5393b078f494ad7f7cdfb33e9eea19f6631702b7eeef83ee540663f582877a16815f5a37cd5f70f8ae08e2d5e26207b4b8e8e0b998672dc85faecc670b909983ce9a87c6ae136b02ca2d62c248b6f3c073297e9e9a84c5a3a76cfde325cffa78aa67d8277c10b875bf04ba53196c5f1f78a86711f8a575d3fc07b01d7261be5080cca273e79835cf629327d604945bcc84916c1781e7c3d8795295098b474fd9fab10f3debe3a79e997eec72e0d6fd43d09dca60fbbaeca19e45e097d64df397613b08b3300bb3300bb3300bb3300bb3300bb3300bb330eb32c22cccc22cccc22cccc2cc9759f3d0b3e7c49a80724b983092ed03e0b9123b4fe6be03f2e829db7d872b9ef5f153cfcc7d87ab815bf72ba03b95c158bdeaa19e45e097d64df357613b08b3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300b336f66cd43dfb020d604945bca84916c9781e75afc3c35098b474fd9ee3b5cf3ac8fa77a86f71dae076eddaf81ee540663f5ba877a16815f5a37cd5f87ed20ccc2ec62d63cf42e44624d40b9654c18c97615786ec4ce93b97f8a3c7acad68fddf0ac8f9f7a66fab19b815bf71ba03b95c158bde9a19e45e097d64df337613be4c27ca100994567d1398a5974169da3984567d1398a5974169da3984567d1398a5974169da3984567d1398a5974169da3984567d1398a5974ee3e3a6b1efa4627b126a0dc72268c64bb0e3c1fc5ce535d99b078f494edbec3479ef5f153cfcc7d875b815bf78f40772a83edeb96877a16815f5a37cddf82edd0d5992f1420b3c4467e98253684398a59624398a398253684398a59624398a398253684398a59624398a398253684398a59624398a398253684398a59624398a398253684398a59624398a398253684398a59624398a39839c486e65961f2c49a80722b983092ed26f0b4c6cf5393b078f4946ddc4eab677d3cd5331cb7733b70ebde0aba53196c5fb73dd4b308fcd2ba699efc09b33047316b9e95264fac0928b7920923d96e01cf9df87952098b474fd9fab13b9ef5f154cfb01ffb3870eb7e0774a73218ab1f7ba86711f8a575d3fcc7b01d0a8d59f334987cabf94d40b906268c64bb0d3c1ee22ee4495a3c347f87816f3ddf68f265e617b757233072d85ec93c68566ef1945b9add4fdfbafeab4cfe41f38bdb6b153072d85ee579d0ac9fc5d3cfd2ec7efad65aac36f9bee617b7d76a60e4b0bdfaf9e549252c1e3d653bdef818783e1f3f4f781ef7710e3c9f079ecfc5cf53e5a99e957abddf07ec71ad576bf5054bab8f2dad92500619bee041bf22f04beba679f227ccc21cc58c7d21b126a0dc1d268c64fb1cf0f8e83774dd479975d1fa7baaf450ff36bfadf1fbadc16b0bbdcc7a8983fc9540999707b5b13d66d8cae0ffb4dd747d6e59364fcfbc55b9aef3d23cf92b0bdce7fabeaea1b65a3cb6ef32873e5ab39b0ecd6e7862b49f69a5f91bc0e8baceebeb79d1a8ebcef8bce81d4b476e9ae173c01f018fafe3e2568ba7d5a1858f3697ebf1e5470e9e4fe2e3a9c4d8405f3e6215fbb68ed4ddd57662ac7b15dec3425f1eda40b89f1a6dd645ebd7fb82dafe5e35afc1fe81f653a3ad3a97409949b09f9a92653f551cdc7d5db8c2d8a90cfdff1363b7d75111dcdf6b4b6590af35bf18a36493fd6ffb7b98b5968edc34c376dd0a3cad9e78a2ae89913fdc86750ecdea1868866d211f7176c7e2b17d27419756a69a619ce17183affeec5ed7f2701bd63b34ab67a019c7feacded2919b66aefe0c755ce8e05ec8809b639fb2d0d2919b66ae3e05755ce4e05ec4809b63bb5e64e9c84db37bb5ebc50eeec50cb839b6ebc5968edc34bb57bb5ee2e05ec2809b63bb5e62e9c84db37bb5eba50eeea50cb839b6eba5968edc34bb57bb5ee6e05ec6809b63bb5e66e9c84db37bb5ebe50eeee50cb839b6ebe5968edc34bb57bb5ee1e05ec1809b63bb5e61e9c84db37bb5eb950eee950cb839b6eb95968edc34bb57bb6e70703730e0e6d8ae1b2c1db96996effb0051f79bc81f6ec34687668d0c34e3d8a7345a3a72d32cdff701ee35061bb7e12a8766ab1868c6b13f5b65e9c84db37cf76751f79bc81f6ec3d50ecd5633d08c637fb6dad2919b6651fd596bfc3c398fb76ff5aa4fe63bcbad39f0e098291f31e5290e2a3d8da90ac7dbdbdfaf68b5b44a06777fd3c2e7d8c3a8f191e44f98855998855998855998855998855998855998855998855998855998855998f933e3f3ccade617df857a870923d9f09e948febfcbaee63ccba68fdfad9de5b03dafcc67fdf225589f75ce9b9e331569d4ba0ccff7dbc8ded63c386f71769bb456dcbfbf56e057c1f05de0bba9ff73b3f726876c3a1d9754f8c769f41f3d781d17effc3fd7ef7c41d4b476e9a45f5b3773cf144c5d91d87ef8ad87ca79a7cddd7d5ef22ec13dcbdffbae3d0d4471ce6faee0b6c17ad1e787cbde742d7e9ba55a75b569d92506618d4f37eb62d9ae6018faffe28b07802873e341533e399c18c670c339ec9cc784a99f14c60c653c58c6724339e6798f13cc18ce731663cfd99f1f461c6d38319cf7c663c3399f14c61c63391194f8a19cfb3cc785632e3799219cf32663c8f33e359cc8c6700339e0798f18c66c653c28ce779663cb398f14c65c6b38619cf24663cd5cc78f2710f34179e61cc782a98f10c64c6f310339e05cc7812cc787a32e399cd8c27cd8ca79619cf70663c35cc781a99f13cc78ca78119cf50663ccb99f10c62c6b38419cfc3cc781632e32963c69364c6d38b19cf1c663cd398f1d431e319c78c6715339ea798f10c66c6f308339e11cc781e64c653ce8c672c339edecc78e632e399ce8ca79e19cf78663c95cc785633e3799a19cf0a663c4398f1dc66c6b39419cf22663c8f32e3e9cb8ca71f339e51cc788a18f02482bb9f5dc2e7e56e818d9eb169055bb1637d342e97caebe3ceb383ef5e77b163dd371c0ca8d335a84bdae42b3fddd4eeb9a222b35e9a277f65c0718309cf28663cfd98f1f465c6f328339e45cc789632e3b9cd8c6708339e15cc789e66c6b39a194f25339ef1cc78ea99f14c67c63397194f6f663c6399f19433e3799019cf08663c8f30e319cc8ce729663cab98f18c63c653c78c671a339e39cc787a31e34932e32963c6b39019cfc3cc789630e319c48c6739339ea1cc781a98f13cc78ca791194f0d339ee1cc786a99f1a499f1cc66c6d393194f8219cf02663c0f31e319c88ca78219cf30663c3799f15433e399c48c670d339ea9cc786631e3799e194f09339ed1cc781e60c6338019cf62663c8f33e359c68ce749663c2b99f13ccb8c27c58c6722339e29cc786632e399cf8ca707339e3ecc78fa33e3798c19cf13cc789e61c63392194f15339e09cc784a99f14c66c6338619cf0c663cc5cc78e6593cf87f7dad81ae2f5e071bfdff3fcdcdfb72538feb96bf18ea5119f56d1e5f9ae194766812f56d1e0e3c3398f18c61c63399194f29339e09cc78aa98f18c64c6f30c339e2798f13cc68ca73f339e3ecc787a30e399cf8c6726339e29cc782632e34931e3799619cf4a663c4f32e359c68ce771663c8b99f10c60c6f300339ed1cc784a98f13ccf8c6716339ea9cc78d630e399c48ca79a19cf4d663c15cc780632e3798819cf02663c09663c3d99f1cc66c69366c653cb8c6738339e1a663c8dcc789e63c6d3c08c6728339ee5cc780631e359c28ce761663c0b99f19431e34932e3e9c58c670e339e69cc78ea98f18c63c6b38a19cf53cc780633e3798419cf08663c0f32e32967c63396194f6f663c7399f14c67c653cf8c673c339e4a663cab99f13ccd8c6705339e21cc786e33e359ca8c6711339e4799f1f465c6d38f19cf28663c450c78a2be8543ffef01b6ab267f1b6c574cfe26d82e9bfc75b07de8b0153b58c8df55b0d138972b60a37b7597c146d78bc8973edebd38f86ed662479d7a3858af38ea74d5b12c6e475a261dc4bb1dd1571ae6c91f7eabe72a139e51cc78fa31e3e9cb8ce751663c8b98f12c65c6739b19cf10663c2b98f13ccd8c6735339e4a663ce399f1d433e399ce8c672e339edecc78c632e32967c6f320339e11cc781e61c6339819cf53cc785631e319c78ca78e19cf34663c7398f1f462c69364c653c68c6721339e8799f12c61c6338819cf72663c4399f13430e3798e194f23339e1a663cc399f1d432e34933e399cd8ca727339e04339e05cc781e62c63390194f05339e9bcc78aa99f14c62c6b38619cf54663cb398f13ccf8ca78419cf68663c0f30e319c08c6731339ec799f12c63c6f324339e95cc789e65c69362c6339119cf14663c3399f1cc67c6d383194f1f663cfd99f13cc68ce709663ccf30e319c98ca78a19cf04663ca5cc782633e319c38c6706339e62663cf32c1ebca6580936ca57818df229b051be1a6c94af011be5c7818df2e3c146f90960a3fc44b0517e12d8284ff78cf0f99e7cbc178e7cd1ba69fe1a30de3679dc2694af03ee0f2c9be6bee489fb038b9be62f0123d5e103b051be1eb82f5a36cd7dc113f7458b9be62f0023d5e122d8283f196c949f0236ca4f05db54f04736ca4f031be5a7838df233c046f99960a3fc2cb0517e36d8283f076c949f0b36cacf031be5e7838df20bc046f985e6576fe3f72d9bdec6e74d3e1dc4bb8dc917ad9be6cf03236deff7c146f945c0fd9e65d3dce73c71bf6771d3fc3960a43abc0736ca2f06eeb3964d739ff1c47dd6e2a6f933c04875380b36ca2f01eed3964d739ff2c47ddae2a6f953c04875380d36ca2f05ee93964d739ff0c47dd2e2a6f913c04875380936ca2f03eee3964d731ff3c47ddce2a6f963c04875380e36ca2f07eea3964d731ff1c47dd4e2a6f923c04875380a36caaf00eec3964d731ff2c47dd8e2a6f943c04875380c36caaf04ee83964d73b778e23e6871d37c0b30521d0e828df2f83efa359e186f5b8cb72ddf781f178f2d0f5836cdf8ae27c6031623cdbf0b8c2d267f00780e78e269b1786cdf49d0650d53cd92606b019e5a4f3cd72c9e6b961638de0dcf05d658369fdb758dc548f30780b1c5e4f3d1365b2c1edb771274a965aa59126c2dc053e789e792c573c9d2029f73c173b75acbe673bbd65a8c765f8171867d85afb6d962f1d8be93a04b1d53cdb0cf6d019e7a4f3c172c9e0b96166590c7f3c73acbe673bbd6598c765f8171867d85afb6d962f1d8be93a04b3d53cdb0cf6d019e164f3ce72d9ef3966fdc8678bebfd0b2f9dcae0b2d469ac73ed76e0ba5908f9ba7dee2b17d27419716a69ab9da82cffeec9cc573cef28ddb10afcf2cb26c3eb7eb228b91e61702638bc9e3365ce489a7c5e2b17d2741977aa69ab9da4229b0c5cd73c6e239636981e3f6f07a5abd65f3b95da3fa8f45c0d862f2f9689b2d168fed3b09ba2c66aa191e43b6004f8b279e5316cf29cb376e43bcfeb9c4b2f9dcae4b2c469ac73ed76e0ba5908f9b67b1c563fb4e822e2d4c3573b5059ffdd9098be784e51bb7215eaf5e6ad97c6ed7a51623cd2f01c61693c76db8d4134f8bc563fb4e822e8b996ae66a0b3efbb36316cf31cb376e43bcbfb0ccb2f9dcaecb2c469a5f0a8c765b28857cdc3c51fd19f94b822e2d4c3573b58552608b9be788c573c4d2a20cf2783fa8c5b2f9dcae2d1623cd2f0346d2aa05785a3cf144c519f94b822ecb996a96045b3ef69b872c9e43966fdc8678ff6e8565f3b95d57588c34df028c765b28857cdc3ccb2d1edb77127459cc5433575b401d1b807ba565f3a9ed4a8b9be65700e362878e2b3df144f5292b41c7064b476e9ab9e211756c04ee06cbe653db068bbbc1d2d6158fa5908f9b27aa5d37808e8d968edc3473c56319b0ad02eec596cda7b651eda80118975bdafadcef456debc5a023e9d2c85433bcae89db9ad8560377a365f3a96da3c56db719dcd6d8661a3df1446deb46d0917459c55433ec7bf07cc8d7f947d4fdae7cf88eba07920fdf51d7c5f3e13bea5a693e7c47dd47cf87efa86b2af9f07daff36c9fbea3ae59e6c377d4795f3e7cdfb67cdfcea3efa8f16ff9f01d3526aaabb76fd99774af7dc9fdecd7baebbe44fa739efdf9eaf87da71241fb731a3d1559f369c8e3f9cb2a0f5a78aa67259e137e12e37a5de7d6cb2dadf0dc1acf517d9dffadb678689efc152233c645517cbe2bf13a0c7edf91ae8b54828dae8b55818dae8ba6c0d662f2d560a37b323560a3fb81e3c046f7a2e7838dc6412c001b8dc1b900361afff53ed868ece179b0d1b8d7f7c04663aecf818dc6fb9f051b3d6b72066cef98fc69b0bd6df2a7c0f696c99f04db9b267f026c6f98fc71b0ed37f96360db67f247c1f659933f02b6bd267f186c7b4cfe10d8769b3c5e7bdf65f2782de733268fd7f25e37f9f160db69f213c0f69ac94f04db0e939f04b6ed267f1b6cdb4cfe0ad8b69a3c7e5f748bc97f00b6cd267f096c9b4cfe22d8369afc64b0359bfc14b06d30f9a9606b32f934d8d69bfc34b0ad33f9e9605b6bf233c0f6aac9cf04db2b263f0b6c2f9bfc6cb0bd64f273c0f6a2c9cf05db0b263f0f6c1f9bfc41b07dcee4f13a68b1c9e3f57b7adf14def3a2775ee23d4f7aaf34de6fa76f7fb4808dbeaf85e38c4a4d1ec7b8d17ba5707c25bd4b12c7a9264c1ec79597993c3ed340dffdc06743e8db51f85c52b9c9e33371f4cdcf0360a3ef92be0b367af7d43b601b60f26f838ddee9fc16d8e83b176f828dbeddf406d8e87b9ffbc146ef98da07b6c74dfeb3601b68f27bc136c8e4f7808dbed1b41b6cf49dc85d60a377497d066cf47ec4d7c15661f23bc136d4e45f03db5326bf036cf4fdc5ed60a377466d031bbd77702bd88699fc16b0d1f70e36836db8c96f021b7dc76b23d8e8dd50cd607bdee437806d94c937816db4c9af071bbd9b671dd8c69afc5ab0d13efb55b0d13efb15b0d13efb65b0d13efb25b0d13efb45b0d13efb05b051dfff31d8a8efa7fe43b753dd7e6f99f97410df7194f6d71ab49fb21dcb1303f2c4796c9c041ef47533f6baa7c2e3f08fccba8acd7a295e6e82efebb1fbce9c03dc30ebea69d67bddf25d02654a07b66d9b6bf0ff34d48196c332b46e9a1f03cb5eb3d65d6eea7bc3537daf5b4cc47d0398a84cd9c0b6b25f32f952582646b6f07c96622d000d714a439e18fc68950acf2f3eca81e706f0c4df4e32e7d73e6202db56dce7d7f675193bd69250e63ae8e7ebbd58372c1e9a277fc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc2cc9f59f3d0fd04624d40b95b4c18c986f7ba7c5ce7c77bae78cfebe6c036bfbeefeff532eb1d6bd5b904ca7c6b601bdb6d932f83ffd3768bda961eee1366dd96dfbb5706f5c17b411eb665c873d3e2b17d9739f4d19a5d736876d513a3dd67d03c7ef385f4bb063cbedae3758bc7f68d7dc60da69a45f5b33ec625648b33d718848ad87ca79a7cddd7d563a1f4580e7bff75cbd214c740e03df32f419f44cbdc31bf09d0e70ee8733ffb007b5c02f653adc0187fbf996a770f98fafe3196a63806e2b78cb6340622fe7e2055e9731f416dd41e5b8175a532bf0ffbb93f34791c07740bd6f515c7ff69ca362601fbd4cbf1d739dcbe1f9a75d1f6bdecf0fd01b0c6e4bb0a7d1799447ec85e02f92f0f6c2b6b7f678ab42676fc1616b2dbcbb55acb25a1cc1547fdd341bcf5bf6cf15cb69875ecfc09c4d957e058cf579f742542a331a01195c1635e5ffbaf8f2c1ee2207fd88ff6b6cad0b22550e6ebd047e9ba503fdf6a7ea3f601be8e17a2f60178bc60ef17128e3aeaf8b835a08db7bb8ff5fb2fe82faec1ffd3c1a71febf75f1043aee3525aff58583f71f50ea2f72d54e67f59fb511fe793b82d6d3d712c2195f97fd00fa50665f2b99cd7ddaf73f4a8f33a1fdfcec4730d9ab2eddf711fe3a37ff154cf4ad7beeb9a55a724941906f5f4701ce3dc6fd1fc65f0edeb7ba9e4838ea1ae5b5a944099a4693bd47744e988d7256ee4a52e29e7f1e058475da8cc00a84b29d8e364f2b9ddf0384baff7a6a3ae54e6b1416d65079a7c02b613f6a5231cffa7295b7f40fae93a5f8cbfcee1f6a5e71669fb5e74f87e1f5863f2ddeefd1574bc4f7ec85e02f9e183dacadadfee24adf15bacf47c1db2dbcb5db7964b42994b8efaa78378eb1ff59d59f2a7636708c419c591cf7ef35284466341232a83f70aeceb2d51fb7d1f63e9b3edf76f02a3dd6fe2b18b4f36fb9cc5be5eee3a1ea43278ce426526403f9b7094f57f1f20736c83f5a27a04565d03abae9e8e5f6b8a2c3dd3e06734d8293e4967fa1f1ee3529969d6feccf7756ce2a67ae0fdbaab16f7354b57bc16351bb875dcdbe716789ceef99cb6068fc5ece3a1abc04e65165ac743f671dc6d475decfd747170f7b9e02756597c3629db7276fe236b19bc66e0ba268b7ddf1560499b7ce5a799aa2a2b91a9d8a185ebbea9ab4fa2768031675f47196dad07afa3acb1fa24bbacee936afbb7e943db11afb5dbd7df3d3d9b16b6b95b56fd6d8d3463abc9e336f4710fa33b3e9b561adb7a27ad2fc4f10ca5563e1edfa90db8afc8a6c555078faf6b9a515a5c75f88e4f8bf14daefd874b8b2b0e1e5fe798515a5c71f88e518b8dae6b0b2e2d2e3b787c9d6b446971d9e13b3e2d26b4bbae914d8b0f1d3cf15fd3c8ae05de13cb85f90a03e6522b1f8fef9af5ae7b772e2d3e70f0f8ba7717a5c5070edff1695135de75ceeed2e29283e7529eb5b8e4f01d9f161327b9aea9b8b4b8e8e0f1707d2dab16171dbe638c8b66bcbe964d8b0b0e9e0b79d6e282c3778cc787e3b35d33442dde77f0f8baf617a5c5fb0edf316ab14efb3edf012dce3b78cee7598bf30edff169b17e9cf6fd5e07b478cfc1f35e9eb578cfe13b3e2dd64dd4becf75408b730e9e7379d6e29cc3778ce750615c9ced8016671d3c67f3acc55987eff8b4d8101e6b9de98016671c3c67f2acc51987eff8b4a80cf7a9a73ba0c56907cfe93c6b71dae13bc6b808cf274f75408b530e9e5379d6e294c3778cfb91302e4e76408b930e9e9379d6e2a4c3777c5a6c0caf3f9de88016271c3c27f2acc50987ef18afb9847171bc035a1c77f01ccfb316c71dbee3d3a23adca71eeb8016c71c3cc7f2acc53187eff8b4680eef891ded8016471d3c47f3acc55187ef188f3bc3fee24807b438e2e03992672d8e387cc778dc195ebf38dc012d0e3b780ee7598bc30edf31f69de171e7a10e6871c8c17328cf5a1c72f88ef1b833d4e26007b438e8e03998672d0e3a7cc778dc19ee475a3aa0458b83a725cf5ab4387cc7181761df79a0035a1c70f01cc8b316071cbe63bcae15f69def76408b771d3cefe6598b771dbe633c1f09aff1bdd3012dde71f0bc93672dde71f88ef15e51780cfe7607b478dbc1f3769eb5781b7cfb1867825ad058ac5196162550e681c1995f1a8b15a523ad039fa1c5babc157b5d32e3cade8ca8cb5b50172ad317ea520af638993cd5358c19fa96028d4d6f75d495ca3c3cb8adeca3269f806d721bd635ccf17f9ab28d4122fd749df7c55fe73056e91b10b47df7397cef05d6987c57a16f1a9b4e7ec85e02f96707b795a572a407694decba8dd0373090dd5eee6d6bb92494d9efa87f3a88b7fefb2c9e7d1673f8dc03c419c5919fbe2bc3b43f42a351a01195c1317bad9e78ec3184c441fe7419dafebdad32b46c099419037d148e2ba57a2682bbc74deafabde1a97ee48bd64df3e42f09b61bc068d751c7c74330f693be0142df07d136fade077ebf6bbc65d3759de0a9aee48bd64df3138091be3f323eff8ca98e328eb31835cf240f9ae1375568cab6bf98043c133df078aa67b81faab5ea34c1aa5312cae0b38db51eea59047e69dd345f0bbe7d6c73d482f6c9c32d2d4aa0cc42ebf8314a475a878edff18ebaf8d2719cc533cee17bb2671d69ddd4274ece83ef3acb778de55bb76d8c313d656bdb75c05cef8159af774afceb0ddbf654b32e8a67f25303754a830671d5097d1759eb267b09e49b06dfcd407ad0be93d8753bc2d8895a6e92b55c12ca4c76d43f1d73fda7583cb88df5a48f1b5e84e34a0fed218c81c91607cdd780765322b49b0cda5119dcf75679d2aedee2a1f92ae0a1e3ab5ab0d1710a7ee392fe9fca03b7ddefd53ab8c986df3cac72308e8f9f313cceaab218697e3c3092ad1e78ea3c69666febe1963e784cd0db2a43cb964099fdb05f4e38ca86cf1d17b5d58bbea5f9498cf5d2ebede5412ffcce6700fa04968634114369d0f62dd038791e08dabef5b97bcfce5deb36352f6bcedcf624b4120b137f8b1cd528061be67b386c41d0fe93a62560a34f9af6045bb1250b7e4a95cad3a7137dc8857ad0ba4b2cce526089d3377e0e96a66ca1d31b787c84b20e1dfa24ac099dc65d5bf634637cf4b4383b133bfa7f3db2948b5a17c5418987ba2313ad9be6c99fd6873e8ffbfabaa66dd3766ddabba3f9b53dbb11d66e5c982fb244b07f5dcb60906063a2f5f4b4c4e913bf3835d8786dbe00fc05c012189ed2f879c240a56f0837addbbe7dc9def5dbb734cddefb5ad39e2d3b5f43457b5bca45a96d37793db9ba3a2c6b97efe5b0d9137eb1b937d8e88bcda56023ff7dc0461c0fc0ffec2de1a54d0c83f55318ebff95980af73215a210a4dd90ee4f749bd1af4dd5bb7ffd8968fd4968bdf9f4dbe2f4279ef5279df5279cf5279bf5279af52799f5db24f413defac8614890f984f29341e615b14383cc2790f5278f9f09da3e69aca7df055efd09637da8a13f51ac3f49fc7c90b954383ac8bc564dbfc6421fb2ea432b7d98a74f6bf421b83e2dd7875efa7281be74a40f63f421a23efcd1872cfa105c1f7a4f355a4f0b329f34d79f309f19643e51ae3f49ae3f413e37c87c627cbe4a0b82cca7b6170599cf07ebcf87ebcf76ebcf79ebcf7cebcfcfebcf82ebcf85ebcf88ebcfcceb4f0feb4fd0af0e329fda7e29c87cb6f89520f399e3b541e6b3c8eb83cc6794370499cf2eebcf31ebcf346f0e329f75d69f7bde16643e0fbd23c87c4e5a7f665a7f7e5a7f965a7fae5a7fc65a7fde5a5f72d7b71af425787d795b5f7ed5b740f4ad1f7d6958dfb2d4b770f52ded962033e4e150901912a38708e921537a08991e527722c80cb9d44350f5905c3d44590fd9d643d8f5907efd88837ee4433f02a31f09d28f48e947c6f42374fa3148fd58a17e4c563f36ac1fa3d6977df523e8fa56a0bedcdb1a642e09df09329f5ffe9c4a9f57e9fb54fa824adfafd20fa8f4832afd904a3facd21755fa11957e54a51f53e9c755fa09957e52a59f52e9a755fa19957e56a59f53e9e755fa0595bea4d22faaf44b2afdb24abfa2d2afaaf46b2afdba4abfa1d26faaf45b2afdb64abf1364e2f1f754fa7d95fe40a53f54e98f54fa6395fe44a53f55e9cf54fa7395fe42a5bf54e9af54fa6b95fe46a5bf55e9ef54fab24a5f51e9ef55fa0795fe51a57f52e9ab2afdb34a5f53e9eb2afd8b4adf50e99b2afdab4affa6d2bfabf42d95fe43a56fabf49da0ed33e5d8790c363dce5033bf6ecf9ee61dafefa9d8b3b362c7deed7bb6bcbefd8d8a7d5bf66caed8f9d9e65d1bb7efdc870b7fd92cfcb8999fb66bd7ba372ab6bcb6a1797fc5cebd7b2a766eac58bf73ef6b1bdaed2cffb75968f0dd1ed76dd810edacb4c7a7202debd139a783cc72f4a5fa79d9ebf6448f4e08f24c67169adbc90acd357b203a0d5b9e39e6abd8bd7de79e8aca8ad7d45fb573ddb9af79c3980afcdf6e25f2ee3d15bbf7acdbb5a762e3ae9d3b2aaac6e07a17f6e94425bed8c70f4c6ff35ea24e85ca6f0eec444dbe36b0739be33f3f0de9ffeca4d3b2419da861ffce2c347e50e708d3832265d9bd77fd9e5deb9af6442f3cebd32cbca033d55cddc96af619dc0967e59d5968f4e0ce112ee88cb37d39380bfe3f4095c818d4550500", + "bytecode": "0x1f8b08000000000000ffed9d07741d45b6ae5bb61ce0481893b3450e06a3e49c64724ec6608c31b62c0b1b0739623298e81cc8c10639e78c718e18c3cc30393381811926dd3b7367ddf5e6be77df7a8f75bbcea9bdf4ab5c7daca3e992ff2355af5552f53ed5bdbffa7b7775aaeeca0952d33fc294a3f3cdc3744170f824bf97e9ff85ffda5414e3ba0a5d72e6640967b32ce16c9e259cb959c2d9224b385b660967ab2ce16c9d259cc7c4c8a9d89a05b5a7b8798f75a06bdc8c892cd3342f0b34cdcf324d8fcb024ddb04d9d1461d9f259c6db384f3842ce13c314b384fca12ce93b384f3942ce13c354b384fcb12ced3b384f38c2ce13c334b38cfca12ceb3b384f39c2ce16c97259c0559c2796e96709e97259ce76709e70559c2796196705e1423677be0bc58ffbf44ffbf54ffbf4cff97b297ebff57e8ff1d741d73f5fc958a2b4cea214db1f15b49984ac3d4314c9d8cdf3a87a94b98ba86a99bfead40ffd63d4c3dc2d4334cbdc2d45b6bd0274c5785e9ea305d13a66bc3745d98ae0fd30d61ba314c3785e9e630dd12a65bc3745b986e0fd31d61ba334c7785a96f98ee0e53bf30dd13a67bc3d43f4cf7856980c1727f980686e981300d0ad383611a1ca621612a0fd3d03055846958982ac3f4509886876944981e0ed3c8308d0ad3e8308d09535598c686695c98c68769429826866952981e09d3e4303d1aa6c7c2f4b8a1d913617a324c4f85e96983f399303d1ba629617a2e4ccf87e98530bd18a697c2f47298a686695a98a68769469866866956986687694e98e686695e985e09d3ab617a2d4caf87e98d30bd19a6b7c2f47698de09d3bb619a1fa605617a4fb3c88ef07e98aac3b4304c8bc2b4384c4bc2b4344ccbc2b43c4c2bc2b4324cabc2b43a4c6bc2b4364cebc2b43e4c1bc2b4314c9bc2b4394c1f84694b983e0cd3d6306d0bd3f630ed08d3ce30ed0ad3ee30ed09d3de30ed0bd3fe301d08d347613a18a68fc374284c9f84e9d3307d2b4cdf0ed377c2f45998be1ba6ef199a7f3f4c3f08d30fc3f4236dfbb1feff135d56eedffd344c3fd3f99febffbfd0ff7fa9ff7f6e2cf3ab30fddab0fd264cbf356c5f84e9773affa5feff95feff7bfdff0ffaffd7faff1ff5ff3fe9ff7fd6ffffa2ffff55ffff37fdffdff5ffbfe9ff7fd7ffff43ffff47981e2848e55b0735535910531b555a997cf623e25f1cd49e9416cdf56ff2bf40db73f5bcfc17ed5ae8f91686bda59e6f69aca7b59e6f6dd8dbeaf9b686fd443d7fa2613f59cf9f6cd84fd5f3a71af60bf4fc05604f04706f58db95adb936e5804de2b519d85a685b73b0b594d581ad95b6b5009b6cdf96603b46db5a81ed586d6b0db684b61d235a86294fdbca82b862a570885a6f7edcebd5cfcb8e8b9f77a85a6f1b47bcc7c7cf3b4cadb7ad035e151f27e8751d0f7173a2b6b505db49da7602d84ed6b613c1768ab69d04b653b5ed64b09da66da780ed746d3b156c6768db69603b53db4e07db59da7606d8ced6b633c1768eb69d05b676da7636d80ab4ed1cb09dab6dedc0769eb61580ed7c6d3b176c1768db7960bb50dbce07db45da7601d8a4fdbd106c72be7891b6a9b6e3981c5846dba5dd4a2e236d36d82e95f61a6c97495b0db6f6d24e83ed72f02db62ba0ad115b076d93764bfdd64de7cb82b8f693e24ab5deee71af375cb35a6fcff8d79b7ce6d82ba8d1b50cfc7407ad7aeb7c8cfd9a8ad0778e4ee247ecb990bf09ca4a39d1438e3dc2ae8e313d74be779ae5ba19cbe543991e96fa9705f1d6bfa7c1d3d3606e017937315b52e263b6ce53c631db1fca9ab127e7418d31666f050e0731dbd9c76c9da78c63b612ca9ab127e7c28d3166ef070e07315bee26668b0b7dcca6ee9b05813df6e47aa831c6ec08e0883f663bfa98adfb9471cc3e0765cdd8936be2c618b3938123fe98ed5ceecf0dea3c651cb373a1ac197b727fa631c6ec8bc0e120662b7d3b5be729e3987d0fca9ab127f70a1b63ccbe0a1cf1c76c5747315be26336483d030d027becc97debc618b30b8123fe981deaefcfd67dca386677405933f6e4194a638cd9f53aaf9e33fc583f67380b6c3fd1b6b38137fed8aee8e828b68b7d6ca7fa8604813d46e5795e638cedbd3aafe2f8e7d01f416cbfd0b673c1f64b6d3b0f6c9f6bdbf9502f07fb40b9df07ea3c65bc0ffc1aca9ab12ccf961be33ef043e07010b3153e66eb3c651cb37f85b266ec493f87c618b35f00878398adf4315be729e398fd3f50d68cbd4b74be31c6acf43555e70b5feaf385cbc0f695b6b507dbefb5ed72b0fd41dbae00dbd7dad6016c7fd4b62bc1f6276d2b04db9fb5ad086c7fd1b662b0fd55db4ac0f66fda560ab67fd7b68e60fb9bb67502dbdfb5ad33d8fe43dbba80ed1fdad655dbd4f32ee97b25e7adad81b52c886fdb26401799728cf932c817bbe529cc071ef4551abfaf1255f792a0ee752f059e8e0eea9e001f75e1e9083c9de2e749f645ed1cff7a93dbb8c4d03401be4aa05e5d1cd42b077cc9ba655efce5830df7f32e16c6aef13316e7802f59b7cc770546b161bb23efffc8fea3dae673736a781dec4bc9e333fa2b030ef1970b65fed9aea6ec859a2d0f7ec736b89361731497c9b8105fb26e99177f79509f4e0dcf585c57c68e06a3ab3622077cc9ba4ddf79902f72ab4f5a9ece24be1d9c775bdb34d1bc7b03f8ee6af82e357c63db2953ba635b57608efdfa471fdb7ac4bfde423c5796eb14f183e70f783d11579dd0b75ca7881fb1e742fe869c9ab2524ef4907658d8d53e2cdb12d9cde5ba18cbe54399ee96fa9705f1d6bf87c1d3c36056c79b9e702c74b03f2463a0bbc121f3a5a05d8f08edba837652e612d0cec1b96752bb6e068fcc77041e69bfb13d2b6a609e2202df780e8bd772f23b9e07b8da5e4506a3ccdbb6575760ec686174704e589cee78580a8c62eb063c258e348bdaae2524be5d5c57e6800f393737af6d72a1ccedcd6bca56e438652bc6736799ea7acd1bff762a2ec4fda32e3c8ef7a12247f15888f76fbe09e28d35b35d32db9ba87b3caedaf2128347e6c59f67f6cc9ed9337b66cfec993db367f6cc9ed9337b66cfec993db367f6cc9ed9337b667e66c523cf13b0df9694eb44c268f67f73759f3ff92d3ebd2e7c06f44fa7fdc18a0bf1d99ff483b8cca8732e9439b1590ddb7f437f30b32f51d4b674d13736ddb6147fd81fac219e21961a3ca6ef3c8b3ef85c1a3573d507ca6c33641efba7897e45c0e36a7f2c36784cdfd86694906a16d5cebaead3171567b6fe8405b1f92e1eeaeab9aefaee99fa76a879fcea64689afc26a961536dd25dcd6beaede2396fa6cf9df1b821f9389fe362bf0cf4157f3b5b5cab7f42b3a0f6b10263dd555f2dd9afa46f4477c3772e9439b759cdb6c13e7565c1e1c706ece325eb96652e83657b18eb6ee3aebe69fba174076ec9b734ead619b8a5cc4570ecfea9ce3b3a061667fa8e041e93e33fbea4fa8b9464c083c73b17e72c8e8ea385188f71f71731fb41dace97a50cf62175d07f37edb158fc7966cfec993db367f6cc9ed9337b66cfec993db367f6cc9ed9337b66cfec993db367e667563ce633747cf65b4ac2d8407d6c92cf33e4fb6cf85c6c6bb31abfae9f01ca33a7f6469df11de55c784779a766c3be0ff85d29dbb674f56c2d6a5b8a3fb6be0f79167d94663d2c9a39f8ae63da6f76e0371245bf1ec0e36a7f8cfa7687adcd2822d52caa9d75d177215d9cd9fa2914c4e63bd55fc4c5735de92f621ebfccef1a613f09b1e173f0a8ef85151bb6a3dd06d8fab5491ebfb9e0628c1b8c67b3afa0f8c37e125f686da59f44fced4071a1cb6384eca3d227a4c4525729f387663565ffa8f3d857a814d6f54fcbef32a5eb93806daa83efc726b7afac4bb6afeddbb57d803526df45b8ae1c9dfa181ae442fe7f35ab292be5a4ac682dec6a1f91ef4a21bbb95c4763b97c28d3cb52ffb220defa9bdf12ee6d30abd8f90bc4d93fe15ccf559bd42b42a3cb40232983e7bcaefad59a6da4d9671afb44b632cae0f9a994f9ffd04645f549b7f5a97475be10d59f13cf176ce734661dcdbee34dbd3f60bebe0e71d11f50d6dd26a8dd272f30d6df1ed62f5cad82e8638b94690beb3f9adfbdb25dfb092ff6379432a7c0b5df0d3a9fc9b5dfd1ba8eb75dfbe1725175c77621ee6323c623b2602c4b9902231e7b447077b52c7b7ec4b2a295f9ed43bc2ec57384f8bf1b996a6f7a1b75917d0abfef2f652e35f69bf8cf9952e79faebe9129eb9236a8d8525729d301f6b5429d4fc076c2778a7a5b7e9729ddf9a7e8a7ea7c55fc754e6edfabf5ba64fb5e65f17d0db0c6e4bb087dcbf9a7f8117b2ee47bc1f144ca891ea2b5b0ab7d44cee190dd5caebbb15c3e94e963a97f59106ffdaf3278ae329855ec94409cf586772d5cb5d57d22346a0f1a4919bc776dfbaeb1ed5e47439da79adf4bcf0f0eff762f1e27dd9cb3d9df9533efdfdace4fda1bfc787e722bb4b3094b59f3beb42c1767ff747c1f08cf0bf17d2057d748f9416d3df30d0e97bedb18bedb34a0efb686efb60de8db6bee3567d29c69cc1f7c0ed90c185d1cebf0b85a1746dbf1af3930ba7a67b3240346fce6351eef84d1c577c2eb3ba6109eebb4004617ef1b677abfba1330e2370684d1c53bda997ea71adfdb96e55a01a38b718d700ca5ba30dac63a6a0dff1d8c6b5454df714070aca36380d1c5d82089a0f678264762ec068cb2dcb1c0e8e2395222a87d5fed488cf8bc52964b38664c776c77dcf7a738d37b100dd1af20ea5c037d3bb8ff5f8c7d13eaa2454fb73c69cf7dd0b783fb5f492d702ccb236981cfe75c8cad99086a3f0b3b120f3e4394e54e00c632478cbd33602c034659ee4460ece388b12c03c63ec028f69380d1c17dc824639f0c18f17e9d2c7732305eed88f1aa0c18af064659ee146074714f31017eebc2780d30ca72a702e3b58e18afc980f15a6094e54e03c6eb1c315e9b01e375c028cb9d0e8cd73b62bc2e03c6eb8151963b03186f70c4787d068c3700a32c772630dee888f1860c186f044659ee2c60bcc911e38d1930de048cb2dcd9c078b323c69b3260bc191865b97380f116478c3767c0780b30ca72ed80f156478cb764c0782b30ca7205c0789b23c65b3360bc0d1865b97381f176478cb765c0783b30ca72e701e31d8e186fcf80f10e6094e5ce07c63b1d31de9101e39dc028cb5d008c773962bc3303c6bb805196bb1018fb3a62bc2b03c6bec028cb5d048c773b62ec9b01e3ddc0d8d7c2d8cf11e3dd1930f6034659ee7260bc277ec6e4b574bf0c18ef019e7be3e7496a764f063cf7bae5497e43f11e8baffbe2f795dc16fd83bad7fd3ee019103f4f725bdc97018f30e4c372a8d9fdf13326351b9001e3fdc033307e9ea466f767c0331034bbdfa2d903f13326351b9801e303c033287e9ea4660f64c03308347bc0a2d983f13326351b9401e383c033387e9ea4660f66c03338a8d1ec418b6643e2674c6a363803c621c0531e3f4f52b32119f0948366432c9a0d8d9f31a95979068c4381a7227e9ea4664333e0a900cd865a341b163f6352b38a0c1887014f65fc3c49cd8665c053099a0db368f650fc8c49cd2a33607c087886c7cf93d4eca10c788683660f59341b113f6352b3e119308e009e87e3e7496a3622039e8741b31116cd463a627c3803c691169eb8bf89feb0c5d76847751f15d4bdeec2900fcb613f89318e184767c03806186539ec2751e588714c068c55c028cb251c33a6eb275105bec7c6ef3bd92e550575d767ac5b9eb4fd24d0f738475a8c0deaaec538b73c69fb49a0eff18eb41817d45d8bf1c033c1811609f051171e61c887e5b09fc444478c1332609c088cb21cf69398e4887162068c93805196c37e128f38629c9401e323c028cb613f89c98e181fc980713230ca72d84fe251478c9333607c14186539ec27f19823c64733607c0c186539ec27f1b823c6c732607c1c186539ec27f18423c6c733607c02186539ec27f1a423c62732607c12186539ec27f19423c62733607c0a186539ec27f1b423c6a732607c1a186539ec27f18c23c6a733607c06186539ec27f1ac23c66732607c16186539ec2731c511e3b319304e0146596ea463c674d72f531ab9efa86b95c6ee3beabaa4b1fbf671eee3bc29f8f671eee3bc29f8f671eee3bc29f8f671eee3bc29f8f671eee3bc29f8f671eee3bc29f8f671eee39cc9f7730e7c27c0874c39c67c19e485211f961be9191b3523f214c4c7538875475fcf13d4fd790b4f8ea3baa3af1708ea2e0cd9c6f85c16308ecc0246af63aa0f627d1815cf8b8e785ec880e745e079c911cf8b19f0bc043c2fc7cf938ca99732e011867c586e6416303e97058c5e47af2313a3d7b1e9e8e8193da367f48c4783311bda70cf9815f1585c5f46c533357e9ea4662f67c033153493e5ee75cb585c5f46c5332d7e9ea4665333e099069a4db568e680b1b8be8c8a677afc3c49cda665c0331d349b66d1cc0163717d1915cf8cf879929a4dcf8067066836dda29903c6e2fa322a9e99f1f324359b9101cf4cd06c864533078cc5f565543cb3e2e7496a3633039e59a0d94c8b660e188bebcba87866c7cf93d46c56063cb341b35916cd1c3016d79751f1cc899f27a9d9ec0c78e68066b32d9a39602cae2fa3e2991b3f4f52b33919f0cc05cde6583463651c99058ccf6501a3631d8bebcba878e639e2999b01cf3ce079c511cfbc0c785e019e57e3e749c6d42b19f008433e2c37320b189fcb0246afa3d79189d1ebd87474f48c9ed13366c6f87c1630fa6ded1959191d5c5fa57d87e69546ee3bea1d9ac6ee3bea1d9ac6eedbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98f7326dfafc5efbb38d377585f031e17efd43aaa67a15aefeb7a5ddfc4a89fd2ea0d43ab570cadf2a1cceba0df1b0ef4cb01bfb26e99177f99325f4cc0ecc877f171e13a8e81fa8b8fe70c3d94ff371dd53daaad7fb391fb8e6aeb1bbbefa8b6beb1fbf671eee3bc29f8f671eee3bc29f8f671eee39cc537e673839af376f9be925ac75b3adf42cf4bf9e7613929d3af55ea7f9bc0ef432e7cfb7dc81f2b9a826f1fe73ece9b826f1fe73ece9b826f1fe77c718ef1707503f004064f9086e749329ece643c63c9788692f1dc43c67313194f2f329ec9643cc5643c33c9781e26e379898c671019cf9d643cd792f15c41c6f334194f57329ef1643cc3c878ee23e3b9858ca78c8ce731329e52329e59643ca3c9785e26e3194cc6d3978ce705329eebc9789e25e3e94ec633878ce752329e89643c9790f13c44c65348c6733f19cf71643c6dc8786e23e3b98a8ce709329e4e643cb3c978aac878a692f19493f1f423e3b9928ce746329e9e643cf3c8781e21e32922e31941c6f30019cf1d643ccdc978ae21e3798a8ca70b19cf38329ef6643c15643cd3c878fa93f1dc4cc6d39b8ce751329e12329e51643c0f92f1dc45c6d310dfe3c884670a19cf75643ccf90f17423e39940c6339d8ce762329e4a329e01643c79643cf9643c1dc8786e25e3e943c6f338194f47329e31643c43c878ee26e379918ce706329e1e643c73c9782691f1cc20e3194ec633908ce732329ee3c978da92f1dc4ec69343c093080eff4672027e7f0d6ccd8c65d567a5ba15d4fcfeb6b6378365ded1f9e69675bf0d36f956d53b966551a7b7a12e653a5ff8af4d499dd05719cc8bbf3ce0788784e776329eb6643cc793f15c46c633908c673819cf0c329e49643c73c9787a90f1dc40c6f32219cfdd643c43c878c690f17424e3799c8ca70f19cfad643c1dc878f2c978f2c8780690f15492f15c4cc6339d8c6702194f37329e67c878ae23e39942c6f31a19cf5d643c0f92f18c22e32921e379948ca73719cfcd643cfdc978a691f15490f1b427e31947c6d3858ce729329e6bc8789a93f1dc41c6f30019cf08329e22329e47c878e691f1f424e3b9918ce74a329e7e643ce5643c53c978aac8786693f17422e379828ce72a329edbc878da90f11c47c6733f194f2119cf43643c9790f14c24e3b9948c670e194f77329e67c978ae27e379818ca72f19cf60329e97c9784693f1cc22e32925e3798c8ca78c8ce716329efbc8788691f18c27e3e94ac6f33419cf15643cd792f1dc49c633888ce725329e87c9786692f11493f14c26e3e945c6731319cf3d643c43c978c692f17426e379928ce76a0bcf6b8e78e47d7759b7ccbf46e2dbc1762854eb7dd7519de6eb75b5d4eb157ef1970b658a8e4dfd57cf877059e132bf4f807dbfe783466f39aa8b3926a6ccbfd5c87db7317cb76922bedb1abedb3611df3ece7d9c33f99e1fbfef62fcb68d4c39c67c19e4f1f8e2e29b408eea59ebd8fe4d8cfa29ad16185abd6568950f65de05fd1638d0cf76be20f3e22f53e68b0998312e0a8278e3e2bdf8eb54acfad21c03babe67e88bf57adf91a651c790f71bb9efa8634863f71d750c69ecbe7d9cfb386f0abe7d9cfb386f0abe7d9cfb3867f25dadf3315e3716a20f75ef57ae07aac1ef229dcf89d1af5ad742bdae167addc2b10878a4cc2b702fdaeff37e9f8fcbb73fb6f9386f0abe99e3dccccb33c44b80cdd533dea8586c88e7cb47d377542c3676df51b1d8d87dfb38f771cee47b71fcbe93cf105f0b6a4fe99e212e069e850eb47054cfe4b5d312a34eaf1975ca8732d550cf250eea99037e65dd32bf04b643b6312b9e293a8fe3bb48b929248c625be89627b97f4d096a4fe9f6af25c0e3603f287254cfe4feb5d4a8d3148bee52a61aeab9d4413d6dfb8ecc2f85ed906dcc8a47dedd15d604947b8184516c8bddf224f7af1782da53bafd6b29f0b8687f1cd533b97f2d33eaf482457729530df55ce6a09eb67d47e697c176c83666c5236399086b02cabd48c228b6256e794a13506799d2ed5fcb80c745fbe3a89ec9fd6bb951a7172dba4b996aa8e77207f5b4ed3b32bf1cb68367f6cc3666c523ef4c0a6b02cabd44c228b6a54e794a0b13506799d2b563cb81c7453bef48f7643bb6c2a8d34b16dda54c35d47385837adaf61d995f01db2113e6f959c85c9d85cc5e67af7314737516327b9dbdce51ccd559c8ec75f63a4731576721b3d7d9eb1cc55c9d85cc5e67af7314737516327b9dbdce51ccd559c8ec75f63a4731576721b3d7d9eb1cc55c9d85cc5e67af7314737516327b9dbdce51ccd559c8ec75f63a4731576721b3d7d9eb1cc55c9d85cc5e67af7314737516327b9dbdce51ccd559c8ec75f63a47315767213383ce8ae7659d17d604947b9984516ccbdcf224dfdf7939a83de518f365905f013ccb1de8e3a89ec97eef2b8d3abd6cd15dca54433d573aa8a76ddf91f995b01d32619e9f85ccd559c8cca0b3e299aaf3c29a8072534918c5b6dc2d4fb21d9b1ad49ed2b5632b81c7453befa89ec9766c9551a7a916dda54c35d47395837adaf61d995f05dbc1337b661bb3e299a6f3c29a8072d34818c5b6c2294f71f23dc46941ed295d3bb60a785cb4f38e744fb663ab8d3a4db3e82e65aaa19eab1dd4d3b6efc8fc6ad80e9930cfcf42e6ea2c64f63a7b9da398abb390d9ebec758e62aece4266afb3d7398ab93a0b99bdce5ee728e6ea2c64f63a7b9da398abb390d9ebec758e62aece4266afb3d7398ab93a0b991974563cd3755e5813506e3a09a3d8563ae529493e77981ed49ed23d77580d3c2e9ecb38d23df9dc618d51a7e916dda54c35d4738d837adaf61d995f03dba1b133cfcf42e66acfdc20cc3e363c7314b38f0dcf1cc5ec63c3334731fbd8f0cc51cc3e363c7314b38f0dcf1cc5ec63c3334731fbd8f0cc51cc3e363c7314b38f0dcf1cc5ec63c3334731fbd8f0cc51cc3e363c7314b38f0dcf1cc5cc101b8a6786ce0b6b02cacd206114db2ab73cc9ef1ecc086a4fe9faedac019ed50ef47154cf64bf9db5469d6658749732d550cfb50eea69db77647e2d6c07cfec996dcc8a67a6ce0b6b02cacd246114db6ab73cc9766c66507b4ad78ead051e17edbca37a26dbb175469d665a749732d550cf750eea69db77647e1d6c07cfec996dcc8a6796ce0b6b02cacd226114db1ab73cc9766c56507b4ad78ead031e17edbca37a26dbb1f5469d6659749732d550cff50eea69db77647e3d6c07cfec996dcc8a67b6ce0b6b02cacd266114db5ab73cc509a8b34ce9dab1f5c0e3a29d7754cf643bb6c1a8d36c8bee52a61aeab9c1413d6dfb8ecc6f80ed906dcc8a678ece0b6b02cacd216114db3ab73cc9fd6b4e507b4ab77f6d001e17ed8fa37a26f7af8d469de658749732d550cf8d0eea69db77647e236c876c63563c73755e5813506e2e09a3d8d6bbe549ee5f7383da53bafd6b23f0b8687f1cd533b97f6d32ea34d7a2bb94a9867a6e72504fdbbe23f39b603b641bb3e299a7f3c29a8072f34818c5b6c1314f02ea2c53bafd6b13f0b8687f1cd533b97f6d36ea34cfa2bb94791feab9d9413d6dfb8ecc6f061e99ae061e577119183c81451f999e24e3e94cc633968c672819cf3d643c3791f1f422e3994cc6534cc6f33019cf20329e3bc978ae25e3b9828ce769329eae643ce3c9788691f1dc47c6730b194f1919cf63643ca5643ca3c9780693f1f425e3b99e8ce759329eee643c9792f14c24e379888ca7908ce77e329ef7c9788e23e36943c6731b19cf55643c4f90f17422e3a922e32927e3e947c6732519cf8d643c3dc9781e21e32922e31941c6f30019cf1d643ccdc978ae21e3798a8ca70b19cf38329ef6643c15643cfdc9781690f1dc4cc6d39b8ce751329e12329e51643c0f92f1dc45c6731d19cf33643cddc8782690f15c4cc65349c633808c278f8c279f8ca70319cfad643c7dc8781e27e3e948c633868c670819cfdd643c3790f1f420e39944c6339c8c672019cf65643cc793f1b425e3b99d8c27878027111cfe2e5e027e5f003679676c1ed83ed0f98d606b66f121cf2236832d57e7651dadc2746dc1e1eb469d5cbd2787beca605efce501c707243cb793f1b425e3399e8ce732329e81643cc3c9782691f1f420e3b9818ce76e321eb91e64e11943c6d3918ce771329e3e643cb792f17420e3c927e3c923e31940c65349c6733119cf04329e6e643ccf90f15c47c6731719cf83643ca3c8784ac8781e25e3e94dc6733319cf02329efe643c15643cedc978c691f17421e3798a8ce71a329ee6643c7790f13c40c633828ca7888ce711329e9e643c3792f15c49c6d38f8ca79c8ca78a8ca71319cf13643c5791f1dc46c6d3868ce738329ef7c978ee27e32924e379888c672219cfa5643cddc9789e25e3b99e8ca72f19cf60329ed1643ca5643c8f91f19491f1dc42c6731f19cf30329ef1643c5dc9789e26e3b9828ce75a329e3bc9780691f13c4cc6534cc633998ca71719cf4d643cf790f10c25e3194bc6d3998ce749329eab2d3c0b1cf198e326c8fc0202df6abe3be8a2a604fc8edf597fdf11e3028351e6df0746e475ad591b83a78da1d9d1f4adea2fefeac83d70dc5ef8de39c3f66ad3009ab53578da1a9a1d4ddf4a0b79b62def0ce2f6c2efd4326c2f7cafda41fb5c9a3078d49463cc97417eb3637d1cd5b310dfbbfe26c6f52aadb6185a2d30b4ca87329b40bf2d0ef4cb01bfb26e99177f9ed93347312b1ee94b62fb1e403f1246b1e1b8181fc6cf539a3078d494ae7dfcd0b13e8eea996cc7b60676dd3f04dda50cc6ea5607f5cc01bfb26e99df6af15d10c4abc5b63a68b1cdc2b3ad81b5107f99326fca4266069d158fbc6b20ac0928d79f84516c5b80677bfc3ca50983474de9dac7ed8ef57154cf649bb023b0ebbe1d749732b87fed7050cf1cf02beb96f91db01d3261de9a85cc5ee7fa312b1e79475b5813506e0009a3d8b601cfced8798a0b13068f9ad2b5633b1debe3a69ea9766c5760d77d27e82e6570ffdae5a09e39e057d62df3bb603b7866cfec993db367f6cc9ed9337b66cfec993db367f6cc9ed9337b66cfec993db367e666563c03755e5813506e2009a3d87600cfeed87952cf1d90474de99e3bec76ac8f9b7aa69e3bec09ecbaef06dda50cc6ea1e07f5cc01bfb26e99df03dbc1337b66cfec993db367f6cc9ed9337b66cfec993db367f6cc9ed9337b66cfec993d3337b3e219a4f3c29a8072834818c5b60b78f6c6cf539a3078d494eeb9c35ec7fa38aa67f2b9c3bec0aefb5ed05dca60acee7350cf1cf02beb96f97db01df67966cf6c61563c83755e5813506e3009a3d8f600cffed87952cf4f91474de9dab1fd8ef57153cf543b7620b0ebbe1f74973218ab071cd43307fccaba65fe006c874c98b76621b3d7d9eb1cc5ec75f63a47317b9dbdce51cc5e67af7314b3d7d9eb1cc5ec75f63a47317b9dbdce51cc5e67af7314b3d7d9eb1cc5ec756e3a3a2b9e729d17d604942b276114db3ee0f928769e92c284c1a3a61c63be0cf21f39d6c74d3d53cf1d0e0676dd3f02dda50cee5f071dd43307fccaba65fe206c87c6cebc350b997d6c340cb38f0dcf1cc5ec63c3334731fbd8f0cc51cc3e363c7314b38f0dcf1cc5ec63c3334731fbd8f0cc51cc3e363c7314b38f0dcf1cc5ec63c3334731fbd8f0cc51cc3e363c7314b38f0dcf1cc5ec63c333473133c486e2a9d079614d40b90a1246b11d009e8fe3e7294d183c6aca31e6cb20ffb1637d1cd533d96fe75060d7fd63d05dcae0fe75c8413d73c0afac5be60fc176f0cc9ed9c6ac782a755e581350ae9284516c0781e793f8798a13068f9ad2b5639f38d6c7513d93edd8a7815df74f40772983b1faa9837ae6805f59b7cc7f0adb21db9815cf709d17d604941b4ec228b643c0e320ee923cf9068fcc7f42e05bcd57e97c9efe8fdbab0a1819b6577e0368d6c6e069636876347dabfa8fd5f9e3f47fdc5e638191617bb56900cdda1a3c6d0dcd8ea66fa5c5389d3f5effc7ed350e1819b6575bb73cc50983474de9ce373e059e6fc7cf93bc8efb34039e6f03cfb7e2e7297254cf42b5deef007b5ceb555a7d6668f5a9a1553e944186cf1ce897037e65dd322ffe3cb3678e62c6b650581350ee131246b17d0b785cb41baaee57e875c9fa5b84e90727d6f875717f0def2db4d4eb150ef1970b65ce6e57c3f613cd9607bfcb7653f53968d81cbdf35664bbcf2bf3e22f2fb05febbbba871a75efe120f01cb46876c0a2d97e478c070c4699df0f8cb6fbbc071cf144dd77167fd8661c24d50cdf03fe08785c9d1747c599eb7d2ed3f3cb8f2c3cdfc4c75388b181be5cc42ab66d75a9bb6ddf89b1ee45f80c0b7d39d80792c7a90e7a5db27e752cf8af139d6a5e8aed831ca73a1875ce8532ff7d4e0ddbff4d739c6a161c7e5fb840dba58cfcfe8db69beb28d0eb96f9eefa3fc689d8fc31b0f673c4ee86966c9ae1bef5b145c71e16ee1e04dc188f0db1ada3ee7de0b6ee61e8c8a6196eeb4f2c3af6b470f724e066dcaf7b1a3ab26976a4fdba9f85bb1f0137e37eddcfd0914db323edd7fd2ddcfd09b819f7ebfe868e6c9a1d69bf1e60e11e40c0cdb85f0f307464d3ec48fbf5400bf740026ec6fd7aa0a1239b6647daaf0759b807117033eed7830c1dd9343bd27e3dd8c23d98809b71bf1e1cd4d6914db323edd7e516ee72026ec6fdbadcd0914db323edd71516ee0a026ec6fdbac2d0914db323edd79516ee4a026ec6fdbad2d0914db323edd7c32ddcc309b819f7ebe1868e6c9a1d69bfaeb27057117033eed755868e6c9a1d69bf1e6be11e4bc0cdb85f8f357464d3ec48fbf5380bf738026ec6fd7a9ca1239b66b6fdda51ffb28cfb217fec549fd4f8b399bc87857d495cc494a3382874d4d724d90f79bfa1d5c78656f85dff03a09fab3e5951fdc6c49f67f6cc9ed9337b66cfec993db367f6cc9ed9337b66cf2c653cb367f6cc9ed9337b66cfcccb8cef79e2f31529d710ef00d785516cf84ccac57d7e55f72bf5ba64fd2dc274fbc9357ee37f6e519c7c0e20facbfb98571a75ce85323bceae61ebabd9f0f9223e17b56dcb03b1d7a16eef9ce37bfaf82ce8683eeffcc8a2d97e8b66fb1c319a6d86ccef0346d16f3ff0b8da1f0f183ca66fdbbbe16c9a45b5b3aee23e2ace6cbe0b62f35d3cd4cdb7108a0bd537da8e090e6f4fa40eb8efba88c34cbf0980fb8583e7ee45aedeff5775da67d4e9a051a77c287331d4739f837ad675df92e96ae071d51e05064f60d147a666643c4f92f17426e3194bc633948ce702329e7bc8784e23e3b9898ce718329e5e643c93c9788ac9781e26e31944c6d38e8ce74e329e13c978ae25e3c925e3b9828ce769329eae643ce3c9788691f15c44c673888ce772329efbc878ce20e3b9858c2741c65346c6f318194f2919cf68329ec1643ce792f1f425e339998ce77a329e96643ccf92f17427e39948c6732919cf43643c9790f11492f1dc4fc6731619cf6d643cc791f1b421e3b98a8ce709329e4e643c55643ce5643ce793f1f423e339958ce74a329e1bc9785a93f1f424e379848ca7888c670419cf03643ce790f1dc41c6730219cf35643ccdc9789e22e3e942c6338e8ca73d194f0519cf85643cfdc9784e27e3b9998ce758329ede643c8f92f19490f18c22e379908ca7808ce72e329e93c878ae23e36941c6e3fa3dc04c799e21e3e946c633818ca7928ce762329e01643c6792f1dc4ac69347c6934fc6d3818ca70f19cfe3643c1dc978c690f10c21e3398f8ce76e329e53c8786e20e36945c6d3838c671219cf70329e81643c6793f15c46c6733b19cff1643c6dc97872087812c1e1df62c2ef7f1d04db3e9dc76f0b36b3ac4f9e0b4b79751cbab5e0f07537b3ac7bbf850175da1bd4d4a54ce70bffb529a913fa2a8379f197071cfb4978da92f11c4fc6733b19cf65643c6793f10c24e3194ec633898ca707194f2b329e1bc8784e21e3b99b8ce73c329e21643c63c8783a92f13c4ec6d3878ca703194f3e194f1e19cfad643c6792f10c20e3b9988ca7928c6702194f37329e67c8783e22e36941c6731d19cf49643c7791f11490f13c48c6338a8ca7848ce751329ede643cc792f1dc4cc6733a194f7f329e0bc9782ac878da93f18c23e3e942c6f314194f73329e6bc8784e20e3b9838ce71c329e07c8784690f11491f13c42c6d3938ca73519cf8d643c5792f19c4ac6d38f8ce77c329e72329e2a329e4e643c4f90f15c45c6d3868ce738329edbc878ce22e3b99f8ca7908ce712329e87c8782e25e39948c6d39d8ce759329e96643cd793f19c4cc6d3978ce75c329ec1643ca3c9784ac9781e23e32923e34990f1dc42c6730619cf7d643c9793f11c22e3b9888c671819cf78329eae643c4f93f15c41c6934bc6732d19cf89643c7792f1b423e31944c6f330194f3119cf64329e5e643cc790f1dc44c6731a19cf3d643c1790f10c25e3194bc6d3998ce749329e66643c571b3cf8bb3ab796f7c3f6814d7e7f56375e6df4baa48c3c1351f796f6183655dfdd8eeabb27a899ca607e37d457d8f700cf1e473c7b0d1ed3771ee47b8066bb0c9b62dce9887197c128f33b8151f4db053cbb1cf1ec36784cdf7990ef099aed306c8a71bb23c61d06a3cc6f0746d16f07f0ec70c4b3d3e0317de741be1f68b6cdb029c6ad8e18b7198c32bf151845bf6dc0b3cd11cf7683c7f49d07f9fea0d987864d316e71c4f8a1c128f35b8051f4fb10783e74c4b3d5e0317de7417e0068f68161538c9b1d317e6030cafc666014fd3e009e0f1cf16c31784cdf79901f089a6d326c8a71a323c64d06a3cc6f0446d16f13f06c72c4b3d9e0317de7417e1068b6c1b029c6f58e1837188c32bf1e1845bf0dc0b3c111cf4683c7f49d07f9c1a0d93ac3a618d73a625c6730cafc5a6014fdd601cf3a473ceb0d1ed3771ee4cb41b335864d31ae76c4b8c66094f9d5c028faad019e358e78d61a3ca6ef3cc8578066ab0c9b625ce9887195c128f32b8151f45b053cab1cf1ac36784cdf7990af04cd561836c5b8dc11e30a8351e69703a3e8b702785638e25969f098bef3203f1c345b66d814e352478ccb0c46995f0a8ca2df32e059e68867b9c163face837c1568b6c4b029c6c58e1897188c32bf181845bf25c0b3c411cf5283c7f49d07f9b1a0d922c3a618173a625c6430cafc426014fd1601cf22473c8b0d1ed3771ee4c78166d5864d31beef88b1da6094f9f78151f4ab069e6a473c0b0d1ed3771ee4fb824d788bc0f69ece17836d81ce97806dbece9782ed5d9def08b67774be13d8ded6f9ce607b4be7bb80ed4d9def0ab63774be1bd85ed7f95e607b4de77b83ed559d2f03db2b3adf076cf374fe2ab0cdd5f9abc13647e7af01db6c9dbf166cb374fe3ab0cdd4f9ebc13643e76f00db749dbf116cd374fe26b04dd5f99bc1f6b2cedf02b69774fe56b0bda8f3b781ed059dbf1d6ccfebfc1d607b4ee7ef04db149dbf0b6c2375fe6eb0ddabf3f780ed539dbf0f6cdfd2f9fbc1f66d9d7f006cdfd1f907c1f699ce0f01db77757e28d8bea7f3c3c0f67d9d7f086c3fd0f91160fba1ce3f0cb61fe9fc28b0fd58e74783ed273a3f066c3fd5f9f160fb99ce4f00dbcf757e22d87ea1f393c0f64b9d7f046c9febfc64b0fd4ae71f05dbaf75fe31b0fd46e71f07db6f75fe09b07da1f34f82ed773aff14d8bed4f9a7c1f695ce3f03b6dfebfcb360fb83ce4bbba6dad93fea7c41106f3bfb75503315806ff1a7cafc49e75b196564d95c2853aa3fe8a39e71a86f994a3b2cedb2b2493bfc1ed8a41d5e00366987e7834ddae177c126edf03b609376f86db0493bfc16d8a41d7e136cd20ebf013669875f079bb4c3af81ad4ce75f059bb4c3af804ddae179609376782ed8a41d9e0336698767834ddae1596093767826d8a41d9e01366987a7834ddae169609376782ad8a41d7e196cd20ebf043669875f049bb4c32f804ddae1e7c126edf073609376780ad8647ff91a6cd2368f049bb4cdf7824ddae64fc1266df3b7c0266df3b7c1266df377c0266df3676093b6f9bb6093b6f97b6093b6f9fb6093b6f9076093b6f9876093b6f947601badf33f069bb4cd3f019bb4cd3f059bb4cd3f039bb4cd3f079bb4cdbf009bb4cdbf049bb4cd9f834ddae65f814ddae65f834ddae6df804ddae6df824ddae62fc0266df3efc0266df3976093b6f92bb03dabf3d256b7069b3c2b5653e1bf38e1383ccdc097309505f1b6fd389541fe19a8bb4cd3c878c692f1bc4ec6730119cf0a329ee5643ca791f17c40c6b3998ce718329e7d643c7bc9786693f1bc43c633888ca71d19cf89643cb9643c5790f15493f1bc4ac6731119cf21329ecbc978ce20e3d944c6b3918c671919cf52329e0419cf1e329edd643cef93f1cc24e3798b8c673019cfb9643c2793f1b424e3e94ec6732919cf3c329e4bc8789690f12c26e32924e3398b8c670319cf7a329e05643cc791f1b421e3d945c6b3938c673a19cfd7643c55643c6f90f19493f19c4fc6d38f8ce754329e2bc9785a93f1f424e39943c6b3888c672119cfbb643ce790f1ac23e3594bc6730219cf0e329eed643ccdc978a692f18c23e3798d8ca73d194f0519cf85643cfdc9784e27e339968c670a19cf2c329eb7c9787e4fc65340c6b3868c673519cf49643cdbc878b692f1b420e3f9888ce715329e4a329ef7c8780690f19c49c69347c6934fc6d3818c672419cf0c329e37c978ce23e35945c6b3928ce714329e0fc978b690f1b4d2ff59787a90f1cc25e3194ec6339f8c672019cfd9643c9791f11c4fc6d3968c27878027011c01d8e4f7e660fb4ae70f814dbed7f311d8bed4f96ab0fd4ee79f05db53165b330b9f307c053679d7fa69b0c9fd992fc126ef70fc0e6c725c14ff6abe6fc1e1fccd6019f1d3dcc28ffe7e67e1923c6e6f59a62c88777ba3afb2e0f0ef29e501c7d3243c6dc9788e27e3b98c8ce76c329e81643cf3c9788693f1cc25e3e941c6d38a8c670b19cf87643ca790f1ac24e35945c6731e19cf9b643c33c8784692f17420e3c927e3c923e339938c670019cf7b643c95643caf90f17c44c6d3828c672b19cf36329e93c8785693f1ac21e32920e3f93d19cfdb643cb3c878a690f11c4bc6733a194f7f329e0bc9782ac878da93f1bc46c6338e8c672a194f73329eed643c3bc8784e20e3594bc6b38e8ce71c329e77c9781692f12c22e39943c6d3938ca73519cf95643ca792f1f423e3399f8ca79c8ce70d329e2a329eafc978a693f1ec24e3d945c6d3868ce738329e05643cebc9783690f19c45c65348c6b3988c670919cf25643cf3c8782e25e3e94ec6d3928ce764329e73c9780693f1bc45c633938ce77d329edd643c7bc87812643c4bc9789691f16c24e3d944c6730619cfe5643c87c8782e22e379958ca79a8ce70a329e5c329e13c978da91f10c22e379878c673619cf5e329e7d643cc790f16c26e3f9808ce734329ee5643c2bc8782e20e3799d8c672c19cf34329e66169e438e78e45829eb96f94304bed57bb8722f7e9ffe9f80df71fce66a478c870c4699af0646b1ed059eee8e78761b3cbb2d5a1c2ddf4a0bf9f6c71efd3f01bfe3f70a5dc554778351e66d31b51b787a38e2d969f0ecb46871b47c2b2da4efa3f42149c0ef381e9eab98ea6130cabc2da6703cd79e8e78b61b3cdb2d5a1c2ddf4a0be96b287df813f03b8e7fe92aa67a1a8c326f8b291cafab9f239ead06cf568b1647cbb7d242de3d93779613f03b8e27e42aa6fa198c326f8b291c1fa2bf239e2d06cf168b1647cbb7d242be2521df444ac0eff87d7f5731d5df6094795b4ce1f7910738e2d96cf06cb66871b47c2b2de45b7572cd9e80dff1fbb6ae626a80c128f3b698da0c3c031df16c3478365ab4385abe951683745e9ec125e0f741c0e82aa6061a8c326f8ba98dc033c811cf7a8367bd458ba3e55b693158e7a54f66027e1f0c8cae626a90c128f3b6985a0f3c831df1ac3578d65ab4385abe9516e53a2fef0c26e0f77260741553830d4699b7c5148ebf5bee8867b5c1b3daa2c5d1f2adb49077efd7e8ff09f81dc7e31cec88b1dc6094f9c1c028361cefadc211cf4a8367a5458ba3e55b6921dfd2926f3026e0771c1fcb554c55188c326f8b291cefa4d211cf728367b9458ba3e55b69315ce757e8ff09f87d3830ba8aa94a8351e66d31b51c78963be2596af02c25f2adb49077e1a40f5b027eaf02c6158e18a3626a05308a6d29f02c75c4b3d8e0594ce45b6921cf72e49d8b04fc3e16189739628c8aa965c028b6c5c033d611cf428367a1458ba3e55b6921df8e59a4ff27e0771caf7db123c6b106a3cc2f0646b12d049e858e78a2eee13584efa8fb510de13beade4a43f88eba4fd010bea3eeb13784efa8ebb786f01d752dd210bea3ee333484efa873fa86f01df57cbb217c473dab6d08df51cf1d1bfbfeed8f254deb587234dbb5a67a2cf1ed39677b3e2e7edfc589a0f6358d9a728cf932c8e3f5cb22075a38aa67215e137e13e37a6dd7f00b0dadf2a10c5ea3babafe1b67f0c8bcf8cb46668c8b9cf87c1726c087bca3ac6c72afe53db0c93d8e0560937b20f3c126f7d0de059bdccf7a076c72bfeb6db00dd7f99160937b97d81f49ee6d6e075bb9ce633f98c13abf156cf29c08fb5fc8b3be2d6093e7b5f8dc5f9eb96f069bf49bc0e7cdd2f76523d8a4ff123ee7943e68ebc126fd08f1f95ab5ceaf059b8c2981cf75bed4f9d560fb4ae7f179828cd5b9126c4feafc14b07da1f35f83ed099d5f08b6dfea3cdef3795ce7c782ed373aff16d87eadf36f82ed319d7f036c8feafc3eb0fd4ae7f7826db2ce63ffd0cf757e37d81ed179ec97f84b9ddf09b65fe8fceb609ba4f3af816da2cebf0ab69febfc2b609ba0f3f3c0f6339d9f0bb6f13a3f076c3fd5f9d960fb89cecf02db189d9f09b61febfc0cb08dd6f9e9601ba5f3d3c0f6239d9f0ab68775fef760fba1ce8f035b339d5f0c36f97e32ded395771697824dc629c17bf5f2ad922ab0c9f87bcbc1d65ae7f1b98cbc97341c6cf26dfb4ab0c9fbff1560933192cac126e3380d069b7c0b6c10d8e47b6503c12663960e009b8cabda1f6cf2ede27e6093f7297b824dc608e90136f98e4a77b0c9d8773826b07cefb21a6cf24e108e132cdfddff126cf26ef9576093f19b704c60f9c6d59360937149bf00db393aff04d8e47dcddf82ad40e71f07dbb93aff1bb09da7f3bf069b7cbff231b0c93b358f824dbea3ff2bb0c9bbd993c176b1ce7f0eb64b74fe11b0c977887e0936192bf617606baff393c026efcc4f04db153aff73b0c9586713c026df57fd19d8e41b5fe3c156a4f33f055bb1ceff046c253a3f066ca53aff63b075d4f9d160eba4f3a3c0d659e77f04b62e3aff30d8baeabcb4336a7f56fbf9413d5f16c4775ea6fc7d1cd49ed25d1b0803f2c479ae9d0f3ce8eb40ec752f4e9ed7cb7edf4caf5762e800f8de17bbefd435c57ebdae167abdfb0cdfb950e653dd88a8e5f6c0ef655007590eafb165ddb2cc95b0ec5e63dd6d747df73baaef3e8349b8f7039394f9ecec9ab24fe8c6b2352c13235bf2fa58622d000d712a83bc30b8d1aab810cf7bebc2b31f78e2df4f52d7eb2e6202f7adb8afd7cd7b4c66ace543997da0df5e07fae1be2eeb9679f1e7993db367f6cc9ed9337b66cfec993db367f6cc9ed9337b66cfec993db367f6cc9e999f59f1c8f3047cae2ce50e92308aed00f0ec8f9fa7109fc3cafad5739d07e0b9ce81d8fdd67ebed752afb7d0a8732e9459754e0ddb109dcf83df65bb456dcb7db1d721fdb6147f79509ffdc0e3605b26790e183ca6ef3c8b3e4ab3bd16cdf6386234db0c99df038cfb747e2ff0b8da1ff7193ca66f6c33f6936a16d5cebae897902ece6c7d100a62f35d3cd4d5735dd5674af5e5308f5f070d4db10f84d8f039781e2cf389fe9f007d3e017d8e661b60f64bc076ea6360dc173b6371ad67c0d2f65f69688a7d205ed4da4a1f88f8db81e24297c708d947cdbe15585729331d8e7333751efb011d8475bd6bf95da61c63be0cf2d8a6ee8abfcec9ed2bfd5765fbeeb2f8de01ac31f9aef52e478e4ee247ecb9907fe79c9ab2524ef410ad851dc7ad427673b98f8de5f2a1cc6e4bfdcb8278ebbfcbe0d96530abd8990371f62e9cebb96a937647687425682465f09cd7419f226b1b291ce24f9591eddfca2883e7a7526631b451aa2ed2ce4b3db11f131e035c9d2f1c34ea27f378be603ba731eba8e2e3f6936b785d5f0b340bec5ab3f4f5db0ced45dc7dfd36430cd9ce4b65fd85b07ee16a15441f5ba4cc56e338eae27a12b7a5a9e77e6092323ba11dfacf7a5cd71dad6bf4a8ebbadd0e78f05a43a674c7773cc6b8685f1cd5b3d076ecda6bd4291fca5c0cf574701e93f69dd45de0dbc536472de41c6a9fa1452e94f9aed17644e928ebc0fb006eeb526c3d1f2cb4d445cafcd868a7763a6072b9ddf03c4badf780a5ae52e617d0fe7d0ee7f3fbf4efd896fec5f2bb4ce9da03fca6fcb6f8eb9cdcbef27ea36cdf6d16df1f026b4cbe6b7d9342cef7c58fd87321ff67387e4b39d143b41676b58fc8fb9dc86e2eb7cf582e1fca6cb7d4bf2c88b7fedb0c9e6d06b38a9ddf409cfd05cef75db59bdb23342a048da40c3e2b30efb7e0bd133cee37d47581cc7f048c62db05fafea7d3fbe529b68f0c36f37eb9ed7cb0d0e0c7f3c1ff0ded6cc252d6fd7380d4b90dd64bea1118750d8cba3a3a7f2dcd31f42c033f1dc0be4fe74567f90dcf71a54c4ebbd47f77f7af6adfc7166ea9073eafdb6370ef3574c57b512d815bc5bd796d81e7e98eaf694bf15ccc3c1fc2eb30299307ecb6f3b84396ba98c7e966c1e1d782df1865f13a3bdd7266fe236319bc6770c0c2646bfb627b2fa7a8b0d0e4b7b57b070d669baeb21f60ccc9bacc7d05cf87a4cc99b0dd1296b2aa4dfaaf136bf491ed88f7da6df7595c1d2fa2eeb3883fc5687b67d2c5338ca6f86e5aebd8d6dbb5dcf69c8dbd3f436b231f8fefe20a3c56a4d3628f85c7d53dcd282df6587cc7a745a7a1b676cea6c56e0b8fab6bcc282d765b7cc7a845a5edde824d8b5d161e57d71a515aecb2f88e4f8bceb5ee6ba4d362a78527fe7b1ae9b5c067629930ef26606e6de4e3f15d5a6e7b7667d3628785c7d5b3bb282d76587cc7a7455127db35bb4d8bed169eed0dacc5768beff8b4e8d2d5764fc5a6c5360b8f83fb6b69b5d866f11d635c0cc3fb6be9b4d86ae1d9dac05a6cb5f88ef1fcb053ba7b86a8c587161e57f7fea2b4f8d0e23b462d8628df5beaa0c5160bcf9606d6628bc5777c5a947754be3fa883161f58783e68602d3eb0f88e4f8b215d94efcd75d062b3856773036bb1d9e23bc66ba8645c6caa83169b2c3c9b1a588b4d16dff16951913cd7da58072d365a783636b0161b2dbee3d3a230794cdd50072d3658783634b0161b2cbe638c8be4f5e4fa3a68b1dec2b3be81b5586ff11de371241917ebeaa0c53a0bcfba06d6629dc5777c5a5426ef3fadad83166b2d3c6b1b588bb516df31de7349c6c59a3a68b1c6c2b3a681b55863f11d9f1625c963eaea3a68b1dac2b3ba81b5586df11d9f16c392cfc456d5418b55169e550dacc52a8bef18cf3b93edc5ca3a68b1d2c2b3b281b55869f11de37967f2fec58a3a68b1c2c2b3a281b55861f11d63db993cef5c5e072d965b785c8d1119a5856d7cca18cf3b935a2cab8316cb2c3caec6368cd26299c5778ce79dc9e3c8d23a68b1d4c2e36a2cca282d6ce360c61817c9b673491db45862e159d2c05a2cb1f88ef1be56b2ed5c5c072d165b785c8dcd11a5c5628bef18af4792f7f816d5418b45169e450dacc5228bef189f1525cfc117d6418b85169e850dacc542f0bd3f76dfa9fedce243fa625d6168910b65be6df4c58ad251d681efd0625daa63af4baa5fd9fb1175a986ba48991f187df9de77c0e4a8aec998794faf4bfaa67f6ca9ab94f969bb9ab23fd7f9046c9343b0ae3f5a7e9729c7982f83bce8a7ea3c3ffe3a276355c60192ed3bdfe2fb1d608dc97711faced149fc883d17f25fb7ab292be5440fd15ad8d53eb240e791dd5c6ea1b15c3e945960a97f59106ffde71b3cf30de6e47b0f106712476edaae14d382088dae008da40cf6d93be488e763834738c45f4e70f8bba8524696c57751ff6ef4db957e9052cfa83e92ef39aa5f541f49f117f52eaa5947151f3f80be9f322e888c19a26c32064809aca7b3615375ede2a8aee24bd62df35d8051c624e9dcf08cc57565ec64302a9e6e0e34c37156644a77bce8063c5d1df038aa67f238d4dda85317a34ef95006df6deceea09e39e057d62df3ddc1b78b6d8e5ac831f952438b5c28935790fa2fe78f513aca3a54fc76b6d4c5958e9d0c9e4e16dfbd1ceb28eb9636b15703f8ee61f8ee68f856fb36c6989ad2eddb3d80b9a70366b5dedef1afb710cf19259ec54f47a8531fd020ae3ae1bae41cb38fa16d2ee4cf2fa8292be5a4ac1c3b855ded47b22d91dd5cae9bb15c3e94e965a97f59106ffd7b1b3cbd0d6675de705a410d8783fd211903bd0c0e99ef08daf58ed0ae17682765f0d8dbc991763d0d1e99ef043c727ed51d6c729e22fc09f8bda401b8cd76afbb855b6c381e61270b63c7f8198bd31d173a02a3d87a024f0f479a99dbfa52431f3c27686594916573a14c9782d47f7957cb2cabf6bb73736aead55cdb637b6f4db7e92d1de885e38106a04f6068289330b40e6ac60c8d93e7d8a0664cd00913abc60f7968d85dc3528f3d052dd7c0c4ff39966a34031be69b5b6c41507be8d35cb0c9d0a72dc0d6cc9005875c95f23274a20bb9500f5977aec1d91a58e2f48dc3c6ca942e745a018f8b5056a12343c7ead0b977fc8889c3303e5a189cf5891df55bf334e5a2d6257190eba0eec824eb9679f1a7f4c9d7f9b143868eec33fea149a3878d99380161cd9d0bf3398608e67fdb321824b833c97a5a18e21c1bbf38a53846b1c917803f9984a17550338e718c3cc94095b186870e1935ea8e49e5a3460cbd6ed298a11347548d41455b1bca45a92dbfb7049bada9c3b26ac2dd17976d65b1d9261cd5b935d8a4053f066cc2732cd89a435eca9b5bc6c93e7231ac5fc25afda6c469a12bde2aa80901392ca9f645ed43ea33aaea74400d2dad8692569b53ddb1534343abafc8a9a19fd550cf6a68673594b31aba590dd5ac86663e3b480dbdacee5e1604a9a194cf0b5243255f10a48642be08f8be0dcc9704a9d30f359471fb203554b1ba7da85e1f579f5a53efb7abd3587579ac4efdd4a58e3a0d53a75fea345bdd4250b793d4a98d3a6d54a744ea34469d96f7d65af709d35561ba3a4cd784e9da305d17a6ebc37443986e0cd34d61ba394cb784e9d630dd16a6dbc3744798ee0cd35d61ea1ba6bb83d470daf784e9de2035dcf67d416a28eefb83d430dd0f04a921bc1f0c52c37b0f0952437f0f0d52c3820f0b5243863f14a486131f11a4862a1e19a486361e1da4864756c3948f0d5243a2aba196d5b0cc6a086735b4b31a1a5a0d23ad869c564351aba1ac9f085243643f15a6a783d410dacf86694a989e0bd3f3617a214c2f86e9a530bd1ca4866557c3b5ab61dc6704a961df6705a961e2d5f0f16a587935dcbc1a865e0d4faf86ad57c3d9bf11a637c3f45698de0e528f05d4e310f59840dd8257b788d5639aea2075fb7a51907accac1ebbab6e08aa5b86eaa6b22248756352ddba543737d5ed4f758354dd42553759d56d5875a356ddca55377bf5da817a0d43bd96a25ed351af2da9d7b8d46b6dea353ff5aaa67af551bdcaab5e6dde17a46e4d1f08528f2bd5ed6a755b5adda257b7d03f0dd3b782544c7e274c9f85e9bb61fa5e98be1fa61f04a921a3d5f0d26a786a3594b51ae25a0d87ad86ce56436fab21b93f0f52437daba1c27f13a4861bff224cbf0b52439e7f15a486bbff4398be0ed31fc3f4a730fd394c7f09d35fc3f46f61faf730fd2d4c7f0fd37f84e91f41cdb0e6d89014e8d6e75c3d3f64e2c461a3c74e2c985855307ad2a88923c68e7aac60f28889c30baa1e1936be7254d5645cf8b77a611993bdcff8f1431e2b1831a662d8a3055593261654551694574d1a5351eb40fafff442671dee71484545b4b3bce6ff02e9f1cdebe7b49d5e4e46bbbf317dddce6b5e0f412ea9cf42b7d4b34277eb23985cf2f54d9d0f164c185535b1a0b0604cf8373cf0564d1e56d1a1007f9b108a3c6162c1848943c64f2ca81c5f35baa0a803aeb7f0d87a5462deb16e604a4eaf9f389f9c9dfa5faf107be19c7a28b0e89cfa916e3ae75f20fdb09e4e3fab4f0d7f549f85feab9e84817ef0699165c2a4f289e3870c9d18bd708b7f65e144bb7a54f38c76f5abe6b7eae3ecfbf559e86ff5244c14d4c359e782ba3b0bfe07c2beb575b8020600", "isInternal": false }, { "selector": { "value": 2603445359 }, - "bytecode": "0x1f8b08000000000000ffed9d69741cc5b5c77b24595e46832d5bde37b1056fb246a3dd968d8cf70dcc8e018317c960b02d638b7d271b092121fb4202bcac2421fbbeef09d9f7852424908484247c7839efbdf3ce791f38afaa5537fa4f51dd6886be72b5e6f639d7537d55d3f7776fdfaaeea9aa6e3f1304412618daaa959c143c77a3bff79acffc0bdb5a123c569e93339312ceaa947056a784b326259ce352c2599b12cef129e19c9012ce8909726ab6aaa0784b9a7712435c9366cca62ca6752988692e65313d2105319d1ca4a38f9a9212cefa94704e4d09e7b4947036a484737a4a3867a48473664a3867a58473764a38e7a484736e4a38e7a584737e4a3817a48473614a381b53c279624a384f4a09e7c929e13c2541cec5c079aaf97c91f93ccd7c2e329f547789f95c6a3e97191f6bcc7e9392e54a9a359ff5373dd15050d2aaa4cdfa5bbb920e259d4abaccdf1acddfba95ac50b252498f92554a562b39ddc4628d923394ac55b24ec97a251b946c54b249c966255b946c55b24dc97625672a394bc90e25672b3947c9b94ace5372be920b945ca8e4228b65a7928b955ca2e45225bb945ca6e47225bb95ec51b257c93e257d4afa95ec577285922b951c50729592ab951c547248c96125034a8e28b946c95125c7940c2ab956c9754aae57728315b31b95dca4e46625b7589cb72ab94dc9ed4aee5072a792bb94bc58c94b94bc54c9cb94bc5cc9dd4a5ea1e4954aee51f22a25f72a79b592d728b94fc96b95bc4ec9eb95bc41c91b95bc49c99b95bc45c95b95bc4dc9fd4ade6e58a821bc43c9034a1e54f29092ff50f24e25ef52f26e25ef51f25e25ef53f2b092f72bf980920f2a7944c987947c58c947947c54c9c7947c5cc927947c52c9a7947c5ac967947c56c9e7947c5ec917947c51c997947c59c957947c55c9d7947c5dc937947c53c9b7947c5bc977943caae4bb4abea7e4fb4a7e60c5fc874a7ea4e4c74a7e62fe46e34b3f55f23353feb9f9fc85f9fca5f9fc95f59d5f2bf98da57b4cc96f2dddef94fcde941f379f7f309f7f349f4f98cf27cde79fcce79fcde75fcce753e6f3afe6f36fe6f369f3f977f3f90ff3f94ff3f98c92fe86a1f2846078eb0d12ea93dafafbf4dc0405fbd4a078d3b1a8367fa3cf46a3af31fbf449b11b67f6c759fa5ab35f6b1d6782d99f60e9ebcd7ebda59f66f6a759fae9667fbaa59f69f667823e1bc018a5d16b5db551654047795805ba7141714cb4ae960e07baf141712cb48ece632de8261add78d04d32ba09a0cb1add448a99923aa3eb0d92ca89fc1e7ddc5cd2c735f3362724cfbb4f1f773213ef94e479fbf571eb1978757e4c35c79a027933cde8ea4167ba95602ae8a61bdd34d0cd30ba06d0cd34bae9a09b6574334037dbe866826e8ed1cd02dd5ca39b0dba7946370774f38d6e2ee81618dd3cd02d34baf9a06b34ba05a03bd1e81682ee24a36b04ddc9467722e84e31ba934047fde7c9a0a3fbbb538c4ef7093519f88ed1537f147e87fa5cd09d46fd2de816515f0bbac5d4cf826e09d826dd52e84348b7cce8a83fd27feb32e5de20a9fc2ff4e9e376277d5c75647ddc95c91f379cd3ea0986e3da0b76ba2156ab4c39c175332d683b6384ec90be06ca1ba12ed5a378d03585d8f5b5638529af8af95e97f5bd1cd459e1f0bf3748d6ff9516cf4a8b791cf8cf93b3ad2d92b323de4aced9f3a1ae9d7b747f331673760b7030e46cbbe4ec88b79273761fd4b5738fee71c762ce5e041c0c39dbcd93b385bce4ecd0585710b8738f7ee78cc59cdd0f1cc9e76cbbe4ecc8b79273f676a86be71efdd61d8b393b081cc9e76c67b7dc1b8c782b3967ef85ba76eed1b8cb58ccd9bb80832167fba49f1df15672cede0f75eddca331c0b198b3f70147f239dbcd94b3ad92b3c1d0bc6510b8738fc6a3c762ce3e001cc9e7ec3e199f1df95672ce7e06eadab94773236331671f018ee473b68f6b7cb620393bb45e2308dcb947f3746331673f6fca7a6eece7666e6c01e87e61740b41f74b586740ba5f19dd89e017431be8943630e2ade436f06ba86be7f249a63c16dbc00f80832167bb256747bc959cb34f415d3bf768fdc258ccd9df020743ceee959c1df15672cefe17d4b5738fd6d28cc59c7dda94f5fdc2e3e67e6111e8fe60748b41f747a35b02ba278c6e29e89e34ba65a0fb93d13581eecf46b71c747f31ba66d03d657479d0fdd5e85a40f737a32b80ee69a36b05dddf8dae0d74ff30ba76d0fdd3e83a40f78cd1751a9d9ec7a235558f1add04f0bd3748eedc86eba882e22d63edf74279192f4f3e17143f2740b696276fab55fbde148cdcf7e5c0d3cce07b166c8c84a71978f2c9f384bf475b923f6e788e9bac9866c15613f85560f02b03b6e8d8b44ff672a0c37ea3e0606c4d9eb190015b746cda6f0546d2613f46cfe150fbd17df3bccc302f435b0aafcf68af1738c85e0dd4c9340cd76d346c75f077ea03eaa08cfd7cded231e56a982bf870562fecb70023f9981f7dc6c248199b2d46ae7e2303b6e8d8b6ed3a477c74cc5a1d316b63626cb51869bf0d18297eada3cf581829a3dd2f30f5492d23ed93282ef9d18fd988ce6b0e7478afd7e6606c4f9e313caf6d1623edb70323e90ac0c3753d8c6aafbed8e6b80fc17ca66b165d7fc85e0dd469ad1eaebb09aea70c7d68a1d47b53ecd3933f4f853c5ecf46c2c37cee5a98f2318f7de7b341b2b966b7f9bc152b6cf3d89773f593517d39d91366611666611666611666611666611666611666611666611666611666611666ff99a3e6e55ceb198e2723e95a8087639c3f7cf7943916ce013d06f33ac9cf5b14f238574feb1817593ed7409dffcd0cb33dee58278173e7cb2d1dd33aa5f05ce23aa55ed8277bb86e03d74d31ac3d0979965a3cb6ed3a477c7c5c47e2d31a8da8755a3ec52c073a5c0fd7c4c41395674d0edb8d89d92eece3693b85bc7ecf8f7e571ef527761bc1b56f4b2c9dee933aaa87fde6c88152e79df1ba41e524e77131dfd056f2eb6d0a45eb13aa82e26b05de5330ac51299aafa6b511ed96ed1aac5315fcfbdc74c0df7b83e7ae11c23a746cda5f04dfedb08e3d99cfdfd8feb01db8a95c6bf9b60cb8a9cea4aa611f3f67ca4cf733055c3f1b006f60f9441baecf48fe7e6f68bd48a1049e36e0e158bbc6745f9bc77c4c7abd4887152bd7fd32d56987f87530c42f6ecd1ad91366611666611666611666611666611666611666611666611666611666611666ff99f1fd17c48acf48b778c2384a6b6cc2f90c7a6f11ce8bdd5f356c977b0e90e69c165b3ee333ca4f570db33d68caf88e00d7f3ee782eb9e6d6a2ce25d9ab0b9efb9c3ed3b91cf1bb1fda1c31eb70c4ac9389d1ee3368bf1318297e1dc0c3d51edb2d1edb36f6196d9ec62caa9fe55abf129567ae750a8d89d91e5a2fc231af4beb45eceb578b15535c27413a9c07c777abe07a2cdfdeff62af5dc07e0ad76825df6f168ae680edb582640fd7497cc3c496d64924df0f14f29cd7086aa3b426a4e0f095ea3c0ad7b9ef9932ae156a81633de6f83b6d716b12b04f65785766787ee9dd8d747ebb1db657026b42b65bd076c608d9217d0d947f53355cd77e1724c59ad8751bb1df57e9fa5edefa5e0eea7439fcef0d92f5bfdbe2e9b69875eefc10f2ec31b8d7e3ea93ba02778c16418ca80edef332ac2972f691f69a695d87ceff78ab0ede9f529d27a18f8a5a93ee7a0f20d7fd42d47b00f17ec1754f63fb68af1daff4f580ff82fea203fede1bbcf0f580ff821c72dd97d2f117c3f1896b7c107d6da13aff635d47b9dad6f3bdf7caf5db8f7871bd21d5f93fe8ab969975b951bf635ccf5970fd6e887aee83ece13d5529be63bf90f4b511f31159c81ee6638d8935e5634704f772c777c7477c976245ebcbf177b21d3f1d87c4df116efa9b6ecb176a535de0cbbfafdfe00bcf3dd3d0fd67f2be16df0f511fd4eaf095ea4c8577c135987216ce13f695273bfe4e5bdcfd27bed7bc27799fc3f34befefa6f3dbe3b0bd1a5813b2dd82b6e9fe93ec90be06ca27550fd7a57a140f8a35b1eb3642f770c86e7fafddfa5e0eeaac74f8df1b24eb7f8fc5d36331ebdc99097976323c6bc1d557af8c88d1628811d5c1671deddffff85b1eaf31c7ebb73cbef313fbf66510d3d17a67aa3d7eebba3f596cc518ef4f5aa09fcd3aeadae3d2740d49727d3a3e0fb414ece2f3404b99e2990b8ae399b338386d4fb66c4f1e45dbf596edfa51b42d319798fb14739ffe2f0cfc3f2baa52c0589d02c69a14308e4b01636d0a18c7a78071420a1827a68071520a18b3c0783cafed0cf12978f6ff3dc5de6ba06d86f73984b158168c3c164dbc3cb1f73e689be11d2a25ff7f03ccff17564bb9ff17560ebe3735058cd352c0d89002c6e929609c9102c69929609c9502c6d929609c9302c6b929609c9702c6f929605c9002c68529606c4c01e38929603c29058c27a780f19414309e9a02c60929605cc2cb58289751f370bc47331b14afe37a3e1ee6f77a86ef2774bd4394e3ff9d2dd577e677fab694fb0e3c5cbfc0fbff28beb0f7f471ac4f28f53d7d71fff7341363a15c46aef526b8b665243cae3528795ec642b98c5ccf77e0f38623e171fd3fb8bccfdb0cc5ac1c46aef558a5ae17c4e7f0da1d3163602c94cbc8b5a61f9f371c098febb9c03c2f63a15c46aeb5af59b031129e2e8859a723660c8c857219999edd0a63d655020f3ee3d4e588190363a15c46cdb3822966dd25f0ac8098753b62e61323f224fdbef16e872d8e67e24af59d189071620a1827a58011d72070f45f716b10ba79e35328373e5ce72b6e0d02da667806238c05aeb97fbe58f4f0f2c4ae4140dbab986281cf443c5f2c56010fc7331a59b031121e62c8c1f7a6a680715a0a181b52c0383d058c3352c03833058cb352c0383b058c7352c03837058cf352c0383f058c0b52c0b830058cf85b95e15e31f6f7cbaa316e3beab7ca58b71df5bb64acdb963c973caf04db92e792e795605bf25cf2bc126c4b9e4b9e57826dc973c9f34ab02d792e795e09b625cf25cf7db29d86317e611c7b8cc8d3981c4f1e7d475ba77be0fbe90e9e0c93ef68abd703dfa99c36c6d529605c91024689e3d01ac4721835cf1a269ede1278d600cf194c3c6b4ae0390378d626cf13e6d41925f010430ebeb722058cab53c028719438fac42871ac9c380aa3300aa3301e0fc634f4e1729d19faed520ea3e659973c4f18b3b525f0ac8398d1f7f2bc8c85721935cffae479c298ad2b81673dc46c9d23660c8c85721935cf86e479c298ad2f816703c46cbd23660c8c85721935cfc6e479c2986d28816723c46c8323660c8c85721935cfa6e479c2986d2c816713c46ca323660c8c85721935cfe6e479c2986d2a816733c46c9323660c8c85721935cf96e479c2986d2e81670bc46cb323660c8c85721935cfd6e479c2986d2981672bc46c8b23660c8c85721935cfb6e479c2986d2d81671bc46cab2366be32ae4801e3ea143032c7b1502ea3e6d9cec4b3ad049eedc0732613cff61278ce049eb392e70973eacc1278882107df5b9102c6d5296094384a1c7d629438564e1c85511885b134c6d353c028e75a187d6564f87d15fb7cca9963dc76d4f32963dd76d4f32963ddb6e4b9e47925d8963c973caf04db92e792e795605bf25cf2bc126c4b9e4b9e57826dc973c9f34ab02d792e795e09b625cf25cf2bc1b6e4b9e47925d8963c973caf04db92e792e795605bf25cf2bc126c4b9e4b9e57826dc973c9f34ab02d792e795e09b625cf25cf2bc1b6e4b9e47925d8963c973caf04db92e792e73ed9de91bced42a9cfb0ee009eb31862c1e4675e1ff76c73ac67138c9f8ed53956acceb46295833a6743fcce61885f06ecd2b1699fec95cafc220f98996c174e50c79808fe938dd5563cb4fd73997c8feaebcf1de3b6a3fafab16e3baaaf1febb625cf25cf2bc1b6e4b9e47925d8963c973cf7c536966b82e1fb767abf923ec679a63cceec53fdd3e17b54a765fcd0e7e440da10876d694372ada804db92e792e795605bf25cf2bc126c4b9efb99e7e7276f3b9c1bc3df177a8b9b1b3b1f78ce638805939f79edd305964fe75a3ee5a00ebeb3f602063f3360978e4dfb17c079481bb3e65965cac49a857aab3c6124dd79bc3c61fb5a15146f71edeb02e06168072d4c7e86edeb42cba7558eb8531dccd50b19fc74b51ddabf10ce43da9873608f58b341f139f5819174e7f3f284edab3728dee2dad785c0c3d1ff30f919b6af8b2c9f7a1d71a73a98ab1731f8e96a3bb47f119c87b4316b9e35f077bd65a1de1a4f184977012f4f5b167ca62dae7d5d043c1cfd0f939f61fbda69f9b4c61177aa83b9ba93c14f57dba1fd9d701e8459985dcc9ae70c5326d62cd43bc31346d25dc8cad396cf82cfb4c5f5633b8187a39f678a7bd88f5d6cf9748623ee540773f562063f5d6d87f62f86f3500af3ea14324b9c25ce51cc1267897314b3c459e21cc52c71963847314b9c25ce51cc1267897314b3c459e21cc52c71963847314b9c25ce51cc1267897314b3c459e21cc52c71963847314b9c25ce51cc1267897314b3c459e21cc52c71963847314b9c25ce51cc1267897314b3c459e21cc52c71963847314b9ccb63d63c6b4d9958b3506fad278ca4bb8897277c7e676d50bc65acfd5e285f0c3c3b19e2c3e467b8eefd12cba7b58eb8531d6c5f9730f8e96a3bb47f099c87529857a79059e25c1eb3e65967cac49a857aeb3c6124dd4e5e9eb01f5b17146f71fdd825c0c3d1cf33f919f663975a3ead73c49dea60fbba94c14f57dba1fd4be13c08b330bb9835cf7a5326d62cd45bef0923e92e66e52984cf21ae0f8ab7b87eec52e0e1e8e799e21ef663bb2c9fd63be24e7530577731f8e96a3bb4bf0bce4329ccab53c82c71963847314b9c25ce51cc1267897314b3c459e21cc52c71963847314b9c25ce51cc1267897314b3c459e21cc52c71963847314b9c2b27ce9a678329136b16ea6df084917497b0f2b486f30e1b82e22d6ede6117f070cccb30c53d9c77b8ccf2698323ee5407dbd7650c7ebada0eed5f06e761ac33af4e21b3e4c6e8304b6e087314b3e4863047314b6e087314b3e4863047314b6e087314b3e4863047314b6e087314b3e4863047314b6e087314b3e4863047314b6e087314b3e4863047314b6e087314b3e486304731fb901b9a67a329136b16ea6df484917497f2f284ef3dd818146f71eb762e039e5d0cf161f2335cb773b9e5d34647dca90eb6afcb19fc74b51ddabf1cce83300bb38b59f36c326562cd42bd4d9e30926e172f4fd88f6d0a8ab7b87eec72e0e1e8e799fc0cfbb1dd964f9b1c71a73a98abbb19fc74b51ddadf0de761b7300bb38359f36c366562cd42bdcd9e3092ee325e9eb01fdb1c146f71fdd86ee0e1e8e799fc0cfbb13d964f9b1d71a73a98ab7b18fc74b51dda277bc22ccc51cc9a678b29136b16ea6df184917497f3f214b2e0336d71fdd81ee0d9cd101f263fc37e6cafe5d31647dca90ee6ea5e063f5d6d87f6f7c279481bb3e6d96acac49a857a5b3d6124dd6e5e9eb07d6d0d8ab7b8f6b5177838fa1f263fc3f6b5cff269ab23ee540773751f839faeb643fbfbe03ca48d59f36c336562cd42bd6d9e30926e0f2f4fd8beb605c55b5cfbda073c1cfd0f939f61fbeab37cdae6883bd5c15ced63f0d3d57668bf0fce43da9835cf765326d62cd4dbee0923e9b09fa2ad0a18b7333106166360c507791678c633cb339ea99ef14cf48ca7da339ea59ef1747bc6d3e519cf42cf78167bc633db339e82673cd33ce359ee19cf24cf78da3de3a9f18c6799673ca779c6b3d2339e399ef13478c6b3c4339eac673ce33ce369f28ca7c7339e0ecf78e67ac6d3ea19cf74cf789a3de3a9f38c27e7194fad673c3b3ce399e719cf0ccf784ef08c67b2673ce33de3e9f48c67be673c6d9ef1ccf48ca7c5339e299ef1d47bc633c1339e459ef1643ce0c906cf5d379085bfef005d95f55d7d7dd9d030fc779aa7ad82eff49b72b5e3d87da0a379dd7ec777314e5c73cf68ab17f6c95e1d70f47bc2b3c8339e099ef1d47bc633c5339e16cf78667ac6d3e619cf7ccf783a3de319ef19cf64cf784ef08c6786673cf33ce3d9e1194fad673c39cf78ea3ce369f68c67ba673cad9ef1ccf58ca7c3339e1ecf789a3ce319e7194fd6339e259ef13478c633c7339e959ef19ce619cf32cf786a3ce369f78c6792673ccb3de399e6194fc1339ed99ef12cf68c67a1673c5d9ef1747bc6b3d4339e6acf78267ac633d5339e599ef12cf08ca7cac1b3838927ead9dd1d9ed866380f797ddcfd4c3e5d618e556b8e4bfc64af06ead49b81473ddf80df252e7bbe1dc796af801871bd372167f1d0febe316e7bb2657b7285d8aeb76cd757886dc973c9f34ab02d792e795e09b625cf25cf7db4fd6c72b6db31cfaac0960feba3e5fd49f13cf2fea4789e6acf78e4fd49f13cf2fea4781e797f523c8fbc3f299e47de9f14cf23ef4f8ae7f1edf978799f533c8fbccf299e47dee714cf23ef738ae769f28c47dee714cf23ef738ae791f739c5f3d479c693f38cc7b7f739c9fb93e279e4fd49f13cf2fea4781e797f523c8fbc3f299e47de9f14cf33c1339e459ef1643ce079bef727e17b8f68ade53ed0d17aceb8f72c65e13857808ec607e918fa7a7576c37319aae03b573ab8f63bec919d2b1ddf1d8db8a3ad5ed8277bf83ea62b3de159e419cf04cf78ea3de399e2194f8b673c333de369f38c67be673c9d9ef18cf78c67b2673c2778c633c3339e799ef1d47ac693f38ca7ce339e66cf78a67bc6d3ea19cf5ccf783a3ce3e9f18ca7c9339e719ef1643de359e2194f83673c733ce359e919cf699ef12cf38c6787673c359ef1b47bc633c9339ee59ef14cf38ca7e019cf6ccf78167bc6b3d0339e2ecf78ba3de359ea194fb5673c133de399ea19cf2ccf781678c653e5e0e17a27522e18de7a617f34dec7f47cb6f5fe52888bdeb2f0f7d1784e7287c548fbb8ce0079896729134fd473ef4b3db0adfda7df5a34679185bfe373385c39b5d462a47d574ee13ac2654c3c51cfeb2ff3c0b68e459329d31c7716fede048c5c39b5cc62a47d574ed5f3f2b465c167dae2d6f6609be338874c7ee6b1fd25f88e88bc8ed5762b564d56ac725067349e138cea0fc89e300b7314b3e6a1b11662c5ebd9683c273d1246d7f5958127ec1f9707c55b5cffb81d7838ae1f4c7e86fdd801cba7e58eb8531dccd5030c7ebada0eed1f70d86e0c928dc5552388c5550e9eab46391664af54e61d2964f621ce9a87d64e102bae276ef68491744b7979c2feb13928dee2fac7ab8087e3fac1e467d8275c6df9d4ec883bd5c1f67535839faeb643fb57c3792885f9400a9925cee5316b1e5a534dac59a8d7e20923e9b6b3f214f259f099b6b87eec6ae0e1e8e799e21ef663072d9f5a1c71a73ad8be0e32f8e96a3bb47f10ce83300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb330fbcdac79e8591562cd42bd82278ca4bb8a956768dea110146f71f30e078187635e8629eee1bcc321cba78223ee540773f510839faeb643fb87e03c08b3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3dfcc9a87dee94aac59a8d7ea0923e9aee6e5099fdb6a0d8ab7b8798743c0c3312fc3e46738ef70d8f2a9d51177aa83b97a98c14f57dba1fdc3701e8459985dcc9a87feaf0762cd42bd364f18497790956768feb42d28dee2fab1c3c0c3d1cf33c53decc7062c9fda1c71a73a98ab030c7ebada0eed0fc0792885f9400a9925ce12e7286689b3c4398a59e22c718e6296384b9ca39825ce12e7286689b3c4398a59e22c718e6296384b9ca39825ce12e728668973e5c459f3d0ff5145ac59a8d7ee0923e90eb1f2b486f30eed41f11637ef30003c1cf3324c710fe71d8e583eb53be24e75b07d1d61f0d3d57668ff089c87b1ce7c2085cc921ba3c32cb921cc51cc921bc21cc52cb921cc51cc921bc21cc52cb921cc51cc921bc21cc52cb921cc51cc921bc21cc52cb921cc51cc921bc21cc52cb921cc51cc921bc21cc52cb921cc51cc921bc21cc5ec436e689e0e5326d62cd4ebf0849174877979c2f71e7404c55bdcba9d23c033c0101f263fc3753bd7583e7538e24e75b07d5dc3e0a7abedd0fe35701e8459985dcc9aa7d39489350bf53a3d6124dd002f4f210b3ed316d78f5d033c1cfd3c939f613f76d4f2a9d31177aa83b97a94c14f57dba1fda3701ed2c6ac79ba4c9958b350afcb1346d2e175b98b892767f1e41cb1385eb6f57eb729d799cf2cfcbd1b18b9fac32e8b91f631c7919778ba9978265b3c931db1385eb6b5ff2b4df904f39985bfaf0446ae9ceab61869df955393816725134fbdc553ef88c5f1b2ad63d163ca53cc6716fede038c5c39b5d262a47d574ed5034f0f134f549fd4330ab6a3dad768d88eca95d1b02d318f8e3943bb0bc7077a82e22deebe1aaf2d1c7d15939f79d7f5bbc7f209afdf788f7abcae4fc22ccc51cc4cf7b96d59cb36c527b07868bb863916a3f93bbbdbf2290dbfb3e3980fa49059e25c1eb3b67d2c79db6d59cb36c527b078683bc61c0b263fc3fe603070c798ece5a00ee6e920839f19b04bc7a6fd41380fa5301f4821b3c4b93c666dfbdac46d0fbd7f186d537c028b87b66b9963c1e3e7507f705de08e31d9cb411dccd3eb18fccc805d3a36ed5f07e74198855998855998855998855998855998855998855998855998855998855998fd66d6b6af4fdcf6d0f83ddaa6f804160f6dd733c782c7cfa1f1fb1b02778cc95e0eeae039bf81c1cf0cd8a563d3fe0d701e84599885599885599885599885599885599885599885599885599885599885d96f666dfbc6e46d87cfe3a06d8a4f60f1d07623732c98fc0cc7ef6f0adc31267b39a883e7fc26063f3360978e4dfb37c17910666176316bdb37276e7b683e0f6d537c028b87b69b9963c1e3e7507f704be08e31d9cb411d3ce7b730f89901bb746cdabf05ce4329cc0752c82c71963847314b9c25ce51cc1267897314b3c459e21cc52c71963847314b9c25ce51cc1267897314b3c459e21cc52c71963847314b9c2b27cedaf6ad89db6e0dc7efd136c527b07868bb9539163c7e0e8ddfdf16b8634cf6725007f3f436063f3360978e4dfbb7c17918ebcc0752c82cb9313acc921bc21cc52cb921cc51cc921bc21cc52cb921cc51cc921bc21cc52cb921cc51cc921bc21cc52cb921cc51cc921bc21cc52cb921cc51cc921bc21cc52cb921cc51cc921bc21cc52cb921cc51cc3ee486b67d7bf2b6c3e7d9d136c527b07868bb9d39164c7e86eb5fee08dc31267b39a883797a07839f19b04bc7a6fd3be03cdc21ccc2ec60d6b6ef4cde76216bd9a6f804160f6d7732c782c9cfb03fb82b70c798ece5a00e9ef3bb18fccc805d3a36eddf05e7216dcc78fe32c9d90ed76d928d2af3a9752f36e56ad0bdc4946b40f752531e07ba9799722de85e6ecae3417737f846ba5798f212d0bdd2947b40778f29af04ddab4cb91b74f79a7217e85e6dcad780ee35a67c1474f799f231d0bdd6940741f73a53be1674af37e5eb40f70653be1e746f34e51b40f72653be11746f36e59b40f71653be19746f35e55b40f73653be1574f79bf26da07bbb29df0eba7798f21da07bc0947780ee41539e08ba874c7912e8fe03caf4f94e53ae03ddbb4c3907ba779bf209a07b8f294f06dd7b4d790ae8de67caf5a07bd894a782eefda63c0d741f30e506d07dd094a783ee11539e01ba0f99f24cd07dd8946781ee23a63c1b741f35e539a0fb9829cf05ddc74d791ee83e61caf341f749535e00ba4f99f242d07dda94f1fc7ec694ef041df51777818efa8b17838efa8b97808efa8b97828efa8b97818efa8b97838efa8bbb414779f70ad051debd12749477f7808ef2ee55a0a3bcbb17749477af061de5dd6b404779771fe828ef5e0b3acabbd7818ef2eef5a0a3bc7b03e828efde083acabb37818ef2eecda0a3bc7b0be828efde0a3acabbb7818ef2ee7ed051debd1d749477ef001de5dd03a0a3bc7b10748da6fc10e84e3465ec3f4e32e57782ee64537e17e84e31e57783ee54537e0fe85e64caef05dd69a6fc3ed02d32e58741b7d894df0f3aba867d00744b4df983a05b66ca8f80aec9943f04bae5a6fc61d0359bf247409737e58f82aec5943f06ba82297f1c74ada6fc09d0b599f22741d76eca9f025d87297f1a749da64cfd876ea7babd91cf148f3af0afc9c14dba09c0dd1b247b0f46b6e8d8b45f00468a77cbe8331646ca98b718354f1b43cc3087688bfb8dd3063cad0c3c4c7e86bf71da2d9f0a964f39a8f322f0b39dc1cf0cd8a563d37e3bd8e638e7188b5a73dcd3ac58d4409d59e6e2a5af937171a463e8fc6d71f8c215c7bcc59377d8ee628e231d9bfac4ae51b0dd61d96eb66c63bf4f5b5cdbee00e64e06667ddceee48f1bb6ed15e65894cf64a7197c5a093148ca27b49d314276485f03e5e686e1ba548fe241d74e62d7ed88ce25b2dbdf6bb3be97833a5d0eff7b8364fdefb678ba2d66fd3be19486610e86f610e64097c541fbcd10bbee88d87541eca80e5e7bf34cb1ebb478683f0f3c747fd50e3aba4f217ebc9f6b1a056ebbdf6b777093ae0318f30ec6e6e4190b71d7856660245d27f07430c5cc3ed7a759f1c17b82f1561dfa6e0dd45907d7e5aca3ae6e77f332c37ed1effa678364fbf45a8678e1984300f109ac18d2460c1382e1718924792605c3e30ec706078eeeb9a2ff9cfe3d7d1940abb130f133e370a30a7458ae76e882a0787805876f697805876fabacb0e0b00ed5d73fe3b45b3484d17fe8c0e0f987fb0fef3b7ae391c1febe6d035720f5388b1e49a33c4052d4d13621181e08ea0d929db8a9b56cc525cf04f81c9f3c4f0b939fe1456fa2e553ade5530eea8c83bf4d64f0330376e9d8b43fd1613bc18e288cc5a411c462928367d228c70207d349872d95fe8e132d55962fd8a2d1273bcf1375880c9e0ac7cf1838fd37ddd8c71967c607c3279b7a4f7d47ab4f821e85d5572d3dcaaa47557517a4474df5054d8f8aea51503deaa94739f5a8a61ec5d4a3967a94528f4aea51483dead8180c8d2aea51443d6a780a703d0aacfad7bcbe3aea513f3dcaa747f5f45d95feb5a6ef44f49db7be2bd07703faae4fffa2d5a31bfa4aabef62f4155a5f55f55da2be3bd477f3faee56cf66ad52b25ac9e926d66b949ca164ad92754ad62bd9a064a3924d4a362bd9a264ab926d4ab62b3953c959c1d068fdd94ace5172ae92f3949cafe40225172ab948c94e25172bb944c9a54a7629b94cc9e54a762bd9a364af927d4afa94f42bd9afe40a255706432b78ae5272b592834a0e2939ac6440c9916068464dcfa0e919333d43a667c4f40c989ef1d2335c7a464bcf60e9192b3d43a567a4f40c949e71ba23189a5dd0b3097af640cf16e8d9013d1ba047ffef0e8646f7f568fe3dc1d068bd1e9dd7a3f17af45d8fb6ebd1753d9aae47cff568b91e1dd7a3e17af45b8f76ebd16d3d9aad47aff568b51e9dd6a3d17af4f9a1606874598f26ebd1633d5aac4787f568b01efd7d38181addd5a3b97af4568fd6ead1593d1aab475ff568ab1e5dd5a3a97af4548f96ead1513d1aaa473f3fabe4734a3eafe40b4abea8e44b4abeace42b4abeaae46b4abeaee41b4abea9e45b4abeade43bc1504e7e57c9f7947c5fc90f94fc50c98f94fc58c94f94fc54c9cf94fc5cc92f94fc52c9af94fc5ac96f943ca6e4b74a7ea7e4f74a1e57f207257f54f284922795fc49c99f95fc45c9534afeaae46f4a9e56f27725ff50f24f25cf04c3b324d871d498de8646ecf70c0ef61f3a32d83838d078e8da8383078e1cbcb1f1fa038357360e5cd77f74ffc181ebf1cb5f375fa6e98835478feeb9b1f1c0e1befe1b1a07ae1d6c1cd8dfb877e0dac37dc7f04b4f982fcd7baec53d7d7dd1c6fef38590fe779946ab4d3f48133d9be37dabad2e232075e57c295f5d9e437973a5a1d9f97387ee701b8f1d1c186ccc371e56ffee39a8bed3dfb7bc11ff764c05f9d860e3b1c13d47071bf71f1d38d4d8b21c8f3ba5ae0c27663694f1a5b50d23f73cf87f8198955c01d50300", + "bytecode": "0x1f8b08000000000000ffed9d67741cc791c76701100ccb2508e64c28514c00178b44800994c41c642a8b4a044950224512140925cbb224cb39e71c64fb9c73b6efcebe6cdff97c3e873b6739e7f8e5fceeeedd7b7a573de832fe68f5acb0f014d483ad79afb83d85dea95fd554f7cc76f70c73d1d0f607929c2dd7925c103d7ee3bff7dacfe29fb7b5a678aca224672e239c3519e1accd08675d4638276584b33e239c9333c23925239c5353e4346c35d1c82d6dde6902714d9b319fb1984ecf404c0b198be98c0cc4b421ca461f3533239c8d19e19c9511ced919e19c9311ceb919e19c9711cef919e15c9011ce8519e15c9411cec519e15c9211cea519e15c9611cee519e16cca08e77919e13c3f239c176484f3c28c705e9422e71ae05c613f2fb69f2bede72afbb9da7ef277d6dacf66eb639ddd6f215967d8485a9dbf9548da48da493a9cbf75927491ac27e9b67f6bb27feb21d940b2916413c966922d360e5b492e21b994e432926d24db497690ec24d945b29b640fc95e927d24fb492e27790ac901922b48ae24b98ae46a926b48ae25b98ee47a87e520c90d243792dc447233c92d248748fa480e931c21394ad24f728ce45692db488e939c20b99de424c92992d32403246748ee20394b728e6490e44e92bb48ee26b987e45e27664f25b98fe46924f73b9c4f277980e4419287489e41f230c933499e45f26c92e7903c97e47924cf277901c90b495e44f262929790bc94e465242f277905c92b495e45f26a92d790bc96e47524af277903c91b49de6459b821bc99e42d248f90bc95e46d246f27f90b927790bc93e45d24ef26790fc97b49de47f27e920f907c90e443241f26f908c947493e46f271924f907c92e453249f26f90cc95f92fc15c95f937c96e473247f43f2b7247f47f2f724ff40f28f24ff44f279922f90fc33c9bf907c91e45f49be44f26f4eccbf4cf2ef245f21f9aad57dcd7e7eddd6e571b1ff20f94f5bfe86fdfca6fdfc96fdfcb6f39def907cd7d17d8fe45147f77d921fd8f20fede78fece78fede74fece74fede7cfece7cfede72fece72fede7afece7afede76fece76fede7efece7efeda799537d68ce50794a34bcf54629f551edc78a664e8583bf221ab99958d4dabff16793d5d7d97dfee4d84db2fb931c7dbdddaf778e33c5ee4f71f48d76bfd1d1cfb6fbb31dfd5cbb3fd7d1cfb7fbf31dfd8576ff42d0e7231873b57aa3abb5aa1ce8385f6b4037c9ea6a4157cf8703dd64ab9b043a3ebff5a09b6a75934137cdeaa6802e6f7553399624d3adae374a2b578a7de6b885b48f6be7a166a4cf7bc41cb741887766fabcfde6b88d02bc263f66d963cd84bc996d758da0b3dd4d340b7473ad6e36e8e659dd1cd0cdb7bab9a05b6075f340b7d0eae6836e91d52d00dd62ab5b08ba2556b708744bad6e31e89659dd12d02db7baa5a06bb2ba65a03bcfea9683ee7cab6b021daf71390f74175addf9a0bbc8ea2e001df7b517828eef0d2fb23ad34f4cc9c177ac9efba8f83bdc3f836e25f7cda05bc5fd32e856739f0cba35609b756ba15f615db3d5711f65fed663cbbd515a6da214b7890d691f978e6c8ebb29fde3c6f3769ba3e1b8f6829d0d10ab2db69ce2daa056b49db3c276585f07e55d5097eb713cf83ac3ece67ab2d196b794f95e8ff3bd02d4d9e8f1bf374ad7ff4d0ecf26877912f82f93b36d25cdd9516f15e7ecb550d7cd3dbee7998839bb17380472b6537376d45bc539db0f75dddce3fbde8998b30781432067fb6472b654d49c1d1a238b227feef16f9f8998b3b70147fa39dba1393bfaade29c7d08eabab9c7bf7f2762cede051ce9e76c579fde1b8c7aab38675f0275dddce3b1988998b3cf040e819cedd77e76d45bc539fb26a8ebe61e8f0b4ec49c7d3970a49fb3dd4239dba6391b0dcd7746913ff7788c7a22e6ec23c0917ece1ed1f1d9d16f15e7ec67a0ae9b7b3c5f321173f683b66ce619be66e7199680eeeb56b71478d3cfeda3ed42b95dd2dc1e5a071245fe1ce5b9bb8998db9fb36593c7df80b507acfba6d59d07ba6f59ddf9a0fbb6d55d007e09b4813e6d03a3de2a6e03df85ba6e2ef33cf2446c035f010e819c3da2393beaade29cfd15d475738fd7344cc49cfd3e7008e46cbfe6eca8b78a73f6bfa1ae9b7b2b6d7922e62caf2b35f70b3fb4f70bab41f723ab5b03ba1f5bdd5ad0fdc4ea9a41f753ab6b01ddcfac6e1de87e6e7545d0fdc2ea5a41f74bab2b81ee5756d706ba5f5b5d3be87e63751da0fbadd57582ee7756d705badf5bdd7ad0fdc1eabaadcecc77f1daab2f5a9d39b71c8fde28bd731bafb78a466e3967bf17cacdb23cc54234f25904b6b52e7d5b6dc6f79668f4beaf039ea280ef79b0311a9e22f0b4a6cf13af3b2da57fdcf81cb73831cd83ad16f0ab4dc0af1cd8e263f33edb2b800efb92360f637bfa8ca51cd8e263f37e3b30b20efb36bec670fb317d73536e9857a02dc5d767b4d70b1c6caf0eea2c9d335cf742cb361dfece7dc0742863dfdfeae8847235ce15b6c5c7e6fd1230b28fade3cf581a2d63d16194ea3772608b8fedda9eee898f8959bb27661d428ced0e23ef770023c7af7dfc194ba36574fb05a13ea975b47d12c7a575fc6336aaf35a001ddeff7578183bd3678ccf6b87c3c8fb9dc0c8ba36e091ba1e26b5d7506c4bdc87603ef3358baf3f6caf0eea74d50ed7dd0bd753813eb454e9bd29f6e9e99fa75211af67a3e1113e77ad42f958c4bef3b128dd5c73db7cab132b6cf3d8974bf593497d39db53666556666556666556666556666556666556666556666556666556666556e6f09993e6e57ceb199e4c46d6958047629c3f7e47953d16ce013d0af33ae9cf5b948a3857cfeb1857393ed7419dffcb0db3fdc8b34e02e7ced7393aa1754af1b9c4754abdb0cff670dd06ae9b12587b12f3ac75785cdbd33df109711d49486b3492d6698514b302e8703d5c8b104f529eb5786c37a566bb7444a6ed948ae67d40e69d7adc9fb86d04d7bead7174a64feaa91df65b22072a9d77c6eb0697d39cc7c57c435be9afb7298d589f50138dbc56e03d85c01a9511f3d5bc36a2d3b15d0775a6d6447f3a37ebe1efbdd1e3d708993a5dceb1f93babe0bb5dceb11be4fc2ddb1f76023797eb1ddf9a819bebcca819f6f1b3b62c743f53c2f5b311f0468e4fbce1fa8cf4eff786d68bb455c0d3013c126bd784ee6b8b988f69af17e97262e5bb5fe63a9d10bf2e81f8955bb3c6f694599995599995599995599995599995599995599995599995599995599995397c667cff05b3e233d2a54018c7698d4d3c9fc1ef32c279b1b7d40cdb959e03e439a7d58ecff88cf26f6b86d9de6ecbf88e00dff3ee782ea5e6d692ce25db9b1e3dfe397da17339ea773f747862d6e589d97a2146b7cfe0fdf5c0c8f1eb021ea9f6d8e9f0b8b6b1cfe808346649fdacd4fa95a43cf3ad53684acdf6d07a1189795d5e2fe25ebf4a4e4c719d04eb701e1cdfad12f2fb5fdcb50bd84fe11aadf4fbcdd288396077ad20dbc375125fb0b1e57512e9f703a5a2e43582db28af0969f3f8ca75be04d7b92fdb32ae152ac1b11ef5fc9db7726b12b04f4dfd1d9cc5a1397e7e77259fdf1e8fed8dc09a92ed56b49db3c276585f07e5efd50cd7e57a1c0f8e35b39b36c2ef324476f77badcef70a50a7dbe37f6f94aeff3d0e4f8fc36c72e7ab90678fc2bd9e549fd49d10a3551023ae83f7bc52d72f77cdb6bb5619fbd1c94e1dfe6e1dd4f919f45195bc2b4aea7e21e91a80f70bee7561346bc7ab7d3de01fa1bf487b3de01f21877cf7a57cfcd5707ce69a1c255f5bb8ceff3ad75181f57aa37aef95efb71ff3e27a43aef318f45545bb2e37e9778cef390ba9df0d49cf7db03dbca7aac477ec17d2be36623e220be6f29faed136d69c8f5d09dceb3cdfcd277c9763c5ebcbf177b21b3f13876ef84e6f2a7118ea6f7a1c5fb84d75832f5ca7117c91b9671abaff4cdfd791f743dc07b57b7ce53af3e05d700b6c390fe709fbca8b3d7fe7addcfd27c7cff83cdeef5447db21bc537d45ed705df7dde81ceb4adfa9dee97c2fc477aa2f863cbb189eb590eaab3726c46835c488ebe0b38eeeefffa46bcc93f95e52b7dfc4ebe478b2b9e3b7befb13ae83f7d05ca703fad9bca7ae3b2ecdd79034d7a7e3f3406bc12e3e0fb456289e8568643c0b0e87a4ed06c776c338da6e746c378ea36d8db9c63ca4980bfcdf1363febf30f0ffaca8c900636d0618eb32c03829038cf519609c9c01c62919609c9a01c6691960cc03e393796d17884f29b0ffefa9ecbd06da16789f431c8be668f4b16891e5297bef83b605dea152f1ff3720fc7f61b58ef5ffc22ac0f766658071760618e76480716e0618e76580717e0618176480716106181765807171061897648071690618976580717906189b32c0785e0618cfcf00e3051960bc30038c176580718532a6c2b84696b114daffe39c8f46ae357b221ee1778fc6ef50f4bde754e2ffc6add477e1f70eb78ef53d7db8c642f6ff7afcf3de2528b186a2d2770996fbffb185184b6365945a4b8eeba847c383cfa1fa9e6f11602c8d9551ea19147c2672343cbeffab57f699a0a1988d85516acd58a56b1af159c14e4fcc04184b6365947aee009f891c0d8fefd9c55659c6d25819a5d6e7e6c1c66878ba2166eb3d3113602c8d9551e8f9b23866dd15f0e07358dd9e98093096c6ca68783608c5aca7029e0d10b31e4fcc4262449eb4df89dee3b125f1dc5ea5be3303324ecd00e3b40c30e23a0989feabdc3a891ed9f894c61a1fa9f3556e9d04da16784e248e053e17f044b1d824cb53769d04dade2c140b7c6ee38962b11978249e23c9838dd1f0304301be372b038cb333c03827038c7333c0382f038cf333c0b820038c0b33c0b828038c8b33c0b824038c4b33c0b82c038ccb33c088bf5505ee15cbfe7ed93cc16d27fd5699e8b6937e974c74db9ae79ae7d5605bf35cf3bc1a6c6b9e6b9e57836dcd73cdf36ab0ad79ae795e0db635cf35cfabc1b6e6b9e67948b6b330c6af8c138f11799ad2e329a2ef68ab3700df7b3d3c3921dfd1d6d6007c6786ac316ec900e3860c306a1c87d6208e85d1f05c22c4b3b5029e4b80e752219e4b2ae0b914782e4b9f27cea94b2be06186027c6f430618b7648051e3a8710c8951e3583d715446655446657c3218b3d0872b6326f2b1345646c3b32d7d9e38669755c0b30d62c6df6b95652c8d95d1f06c4f9f278ed9b60a78b643ccb6796226c0581a2ba3e1d9913e4f1cb3ed15f0ec80986df7c44c80b1345646c3b3337d9e38663b2ae0d90931dbe18999006369ac8c866757fa3c71cc7656c0b30b62b6d3133301c6d258190dcfeef479e298edaa806737c46c972766028ca5b1321a9e3de9f3c431db5d01cf1e88d96e4fcc04184b6365343c7bd3e78963b6a7029ebd10b33d9e98093096c6ca6878f6a5cf13c76c6f053cfb20667b3d310b9571430618b7648051388ea5b1321a9efd423cfb2ae0d90f3c970bf1ecaf80e772e0794afa3c714e5d5e010f3314e07b1b32c0b825038c1a478d63488c1ac7ea89a3322aa33256c6d89b01463dd7ca182aa3c0efabb2cfd05c3ec16d3738b61baac476d2333413ddb6e6b9e67935d8d63cd73caf06db9ae79ae7d5605bf35cf3bc1a6c6b9e6b9e57836dcd73cdf36ab0ad79ae795e0db635cf35cfabc1b6e6b9e67935d8d63cd73caf06db9ae79ae7d5605bf35cf3bc1a6c6b9e6b9e57836dcd73cdf36ab0ad79ae795e0db635cf35cfabc1b6e6b9e67935d8d63cd73caf06db9ae79ae721d93e90beed52a5cfb01e001e89676a85fc2c9ae35e618ff5588af133b1bad289d5e54eac0a50e70a88df9502f1cb815d3e36efb3bd4a992f0e8059c87669061d632af8cf36b638f130f6af12f23da9afbf6a82db4eeaeb27baeda4be7ea2dbd63cd73caf06db9ae79ae7d5605bf35cf33c14db58ae8b86efdbf9fd4ae61857dbf224bb8facfc3daeb369f2d06743a46d48c2b6b621bd5654836dcd73cdf36ab0ad79ae795e0db635cfc3ccf36bd2b71dcf8de1ef0bb3959b1bbb0678ae168885909f45e3d3b58e4f57393e15a00ebeb3f65a013f7360978fcdfbd7c279c81ab3e1d96ccbcc9a877a9b036164ddd5b23c71fbda1c8ddccab5af6b8147a01db40af919b7afeb1c9f367be2ce753057af13f0d3d77678ff3a380f5963363c5b6d9959f3506f6b208cacbb4696276e5f5ba3915bb9f6751df048f43f427ec6edeb7ac7a7ad9eb8731dccd5eb05fcf4b51ddebf1ece43d6980dcf25b6ccac79a87749208cacbb5696a73d0f3ef356ae7d5d0f3c12fd8f909f71fb3ae8f8748927ee5c0773f5a0809fbeb6c3fb07e13c28b332fb980d0fff9ff2cc9a877a9706c2c8baeb4479da8b79f099b772fdd841e091e8e785e21ef76337383e5dea893bd7c15cbd41c04f5fdbe1fd1be03c54c2bc2583cc1a678d7312b3c659e39cc4ac71d63827316b9c35ce49cc1a678d7312b3c659e39cc4ac71d63827316b9c35ce49cc1a678d7312b3c659e39cc4ac71d63827316b9c35ce49cc1a678d7312b3c659e39cc4ac71d63827316b9c35ce49cc1a678d7312b3c659e39cc4ac71d63827316b9c35ce49cc1ae7b1311b9ecb6c9959f350efb240185977bd2c4ffcfcce65d1c82de7ecf742f906e03928101f213fe375ef373a3e5de6893bd7c1f675a3809fbeb6c3fb37c279a884794b069935ce6363363cdb6c9959f3506f5b208cac3b28cb13f763dba2915bb97eec46e091e8e785fc8cfbb19b1c9fb679e2ce75b07ddd24e0a7afedf0fe4d701e9459997dcc8667bb2d336b1eea6d0f8491753788f294e2e710b74723b772fdd84dc023d1cf0bc53deec76e767cdaee893bd7c15cbd59c04f5fdbe1fd9be13c54c2bc2583cc1a678d7312b3c659e39cc4ac71d63827316b9c35ce49cc1a678d7312b3c659e39cc4ac71d63827316b9c35ce49cc1a678d7312b3c6b97ae26c7876d832b3e6a1de8e40185977a3284f5b3cefb0231ab9959b77b8197824e66584e21ecf3bdce2f8b4c31377ae83edeb16013f7d6d87f76f81f330d199b764905973637c98353794398959734399939835379439895973439993983537943989597343999398353794398959734399939835379439895973439993983537943989597343999398353794398959734399939843c88d02c94e5b66d63cd4db190823eb6e92e589df7bb0331ab9955bb7730bf0dc2c101f213fe3753b871c9f767ae2ce75b07d1d12f0d3d77678ff109c8743caaccc1e66c3b3cb9699350ff57605c2c8ba9b6579e27e6c5734722bd78f1d021e897e5ec8cfb81feb737cdae5893bd7c15ced13f0d3d776789fed29b33227311b9eddb6ccac79a8b73b1046d6dd22cb13f763bba3915bb97eac0f780e09c447c8cfb81f3becf8b4db1377ae83b97a58c04f5fdbe1fdc3701e9459997dcc86678f2d336b1eeaed098491758764794a79f099b772fdd861e091e8e785fc8cfbb1238e4f7b3c71e73a98ab4704fcf4b51dde3f02e7216bcc8667af2d336b1eeaed0d8491757db23c71fbda1b8ddccab5af23c023d1ff08f919b7afa38e4f7b3d71e73a98ab4705fcf4b51dde3f0ae7216bcc86679f2d336b1eeaed0b849175876579e2f6b52f1ab9956b5f478147a2ff11f2336e5ffd8e4ffb3c71e73a98abfd027efada0eeff7c379c81ab3e1d96fcbcc9a877afb0361641df653bcd500e37e21c6c8618c9cf820cfb2c0780e04c6b320309e5981f14c0d8c6755603cb581f1ac0f8ca723309e52603ccb03e3591818cfecc078a605c6b336309ebac0785604c6b33a309e4581f1cc098c271f184f73603c9302e3e9098ca73b309e9581f17406c6d31618cfbac0781607c63337309e3581f14c0f8ca710184f4b603cf581f16c0c8c6749603cf302e39911184f43603c9303e3d914184f57603ced81f11403e3591a18cffcc0786606c6d31818cf94c0787201f0e4a3c7af63c8c3df0f80aec6f9aeb9be1c9e33fc779e37ae81ef1cb3e55acfb1fb41c7f3ccc73cdfc53849cd85a3ad5ed8677bd381e358203c5302e3690c8c6766603cf303e3591a184f31309ef6c078ba02e3d91418cfe4c0781a02e3991118cfbcc0789604c6b331309efac0785a02e32904c6333d309e3581f1cc0d8c6771603ceb02e3690b8ca733309e9581f17407c6d31318cfa4c0789a03e3c907c63327309e4581f1ac0e8c6745603c7581f1ac0d8c675a603cb303e3591818cff2c0784a81f17404c6b33e309edac0785605c63335309e5981f12c088ce740603ccb02e3a9f1f01c10e2497ab6f94020b605ce43d11cf756219f6eb3c7aab7c7657eb65707752eb0038f66fe03bfcb5ceefc3fb69ddb204652ef9528383cbc7f7482db6e706c375489ed46c7766395d8d63cd73caf06db9ae79ae7d5605bf35cf33c44db8fa567bb43df2f357a1e7d9f53791e7d9f53791e7d9f53791e7d9f53791e7d9f53791e7d9f53791e7d9f53799e1581f1e8fb9ccaf3e8fb9ccaf33407c63329301e7d9f53799e9581f1e8fb9ccaf3e8fb9ccaf3e8fb9ccaf34c0f8c47dfe7549ea73e309ed0dee714dafbe0f5fd52e5796604c6a3ef972acfa3ef972acfa3ef972acfa3ef972acfa3ef972acf3325309e5c003c4ff47e297c2fd46db67c1474bcbeb4dc7ba8f2709cdb40c7e3b97c0c73bd3a35e7f10c35f09de31eae5b3df6d8ce71cf77c723ee68ab17f6d91ebeafea78203c5302e3690c8c6766603cf303e3591a184f31309ef6c078ba02e3d91418cfe4c0781a02e3991118cfbcc0789604c67320309e8d81f1d407c6d312184f21309ee981f1ac098c676e603c8b03e35917184f5b603c9d81f1ac0c8ca73b309e9ec0782605c6d31c184f3e309e3981f12c0a8c6775603c2b02e3a90b8c676d603cd302e3991d18cfc2c0789607c6530a8ca723309ef581f1d406c6b32a309ea981f1cc0a8c6741603ccb02e3a9f1f048bd332ae9f9faf1785fd513d936fb6b212e66cbc3dfc7e339ae030e23efe3ba07e4659eb5423c49ef05581b806de33fff169d613ff3f0777c0e472aa7d63a8cbcefcb295cd7d82cc493f43e83e6006c9b58b4d832af01c8c3df5b80512aa79a1d46def7e554a32c4f7b1e7ce6addc5a236c7312e750c8cf22b6bf14dfa15134b1daefc4aac5895501ea8cc7baf4a4fe80ed29b33227311b1e9e4b6156bc9e8dc77366a361f45d5f0578e2fe715d34722bd73fee071e89eb87909f713f76c2f1699d27ee5c0773f584809fbeb6c3fb273cb69ba2746371fb286271bb87e7f6718e05dbab94f94006994388b3e1e1b588cc8aeb9b8b8130b26ead2c4fdc3f16a3915bb9fef176e091b87e08f919f709271d9f8a9eb8731d6c5f2705fcf4b51dde3f09e7a112e6131964d6388f8dd9f0f01c04b3e6a15e291046d6ed17e52915f3e0336fe5fab193c023d1cf0bc53deec74e393e953c71e73ad8be4e09f8e96b3bbc7f0ace83322bb3322bb3322bb3322bb3322bb3322bb3322bb3322bb3322bb3322bb33287cd6c78f8d95866cd43bdb640185977bb28cfd0bc435b34722b37ef700a7824e66584e21ecf3b9c767c6af3c49deb60ae9e16f0d3d77678ff349c07655666655666655666655666655666655666655666655666655666655666650e9bd9f0f03bdb99350ff5da036164dd49599ef8b9adf668e4566edee134f09c12888f909ff1bcc380e353bb27ee5c07737540c04f5fdbe1fd01380fcaaccc3e66c3c3ef6a63d63cd4eb08849175a7447986e64f3ba2915bb97e6c007824fa79a1b8c7fdd819c7a70e4fdcb90ee6ea19013f7d6d87f7cfc079a884f944069935ce1ae724668db3c6398959e3ac714e62d6386b9c939835ce1ae724668db3c6398959e3ac714e62d6386b9c939835ce1ae724668df3f830871067c3c3ff8720b3e6a15e67208cac3b2dcad316cf3b744623b772f30e678047625e4628eef1bcc31d8e4f9d9eb8731d6c5f7708f8e96b3bbc7f079c8789ce7c2283cc9a1be3c3acb9a1cc49cc9a1bca9cc4acb9a1cc49cc9a1bca9cc4acb9a1cc49cc9a1bca9cc4acb9a1cc49cc9a1bca9cc4acb9a1cc49cc9a1bca9cc4acb9a1cc49cc9a1bca9cc4acb9a1cc49cc9a1bca9cc41c426e189e2e5b66d63cd4eb0a84917503b23cf17b0fbaa2915bb9753b7700cf1981f808f919afdb39ebf8d4e5893bd7c1f67556c04f5fdbe1fdb3701e9459997dcc8667bd2d336b1eeaad0f8491756764794a79f099b772fdd859e091e8e785fc8cfbb1738e4feb3d71e73a98abe704fcf4b51dde3f07e7216bcc86a7db9699350ff5ba0361641d5e97bb85780a0e4fc1138b27cbb6d9efb1e5e9f6330f7fef0146a9feb0db61e47dcc71e4659e1e219e0687a7c1138b27cbb6f17fa32dcfb09f79f8fb466094caa91e8791f77d39d5003c1b85781a1d9e464f2c9e2cdb26169b6c79a6fdccc3df3701a3544e6d741879df97538dc0b3498827a94fda340eb693dad778d84eca95f1b0ad314f8eb940bb8bc707364523b772f7d5786d91e8ab84fc2cfaaedf9b1c9ff0fa8df7a84fd6f5499995398959e83eb73defd8e6f8440e0f6f678563319ebfb37b1c9fb2f03bbb1cf3890c326b9cc7c66c6c0fa66fbb3defd8e6f8440e0f6f83c2b110f233ee0fee8cfc31667b05a883797aa7809f39b0cbc7e6fd3be13c54c27c2283cc1ae7b1311bdb77a56e7be8fdc3689be313393cbcdd251c0b193f87fa83bb237f8cd95e01ea609ede2de0670eecf2b179ff6e380fcaaccccaaccccaaccccaaccccaaccccaaccccaaccccaaccccaaccccaacccca1c36b3b17d4feab687c6efd136c727727878bb473816327e0e8ddfdf1bf963ccf60a5007cff9bd027ee6c02e1f9bf7ef85f3a0cccaaccccaaccccaaccccaaccccaaccccaaccccaaccccaaccccaaccccaaccc61331bdb4f4ddf76fc3c0edae6f8440e0f6f4f158e85909ff1f8fd7d913fc66caf0075f09cdf27e0670eecf2b179ff3e380fcaaccc3e6663fb69a9db1e9acf43db1c9fc8e1e1ed69c2b190f173a83fb83ff2c798ed15a00e9ef3fb05fccc815d3e36efdf0fe7a112e6131964d6386b9c939835ce1ae724668db3c6398959e3ac714e62d6386b9c939835ce1ae724668db3c6398959e3ac714e62d6386b9c939835ced5136763fbe9a9db6e8bc7efd136c7277278787bba702c64fc1c1abf7f20f2c798ed15a00ee6e903027ee6c02e1f9bf71f80f330d1994f64905973637c98353794398959734399939835379439895973439993983537943989597343999398353794398959734399939835379439895973439993983537943989597343999398353794398959734399939843c80d63fbc1f46dc7cfb3a36d8e4fe4f0f0f6a0702c84fc8cd7bf3c14f963ccf60a5007f3f421013f7360978fcdfb6c4f99953989d9d87e46fab64b79c736c7277278787b86702c84fc8cfb8387237f8cd95e01eae0397f58c0cf1cd8e563f3fec3701eb2c68ce72f979eed78dd26dba8b19f46f74c5bae05ddb36cb90e74cfb6e549a07b8e2dd783eeb9b63c1974cf03df58f77c5b5e03ba17d8f226d0bdd0963782ee45b6dc03ba17db7237e85e62cb6741f7525b3e07ba97d9f220e85e6ecb7782ee15b67c17e85e69cb7783ee55b67c0fe85e6dcbf782ee35b6fc54d0bdd696ef03ddeb6cf969a07bbd2ddf0fba37d8f2d341f7465b7e00746fb2e515a07bb347f7165b7e10748fd8f243a07bab2d1f00dddb6c792ae8de6ecbd340f71750e6cf77d8f274d0bdd3960ba07b972dcf00ddbb6db90174efb1e599a07baf2d3782ee7db63c0b74efb7e5d9a0fb802dcf01dd076d792ee83e64cbf340f7615b9e0fba8fd8f202d07dd4961782ee63b6bc08741fb7e5c5a0fb842d2f01dd276d7929e83e65cbcb40f7695b5e0ebacfd8329edfbfb4e567808efb958741c7fdca3341c7fdcab340c7fdcab341c7fdca7340c7fdca7341c7fdcaf340c779f77cd071debd00749c772f041de7dd8b40c779f762d071debd04749c772f051de7ddcb40c779f772d071debd02749c77af041de7ddab40c779f76ad071debd06749c77af051de7ddeb40c779f77ad071debd01749c776f041de7dd9b40c779f766d071debd05749c778f80aec996df0abaf36cf96da03bdf96df0eba0b6c19fb990b6df91da0bbc896df093aee0bdf05ba8b6df9dda05b69cbef01dd2a5b7e2fe856dbf2fb40b7c696df0fbab5b6fc01d035dbf20741d762cb1f02dd3a5bfe30e88ab6fc11d0b5daf2474157b2e58f81aecd963f0eba765bfe04e83a6cf993a0ebb4e54f81aecb963f0dbaf5b6fc19d0f1759cfb19d39e4dbbe438708c8c8e7d6ef1f8c2ba29e04b6f94ee3d1ddbe263f37e1b30f239288d3f6369b48cad0ea3e1e9108819e6156fe57e3375004fbb008f909ff16fa64ec7a736c7a702d4b918fcec14f0330776f9d8bcdf09b625ce39c6a2de1e77a5138b3aa8d36e2f72e67a5a2e8e7c0c93bf258f2f52716c75785a3db6bb85e3c8c7e63eb17b1c6c7739b68b8e6dbc16f056ae6d7701f37a016673dc9ef48f1bb7ed0df6589ccf6ca7083e6d8418a4e513dace59613bacaf83f29e39c375b91ec783af9dcc6eda119f4b6477bfd7e17caf0075ba3dfef746e9fadfe3f0f438cce6f744ef9c610e81f610e740b7c3c1fb45885d4f42ecba21765c07afbdcd42b15beff0f07e33f0f0fd5527e8f83e85f9f11eaf651cb8dd7eafd3c3cdba2e606cf63096d2678cefb39a1d46de2f0123ebd6034f9750ccdc73bdd2890fde134c76eaf077eba0ce21b82ee73d754dbb6bca0dfbc5bfff1f8bd2edd3eb05e285631311c4277262c81b334c8986c72fd2e499160d8f4f9c1b1c38db776bff15fd7d47738056e760e267cee3460de8b05cebd145d1c861181c0ee661181c0eae71c282c33f5cdffc8c336ef15047ffa9e383579fee3f7de4ecbd6706fb8fee1db815a92739f4489ae40192a28eb729d1f080516f94ee4450bd63ab5cf24c81cfc9e9f3b40af9195ff4a63a3ed53b3e15a0ce24f8db54013f7360978fcdfb533db653ec88e2584c1b452ca67978a68d732c70d09d75d852f9ef387153e3f8822d1a7d72f33c5587d8e00a387ecec299bf99c63ec93a33391a3ed9dc7b9a3b5a7312cc68adb96a99d15833fa6aba2033ba6a2e6866f4d48c969ad151331a6a463fcd68a719dd34a39966f4d28c569ad1c9a66868f4d18c369ad145339a7811b07d1178cd2f7a738534a38166f4cf8cf6993b2b730760ee46ccddb7b95334bf1ecd1d82f9556b4638ccd5d6dcc998abb4b9b29a3b45738768eee8cd1dae9921db4cb2c5c67a2bc9252497925c46b28d643bc90e929d24bb487693ec21d94bb28f643fc9e5244f898646f6af20b992e42a92ab49ae21b996e43a92eb490e92dc407223c94d243793dc427288a48fe430c91192a324fd24c7486e25b98de47834b42ae876929324a7484e930c909c21b9231a9aa533b3726616ceccba99593633ab6666d1ccac99992533b3626616cccc7a99592e33abf56034341b656622cccc83996930330b6626c1cc1c3c371a9a193033012f888646facdc8be19c93723f766a4de8ccc9b917833f26e46dacdc8ba19493723e766a4dc8c8c9b917033f26d46bacdc8b619c93623d78f444323d36624da8c3c9b916633b26c4692cdc8f1bba3a1916133126c467ecd48af19d93523b966e4d68cd49a915933126b465ecd48ab19593523a966e4d48c949a91513312fa57247f4df25992cf91fc0dc9df92fc1dc9df93fc03c93f92fc13c9e749be40f2cf24ff120de5e5bf927c89e4df48be4cf2ef245f21f92ac9d748be4ef21f24ff49f20d926f927c8be4db24df21f92ec9f7481e25f93ec90f487e48f223921f93fc84e4a7243f23f939c92f487e49f22b925f93fc86e4b724bf23f93dc91fa2e19915ec44a6d89e8747f9fb0607fb4f9d196c1a1c683a75e7c9c1e3674ededb74f7f1c1db9a06eeea3f7bece4c0ddf8e5cfdb2ff314c6d6b367fbee6d3a7efa68ff3d4d03770e360d1c6b3a3c70e7e9a3e7f04b3fb55f5af2788b7d478f261bfbaf3f87f47fc66874b2ed137972685779dfa6d58e212033c7f2a5f6dab139b4d15e75f8d7fb954377bb4de74e0e0c36159b4ed3bf7d27e93bfd475b9af06fe728c8e7069bce0df69d1d6c3a7676e054536b0b1ef7fce96370a26dce18be74cb9cd17b1efd3fc9de5641f9d90300", "isInternal": false } ], - "packedBytecode": "0x000000028df71de50000003e021f8b08000000000000ffed9d0774154796f75b4280f0d3b3088e045b3860c004e9492449c023679325030e801019e3210c382272c618b0c946e0999d4db339cfe69c739cd9303bb333bb3b3b73ce37bb5ffecef1f9aafad51dfd55543ff4e4aec77dd2ed734aaffaaabaefaffe7dab3a55777f270882a22033f550e9e9e0ee89fe9f36bf959f6eaa8a715d953e398b0a84b3b840387b140867498170f62c10ce5e05c2d9bb40384b0b84b34f8c9c9aad38683fc5cdfb80075de3664c1498a66505a069b2c0347db000342d0f0aa38fea5b209cfd0a84b37f81700e2810ce870a84f3e102e17ca440381f2d10cec70a84f3f102e11c58209c830a84737081700e2910ce270a84f3c902e1ac2810cea105c2f95481703e5d209ccf1408e7b331728e00ce61e6f739f33bdcfc529991e6f779f33bcafc8e36752c31f363541aabd954aab2fe9752a95aa51a95c659ff1bafd2049526aa34c9fcafc2fcaf56a53a95ea559aacd21495a61a1da6a9345da5192acd5469964ab3559aa3d25c95e6a9345fa5052a2d5469914a2fa8b458a5252a2d5569994acb555aa1d24a951a546a54e9459556592cab555aa3d24b2abdacd22b2abdaad25a95d6a9b45ea5269536a8d4acd2469536a9b459a52d2a6d55699b4adb55daa1d26b2aed54e975953ea3d22e9576abb447a5bd2a7d56a57d2aed57e90d4bb337557a4ba5b7557ac7e27c57a5032ab5a87450a5432a1d56e9884a47553aa6d271954ea87452a5532a9d56e98c4a67553aa7d27b2a9d57e97d952ea87451a54b2a7da0d2872a5d56e98a4a5755baa6d275956ea874d3b05043f848a55b2ab5aa745ba53b2a7dacd2e754fabc4adfa7d21754fa7e957e40a51f54e98754fa6195bea8d28fa8f4a32afd984a3faed24fa8f4932afd944a3fadd2cfa8f4b32afd9c4a3fafd22fa8f425957e51a55f52e99755fa15957e55a55f53e9d755fa0d957e53a5df52e9b755fa1d957e57a5df53e9f755fa0395fe50a53fb234ff6395fe44a53f55e9cfccffe83ad89fabf41726ff97e6f7afccef5f9bdfbfb196f95b95feceb27d59a5af58b6bf57e91f4cfe1fcdef3f99dfaf9adf7f36bf5f33bf5f37bfff627ebf617ebf697effd5fcfe9bf9fd77f3fb2df3fb1fe6f7dbe6f73b2add1c9cc997066d533a88a94faa696ed6f75048ec6141fb496bd1c3fc8f7e2b8cbdc4ccd32f69d7d3ccf7b4ecbdcc7c2f6b3da566bed4b2f733f3fd2cfb00333fc0b23f6ce61fb6ec8f9af947c19e08e05aaab16b5b0f632a021bc56131d87a06ed35d1b65eb43ab0f50eda6ba16db41d7b81ad8fb1f506db03c6560ab684b1f521cd542a33b67410574c54aed3eb4dc6bd5e737fe9c1f8799bf47acb3df1f68d9fb759afb79f075e1d1ffdcdbafa42dc0c30b67e607bc8d8fa83ed61631b00b6478ced21b03d6a6c0f83ed31637b046c8f1bdba3601b686c8f816d90b13d0e36d3ed0503c136c4d80681ed09631b0cb6278d6d08d82a8ced09b00d35b627c1f694b155808dc6ae0c05db33c6f614d89e35b6a7c1467dea3360a363be678d4df7133d8b601963a73e2a5c86fa61b00da73e186c23a8ff05db48ea7bc1f63cf826db28e857c836dad8a88fd2ff9b68f2e920ae36910adbc4a4b8d7abd6acd75b17ff7ac3fb71f5419bae69f03309b49a6cf2318ef9a942df4526911fb297407e2e94a572a407ed67885def4f6a4d7e7296e5265acb25a14cada3fee920defad7593c7516734fc8fb89d9ea94c46c87a79c63b601cadab147c73c5d316617008787981d2f31dbe129e798dd0065edd8a3e3deae18b3ab80c343ccaef313b3a94a89d9ccf5af2070c71e9dfb74c598dd041cf1c7ec3889d98e4f39c76c0b94b5638fce7fbb62ccee058ef86376c23a3936e8f09473cc9e83b276ecd1b598ae18b38781c343cc364b3fdbe129e798bd0165edd8a3eb825d3166df078ef8637692a798ad96980d32f73283c01d7b748dba2bc6ec2de0883f669be4fa6cc7a79c63f6e7a0ac1d7b74bfa42bc6ec178123fe98dde0ebfa6c4a623633862308dcb147f7eeba62cc7ec9e4f5bdb1bf34f7c69e00db5f19db9360fb6b187b40b6bf31b6a1502f0f6d60a2b4810e4f39b781bf85b2762c3f65f25db10dfc11707888d97512b31d9e728ed96f42593bf6684c43578cd9af008787986d9298edf09473ccfe77286bc71e8dafe98a314be343f5f1c23f9ae385e160fb27631b01b6af1adb48b0fdb3b13d0fb6af19db28b07dddd84683ed5f8c6d0cd8be616c63c1f64d63ab04dbbf1a5b15d8fecdd85260fb7763ab06dbb78cad066cff616ce3c0f66d631b0fb6ef18db0463d3f7b1684cd5ef1a5b2970a583f8b66d0234a0a9c89a4f43beca2f4f651278d05775fcbeaa75dd5341c7eb5e0d3c351eea9e001f1de1a9019e71f1f384e349c7c7bfde701ba72c4d13e02b05f59ae0a15e45e08bd64df3e42f09366cd3131c8cb1ef9fd57eb4087cd1ba697e2230920dfb18ea73a9fde8be7948511baf87b614ee9fd15f1a38c85f09941937b8adec50c35606ffc7fe769c65f31497615c902f5a37cd93bf32a8cfb8fc33a63aca586331faea238ac017addbf65d06f94abffa64e519cfc477ad27df769f469ad7e6c1f744cb77b5e51bfb4e9ab2eddb2602b387f394aafb719e82c70f1cce536616b595b5cf37a81fcef53c6582b51cc7f39449b02ff4d01ec218a8b53868be1ab4ab8bd0ae16b4a332cf8176befaf149160fcd8f031eeabfb13fabcc334f2503df780c4bdb0dcfa5f038c0d7f6aab41869deb5bd2602a3eb58c5c3f94cd663951a60241b5ec74979d22c6abba698f8f6102b617f443ee8d89cda2ff92b81320b7ab4955d0b7da58f18c178a4a9a3e7bcf16fa754780e5e93030f6e3b0fe755559ee2b112afdf7c12c41b6b76bf54636915758dc7575f9eb278689efc09b3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300b337f66bc9f84e3b6a8dc38268cf6f8375fd7f9c377ec9975e13da0ef7a1d0f96aac4b130340e628455e71228535edcc6f63f603c983d96286a5bfa181b9b6d5b923f1c0f968f7b88d5168fedbbcca10fde9746cd7c8d81b2fb0c9ac7f169a45f25f0f86a8f55168fed1bfb8c1453cda2fa595f630ba2e2cc359eb02236dfa9265ff775f5fbccf43b41edfdd7384bd3f05da3964df7492ff468abb78ffbbcb9de77c6fd06e5e3bc8f9b041ef4157f3f9b6a373ea13868bfafc058f735568bda158d8da8b57c97409921c56ddba60efe9f0eeede3760195a37cd8f8065ebac7597fbab6fd67128b5c04df95e56ddc6033795790af6dd7f66f29ef681a95c9f91c07d72fcfb97cc7891540e3cb8bff371cce2693f5a89f118f778117b1ca4eb7899cae018520fe377b3ee8bc99f300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb330f367d63cf63d74bcf75bcd84314f636cc2fb19f42e36bc2ff693c56d7e7ddf03a47b4e23ad3ae333ca013ca3fcb3860dc73ee07ba55cdbd2d7bdb5a86d49feb88d7d2873e8a335ab736856ef89d1ee3368be1e1849bf3ae0f1d51ea3dedde1ea332a996a16d5cffa18bb902dce5ce3142a62f39d192fe2e3be2e8d17b1f75ff67b8d709c04d9f03e78d4fbc2aa2cdbfdee035ce3da288fef5c88bfdf4cb5bb076c8f15247f384ee22b465b1a27117f3f90aaf4b98fa0364a6342528eba5299af16b795fd9ac9e358a16a58d7771dffa729db9804ec53a7c45fe770fb4e35eba2ed3bc5e13b0dac31f9ae42df45d6bac95e02f9ff567c3703e9415a13bb6e23f81eaba8e56aace5925066b2a3fee998eb3fc5e2c16dac271d3bdf8038fb2e1cebf9ea93264768340234a2329edf03eb1ce76b8f55c67eb4b7558696c5f75bfe1fe8a3a2c6a4bbf601be8e17a2f60178bc60ef173a3276bcbb8f07ec63ce437c8c07a4759707edc7e405d6fa47c2fa89ab7710bd6ff9deb938acdfe798f57bbdf7ca75ee47bc38de90caf48773bf99269fcbb9dffd3a8f779dfbe1725175c77e21ee7d23c623b2e0fb22a9cc602b1eeb22b8273a967d326259d2ca7ef7219e97e23142fcef8dccf43753acba509b9a0c75a132cf5aed26fe63a6ccf1a7af7764d2b10ef541558eba529991d0d646997c02b613ee17ea1cffa729dbf127e9a7eb3c2dfe3a87db77ba59176ddf690edf33803526df55e89b8e3fc90fd94b205f0bfb132a477a90d6c45e069cc86e2f576b2d9784326947fdd331d77f9ac533cd62d6b13316e2ac0e9eb5f0d557a703b7462341a3eff9039bebbdc6ae7d8cafe7d1a2f63155c068f79bb89fcce7b372f6f55bd7f10995c163682a330ffad984a3ac7d5d9a968b737c3a3e0f84c785f83c90af73a464d05ecfa4c5e1d377b9e5bb3c8fbefb59befbe5d1b7682e9a73d29cd3377f70df520c8c3ece1bf1fa484718f17d04b45c0f60f4f5cc662a07c66a60c4fd1d317a78bf725567bf2984c73a3d81d1c7f3c6b95eafc6f79be33b0688d1c733dab9bea71a9fdba6e57a03a38fef1ae137943ac2e8fad65129fc7af8ae515567bf0382df3aea038c3ebe0d9208da7fcfe45e8c938091967b00187ddc474a04edafabdd8b11ef57d27209cf8cd9f6ed9ec7fea472bd06918f710551c71ae8dbc3f5ff148e4de88816f57e79b21efba06f0fd7bf422dea838e6b81f7e73cdc1b0ddbf1e41c78f01e222dd71f18a77a629c9203e35460a4e5060063da13e3d41c18d3c048cb3d048c1eae43868ce91c18f17a1dd91f06c6e99e18a7e5c0381d1869b94780d1c735c504f8ed08e30c60a4e51e05c6999e1867e4c038131869b9c780719627c6993930ce02465aee71609ced8971560e8cb38191961b088c733c31cece81710e30d272838071ae27c6393930ce05465a6e3030cef3c4383707c679c048cb0d01c6f99e18e7e5c0381f1869b92780718127c6f939302e00465aee49605ce88971410e8c0b819196ab2800c6a105c0f85401303e5d008ccf1400e3b305c0585a008ccf03e3a2f819c3f3d48539302e029e17e2e709355b9403cf0b7e79c2f7132e72f85a1cbfaf54ae755f0c3c4be2e709b7c5e21c78882109cbbde09731d55946cdb3347e9e50b32539f02c05cd963834f3c098ea2ca3e659163f4fa8d9d21c789681664b1d9a79604c759651f32c8f9f27d46c590e3ccb41b3650ecd3c30a63acba87956c4cf136ab63c079e15a0d97287661e18539d65d43c2be3e709355b9103cf4ad06c8543330f8ca9ce326a9e86f87942cd56e6c0d3009aad7468e68131d55946cdd3183f4fa859430e3c8da0598343330f8ca9ce326a9e17e3e709356bcc81e745d0acd1a1192746e489fb7de38d0e5fab18d49d1890b14f01303e50008c3806c147ff956d0c42a35f7d529dd5c7d7f6ca3606017daff6a4c5aaa0e35aacf6cb93750c02fa5ee3498bd541c7b558033c2f79d022013e3ac2430c4958ae7f01300e2800c6870a80f1e102607ca400181f2d00c6c70a80f1f102601c58008c830a80717001300e2900c6270a80f1c902607cd13363b6f39797bab8efa87395aeee3beabca4abfb96389738ef0ebe25ce25cebb836f897389f3eee05be25ce2bc3bf896389738ef0ebe25ce25cebb836f897389734ebe5ff6e03b013e68ca768d9f1892b0dc8bc2d8a51991a7223e9e4aac3bfa7a8541dd5f71f01479aa3bfa7a9541dd89a1d0185f2e00c6170b805174cc8c41ec0ca3e659eb89e7d51c78d602cf3a4f3c6b73e059073cebe3e709636a5d0e3cc49084e55e2c00c6970b805174141d39318a8edd47476114466114c6fbc158087db8ec6732e72e9d61d43c4df1f3849aadcf81a70934a3e55ef0cb98ea2ca3e6d9103f4fa859530e3c1b40b32687661e18539d65d43ccdf1f3849a6dc881a71934dbe0d0cc0363aab38c9a6763fc3ca166cd39f06c04cd9a1d9a79604c759651f36c8a9f27d46c630e3c9b40b38d0ecd3c30a63acba87936c7cf136ab629079ecda0d92687661e18539d65d43c5be2e70935db9c03cf16d06cb343330f8ca9ce326a9eadf1f3849a6dc981672b68b6c5a19907c654671935cfb6f87942cdb6e6c0b30d34dbead08c2be38b05c0f87201307ad631d55946cdb3dd13cfb61c78b603cf0e4f3cdb73e0d9013cafc5cf13c6d48e1c78882109cbbd58008c2f1700a3e8283a7262141dbb8f8ec2288cc2981be32b05c028db5a18b9327a38bfcafa7cca8e2eee3beaf994aeee3beaf994aeee5be25ce2bc3bf896389738ef0ebe25ce25cebb836f897389f3eee05be25ce2bc3bf896389738ef0ebe25ce25cebb836f897389f3eee05be25ce2bc3bf896389738ef0ebe25ce25cebb836f897389f3eee05be25ce2bc3bf896389738ef0ebe25ce25cebb836f897389f3eee05be25ce2bc3bf896389738ef0ebe25ce25ce39f9de19bfef54aecfb0ee041e1fcfd47aaa67a55eefeb665d9fc4a89fd6ea3396563b2cad9250e675d0ef331ef42b02bfb46e9a277fb9320f63c0ecc977ea41b58e3e507ff2f1b2a587f6bfcb53dda3fafa5d5ddc77545fdfd57d47f5f55dddb7c4b9c47977f02d712e71de1d7c4b9c4b9c73f18df992a0edb89ddeafa4d7b1dbe47b9a792aff0a2c4765e6f5cefc9607d2867cf8963624fb8aeee05be25ce2bc3bf896389738ef0ebe25cef9c539c6c3bc3cf004164f9085271ff70f72e119c38c6706339ec9cc782630e3a962c6339219cf66663ccdcc78d633e3e9c18c673e339e99cc785e62c6338519cf44663c29663c5b99f1ac64c6b38c19cf68663c8b99f1bcca8c6716339ea9cc78d630e399c48ca79a19cf36663c5b98f10c63c6b391194f13339e05cc78d632e399cd8c27cd8ca79619cf70663c35cc78b633e3798e194f23339e06663ccb99f12c61c653c68c27c98c6721339e39cc78a631e3a963c6338e19cf2a663c9b98f16c60c6b38e19cf08663c0f32e32967c6339619cf5c663cd399f1d433e319cf8ca79219cf6a663c2b98f12c65c6d397194f3f663c8b98f18c62c653c4802711dcfd8e9304fc7f27d88aad65f563616f0e6efbff1e632f8665f69a7c0fc7baf7808d9e35dbeb581675da0375499b7ce5a79b429dd0571ae6c95f1970ec65c2338a19cf22663cfd98f1f465c6b39419cf0a663cab99f15432e319cf8ca79e19cf74663c7399f18c65c653ce8ce741663c2398f1ac63c6b38119cf26663cab98f18c63c653c78c671a339e39cc781632e34932e32963c6b38419cf72663c0dcc781a99f13cc78c673b339e1a663cc399f1d432e34933e399cd8c672d339e05cc789a98f16c64c6338c19cf16663cdb98f15433e399c48c670d339ea9cc786631e3799519cf62663ca399f12c63c6b39219cf56663c29663c1399f14c61c6f312339e99cc78e633e3e9c18c673d339e66663c9b99f18c64c653c58c6702339ec9cc786630e319c38c6727339e790e1e0fdfcf0b7968bc2aad9be67732f1ed613b84df0dfcaca73aed33ebea65d64bfce4af04ca2cea93f9d5e3757059e2b2c71763acee038d767baa4bd43b99777771df51ef64eeeabea3dec9dcd57d4b9c4b9c73f2bd2f7edf297c3685a6226b3e0d79dcbff878a6c7533ddbeddbe3fe26f07e4babdd96564928f359d06fbf07fd5cc70b344ffe72651ec68019e3a22288372ede88bf4edffbd630e9fa86a52fd6eb4d4f9a46ed43deece2bea3f6215ddd77d43ea4abfb96389738ef0ebe25ce25cebb836f897389734ebedf32f918cf1b2bd187bef64be7036f81df774cbe2846bf7a5d6f9b75d1b79189e31de0a1323f02d7a2a5cd4b9b8fcbb7ecdb24cebb836fce716ee7e91e22beb7dbd73ddea858ccc7fde5fbe93b2a16bbbaefa858eceabe25ce25ce39f97e377edfe13dc49d41fb29db3dc47781e76d0f5a78aa6778ee74c0aad34eab4e492883e772073cd4b308fcd2ba69fe006c874263d63c34961ddfcf48e55e62c248b6b7fdf284edeba5a0fd94ad7d1d001e0feda0ca533dc3f6d562d5e92587ee540663b5c5433d5d6d87e65b603bb41418b3e6a167e7883501e55e65c248b677fdf284edebd5a0fd94ad7db5008f8ffec7533dc3f675d0aad3ab0edda90cc6ea410ff574b51d9a277f85c8ac79d69a3cb126a0dc5a268c643be097a7260175a6295bfb3a083c2d1ef4f154cfb07d1db2eab436b85b772a83b17ac8433d5d6d87e60fc17610666176316b9e7526bfd6fc26a0dc3a268c646bf1ca535399803ad394ad1f3b043c3efa794fba87fdd861ab4eeb1cba53198cd5c31eeae96a3b347f18b6432eccfb0a905974169da3984567d1398a5974169da3984567d1398a5974169da3984567d1398a5974169da3984567d1398a5974169da3984567d1398a5974169da3984567d1398a5974169da3984567d1398a5974169da3984567d1398a5974169da3984567d1398a5974169da3984567d1398a5974ee1cb3e6596ff2c49a8072eb993092eda05f9ef0f99df541fba9c89a4f43fe30f01cf2a08fa77a86e3de8f58755aefd09dca60fb3ae2a19eaeb643f347603be4c2bcaf009945e7ce316b9e269327d604946b62c248b6437e79c27eac29683f65ebc78e008f8f7ede533dc37eeca855a72687ee5406dbd7510ff574b51d9a3f0adb419885d9c5ac7936983cb126a0dc06268c643bec9527153e87b821683f65ebc78e028f8f7ede93ee613f76ccaad30687ee540663f598877abada0ecd1f83ed900bf3be0264169d45e72866d159748e62169d45e72866d159748e62169d45e72866d159748e62169d45e72866d159748e62169d45e72866d1b9fbe8ac799a4d9e581350ae990923d98e78e5a90eef3b3407eda76cf71d8e018f8ffb329e740fef3b1cb7ead4ecd09dca60fb3aeea19eaeb643f3c7613b7475e67d05c82cb1911f66890d618e6296d810e62866890d618e6296d810e62866890d618e6296d810e62866890d618e6296d810e62866890d618e6296d810e62866890d618e6296d810e62866890d618e6296d810e628660eb1a179369a3cb126a0dc46268c643bea97277cefc1c6a0fd946ddcce71e039e6411f4ff50cc7ed9cb0eab4d1a13b95c1f675c2433d5d6d87e64fc07610666176316b9e4d264fac0928b7890923d98ef9e509fbb14d41fb295b3f7602787cf4f39eea19f66327ad3a6d72e84e6530564f7aa8a7abedd0fc49d80ec22ccc2e66cdb3d9e4893501e536336124db71bf3c613fb639683f65ebc74e028f8f7ede533dc37eec9455a7cd0edda90cc6ea290ff574b51d9a3f05db419885d9c5ac79b6983cb126a0dc16268c643be1972795803ad394ad1f3b053c3efa794ff50cfbb1d3569db63874a73218aba73dd4d3d57668fe346c874263d63c5b4d9e5813506e2b1346b29df4cb13b6afad41fb295bfb3a0d3c3efa1f4ff50cdbd719ab4e5b1dba53198cd5331eeae96a3b347f06b643a1316b9e6d264fac0928b78d0923d94ef9e509dbd7b6a0fd94ad7d9d011e1ffd8fa77a86edebac55a76d0edda90cc6ea590ff574b51d9a3f0bdba1d09835cf769327d60494dbce84916ca73df324a0ce34656b5f6781c747ffe3a99e61fb3a67d569bb43772af326d4f39c877abada0ecd9f031e9ae6018fafb80c2c9ec0a10f4d6398f1cc60c6339919cf04663c55cc784632e3e9c18c673e339e99cc78a630e399c88c27c58c6725339e65cc784633e3799319cf62663cb398f14c65c6b38619cf24663cd5cc788631e359c08c6736339e34339e5a663cc399f1d430e36964c6d3c08c6739339e25cc78ca98f12499f12c64c6338719cf34663c75cc78c631e359c58c6704339e0799f19433e319cb8c673f339eb9cc78a633e3a967c6339e194f25339ed5cc785630e359ca8ca72f339e7ecc781631e319c58ca788014f22b87b2c4d02febf1f6c34e6633bd8de33f933602b76f8a07bc5e7c05662f2b48ede2a1d1d7cf7ba51275fe35cd0571ae6c95f1970bcc7846714339e45cc78fa31e3e9cb8c6729339e15cc785633e3a964c6339e194f3d339ee9cc78e632e3d9cf8c672c339e72663c0f32e319c18c6715339e71cc78ea98f14c63c6338719cf42663c49663c65cc789630e359ce8ca781194f23339e1a663cc399f1d432e34933e399cd8c6701339e61cc78aa99f14c62c6b38619cf54663cb398f12c66c6f326339ed1cc789631e359c98c27c58c6722339e29cc786632e399cf8ca707339e91cc78aa98f14c60c6339919cf0c663c6398f1cc73f0ecf7c4633fe745f3fb19f8d6f3b5a08b9e12f07f7c0eec4d4f8cfb2d469a7f131891d7b766e5164fb9a5d9fdf4adeb4ff72a1e34bfb8bdf0b9070edbab3c0f9af5b378fa599add4fdf5a0bbaf74f636c707be138680edb0bc7697ae89f6b12168f9e8aacf934e4cf79d6c7533d2b71dce42731ae576b75ded26abfa55512ca9c05fdce7bd0af08fcd2ba699efc09b33047316b1eba97eb1acfbb900923d9f03d2aefc7cf5393b078f494ad7f7cdfb33e9eea19f6631702b7eeef83ee540663f582877a16815f5a37cd5f70f8ae08e2d5e26207b4b8e8e0b998672dc85faecc670b909983ce9a87c6ae136b02ca2d62c248b6f3c073297e9e9a84c5a3a76cfde325cffa78aa67d8277c10b875bf04ba53196c5f1f78a86711f8a575d3fc07b01d7261be5080cca273e79835cf629327d604945bcc84916c1781e7c3d8795295098b474fd9fab10f3debe3a79e997eec72e0d6fd43d09dca60fbbaeca19e45e097d64df397613b08b3300bb3300bb3300bb3300bb3300bb3300bb330eb32c22cccc22cccc22cccc2cc9759f3d0b3e7c49a80724b983092ed03e0b9123b4fe6be03f2e829db7d872b9ef5f153cfcc7d87ab815bf72ba03b95c158bdeaa19e45e097d64df357613b08b3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300b336f66cd43dfb020d604945bca84916c9781e75afc3c35098b474fd9ee3b5cf3ac8fa77a86f71dae076eddaf81ee540663f5ba877a16815f5a37cd5f87ed20ccc2ec62d63cf42e44624d40b9654c18c97615786ec4ce93b97f8a3c7acad68fddf0ac8f9f7a66fab19b815bf71ba03b95c158bde9a19e45e097d64df337613be4c27ca100994567d1398a5974169da3984567d1398a5974169da3984567d1398a5974169da3984567d1398a5974169da3984567d1398a5974ee3e3a6b1efa4627b126a0dc72268c64bb0e3c1fc5ce535d99b078f494edbec3479ef5f153cfcc7d875b815bf78f40772a83edeb96877a16815f5a37cddf82edd0d5992f1420b3c4467e98253684398a59624398a398253684398a59624398a398253684398a59624398a398253684398a59624398a398253684398a59624398a398253684398a59624398a398253684398a59624398a39839c486e65961f2c49a80722b983092ed26f0b4c6cf5393b078f4946ddc4eab677d3cd5331cb7733b70ebde0aba53196c5fb73dd4b308fcd2ba699efc09b33047316b9e95264fac0928b7920923d96e01cf9df87952098b474fd9fab13b9ef5f154cfb01ffb3870eb7e0774a73218ab1f7ba86711f8a575d3fcc7b01d0a8d59f334987cabf94d40b906268c64bb0d3c1ee22ee4495a3c347f87816f3ddf68f265e617b757233072d85ec93c68566ef1945b9add4fdfbafeab4cfe41f38bdb6b153072d85ee579d0ac9fc5d3cfd2ec7efad65aac36f9bee617b7d76a60e4b0bdfaf9e549252c1e3d653bdef818783e1f3f4f781ef7710e3c9f079ecfc5cf53e5a99e957abddf07ec71ad576bf5054bab8f2dad92500619bee041bf22f04beba679f227ccc21cc58c7d21b126a0dc1d268c64fb1cf0f8e83774dd479975d1fa7baaf450ff36bfadf1fbadc16b0bbdcc7a8983fc9540999707b5b13d66d8cae0ffb4dd747d6e59364fcfbc55b9aef3d23cf92b0bdce7fabeaea1b65a3cb6ef32873e5ab39b0ecd6e7862b49f69a5f91bc0e8baceebeb79d1a8ebcef8bce81d4b476e9ae173c01f018fafe3e2568ba7d5a1858f3697ebf1e5470e9e4fe2e3a9c4d8405f3e6215fbb68ed4ddd57662ac7b15dec3425f1eda40b89f1a6dd645ebd7fb82dafe5e35afc1fe81f653a3ad3a97409949b09f9a92653f551cdc7d5db8c2d8a90cfdff1363b7d75111dcdf6b4b6590af35bf18a36493fd6ffb7b98b5968edc34c376dd0a3cad9e78a2ae89913fdc86750ecdea1868866d211f7176c7e2b17d27419756a69a619ce17183affeec5ed7f2701bd63b34ab67a019c7feacded2919b66aefe0c755ce8e05ec8809b639fb2d0d2919b66ae3e05755ce4e05ec4809b63bb5e64e9c84db37bb5ebc50eeec50cb839b6ebc5968edc34bb57bb5ee2e05ec2809b63bb5e62e9c84db37bb5eba50eeea50cb839b6eba5968edc34bb57bb5ee6e05ec6809b63bb5e66e9c84db37bb5ebe50eeee50cb839b6ebe5968edc34bb57bb5ee1e05ec1809b63bb5e61e9c84db37bb5eb950eee950cb839b6eb95968edc34bb57bb6e70703730e0e6d8ae1b2c1db96996effb0051f79bc81f6ec34687668d0c34e3d8a7345a3a72d32cdff701ee35061bb7e12a8766ab1868c6b13f5b65e9c84db37cf76751f79bc81f6ec3d50ecd5633d08c637fb6dad2919b6651fd596bfc3c398fb76ff5aa4fe63bcbad39f0e098291f31e5290e2a3d8da90ac7dbdbdfaf68b5b44a06777fd3c2e7d8c3a8f191e44f98855998855998855998855998855998855998855998855998855998855998f933e3f3ccade617df857a870923d9f09e948febfcbaee63ccba68fdfad9de5b03dafcc67fdf225589f75ce9b9e331569d4ba0ccff7dbc8ded63c386f71769bb456dcbfbf56e057c1f05de0bba9ff73b3f726876c3a1d9754f8c769f41f3d781d17effc3fd7ef7c41d4b476e9a45f5b3773cf144c5d91d87ef8ad87ca79a7cddd7d5ef22ec13dcbdffbae3d0d4471ce6faee0b6c17ad1e787cbde742d7e9ba55a75b569d92506618d4f37eb62d9ae6018faffe28b07802873e341533e399c18c670c339ec9cc784a99f14c60c653c58c6724339e6798f13cc18ce731663cfd99f1f461c6d38319cf7c663c3399f14c61c63391194f8a19cfb3cc785632e3799219cf32663c8f33e359cc8c6700339e0798f18c66c653c28ce779663cb398f14c65c6b38619cf24663cd5cc78f2710f34179e61cc782a98f10c64c6f310339e05cc7812cc787a32e399cd8c27cd8ca79619cf70663c35cc781a99f13cc78ca78119cf50663ccb99f10c62c6b38419cfc3cc781632e32963c69364c6d38b19cf1c663cd398f1d431e319c78c6715339ea798f10c66c6f308339e11cc781e64c653ce8c672c339edecc78e632e399ce8ca79e19cf78663c95cc785633e3799a19cf0a663c4398f1dc66c6b39419cf22663c8f32e3e9cb8ca71f339e51cc788a18f02482bb9f5dc2e7e56e818d9eb169055bb1637d342e97caebe3ceb383ef5e77b163dd371c0ca8d335a84bdae42b3fddd4eeb9a222b35e9a277f65c0718309cf28663cfd98f1f465c6f328339e45cc789632e3b9cd8c6708339e15cc789e66c6b39a194f25339ef1cc78ea99f14c67c63397194f6f663c6399f19433e3799019cf08663c8f30e319cc8ce729663cab98f18c63c653c78c671a339e39cc787a31e34932e32963c6b39019cfc3cc789630e319c48c6739339ea1cc781a98f13cc78ca791194f0d339ee1cc786a99f1a499f1cc66c6d393194f8219cf02663c0f31e319c88ca78219cf30663c3799f15433e399c48c670d339ea9cc786631e3799e194f09339ed1cc781e60c6338019cf62663c8f33e359c68ce749663c2b99f13ccb8c27c58c6722339e29cc786632e399cf8ca707339e3ecc78fa33e3798c19cf13cc789e61c63392194f15339e09cc784a99f14c66c6338619cf0c663cc5cc78e6593cf87f7dad81ae2f5e071bfdff3fcdcdfb72538feb96bf18ea5119f56d1e5f9ae194766812f56d1e0e3c3398f18c61c63399194f29339e09cc78aa98f18c64c6f30c339e2798f13cc68ca73f339e3ecc787a30e399cf8c6726339e29cc782632e34931e3799619cf4a663c4f32e359c68ce771663c8b99f10c60c6f300339ed1cc784a98f13ccf8c6716339ea9cc78d630e399c48ca79a19cf4d663c15cc780632e3798819cf02663c09663c3d99f1cc66c69366c653cb8c6738339e1a663c8dcc789e63c6d3c08c6728339ee5cc780631e359c28ce761663c0b99f19431e34932e3e9c58c670e339e69cc78ea98f18c63c6b38a19cf53cc780633e3798419cf08663c0f32e32967c63396194f6f663c7399f14c67c653cf8c673c339e4a663cab99f13ccd8c6705339e21cc786e33e359ca8c6711339e4799f1f465c6d38f19cf28663c450c78a2be8543ffef01b6ab267f1b6c574cfe26d82e9bfc75b07de8b0153b58c8df55b0d138972b60a37b7597c146d78bc8973edebd38f86ed662479d7a3858af38ea74d5b12c6e475a261dc4bb1dd1571ae6c91f7eabe72a139e51cc78fa31e3e9cb8ce751663c8b98f12c65c6739b19cf10663c2b98f13ccd8c6735339e4a663ce399f1d433e399ce8c672e339edecc78c632e32967c6f320339e11cc781e61c6339819cf53cc785631e319c78ca78e19cf34663c7398f1f462c69364c653c68c6721339e8799f12c61c6338819cf72663c4399f13430e3798e194f23339e1a663cc399f1d432e34933e399cd8ca727339e04339e05cc781e62c63390194f05339e9bcc78aa99f14c62c6b38619cf54663cb398f13ccf8ca78419cf68663c0f30e319c08c6731339ec799f12c63c6f324339e95cc789e65c69362c6339119cf14663c3399f1cc67c6d383194f1f663cfd99f13cc68ce709663ccf30e319c98ca78a19cf04663ca5cc782633e319c38c6706339e62663cf32c1ebca6580936ca57818df229b051be1a6c94af011be5c7818df2e3c146f90960a3fc44b0517e12d8284ff78cf0f99e7cbc178e7cd1ba69fe1a30de3679dc2694af03ee0f2c9be6bee489fb038b9be62f0123d5e103b051be1eb82f5a36cd7dc113f7458b9be62f0023d5e122d8283f196c949f0236ca4f05db54f04736ca4f031be5a7838df233c046f99960a3fc2cb0517e36d8283f076c949f0b36cacf031be5e7838df20bc046f985e6576fe3f72d9bdec6e74d3e1dc4bb8dc917ad9be6cf03236deff7c146f945c0fd9e65d3dce73c71bf6771d3fc3960a43abc0736ca2f06eeb3964d739ff1c47dd6e2a6f933c04875380b36ca2f01eed3964d739ff2c47ddae2a6f953c04875380d36ca2f05ee93964d739ff0c47dd2e2a6f913c04875380936ca2f03eee3964d731ff3c47ddce2a6f963c04875380e36ca2f07eea3964d731ff1c47dd4e2a6f923c04875380a36caaf00eec3964d731ff2c47dd8e2a6f943c04875380c36caaf04ee83964d73b778e23e6871d37c0b30521d0e828df2f83efa359e186f5b8cb72ddf781f178f2d0f5836cdf8ae27c6031623cdbf0b8c2d267f00780e78e269b1786cdf49d0650d53cd92606b019e5a4f3cd72c9e6b961638de0dcf05d658369fdb758dc548f30780b1c5e4f3d1365b2c1edb771274a965aa59126c2dc053e789e792c573c9d2029f73c173b75acbe673bbd65a8c765f8171867d85afb6d962f1d8be93a04b1d53cdb0cf6d019e7a4f3c172c9e0b96166590c7f3c73acbe673bbd6598c765f8171867d85afb6d962f1d8be93a04b3d53cdb0cf6d019e164f3ce72d9ef3966fdc8678bebfd0b2f9dcae0b2d469ac73ed76e0ba5908f9ba7dee2b17d27419716a69ab9da82cffeec9cc573cef28ddb10afcf2cb26c3eb7eb228b91e61702638bc9e3365ce489a7c5e2b17d2741977aa69ab9da4229b0c5cd73c6e239636981e3f6f07a5abd65f3b95da3fa8f45c0d862f2f9689b2d168fed3b09ba2c66aa191e43b6004f8b279e5316cf29cb376e43bcfeb9c4b2f9dcae4b2c469ac73ed76e0ba5908f9b67b1c563fb4e822e2d4c3573b5059ffdd9098be784e51bb7215eaf5e6ad97c6ed7a51623cd2f01c61693c76db8d4134f8bc563fb4e822e8b996ae66a0b3efbb36316cf31cb376e43bcbfb0ccb2f9dcaecb2c469a5f0a8c765b28857cdc3c51fd19f94b822e2d4c3573b58552608b9be788c573c4d2a20cf2783fa8c5b2f9dcae2d1623cd2f0346d2aa05785a3cf144c519f94b822ecb996a96045b3ef69b872c9e43966fdc8678ff6e8565f3b95d57588c34df028c765b28857cdc3ccb2d1edb77127459cc5433575b401d1b807ba565f3a9ed4a8b9be65700e362878e2b3df144f5292b41c7064b476e9ab9e211756c04ee06cbe653db068bbbc1d2d6158fa5908f9b27aa5d37808e8d968edc3473c56319b0ad02eec596cda7b651eda80118975bdafadcef456debc5a023e9d2c85433bcae89db9ad8560377a365f3a96da3c56db719dcd6d8661a3df1446deb46d0917459c55433ec7bf07cc8d7f947d4fdae7cf88eba07920fdf51d7c5f3e13bea5a693e7c47dd47cf87efa86b2af9f07daff36c9fbea3ae59e6c377d4795f3e7cdfb67cdfcea3efa8f16ff9f01d3526aaabb76fd99774af7dc9fdecd7baebbe44fa739efdf9eaf87da71241fb731a3d1559f369c8e3f9cb2a0f5a78aa67259e137e12e37a5de7d6cb2dadf0dc1acf517d9dffadb678689efc152233c645517cbe2bf13a0c7edf91ae8b54828dae8b55818dae8ba6c0d662f2d560a37b323560a3fb81e3c046f7a2e7838dc6412c001b8dc1b900361afff53ed868ece179b0d1b8d7f7c04663aecf818dc6fb9f051b3d6b72066cef98fc69b0bd6df2a7c0f696c99f04db9b267f026c6f98fc71b0ed37f96360db67f247c1f659933f02b6bd267f186c7b4cfe10d8769b3c5e7bdf65f2782de733268fd7f25e37f9f160db69f213c0f69ac94f04db0e939f04b6ed267f1b6cdb4cfe0ad8b69a3c7e5f748bc97f00b6cd267f096c9b4cfe22d8369afc64b0359bfc14b06d30f9a9606b32f934d8d69bfc34b0ad33f9e9605b6bf233c0f6aac9cf04db2b263f0b6c2f9bfc6cb0bd64f273c0f6a2c9cf05db0b263f0f6c1f9bfc41b07dcee4f13a68b1c9e3f57b7adf14def3a2775ee23d4f7aaf34de6fa76f7fb4808dbeaf85e38c4a4d1ec7b8d17ba5707c25bd4b12c7a9264c1ec79597993c3ed340dffdc06743e8db51f85c52b9c9e33371f4cdcf0360a3ef92be0b367af7d43b601b60f26f838ddee9fc16d8e83b176f828dbeddf406d8e87b9ffbc146ef98da07b6c74dfeb3601b68f27bc136c8e4f7808dbed1b41b6cf49dc85d60a377497d066cf47ec4d7c15661f23bc136d4e45f03db5326bf036cf4fdc5ed60a377466d031bbd77702bd88699fc16b0d1f70e36836db8c96f021b7dc76b23d8e8dd50cd607bdee437806d94c937816db4c9af071bbd9b671dd8c69afc5ab0d13efb55b0d13efb15b0d13efb65b0d13efb25b0d13efb45b0d13efb05b051dfff31d8a8efa7fe43b753dd7e6f99f97410df7194f6d71ab49fb21dcb1303f2c4796c9c041ef47533f6baa7c2e3f08fccba8acd7a295e6e82efebb1fbce9c03dc30ebea69d67bddf25d02654a07b66d9b6bf0ff34d48196c332b46e9a1f03cb5eb3d65d6eea7bc3537daf5b4cc47d0398a84cd9c0b6b25f32f952582646b6f07c96622d000d714a439e18fc68950acf2f3eca81e706f0c4df4e32e7d73e6202db56dce7d7f675193bd69250e63ae8e7ebbd58372c1e9a277fc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc22cccc2cc9f59f3d0fd04624d40b95b4c18c986f7ba7c5ce7c77bae78cfebe6c036bfbeefeff532eb1d6bd5b904ca7c6b601bdb6d932f83ffd3768bda961eee1366dd96dfbb5706f5c17b411eb665c873d3e2b17d9739f4d19a5d736876d513a3dd67d03c7ef385f4bb063cbedae3758bc7f68d7dc60da69a45f5b33ec625648b33d718848ad87ca79a7cddd7d563a1f4580e7bff75cbd214c740e03df32f419f44cbdc31bf09d0e70ee8733ffb007b5c02f653adc0187fbf996a770f98fafe3196a63806e2b78cb6340622fe7e2055e9731f416dd41e5b8175a532bf0ffbb93f34791c07740bd6f515c7ff69ca362601fbd4cbf1d739dcbe1f9a75d1f6bdecf0fd01b0c6e4bb0a7d1799447ec85e02f92f0f6c2b6b7f678ab42676fc1616b2dbcbb55acb25a1cc1547fdd341bcf5bf6cf15cb69875ecfc09c4d957e058cf579f742542a331a01195c1635e5ffbaf8f2c1ee2207fd88ff6b6cad0b22550e6ebd047e9ba503fdf6a7ea3f601be8e17a2f60178bc60ef17128e3aeaf8b835a08db7bb8ff5fb2fe82faec1ffd3c1a71febf75f1043aee3525aff58583f71f50ea2f72d54e67f59fb511fe793b82d6d3d712c2195f97fd00fa50665f2b99cd7ddaf73f4a8f33a1fdfcec4730d9ab2eddf711fe3a37ff154cf4ad7beeb9a55a724941906f5f4701ce3dc6fd1fc65f0edeb7ba9e4838ea1ae5b5a944099a4693bd47744e988d7256ee4a52e29e7f1e058475da8cc00a84b29d8e364f2b9ddf0384baff7a6a3ae54e6b1416d65079a7c02b613f6a5231cffa7295b7f40fae93a5f8cbfcee1f6a5e71669fb5e74f87e1f5863f2ddeefd1574bc4f7ec85e02f9e183dacadadfee24adf15bacf47c1db2dbcb5db7964b42994b8efaa78378eb1ff59d59f2a7636708c419c591cf7ef35284466341232a83f70aeceb2d51fb7d1f63e9b3edf76f02a3dd6fe2b18b4f36fb9cc5be5eee3a1ea43278ce426526403f9b7094f57f1f20736c83f5a27a04565d03abae9e8e5f6b8a2c3dd3e06734d8293e4967fa1f1ee3529969d6feccf7756ce2a67ae0fdbaab16f7354b57bc16351bb875dcdbe716789ceef99cb6068fc5ece3a1abc04e65165ac743f671dc6d475decfd747170f7b9e02756597c3629db7276fe236b19bc66e0ba268b7ddf1560499b7ce5a799aa2a2b91a9d8a185ebbea9ab4fa2768031675f47196dad07afa3acb1fa24bbacee936afbb7e943db11afb5dbd7df3d3d9b16b6b95b56fd6d8d3463abc9e336f4710fa33b3e9b561adb7a27ad2fc4f10ca5563e1edfa90db8afc8a6c555078faf6b9a515a5c75f88e4f8bf14daefd874b8b2b0e1e5fe798515a5c71f88e518b8dae6b0b2e2d2e3b787c9d6b446971d9e13b3e2d26b4bbae914d8b0f1d3cf15fd3c8ae05de13cb85f90a03e6522b1f8fef9af5ae7b772e2d3e70f0f8ba7717a5c5070edff1695135de75ceeed2e29283e7529eb5b8e4f01d9f161327b9aea9b8b4b8e8e0f1707d2dab16171dbe638c8b66bcbe964d8b0b0e9e0b79d6e282c3778cc787e3b35d33442dde77f0f8baf617a5c5fb0edf316ab14efb3edf012dce3b78cee7598bf30edff169b17e9cf6fd5e07b478cfc1f35e9eb578cfe13b3e2dd64dd4becf75408b730e9e7379d6e29cc3778ce750615c9ced8016671d3c67f3acc55987eff8b4d8101e6b9de98016671c3c67f2acc51987eff8b4a80cf7a9a73ba0c56907cfe93c6b71dae13bc6b808cf274f75408b530e9e5379d6e294c3778cfb91302e4e76408b930e9e9379d6e2a4c3777c5a6c0caf3f9de88016271c3c27f2acc50987ef18afb9847171bc035a1c77f01ccfb316c71dbee3d3a23adca71eeb8016c71c3cc7f2acc53187eff8b4680eef891ded8016471d3c47f3acc55187ef188f3bc3fee24807b438e2e03992672d8e387cc778dc195ebf38dc012d0e3b780ee7598bc30edf31f69de171e7a10e6871c8c17328cf5a1c72f88ef1b833d4e26007b438e8e03998672d0e3a7cc778dc19ee475a3aa0458b83a725cf5ab4387cc7181761df79a0035a1c70f01cc8b316071cbe63bcae15f69def76408b771d3cefe6598b771dbe633c1f09aff1bdd3012dde71f0bc93672dde71f88ef15e51780cfe7607b478dbc1f3769eb5781b7cfb1867825ad058ac5196162550e681c1995f1a8b15a523ad039fa1c5babc157b5d32e3cade8ca8cb5b50172ad317ea520af638993cd5358c19fa96028d4d6f75d495ca3c3cb8adeca3269f806d721bd635ccf17f9ab28d4122fd749df7c55fe73056e91b10b47df7397cef05d6987c57a16f1a9b4e7ec85e02f96707b795a572a407694decba8dd0373090dd5eee6d6bb92494d9efa87f3a88b7fefb2c9e7d1673f8dc03c419c5919fbe2bc3b43f42a351a01195c1317bad9e78ec3184c441fe7419dafebdad32b46c099419037d148e2ba57a2682bbc74deafabde1a97ee48bd64df3e42f09b61bc068d751c7c74330f693be0142df07d136fade077ebf6bbc65d3759de0a9aee48bd64df3138091be3f323eff8ca98e328eb31835cf240f9ae1375568cab6bf98043c133df078aa67b81faab5ea34c1aa5312cae0b38db51eea59047e69dd345f0bbe7d6c73d482f6c9c32d2d4aa0cc42ebf8314a475a878edff18ebaf8d2719cc533cee17bb2671d69ddd4274ece83ef3acb778de55bb76d8c313d656bdb75c05cef8159af774afceb0ddbf654b32e8a67f25303754a830671d5097d1759eb267b09e49b06dfcd407ad0be93d8753bc2d8895a6e92b55c12ca4c76d43f1d73fda7583cb88df5a48f1b5e84e34a0fed218c81c91607cdd780765322b49b0cda5119dcf75679d2aedee2a1f92ae0a1e3ab5ab0d1710a7ee392fe9fca03b7ddefd53ab8c986df3cac72308e8f9f313cceaab218697e3c3092ad1e78ea3c69666febe1963e784cd0db2a43cb964099fdb05f4e38ca86cf1d17b5d58bbea5f9498cf5d2ebede5412ffcce6700fa04968634114369d0f62dd038791e08dabef5b97bcfce5deb36352f6bcedcf624b4120b137f8b1cd528061be67b386c41d0fe93a62560a34f9af6045bb1250b7e4a95cad3a7137dc8857ad0ba4b2cce526089d3377e0e96a66ca1d31b787c84b20e1dfa24ac099dc65d5bf634637cf4b4383b133bfa7f3db2948b5a17c5418987ba2313ad9be6c99fd6873e8ffbfabaa66dd3766ddabba3f9b53dbb11d66e5c982fb244b07f5dcb60906063a2f5f4b4c4e913bf3835d8786dbe00fc05c012189ed2f879c240a56f0837addbbe7dc9def5dbb734cddefb5ad39e2d3b5f43457b5bca45a96d37793db9ba3a2c6b97efe5b0d9137eb1b937d8e88bcda56023ff7dc0461c0fc0ffec2de1a54d0c83f55318ebff95980af73215a210a4dd90ee4f749bd1af4dd5bb7ffd8968fd4968bdf9f4dbe2f4279ef5279df5279cf5279bf5279af52799f5db24f413defac8614890f984f29341e615b14383cc2790f5278f9f09da3e69aca7df055efd09637da8a13f51ac3f49fc7c90b954383ac8bc564dbfc6421fb2ea432b7d98a74f6bf421b83e2dd7875efa7281be74a40f63f421a23efcd1872cfa105c1f7a4f355a4f0b329f34d79f309f19643e51ae3f49ae3f413e37c87c627cbe4a0b82cca7b6170599cf07ebcf87ebcf76ebcf79ebcf7cebcfcfebcf82ebcf85ebcf88ebcfcceb4f0feb4fd0af0e329fda7e29c87cb6f89520f399e3b541e6b3c8eb83cc6794370499cf2eebcf31ebcf346f0e329f75d69f7bde16643e0fbd23c87c4e5a7f665a7f7e5a7f965a7fae5a7fc65a7fde5a5f72d7b71af425787d795b5f7ed5b740f4ad1f7d6958dfb2d4b770f52ded962033e4e150901912a38708e921537a08991e527722c80cb9d44350f5905c3d44590fd9d643d8f5907efd88837ee4433f02a31f09d28f48e947c6f42374fa3148fd58a17e4c563f36ac1fa3d6977df523e8fa56a0bedcdb1a642e09df09329f5ffe9c4a9f57e9fb54fa824adfafd20fa8f4832afd904a3facd21755fa11957e54a51f53e9c755fa09957e52a59f52e9a755fa19957e56a59f53e9e755fa0595bea4d22faaf44b2afdb24abfa2d2afaaf46b2afdba4abfa1d26faaf45b2afdb64abf1364e2f1f754fa7d95fe40a53f54e98f54fa6395fe44a53f55e9cf54fa7395fe42a5bf54e9af54fa6b95fe46a5bf55e9ef54fab24a5f51e9ef55fa0795fe51a57f52e9ab2afdb34a5f53e9eb2afd8b4adf50e99b2afdab4affa6d2bfabf42d95fe43a56fabf49da0ed33e5d8790c363dce5033bf6ecf9ee61dafefa9d8b3b362c7deed7bb6bcbefd8d8a7d5bf66caed8f9d9e65d1bb7efdc870b7fd92cfcb8999fb66bd7ba372ab6bcb6a1797fc5cebd7b2a766eac58bf73ef6b1bdaed2cffb75968f0dd1ed76dd810edacb4c7a7202debd139a783cc72f4a5fa79d9ebf6448f4e08f24c67169adbc90acd357b203a0d5b9e39e6abd8bd7de79e8aca8ad7d45fb573ddb9af79c3980afcdf6e25f2ee3d15bbf7acdbb5a762e3ae9d3b2aaac6e07a17f6e94425bed8c70f4c6ff35ea24e85ca6f0eec444dbe36b0739be33f3f0de9ffeca4d3b2419da861ffce2c347e50e708d3832265d9bd77fd9e5deb9af6442f3cebd32cbca033d55cddc96af619dc0967e59d5968f4e0ce112ee88cb37d39380bfe3f4095c818d45505009b2d6c6f00000027451f8b08000000000000ffed9d69741cc5b5c77b24595e46832d5bde37b1056fb246a3dd968d8cf70dcc8e018317c960b02d638b7d271b092121fb4202bcac2421fbbeef09d9f7852424908484247c7839efbdf3ce791f38afaa5537fa4f51dd6886be72b5e6f639d7537d55d3f7776fdfaaeea9aa6e3f1304412618daaa959c143c77a3bff79acffc0bdb5a123c569e93339312ceaa947056a784b326259ce352c2599b12cef129e19c9012ce8909726ab6aaa0784b9a7712435c9366cca62ca6752988692e65313d2105319d1ca4a38f9a9212cefa94704e4d09e7b4947036a484737a4a3867a48473664a3867a58473764a38e7a484736e4a38e7a584737e4a3817a48473614a381b53c279624a384f4a09e7c929e13c2541cec5c079aaf97c91f93ccd7c2e329f547789f95c6a3e97191f6bcc7e9392e54a9a359ff5373dd15050d2aaa4cdfa5bbb920e259d4abaccdf1acddfba95ac50b252498f92554a562b39ddc4628d923394ac55b24ec97a251b946c54b249c966255b946c55b24dc97625672a394bc90e25672b3947c9b94ace5372be920b945ca8e4228b65a7928b955ca2e45225bb945ca6e47225bb95ec51b257c93e257d4afa95ec577285922b951c50729592ab951c547248c96125034a8e28b946c95125c7940c2ab956c9754aae57728315b31b95dca4e46625b7589cb72ab94dc9ed4aee5072a792bb94bc58c94b94bc54c9cb94bc5cc9dd4a5ea1e4954aee51f22a25f72a79b592d728b94fc96b95bc4ec9eb95bc41c91b95bc49c99b95bc45c95b95bc4dc9fd4ade6e58a821bc43c9034a1e54f29092ff50f24e25ef52f26e25ef51f25e25ef53f2b092f72bf980920f2a7944c987947c58c947947c54c9c7947c5cc927947c52c9a7947c5ac967947c56c9e7947c5ec917947c51c997947c59c957947c55c9d7947c5dc937947c53c9b7947c5bc977943caae4bb4abea7e4fb4a7e60c5fc874a7ea4e4c74a7e62fe46e34b3f55f23353feb9f9fc85f9fca5f9fc95f59d5f2bf98da57b4cc96f2dddef94fcde941f379f7f309f7f349f4f98cf27cde79fcce79fcde75fcce753e6f3afe6f36fe6f369f3f977f3f90ff3f94ff3f98c92fe86a1f2846078eb0d12ea93dafafbf4dc0405fbd4a078d3b1a8367fa3cf46a3af31fbf449b11b67f6c759fa5ab35f6b1d6782d99f60e9ebcd7ebda59f66f6a759fae9667fbaa59f69f667823e1bc018a5d16b5db551654047795805ba7141714cb4ae960e07baf141712cb48ece632de8261add78d04d32ba09a0cb1add448a99923aa3eb0d92ca89fc1e7ddc5cd2c735f3362724cfbb4f1f773213ef94e479fbf571eb1978757e4c35c79a027933cde8ea4167ba95602ae8a61bdd34d0cd30ba06d0cd34bae9a09b6574334037dbe866826e8ed1cd02dd5ca39b0dba7946370774f38d6e2ee81618dd3cd02d34baf9a06b34ba05a03bd1e81682ee24a36b04ddc9467722e84e31ba934047fde7c9a0a3fbbb538c4ef7093519f88ed1537f147e87fa5cd09d46fd2de816515f0bbac5d4cf826e09d826dd52e84348b7cce8a83fd27feb32e5de20a9fc2ff4e9e376277d5c75647ddc95c91f379cd3ea0986e3da0b76ba2156ab4c39c175332d683b6384ec90be06ca1ba12ed5a378d03585d8f5b5638529af8af95e97f5bd1cd459e1f0bf3748d6ff9516cf4a8b791cf8cf93b3ad2d92b323de4aced9f3a1ae9d7b747f331673760b7030e46cbbe4ec88b79273761fd4b5738fee71c762ce5e041c0c39dbcd93b385bce4ecd0585710b8738f7ee78cc59cdd0f1cc9e76cbbe4ecc8b79273f676a86be71efdd61d8b393b081cc9e76c67b7dc1b8c782b3967ef85ba76eed1b8cb58ccd9bb80832167fba49f1df15672cede0f75eddca331c0b198b3f70147f239dbcd94b3ad92b3c1d0bc6510b8738fc6a3c762ce3e001cc9e7ec3e199f1df95672ce7e06eadab94773236331671f018ee473b68f6b7cb620393bb45e2308dcb947f3746331673f6fca7a6eece7666e6c01e87e61740b41f74b586740ba5f19dd89e017431be8943630e2ade436f06ba86be7f249a63c16dbc00f80832167bb256747bc959cb34f415d3bf768fdc258ccd9df020743ceee959c1df15672cefe17d4b5738fd6d28cc59c7dda94f5fdc2e3e67e6111e8fe60748b41f747a35b02ba278c6e29e89e34ba65a0fb93d13581eecf46b71c747f31ba66d03d657479d0fdd5e85a40f737a32b80ee69a36b05dddf8dae0d74ff30ba76d0fdd3e83a40f78cd1751a9d9ec7a235558f1add04f0bd3748eedc86eba882e22d63edf74279192f4f3e17143f2740b696276fab55fbde148cdcf7e5c0d3cce07b166c8c84a71978f2c9f384bf475b923f6e788e9bac9866c15613f85560f02b03b6e8d8b44ff672a0c37ea3e0606c4d9eb190015b746cda6f0546d2613f46cfe150fbd17df3bccc302f435b0aafcf68af1738c85e0dd4c9340cd76d346c75f077ea03eaa08cfd7cded231e56a982bf870562fecb70023f9981f7dc6c248199b2d46ae7e2303b6e8d8b6ed3a477c74cc5a1d316b63626cb51869bf0d18297eada3cf581829a3dd2f30f5492d23ed93282ef9d18fd988ce6b0e7478afd7e6606c4f9e313caf6d1623edb70323e90ac0c3753d8c6aafbed8e6b80fc17ca66b165d7fc85e0dd469ad1eaebb09aea70c7d68a1d47b53ecd3933f4f853c5ecf46c2c37cee5a98f2318f7de7b341b2b966b7f9bc152b6cf3d89773f593517d39d91366611666611666611666611666611666611666611666611666611666611666ff99a3e6e55ceb198e2723e95a8087639c3f7cf7943916ce013d06f33ac9cf5b14f238574feb1817593ed7409dffcd0cb33dee58278173e7cb2d1dd33aa5f05ce23aa55ed8277bb86e03d74d31ac3d0979965a3cb6ed3a477c7c5c47e2d31a8da8755a3ec52c073a5c0fd7c4c41395674d0edb8d89d92eece3693b85bc7ecf8f7e571ef527761bc1b56f4b2c9dee933aaa87fde6c88152e79df1ba41e524e77131dfd056f2eb6d0a45eb13aa82e26b05de5330ac51299aafa6b511ed96ed1aac5315fcfbdc74c0df7b83e7ae11c23a746cda5f04dfedb08e3d99cfdfd8feb01db8a95c6bf9b60cb8a9cea4aa611f3f67ca4cf733055c3f1b006f60f9441baecf48fe7e6f68bd48a1049e36e0e158bbc6745f9bc77c4c7abd4887152bd7fd32d56987f87530c42f6ecd1ad91366611666611666611666611666611666611666611666611666611666611666ff99f1fd17c48acf48b778c2384a6b6cc2f90c7a6f11ce8bdd5f356c977b0e90e69c165b3ee333ca4f570db33d68caf88e00d7f3ee782eb9e6d6a2ce25d9ab0b9efb9c3ed3b91cf1bb1fda1c31eb70c4ac9389d1ee3368bf1318297e1dc0c3d51edb2d1edb36f6196d9ec62caa9fe55abf129567ae750a8d89d91e5a2fc231af4beb45eceb578b15535c27413a9c07c777abe07a2cdfdeff62af5dc07e0ad76825df6f168ae680edb582640fd7497cc3c496d64924df0f14f29cd7086aa3b426a4e0f095ea3c0ad7b9ef9932ae156a81633de6f83b6d716b12b04f65785766787ee9dd8d747ebb1db657026b42b65bd076c608d9217d0d947f53355cd77e1724c59ad8751bb1df57e9fa5edefa5e0eea7439fcef0d92f5bfdbe2e9b69875eefc10f2ec31b8d7e3ea93ba02778c16418ca80edef332ac2972f691f69a695d87ceff78ab0ede9f529d27a18f8a5a93ee7a0f20d7fd42d47b00f17ec1754f63fb68af1daff4f580ff82fea203fede1bbcf0f580ff821c72dd97d2f117c3f1896b7c107d6da13aff635d47b9dad6f3bdf7caf5db8f7871bd21d5f93fe8ab969975b951bf635ccf5970fd6e887aee83ece13d5529be63bf90f4b511f31159c81ee6638d8935e5634704f772c777c7477c976245ebcbf177b21d3f1d87c4df116efa9b6ecb176a535de0cbbfafdfe00bcf3dd3d0fd67f2be16df0f511fd4eaf095ea4c8577c135987216ce13f695273bfe4e5bdcfd27bed7bc27799fc3f34befefa6f3dbe3b0bd1a5813b2dd82b6e9fe93ec90be06ca27550fd7a57a140f8a35b1eb3642f770c86e7fafddfa5e0eeaac74f8df1b24eb7f8fc5d36331ebdc99097976323c6bc1d557af8c88d1628811d5c1671deddffff85b1eaf31c7ebb73cbef313fbf66510d3d17a67aa3d7eebba3f596cc518ef4f5aa09fcd3aeadae3d2740d49727d3a3e0fb414ece2f3404b99e2990b8ae399b338386d4fb66c4f1e45dbf596edfa51b42d319798fb14739ffe2f0cfc3f2baa52c0589d02c69a14308e4b01636d0a18c7a78071420a1827a68071520a18b3c0783cafed0cf12978f6ff3dc5de6ba06d86f73984b158168c3c164dbc3cb1f73e689be11d2a25ff7f03ccff17564bb9ff17560ebe3735058cd352c0d89002c6e929609c9102c69929609c9502c6d929609c9302c6b929609c9702c6f929605c9002c68529606c4c01e38929603c29058c27a780f19414309e9a02c60929605cc2cb58289751f370bc47331b14afe37a3e1ee6f77a86ef2774bd4394e3ff9d2dd577e677fab694fb0e3c5cbfc0fbff28beb0f7f471ac4f28f53d7d71fff7341363a15c46aef526b8b665243cae3528795ec642b98c5ccf77e0f38623e171fd3fb8bccfdb0cc5ac1c46aef558a5ae17c4e7f0da1d3163602c94cbc8b5a61f9f371c098febb9c03c2f63a15c46aeb5af59b031129e2e8859a723660c8c857219999edd0a63d655020f3ee3d4e588190363a15c46cdb3822966dd25f0ac8098753b62e61323f224fdbef16e872d8e67e24af59d189071620a1827a58011d72070f45f716b10ba79e35328373e5ce72b6e0d02da667806238c05aeb97fbe58f4f0f2c4ae4140dbab986281cf443c5f2c56010fc7331a59b031121e62c8c1f7a6a680715a0a181b52c0383d058c3352c03833058cb352c0383b058c7352c03837058cf352c0383f058c0b52c0b830058cf85b95e15e31f6f7cbaa316e3beab7ca58b71df5bb64acdb963c973caf04db92e792e795605bf25cf2bc126c4b9e4b9e57826dc973c9f34ab02d792e795e09b625cf25cf7db29d86317e611c7b8cc8d3981c4f1e7d475ba77be0fbe90e9e0c93ef68abd703dfa99c36c6d529605c91024689e3d01ac4721835cf1a269ede1278d600cf194c3c6b4ae0390378d626cf13e6d41925f010430ebeb722058cab53c028719438fac42871ac9c380aa3300aa3301e0fc634f4e1729d19faed520ea3e659973c4f18b3b525f0ac8398d1f7f2bc8c85721935cffae479c298ad2b81673dc46c9d23660c8c85721935cf86e479c298ad2f816703c46cbd23660c8c85721935cfc6e479c2986d28816723c46c8323660c8c85721935cfa6e479c2986d2c816713c46ca323660c8c85721935cfe6e479c2986d2a816733c46c9323660c8c85721935cf96e479c2986d2e81670bc46cb323660c8c85721935cfd6e479c2986d2981672bc46c8b23660c8c85721935cfb6e479c2986d2d81671bc46cab2366be32ae4801e3ea143032c7b1502ea3e6d9cec4b3ad049eedc0732613cff61278ce049eb392e70973eacc1278882107df5b9102c6d5296094384a1c7d629438564e1c85511885b134c6d353c028e75a187d6564f87d15fb7cca9963dc76d4f32963dd76d4f32963ddb6e4b9e47925d8963c973caf04db92e792e795605bf25cf2bc126c4b9e4b9e57826dc973c9f34ab02d792e795e09b625cf25cf2bc1b6e4b9e47925d8963c973caf04db92e792e795605bf25cf2bc126c4b9e4b9e57826dc973c9f34ab02d792e795e09b625cf25cf2bc1b6e4b9e47925d8963c973caf04db92e792e73ed9de91bced42a9cfb0ee009eb31862c1e4675e1ff76c73ac67138c9f8ed53956acceb46295833a6743fcce61885f06ecd2b1699fec95cafc220f98996c174e50c79808fe938dd5563cb4fd73997c8feaebcf1de3b6a3fafab16e3baaaf1febb625cf25cf2bc1b6e4b9e47925d8963c973cf7c536966b82e1fb767abf923ec679a63cceec53fdd3e17b54a765fcd0e7e440da10876d694372ada804db92e792e795605bf25cf2bc126c4b9efb99e7e7276f3b9c1bc3df177a8b9b1b3b1f78ce638805939f79edd305964fe75a3ee5a00ebeb3f602063f3360978e4dfb17c079481bb3e65965cac49a857aab3c6124dd79bc3c61fb5a15146f71edeb02e06168072d4c7e86edeb42cba7558eb8531dccd50b19fc74b51ddabf10ce43da9873608f58b341f139f5819174e7f3f284edab3728dee2dad785c0c3d1ff30f919b6af8b2c9f7a1d71a73a98ab1731f8e96a3bb47f119c87b4316b9e35f077bd65a1de1a4f184977012f4f5b167ca62dae7d5d043c1cfd0f939f61fbda69f9b4c61177aa83b9ba93c14f57dba1fd9d701e8459985dcc9ae70c5326d62cd43bc31346d25dc8cad396cf82cfb4c5f5633b8187a39f678a7bd88f5d6cf9748623ee540773f562063f5d6d87f62f86f3500af3ea14324b9c25ce51cc1267897314b3c459e21cc52c71963847314b9c25ce51cc1267897314b3c459e21cc52c71963847314b9c25ce51cc1267897314b3c459e21cc52c71963847314b9c25ce51cc1267897314b3c459e21cc52c71963847314b9c25ce51cc1267897314b3c459e21cc52c71963847314b9ccb63d63c6b4d9958b3506fad278ca4bb8897277c7e676d50bc65acfd5e285f0c3c3b19e2c3e467b8eefd12cba7b58eb8531d6c5f9730f8e96a3bb47f099c87529857a79059e25c1eb3e65967cac49a857aeb3c6124dd4e5e9eb01f5b17146f71fdd825c0c3d1cf33f919f663975a3ead73c49dea60fbba94c14f57dba1fd4be13c08b330bb9835cf7a5326d62cd45bef0923e92e66e52984cf21ae0f8ab7b87eec52e0e1e8e799e21ef663bb2c9fd63be24e7530577731f8e96a3bb4bf0bce4329ccab53c82c71963847314b9c25ce51cc1267897314b3c459e21cc52c71963847314b9c25ce51cc1267897314b3c459e21cc52c71963847314b9c2b27ce9a678329136b16ea6df084917497b0f2b486f30e1b82e22d6ede6117f070cccb30c53d9c77b8ccf2698323ee5407dbd7650c7ebada0eed5f06e761ac33af4e21b3e4c6e8304b6e087314b3e4863047314b6e087314b3e4863047314b6e087314b3e4863047314b6e087314b3e4863047314b6e087314b3e4863047314b6e087314b3e4863047314b6e087314b3e486304731fb901b9a67a329136b16ea6df484917497f2f284ef3dd818146f71eb762e039e5d0cf161f2335cb773b9e5d34647dca90eb6afcb19fc74b51ddabf1cce83300bb38b59f36c326562cd42bd4d9e30926e172f4fd88f6d0a8ab7b87eec72e0e1e8e799fc0cfbb1dd964f9b1c71a73a98abbb19fc74b51ddadf0de761b7300bb38359f36c366562cd42bdcd9e3092ee325e9eb01fdb1c146f71fdd86ee0e1e8e799fc0cfbb13d964f9b1d71a73a98ab7b18fc74b51dda277bc22ccc51cc9a678b29136b16ea6df184917497f3f214b2e0336d71fdd81ee0d9cd101f263fc37e6cafe5d31647dca90ee6ea5e063f5d6d87f6f7c279481bb3e6d96acac49a857a5b3d6124dd6e5e9eb07d6d0d8ab7b8f6b5177838fa1f263fc3f6b5cff269ab23ee540773751f839faeb643fbfbe03ca48d59f36c336562cd42bd6d9e30926e0f2f4fd8beb605c55b5cfbda073c1cfd0f939f61fbeab37cdae6883bd5c15ced63f0d3d57668bf0fce43da9835cf765326d62cd4dbee0923e9b09fa2ad0a18b7333106166360c507791678c633cb339ea99ef14cf48ca7da339ea59ef1747bc6d3e519cf42cf78167bc633db339e82673cd33ce359ee19cf24cf78da3de3a9f18c6799673ca779c6b3d2339e399ef13478c6b3c4339eac673ce33ce369f28ca7c7339e0ecf78e67ac6d3ea19cf74cf789a3de3a9f38c27e7194fad673c3b3ce399e719cf0ccf784ef08c67b2673ce33de3e9f48c67be673c6d9ef1ccf48ca7c5339e299ef1d47bc633c1339e459ef1643ce0c906cf5d379085bfef005d95f55d7d7dd9d030fc779aa7ad82eff49b72b5e3d87da0a379dd7ec777314e5c73cf68ab17f6c95e1d70f47bc2b3c8339e099ef1d47bc633c5339e16cf78667ac6d3e619cf7ccf783a3de319ef19cf64cf784ef08c6786673cf33ce3d9e1194fad673c39cf78ea3ce369f68c67ba673cad9ef1ccf58ca7c3339e1ecf789a3ce319e7194fd6339e259ef13478c633c7339e959ef19ce619cf32cf786a3ce369f78c6792673ccb3de399e6194fc1339ed99ef12cf68c67a1673c5d9ef1747bc6b3d4339e6acf78267ac633d5339e599ef12cf08ca7cac1b3838927ead9dd1d9ed866380f797ddcfd4c3e5d618e556b8e4bfc64af06ead49b81473ddf80df252e7bbe1dc796af801871bd372167f1d0febe316e7bb2657b7285d8aeb76cd757886dc973c9f34ab02d792e795e09b625cf25cf7db4fd6c72b6db31cfaac0960feba3e5fd49f13cf2fea4789e6acf78e4fd49f13cf2fea4781e797f523c8fbc3f299e47de9f14cf23ef4f8ae7f1edf978799f533c8fbccf299e47dee714cf23ef738ae769f28c47dee714cf23ef738ae791f739c5f3d479c693f38cc7b7f739c9fb93e279e4fd49f13cf2fea4781e797f523c8fbc3f299e47de9f14cf33c1339e459ef1643ce079bef727e17b8f68ade53ed0d17aceb8f72c65e13857808ec607e918fa7a7576c37319aae03b573ab8f63bec919d2b1ddf1d8db8a3ad5ed8277bf83ea62b3de159e419cf04cf78ea3de399e2194f8b673c333de369f38c67be673c9d9ef18cf78c67b2673c2778c633c3339e799ef1d47ac693f38ca7ce339e66cf78a67bc6d3ea19cf5ccf783a3ce3e9f18ca7c9339e719ef1643de359e2194f83673c733ce359e919cf699ef12cf38c6787673c359ef1b47bc633c9339ee59ef14cf38ca7e019cf6ccf78167bc6b3d0339e2ecf78ba3de359ea194fb5673c133de399ea19cf2ccf781678c653e5e0e17a27522e18de7a617f34dec7f47cb6f5fe52888bdeb2f0f7d1784e7287c548fbb8ce0079896729134fd473ef4b3db0adfda7df5a34679185bfe373385c39b5d462a47d574ee13ac2654c3c51cfeb2ff3c0b68e459329d31c7716fede048c5c39b5cc62a47d574ed5f3f2b465c167dae2d6f6609be338874c7ee6b1fd25f88e88bc8ed5762b564d56ac725067349e138cea0fc89e300b7314b3e6a1b11662c5ebd9683c273d1246d7f5958127ec1f9707c55b5cffb81d7838ae1f4c7e86fdd801cba7e58eb8531dccd5030c7ebada0eed1f70d86e0c928dc5552388c5550e9eab46391664af54e61d2964f621ce9a87d64e102bae276ef68491744b7979c2feb13928dee2fac7ab8087e3fac1e467d8275c6df9d4ec883bd5c1f67535839faeb643fb57c3792885f9400a9925cee5316b1e5a534dac59a8d7e20923e9b6b3f214f259f099b6b87eec6ae0e1e8e799e21ef663072d9f5a1c71a73ad8be0e32f8e96a3bb47f10ce83300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb330fbcdac79e8591562cd42bd82278ca4bb8a956768dea110146f71f30e078187635e8629eee1bcc321cba78223ee540773f510839faeb643fb87e03c08b3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3300bb3dfcc9a87dee94aac59a8d7ea0923e9aee6e5099fdb6a0d8ab7b8798743c0c3312fc3e46738ef70d8f2a9d51177aa83b97a98c14f57dba1fdc3701e8459985dcc9a87feaf0762cd42bd364f18497790956768feb42d28dee2fab1c3c0c3d1cf33c53decc7062c9fda1c71a73a98ab030c7ebada0eed0fc0792885f9400a9925ce12e7286689b3c4398a59e22c718e6296384b9ca39825ce12e7286689b3c4398a59e22c718e6296384b9ca39825ce12e728668973e5c459f3d0ff5145ac59a8d7ee0923e90eb1f2b486f30eed41f11637ef30003c1cf3324c710fe71d8e583eb53be24e75b07d1d61f0d3d57668ff089c87b1ce7c2085cc921ba3c32cb921cc51cc921bc21cc52cb921cc51cc921bc21cc52cb921cc51cc921bc21cc52cb921cc51cc921bc21cc52cb921cc51cc921bc21cc52cb921cc51cc921bc21cc52cb921cc51cc921bc21cc5ec436e689e0e5326d62cd4ebf0849174877979c2f71e7404c55bdcba9d23c033c0101f263fc3753bd7583e7538e24e75b07d5dc3e0a7abedd0fe35701e8459985dcc9aa7d39489350bf53a3d6124dd002f4f210b3ed316d78f5d033c1cfd3c939f613f76d4f2a9d31177aa83b97a94c14f57dba1fda3701ed2c6ac79ba4c9958b350afcb1346d2e175b98b892767f1e41cb1385eb6f57eb729d799cf2cfcbd1b18b9fac32e8b91f631c7919778ba9978265b3c931db1385eb6b5ff2b4df904f39985bfaf0446ae9ceab61869df955393816725134fbdc553ef88c5f1b2ad63d163ca53cc6716fede038c5c39b5d262a47d574ed5034f0f134f549fd4330ab6a3dad768d88eca95d1b02d318f8e3943bb0bc7077a82e22deebe1aaf2d1c7d15939f79d7f5bbc7f209afdf788f7abcae4fc22ccc51cc4cf7b96d59cb36c527b07868bb863916a3f93bbbdbf2290dbfb3e3980fa49059e25c1eb3b67d2c79db6d59cb36c527b078683bc61c0b263fc3fe603070c798ece5a00ee6e920839f19b04bc7a6fd41380fa5301f4821b3c4b93c666dfbdac46d0fbd7f186d537c028b87b66b9963c1e3e7507f705de08e31d9cb411dccd3eb18fccc805d3a36ed5f07e74198855998855998855998855998855998855998855998855998855998855998fd66d6b6af4fdcf6d0f83ddaa6f804160f6dd733c782c7cfa1f1fb1b02778cc95e0eeae039bf81c1cf0cd8a563d3fe0d701e84599885599885599885599885599885599885599885599885599885599885d96f666dfbc6e46d87cfe3a06d8a4f60f1d07623732c98fc0cc7ef6f0adc31267b39a883e7fc26063f3360978e4dfb37c17910666176316bdb37276e7b683e0f6d537c028b87b69b9963c1e3e7507f704be08e31d9cb411d3ce7b730f89901bb746cdabf05ce4329cc0752c82c71963847314b9c25ce51cc1267897314b3c459e21cc52c71963847314b9c25ce51cc1267897314b3c459e21cc52c71963847314b9c2b27cedaf6ad89db6e0dc7efd136c527b07868bb9539163c7e0e8ddfdf16b8634cf6725007f3f436063f3360978e4dfbb7c17918ebcc0752c82cb9313acc921bc21cc52cb921cc51cc921bc21cc52cb921cc51cc921bc21cc52cb921cc51cc921bc21cc52cb921cc51cc921bc21cc52cb921cc51cc921bc21cc52cb921cc51cc921bc21cc52cb921cc51cc3ee486b67d7bf2b6c3e7d9d136c527b07868bb9d39164c7e86eb5fee08dc31267b39a883797a07839f19b04bc7a6fd3be03cdc21ccc2ec60d6b6ef4cde76216bd9a6f804160f6d7732c782c9cfb03fb82b70c798ece5a00e9ef3bb18fccc805d3a36eddf05e7216dcc78fe32c9d90ed76d928d2af3a9752f36e56ad0bdc4946b40f752531e07ba9799722de85e6ecae3417737f846ba5798f212d0bdd2947b40778f29af04ddab4cb91b74f79a7217e85e6dcad780ee35a67c1474f799f231d0bdd6940741f73a53be1674af37e5eb40f70653be1e746f34e51b40f72653be11746f36e59b40f71653be19746f35e55b40f73653be1574f79bf26da07bbb29df0eba7798f21da07bc0947780ee41539e08ba874c7912e8fe03caf4f94e53ae03ddbb4c3907ba779bf209a07b8f294f06dd7b4d790ae8de67caf5a07bd894a782eefda63c0d741f30e506d07dd094a783ee11539e01ba0f99f24cd07dd8946781ee23a63c1b741f35e539a0fb9829cf05ddc74d791ee83e61caf341f749535e00ba4f99f242d07dda94f1fc7ec694ef041df51777818efa8b17838efa8b97808efa8b97828efa8b97818efa8b97838efa8bbb414779f70ad051debd12749477f7808ef2ee55a0a3bcbb17749477af061de5dd6b404779771fe828ef5e0b3acabbd7818ef2eef5a0a3bc7b03e828efde083acabb37818ef2eecda0a3bc7b0be828efde0a3acabbb7818ef2ee7ed051debd1d749477ef001de5dd03a0a3bc7b10748da6fc10e84e3465ec3f4e32e57782ee64537e17e84e31e57783ee54537e0fe85e64caef05dd69a6fc3ed02d32e58741b7d894df0f3aba867d00744b4df983a05b66ca8f80aec9943f04bae5a6fc61d0359bf247409737e58f82aec5943f06ba82297f1c74ada6fc09d0b599f22741d76eca9f025d87297f1a749da64cfd876ea7babd91cf148f3af0afc9c14dba09c0dd1b247b0f46b6e8d8b45f00468a77cbe8331646ca98b718354f1b43cc3087688bfb8dd3063cad0c3c4c7e86bf71da2d9f0a964f39a8f322f0b39dc1cf0cd8a563d37e3bd8e638e7188b5a73dcd3ac58d4409d59e6e2a5af937171a463e8fc6d71f8c215c7bcc59377d8ee628e231d9bfac4ae51b0dd61d96eb66c63bf4f5b5cdbee00e64e06667ddceee48f1bb6ed15e65894cf64a7197c5a093148ca27b49d314276485f03e5e686e1ba548fe241d74e62d7ed88ce25b2dbdf6bb3be97833a5d0eff7b8364fdefb678ba2d66fd3be19486610e86f610e64097c541fbcd10bbee88d87541eca80e5e7bf34cb1ebb478683f0f3c747fd50e3aba4f217ebc9f6b1a056ebbdf6b777093ae0318f30ec6e6e4190b71d7856660245d27f07430c5cc3ed7a759f1c17b82f1561dfa6e0dd45907d7e5aca3ae6e77f332c37ed1effa678364fbf45a8678e1984300f109ac18d2460c1382e1718924792605c3e30ec706078eeeb9a2ff9cfe3d7d1940abb130f133e370a30a7458ae76e882a0787805876f697805876fabacb0e0b00ed5d73fe3b45b3484d17fe8c0e0f987fb0fef3b7ae391c1febe6d035720f5388b1e49a33c4052d4d13621181e08ea0d929db8a9b56cc525cf04f81c9f3c4f0b939fe1456fa2e553ade5530eea8c83bf4d64f0330376e9d8b43fd1613bc18e288cc5a411c462928367d228c70207d349872d95fe8e132d55962fd8a2d1273bcf1375880c9e0ac7cf1838fd37ddd8c71967c607c3279b7a4f7d47ab4f821e85d5572d3dcaaa47557517a4474df5054d8f8aea51503deaa94739f5a8a61ec5d4a3967a94528f4aea51483dead8180c8d2aea51443d6a780a703d0aacfad7bcbe3aea513f3dcaa747f5f45d95feb5a6ef44f49db7be2bd07703faae4fffa2d5a31bfa4aabef62f4155a5f55f55da2be3bd477f3faee56cf66ad52b25ac9e926d66b949ca164ad92754ad62bd9a064a3924d4a362bd9a264ab926d4ab62b3953c959c1d068fdd94ace5172ae92f3949cafe40225172ab948c94e25172bb944c9a54a7629b94cc9e54a762bd9a364af927d4afa94f42bd9afe40a255706432b78ae5272b592834a0e2939ac6440c9916068464dcfa0e919333d43a667c4f40c989ef1d2335c7a464bcf60e9192b3d43a567a4f40c949e71ba23189a5dd0b3097af640cf16e8d9013d1ba047ffef0e8646f7f568fe3dc1d068bd1e9dd7a3f17af45d8fb6ebd1753d9aae47cff568b91e1dd7a3e17af45b8f76ebd16d3d9aad47aff568b51e9dd6a3d17af4f9a1606874598f26ebd1633d5aac4787f568b01efd7d38181addd5a3b97af4568fd6ead1593d1aab475ff568ab1e5dd5a3a97af4548f96ead1513d1aaa473f3fabe4734a3eafe40b4abea8e44b4abeace42b4abeaae46b4abeaee41b4abea9e45b4abeade43bc1504e7e57c9f7947c5fc90f94fc50c98f94fc58c94f94fc54c9cf94fc5cc92f94fc52c9af94fc5ac96f943ca6e4b74a7ea7e4f74a1e57f207257f54f284922795fc49c99f95fc45c9534afeaae46f4a9e56f27725ff50f24f25cf04c3b324d871d498de8646ecf70c0ef61f3a32d83838d078e8da8383078e1cbcb1f1fa038357360e5cd77f74ffc181ebf1cb5f375fa6e98835478feeb9b1f1c0e1befe1b1a07ae1d6c1cd8dfb877e0dac37dc7f04b4f982fcd7baec53d7d7dd1c6fef38590fe779946ab4d3f48133d9be37dabad2e232075e57c295f5d9e437973a5a1d9f97387ee701b8f1d1c186ccc371e56ffee39a8bed3dfb7bc11ff764c05f9d860e3b1c13d47071bf71f1d38d4d8b21c8f3ba5ae0c27663694f1a5b50d23f73cf87f8198955c01d50300", + "packedBytecode": "0x000000028df71de5000000468d1f8b08000000000000ffed9d07741d45b6ae5bb61ce0481893b3450e06a3e49c64724ec6608c31b62c0b1b0739623298e81cc8c10639e78c718e18c3cc30393381811926dd3b7367ddf5e6be77df7a8f75bbcea9bdf4ab5c7daca3e992ff2355af5552f53ed5bdbffa7b7775aaeeca0952d33fc294a3f3cdc3744170f824bf97e9ff85ffda5414e3ba0a5d72e6640967b32ce16c9e259cb959c2d9224b385b660967ab2ce16c9d259cc7c4c8a9d89a05b5a7b8798f75a06bdc8c892cd3342f0b34cdcf324d8fcb024ddb04d9d1461d9f259c6db384f3842ce13c314b384fca12ce93b384f3942ce13c354b384fcb12ced3b384f38c2ce13c334b38cfca12ceb3b384f39c2ce16c97259c0559c2796e96709e97259ce76709e70559c2796196705e1423677be0bc58ffbf44ffbf54ffbf4cff97b297ebff57e8ff1d741d73f5fc958a2b4cea214db1f15b49984ac3d4314c9d8cdf3a87a94b98ba86a99bfead40ffd63d4c3dc2d4334cbdc2d45b6bd0274c5785e9ea305d13a66bc3745d98ae0fd30d61ba314c3785e9e630dd12a65bc3745b986e0fd31d61ba334c7785a96f98ee0e53bf30dd13a67bc3d43f4cf7856980c1727f980686e981300d0ad383611a1ca621612a0fd3d03055846958982ac3f4509886876944981e0ed3c8308d0ad3e8308d09535598c686695c98c68769429826866952981e09d3e4303d1aa6c7c2f4b8a1d913617a324c4f85e96983f399303d1ba629617a2e4ccf87e98530bd18a697c2f47298a686695a98a68769469866866956986687694e98e686695e985e09d3ab617a2d4caf87e98d30bd19a6b7c2f47698de09d3bb619a1fa605617a4fb3c88ef07e98aac3b4304c8bc2b4384c4bc2b4344ccbc2b43c4c2bc2b4324cabc2b43a4c6bc2b4364cebc2b43e4c1bc2b4314c9bc2b4394c1f84694b983e0cd3d6306d0bd3f630ed08d3ce30ed0ad3ee30ed09d3de30ed0bd3fe301d08d347613a18a68fc374284c9f84e9d3307d2b4cdf0ed377c2f45998be1ba6ef199a7f3f4c3f08d30fc3f4236dfbb1feff135d56eedffd344c3fd3f99febffbfd0ff7fa9ff7f6e2cf3ab30fddab0fd264cbf356c5f84e9773affa5feff95feff7bfdff0ffaffd7faff1ff5ff3fe9ff7fd6ffffa2ffff55ffff37fdffdff5ffbfe9ff7fd7ffff43ffff47981e2848e55b0735535910531b555a997cf623e25f1cd49e9416cdf56ff2bf40db73f5bcfc17ed5ae8f91686bda59e6f69aca7b59e6f6dd8dbeaf9b686fd443d7fa2613f59cf9f6cd84fd5f3a71af60bf4fc05604f04706f58db95adb936e5804de2b519d85a685b73b0b594d581ad95b6b5009b6cdf96603b46db5a81ed586d6b0db684b61d235a86294fdbca82b862a570885a6f7edcebd5cfcb8e8b9f77a85a6f1b47bcc7c7cf3b4cadb7ad035e151f27e8751d0f7173a2b6b505db49da7602d84ed6b613c1768ab69d04b653b5ed64b09da66da780ed746d3b156c6768db69603b53db4e07db59da7606d8ced6b633c1768eb69d05b676da7636d80ab4ed1cb09dab6dedc0769eb61580ed7c6d3b176c1768db7960bb50dbce07db45da7601d8a4fdbd106c72be7891b6a9b6e3981c5846dba5dd4a2e236d36d82e95f61a6c97495b0db6f6d24e83ed72f02db62ba0ad115b076d93764bfdd64de7cb82b8f693e24ab5deee71af375cb35a6fcff8d79b7ce6d82ba8d1b50cfc7407ad7aeb7c8cfd9a8ad0778e4ee247ecb990bf09ca4a39d1438e3dc2ae8e313d74be779ae5ba19cbe543991e96fa9705f1d6bfa7c1d3d3606e017937315b52e263b6ce53c631db1fca9ab127e7418d31666f050e0731dbd9c76c9da78c63b612ca9ab127e7c28d3166ef070e07315bee26668b0b7dcca6ee9b05813df6e47aa831c6ec08e0883f663bfa98adfb9471cc3e0765cdd8936be2c618b3938123fe98ed5ceecf0dea3c651cb373a1ac197b727fa631c6ec8bc0e120662b7d3b5be729e3987d0fca9ab127f70a1b63ccbe0a1cf1c76c5747315be26336483d030d027becc97debc618b30b8123fe981deaefcfd67dca386677405933f6e4194a638cd9f53aaf9e33fc583f67380b6c3fd1b6b38137fed8aee8e828b68b7d6ca7fa8604813d46e5795e638cedbd3aafe2f8e7d01f416cbfd0b673c1f64b6d3b0f6c9f6bdbf9502f07fb40b9df07ea3c65bc0ffc1aca9ab12ccf961be33ef043e07010b3153e66eb3c651cb37f85b266ec493f87c618b35f00878398adf4315be729e398fd3f50d68cbd4b74be31c6acf43555e70b5feaf385cbc0f695b6b507dbefb5ed72b0fd41dbae00dbd7dad6016c7fd4b62bc1f6276d2b04db9fb5ad086c7fd1b662b0fd55db4ac0f66fda560ab67fd7b68e60fb9bb67502dbdfb5ad33d8fe43dbba80ed1fdad655dbd4f32ee97b25e7adad81b52c886fdb26401799728cf932c817bbe529cc071ef4551abfaf1255f792a0ee752f059e8e0eea9e001f75e1e9083c9de2e749f645ed1cff7a93dbb8c4d03401be4aa05e5d1cd42b077cc9ba655efce5830df7f32e16c6aef13316e7802f59b7cc770546b161bb23efffc8fea3dae673736a781dec4bc9e333fa2b030ef1970b65fed9aea6ec859a2d0f7ec736b89361731497c9b8105fb26e99177f79509f4e0dcf585c57c68e06a3ab3622077cc9ba4ddf79902f72ab4f5a9ece24be1d9c775bdb34d1bc7b03f8ee6af82e357c63db2953ba635b57608efdfa471fdb7ac4bfde423c5796eb14f183e70f783d11579dd0b75ca7881fb1e742fe869c9ab2524ef4907658d8d53e2cdb12d9cde5ba18cbe54399ee96fa9705f1d6bf87c1d3c36056c79b9e702c74b03f2463a0bbc121f3a5a05d8f08edba837652e612d0cec1b96752bb6e068fcc77041e69bfb13d2b6a609e2202df780e8bd772f23b9e07b8da5e4506a3ccdbb6575760ec686174704e589cee78580a8c62eb063c258e348bdaae2524be5d5c57e6800f393737af6d72a1ccedcd6bca56e438652bc6736799ea7acd1bff762a2ec4fda32e3c8ef7a12247f15888f76fbe09e28d35b35d32db9ba87b3caedaf2128347e6c59f67f6cc9ed9337b66cfec993db367f6cc9ed9337b66cfec993db367f6cc9ed9337b667e66c523cf13b0df9694eb44c268f67f73759f3ff92d3ebd2e7c06f44fa7fdc18a0bf1d99ff483b8cca8732e9439b1590ddb7f437f30b32f51d4b674d13736ddb6147fd81fac219e21961a3ca6ef3c8b3ef85c1a3573d507ca6c33641efba7897e45c0e36a7f2c36784cdfd86694906a16d5cebaead3171567b6fe8405b1f92e1eeaeab9aefaee99fa76a879fcea64689afc26a961536dd25dcd6beaede2396fa6cf9df1b821f9389fe362bf0cf4157f3b5b5cab7f42b3a0f6b10263dd555f2dd9afa46f4477c3772e9439b759cdb6c13e7565c1e1c706ece325eb96652e83657b18eb6ee3aebe69fba174076ec9b734ead619b8a5cc4570ecfea9ce3b3a061667fa8e041e93e33fbea4fa8b9464c083c73b17e72c8e8ea385188f71f71731fb41dace97a50cf62175d07f37edb158fc7966cfec993db367f6cc9ed9337b66cfec993db367f6cc9ed9337b66cfec993db367e667563ce633747cf65b4ac2d8407d6c92cf33e4fb6cf85c6c6bb31abfae9f01ca33a7f6469df11de55c784779a766c3be0ff85d29dbb674f56c2d6a5b8a3fb6be0f79167d94663d2c9a39f8ae63da6f76e0371245bf1ec0e36a7f8cfa7687adcd2822d52caa9d75d177215d9cd9fa2914c4e63bd55fc4c5735de92f621ebfccef1a613f09b1e173f0a8ef85151bb6a3dd06d8fab5491ebfb9e0628c1b8c67b3afa0f8c37e125f686da59f44fced4071a1cb6384eca3d227a4c4525729f387663565ffa8f3d857a814d6f54fcbef32a5eb93806daa83efc726b7afac4bb6afeddbb57d803526df45b8ae1c9dfa181ae442fe7f35ab292be5a4ac682dec6a1f91ef4a21bbb95c4763b97c28d3cb52ffb220defa9bdf12ee6d30abd8f90bc4d93fe15ccf559bd42b42a3cb40232983e7bcaefad59a6da4d9671afb44b632cae0f9a994f9ffd04645f549b7f5a97475be10d59f13cf176ce734661dcdbee34dbd3f60bebe0e71d11f50d6dd26a8dd272f30d6df1ed62f5cad82e8638b94690beb3f9adfbdb25dfb092ff6379432a7c0b5df0d3a9fc9b5dfd1ba8eb75dfbe1725175c77621ee6323c623b2602c4b9902231e7b447077b52c7b7ec4b2a295f9ed43bc2ec57384f8bf1b996a6f7a1b75917d0abfef2f652e35f69bf8cf9952e79faebe9129eb9236a8d8525729d301f6b5429d4fc076c2778a7a5b7e9729ddf9a7e8a7ea7c55fc754e6edfabf5ba64fb5e65f17d0db0c6e4bb087dcbf9a7f8117b2ee47bc1f144ca891ea2b5b0ab7d44cee190dd5caebbb15c3e94e963a97f59106ffdaf3278ae329855ec94409cf586772d5cb5d57d22346a0f1a4919bc776dfbaeb1ed5e47439da79adf4bcf0f0eff762f1e27dd9cb3d9df9533efdfdace4fda1bfc787e722bb4b3094b59f3beb42c1767ff747c1f08cf0bf17d2057d748f9416d3df30d0e97bedb18bedb34a0efb686efb60de8db6bee3567d29c69cc1f7c0ed90c185d1cebf0b85a1746dbf1af3930ba7a67b3240346fce6351eef84d1c577c2eb3ba6109eebb4004617ef1b677abfba1330e2370684d1c53bda997ea71adfdb96e55a01a38b718d700ca5ba30dac63a6a0dff1d8c6b5454df714070aca36380d1c5d82089a0f678264762ec068cb2dcb1c0e8e2395222a87d5fed488cf8bc52964b38664c776c77dcf7a738d37b100dd1af20ea5c037d3bb8ff5f8c7d13eaa2454fb73c69cf7dd0b783fb5f492d702ccb236981cfe75c8cad99086a3f0b3b120f3e4394e54e00c632478cbd33602c034659ee4460ece388b12c03c63ec028f69380d1c17dc824639f0c18f17e9d2c7732305eed88f1aa0c18af064659ee146074714f31017eebc2780d30ca72a702e3b58e18afc980f15a6094e54e03c6eb1c315e9b01e375c028cb9d0e8cd73b62bc2e03c6eb8151963b03186f70c4787d068c3700a32c772630dee888f1860c186f044659ee2c60bcc911e38d1930de048cb2dcd9c078b323c69b3260bc191865b97380f116478c3767c0780b30ca72ed80f156478cb764c0782b30ca7205c0789b23c65b3360bc0d1865b97381f176478cb765c0783b30ca72e701e31d8e186fcf80f10e6094e5ce07c63b1d31de9101e39dc028cb5d008c773962bc3303c6bb805196bb1018fb3a62bc2b03c6bec028cb5d048c773b62ec9b01e3ddc0d8d7c2d8cf11e3dd1930f6034659ee7260bc277ec6e4b574bf0c18ef019e7be3e7496a764f063cf7bae5497e43f11e8baffbe2f795dc16fd83bad7fd3ee019103f4f725bdc97018f30e4c372a8d9fdf13326351b9001e3fdc033307e9ea466f767c0331034bbdfa2d903f13326351b9801e303c033287e9ea4660f64c03308347bc0a2d983f13326351b9401e383c033387e9ea4660f66c03338a8d1ec418b6643e2674c6a363803c621c0531e3f4f52b32119f0948366432c9a0d8d9f31a95979068c4381a7227e9ea4664333e0a900cd865a341b163f6352b38a0c1887014f65fc3c49cd8665c053099a0db368f650fc8c49cd2a33607c087886c7cf93d4eca10c788683660f59341b113f6352b3e119308e009e87e3e7496a3622039e8741b31116cd463a627c3803c691169eb8bf89feb0c5d76847751f15d4bdeec2900fcb613f89318e184767c03806186539ec2751e588714c068c55c028cb251c33a6eb275105bec7c6ef3bd92e550575d767ac5b9eb4fd24d0f738475a8c0deaaec538b73c69fb49a0eff18eb41817d45d8bf1c033c1811609f051171e61c887e5b09fc444478c1332609c088cb21cf69398e4887162068c93805196c37e128f38629c9401e323c028cb613f89c98e181fc980713230ca72d84fe251478c9333607c14186539ec27f19823c64733607c0c186539ec27f1b823c6c732607c1c186539ec27f18423c6c733607c02186539ec27f1a423c62732607c12186539ec27f19423c62733607c0a186539ec27f1b423c6a732607c1a186539ec27f18c23c6a733607c06186539ec27f1ac23c66732607c16186539ec2731c511e3b319304e0146596ea463c674d72f531ab9efa86b95c6ee3beabaa4b1fbf671eee3bc29f8f671eee3bc29f8f671eee3bc29f8f671eee3bc29f8f671eee3bc29f8f671eee3bc29f8f671eee39cc9f7730e7c27c0874c39c67c19e485211f961be9191b3523f214c4c7538875475fcf13d4fd790b4f8ea3baa3af1708ea2e0cd9c6f85c16308ecc0246af63aa0f627d1815cf8b8e785ec880e745e079c911cf8b19f0bc043c2fc7cf938ca99732e011867c586e6416303e97058c5e47af2313a3d7b1e9e8e8193da367f48c4783311bda70cf9815f1585c5f46c533357e9ea4662f67c033153493e5ee75cb585c5f46c5332d7e9ea4665333e099069a4db568e680b1b8be8c8a677afc3c49cda665c0331d349b66d1cc0163717d1915cf8cf879929a4dcf8067066836dda29903c6e2fa322a9e99f1f324359b9101cf4cd06c864533078cc5f565543cb3e2e7496a3633039e59a0d94c8b660e188bebcba87866c7cf93d46c56063cb341b35916cd1c3016d79751f1cc899f27a9d9ec0c78e68066b32d9a39602cae2fa3e2991b3f4f52b33919f0cc05cde6583463651c99058ccf6501a3631d8bebcba878e639e2999b01cf3ce079c511cfbc0c785e019e57e3e749c6d42b19f008433e2c37320b189fcb0246afa3d79189d1ebd87474f48c9ed13366c6f87c1630fa6ded1959191d5c5fa57d87e69546ee3bea1d9ac6ee3bea1d9ac6eedbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98f7326dfafc5efbb38d377585f031e17efd43aaa67a15aefeb7a5ddfc4a89fd2ea0d43ab570cadf2a1cceba0df1b0ef4cb01bfb26e99177f99325f4cc0ecc877f171e13a8e81fa8b8fe70c3d94ff371dd53daaad7fb391fb8e6aeb1bbbefa8b6beb1fbf671eee3bc29f8f671eee3bc29f8f671eee39cc537e673839af376f9be925ac75b3adf42cf4bf9e7613929d3af55ea7f9bc0ef432e7cfb7dc81f2b9a826f1fe73ece9b826f1fe73ece9b826f1fe77c718ef1707503f004064f9086e749329ece643c63c9788692f1dc43c67313194f2f329ec9643cc5643c33c9781e26e379898c671019cf9d643cd792f15c41c6f334194f57329ef1643cc3c878ee23e3b9858ca78c8ce731329e52329e59643ca3c9785e26e3194cc6d3978ce705329eebc9789e25e3e94ec633878ce752329e89643c9790f13c44c65348c6733f19cf71643c6dc8786e23e3b98a8ce709329e4e643cb3c978aac878a692f19493f1f423e3b9928ce746329e9e643cf3c8781e21e32922e31941c6f30019cf1d643ccdc978ae21e3798a8ca70b19cf38329ef6643c15643cd3c878fa93f1dc4cc6d39b8ce751329e12329e51643c0f92f1dc45c6d310dfe3c884670a19cf75643ccf90f17423e39940c6339d8ce762329e4a329e01643c79643cf9643c1dc8786e25e3e943c6f338194f47329e31643c43c878ee26e379918ce706329e1e643c73c9782691f1cc20e3194ec633908ce732329ee3c978da92f1dc4ec69343c093080eff4672027e7f0d6ccd8c65d567a5ba15d4fcfeb6b6378365ded1f9e69675bf0d36f956d53b966551a7b7a12e653a5ff8af4d499dd05719cc8bbf3ce0788784e776329eb6643cc793f15c46c633908c673819cf0c329e49643c73c9787a90f1dc40c6f32219cfdd643c43c878c690f17424e3799c8ca70f19cfad643c1dc878f2c978f2c8780690f15492f15c4cc6339d8c6702194f37329e67c878ae23e39942c6f31a19cf5d643c0f92f18c22e32921e379948ca73719cfcd643cfdc978a691f15490f1b427e31947c6d3858ce729329e6bc8789a93f1dc41c6f30019cf08329e22329e47c878e691f1f424e3b9918ce74a329e7e643ce5643c53c978aac8786693f17422e379828ce72a329edbc878da90f11c47c6733f194f2119cf43643c9790f14c24e3b9948c670e194f77329e67c978ae27e379818ca72f19cf60329e97c9784693f1cc22e32925e3798c8ca78c8ce716329efbc8788691f18c27e3e94ac6f33419cf15643cd792f1dc49c633888ce725329e87c9786692f11493f14c26e3e945c6731319cf3d643c43c978c692f17426e379928ce76a0bcf6b8e78e47d7759b7ccbf46e2dbc1762854eb7dd7519de6eb75b5d4eb157ef1970b658a8e4dfd57cf877059e132bf4f807dbfe783466f39aa8b3926a6ccbfd5c87db7317cb76922bedb1abedb3611df3ece7d9c33f99e1fbfef62fcb68d4c39c67c19e4f1f8e2e29b408eea59ebd8fe4d8cfa29ad16185abd6568950f65de05fd1638d0cf76be20f3e22f53e68b0998312e0a8278e3e2bdf8eb54acfad21c03babe67e88bf57adf91a651c790f71bb9efa8634863f71d750c69ecbe7d9cfb386f0abe7d9cfb386f0abe7d9cfb3867f25dadf3315e3716a20f75ef57ae07aac1ef229dcf89d1af5ad742bdae167addc2b10878a4cc2b702fdaeff37e9f8fcbb73fb6f9386f0abe99e3dccccb33c44b80cdd533dea8586c88e7cb47d377542c3676df51b1d8d87dfb38f771cee47b71fcbe93cf105f0b6a4fe99e212e069e850eb47054cfe4b5d312a34eaf1975ca8732d550cf250eea99037e65dd32bf04b643b6312b9e293a8fe3bb48b929248c625be89627b97f4d096a4fe9f6af25c0e3603f287254cfe4feb5d4a8d3148bee52a61aeab9d4413d6dfb8ecc2f85ed906dcc8a47dedd15d604947b8184516c8bddf224f7af1782da53bafd6b29f0b8687f1cd533b97f2d33eaf482457729530df55ce6a09eb67d47e697c176c83666c5236399086b02cabd48c228b6256e794a13506799d2ed5fcb80c745fbe3a89ec9fd6bb951a7172dba4b996aa8e77207f5b4ed3b32bf1cb68367f6cc3666c523ef4c0a6b02cabd44c228b6a54e794a0b13506799d2b563cb81c7453bef48f7643bb6c2a8d34b16dda54c35d47385837adaf61d995f01db2113e6f959c85c9d85cc5e67af7314737516327b9dbdce51ccd559c8ec75f63a4731576721b3d7d9eb1cc55c9d85cc5e67af7314737516327b9dbdce51ccd559c8ec75f63a4731576721b3d7d9eb1cc55c9d85cc5e67af7314737516327b9dbdce51ccd559c8ec75f63a4731576721b3d7d9eb1cc55c9d85cc5e67af7314737516327b9dbdce51ccd559c8ec75f63a47315767213383ce8ae7659d17d604947b9984516ccbdcf224dfdf7939a83de518f365905f013ccb1de8e3a89ec97eef2b8d3abd6cd15dca54433d573aa8a76ddf91f995b01d32619e9f85ccd559c8cca0b3e299aaf3c29a8072534918c5b6dc2d4fb21d9b1ad49ed2b5632b81c7453befa89ec9766c9551a7a916dda54c35d47395837adaf61d995f05dbc1337b661bb3e299a6f3c29a8072d34818c5b6c2294f71f23dc46941ed295d3bb60a785cb4f38e744fb663ab8d3a4db3e82e65aaa19eab1dd4d3b6efc8fc6ad80e9930cfcf42e6ea2c64f63a7b9da398abb390d9ebec758e62aece4266afb3d7398ab93a0b99bdce5ee728e6ea2c64f63a7b9da398abb390d9ebec758e62aece4266afb3d7398ab93a0b991974563cd3755e5813506e3a09a3d8563ae529493e77981ed49ed23d77580d3c2e9ecb38d23df9dc618d51a7e916dda54c35d4738d837adaf61d995f03dba1b133cfcf42e66acfdc20cc3e363c7314b38f0dcf1cc5ec63c3334731fbd8f0cc51cc3e363c7314b38f0dcf1cc5ec63c3334731fbd8f0cc51cc3e363c7314b38f0dcf1cc5ec63c3334731fbd8f0cc51cc3e363c7314b38f0dcf1cc5cc101b8a6786ce0b6b02cacd206114db2ab73cc9ef1ecc086a4fe9faedac019ed50ef47154cf64bf9db5469d6658749732d550cfb50eea69db77647e2d6c07cfec996dcc8a67a6ce0b6b02cacd246114db6ab73cc9766c66507b4ad78ead051e17edbca37a26dbb175469d665a749732d550cf750eea69db77647e1d6c07cfec996dcc8a6796ce0b6b02cacd226114db1ab73cc9766c56507b4ad78ead031e17edbca37a26dbb1f5469d6659749732d550cff50eea69db77647e3d6c07cfec996dcc8a67b6ce0b6b02cacd266114db5ab73cc509a8b34ce9dab1f5c0e3a29d7754cf643bb6c1a8d36c8bee52a61aeab9c1413d6dfb8ecc6f80ed906dcc8a678ece0b6b02cacd216114db3ab73cc9fd6b4e507b4ab77f6d001e17ed8fa37a26f7af8d469de658749732d550cf8d0eea69db77647e236c876c63563c73755e5813506e2e09a3d8d6bbe549ee5f7383da53bafd6b23f0b8687f1cd533b97f6d32ea34d7a2bb94a9867a6e72504fdbbe23f39b603b641bb3e299a7f3c29a8072f34818c5b6c1314f02ea2c53bafd6b13f0b8687f1cd533b97f6d36ea34cfa2bb94791feab9d9413d6dfb8ecc6f061e99ae061e577119183c81451f999e24e3e94cc633968c672819cf3d643c3791f1f422e3994cc6534cc6f33019cf20329e3bc978ae25e3b9828ce769329eae643ce3c9788691f1dc47c6730b194f1919cf63643ca5643ca3c9780693f1f425e3b99e8ce759329eee643c9792f14c24e379888ca7908ce77e329ef7c9788e23e36943c6731b19cf55643c4f90f17422e3a922e32927e3e947c6732519cf8d643c3dc9781e21e32922e31941c6f30019cf1d643ccdc978ae21e3798a8ca70b19cf38329ef6643c15643cfdc9781690f1dc4cc6d39b8ce751329e12329e51643c0f92f1dc45c6731d19cf33643cddc8782690f15c4cc65349c633808c278f8c279f8ca70319cfad643c7dc8781e27e3e948c633868c670819cfdd643c3790f1f420e39944c6339c8c672019cf65643cc793f1b425e3b99d8c27878027111cfe2e5e027e5f003679676c1ed83ed0f98d606b66f121cf2236832d57e7651dadc2746dc1e1eb469d5cbd2787beca605efce501c707243cb793f1b425e3399e8ce732329e81643cc3c9782691f1f420e3b9818ce76e321eb91e64e11943c6d3918ce771329e3e643cb792f17420e3c927e3c923e31940c65349c6733119cf04329e6e643ccf90f15c47c6731719cf83643ca3c8784ac8781e25e3e94dc6733319cf02329efe643c15643cedc978c691f17421e3798a8ce71a329ee6643c7790f13c40c633828ca7888ce711329e9e643c3792f15c49c6d38f8ca79c8ca78a8ca71319cf13643c5791f1dc46c6d3868ce738329ef7c978ee27e32924e379888c672219cfa5643cddc9789e25e3b99e8ca72f19cf60329ed1643ca5643c8f91f19491f1dc42c6731f19cf30329ef1643c5dc9789e26e3b9828ce75a329e3bc9780691f13c4cc6534cc633998ca71719cf4d643cf790f10c25e3194bc6d3998ce749329eab2d3c0b1cf198e326c8fc0202df6abe3be8a2a604fc8edf597fdf11e3028351e6df0746e475ad591b83a78da1d9d1f4adea2fefeac83d70dc5ef8de39c3f66ad3009ab53578da1a9a1d4ddf4a0b79b62def0ce2f6c2efd4326c2f7cafda41fb5c9a3078d49463cc97417eb3637d1cd5b310dfbbfe26c6f52aadb6185a2d30b4ca87329b40bf2d0ef4cb01bfb26e99177f9ed93347312b1ee94b62fb1e403f1246b1e1b8181fc6cf539a3078d494ae7dfcd0b13e8eea996cc7b60676dd3f04dda50cc6ea5607f5cc01bfb26e99df6af15d10c4abc5b63a68b1cdc2b3ad81b5107f99326fca4266069d158fbc6b20ac0928d79f84516c5b80677bfc3ca50983474de9dac7ed8ef57154cf649bb023b0ebbe1d749732b87fed7050cf1cf02beb96f91db01d3261de9a85cc5ee7fa312b1e79475b5813506e0009a3d8b601cfced8798a0b13068f9ad2b5633b1debe3a69ea9766c5760d77d27e82e6570ffdae5a09e39e057d62df3bb603b7866cfec993db367f6cc9ed9337b66cfec993db367f6cc9ed9337b66cfec993db367e666563c03755e5813506e2009a3d87600cfeed87952cf1d90474de99e3bec76ac8f9b7aa69e3bec09ecbaef06dda50cc6ea1e07f5cc01bfb26e99df03dbc1337b66cfec993db367f6cc9ed9337b66cfec993db367f6cc9ed9337b66cfec993d3337b3e219a4f3c29a8072834818c5b60b78f6c6cf539a3078d494eeb9c35ec7fa38aa67f2b9c3bec0aefb5ed05dca60acee7350cf1cf02beb96f97db01df67966cf6c61563c83755e5813506e3009a3d8f600cffed87952cf4f91474de9dab1fd8ef57153cf543b7620b0ebbe1f74973218ab071cd43307fccaba65fe006c874c98b76621b3d7d9eb1cc5ec75f63a47317b9dbdce51cc5e67af7314b3d7d9eb1cc5ec75f63a47317b9dbdce51cc5e67af7314b3d7d9eb1cc5ec756e3a3a2b9e729d17d604942b276114db3ee0f928769e92c284c1a3a61c63be0cf21f39d6c74d3d53cf1d0e0676dd3f02dda50cee5f071dd43307fccaba65fe206c87c6cebc350b997d6c340cb38f0dcf1cc5ec63c3334731fbd8f0cc51cc3e363c7314b38f0dcf1cc5ec63c3334731fbd8f0cc51cc3e363c7314b38f0dcf1cc5ec63c3334731fbd8f0cc51cc3e363c7314b38f0dcf1cc5ec63c333473133c486e2a9d079614d40b90a1246b11d009e8fe3e7294d183c6aca31e6cb20ffb1637d1cd533d96fe75060d7fd63d05dcae0fe75c8413d73c0afac5be60fc176f0cc9ed9c6ac782a755e581350ae9284516c0781e793f8798a13068f9ad2b5639f38d6c7513d93edd8a7815df74f40772983b1faa9837ae6805f59b7cc7f0adb21db9815cf709d17d604941b4ec228b643c0e320ee923cf9068fcc7f42e05bcd57e97c9efe8fdbab0a1819b6577e0368d6c6e069636876347dabfa8fd5f9e3f47fdc5e638191617bb56900cdda1a3c6d0dcd8ea66fa5c5389d3f5effc7ed350e1819b6575bb73cc50983474de9ce373e059e6fc7cf93bc8efb34039e6f03cfb7e2e7297254cf42b5deef007b5ceb555a7d6668f5a9a1553e944186cf1ce897037e65dd322ffe3cb3678e62c6b650581350ee131246b17d0b785cb41baaee57e875c9fa5b84e90727d6f875717f0def2db4d4eb150ef1970b65ce6e57c3f613cd9607bfcb7653f53968d81cbdf35664bbcf2bf3e22f2fb05febbbba871a75efe120f01cb46876c0a2d97e478c070c4699df0f8cb6fbbc071cf144dd77167fd8661c24d50cdf03fe08785c9d1747c599eb7d2ed3f3cb8f2c3cdfc4c75388b181be5cc42ab66d75a9bb6ddf89b1ee45f80c0b7d39d80792c7a90e7a5db27e752cf8af139d6a5e8aed831ca73a1875ce8532ff7d4e0ddbff4d739c6a161c7e5fb840dba58cfcfe8db69beb28d0eb96f9eefa3fc689d8fc31b0f673c4ee86966c9ae1bef5b145c71e16ee1e04dc188f0db1ada3ee7de0b6ee61e8c8a6196eeb4f2c3af6b470f724e066dcaf7b1a3ab26976a4fdba9f85bb1f0137e37eddcfd0914db323edd7fd2ddcfd09b819f7ebfe868e6c9a1d69bf1e60e11e40c0cdb85f0f307464d3ec48fbf5400bf740026ec6fd7aa0a1239b6647daaf0759b807117033eed7830c1dd9343bd27e3dd8c23d98809b71bf1e1cd4d6914db323edd7e516ee72026ec6fdbadcd0914db323edd71516ee0a026ec6fdbac2d0914db323edd79516ee4a026ec6fdbad2d0914db323edd7c32ddcc309b819f7ebe1868e6c9a1d69bfaeb27057117033eed755868e6c9a1d69bf1e6be11e4bc0cdb85f8f357464d3ec48fbf5380bf738026ec6fd7a9ca1239b66b6fdda51ffb28cfb217fec549fd4f8b399bc87857d495cc494a3382874d4d724d90f79bfa1d5c78656f85dff03a09fab3e5951fdc6c49f67f6cc9ed9337b66cfec993db367f6cc9ed9337b66cf2c653cb367f6cc9ed9337b66cfcccb8cef79e2f31529d710ef00d785516cf84ccac57d7e55f72bf5ba64fd2dc274fbc9357ee37f6e519c7c0e20facbfb98571a75ce85323bceae61ebabd9f0f9223e17b56dcb03b1d7a16eef9ce37bfaf82ce8683eeffcc8a2d97e8b66fb1c319a6d86ccef0346d16f3ff0b8da1f0f183ca66fdbbbe16c9a45b5b3aee23e2ace6cbe0b62f35d3cd4cdb7108a0bd537da8e090e6f4fa40eb8efba88c34cbf0980fb8583e7ee45aedeff5775da67d4e9a051a77c287331d4739f837ad675df92e96ae071d51e05064f60d147a666643c4f92f17426e3194bc633948ce702329e7bc8784e23e3b9898ce718329e5e643c93c9788ac9781e26e31944c6d38e8ce74e329e13c978ae25e3c925e3b9828ce769329eae643ce3c9788691f15c44c673888ce772329efbc878ce20e3b9858c2741c65346c6f318194f2919cf68329ec1643ce792f1f425e339998ce77a329e96643ccf92f17427e39948c6732919cf43643c9790f11492f1dc4fc6731619cf6d643cc791f1b421e3b98a8ce709329e4e643c55643ce5643ce793f1f423e339958ce74a329e1bc9785a93f1f424e379848ca7888c670419cf03643ce790f1dc41c6730219cf35643ccdc9789e22e3e942c6338e8ca73d194f0519cf85643cfdc9784e27e3b9998ce758329ede643c8f92f19490f18c22e379908ca7808ce72e329e93c878ae23e36941c6e3fa3dc04c799e21e3e946c633818ca7928ce762329e01643c6792f1dc4ac69347c6934fc6d3818ca70f19cfe3643c1dc978c690f10c21e3398f8ce76e329e53c8786e20e36945c6d3838c671219cf70329e81643c6793f15c46c6733b19cff1643c6dc97872087812c1e1df62c2ef7f1d04db3e9dc76f0b36b3ac4f9e0b4b79751cbab5e0f07537b3ac7bbf850175da1bd4d4a54ce70bffb529a913fa2a8379f197071cfb4978da92f11c4fc6733b19cf65643c6793f10c24e3194ec633898ca707194f2b329e1bc8784e21e3b99b8ce73c329e21643c63c8783a92f13c4ec6d3878ca703194f3e194f1e19cfad643c6792f10c20e3b9988ca7928c6702194f37329e67c8783e22e36941c6731d19cf49643c7791f11490f13c48c6338a8ca7848ce751329ede643cc792f1dc4cc6733a194f7f329e0bc9782ac878da93f18c23e3e942c6f314194f73329e6bc8784e20e3b9838ce71c329e07c8784690f11491f13c42c6d3938ca73519cf8d643c5792f19c4ac6d38f8ce77c329e72329e2a329e4e643c4f90f15c45c6d3868ce738329edbc878ce22e3b99f8ca7908ce712329e87c8782e25e39948c6d39d8ce759329e96643cd793f19c4cc6d3978ce75c329ec1643ca3c9784ac9781e23e32923e34990f1dc42c6730619cf7d643c9793f11c22e3b9888c671819cf78329eae643c4f93f15c41c6934bc6732d19cf89643c7792f1b423e31944c6f330194f3119cf64329e5e643cc790f1dc44c6731a19cf3d643c1790f10c25e3194bc6d3998ce749329e66643c571b3cf8bb3ab796f7c3f6814d7e7f56375e6df4baa48c3c1351f796f6183655dfdd8eeabb27a899ca607e37d457d8f700cf1e473c7b0d1ed3771ee47b8066bb0c9b62dce9887197c128f33b8151f4db053cbb1cf1ec36784cdf7990ef099aed306c8a71bb23c61d06a3cc6f0746d16f07f0ec70c4b3d3e0317de741be1f68b6cdb029c6ad8e18b7198c32bf151845bf6dc0b3cd11cf7683c7f49d07f9fea0d987864d316e71c4f8a1c128f35b8051f4fb10783e74c4b3d5e0317de7417e0068f68161538c9b1d317e6030cafc666014fd3e009e0f1cf16c31784cdf79901f089a6d326c8a71a323c64d06a3cc6f0446d16f13f06c72c4b3d9e0317de7417e1068b6c1b029c6f58e1837188c32bf1e1845bf0dc0b3c111cf4683c7f49d07f9c1a0d93ac3a618d73a625c6730cafc5a6014fdd601cf3a473ceb0d1ed3771ee4cb41b335864d31ae76c4b8c66094f9d5c028faad019e358e78d61a3ca6ef3cc8578066ab0c9b625ce9887195c128f32b8151f45b053cab1cf1ac36784cdf7990af04cd561836c5b8dc11e30a8351e69703a3e8b702785638e25969f098bef3203f1c345b66d814e352478ccb0c46995f0a8ca2df32e059e68867b9c163face837c1568b6c4b029c6c58e1897188c32bf181845bf25c0b3c411cf5283c7f49d07f9b1a0d922c3a618173a625c6430cafc426014fd1601cf22473c8b0d1ed3771ee4c78166d5864d31beef88b1da6094f9f78151f4ab069e6a473c0b0d1ed3771ee4fb824d788bc0f69ece17836d81ce97806dbece9782ed5d9def08b67774be13d8ded6f9ce607b4be7bb80ed4d9def0ab63774be1bd85ed7f95e607b4de77b83ed559d2f03db2b3adf076cf374fe2ab0cdd5f9abc13647e7af01db6c9dbf166cb374fe3ab0cdd4f9ebc13643e76f00db749dbf116cd374fe26b04dd5f99bc1f6b2cedf02b69774fe56b0bda8f3b781ed059dbf1d6ccfebfc1d607b4ee7ef04db149dbf0b6c2375fe6eb0ddabf3f780ed539dbf0f6cdfd2f9fbc1f66d9d7f006cdfd1f907c1f699ce0f01db77757e28d8bea7f3c3c0f67d9d7f086c3fd0f91160fba1ce3f0cb61fe9fc28b0fd58e74783ed273a3f066c3fd5f9f160fb99ce4f00dbcf757e22d87ea1f393c0f64b9d7f046c9febfc64b0fd4ae71f05dbaf75fe31b0fd46e71f07db6f75fe09b07da1f34f82ed773aff14d8bed4f9a7c1f695ce3f03b6dfebfcb360fb83ce4bbba6dad93fea7c41106f3bfb75503315806ff1a7cafc49e75b196564d95c2853aa3fe8a39e71a86f994a3b2cedb2b2493bfc1ed8a41d5e00366987e7834ddae177c126edf03b609376f86db0493bfc16d8a41d7e136cd20ebf013669875f079bb4c3af81ad4ce75f059bb4c3af804ddae179609376782ed8a41d9e0336698767834ddae1596093767826d8a41d9e01366987a7834ddae169609376782ad8a41d7e196cd20ebf043669875f049bb4c32f804ddae1e7c126edf073609376780ad8647ff91a6cd2368f049bb4cdf7824ddae64fc1266df3b7c0266df3b7c1266df377c0266df3676093b6f9bb6093b6f97b6093b6f9fb6093b6f9076093b6f9876093b6f947601badf33f069bb4cd3f019bb4cd3f059bb4cd3f039bb4cd3f079bb4cdbf009bb4cdbf049bb4cd9f834ddae65f814ddae65f834ddae6df804ddae6df824ddae62fc0266df3efc0266df3976093b6f92bb03dabf3d256b7069b3c2b5653e1bf38e1383ccdc097309505f1b6fd389541fe19a8bb4cd3c878c692f1bc4ec6730119cf0a329ee5643ca791f17c40c6b3998ce718329e7d643c7bc9786693f1bc43c633888ca71d19cf89643cb9643c5790f15493f1bc4ac6731119cf21329ecbc978ce20e3d944c6b3918c671919cf52329e0419cf1e329edd643cef93f1cc24e3798b8c673019cfb9643c2793f1b424e3e94ec6732919cf3c329e4bc8789690f12c26e32924e3398b8c670319cf7a329e05643cc791f1b421e3d945c6b3938c673a19cfd7643c55643c6f90f19493f19c4fc6d38f8ce754329e2bc9785a93f1f424e39943c6b3888c672119cfbb643ce790f1ac23e3594bc6730219cf0e329eed643ccdc978a692f18c23e3798d8ca73d194f0519cf85643cfdc9784e27e339968c670a19cf2c329eb7c9787e4fc65340c6b3868c673519cf49643cdbc878b692f1b420e3f9888ce715329e4a329ef7c8780690f19c49c69347c6934fc6d3818c672419cf0c329e37c978ce23e35945c6b3928ce714329e0fc978b690f1b4d2ff59787a90f1cc25e3194ec6339f8c672019cfd9643c9791f11c4fc6d3968c27878027011c01d8e4f7e660fb4ae70f814dbed7f311d8bed4f96ab0fd4ee79f05db53165b330b9f307c053679d7fa69b0c9fd992fc126ef70fc0e6c725c14ff6abe6fc1e1fccd6019f1d3dcc28ffe7e67e1923c6e6f59a62c88777ba3afb2e0f0ef29e501c7d3243c6dc9788e27e3b98c8ce76c329e81643cf3c9788693f1cc25e3e941c6d38a8c670b19cf87643ca790f1ac24e35945c6731e19cf9b643c33c8784692f17420e3c927e3c923e339938c670019cf7b643c95643caf90f17c44c6d3828c672b19cf36329e93c8785693f1ac21e32920e3f93d19cfdb643cb3c878a690f11c4bc6733a194f7f329e0bc9782ac878da93f1bc46c6338e8c672a194f73329eed643c3bc8784e20e3594bc6b38e8ce71c329e77c9781692f12c22e39943c6d3938ca73519cf95643ca792f1f423e3399f8ca79c8ce70d329e2a329eafc978a693f1ec24e3d945c6d3868ce738329e05643cebc9783690f19c45c65348c6b3988c670919cf25643cf3c8782e25e3e94ec6d3928ce764329e73c9780693f1bc45c633938ce77d329edd643c7bc87812643c4bc9789691f16c24e3d944c6730619cfe5643c87c8782e22e379958ca79a8ce70a329e5c329e13c978da91f10c22e379878c673619cf5e329e7d643cc790f16c26e3f9808ce734329ee5643c2bc8782e20e3799d8c672c19cf34329e66169e438e78e45829eb96f94304bed57bb8722f7e9ffe9f80df71fce66a478c870c4699af0646b1ed059eee8e78761b3cbb2d5a1c2ddf4a0bf9f6c71efd3f01bfe3f70a5dc554778351e66d31b51b787a38e2d969f0ecb46871b47c2b2da4efa3f42149c0ef381e9eab98ea6130cabc2da6703cd79e8e78b61b3cdb2d5a1c2ddf4a0be96b287df813f03b8e7fe92aa67a1a8c326f8b291cafab9f239ead06cf568b1647cbb7d242de3d93779613f03b8e27e42aa6fa198c326f8b291c1fa2bf239e2d06cf168b1647cbb7d242be2521df444ac0eff87d7f5731d5df6094795b4ce1f7910738e2d96cf06cb66871b47c2b2de45b7572cd9e80dff1fbb6ae626a80c128f3b698da0c3c031df16c3478365ab4385abe951683745e9ec125e0f741c0e82aa6061a8c326f8ba98dc033c811cf7a8367bd458ba3e55b693158e7a54f66027e1f0c8cae626a90c128f3b6985a0f3c831df1ac3578d65ab4385abe9516e53a2fef0c26e0f77260741553830d4699b7c5148ebf5bee8867b5c1b3daa2c5d1f2adb49077efd7e8ff09f81dc7e31cec88b1dc6094f9c1c028361cefadc211cf4a8367a5458ba3e55b6921dfd2926f3026e0771c1fcb554c55188c326f8b291cefa4d211cf728367b9458ba3e55b69315ce757e8ff09f87d3830ba8aa94a8351e66d31b51c78963be2596af02c25f2adb49077e1a40f5b027eaf02c6158e18a3626a05308a6d29f02c75c4b3d8e0594ce45b6921cf72e49d8b04fc3e16189739628c8aa965c028b6c5c033d611cf428367a1458ba3e55b6921df8e59a4ff27e0771caf7db123c6b106a3cc2f0646b12d049e858e78a2eee13584efa8fb510de13beade4a43f88eba4fd010bea3eeb13784efa8ebb786f01d752dd210bea3ee333484efa873fa86f01df57cbb217c473dab6d08df51cf1d1bfbfeed8f254deb587234dbb5a67a2cf1ed39677b3e2e7edfc589a0f6358d9a728cf932c8e3f5cb22075a38aa67215e137e13e37a6dd7f00b0dadf2a10c5ea3babafe1b67f0c8bcf8cb46668c8b9cf87c1726c087bca3ac6c72afe53db0c93d8e0560937b20f3c126f7d0de059bdccf7a076c72bfeb6db00dd7f99160937b97d81f49ee6d6e075bb9ce633f98c13abf156cf29c08fb5fc8b3be2d6093e7b5f8dc5f9eb96f069bf49bc0e7cdd2f76523d8a4ff123ee7943e68ebc126fd08f1f95ab5ceaf059b8c2981cf75bed4f9d560fb4ae7f179828cd5b9126c4feafc14b07da1f35f83ed099d5f08b6dfea3cdef3795ce7c782ed373aff16d87eadf36f82ed319d7f036c8feafc3eb0fd4ae7f7826db2ce63ffd0cf757e37d81ed179ec97f84b9ddf09b65fe8fceb609ba4f3af816da2cebf0ab69febfc2b609ba0f3f3c0f6339d9f0bb6f13a3f076c3fd5f9d960fb89cecf02db189d9f09b61febfc0cb08dd6f9e9601ba5f3d3c0f6239d9f0ab68775fef760fba1ce8f035b339d5f0c36f97e32ded395771697824dc629c17bf5f2ad922ab0c9f87bcbc1d65ae7f1b98cbc97341c6cf26dfb4ab0c9fbff1560933192cac126e3380d069b7c0b6c10d8e47b6503c12663960e009b8cabda1f6cf2ede27e6093f7297b824dc608e90136f98e4a77b0c9d8773826b07cefb21a6cf24e108e132cdfddff126cf26ef9576093f19b704c60f9c6d59360937149bf00db393aff04d8e47dcddf82ad40e71f07dbb93aff1bb09da7f3bf069b7cbff231b0c93b358f824dbea3ff2bb0c9bbd993c176b1ce7f0eb64b74fe11b0c977887e0936192bf617606baff393c026efcc4f04db153aff73b0c9586713c026df57fd19d8e41b5fe3c156a4f33f055bb1ceff046c253a3f066ca53aff63b075d4f9d160eba4f3a3c0d659e77f04b62e3aff30d8baeabcb4336a7f56fbf9413d5f16c4775ea6fc7d1cd49ed25d1b0803f2c479ae9d0f3ce8eb40ec752f4e9ed7cb7edf4caf5762e800f8de17bbefd435c57ebdae167abdfb0cdfb950e653dd88a8e5f6c0ef655007590eafb165ddb2cc95b0ec5e63dd6d747df73baaef3e8349b8f7039394f9ecec9ab24fe8c6b2352c13235bf2fa58622d000d712a83bc30b8d1aab810cf7bebc2b31f78e2df4f52d7eb2e6202f7adb8afd7cd7b4c66ace543997da0df5e07fae1be2eeb9679f1e7993db367f6cc9ed9337b66cfec993db367f6cc9ed9337b66cfec993db367f6cc9e999f59f1c8f3047cae2ce50e92308aed00f0ec8f9fa7109fc3cafad5739d07e0b9ce81d8fdd67ebed752afb7d0a8732e9459754e0ddb109dcf83df65bb456dcb7db1d721fdb6147f79509ffdc0e3605b26790e183ca6ef3c8b3e4ab3bd16cdf6386234db0c99df038cfb747e2ff0b8da1ff7193ca66f6c33f6936a16d5cebae897902ece6c7d100a62f35d3cd4d5735dd5674af5e5308f5f070d4db10f84d8f039781e2cf389fe9f007d3e017d8e661b60f64bc076ea6360dc173b6371ad67c0d2f65f69688a7d205ed4da4a1f88f8db81e24297c708d947cdbe15585729331d8e7333751efb011d8475bd6bf95da61c63be0cf2d8a6ee8abfcec9ed2bfd5765fbeeb2f8de01ac31f9aef52e478e4ee247ecb9907fe79c9ab2524ef410ad851dc7ad427673b98f8de5f2a1cc6e4bfdcb8278ebbfcbe0d96530abd8990371f62e9cebb96a937647687425682465f09cd7419f226b1b291ce24f9591eddfca2883e7a7526631b451aa2ed2ce4b3db11f131e035c9d2f1c34ea27f378be603ba731eba8e2e3f6936b785d5f0b340bec5ab3f4f5db0ced45dc7dfd36430cd9ce4b65fd85b07ee16a15441f5ba4cc56e338eae27a12b7a5a9e77e6092323ba11dfacf7a5cd71dad6bf4a8ebbadd0e78f05a43a674c7773cc6b8685f1cd5b3d076ecda6bd4291fca5c0cf574701e93f69dd45de0dbc536472de41c6a9fa1452e94f9aed17644e928ebc0fb006eeb526c3d1f2cb4d445cafcd868a7763a6072b9ddf03c4badf780a5ae52e617d0fe7d0ee7f3fbf4efd896fec5f2bb4ce9da03fca6fcb6f8eb9cdcbef27ea36cdf6d16df1f026b4cbe6b7d9342cef7c58fd87321ff67387e4b39d143b41676b58fc8fb9dc86e2eb7cf582e1fca6cb7d4bf2c88b7fedb0c9e6d06b38a9ddf409cfd05cef75db59bdb23342a048da40c3e2b30efb7e0bd133cee37d47581cc7f048c62db05fafea7d3fbe529b68f0c36f37eb9ed7cb0d0e0c7f3c1ff0ded6cc252d6fd7380d4b90dd64bea1118750d8cba3a3a7f2dcd31f42c033f1dc0be4fe74567f90dcf71a54c4ebbd47f77f7af6adfc7166ea9073eafdb6370ef3574c57b512d815bc5bd796d81e7e98eaf694bf15ccc3c1fc2eb30299307ecb6f3b84396ba98c7e966c1e1d782df1865f13a3bdd7266fe236319bc6770c0c2646bfb627b2fa7a8b0d0e4b7b57b070d669baeb21f60ccc9bacc7d05cf87a4cc99b0dd1296b2aa4dfaaf136bf491ed88f7da6df7595c1d2fa2eeb3883fc5687b67d2c5338ca6f86e5aebd8d6dbb5dcf69c8dbd3f436b231f8fefe20a3c56a4d3628f85c7d53dcd282df6587cc7a745a7a1b676cea6c56e0b8fab6bcc282d765b7cc7a845a5edde824d8b5d161e57d71a515aecb2f88e4f8bceb5ee6ba4d362a78527fe7b1ae9b5c067629930ef26606e6de4e3f15d5a6e7b7667d3628785c7d5b3bb282d76587cc7a7455127db35bb4d8bed169eed0dacc5768beff8b4e8d2d5764fc5a6c5360b8f83fb6b69b5d866f11d635c0cc3fb6be9b4d86ae1d9dac05a6cb5f88ef1fcb053ba7b86a8c587161e57f7fea2b4f8d0e23b462d8628df5beaa0c5160bcf9606d6628bc5777c5a947754be3fa883161f58783e68602d3eb0f88e4f8b215d94efcd75d062b3856773036bb1d9e23bc66ba8645c6caa83169b2c3c9b1a588b4d16dff16951913cd7da58072d365a783636b0161b2dbee3d3a230794cdd50072d3658783634b0161b2cbe638c8be4f5e4fa3a68b1dec2b3be81b5586ff11de371241917ebeaa0c53a0bcfba06d6629dc5777c5a5426ef3fadad83166b2d3c6b1b588bb516df31de7349c6c59a3a68b1c6c2b3a681b55863f11d9f1625c963eaea3a68b1dac2b3ba81b5586df11d9f16c392cfc456d5418b55169e550dacc52a8bef18cf3b93edc5ca3a68b1d2c2b3b281b55869f11de37967f2fec58a3a68b1c2c2b3a281b55861f11d63db993cef5c5e072d965b785c8d1119a5856d7cca18cf3b935a2cab8316cb2c3caec6368cd26299c5778ce79dc9e3c8d23a68b1d4c2e36a2cca282d6ce360c61817c9b673491db45862e159d2c05a2cb1f88ef1be56b2ed5c5c072d165b785c8dcd11a5c5628bef18af4792f7f816d5418b45169e450dacc5228bef189f1525cfc117d6418b85169e850dacc542f0bd3f76dfa9fedce243fa625d6168910b65be6df4c58ad251d681efd0625daa63af4baa5fd9fb1175a986ba48991f187df9de77c0e4a8aec998794faf4bfaa67f6ca9ab94f969bb9ab23fd7f9046c9343b0ae3f5a7e9729c7982f83bce8a7ea3c3ffe3a276355c60192ed3bdfe2fb1d608dc97711faced149fc883d17f25fb7ab292be5440fd15ad8d53eb240e791dd5c6ea1b15c3e945960a97f59106ffde71b3cf30de6e47b0f106712476edaae14d382088dae008da40cf6d93be488e763834738c45f4e70f8bba8524696c57751ff6ef4db957e9052cfa83e92ef39aa5f541f49f117f52eaa5947151f3f80be9f322e888c19a26c32064809aca7b3615375ede2a8aee24bd62df35d8051c624e9dcf08cc57565ec64302a9e6e0e34c37156644a77bce8063c5d1df038aa67f238d4dda85317a34ef95006df6deceea09e39e057d62df3ddc1b78b6d8e5ac831f952438b5c28935790fa2fe78f513aca3a54fc76b6d4c5958e9d0c9e4e16dfbd1ceb28eb9636b15703f8ee61f8ee68f856fb36c6989ad2eddb3d80b9a70366b5dedef1afb710cf19259ec54f47a8531fd020ae3ae1bae41cb38fa16d2ee4cf2fa8292be5a4ac1c3b855ded47b22d91dd5cae9bb15c3e94e965a97f59106ffd7b1b3cbd0d6675de705a410d8783fd211903bd0c0e99ef08daf58ed0ae17682765f0d8dbc991763d0d1e99ef043c727ed51d6c729e22fc09f8bda401b8cd76afbb855b6c381e61270b63c7f8198bd31d173a02a3d87a024f0f479a99dbfa52431f3c27686594916573a14c9782d47f7957cb2cabf6bb73736aead55cdb637b6f4db7e92d1de885e38106a04f6068289330b40e6ac60c8d93e7d8a0664cd00913abc60f7968d85dc3528f3d052dd7c0c4ff39966a34031be69b5b6c41507be8d35cb0c9d0a72dc0d6cc9005875c95f23274a20bb9500f5977aec1d91a58e2f48dc3c6ca942e745a018f8b5056a12343c7ead0b977fc8889c3303e5a189cf5891df55bf334e5a2d6257190eba0eec824eb9679f1a7f4c9d7f9b143868eec33fea149a3878d99380161cd9d0bf3398608e67fdb321824b833c97a5a18e21c1bbf38a53846b1c917803f9984a17550338e718c3cc94095b186870e1935ea8e49e5a3460cbd6ed298a11347548d41455b1bca45a92dbfb7049bada9c3b26ac2dd17976d65b1d9261cd5b935d8a4053f066cc2732cd89a435eca9b5bc6c93e7231ac5fc25afda6c469a12bde2aa80901392ca9f645ed43ea33aaea74400d2dad8692569b53ddb1534343abafc8a9a19fd550cf6a68673594b31aba590dd5ac86663e3b480dbdacee5e1604a9a194cf0b5243255f10a48642be08f8be0dcc9704a9d30f359471fb203554b1ba7da85e1f579f5a53efb7abd3587579ac4efdd4a58e3a0d53a75fea345bdd4250b793d4a98d3a6d54a744ea34469d96f7d65af709d35561ba3a4cd784e9da305d17a6ebc37443986e0cd34d61ba394cb784e9d630dd16a6dbc3744798ee0cd35d61ea1ba6bb83d470daf784e9de2035dcf67d416a28eefb83d430dd0f04a921bc1f0c52c37b0f0952437f0f0d52c3820f0b5243863f14a486131f11a4862a1e19a486361e1da4864756c3948f0d5243a2aba196d5b0cc6a086735b4b31a1a5a0d23ad869c564351aba1ac9f085243643f15a6a783d410dacf86694a989e0bd3f3617a214c2f86e9a530bd1ca4866557c3b5ab61dc6704a961df6705a961e2d5f0f16a587935dcbc1a865e0d4faf86ad57c3d9bf11a637c3f45698de0e528f05d4e310f59840dd8257b788d5639aea2075fb7a51907accac1ebbab6e08aa5b86eaa6b22248756352ddba543737d5ed4f758354dd42553759d56d5875a356ddca55377bf5da817a0d43bd96a25ed351af2da9d7b8d46b6dea353ff5aaa67af551bdcaab5e6dde17a46e4d1f08528f2bd5ed6a755b5adda257b7d03f0dd3b782544c7e274c9f85e9bb61fa5e98be1fa61f04a921a3d5f0d26a786a3594b51ae25a0d87ad86ce56436fab21b93f0f52437daba1c27f13a4861bff224cbf0b52439e7f15a486bbff4398be0ed31fc3f4a730fd394c7f09d35fc3f46f61faf730fd2d4c7f0fd37f84e91f41cdb0e6d89014e8d6e75c3d3f64e2c461a3c74e2c985855307ad2a88923c68e7aac60f28889c30baa1e1936be7254d5645cf8b77a611993bdcff8f1431e2b1831a662d8a3055593261654551694574d1a5351eb40fafff442671dee71484545b4b3bce6ff02e9f1cdebe7b49d5e4e46bbbf317dddce6b5e0f412ea9cf42b7d4b34277eb23985cf2f54d9d0f164c185535b1a0b0604cf8373cf0564d1e56d1a1007f9b108a3c6162c1848943c64f2ca81c5f35baa0a803aeb7f0d87a5462deb16e604a4eaf9f389f9c9dfa5faf107be19c7a28b0e89cfa916e3ae75f20fdb09e4e3fab4f0d7f549f85feab9e84817ef0699165c2a4f289e3870c9d18bd708b7f65e144bb7a54f38c76f5abe6b7eae3ecfbf559e86ff5244c14d4c359e782ba3b0bfe07c2beb575b80206009b2d6c6f000000275e1f8b08000000000000ffed9d67741cc791c76701100ccb2508e64c28514c00178b44800994c41c642a8b4a044950224512140925cbb224cb39e71c64fb9c73b6efcebe6cdff97c3e873b6739e7f8e5fceeeedd7b7a573de832fe68f5acb0f014d483ad79afb83d85dea95fd554f7cc76f70c73d1d0f607929c2dd7925c103d7ee3bff7dacfe29fb7b5a678aca224672e239c3519e1accd08675d4638276584b33e239c9333c23925239c5353e4346c35d1c82d6dde6902714d9b319fb1984ecf404c0b198be98c0cc4b421ca461f3533239c8d19e19c9511ced919e19c9311ceb919e19c9711cef919e15c9011ce8519e15c9411cec519e15c9211cea519e15c9611cee519e16cca08e77919e13c3f239c176484f3c28c705e9422e71ae05c613f2fb69f2bede72afbb9da7ef277d6dacf66eb639ddd6f215967d8485a9dbf9548da48da493a9cbf75927491ac27e9b67f6bb27feb21d940b2916413c966922d360e5b492e21b994e432926d24db497690ec24d945b29b640fc95e927d24fb492e27790ac901922b48ae24b98ae46a926b48ae25b98ee47a87e520c90d243792dc447233c92d248748fa480e931c21394ad24f728ce45692db488e939c20b99de424c92992d32403246748ee20394b728e6490e44e92bb48ee26b987e45e27664f25b98fe46924f73b9c4f277980e4419287489e41f230c933499e45f26c92e7903c97e47924cf277901c90b495e44f262929790bc94e465242f277905c92b495e45f26a92d790bc96e47524af277903c91b49de6459b821bc99e42d248f90bc95e46d246f27f90b927790bc93e45d24ef26790fc97b49de47f27e920f907c90e443241f26f908c947493e46f271924f907c92e453249f26f90cc95f92fc15c95f937c96e473247f43f2b7247f47f2f724ff40f28f24ff44f279922f90fc33c9bf907c91e45f49be44f26f4eccbf4cf2ef245f21f9aad57dcd7e7eddd6e571b1ff20f94f5bfe86fdfca6fdfc96fdfcb6f39def907cd7d17d8fe45147f77d921fd8f20fede78fece78fede74fece74fede7cfece7cfede72fece72fede7afece7afede76fece76fede7efece7efeda799537d68ce50794a34bcf54629f551edc78a664e8583bf221ab99958d4dabff16793d5d7d97dfee4d84db2fb931c7dbdddaf778e33c5ee4f71f48d76bfd1d1cfb6fbb31dfd5cbb3fd7d1cfb7fbf31dfd8576ff42d0e7231873b57aa3abb5aa1ce8385f6b4037c9ea6a4157cf8703dd64ab9b043a3ebff5a09b6a75934137cdeaa6802e6f7553399624d3adae374a2b578a7de6b885b48f6be7a166a4cf7bc41cb741887766fabcfde6b88d02bc263f66d963cd84bc996d758da0b3dd4d340b7473ad6e36e8e659dd1cd0cdb7bab9a05b6075f340b7d0eae6836e91d52d00dd62ab5b08ba2556b708744bad6e31e89659dd12d02db7baa5a06bb2ba65a03bcfea9683ee7cab6b021daf71390f74175addf9a0bbc8ea2e001df7b517828eef0d2fb23ad34f4cc9c177ac9efba8f83bdc3f836e25f7cda05bc5fd32e856739f0cba35609b756ba15f615db3d5711f65fed663cbbd515a6da214b7890d691f978e6c8ebb29fde3c6f3769ba3e1b8f6829d0d10ab2db69ce2daa056b49db3c276585f07e55d5097eb713cf83ac3ece67ab2d196b794f95e8ff3bd02d4d9e8f1bf374ad7ff4d0ecf26877912f82f93b36d25cdd9516f15e7ecb550d7cd3dbee7998839bb17380472b6537376d45bc539db0f75dddce3fbde8998b30781432067fb6472b654d49c1d1a238b227feef16f9f8998b3b70147fa39dba1393bfaade29c7d08eabab9c7bf7f2762cede051ce9e76c579fde1b8c7aab38675f0275dddce3b1988998b3cf040e819cedd77e76d45bc539fb26a8ebe61e8f0b4ec49c7d3970a49fb3dd4239dba6391b0dcd7746913ff7788c7a22e6ec23c0917ece1ed1f1d9d16f15e7ec67a0ae9b7b3c5f321173f683b66ce619be66e7199680eeeb56b71478d3cfeda3ed42b95dd2dc1e5a071245fe1ce5b9bb8998db9fb36593c7df80b507acfba6d59d07ba6f59ddf9a0fbb6d55d007e09b4813e6d03a3de2a6e03df85ba6e2ef33cf2446c035f010e819c3da2393beaade29cfd15d475738fd7344cc49cfd3e7008e46cbfe6eca8b78a73f6bfa1ae9b7b2b6d7922e62caf2b35f70b3fb4f70bab41f723ab5b03ba1f5bdd5ad0fdc4ea9a41f753ab6b01ddcfac6e1de87e6e7545d0fdc2ea5a41f74bab2b81ee5756d706ba5f5b5d3be87e63751da0fbadd57582ee7756d705badf5bdd7ad0fdc1eabaadcecc77f1daab2f5a9d39b71c8fde28bd731bafb78a466e3967bf17cacdb23cc54234f25904b6b52e7d5b6dc6f79668f4beaf039ea280ef79b0311a9e22f0b4a6cf13af3b2da57fdcf81cb73831cd83ad16f0ab4dc0af1cd8e263f33edb2b800efb92360f637bfa8ca51cd8e263f37e3b30b20efb36bec670fb317d73536e9857a02dc5d767b4d70b1c6caf0eea2c9d335cf742cb361dfece7dc0742863dfdfeae8847235ce15b6c5c7e6fd1230b28fade3cf581a2d63d16194ea3772608b8fedda9eee898f8959bb27661d428ced0e23ef770023c7af7dfc194ba36574fb05a13ea975b47d12c7a575fc6336aaf35a001ddeff7578183bd3678ccf6b87c3c8fb9dc0c8ba36e091ba1e26b5d7506c4bdc87603ef3358baf3f6caf0eea74d50ed7dd0bd753813eb454e9bd29f6e9e99fa75211af67a3e1113e77ad42f958c4bef3b128dd5c73db7cab132b6cf3d8974bf593497d39db53666556666556666556666556666556666556666556666556666556666556e6f09993e6e57ceb199e4c46d6958047629c3f7e47953d16ce013d0af33ae9cf5b948a3857cfeb1857393ed7419dffcb0db3fdc8b34e02e7ced7393aa1754af1b9c4754abdb0cff670dd06ae9b12587b12f3ac75785cdbd33df109711d49486b3492d6698514b302e8703d5c8b104f529eb5786c37a566bb7444a6ed948ae67d40e69d7adc9fb86d04d7bead7174a64feaa91df65b22072a9d77c6eb0697d39cc7c57c435be9afb7298d589f50138dbc56e03d85c01a9511f3d5bc36a2d3b15d0775a6d6447f3a37ebe1efbdd1e3d708993a5dceb1f93babe0bb5dceb11be4fc2ddb1f76023797eb1ddf9a819bebcca819f6f1b3b62c743f53c2f5b311f0468e4fbce1fa8cf4eff786d68bb455c0d3013c126bd784ee6b8b988f69af17e97262e5bb5fe63a9d10bf2e81f8955bb3c6f694599995599995599995599995599995599995599995599995599995599995397c667cff05b3e233d2a54018c7698d4d3c9fc1ef32c279b1b7d40cdb959e03e439a7d58ecff88cf26f6b86d9de6ecbf88e00dff3ee782ea5e6d692ce25db9b1e3dfe397da17339ea773f747862d6e589d97a2146b7cfe0fdf5c0c8f1eb021ea9f6d8e9f0b8b6b1cfe808346649fdacd4fa95a43cf3ad53684acdf6d07a1189795d5e2fe25ebf4a4e4c719d04eb701e1cdfad12f2fb5fdcb50bd84fe11aadf4fbcdd288396077ad20dbc375125fb0b1e57512e9f703a5a2e43582db28af0969f3f8ca75be04d7b92fdb32ae152ac1b11ef5fc9db7726b12b04f4dfd1d9cc5a1397e7e77259fdf1e8fed8dc09a92ed56b49db3c276585f07e5efd50cd7e57a1c0f8e35b39b36c2ef324476f77badcef70a50a7dbe37f6f94aeff3d0e4f8fc36c72e7ab90678fc2bd9e549fd49d10a3551023ae83f7bc52d72f77cdb6bb5619fbd1c94e1dfe6e1dd4f919f45195bc2b4aea7e21e91a80f70bee7561346bc7ab7d3de01fa1bf487b3de01f21877cf7a57cfcd5707ce69a1c255f5bb8ceff3ad75181f57aa37aef95efb71ff3e27a43aef318f45545bb2e37e9778cef390ba9df0d49cf7db03dbca7aac477ec17d2be36623e220be6f29faed136d69c8f5d09dceb3cdfcd277c9763c5ebcbf177b21b3f13876ef84e6f2a7118ea6f7a1c5fb84d75832f5ca7117c91b9671abaff4cdfd791f743dc07b57b7ce53af3e05d700b6c390fe709fbca8b3d7fe7addcfd27c7cff83cdeef5447db21bc537d45ed705df7dde81ceb4adfa9dee97c2fc477aa2f863cbb189eb590eaab3726c46835c488ebe0b38eeeefffa46bcc93f95e52b7dfc4ebe478b2b9e3b7befb13ae83f7d05ca703fad9bca7ae3b2ecdd79034d7a7e3f3406bc12e3e0fb456289e8568643c0b0e87a4ed06c776c338da6e746c378ea36d8db9c63ca4980bfcdf1363febf30f0ffaca8c900636d0618eb32c03829038cf519609c9c01c62919609c9a01c6691960cc03e393796d17884f29b0ffefa9ecbd06da16789f431c8be668f4b16891e5297bef83b605dea152f1ff3720fc7f61b58ef5ffc22ac0f766658071760618e76480716e0618e76580717e0618176480716106181765807171061897648071690618976580717906189b32c0785e0618cfcf00e3051960bc30038c176580718532a6c2b84696b114daffe39c8f46ae357b221ee1778fc6ef50f4bde754e2ffc6add477e1f70eb78ef53d7db8c642f6ff7afcf3de2528b186a2d2770996fbffb185184b6365945a4b8eeba847c383cfa1fa9e6f11602c8d9551ea19147c2672343cbeffab57f699a0a1988d85516acd58a56b1af159c14e4fcc04184b6365947aee009f891c0d8fefd9c55659c6d25819a5d6e7e6c1c66878ba2166eb3d3113602c8d9551e8f9b23866dd15f0e07358dd9e98093096c6ca68783608c5aca7029e0d10b31e4fcc4262449eb4df89dee3b125f1dc5ea5be3303324ecd00e3b40c30e23a0989feabdc3a891ed9f894c61a1fa9f3556e9d04da16784e248e053e17f044b1d824cb53769d04dade2c140b7c6ee38962b11978249e23c9838dd1f0304301be372b038cb333c03827038c7333c0382f038cf333c0b820038c0b33c0b828038c8b33c0b824038c4b33c0b82c038ccb33c088bf5505ee15cbfe7ed93cc16d27fd5699e8b6937e974c74db9ae79ae7d5605bf35cf3bc1a6c6b9e6b9e57836dcd73cdf36ab0ad79ae795e0db635cf35cfabc1b6e6b9e67948b6b330c6af8c138f11799ad2e329a2ef68ab3700df7b3d3c3921dfd1d6d6007c6786ac316ec900e3860c306a1c87d6208e85d1f05c22c4b3b5029e4b80e752219e4b2ae0b914782e4b9f27cea94b2be06186027c6f430618b7648051e3a8710c8951e3583d715446655446657c3218b3d0872b6326f2b1345646c3b32d7d9e38669755c0b30d62c6df6b95652c8d95d1f06c4f9f278ed9b60a78b643ccb6796226c0581a2ba3e1d9913e4f1cb3ed15f0ec80986df7c44c80b1345646c3b3337d9e38663b2ae0d90931dbe18999006369ac8c866757fa3c71cc7656c0b30b62b6d3133301c6d258190dcfeef479e298edaa806737c46c972766028ca5b1321a9e3de9f3c431db5d01cf1e88d96e4fcc04184b6365343c7bd3e78963b6a7029ebd10b33d9e98093096c6ca6878f6a5cf13c76c6f053cfb20667b3d310b9571430618b7648051388ea5b1321a9efd423cfb2ae0d90f3c970bf1ecaf80e772e0794afa3c714e5d5e010f3314e07b1b32c0b825038c1a478d63488c1ac7ea89a3322aa33256c6d89b01463dd7ca182aa3c0efabb2cfd05c3ec16d3738b61baac476d2333413ddb6e6b9e67935d8d63cd73caf06db9ae79ae7d5605bf35cf3bc1a6c6b9e6b9e57836dcd73cdf36ab0ad79ae795e0db635cf35cfabc1b6e6b9e67935d8d63cd73caf06db9ae79ae7d5605bf35cf3bc1a6c6b9e6b9e57836dcd73cdf36ab0ad79ae795e0db635cf35cfabc1b6e6b9e67935d8d63cd73caf06db9ae79ae721d93e90beed52a5cfb01e001e89676a85fc2c9ae35e618ff5588af133b1bad289d5e54eac0a50e70a88df9502f1cb815d3e36efb3bd4a992f0e8059c87669061d632af8cf36b638f130f6af12f23da9afbf6a82db4eeaeb27baeda4be7ea2dbd63cd73caf06db9ae79ae7d5605bf35cf33c14db58ae8b86efdbf9fd4ae61857dbf224bb8facfc3daeb369f2d06743a46d48c2b6b621bd5654836dcd73cdf36ab0ad79ae795e0db635cfc3ccf36bd2b71dcf8de1ef0bb3959b1bbb0678ae168885909f45e3d3b58e4f57393e15a00ebeb3f65a013f7360978fcdfbd7c279c81ab3e1d96ccbcc9a877a9b036164ddd5b23c71fbda1c8ddccab5af6b8147a01db40af919b7afeb1c9f367be2ce753057af13f0d3d77678ff3a380f5963363c5b6d9959f3506f6b208cacbb4696276e5f5ba3915bb9f6751df048f43f427ec6edeb7ac7a7ad9eb8731dccd5eb05fcf4b51ddebf1ece43d6980dcf25b6ccac79a87749208cacbb5696a73d0f3ef356ae7d5d0f3c12fd8f909f71fb3ae8f8748927ee5c0773f5a0809fbeb6c3fb07e13c28b332fb980d0fff9ff2cc9a877a9706c2c8baeb4479da8b79f099b772fdd841e091e8e785e21ef76337383e5dea893bd7c15cbd41c04f5fdbe1fd1be03c54c2bc2583cc1a678d7312b3c659e39cc4ac71d63827316b9c35ce49cc1a678d7312b3c659e39cc4ac71d63827316b9c35ce49cc1a678d7312b3c659e39cc4ac71d63827316b9c35ce49cc1a678d7312b3c659e39cc4ac71d63827316b9c35ce49cc1a678d7312b3c659e39cc4ac71d63827316b9c35ce49cc1ae7b1311b9ecb6c9959f350efb240185977bd2c4ffcfcce65d1c82de7ecf742f906e03928101f213fe375ef373a3e5de6893bd7c1f675a3809fbeb6c3fb37c279a884794b069935ce6363363cdb6c9959f3506f5b208cac3b28cb13f763dba2915bb97eec46e091e8e785fc8cfbb19b1c9fb679e2ce75b07ddd24e0a7afedf0fe4d701e9459997dcc8667bb2d336b1eea6d0f8491753788f294e2e710b74723b772fdd84dc023d1cf0bc53deec76e767cdaee893bd7c15cbd59c04f5fdbe1fd9be13c54c2bc2583cc1a678d7312b3c659e39cc4ac71d63827316b9c35ce49cc1a678d7312b3c659e39cc4ac71d63827316b9c35ce49cc1a678d7312b3c6b97ae26c7876d832b3e6a1de8e40185977a3284f5b3cefb0231ab9959b77b8197824e66584e21ecf3bdce2f8b4c31377ae83edeb16013f7d6d87f76f81f330d199b764905973637c98353794398959734399939835379439895973439993983537943989597343999398353794398959734399939835379439895973439993983537943989597343999398353794398959734399939843c88d02c94e5b66d63cd4db190823eb6e92e589df7bb0331ab9955bb7730bf0dc2c101f213fe3753b871c9f767ae2ce75b07d1d12f0d3d77678ff109c8743caaccc1e66c3b3cb9699350ff57605c2c8ba9b6579e27e6c5734722bd78f1d021e897e5ec8cfb81feb737cdae5893bd7c15ced13f0d3d776789fed29b33227311b9eddb6ccac79a8b73b1046d6dd22cb13f763bba3915bb97eac0f780e09c447c8cfb81f3becf8b4db1377ae83b97a58c04f5fdbe1fdc3701e9459997dcc86678f2d336b1eeaed098491758764794a79f099b772fdd861e091e8e785fc8cfbb1238e4f7b3c71e73a98ab4704fcf4b51dde3f02e7216bcc8667af2d336b1eeaed0d8491757db23c71fbda1b8ddccab5af23c023d1ff08f919b7afa38e4f7b3d71e73a98ab4705fcf4b51dde3f0ae7216bcc86679f2d336b1eeaed0b849175876579e2f6b52f1ab9956b5f478147a2ff11f2336e5ffd8e4ffb3c71e73a98abfd027efada0eeff7c379c81ab3e1d96fcbcc9a877afb0361641df653bcd500e37e21c6c8618c9cf820cfb2c0780e04c6b320309e5981f14c0d8c6755603cb581f1ac0f8ca723309e52603ccb03e3591818cfecc078a605c6b336309ebac0785604c6b33a309e4581f1cc098c271f184f73603c9302e3e9098ca73b309e9581f17406c6d31618cfbac0781607c63337309e3581f14c0f8ca710184f4b603cf581f16c0c8c6749603cf302e39911184f43603c9303e3d914184f57603ced81f11403e3591a18cffcc0786606c6d31818cf94c0787201f0e4a3c7af63c8c3df0f80aec6f9aeb9be1c9e33fc779e37ae81ef1cb3e55acfb1fb41c7f3ccc73cdfc53849cd85a3ad5ed8677bd381e358203c5302e3690c8c6766603cf303e3591a184f31309ef6c078ba02e3d91418cfe4c0781a02e3991118cfbcc0789604c6b331309efac0785a02e32904c6333d309e3581f1cc0d8c6771603ceb02e3690b8ca733309e9581f17407c6d31318cfa4c0789a03e3c907c63327309e4581f1ac0e8c6745603c7581f1ac0d8c675a603cb303e3591818cff2c0784a81f17404c6b33e309edac0785605c63335309e5981f12c088ce740603ccb02e3a9f1f01c10e2497ab6f94020b605ce43d11cf756219f6eb3c7aab7c7657eb65707752eb0038f66fe03bfcb5ceefc3fb69ddb204652ef9528383cbc7f7482db6e706c375489ed46c7766395d8d63cd73caf06db9ae79ae7d5605bf35cf33c44db8fa567bb43df2f357a1e7d9f53791e7d9f53791e7d9f53791e7d9f53791e7d9f53791e7d9f53791e7d9f53799e1581f1e8fb9ccaf3e8fb9ccaf33407c63329301e7d9f53799e9581f1e8fb9ccaf3e8fb9ccaf3e8fb9ccaf34c0f8c47dfe7549ea73e309ed0dee714dafbe0f5fd52e5796604c6a3ef972acfa3ef972acfa3ef972acfa3ef972acfa3ef972acf3325309e5c003c4ff47e297c2fd46db67c1474bcbeb4dc7ba8f2709cdb40c7e3b97c0c73bd3a35e7f10c35f09de31eae5b3df6d8ce71cf77c723ee68ab17f6d91ebeafea78203c5302e3690c8c6766603cf303e3591a184f31309ef6c078ba02e3d91418cfe4c0781a02e3991118cfbcc0789604c67320309e8d81f1d407c6d312184f21309ee981f1ac098c676e603c8b03e35917184f5b603c9d81f1ac0c8ca73b309e9ec0782605c6d31c184f3e309e3981f12c0a8c6775603c2b02e3a90b8c676d603cd302e3991d18cfc2c0789607c6530a8ca723309ef581f1d406c6b32a309ea981f1cc0a8c6741603ccb02e3a9f1f048bd332ae9f9faf1785fd513d936fb6b212e66cbc3dfc7e339ae030e23efe3ba07e4659eb5423c49ef05581b806de33fff169d613ff3f0777c0e472aa7d63a8cbcefcb295cd7d82cc493f43e83e6006c9b58b4d832af01c8c3df5b80512aa79a1d46def7e554a32c4f7b1e7ce6addc5a236c7312e750c8cf22b6bf14dfa15134b1daefc4aac5895501ea8cc7baf4a4fe80ed29b33227311b1e9e4b6156bc9e8dc77366a361f45d5f0578e2fe715d34722bd73fee071e89eb87909f713f76c2f1699d27ee5c0773f584809fbeb6c3fb273cb69ba2746371fb286271bb87e7f6718e05dbab94f94006994388b3e1e1b588cc8aeb9b8b8130b26ead2c4fdc3f16a3915bb9fef176e091b87e08f919f709271d9f8a9eb8731d6c5f2705fcf4b51dde3f09e7a112e6131964d6388f8dd9f0f01c04b3e6a15e291046d6ed17e52915f3e0336fe5fab193c023d1cf0bc53deec74e393e953c71e73ad8be4e09f8e96b3bbc7f0ace83322bb3322bb3322bb3322bb3322bb3322bb3322bb3322bb3322bb3322bb33287cd6c78f8d95866cd43bdb640185977bb28cfd0bc435b34722b37ef700a7824e66584e21ecf3b9c767c6af3c49deb60ae9e16f0d3d77678ff349c07655666655666655666655666655666655666655666655666655666655666650e9bd9f0f03bdb99350ff5da036164dd49599ef8b9adf668e4566edee134f09c12888f909ff1bcc380e353bb27ee5c07737540c04f5fdbe1fd01380fcaaccc3e66c3c3ef6a63d63cd4eb08849175a7447986e64f3ba2915bb97e6c007824fa79a1b8c7fdd819c7a70e4fdcb90ee6ea19013f7d6d87f7cfc079a884f944069935ce1ae724668db3c6398959e3ac714e62d6386b9c939835ce1ae724668db3c6398959e3ac714e62d6386b9c939835ce1ae724668df3f830871067c3c3ff8720b3e6a15e67208cac3b2dcad316cf3b744623b772f30e678047625e4628eef1bcc31d8e4f9d9eb8731d6c5f7708f8e96b3bbc7f079c8789ce7c2283cc9a1be3c3acb9a1cc49cc9a1bca9cc4acb9a1cc49cc9a1bca9cc4acb9a1cc49cc9a1bca9cc4acb9a1cc49cc9a1bca9cc4acb9a1cc49cc9a1bca9cc4acb9a1cc49cc9a1bca9cc4acb9a1cc49cc9a1bca9cc41c426e189e2e5b66d63cd4eb0a84917503b23cf17b0fbaa2915bb9753b7700cf1981f808f919afdb39ebf8d4e5893bd7c1f67556c04f5fdbe1fdb3701e9459997dcc8667bd2d336b1eeaad0f8491756764794a79f099b772fdd859e091e8e785fc8cfbb1738e4feb3d71e73a98abe704fcf4b51dde3f07e7216bcc86a7db9699350ff5ba0361641d5e97bb85780a0e4fc1138b27cbb6d9efb1e5e9f6330f7fef0146a9feb0db61e47dcc71e4659e1e219e0687a7c1138b27cbb6f17fa32dcfb09f79f8fb466094caa91e8791f77d39d5003c1b85781a1d9e464f2c9e2cdb26169b6c79a6fdccc3df3701a3544e6d741879df97538dc0b3498827a94fda340eb693dad778d84eca95f1b0ad314f8eb940bb8bc707364523b772f7d5786d91e8ab84fc2cfaaedf9b1c9ff0fa8df7a84fd6f5499995398959e83eb73defd8e6f8440e0f6f678563319ebfb37b1c9fb2f03bbb1cf3890c326b9cc7c66c6c0fa66fbb3defd8e6f8440e0f6f83c2b110f233ee0fee8cfc31667b05a883797aa7809f39b0cbc7e6fd3be13c54c27c2283cc1ae7b1311bdb77a56e7be8fdc3689be313393cbcdd251c0b193f87fa83bb237f8cd95e01ea609ede2de0670eecf2b179ff6e380fcaaccccaaccccaaccccaaccccaaccccaaccccaaccccaaccccaaccccaacccca1c36b3b17d4feab687c6efd136c727727878bb473816327e0e8ddfdf1bf963ccf60a5007cff9bd027ee6c02e1f9bf7ef85f3a0cccaaccccaaccccaaccccaaccccaaccccaaccccaaccccaaccccaaccccaaccc61331bdb4f4ddf76fc3c0edae6f8440e0f6f4f158e85909ff1f8fd7d913fc66caf0075f09cdf27e0670eecf2b179ff3e380fcaaccc3e6663fb69a9db1e9acf43db1c9fc8e1e1ed69c2b190f173a83fb83ff2c798ed15a00e9ef3fb05fccc815d3e36efdf0fe7a112e6131964d6386b9c939835ce1ae724668db3c6398959e3ac714e62d6386b9c939835ce1ae724668db3c6398959e3ac714e62d6386b9c939835ced5136763fbe9a9db6e8bc7efd136c7277278787bba702c64fc1c1abf7f20f2c798ed15a00ee6e903027ee6c02e1f9bf71f80f330d1994f64905973637c98353794398959734399939835379439895973439993983537943989597343999398353794398959734399939835379439895973439993983537943989597343999398353794398959734399939843c80d63fbc1f46dc7cfb3a36d8e4fe4f0f0f6a0702c84fc8cd7bf3c14f963ccf60a5007f3f421013f7360978fcdfb6c4f99953989d9d87e46fab64b79c736c7277278787b86702c84fc8cfb8387237f8cd95e01eae0397f58c0cf1cd8e563f3fec3701eb2c68ce72f979eed78dd26dba8b19f46f74c5bae05ddb36cb90e74cfb6e549a07b8e2dd783eeb9b63c1974cf03df58f77c5b5e03ba17d8f226d0bdd0963782ee45b6dc03ba17db7237e85e62cb6741f7525b3e07ba97d9f220e85e6ecb7782ee15b67c17e85e69cb7783ee55b67c0fe85e6dcbf782ee35b6fc54d0bdd696ef03ddeb6cf969a07bbd2ddf0fba37d8f2d341f7465b7e00746fb2e515a07bb347f7165b7e10748fd8f243a07bab2d1f00dddb6c792ae8de6ecbd340f71750e6cf77d8f274d0bdd3960ba07b972dcf00ddbb6db90174efb1e599a07baf2d3782ee7db63c0b74efb7e5d9a0fb802dcf01dd076d792ee83e64cbf340f7615b9e0fba8fd8f202d07dd4961782ee63b6bc08741fb7e5c5a0fb842d2f01dd276d7929e83e65cbcb40f7695b5e0ebacfd8329edfbfb4e567808efb958741c7fdca3341c7fdcab340c7fdcab341c7fdca7340c7fdca7341c7fdcaf340c779f77cd071debd00749c772f041de7dd8b40c779f762d071debd04749c772f051de7ddcb40c779f772d071debd02749c77af041de7ddab40c779f76ad071debd06749c77af051de7ddeb40c779f77ad071debd01749c776f041de7dd9b40c779f766d071debd05749c778f80aec996df0abaf36cf96da03bdf96df0eba0b6c19fb990b6df91da0bbc896df093aee0bdf05ba8b6df9dda05b69cbef01dd2a5b7e2fe856dbf2fb40b7c696df0fbab5b6fc01d035dbf20741d762cb1f02dd3a5bfe30e88ab6fc11d0b5daf2474157b2e58f81aecd963f0eba765bfe04e83a6cf993a0ebb4e54f81aecb963f0dbaf5b6fc19d0f1759cfb19d39e4dbbe438708c8c8e7d6ef1f8c2ba29e04b6f94ee3d1ddbe263f37e1b30f239288d3f6369b48cad0ea3e1e9108819e6156fe57e3375004fbb008f909ff16fa64ec7a736c7a702d4b918fcec14f0330776f9d8bcdf09b625ce39c6a2de1e77a5138b3aa8d36e2f72e67a5a2e8e7c0c93bf258f2f52716c75785a3db6bb85e3c8c7e63eb17b1c6c7739b68b8e6dbc16f056ae6d7701f37a016673dc9ef48f1bb7ed0df6589ccf6ca7083e6d8418a4e513dace59613bacaf83f29e39c375b91ec783af9dcc6eda119f4b6477bfd7e17caf0075ba3dfef746e9fadfe3f0f438cce6f744ef9c610e81f610e740b7c3c1fb45885d4f42ecba21765c07afbdcd42b15beff0f07e33f0f0fd5527e8f83e85f9f11eaf651cb8dd7eafd3c3cdba2e606cf63096d2678cefb39a1d46de2f0123ebd6034f9750ccdc73bdd2890fde134c76eaf077eba0ce21b82ee73d754dbb6bca0dfbc5bfff1f8bd2edd3eb05e285631311c4277262c81b334c8986c72fd2e499160d8f4f9c1b1c38db776bff15fd7d47738056e760e267cee3460de8b05cebd145d1c861181c0ee661181c0eae71c282c33f5cdffc8c336ef15047ffa9e383579fee3f7de4ecbd6706fb8fee1db815a92739f4489ae40192a28eb729d1f080516f94ee4450bd63ab5cf24c81cfc9e9f3b40af9195ff4a63a3ed53b3e15a0ce24f8db54013f7360978fcdfb533db653ec88e2584c1b452ca67978a68d732c70d09d75d852f9ef387153e3f8822d1a7d72f33c5587d8e00a387ecec299bf99c63ec93a33391a3ed9dc7b9a3b5a7312cc68adb96a99d15833fa6aba2033ba6a2e6866f4d48c969ad151331a6a463fcd68a719dd34a39966f4d28c569ad1c9a66868f4d18c369ad145339a7811b07d1178cd2f7a738534a38166f4cf8cf6993b2b730760ee46ccddb7b95334bf1ecd1d82f9556b4638ccd5d6dcc998abb4b9b29a3b45738768eee8cd1dae9921db4cb2c5c67a2bc9252497925c46b28d643bc90e929d24bb487693ec21d94bb28f643fc9e5244f898646f6af20b992e42a92ab49ae21b996e43a92eb490e92dc407223c94d243793dc427288a48fe430c91192a324fd24c7486e25b98de47834b42ae876929324a7484e930c909c21b9231a9aa533b3726616ceccba99593633ab6666d1ccac99992533b3626616cccc7a99592e33abf56034341b656622cccc83996930330b6626c1cc1c3c371a9a193033012f888646facdc8be19c93723f766a4de8ccc9b917833f26e46dacdc8ba19493723e766a4dc8c8c9b917033f26d46bacdc8b619c93623d78f444323d36624da8c3c9b916633b26c4692cdc8f1bba3a1916133126c467ecd48af19d93523b966e4d68cd49a915933126b465ecd48ab19593523a966e4d48c949a91513312fa57247f4df25992cf91fc0dc9df92fc1dc9df93fc03c93f92fc13c9e749be40f2cf24ff120de5e5bf927c89e4df48be4cf2ef245f21f92ac9d748be4ef21f24ff49f20d926f927c8be4db24df21f92ec9f7481e25f93ec90f487e48f223921f93fc84e4a7243f23f939c92f487e49f22b925f93fc86e4b724bf23f93dc91fa2e19915ec44a6d89e8747f9fb0607fb4f9d196c1a1c683a75e7c9c1e3674ededb74f7f1c1db9a06eeea3f7bece4c0ddf8e5cfdb2ff314c6d6b367fbee6d3a7efa68ff3d4d03770e360d1c6b3a3c70e7e9a3e7f04b3fb55f5af2788b7d478f261bfbaf3f87f47fc66874b2ed137972685779dfa6d58e212033c7f2a5f6dab139b4d15e75f8d7fb954377bb4de74e0e0c36159b4ed3bf7d27e93bfd475b9af06fe728c8e7069bce0df69d1d6c3a7676e054536b0b1ef7fce96370a26dce18be74cb9cd17b1efd3fc9de5641f9d90300", "privateFunctions": [ { "selector": { @@ -44,8 +44,8 @@ exports[`ContractClass creates a contract class from a contract compilation arti "isInternal": false } ], - "id": "0x193b0f08a5af3b2286bff06aaddcf074dd2e467e6fb1e412d747d2b64648866f", + "id": "0x01d273e0c02fb9a303814be7a40a168c5bc1604e452f678af77d5feb119dec2f", "privateFunctionsRoot": "0x05fa82a96814b6294d557d507151f7ccc12f70522ec4d9d0395a90e87e8087c6", - "publicBytecodeCommitment": "0x0de7228dd1c2821b5dcb66dc4e0de48e1f6a88e2830be489ad6c7006fcd868b8" + "publicBytecodeCommitment": "0x0084bda5b128cd65dbe6d5d9b4e57417838565f6e7437aa697c8fa607a305c42" }" `; diff --git a/yarn-project/protocol-contracts/src/gas-token/__snapshots__/index.test.ts.snap b/yarn-project/protocol-contracts/src/gas-token/__snapshots__/index.test.ts.snap index 75502444a15a..27a07f0273c1 100644 --- a/yarn-project/protocol-contracts/src/gas-token/__snapshots__/index.test.ts.snap +++ b/yarn-project/protocol-contracts/src/gas-token/__snapshots__/index.test.ts.snap @@ -2,10 +2,10 @@ exports[`GasToken returns canonical protocol contract 1`] = ` { - "address": AztecAddress<0x1db73bf9f9d1d49b40d40fc5b81a9d917ef267b9860b8601ba5eb9d9594bfd33>, + "address": AztecAddress<0x1ad6b44772790199d32f045454767652210040229e609aff0eaf3efb5caaf430>, "instance": { - "address": AztecAddress<0x1db73bf9f9d1d49b40d40fc5b81a9d917ef267b9860b8601ba5eb9d9594bfd33>, - "contractClassId": Fr<0x232bbde5f406677a8d090400dd2265fd12d3f40fd1b2de47f0331b2f975ea0f4>, + "address": AztecAddress<0x1ad6b44772790199d32f045454767652210040229e609aff0eaf3efb5caaf430>, + "contractClassId": Fr<0x26930ec0721619c525633357b71f7fa0f8009472bd5243a628e1bf26bed82831>, "initializationHash": Fr<0x0bf6e812f14bb029f7cb9c8da8367dd97c068e788d4f21007fd97014eba8cf9f>, "portalContractAddress": EthAddress<0x0000000000000000000000000000000000000000>, "publicKeysHash": Fr<0x27b1d0839a5b23baf12a8d195b18ac288fcf401afb2f70b8a4b529ede5fa9fed>, @@ -18,7 +18,7 @@ exports[`GasToken returns canonical protocol contract 1`] = ` exports[`GasToken returns canonical protocol contract 2`] = ` { "artifactHash": Fr<0x076fb6d7493b075a880eeed90fec7c4c01e0a24d442522449e4d56c26357205f>, - "id": Fr<0x232bbde5f406677a8d090400dd2265fd12d3f40fd1b2de47f0331b2f975ea0f4>, + "id": Fr<0x26930ec0721619c525633357b71f7fa0f8009472bd5243a628e1bf26bed82831>, "privateFunctions": [ { "isInternal": false, @@ -27,7 +27,7 @@ exports[`GasToken returns canonical protocol contract 2`] = ` }, ], "privateFunctionsRoot": Fr<0x13b29c3f4a96eb14d5d3539a6308ff9736ad5d67e3f61ffbb7da908e14980828>, - "publicBytecodeCommitment": Fr<0x0d917c13945d9fc55c69a2d78ddcb38aac8b9f88089f3240fdeb1d90d1accb91>, + "publicBytecodeCommitment": Fr<0x0814d00c42baccb4f02771bea96111ca7c8f5fe6025694db72218e26da78e7ee>, "version": 1, } `; From 204ec206b23d5d20eb446cc503670606a8126e80 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Wed, 13 Mar 2024 21:39:31 +0000 Subject: [PATCH 076/139] change back to original timeouts --- .../end-to-end/src/benchmarks/bench_process_history.test.ts | 2 +- .../end-to-end/src/benchmarks/bench_publish_rollup.test.ts | 2 +- yarn-project/end-to-end/src/e2e_counter_contract.test.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn-project/end-to-end/src/benchmarks/bench_process_history.test.ts b/yarn-project/end-to-end/src/benchmarks/bench_process_history.test.ts index b518d8bf151c..8d0747cf27f5 100644 --- a/yarn-project/end-to-end/src/benchmarks/bench_process_history.test.ts +++ b/yarn-project/end-to-end/src/benchmarks/bench_process_history.test.ts @@ -30,7 +30,7 @@ describe('benchmarks/process_history', () => { beforeEach(async () => { ({ context, contract, sequencer } = await benchmarkSetup({ maxTxsPerBlock: BLOCK_SIZE })); - }, 100_000); + }, 60_000); it( `processes chain history of ${MAX_CHAIN_LENGTH} with ${BLOCK_SIZE}-tx blocks`, diff --git a/yarn-project/end-to-end/src/benchmarks/bench_publish_rollup.test.ts b/yarn-project/end-to-end/src/benchmarks/bench_publish_rollup.test.ts index 5cae33317c13..fea4012690b2 100644 --- a/yarn-project/end-to-end/src/benchmarks/bench_publish_rollup.test.ts +++ b/yarn-project/end-to-end/src/benchmarks/bench_publish_rollup.test.ts @@ -14,7 +14,7 @@ describe('benchmarks/publish_rollup', () => { beforeEach(async () => { ({ context, contract, sequencer } = await benchmarkSetup({ maxTxsPerBlock: 1024 })); - }, 100_000); + }, 60_000); it.each(BENCHMARK_BLOCK_SIZES)( `publishes a rollup with %d txs`, diff --git a/yarn-project/end-to-end/src/e2e_counter_contract.test.ts b/yarn-project/end-to-end/src/e2e_counter_contract.test.ts index 52e944973091..f47c6ba8d203 100644 --- a/yarn-project/end-to-end/src/e2e_counter_contract.test.ts +++ b/yarn-project/end-to-end/src/e2e_counter_contract.test.ts @@ -25,7 +25,7 @@ describe('e2e_counter_contract', () => { counterContract = await CounterContract.deploy(wallet, 0, owner).send().deployed(); logger(`Counter contract deployed at ${counterContract.address}`); - }, 50_000); + }, 25_000); afterAll(() => teardown()); From 0be14a175abad6e6dfc1a3acebc1cd0ddded93bb Mon Sep 17 00:00:00 2001 From: vezenovm Date: Wed, 13 Mar 2024 21:41:34 +0000 Subject: [PATCH 077/139] more readme updates --- barretenberg/cpp/src/barretenberg/dsl/README.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/dsl/README.md b/barretenberg/cpp/src/barretenberg/dsl/README.md index b474c9bbdb27..0e91448b61f4 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/README.md +++ b/barretenberg/cpp/src/barretenberg/dsl/README.md @@ -24,5 +24,11 @@ A full change is when you attempt to change the object whose buffer we are actua Even if you correctly update all serialization in [acvm_js](../../../../../noir/noir-repo/acvm-repo/acvm_js/README.md) such as during [execution](../../../../../noir/noir-repo/acvm-repo/acvm_js/src/execute.rs#57), there is multiple places the `yarn-project` uses the ACIR top-level serialization. The `yarn-project` sequencer also uses the native `acvm_cli tool` that has an execute method that [expects raw byte code](../../../../../noir/noir-repo/tooling/acvm_cli/src/cli/execute_cmd.rs#63). -In the context of Aztec we need to regenerate all the artifacts in [noir-projects](../../../../../noir-projects/bootstrap.sh). This regeneration assumes that we have rebuilt the compiler from which we got the original ACIR object from to use the new serialization. After regenerating these artifacts we can bootstrap the yarn-project. There are multiple packages in the yarn-project that rely on pre-computed artifacts such as `yarn-project/circuits.js` and `yarn-project/protocol-contracts`. These can be individually regenerated using `yarn test -u`, however, it is much easier to let the bootstrap scripts handle these updates. - +In the context of Aztec we need to regenerate all the artifacts in [noir-projects](../../../../../noir-projects/bootstrap.sh). This regeneration assumes that we have rebuilt the compiler from which we got the original ACIR object from to use the new serialization. After regenerating these artifacts we can bootstrap the yarn-project. There are multiple packages in the yarn-project that rely on pre-computed artifacts such as `yarn-project/circuits.js` and `yarn-project/protocol-contracts`. + +The Aztec artifacts can be individually regenerated as well using `yarn test -u`. +You can also run the command on the relevant workspaces, which at the time are the following: +``` +yarn workspace @aztec/circuits.js test -u +yarn workspace @aztec/protocol-contracts test -u +``` From f3a35335c62e57674a054912887096ef639e85e2 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Thu, 14 Mar 2024 18:37:08 +0000 Subject: [PATCH 078/139] initial fold attribute and inline type on SSA func --- .../src/ssa/function_builder/mod.rs | 14 +++++---- .../noirc_evaluator/src/ssa/ir/function.rs | 24 ++++++++++++++- .../src/ssa/opt/bubble_up_constrains.rs | 2 +- .../src/ssa/opt/constant_folding.rs | 12 ++++---- .../src/ssa/opt/defunctionalize.rs | 2 +- .../noirc_evaluator/src/ssa/opt/die.rs | 2 +- .../src/ssa/opt/flatten_cfg.rs | 18 +++++------ .../ssa/opt/flatten_cfg/branch_analysis.rs | 4 +-- .../noirc_evaluator/src/ssa/opt/inlining.rs | 30 +++++++++++-------- .../noirc_evaluator/src/ssa/opt/mem2reg.rs | 10 +++---- .../src/ssa/opt/simplify_cfg.rs | 4 +-- .../noirc_evaluator/src/ssa/opt/unrolling.rs | 4 +-- .../src/ssa/ssa_gen/context.rs | 5 ++-- .../noirc_evaluator/src/ssa/ssa_gen/mod.rs | 3 +- .../noirc_frontend/src/ast/function.rs | 1 + .../src/hir/resolution/resolver.rs | 13 ++++++-- .../noirc_frontend/src/hir/type_check/mod.rs | 1 + .../noirc_frontend/src/hir_def/function.rs | 4 +++ .../noirc_frontend/src/lexer/lexer.rs | 13 ++++++++ .../noirc_frontend/src/lexer/token.rs | 8 +++++ .../src/monomorphization/ast.rs | 1 + .../src/monomorphization/mod.rs | 11 ++++--- .../execution_success/fold_basic/Nargo.toml | 7 +++++ .../execution_success/fold_basic/src/main.nr | 9 ++++++ 24 files changed, 144 insertions(+), 58 deletions(-) create mode 100644 noir/noir-repo/test_programs/execution_success/fold_basic/Nargo.toml create mode 100644 noir/noir-repo/test_programs/execution_success/fold_basic/src/main.nr diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs index bf34a47485bb..18a8a486816f 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs @@ -46,8 +46,9 @@ impl FunctionBuilder { function_name: String, function_id: FunctionId, runtime: RuntimeType, + should_fold: bool, ) -> Self { - let mut new_function = Function::new(function_name, function_id); + let mut new_function = Function::new(function_name, function_id, should_fold); new_function.set_runtime(runtime); let current_block = new_function.entry_block(); @@ -69,8 +70,9 @@ impl FunctionBuilder { name: String, function_id: FunctionId, runtime_type: RuntimeType, + should_fold: bool, ) { - let mut new_function = Function::new(name, function_id); + let mut new_function = Function::new(name, function_id, should_fold); new_function.set_runtime(runtime_type); self.current_block = new_function.entry_block(); @@ -79,13 +81,13 @@ impl FunctionBuilder { } /// Finish the current function and create a new ACIR function. - pub(crate) fn new_function(&mut self, name: String, function_id: FunctionId) { - self.new_function_with_type(name, function_id, RuntimeType::Acir); + pub(crate) fn new_function(&mut self, name: String, function_id: FunctionId, should_fold: bool,) { + self.new_function_with_type(name, function_id, RuntimeType::Acir, should_fold); } /// Finish the current function and create a new unconstrained function. pub(crate) fn new_brillig_function(&mut self, name: String, function_id: FunctionId) { - self.new_function_with_type(name, function_id, RuntimeType::Brillig); + self.new_function_with_type(name, function_id, RuntimeType::Brillig, false); } /// Consume the FunctionBuilder returning all the functions it has generated. @@ -463,7 +465,7 @@ mod tests { // let x = 7; // let bits = x.to_le_bits(8); let func_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("func".into(), func_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("func".into(), func_id, RuntimeType::Acir, false); let one = builder.numeric_constant(FieldElement::one(), Type::bool()); let zero = builder.numeric_constant(FieldElement::zero(), Type::bool()); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/function.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/function.rs index 360f57101136..e1b8773c117c 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/function.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/function.rs @@ -17,6 +17,15 @@ pub(crate) enum RuntimeType { Brillig, } +#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] +pub(crate) enum InlineType { + /// The most basic entry point can expect all its functions to be inlined. + /// All function calls are expected to be inlined into a single ACIR. + Inline, + /// Functions marked as foldable will not be inlined and compiled separately into ACIR + Fold, +} + /// A function holds a list of instructions. /// These instructions are further grouped into Basic blocks /// @@ -35,6 +44,10 @@ pub(crate) struct Function { runtime: RuntimeType, + /// Represents how an ACIR function should be inlined. + /// This type should only be accessed when operating on a function of RuntimeType::Acir + inline_type: InlineType, + /// The DataFlowGraph holds the majority of data pertaining to the function /// including its blocks, instructions, and values. pub(crate) dfg: DataFlowGraph, @@ -47,7 +60,7 @@ impl Function { pub(crate) fn new(name: String, id: FunctionId) -> Self { let mut dfg = DataFlowGraph::default(); let entry_block = dfg.make_block(); - Self { name, id, entry_block, dfg, runtime: RuntimeType::Acir } + Self { name, id, entry_block, dfg, runtime: RuntimeType::Acir, inline_type: InlineType::Inline } } /// The name of the function. @@ -71,6 +84,15 @@ impl Function { self.runtime = runtime; } + pub(crate) fn inline_type(&self) -> InlineType { + assert!(matches!(self.runtime, RuntimeType::Acir), "ICE: We should only check the inline type for ACIR functions. All Brillig functions are expected to not be inlined"); + self.inline_type + } + + pub(crate) fn set_inline_type(&mut self, inline_type: InlineType) { + self.inline_type = inline_type + } + /// Retrieves the entry block of a function. /// /// A function's entry block contains the instructions diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/bubble_up_constrains.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/bubble_up_constrains.rs index b737c51d145d..17e1593199ee 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/bubble_up_constrains.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/bubble_up_constrains.rs @@ -100,7 +100,7 @@ mod test { let main_id = Id::test_new(0); // Compiling main - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir, false); let v0 = builder.add_parameter(Type::field()); let one = builder.field_constant(1u128); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/constant_folding.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/constant_folding.rs index 06ae4bf52023..4efcbaa03aab 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/constant_folding.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/constant_folding.rs @@ -305,7 +305,7 @@ mod test { let main_id = Id::test_new(0); // Compiling main - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir, false); let v0 = builder.add_parameter(Type::field()); let one = builder.field_constant(1u128); @@ -361,7 +361,7 @@ mod test { let main_id = Id::test_new(0); // Compiling main - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir, false); let v0 = builder.add_parameter(Type::unsigned(16)); let v1 = builder.add_parameter(Type::unsigned(16)); @@ -415,7 +415,7 @@ mod test { let main_id = Id::test_new(0); // Compiling main - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir, false); let v0 = builder.add_parameter(Type::unsigned(16)); let v1 = builder.add_parameter(Type::unsigned(16)); @@ -471,7 +471,7 @@ mod test { let main_id = Id::test_new(0); // Compiling main - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir, false); let v0 = builder.add_parameter(Type::field()); let one = builder.field_constant(1u128); let v1 = builder.insert_binary(v0, BinaryOp::Add, one); @@ -518,7 +518,7 @@ mod test { let main_id = Id::test_new(0); // Compiling main - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir, false); let v0 = builder.add_parameter(Type::unsigned(16)); let v1 = builder.insert_cast(v0, Type::unsigned(32)); @@ -562,7 +562,7 @@ mod test { let main_id = Id::test_new(0); // Compiling main - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir, false); let v0 = builder.add_parameter(Type::bool()); let v1 = builder.add_parameter(Type::bool()); let v2 = builder.add_parameter(Type::bool()); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/defunctionalize.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/defunctionalize.rs index 1f09a1321321..e8fbc164ba70 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/defunctionalize.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/defunctionalize.rs @@ -304,7 +304,7 @@ fn create_apply_function( ) -> FunctionId { assert!(!function_ids.is_empty()); ssa.add_fn(|id| { - let mut function_builder = FunctionBuilder::new("apply".to_string(), id, RuntimeType::Acir); + let mut function_builder = FunctionBuilder::new("apply".to_string(), id, RuntimeType::Acir, false); let target_id = function_builder.add_parameter(Type::field()); let params_ids = vecmap(signature.params, |typ| function_builder.add_parameter(typ)); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/die.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/die.rs index f7d8adb52757..754130bff049 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/die.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/die.rs @@ -195,7 +195,7 @@ mod test { let main_id = Id::test_new(0); // Compiling main - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir, false); let v0 = builder.add_parameter(Type::field()); let b1 = builder.insert_block(); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs index 46f1e7a27650..91d75d22d137 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs @@ -860,7 +860,7 @@ mod test { // return v1 // } let main_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir, false); let b1 = builder.insert_block(); let b2 = builder.insert_block(); @@ -914,7 +914,7 @@ mod test { // return // } let main_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir, false); let b1 = builder.insert_block(); let b2 = builder.insert_block(); @@ -963,7 +963,7 @@ mod test { // return // } let main_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir, false); let b1 = builder.insert_block(); let b2 = builder.insert_block(); @@ -1024,7 +1024,7 @@ mod test { // return // } let main_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir, false); let b1 = builder.insert_block(); let b2 = builder.insert_block(); @@ -1114,7 +1114,7 @@ mod test { // ↘ ↙ // b9 let main_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir, false); let b1 = builder.insert_block(); let b2 = builder.insert_block(); @@ -1271,7 +1271,7 @@ mod test { // before the first store to allocate, which loaded an uninitialized value. // In this test we assert the ordering is strictly Allocate then Store then Load. let main_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir, false); let b1 = builder.insert_block(); let b2 = builder.insert_block(); @@ -1370,7 +1370,7 @@ mod test { // return // } let main_id = Id::test_new(1); - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir, false); builder.insert_block(); // entry @@ -1423,7 +1423,7 @@ mod test { // jmp b3() // } let main_id = Id::test_new(1); - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir, false); builder.insert_block(); // b0 let b1 = builder.insert_block(); @@ -1533,7 +1533,7 @@ mod test { // jmp b5() // } let main_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir, false); let b1 = builder.insert_block(); let b2 = builder.insert_block(); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg/branch_analysis.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg/branch_analysis.rs index 59bee00936ac..e2b0e931de6b 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg/branch_analysis.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg/branch_analysis.rs @@ -134,7 +134,7 @@ mod test { // ↘ ↙ // b9 let main_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir, false); let b1 = builder.insert_block(); let b2 = builder.insert_block(); @@ -195,7 +195,7 @@ mod test { // ↘ ↙ // b15 let main_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir, false); let b1 = builder.insert_block(); let b2 = builder.insert_block(); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/inlining.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/inlining.rs index 776f22b2877a..c81ab4054d3a 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/inlining.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/inlining.rs @@ -99,7 +99,11 @@ struct PerFunctionContext<'function> { fn get_entry_point_functions(ssa: &Ssa) -> BTreeSet { let functions = ssa.functions.iter(); let mut entry_points = functions - .filter(|(_, function)| function.runtime() == RuntimeType::Brillig) + .filter(|(_, function)| { + dbg!(function.foldable()); + dbg!(function.id()); + function.runtime() == RuntimeType::Brillig + }) .map(|(id, _)| *id) .collect::>(); @@ -115,7 +119,7 @@ impl InlineContext { /// that could not be inlined calling it. fn new(ssa: &Ssa, entry_point: FunctionId) -> InlineContext { let source = &ssa.functions[&entry_point]; - let builder = FunctionBuilder::new(source.name().to_owned(), entry_point, source.runtime()); + let builder = FunctionBuilder::new(source.name().to_owned(), entry_point, source.runtime(), false); Self { builder, recursion_level: 0, entry_point, call_stack: CallStack::new() } } @@ -533,14 +537,14 @@ mod test { // return 72 // } let foo_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("foo".into(), foo_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("foo".into(), foo_id, RuntimeType::Acir, false); let bar_id = Id::test_new(1); let bar = builder.import_function(bar_id); let results = builder.insert_call(bar, Vec::new(), vec![Type::field()]).to_vec(); builder.terminate_with_return(results); - builder.new_function("bar".into(), bar_id); + builder.new_function("bar".into(), bar_id, false); let expected_return = 72u128; let seventy_two = builder.field_constant(expected_return); builder.terminate_with_return(vec![seventy_two]); @@ -582,7 +586,7 @@ mod test { let id2_id = Id::test_new(3); // Compiling main - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir, false); let main_v0 = builder.add_parameter(Type::field()); let main_f1 = builder.import_function(square_id); @@ -595,18 +599,18 @@ mod test { builder.terminate_with_return(vec![main_v16]); // Compiling square f1 - builder.new_function("square".into(), square_id); + builder.new_function("square".into(), square_id, false); let square_v0 = builder.add_parameter(Type::field()); let square_v2 = builder.insert_binary(square_v0, BinaryOp::Mul, square_v0); builder.terminate_with_return(vec![square_v2]); // Compiling id1 f2 - builder.new_function("id1".into(), id1_id); + builder.new_function("id1".into(), id1_id, false); let id1_v0 = builder.add_parameter(Type::Function); builder.terminate_with_return(vec![id1_v0]); // Compiling id2 f3 - builder.new_function("id2".into(), id2_id); + builder.new_function("id2".into(), id2_id, false); let id2_v0 = builder.add_parameter(Type::Function); builder.terminate_with_return(vec![id2_v0]); @@ -638,7 +642,7 @@ mod test { // return v4 // } let main_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir, false); let factorial_id = Id::test_new(1); let factorial = builder.import_function(factorial_id); @@ -647,7 +651,7 @@ mod test { let results = builder.insert_call(factorial, vec![five], vec![Type::field()]).to_vec(); builder.terminate_with_return(results); - builder.new_function("factorial".into(), factorial_id); + builder.new_function("factorial".into(), factorial_id, false); let b1 = builder.insert_block(); let b2 = builder.insert_block(); @@ -738,7 +742,7 @@ mod test { // jmp b3(Field 2) // } let main_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir, false); let main_cond = builder.add_parameter(Type::bool()); let inner1_id = Id::test_new(1); @@ -748,14 +752,14 @@ mod test { builder.insert_call(assert_constant, vec![main_v2], vec![]); builder.terminate_with_return(vec![]); - builder.new_function("inner1".into(), inner1_id); + builder.new_function("inner1".into(), inner1_id, false); let inner1_cond = builder.add_parameter(Type::bool()); let inner2_id = Id::test_new(2); let inner2 = builder.import_function(inner2_id); let inner1_v2 = builder.insert_call(inner2, vec![inner1_cond], vec![Type::field()])[0]; builder.terminate_with_return(vec![inner1_v2]); - builder.new_function("inner2".into(), inner2_id); + builder.new_function("inner2".into(), inner2_id, false); let inner2_cond = builder.add_parameter(Type::bool()); let then_block = builder.insert_block(); let else_block = builder.insert_block(); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/mem2reg.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/mem2reg.rs index 0a49ca4eccaa..c6cc39bb495c 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/mem2reg.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/mem2reg.rs @@ -433,7 +433,7 @@ mod tests { // } let func_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("func".into(), func_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("func".into(), func_id, RuntimeType::Acir, false); let v0 = builder.insert_allocate(Type::Array(Rc::new(vec![Type::field()]), 2)); let one = builder.field_constant(FieldElement::one()); let two = builder.field_constant(FieldElement::one()); @@ -474,7 +474,7 @@ mod tests { // } let func_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("func".into(), func_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("func".into(), func_id, RuntimeType::Acir, false); let v0 = builder.insert_allocate(Type::field()); let one = builder.field_constant(FieldElement::one()); builder.insert_store(v0, one); @@ -508,7 +508,7 @@ mod tests { // } let func_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("func".into(), func_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("func".into(), func_id, RuntimeType::Acir, false); let v0 = builder.insert_allocate(Type::field()); let const_one = builder.field_constant(FieldElement::one()); builder.insert_store(v0, const_one); @@ -567,7 +567,7 @@ mod tests { // return v2, v3, v4 // } let main_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir, false); let v0 = builder.insert_allocate(Type::field()); @@ -647,7 +647,7 @@ mod tests { // return // } let main_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir, false); let v0 = builder.insert_allocate(Type::field()); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/simplify_cfg.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/simplify_cfg.rs index a31def8fd984..9e15ca32c8eb 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/simplify_cfg.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/simplify_cfg.rs @@ -172,7 +172,7 @@ mod test { // return v1 // } let main_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir, false); let b1 = builder.insert_block(); let b2 = builder.insert_block(); @@ -228,7 +228,7 @@ mod test { // return Field 2 // } let main_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir, false); let v0 = builder.add_parameter(Type::bool()); let b1 = builder.insert_block(); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/unrolling.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/unrolling.rs index 645adb6b3501..ad02e2330678 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/unrolling.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/unrolling.rs @@ -503,7 +503,7 @@ mod tests { let main_id = Id::test_new(0); // Compiling main - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir, false); let b1 = builder.insert_block(); let b2 = builder.insert_block(); @@ -605,7 +605,7 @@ mod tests { // return Field 0 // } let main_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir, false); let b1 = builder.insert_block(); let b2 = builder.insert_block(); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs index 9c760c013a9e..a7fb5acbc314 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs @@ -89,13 +89,14 @@ impl<'a> FunctionContext<'a> { parameters: &Parameters, runtime: RuntimeType, shared_context: &'a SharedContext, + should_fold: bool, ) -> Self { let function_id = shared_context .pop_next_function_in_queue() .expect("No function in queue for the FunctionContext to compile") .1; - let builder = FunctionBuilder::new(function_name, function_id, runtime); + let builder = FunctionBuilder::new(function_name, function_id, runtime, should_fold); let mut this = Self { definitions: HashMap::default(), builder, shared_context }; this.add_parameters_to_scope(parameters); this @@ -111,7 +112,7 @@ impl<'a> FunctionContext<'a> { if func.unconstrained { self.builder.new_brillig_function(func.name.clone(), id); } else { - self.builder.new_function(func.name.clone(), id); + self.builder.new_function(func.name.clone(), id, func.should_fold); } self.add_parameters_to_scope(&func.parameters); } diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs index f3fa5d1d2f87..e5f89e961f1a 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs @@ -52,7 +52,7 @@ pub(crate) fn generate_ssa( // Queue the main function for compilation context.get_or_queue_function(main_id); - + dbg!(main.should_fold); let mut function_context = FunctionContext::new( main.name.clone(), &main.parameters, @@ -62,6 +62,7 @@ pub(crate) fn generate_ssa( RuntimeType::Acir }, &context, + main.should_fold, ); // Generate the call_data bus from the relevant parameters. We create it *before* processing the function body diff --git a/noir/noir-repo/compiler/noirc_frontend/src/ast/function.rs b/noir/noir-repo/compiler/noirc_frontend/src/ast/function.rs index 46f0ac0fa0fc..9ed6c784c7cf 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/ast/function.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/ast/function.rs @@ -108,6 +108,7 @@ impl From for NoirFunction { Some(FunctionAttribute::Test { .. }) => FunctionKind::Normal, Some(FunctionAttribute::Oracle(_)) => FunctionKind::Oracle, Some(FunctionAttribute::Recursive) => FunctionKind::Recursive, + Some(FunctionAttribute::Fold) => FunctionKind::Normal, None => FunctionKind::Normal, }; diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/resolver.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/resolver.rs index 00b1b443430e..16a23aca854c 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/resolver.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/resolver.rs @@ -897,7 +897,7 @@ impl<'a> Resolver<'a> { let name_ident = HirIdent::non_trait_method(id, location); let attributes = func.attributes().clone(); - + let mut generics = vecmap(&self.generics, |(_, typevar, _)| typevar.clone()); let mut parameters = vec![]; let mut parameter_types = vec![]; @@ -928,7 +928,7 @@ impl<'a> Resolver<'a> { }); } let is_low_level_function = - func.attributes().function.as_ref().map_or(false, |func| func.is_low_level()); + attributes.function.as_ref().map_or(false, |func| func.is_low_level()); if !self.path_resolver.module_id().krate.is_stdlib() && is_low_level_function { let error = ResolverError::LowLevelFunctionOutsideOfStdlib { ident: func.name_ident().clone() }; @@ -977,6 +977,14 @@ impl<'a> Resolver<'a> { .map(|(name, typevar, _span)| (name.clone(), typevar.clone())) .collect(); + let should_inline = attributes.function.as_ref().map_or(true, |func_attribute| !func_attribute.is_foldable()); + if func.name() == "basic_func" { + dbg!(attributes.clone()); + } + // if matches!(attributes.function, Some(FunctionAttribute::Fold)) { + // dbg!(name_ident.clone()); + // } + FuncMeta { name: name_ident, kind: func.kind, @@ -991,6 +999,7 @@ impl<'a> Resolver<'a> { has_body: !func.def.body.is_empty(), trait_constraints: self.resolve_trait_constraints(&func.def.where_clause), is_entry_point: self.is_entry_point_function(func), + should_inline, } } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/mod.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/mod.rs index ab759f454e5f..7eb3642f7218 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/mod.rs @@ -502,6 +502,7 @@ mod test { trait_constraints: Vec::new(), direct_generics: Vec::new(), is_entry_point: true, + should_inline: true, }; interner.push_fn_meta(func_meta, func_id); diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir_def/function.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir_def/function.rs index 56543e8185c2..825bae30a9e2 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir_def/function.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir_def/function.rs @@ -124,6 +124,10 @@ pub struct FuncMeta { /// True if this function is an entry point to the program. /// For non-contracts, this means the function is `main`. pub is_entry_point: bool, + + /// False if this function is marked with an attribute + /// that indicates it should not be inlined, such as for folding. + pub should_inline: bool, } impl FuncMeta { diff --git a/noir/noir-repo/compiler/noirc_frontend/src/lexer/lexer.rs b/noir/noir-repo/compiler/noirc_frontend/src/lexer/lexer.rs index cf66ece0c300..41433e81acaf 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/lexer/lexer.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/lexer/lexer.rs @@ -726,6 +726,19 @@ mod tests { ); } + #[test] + fn fold_attribute() { + let input = r#"#[fold]"#; + + let mut lexer = Lexer::new(input); + let token = lexer.next_token().unwrap(); + + assert_eq!( + token.token(), + &Token::Attribute(Attribute::Function(FunctionAttribute::Fold)) + ); + } + #[test] fn contract_library_method_attribute() { let input = r#"#[contract_library_method]"#; diff --git a/noir/noir-repo/compiler/noirc_frontend/src/lexer/token.rs b/noir/noir-repo/compiler/noirc_frontend/src/lexer/token.rs index 3dc9d05b15ee..78ddbf3c341e 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/lexer/token.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/lexer/token.rs @@ -486,6 +486,7 @@ impl Attribute { } ["test"] => Attribute::Function(FunctionAttribute::Test(TestScope::None)), ["recursive"] => Attribute::Function(FunctionAttribute::Recursive), + ["fold"] => Attribute::Function(FunctionAttribute::Fold), ["test", name] => { validate(name)?; let malformed_scope = @@ -537,6 +538,7 @@ pub enum FunctionAttribute { Oracle(String), Test(TestScope), Recursive, + Fold, } impl FunctionAttribute { @@ -565,6 +567,10 @@ impl FunctionAttribute { pub fn is_low_level(&self) -> bool { matches!(self, FunctionAttribute::Foreign(_) | FunctionAttribute::Builtin(_)) } + + pub fn is_foldable(&self) -> bool { + matches!(self, FunctionAttribute::Fold) + } } impl fmt::Display for FunctionAttribute { @@ -575,6 +581,7 @@ impl fmt::Display for FunctionAttribute { FunctionAttribute::Builtin(ref k) => write!(f, "#[builtin({k})]"), FunctionAttribute::Oracle(ref k) => write!(f, "#[oracle({k})]"), FunctionAttribute::Recursive => write!(f, "#[recursive]"), + FunctionAttribute::Fold => write!(f, "#[fold]"), } } } @@ -619,6 +626,7 @@ impl AsRef for FunctionAttribute { FunctionAttribute::Oracle(string) => string, FunctionAttribute::Test { .. } => "", FunctionAttribute::Recursive => "", + FunctionAttribute::Fold => "", } } } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/ast.rs b/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/ast.rs index 7fcf8e877928..532c95f9a22f 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/ast.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/ast.rs @@ -208,6 +208,7 @@ pub struct Function { pub return_type: Type, pub unconstrained: bool, + pub should_fold: bool, } /// Compared to hir_def::types::Type, this monomorphized Type has: diff --git a/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/mod.rs b/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/mod.rs index 4938d33aff98..df0aac4bfc0a 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/mod.rs @@ -314,9 +314,12 @@ impl<'interner> Monomorphizer<'interner> { }); let unconstrained = modifiers.is_unconstrained; + let should_fold = !meta.should_inline; + dbg!(should_fold); + let parameters = self.parameters(&meta.parameters); let body = self.expr(body_expr_id)?; - let function = ast::Function { id, name, parameters, body, return_type, unconstrained }; + let function = ast::Function { id, name, parameters, body, return_type, unconstrained, should_fold }; self.push_function(id, function); Ok(()) @@ -1336,7 +1339,7 @@ impl<'interner> Monomorphizer<'interner> { let name = lambda_name.to_owned(); let unconstrained = false; - let function = ast::Function { id, name, parameters, body, return_type, unconstrained }; + let function = ast::Function { id, name, parameters, body, return_type, unconstrained, should_fold: false }; self.push_function(id, function); let typ = @@ -1450,7 +1453,7 @@ impl<'interner> Monomorphizer<'interner> { parameters.append(&mut converted_parameters); let unconstrained = false; - let function = ast::Function { id, name, parameters, body, return_type, unconstrained }; + let function = ast::Function { id, name, parameters, body, return_type, unconstrained, should_fold: false }; self.push_function(id, function); let lambda_value = @@ -1568,7 +1571,7 @@ impl<'interner> Monomorphizer<'interner> { let name = lambda_name.to_owned(); let unconstrained = false; - let function = ast::Function { id, name, parameters, body, return_type, unconstrained }; + let function = ast::Function { id, name, parameters, body, return_type, unconstrained, should_fold: false }; self.push_function(id, function); ast::Expression::Ident(ast::Ident { diff --git a/noir/noir-repo/test_programs/execution_success/fold_basic/Nargo.toml b/noir/noir-repo/test_programs/execution_success/fold_basic/Nargo.toml new file mode 100644 index 000000000000..575ba1f3ad14 --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/fold_basic/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "fold_basic" +type = "bin" +authors = [""] +compiler_version = ">=0.25.0" + +[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/execution_success/fold_basic/src/main.nr b/noir/noir-repo/test_programs/execution_success/fold_basic/src/main.nr new file mode 100644 index 000000000000..946f2528f788 --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/fold_basic/src/main.nr @@ -0,0 +1,9 @@ +fn main(x: Field, y: pub Field) { + basic_func(x, y); + basic_func(x, y); +} + +#[fold] +fn basic_func(x: Field, y: Field) { + assert(x != y); +} From 99bee540cf86985a5c2395836fb98608800377a8 Mon Sep 17 00:00:00 2001 From: Maxim Vezenov Date: Thu, 14 Mar 2024 18:49:29 +0000 Subject: [PATCH 079/139] Update noir/noir-repo/acvm-repo/acvm_js/src/compression.rs Co-authored-by: Tom French <15848336+TomAFrench@users.noreply.github.com> --- noir/noir-repo/acvm-repo/acvm_js/src/compression.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noir/noir-repo/acvm-repo/acvm_js/src/compression.rs b/noir/noir-repo/acvm-repo/acvm_js/src/compression.rs index 73bcd02ecd1b..18e9216297ec 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/src/compression.rs +++ b/noir/noir-repo/acvm-repo/acvm_js/src/compression.rs @@ -13,7 +13,7 @@ pub fn compress_witness(witness_map: JsWitnessMap) -> Result, JsString> console_error_panic_hook::set_once(); let witness_map = WitnessMap::from(witness_map); - let witness_stack: WitnessStack = witness_map.into(); + let witness_stack = WitnessStack::from(witness_map); let compressed_witness_stack: Vec = Vec::::try_from(witness_stack).map_err(|err| err.to_string())?; From 9a57443b06bc9f3939eb3fda2aa00f4d0c4e74f6 Mon Sep 17 00:00:00 2001 From: Maxim Vezenov Date: Thu, 14 Mar 2024 18:50:33 +0000 Subject: [PATCH 080/139] Update noir/noir-repo/acvm-repo/acvm_js/src/execute.rs Co-authored-by: Tom French <15848336+TomAFrench@users.noreply.github.com> --- noir/noir-repo/acvm-repo/acvm_js/src/execute.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noir/noir-repo/acvm-repo/acvm_js/src/execute.rs b/noir/noir-repo/acvm-repo/acvm_js/src/execute.rs index 6985183a8a07..dee74bfc1eed 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/src/execute.rs +++ b/noir/noir-repo/acvm-repo/acvm_js/src/execute.rs @@ -59,7 +59,7 @@ pub async fn execute_circuit_with_black_box_solver( // TODO(https://github.com/noir-lang/noir/issues/4428): These need to be updated to match the same interfaces // as the native ACVM executor. Right now native execution still only handles one circuit so I do not feel the need // to break the JS interface just yet. - circuit: Vec, + program: Vec, initial_witness: JsWitnessMap, foreign_call_handler: ForeignCallHandler, ) -> Result { From f5327b7d76152ff415758060d888975941f37c83 Mon Sep 17 00:00:00 2001 From: Maxim Vezenov Date: Thu, 14 Mar 2024 18:50:40 +0000 Subject: [PATCH 081/139] Update noir/noir-repo/acvm-repo/acvm_js/src/public_witness.rs Co-authored-by: Tom French <15848336+TomAFrench@users.noreply.github.com> --- noir/noir-repo/acvm-repo/acvm_js/src/public_witness.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noir/noir-repo/acvm-repo/acvm_js/src/public_witness.rs b/noir/noir-repo/acvm-repo/acvm_js/src/public_witness.rs index 2ae90b79a6a5..d86a0cb77bc4 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/src/public_witness.rs +++ b/noir/noir-repo/acvm-repo/acvm_js/src/public_witness.rs @@ -29,7 +29,7 @@ pub fn get_return_witness( // TODO(https://github.com/noir-lang/noir/issues/4428): These need to be updated to match the same interfaces // as the native ACVM executor. Right now native execution still only handles one circuit so I do not feel the need // to break the JS interface just yet. - circuit: Vec, + program: Vec, witness_map: JsWitnessMap, ) -> Result { console_error_panic_hook::set_once(); From 8612d41a5bde7f334457fd45cd3bd01c2f83324c Mon Sep 17 00:00:00 2001 From: Maxim Vezenov Date: Thu, 14 Mar 2024 18:50:46 +0000 Subject: [PATCH 082/139] Update noir/noir-repo/acvm-repo/acvm_js/src/public_witness.rs Co-authored-by: Tom French <15848336+TomAFrench@users.noreply.github.com> --- noir/noir-repo/acvm-repo/acvm_js/src/public_witness.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noir/noir-repo/acvm-repo/acvm_js/src/public_witness.rs b/noir/noir-repo/acvm-repo/acvm_js/src/public_witness.rs index d86a0cb77bc4..9b8c36bfe8da 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/src/public_witness.rs +++ b/noir/noir-repo/acvm-repo/acvm_js/src/public_witness.rs @@ -57,7 +57,7 @@ pub fn get_public_parameters_witness( ) -> Result { console_error_panic_hook::set_once(); let program: Program = - Program::deserialize_program(&circuit).expect("Failed to deserialize circuit"); + Program::deserialize_program(&program).expect("Failed to deserialize circuit"); let circuit = &program.functions[0]; let witness_map = WitnessMap::from(solved_witness); From 246adb2fa0cc6975c811df6f65edfbd1aec45766 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Thu, 14 Mar 2024 18:57:32 +0000 Subject: [PATCH 083/139] rename remaining vars to --- noir/noir-repo/acvm-repo/acvm_js/src/execute.rs | 6 +++--- noir/noir-repo/acvm-repo/acvm_js/src/public_witness.rs | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/noir/noir-repo/acvm-repo/acvm_js/src/execute.rs b/noir/noir-repo/acvm-repo/acvm_js/src/execute.rs index dee74bfc1eed..36c9d60f118b 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/src/execute.rs +++ b/noir/noir-repo/acvm-repo/acvm_js/src/execute.rs @@ -34,7 +34,7 @@ pub async fn create_black_box_solver() -> WasmBlackBoxFunctionSolver { /// @returns {WitnessMap} The solved witness calculated by executing the circuit on the provided inputs. #[wasm_bindgen(js_name = executeCircuit, skip_jsdoc)] pub async fn execute_circuit( - circuit: Vec, + program: Vec, initial_witness: JsWitnessMap, foreign_call_handler: ForeignCallHandler, ) -> Result { @@ -42,7 +42,7 @@ pub async fn execute_circuit( let solver = WasmBlackBoxFunctionSolver::initialize().await; - execute_circuit_with_black_box_solver(&solver, circuit, initial_witness, foreign_call_handler) + execute_circuit_with_black_box_solver(&solver, program, initial_witness, foreign_call_handler) .await } @@ -64,7 +64,7 @@ pub async fn execute_circuit_with_black_box_solver( foreign_call_handler: ForeignCallHandler, ) -> Result { console_error_panic_hook::set_once(); - let program: Program = Program::deserialize_program(&circuit) + let program: Program = Program::deserialize_program(&program) .map_err(|_| JsExecutionError::new("Failed to deserialize circuit. This is likely due to differing serialization formats between ACVM_JS and your compiler".to_string(), None))?; let circuit = &program.functions[0]; diff --git a/noir/noir-repo/acvm-repo/acvm_js/src/public_witness.rs b/noir/noir-repo/acvm-repo/acvm_js/src/public_witness.rs index 9b8c36bfe8da..881ac0749829 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/src/public_witness.rs +++ b/noir/noir-repo/acvm-repo/acvm_js/src/public_witness.rs @@ -34,7 +34,7 @@ pub fn get_return_witness( ) -> Result { console_error_panic_hook::set_once(); let program: Program = - Program::deserialize_program(&circuit).expect("Failed to deserialize circuit"); + Program::deserialize_program(&program).expect("Failed to deserialize circuit"); let circuit = &program.functions[0]; let witness_map = WitnessMap::from(witness_map); @@ -52,7 +52,7 @@ pub fn get_return_witness( /// @returns {WitnessMap} A witness map containing the circuit's public parameters. #[wasm_bindgen(js_name = getPublicParametersWitness)] pub fn get_public_parameters_witness( - circuit: Vec, + program: Vec, solved_witness: JsWitnessMap, ) -> Result { console_error_panic_hook::set_once(); @@ -75,12 +75,12 @@ pub fn get_public_parameters_witness( /// @returns {WitnessMap} A witness map containing the circuit's public inputs. #[wasm_bindgen(js_name = getPublicWitness)] pub fn get_public_witness( - circuit: Vec, + program: Vec, solved_witness: JsWitnessMap, ) -> Result { console_error_panic_hook::set_once(); let program: Program = - Program::deserialize_program(&circuit).expect("Failed to deserialize circuit"); + Program::deserialize_program(&program).expect("Failed to deserialize circuit"); let circuit = &program.functions[0]; let witness_map = WitnessMap::from(solved_witness); From 5bc6d2f9157022f6ae510c842e3a1172e8bdb06e Mon Sep 17 00:00:00 2001 From: vezenovm Date: Thu, 14 Mar 2024 19:01:52 +0000 Subject: [PATCH 084/139] add comment to witness_compression --- .../execution_success/witness_compression/src/main.nr | 3 +++ 1 file changed, 3 insertions(+) diff --git a/noir/noir-repo/test_programs/execution_success/witness_compression/src/main.nr b/noir/noir-repo/test_programs/execution_success/witness_compression/src/main.nr index 803b72c64c55..f18d4b902a5f 100644 --- a/noir/noir-repo/test_programs/execution_success/witness_compression/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/witness_compression/src/main.nr @@ -1,3 +1,6 @@ +// This test should be used to regenerate the serialized witness used in the `acvm_js` integration tests. +// The `acvm_js` test file containing the serialized witness should be also called `witness_compression`. +// After recompiling Noir, you can manually print the witness byte array to be written to file after execution. fn main(x : Field, y : pub Field) -> pub Field { assert(x != y); x + y From 8c4fcde1dd1c1a347acc02f4066b5b96aec70fae Mon Sep 17 00:00:00 2001 From: vezenovm Date: Thu, 14 Mar 2024 19:23:14 +0000 Subject: [PATCH 085/139] update snapshots' --- .../__snapshots__/contract_class.test.ts.snap | 12 +++++----- .../__snapshots__/index.test.ts.snap | 24 +++++++------------ 2 files changed, 15 insertions(+), 21 deletions(-) diff --git a/yarn-project/circuits.js/src/contract/__snapshots__/contract_class.test.ts.snap b/yarn-project/circuits.js/src/contract/__snapshots__/contract_class.test.ts.snap index a13cd2f939b1..521b8358102e 100644 --- a/yarn-project/circuits.js/src/contract/__snapshots__/contract_class.test.ts.snap +++ b/yarn-project/circuits.js/src/contract/__snapshots__/contract_class.test.ts.snap @@ -9,18 +9,18 @@ exports[`ContractClass creates a contract class from a contract compilation arti "selector": { "value": 2381782501 }, - "bytecode": "0x1f8b08000000000000ffed9d07741d45b6ae5bb61ce0481893b3450e06a3e49c64724ec6608c31b62c0b1b0739623298e81cc8c10639e78c718e18c3cc30393381811926dd3b7367ddf5e6be77df7a8f75bbcea9bdf4ab5c7daca3e992ff2355af5552f53ed5bdbffa7b7775aaeeca0952d33fc294a3f3cdc3744170f824bf97e9ff85ffda5414e3ba0a5d72e6640967b32ce16c9e259cb959c2d9224b385b660967ab2ce16c9d259cc7c4c8a9d89a05b5a7b8798f75a06bdc8c892cd3342f0b34cdcf324d8fcb024ddb04d9d1461d9f259c6db384f3842ce13c314b384fca12ce93b384f3942ce13c354b384fcb12ced3b384f38c2ce13c334b38cfca12ceb3b384f39c2ce16c97259c0559c2796e96709e97259ce76709e70559c2796196705e1423677be0bc58ffbf44ffbf54ffbf4cff97b297ebff57e8ff1d741d73f5fc958a2b4cea214db1f15b49984ac3d4314c9d8cdf3a87a94b98ba86a99bfead40ffd63d4c3dc2d4334cbdc2d45b6bd0274c5785e9ea305d13a66bc3745d98ae0fd30d61ba314c3785e9e630dd12a65bc3745b986e0fd31d61ba334c7785a96f98ee0e53bf30dd13a67bc3d43f4cf7856980c1727f980686e981300d0ad383611a1ca621612a0fd3d03055846958982ac3f4509886876944981e0ed3c8308d0ad3e8308d09535598c686695c98c68769429826866952981e09d3e4303d1aa6c7c2f4b8a1d913617a324c4f85e96983f399303d1ba629617a2e4ccf87e98530bd18a697c2f47298a686695a98a68769469866866956986687694e98e686695e985e09d3ab617a2d4caf87e98d30bd19a6b7c2f47698de09d3bb619a1fa605617a4fb3c88ef07e98aac3b4304c8bc2b4384c4bc2b4344ccbc2b43c4c2bc2b4324cabc2b43a4c6bc2b4364cebc2b43e4c1bc2b4314c9bc2b4394c1f84694b983e0cd3d6306d0bd3f630ed08d3ce30ed0ad3ee30ed09d3de30ed0bd3fe301d08d347613a18a68fc374284c9f84e9d3307d2b4cdf0ed377c2f45998be1ba6ef199a7f3f4c3f08d30fc3f4236dfbb1feff135d56eedffd344c3fd3f99febffbfd0ff7fa9ff7f6e2cf3ab30fddab0fd264cbf356c5f84e9773affa5feff95feff7bfdff0ffaffd7faff1ff5ff3fe9ff7fd6ffffa2ffff55ffff37fdffdff5ffbfe9ff7fd7ffff43ffff47981e2848e55b0735535910531b555a997cf623e25f1cd49e9416cdf56ff2bf40db73f5bcfc17ed5ae8f91686bda59e6f69aca7b59e6f6dd8dbeaf9b686fd443d7fa2613f59cf9f6cd84fd5f3a71af60bf4fc05604f04706f58db95adb936e5804de2b519d85a685b73b0b594d581ad95b6b5009b6cdf96603b46db5a81ed586d6b0db684b61d235a86294fdbca82b862a570885a6f7edcebd5cfcb8e8b9f77a85a6f1b47bcc7c7cf3b4cadb7ad035e151f27e8751d0f7173a2b6b505db49da7602d84ed6b613c1768ab69d04b653b5ed64b09da66da780ed746d3b156c6768db69603b53db4e07db59da7606d8ced6b633c1768eb69d05b676da7636d80ab4ed1cb09dab6dedc0769eb61580ed7c6d3b176c1768db7960bb50dbce07db45da7601d8a4fdbd106c72be7891b6a9b6e3981c5846dba5dd4a2e236d36d82e95f61a6c97495b0db6f6d24e83ed72f02db62ba0ad115b076d93764bfdd64de7cb82b8f693e24ab5deee71af375cb35a6fcff8d79b7ce6d82ba8d1b50cfc7407ad7aeb7c8cfd9a8ad0778e4ee247ecb990bf09ca4a39d1438e3dc2ae8e313d74be779ae5ba19cbe543991e96fa9705f1d6bfa7c1d3d3606e017937315b52e263b6ce53c631db1fca9ab127e7418d31666f050e0731dbd9c76c9da78c63b612ca9ab127e7c28d3166ef070e07315bee26668b0b7dcca6ee9b05813df6e47aa831c6ec08e0883f663bfa98adfb9471cc3e0765cdd8936be2c618b3938123fe98ed5ceecf0dea3c651cb373a1ac197b727fa631c6ec8bc0e120662b7d3b5be729e3987d0fca9ab127f70a1b63ccbe0a1cf1c76c5747315be26336483d030d027becc97debc618b30b8123fe981deaefcfd67dca386677405933f6e4194a638cd9f53aaf9e33fc583f67380b6c3fd1b6b38137fed8aee8e828b68b7d6ca7fa8604813d46e5795e638cedbd3aafe2f8e7d01f416cbfd0b673c1f64b6d3b0f6c9f6bdbf9502f07fb40b9df07ea3c65bc0ffc1aca9ab12ccf961be33ef043e07010b3153e66eb3c651cb37f85b266ec493f87c618b35f00878398adf4315be729e398fd3f50d68cbd4b74be31c6acf43555e70b5feaf385cbc0f695b6b507dbefb5ed72b0fd41dbae00dbd7dad6016c7fd4b62bc1f6276d2b04db9fb5ad086c7fd1b662b0fd55db4ac0f66fda560ab67fd7b68e60fb9bb67502dbdfb5ad33d8fe43dbba80ed1fdad655dbd4f32ee97b25e7adad81b52c886fdb26401799728cf932c817bbe529cc071ef4551abfaf1255f792a0ee752f059e8e0eea9e001f75e1e9083c9de2e749f645ed1cff7a93dbb8c4d03401be4aa05e5d1cd42b077cc9ba655efce5830df7f32e16c6aef13316e7802f59b7cc770546b161bb23efffc8fea3dae673736a781dec4bc9e333fa2b030ef1970b65fed9aea6ec859a2d0f7ec736b89361731497c9b8105fb26e99177f79509f4e0dcf585c57c68e06a3ab3622077cc9ba4ddf79902f72ab4f5a9ece24be1d9c775bdb34d1bc7b03f8ee6af82e357c63db2953ba635b57608efdfa471fdb7ac4bfde423c5796eb14f183e70f783d11579dd0b75ca7881fb1e742fe869c9ab2524ef4907658d8d53e2cdb12d9cde5ba18cbe54399ee96fa9705f1d6bf87c1d3c36056c79b9e702c74b03f2463a0bbc121f3a5a05d8f08edba837652e612d0cec1b96752bb6e068fcc77041e69bfb13d2b6a609e2202df780e8bd772f23b9e07b8da5e4506a3ccdbb6575760ec686174704e589cee78580a8c62eb063c258e348bdaae2524be5d5c57e6800f393737af6d72a1ccedcd6bca56e438652bc6736799ea7acd1bff762a2ec4fda32e3c8ef7a12247f15888f76fbe09e28d35b35d32db9ba87b3caedaf2128347e6c59f67f6cc9ed9337b66cfec993db367f6cc9ed9337b66cfec993db367f6cc9ed9337b667e66c523cf13b0df9694eb44c268f67f73759f3ff92d3ebd2e7c06f44fa7fdc18a0bf1d99ff483b8cca8732e9439b1590ddb7f437f30b32f51d4b674d13736ddb6147fd81fac219e21961a3ca6ef3c8b3ef85c1a3573d507ca6c33641efba7897e45c0e36a7f2c36784cdfd86694906a16d5cebaead3171567b6fe8405b1f92e1eeaeab9aefaee99fa76a879fcea64689afc26a961536dd25dcd6beaede2396fa6cf9df1b821f9389fe362bf0cf4157f3b5b5cab7f42b3a0f6b10263dd555f2dd9afa46f4477c3772e9439b759cdb6c13e7565c1e1c706ece325eb96652e83657b18eb6ee3aebe69fba174076ec9b734ead619b8a5cc4570ecfea9ce3b3a061667fa8e041e93e33fbea4fa8b9464c083c73b17e72c8e8ea385188f71f71731fb41dace97a50cf62175d07f37edb158fc7966cfec993db367f6cc9ed9337b66cfec993db367f6cc9ed9337b66cfec993db367e667563ce633747cf65b4ac2d8407d6c92cf33e4fb6cf85c6c6bb31abfae9f01ca33a7f6469df11de55c784779a766c3be0ff85d29dbb674f56c2d6a5b8a3fb6be0f79167d94663d2c9a39f8ae63da6f76e0371245bf1ec0e36a7f8cfa7687adcd2822d52caa9d75d177215d9cd9fa2914c4e63bd55fc4c5735de92f621ebfccef1a613f09b1e173f0a8ef85151bb6a3dd06d8fab5491ebfb9e0628c1b8c67b3afa0f8c37e125f686da59f44fced4071a1cb6384eca3d227a4c4525729f387663565ffa8f3d857a814d6f54fcbef32a5eb93806daa83efc726b7afac4bb6afeddbb57d803526df45b8ae1c9dfa181ae442fe7f35ab292be5a4ac682dec6a1f91ef4a21bbb95c4763b97c28d3cb52ffb220defa9bdf12ee6d30abd8f90bc4d93fe15ccf559bd42b42a3cb40232983e7bcaefad59a6da4d9671afb44b632cae0f9a994f9ffd04645f549b7f5a97475be10d59f13cf176ce734661dcdbee34dbd3f60bebe0e71d11f50d6dd26a8dd272f30d6df1ed62f5cad82e8638b94690beb3f9adfbdb25dfb092ff6379432a7c0b5df0d3a9fc9b5dfd1ba8eb75dfbe1725175c77621ee6323c623b2602c4b9902231e7b447077b52c7b7ec4b2a295f9ed43bc2ec57384f8bf1b996a6f7a1b75917d0abfef2f652e35f69bf8cf9952e79faebe9129eb9236a8d8525729d301f6b5429d4fc076c2778a7a5b7e9729ddf9a7e8a7ea7c55fc754e6edfabf5ba64fb5e65f17d0db0c6e4bb087dcbf9a7f8117b2ee47bc1f144ca891ea2b5b0ab7d44cee190dd5caebbb15c3e94e963a97f59106ffdaf3278ae329855ec94409cf586772d5cb5d57d22346a0f1a4919bc776dfbaeb1ed5e47439da79adf4bcf0f0eff762f1e27dd9cb3d9df9533efdfdace4fda1bfc787e722bb4b3094b59f3beb42c1767ff747c1f08cf0bf17d2057d748f9416d3df30d0e97bedb18bedb34a0efb686efb60de8db6bee3567d29c69cc1f7c0ed90c185d1cebf0b85a1746dbf1af3930ba7a67b3240346fce6351eef84d1c577c2eb3ba6109eebb4004617ef1b677abfba1330e2370684d1c53bda997ea71adfdb96e55a01a38b718d700ca5ba30dac63a6a0dff1d8c6b5454df714070aca36380d1c5d82089a0f678264762ec068cb2dcb1c0e8e2395222a87d5fed488cf8bc52964b38664c776c77dcf7a738d37b100dd1af20ea5c037d3bb8ff5f8c7d13eaa2454fb73c69cf7dd0b783fb5f492d702ccb236981cfe75c8cad99086a3f0b3b120f3e4394e54e00c632478cbd33602c034659ee4460ece388b12c03c63ec028f69380d1c17dc824639f0c18f17e9d2c7732305eed88f1aa0c18af064659ee146074714f31017eebc2780d30ca72a702e3b58e18afc980f15a6094e54e03c6eb1c315e9b01e375c028cb9d0e8cd73b62bc2e03c6eb8151963b03186f70c4787d068c3700a32c772630dee888f1860c186f044659ee2c60bcc911e38d1930de048cb2dcd9c078b323c69b3260bc191865b97380f116478c3767c0780b30ca72ed80f156478cb764c0782b30ca7205c0789b23c65b3360bc0d1865b97381f176478cb765c0783b30ca72e701e31d8e186fcf80f10e6094e5ce07c63b1d31de9101e39dc028cb5d008c773962bc3303c6bb805196bb1018fb3a62bc2b03c6bec028cb5d048c773b62ec9b01e3ddc0d8d7c2d8cf11e3dd1930f6034659ee7260bc277ec6e4b574bf0c18ef019e7be3e7496a764f063cf7bae5497e43f11e8baffbe2f795dc16fd83bad7fd3ee019103f4f725bdc97018f30e4c372a8d9fdf13326351b9001e3fdc033307e9ea466f767c0331034bbdfa2d903f13326351b9801e303c033287e9ea4660f64c03308347bc0a2d983f13326351b9401e383c033387e9ea4660f66c03338a8d1ec418b6643e2674c6a363803c621c0531e3f4f52b32119f0948366432c9a0d8d9f31a95979068c4381a7227e9ea4664333e0a900cd865a341b163f6352b38a0c1887014f65fc3c49cd8665c053099a0db368f650fc8c49cd2a33607c087886c7cf93d4eca10c788683660f59341b113f6352b3e119308e009e87e3e7496a3622039e8741b31116cd463a627c3803c691169eb8bf89feb0c5d76847751f15d4bdeec2900fcb613f89318e184767c03806186539ec2751e588714c068c55c028cb251c33a6eb275105bec7c6ef3bd92e550575d767ac5b9eb4fd24d0f738475a8c0deaaec538b73c69fb49a0eff18eb41817d45d8bf1c033c1811609f051171e61c887e5b09fc444478c1332609c088cb21cf69398e4887162068c93805196c37e128f38629c9401e323c028cb613f89c98e181fc980713230ca72d84fe251478c9333607c14186539ec27f19823c64733607c0c186539ec27f1b823c6c732607c1c186539ec27f18423c6c733607c02186539ec27f1a423c62732607c12186539ec27f19423c62733607c0a186539ec27f1b423c6a732607c1a186539ec27f18c23c6a733607c06186539ec27f1ac23c66732607c16186539ec2731c511e3b319304e0146596ea463c674d72f531ab9efa86b95c6ee3beabaa4b1fbf671eee3bc29f8f671eee3bc29f8f671eee3bc29f8f671eee3bc29f8f671eee3bc29f8f671eee3bc29f8f671eee39cc9f7730e7c27c0874c39c67c19e485211f961be9191b3523f214c4c7538875475fcf13d4fd790b4f8ea3baa3af1708ea2e0cd9c6f85c16308ecc0246af63aa0f627d1815cf8b8e785ec880e745e079c911cf8b19f0bc043c2fc7cf938ca99732e011867c586e6416303e97058c5e47af2313a3d7b1e9e8e8193da367f48c4783311bda70cf9815f1585c5f46c533357e9ea4662f67c033153493e5ee75cb585c5f46c5332d7e9ea4665333e099069a4db568e680b1b8be8c8a677afc3c49cda665c0331d349b66d1cc0163717d1915cf8cf879929a4dcf8067066836dda29903c6e2fa322a9e99f1f324359b9101cf4cd06c864533078cc5f565543cb3e2e7496a3633039e59a0d94c8b660e188bebcba87866c7cf93d46c56063cb341b35916cd1c3016d79751f1cc899f27a9d9ec0c78e68066b32d9a39602cae2fa3e2991b3f4f52b33919f0cc05cde6583463651c99058ccf6501a3631d8bebcba878e639e2999b01cf3ce079c511cfbc0c785e019e57e3e749c6d42b19f008433e2c37320b189fcb0246afa3d79189d1ebd87474f48c9ed13366c6f87c1630fa6ded1959191d5c5fa57d87e69546ee3bea1d9ac6ee3bea1d9ac6eedbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98f7326dfafc5efbb38d377585f031e17efd43aaa67a15aefeb7a5ddfc4a89fd2ea0d43ab570cadf2a1cceba0df1b0ef4cb01bfb26e99177f99325f4cc0ecc877f171e13a8e81fa8b8fe70c3d94ff371dd53daaad7fb391fb8e6aeb1bbbefa8b6beb1fbf671eee3bc29f8f671eee3bc29f8f671eee39cc537e673839af376f9be925ac75b3adf42cf4bf9e7613929d3af55ea7f9bc0ef432e7cfb7dc81f2b9a826f1fe73ece9b826f1fe73ece9b826f1fe77c718ef1707503f004064f9086e749329ece643c63c9788692f1dc43c67313194f2f329ec9643cc5643c33c9781e26e379898c671019cf9d643cd792f15c41c6f334194f57329ef1643cc3c878ee23e3b9858ca78c8ce731329e52329e59643ca3c9785e26e3194cc6d3978ce705329eebc9789e25e3e94ec633878ce752329e89643c9790f13c44c65348c6733f19cf71643c6dc8786e23e3b98a8ce709329e4e643cb3c978aac878a692f19493f1f423e3b9928ce746329e9e643cf3c8781e21e32922e31941c6f30019cf1d643ccdc978ae21e3798a8ca70b19cf38329ef6643c15643cd3c878fa93f1dc4cc6d39b8ce751329e12329e51643c0f92f1dc45c6d310dfe3c884670a19cf75643ccf90f17423e39940c6339d8ce762329e4a329e01643c79643cf9643c1dc8786e25e3e943c6f338194f47329e31643c43c878ee26e379918ce706329e1e643c73c9782691f1cc20e3194ec633908ce732329ee3c978da92f1dc4ec69343c093080eff4672027e7f0d6ccd8c65d567a5ba15d4fcfeb6b6378365ded1f9e69675bf0d36f956d53b966551a7b7a12e653a5ff8af4d499dd05719cc8bbf3ce0788784e776329eb6643cc793f15c46c633908c673819cf0c329e49643c73c9787a90f1dc40c6f32219cfdd643c43c878c690f17424e3799c8ca70f19cfad643c1dc878f2c978f2c8780690f15492f15c4cc6339d8c6702194f37329e67c878ae23e39942c6f31a19cf5d643c0f92f18c22e32921e379948ca73719cfcd643cfdc978a691f15490f1b427e31947c6d3858ce729329e6bc8789a93f1dc41c6f30019cf08329e22329e47c878e691f1f424e3b9918ce74a329e7e643ce5643c53c978aac8786693f17422e379828ce72a329edbc878da90f11c47c6733f194f2119cf43643c9790f14c24e3b9948c670e194f77329e67c978ae27e379818ca72f19cf60329e97c9784693f1cc22e32925e3798c8ca78c8ce716329efbc8788691f18c27e3e94ac6f33419cf15643cd792f1dc49c633888ce725329e87c9786692f11493f14c26e3e945c6731319cf3d643c43c978c692f17426e379928ce76a0bcf6b8e78e47d7759b7ccbf46e2dbc1762854eb7dd7519de6eb75b5d4eb157ef1970b658a8e4dfd57cf877059e132bf4f807dbfe783466f39aa8b3926a6ccbfd5c87db7317cb76922bedb1abedb3611df3ece7d9c33f99e1fbfef62fcb68d4c39c67c19e4f1f8e2e29b408eea59ebd8fe4d8cfa29ad16185abd6568950f65de05fd1638d0cf76be20f3e22f53e68b0998312e0a8278e3e2bdf8eb54acfad21c03babe67e88bf57adf91a651c790f71bb9efa8634863f71d750c69ecbe7d9cfb386f0abe7d9cfb386f0abe7d9cfb3867f25dadf3315e3716a20f75ef57ae07aac1ef229dcf89d1af5ad742bdae167addc2b10878a4cc2b702fdaeff37e9f8fcbb73fb6f9386f0abe99e3dccccb33c44b80cdd533dea8586c88e7cb47d377542c3676df51b1d8d87dfb38f771cee47b71fcbe93cf105f0b6a4fe99e212e069e850eb47054cfe4b5d312a34eaf1975ca8732d550cf250eea99037e65dd32bf04b643b6312b9e293a8fe3bb48b929248c625be89627b97f4d096a4fe9f6af25c0e3603f287254cfe4feb5d4a8d3148bee52a61aeab9d4413d6dfb8ecc2f85ed906dcc8a47dedd15d604947b8184516c8bddf224f7af1782da53bafd6b29f0b8687f1cd533b97f2d33eaf482457729530df55ce6a09eb67d47e697c176c83666c5236399086b02cabd48c228b6256e794a13506799d2ed5fcb80c745fbe3a89ec9fd6bb951a7172dba4b996aa8e77207f5b4ed3b32bf1cb68367f6cc3666c523ef4c0a6b02cabd44c228b6a54e794a0b13506799d2b563cb81c7453bef48f7643bb6c2a8d34b16dda54c35d47385837adaf61d995f01db2113e6f959c85c9d85cc5e67af7314737516327b9dbdce51ccd559c8ec75f63a4731576721b3d7d9eb1cc55c9d85cc5e67af7314737516327b9dbdce51ccd559c8ec75f63a4731576721b3d7d9eb1cc55c9d85cc5e67af7314737516327b9dbdce51ccd559c8ec75f63a4731576721b3d7d9eb1cc55c9d85cc5e67af7314737516327b9dbdce51ccd559c8ec75f63a47315767213383ce8ae7659d17d604947b9984516ccbdcf224dfdf7939a83de518f365905f013ccb1de8e3a89ec97eef2b8d3abd6cd15dca54433d573aa8a76ddf91f995b01d32619e9f85ccd559c8cca0b3e299aaf3c29a8072534918c5b6dc2d4fb21d9b1ad49ed2b5632b81c7453befa89ec9766c9551a7a916dda54c35d47395837adaf61d995f05dbc1337b661bb3e299a6f3c29a8072d34818c5b6c2294f71f23dc46941ed295d3bb60a785cb4f38e744fb663ab8d3a4db3e82e65aaa19eab1dd4d3b6efc8fc6ad80e9930cfcf42e6ea2c64f63a7b9da398abb390d9ebec758e62aece4266afb3d7398ab93a0b99bdce5ee728e6ea2c64f63a7b9da398abb390d9ebec758e62aece4266afb3d7398ab93a0b991974563cd3755e5813506e3a09a3d8563ae529493e77981ed49ed23d77580d3c2e9ecb38d23df9dc618d51a7e916dda54c35d4738d837adaf61d995f03dba1b133cfcf42e66acfdc20cc3e363c7314b38f0dcf1cc5ec63c3334731fbd8f0cc51cc3e363c7314b38f0dcf1cc5ec63c3334731fbd8f0cc51cc3e363c7314b38f0dcf1cc5ec63c3334731fbd8f0cc51cc3e363c7314b38f0dcf1cc5cc101b8a6786ce0b6b02cacd206114db2ab73cc9ef1ecc086a4fe9faedac019ed50ef47154cf64bf9db5469d6658749732d550cfb50eea69db77647e2d6c07cfec996dcc8a67a6ce0b6b02cacd246114db6ab73cc9766c66507b4ad78ead051e17edbca37a26dbb175469d665a749732d550cf750eea69db77647e1d6c07cfec996dcc8a6796ce0b6b02cacd226114db1ab73cc9766c56507b4ad78ead031e17edbca37a26dbb1f5469d6659749732d550cff50eea69db77647e3d6c07cfec996dcc8a67b6ce0b6b02cacd266114db5ab73cc509a8b34ce9dab1f5c0e3a29d7754cf643bb6c1a8d36c8bee52a61aeab9c1413d6dfb8ecc6f80ed906dcc8a678ece0b6b02cacd216114db3ab73cc9fd6b4e507b4ab77f6d001e17ed8fa37a26f7af8d469de658749732d550cf8d0eea69db77647e236c876c63563c73755e5813506e2e09a3d8d6bbe549ee5f7383da53bafd6b23f0b8687f1cd533b97f6d32ea34d7a2bb94a9867a6e72504fdbbe23f39b603b641bb3e299a7f3c29a8072f34818c5b6c1314f02ea2c53bafd6b13f0b8687f1cd533b97f6d36ea34cfa2bb94791feab9d9413d6dfb8ecc6f061e99ae061e577119183c81451f999e24e3e94cc633968c672819cf3d643c3791f1f422e3994cc6534cc6f33019cf20329e3bc978ae25e3b9828ce769329eae643ce3c9788691f1dc47c6730b194f1919cf63643ca5643ca3c9780693f1f425e3b99e8ce759329eee643c9792f14c24e379888ca7908ce77e329ef7c9788e23e36943c6731b19cf55643c4f90f17422e3a922e32927e3e947c6732519cf8d643c3dc9781e21e32922e31941c6f30019cf1d643ccdc978ae21e3798a8ca70b19cf38329ef6643c15643cfdc9781690f1dc4cc6d39b8ce751329e12329e51643c0f92f1dc45c6731d19cf33643cddc8782690f15c4cc65349c633808c278f8c279f8ca70319cfad643c7dc8781e27e3e948c633868c670819cfdd643c3790f1f420e39944c6339c8c672019cf65643cc793f1b425e3b99d8c27878027111cfe2e5e027e5f003679676c1ed83ed0f98d606b66f121cf2236832d57e7651dadc2746dc1e1eb469d5cbd2787beca605efce501c707243cb793f1b425e3399e8ce732329e81643cc3c9782691f1f420e3b9818ce76e321eb91e64e11943c6d3918ce771329e3e643cb792f17420e3c927e3c923e31940c65349c6733119cf04329e6e643ccf90f15c47c6731719cf83643ca3c8784ac8781e25e3e94dc6733319cf02329efe643c15643cedc978c691f17421e3798a8ce71a329ee6643c7790f13c40c633828ca7888ce711329e9e643c3792f15c49c6d38f8ca79c8ca78a8ca71319cf13643c5791f1dc46c6d3868ce738329ef7c978ee27e32924e379888c672219cfa5643cddc9789e25e3b99e8ca72f19cf60329ed1643ca5643c8f91f19491f1dc42c6731f19cf30329ef1643c5dc9789e26e3b9828ce75a329e3bc9780691f13c4cc6534cc633998ca71719cf4d643cf790f10c25e3194bc6d3998ce749329eab2d3c0b1cf198e326c8fc0202df6abe3be8a2a604fc8edf597fdf11e3028351e6df0746e475ad591b83a78da1d9d1f4adea2fefeac83d70dc5ef8de39c3f66ad3009ab53578da1a9a1d4ddf4a0b79b62def0ce2f6c2efd4326c2f7cafda41fb5c9a3078d49463cc97417eb3637d1cd5b310dfbbfe26c6f52aadb6185a2d30b4ca87329b40bf2d0ef4cb01bfb26e99177f9ed93347312b1ee94b62fb1e403f1246b1e1b8181fc6cf539a3078d494ae7dfcd0b13e8eea996cc7b60676dd3f04dda50cc6ea5607f5cc01bfb26e99df6af15d10c4abc5b63a68b1cdc2b3ad81b5107f99326fca4266069d158fbc6b20ac0928d79f84516c5b80677bfc3ca50983474de9dac7ed8ef57154cf649bb023b0ebbe1d749732b87fed7050cf1cf02beb96f91db01d3261de9a85cc5ee7fa312b1e79475b5813506e0009a3d8b601cfced8798a0b13068f9ad2b5633b1debe3a69ea9766c5760d77d27e82e6570ffdae5a09e39e057d62df3bb603b7866cfec993db367f6cc9ed9337b66cfec993db367f6cc9ed9337b66cfec993db367e666563c03755e5813506e2009a3d87600cfeed87952cf1d90474de99e3bec76ac8f9b7aa69e3bec09ecbaef06dda50cc6ea1e07f5cc01bfb26e99df03dbc1337b66cfec993db367f6cc9ed9337b66cfec993db367f6cc9ed9337b66cfec993d3337b3e219a4f3c29a8072834818c5b60b78f6c6cf539a3078d494eeb9c35ec7fa38aa67f2b9c3bec0aefb5ed05dca60acee7350cf1cf02beb96f97db01df67966cf6c61563c83755e5813506e3009a3d8f600cffed87952cf4f91474de9dab1fd8ef57153cf543b7620b0ebbe1f74973218ab071cd43307fccaba65fe006c874c98b76621b3d7d9eb1cc5ec75f63a47317b9dbdce51cc5e67af7314b3d7d9eb1cc5ec75f63a47317b9dbdce51cc5e67af7314b3d7d9eb1cc5ec756e3a3a2b9e729d17d604942b276114db3ee0f928769e92c284c1a3a61c63be0cf21f39d6c74d3d53cf1d0e0676dd3f02dda50cee5f071dd43307fccaba65fe206c87c6cebc350b997d6c340cb38f0dcf1cc5ec63c3334731fbd8f0cc51cc3e363c7314b38f0dcf1cc5ec63c3334731fbd8f0cc51cc3e363c7314b38f0dcf1cc5ec63c3334731fbd8f0cc51cc3e363c7314b38f0dcf1cc5ec63c333473133c486e2a9d079614d40b90a1246b11d009e8fe3e7294d183c6aca31e6cb20ffb1637d1cd533d96fe75060d7fd63d05dcae0fe75c8413d73c0afac5be60fc176f0cc9ed9c6ac782a755e581350ae9284516c0781e793f8798a13068f9ad2b5639f38d6c7513d93edd8a7815df74f40772983b1faa9837ae6805f59b7cc7f0adb21db9815cf709d17d604941b4ec228b643c0e320ee923cf9068fcc7f42e05bcd57e97c9efe8fdbab0a1819b6577e0368d6c6e069636876347dabfa8fd5f9e3f47fdc5e638191617bb56900cdda1a3c6d0dcd8ea66fa5c5389d3f5effc7ed350e1819b6575bb73cc50983474de9ce373e059e6fc7cf93bc8efb34039e6f03cfb7e2e7297254cf42b5deef007b5ceb555a7d6668f5a9a1553e944186cf1ce897037e65dd322ffe3cb3678e62c6b650581350ee131246b17d0b785cb41baaee57e875c9fa5b84e90727d6f875717f0def2db4d4eb150ef1970b65ce6e57c3f613cd9607bfcb7653f53968d81cbdf35664bbcf2bf3e22f2fb05febbbba871a75efe120f01cb46876c0a2d97e478c070c4699df0f8cb6fbbc071cf144dd77167fd8661c24d50cdf03fe08785c9d1747c599eb7d2ed3f3cb8f2c3cdfc4c75388b181be5cc42ab66d75a9bb6ddf89b1ee45f80c0b7d39d80792c7a90e7a5db27e752cf8af139d6a5e8aed831ca73a1875ce8532ff7d4e0ddbff4d739c6a161c7e5fb840dba58cfcfe8db69beb28d0eb96f9eefa3fc689d8fc31b0f673c4ee86966c9ae1bef5b145c71e16ee1e04dc188f0db1ada3ee7de0b6ee61e8c8a6196eeb4f2c3af6b470f724e066dcaf7b1a3ab26976a4fdba9f85bb1f0137e37eddcfd0914db323edd7fd2ddcfd09b819f7ebfe868e6c9a1d69bf1e60e11e40c0cdb85f0f307464d3ec48fbf5400bf740026ec6fd7aa0a1239b6647daaf0759b807117033eed7830c1dd9343bd27e3dd8c23d98809b71bf1e1cd4d6914db323edd7e516ee72026ec6fdbadcd0914db323edd71516ee0a026ec6fdbac2d0914db323edd79516ee4a026ec6fdbad2d0914db323edd7c32ddcc309b819f7ebe1868e6c9a1d69bfaeb27057117033eed755868e6c9a1d69bf1e6be11e4bc0cdb85f8f357464d3ec48fbf5380bf738026ec6fd7a9ca1239b66b6fdda51ffb28cfb217fec549fd4f8b399bc87857d495cc494a3382874d4d724d90f79bfa1d5c78656f85dff03a09fab3e5951fdc6c49f67f6cc9ed9337b66cfec993db367f6cc9ed9337b66cf2c653cb367f6cc9ed9337b66cfcccb8cef79e2f31529d710ef00d785516cf84ccac57d7e55f72bf5ba64fd2dc274fbc9357ee37f6e519c7c0e20facbfb98571a75ce85323bceae61ebabd9f0f9223e17b56dcb03b1d7a16eef9ce37bfaf82ce8683eeffcc8a2d97e8b66fb1c319a6d86ccef0346d16f3ff0b8da1f0f183ca66fdbbbe16c9a45b5b3aee23e2ace6cbe0b62f35d3cd4cdb7108a0bd537da8e090e6f4fa40eb8efba88c34cbf0980fb8583e7ee45aedeff5775da67d4e9a051a77c287331d4739f837ad675df92e96ae071d51e05064f60d147a666643c4f92f17426e3194bc633948ce702329e7bc8784e23e3b9898ce718329e5e643c93c9788ac9781e26e31944c6d38e8ce74e329e13c978ae25e3c925e3b9828ce769329eae643ce3c9788691f15c44c673888ce772329efbc878ce20e3b9858c2741c65346c6f318194f2919cf68329ec1643ce792f1f425e339998ce77a329e96643ccf92f17427e39948c6732919cf43643c9790f11492f1dc4fc6731619cf6d643cc791f1b421e3b98a8ce709329e4e643c55643ce5643ce793f1f423e339958ce74a329e1bc9785a93f1f424e379848ca7888c670419cf03643ce790f1dc41c6730219cf35643ccdc9789e22e3e942c6338e8ca73d194f0519cf85643cfdc9784e27e3b9998ce758329ede643c8f92f19490f18c22e379908ca7808ce72e329e93c878ae23e36941c6e3fa3dc04c799e21e3e946c633818ca7928ce762329e01643c6792f1dc4ac69347c6934fc6d3818ca70f19cfe3643c1dc978c690f10c21e3398f8ce76e329e53c8786e20e36945c6d3838c671219cf70329e81643c6793f15c46c6733b19cff1643c6dc97872087812c1e1df62c2ef7f1d04db3e9dc76f0b36b3ac4f9e0b4b79751cbab5e0f07537b3ac7bbf850175da1bd4d4a54ce70bffb529a913fa2a8379f197071cfb4978da92f11c4fc6733b19cf65643c6793f10c24e3194ec633898ca707194f2b329e1bc8784e21e3b99b8ce73c329e21643c63c8783a92f13c4ec6d3878ca703194f3e194f1e19cfad643c6792f10c20e3b9988ca7928c6702194f37329e67c8783e22e36941c6731d19cf49643c7791f11490f13c48c6338a8ca7848ce751329ede643cc792f1dc4cc6733a194f7f329e0bc9782ac878da93f18c23e3e942c6f314194f73329e6bc8784e20e3b9838ce71c329e07c8784690f11491f13c42c6d3938ca73519cf8d643c5792f19c4ac6d38f8ce77c329e72329e2a329e4e643c4f90f15c45c6d3868ce738329edbc878ce22e3b99f8ca7908ce712329e87c8782e25e39948c6d39d8ce759329e96643cd793f19c4cc6d3978ce75c329ec1643ca3c9784ac9781e23e32923e34990f1dc42c6730619cf7d643c9793f11c22e3b9888c671819cf78329eae643c4f93f15c41c6934bc6732d19cf89643c7792f1b423e31944c6f330194f3119cf64329e5e643cc790f1dc44c6731a19cf3d643c1790f10c25e3194bc6d3998ce749329e66643c571b3cf8bb3ab796f7c3f6814d7e7f56375e6df4baa48c3c1351f796f6183655dfdd8eeabb27a899ca607e37d457d8f700cf1e473c7b0d1ed3771ee47b8066bb0c9b62dce9887197c128f33b8151f4db053cbb1cf1ec36784cdf7990ef099aed306c8a71bb23c61d06a3cc6f0746d16f07f0ec70c4b3d3e0317de741be1f68b6cdb029c6ad8e18b7198c32bf151845bf6dc0b3cd11cf7683c7f49d07f9fea0d987864d316e71c4f8a1c128f35b8051f4fb10783e74c4b3d5e0317de7417e0068f68161538c9b1d317e6030cafc666014fd3e009e0f1cf16c31784cdf79901f089a6d326c8a71a323c64d06a3cc6f0446d16f13f06c72c4b3d9e0317de7417e1068b6c1b029c6f58e1837188c32bf1e1845bf0dc0b3c111cf4683c7f49d07f9c1a0d93ac3a618d73a625c6730cafc5a6014fdd601cf3a473ceb0d1ed3771ee4cb41b335864d31ae76c4b8c66094f9d5c028faad019e358e78d61a3ca6ef3cc8578066ab0c9b625ce9887195c128f32b8151f45b053cab1cf1ac36784cdf7990af04cd561836c5b8dc11e30a8351e69703a3e8b702785638e25969f098bef3203f1c345b66d814e352478ccb0c46995f0a8ca2df32e059e68867b9c163face837c1568b6c4b029c6c58e1897188c32bf181845bf25c0b3c411cf5283c7f49d07f9b1a0d922c3a618173a625c6430cafc426014fd1601cf22473c8b0d1ed3771ee4c78166d5864d31beef88b1da6094f9f78151f4ab069e6a473c0b0d1ed3771ee4fb824d788bc0f69ece17836d81ce97806dbece9782ed5d9def08b67774be13d8ded6f9ce607b4be7bb80ed4d9def0ab63774be1bd85ed7f95e607b4de77b83ed559d2f03db2b3adf076cf374fe2ab0cdd5f9abc13647e7af01db6c9dbf166cb374fe3ab0cdd4f9ebc13643e76f00db749dbf116cd374fe26b04dd5f99bc1f6b2cedf02b69774fe56b0bda8f3b781ed059dbf1d6ccfebfc1d607b4ee7ef04db149dbf0b6c2375fe6eb0ddabf3f780ed539dbf0f6cdfd2f9fbc1f66d9d7f006cdfd1f907c1f699ce0f01db77757e28d8bea7f3c3c0f67d9d7f086c3fd0f91160fba1ce3f0cb61fe9fc28b0fd58e74783ed273a3f066c3fd5f9f160fb99ce4f00dbcf757e22d87ea1f393c0f64b9d7f046c9febfc64b0fd4ae71f05dbaf75fe31b0fd46e71f07db6f75fe09b07da1f34f82ed773aff14d8bed4f9a7c1f695ce3f03b6dfebfcb360fb83ce4bbba6dad93fea7c41106f3bfb75503315806ff1a7cafc49e75b196564d95c2853aa3fe8a39e71a86f994a3b2cedb2b2493bfc1ed8a41d5e00366987e7834ddae177c126edf03b609376f86db0493bfc16d8a41d7e136cd20ebf013669875f079bb4c3af81ad4ce75f059bb4c3af804ddae179609376782ed8a41d9e0336698767834ddae1596093767826d8a41d9e01366987a7834ddae169609376782ad8a41d7e196cd20ebf043669875f049bb4c32f804ddae1e7c126edf073609376780ad8647ff91a6cd2368f049bb4cdf7824ddae64fc1266df3b7c0266df3b7c1266df377c0266df3676093b6f9bb6093b6f97b6093b6f9fb6093b6f9076093b6f9876093b6f947601badf33f069bb4cd3f019bb4cd3f059bb4cd3f039bb4cd3f079bb4cdbf009bb4cdbf049bb4cd9f834ddae65f814ddae65f834ddae6df804ddae6df824ddae62fc0266df3efc0266df3976093b6f92bb03dabf3d256b7069b3c2b5653e1bf38e1383ccdc097309505f1b6fd389541fe19a8bb4cd3c878c692f1bc4ec6730119cf0a329ee5643ca791f17c40c6b3998ce718329e7d643c7bc9786693f1bc43c633888ca71d19cf89643cb9643c5790f15493f1bc4ac6731119cf21329ecbc978ce20e3d944c6b3918c671919cf52329e0419cf1e329edd643cef93f1cc24e3798b8c673019cfb9643c2793f1b424e3e94ec6732919cf3c329e4bc8789690f12c26e32924e3398b8c670319cf7a329e05643cc791f1b421e3d945c6b3938c673a19cfd7643c55643c6f90f19493f19c4fc6d38f8ce754329e2bc9785a93f1f424e39943c6b3888c672119cfbb643ce790f1ac23e3594bc6730219cf0e329eed643ccdc978a692f18c23e3798d8ca73d194f0519cf85643cfdc9784e27e339968c670a19cf2c329eb7c9787e4fc65340c6b3868c673519cf49643cdbc878b692f1b420e3f9888ce715329e4a329ef7c8780690f19c49c69347c6934fc6d3818c672419cf0c329e37c978ce23e35945c6b3928ce714329e0fc978b690f1b4d2ff59787a90f1cc25e3194ec6339f8c672019cfd9643c9791f11c4fc6d3968c27878027011c01d8e4f7e660fb4ae70f814dbed7f311d8bed4f96ab0fd4ee79f05db53165b330b9f307c053679d7fa69b0c9fd992fc126ef70fc0e6c725c14ff6abe6fc1e1fccd6019f1d3dcc28ffe7e67e1923c6e6f59a62c88777ba3afb2e0f0ef29e501c7d3243c6dc9788e27e3b98c8ce76c329e81643cf3c9788693f1cc25e3e941c6d38a8c670b19cf87643ca790f1ac24e35945c6731e19cf9b643c33c8784692f17420e3c927e3c923e339938c670019cf7b643c95643caf90f17c44c6d3828c672b19cf36329e93c8785693f1ac21e32920e3f93d19cfdb643cb3c878a690f11c4bc6733a194f7f329e0bc9782ac878da93f1bc46c6338e8c672a194f73329eed643c3bc8784e20e3594bc6b38e8ce71c329e77c9781692f12c22e39943c6d3938ca73519cf95643ca792f1f423e3399f8ca79c8ce70d329e2a329eafc978a693f1ec24e3d945c6d3868ce738329e05643cebc9783690f19c45c65348c6b3988c670919cf25643cf3c8782e25e3e94ec6d3928ce764329e73c9780693f1bc45c633938ce77d329edd643c7bc87812643c4bc9789691f16c24e3d944c6730619cfe5643c87c8782e22e379958ca79a8ce70a329e5c329e13c978da91f10c22e379878c673619cf5e329e7d643cc790f16c26e3f9808ce734329ee5643c2bc8782e20e3799d8c672c19cf34329e66169e438e78e45829eb96f94304bed57bb8722f7e9ffe9f80df71fce66a478c870c4699af0646b1ed059eee8e78761b3cbb2d5a1c2ddf4a0bf9f6c71efd3f01bfe3f70a5dc554778351e66d31b51b787a38e2d969f0ecb46871b47c2b2da4efa3f42149c0ef381e9eab98ea6130cabc2da6703cd79e8e78b61b3cdb2d5a1c2ddf4a0be96b287df813f03b8e7fe92aa67a1a8c326f8b291cafab9f239ead06cf568b1647cbb7d242de3d93779613f03b8e27e42aa6fa198c326f8b291c1fa2bf239e2d06cf168b1647cbb7d242be2521df444ac0eff87d7f5731d5df6094795b4ce1f7910738e2d96cf06cb66871b47c2b2de45b7572cd9e80dff1fbb6ae626a80c128f3b698da0c3c031df16c3478365ab4385abe951683745e9ec125e0f741c0e82aa6061a8c326f8ba98dc033c811cf7a8367bd458ba3e55b693158e7a54f66027e1f0c8cae626a90c128f3b6985a0f3c831df1ac3578d65ab4385abe9516e53a2fef0c26e0f77260741553830d4699b7c5148ebf5bee8867b5c1b3daa2c5d1f2adb49077efd7e8ff09f81dc7e31cec88b1dc6094f9c1c028361cefadc211cf4a8367a5458ba3e55b6921dfd2926f3026e0771c1fcb554c55188c326f8b291cefa4d211cf728367b9458ba3e55b69315ce757e8ff09f87d3830ba8aa94a8351e66d31b51c78963be2596af02c25f2adb49077e1a40f5b027eaf02c6158e18a3626a05308a6d29f02c75c4b3d8e0594ce45b6921cf72e49d8b04fc3e16189739628c8aa965c028b6c5c033d611cf428367a1458ba3e55b6921df8e59a4ff27e0771caf7db123c6b106a3cc2f0646b12d049e858e78a2eee13584efa8fb510de13beade4a43f88eba4fd010bea3eeb13784efa8ebb786f01d752dd210bea3ee333484efa873fa86f01df57cbb217c473dab6d08df51cf1d1bfbfeed8f254deb587234dbb5a67a2cf1ed39677b3e2e7edfc589a0f6358d9a728cf932c8e3f5cb22075a38aa67215e137e13e37a6dd7f00b0dadf2a10c5ea3babafe1b67f0c8bcf8cb46668c8b9cf87c1726c087bca3ac6c72afe53db0c93d8e0560937b20f3c126f7d0de059bdccf7a076c72bfeb6db00dd7f99160937b97d81f49ee6d6e075bb9ce633f98c13abf156cf29c08fb5fc8b3be2d6093e7b5f8dc5f9eb96f069bf49bc0e7cdd2f76523d8a4ff123ee7943e68ebc126fd08f1f95ab5ceaf059b8c2981cf75bed4f9d560fb4ae7f179828cd5b9126c4feafc14b07da1f35f83ed099d5f08b6dfea3cdef3795ce7c782ed373aff16d87eadf36f82ed319d7f036c8feafc3eb0fd4ae7f7826db2ce63ffd0cf757e37d81ed179ec97f84b9ddf09b65fe8fceb609ba4f3af816da2cebf0ab69febfc2b609ba0f3f3c0f6339d9f0bb6f13a3f076c3fd5f9d960fb89cecf02db189d9f09b61febfc0cb08dd6f9e9601ba5f3d3c0f6239d9f0ab68775fef760fba1ce8f035b339d5f0c36f97e32ded395771697824dc629c17bf5f2ad922ab0c9f87bcbc1d65ae7f1b98cbc97341c6cf26dfb4ab0c9fbff1560933192cac126e3380d069b7c0b6c10d8e47b6503c12663960e009b8cabda1f6cf2ede27e6093f7297b824dc608e90136f98e4a77b0c9d8773826b07cefb21a6cf24e108e132cdfddff126cf26ef9576093f19b704c60f9c6d59360937149bf00db393aff04d8e47dcddf82ad40e71f07dbb93aff1bb09da7f3bf069b7cbff231b0c93b358f824dbea3ff2bb0c9bbd993c176b1ce7f0eb64b74fe11b0c977887e0936192bf617606baff393c026efcc4f04db153aff73b0c9586713c026df57fd19d8e41b5fe3c156a4f33f055bb1ceff046c253a3f066ca53aff63b075d4f9d160eba4f3a3c0d659e77f04b62e3aff30d8baeabcb4336a7f56fbf9413d5f16c4775ea6fc7d1cd49ed25d1b0803f2c479ae9d0f3ce8eb40ec752f4e9ed7cb7edf4caf5762e800f8de17bbefd435c57ebdae167abdfb0cdfb950e653dd88a8e5f6c0ef655007590eafb165ddb2cc95b0ec5e63dd6d747df73baaef3e8349b8f7039394f9ecec9ab24fe8c6b2352c13235bf2fa58622d000d712a83bc30b8d1aab810cf7bebc2b31f78e2df4f52d7eb2e6202f7adb8afd7cd7b4c66ace543997da0df5e07fae1be2eeb9679f1e7993db367f6cc9ed9337b66cfec993db367f6cc9ed9337b66cfec993db367f6cc9e999f59f1c8f3047cae2ce50e92308aed00f0ec8f9fa7109fc3cafad5739d07e0b9ce81d8fdd67ebed752afb7d0a8732e9459754e0ddb109dcf83df65bb456dcb7db1d721fdb6147f79509ffdc0e3605b26790e183ca6ef3c8b3e4ab3bd16cdf6386234db0c99df038cfb747e2ff0b8da1ff7193ca66f6c33f6936a16d5cebae897902ece6c7d100a62f35d3cd4d5735dd5674af5e5308f5f070d4db10f84d8f039781e2cf389fe9f007d3e017d8e661b60f64bc076ea6360dc173b6371ad67c0d2f65f69688a7d205ed4da4a1f88f8db81e24297c708d947cdbe15585729331d8e7333751efb011d8475bd6bf95da61c63be0cf2d8a6ee8abfcec9ed2bfd5765fbeeb2f8de01ac31f9aef52e478e4ee247ecb9907fe79c9ab2524ef410ad851dc7ad427673b98f8de5f2a1cc6e4bfdcb8278ebbfcbe0d96530abd8990371f62e9cebb96a937647687425682465f09cd7419f226b1b291ce24f9591eddfca2883e7a7526631b451aa2ed2ce4b3db11f131e035c9d2f1c34ea27f378be603ba731eba8e2e3f6936b785d5f0b340bec5ab3f4f5db0ced45dc7dfd36430cd9ce4b65fd85b07ee16a15441f5ba4cc56e338eae27a12b7a5a9e77e6092323ba11dfacf7a5cd71dad6bf4a8ebbadd0e78f05a43a674c7773cc6b8685f1cd5b3d076ecda6bd4291fca5c0cf574701e93f69dd45de0dbc536472de41c6a9fa1452e94f9aed17644e928ebc0fb006eeb526c3d1f2cb4d445cafcd868a7763a6072b9ddf03c4badf780a5ae52e617d0fe7d0ee7f3fbf4efd896fec5f2bb4ce9da03fca6fcb6f8eb9cdcbef27ea36cdf6d16df1f026b4cbe6b7d9342cef7c58fd87321ff67387e4b39d143b41676b58fc8fb9dc86e2eb7cf582e1fca6cb7d4bf2c88b7fedb0c9e6d06b38a9ddf409cfd05cef75db59bdb23342a048da40c3e2b30efb7e0bd133cee37d47581cc7f048c62db05fafea7d3fbe529b68f0c36f37eb9ed7cb0d0e0c7f3c1ff0ded6cc252d6fd7380d4b90dd64bea1118750d8cba3a3a7f2dcd31f42c033f1dc0be4fe74567f90dcf71a54c4ebbd47f77f7af6adfc7166ea9073eafdb6370ef3574c57b512d815bc5bd796d81e7e98eaf694bf15ccc3c1fc2eb30299307ecb6f3b84396ba98c7e966c1e1d782df1865f13a3bdd7266fe236319bc6770c0c2646bfb627b2fa7a8b0d0e4b7b57b070d669baeb21f60ccc9bacc7d05cf87a4cc99b0dd1296b2aa4dfaaf136bf491ed88f7da6df7595c1d2fa2eeb3883fc5687b67d2c5338ca6f86e5aebd8d6dbb5dcf69c8dbd3f436b231f8fefe20a3c56a4d3628f85c7d53dcd282df6587cc7a745a7a1b676cea6c56e0b8fab6bcc282d765b7cc7a845a5edde824d8b5d161e57d71a515aecb2f88e4f8bceb5ee6ba4d362a78527fe7b1ae9b5c067629930ef26606e6de4e3f15d5a6e7b7667d3628785c7d5b3bb282d76587cc7a7455127db35bb4d8bed169eed0dacc5768beff8b4e8d2d5764fc5a6c5360b8f83fb6b69b5d866f11d635c0cc3fb6be9b4d86ae1d9dac05a6cb5f88ef1fcb053ba7b86a8c587161e57f7fea2b4f8d0e23b462d8628df5beaa0c5160bcf9606d6628bc5777c5a947754be3fa883161f58783e68602d3eb0f88e4f8b215d94efcd75d062b3856773036bb1d9e23bc66ba8645c6caa83169b2c3c9b1a588b4d16dff16951913cd7da58072d365a783636b0161b2dbee3d3a230794cdd50072d3658783634b0161b2cbe638c8be4f5e4fa3a68b1dec2b3be81b5586ff11de371241917ebeaa0c53a0bcfba06d6629dc5777c5a5426ef3fadad83166b2d3c6b1b588bb516df31de7349c6c59a3a68b1c6c2b3a681b55863f11d9f1625c963eaea3a68b1dac2b3ba81b5586df11d9f16c392cfc456d5418b55169e550dacc52a8bef18cf3b93edc5ca3a68b1d2c2b3b281b55869f11de37967f2fec58a3a68b1c2c2b3a281b55861f11d63db993cef5c5e072d965b785c8d1119a5856d7cca18cf3b935a2cab8316cb2c3caec6368cd26299c5778ce79dc9e3c8d23a68b1d4c2e36a2cca282d6ce360c61817c9b673491db45862e159d2c05a2cb1f88ef1be56b2ed5c5c072d165b785c8dcd11a5c5628bef18af4792f7f816d5418b45169e450dacc5228bef189f1525cfc117d6418b85169e850dacc542f0bd3f76dfa9fedce243fa625d6168910b65be6df4c58ad251d681efd0625daa63af4baa5fd9fb1175a986ba48991f187df9de77c0e4a8aec998794faf4bfaa67f6ca9ab94f969bb9ab23fd7f9046c9343b0ae3f5a7e9729c7982f83bce8a7ea3c3ffe3a276355c60192ed3bdfe2fb1d608dc97711faced149fc883d17f25fb7ab292be5440fd15ad8d53eb240e791dd5c6ea1b15c3e945960a97f59106ffde71b3cf30de6e47b0f106712476edaae14d382088dae008da40cf6d93be488e763834738c45f4e70f8bba8524696c57751ff6ef4db957e9052cfa83e92ef39aa5f541f49f117f52eaa5947151f3f80be9f322e888c19a26c32064809aca7b3615375ede2a8aee24bd62df35d8051c624e9dcf08cc57565ec64302a9e6e0e34c37156644a77bce8063c5d1df038aa67f238d4dda85317a34ef95006df6deceea09e39e057d62df3ddc1b78b6d8e5ac831f952438b5c28935790fa2fe78f513aca3a54fc76b6d4c5958e9d0c9e4e16dfbd1ceb28eb9636b15703f8ee61f8ee68f856fb36c6989ad2eddb3d80b9a70366b5dedef1afb710cf19259ec54f47a8531fd020ae3ae1bae41cb38fa16d2ee4cf2fa8292be5a4ac1c3b855ded47b22d91dd5cae9bb15c3e94e965a97f59106ffd7b1b3cbd0d6675de705a410d8783fd211903bd0c0e99ef08daf58ed0ae17682765f0d8dbc991763d0d1e99ef043c727ed51d6c729e22fc09f8bda401b8cd76afbb855b6c381e61270b63c7f8198bd31d173a02a3d87a024f0f479a99dbfa52431f3c27686594916573a14c9782d47f7957cb2cabf6bb73736aead55cdb637b6f4db7e92d1de885e38106a04f6068289330b40e6ac60c8d93e7d8a0664cd00913abc60f7968d85dc3528f3d052dd7c0c4ff39966a34031be69b5b6c41507be8d35cb0c9d0a72dc0d6cc9005875c95f23274a20bb9500f5977aec1d91a58e2f48dc3c6ca942e745a018f8b5056a12343c7ead0b977fc8889c3303e5a189cf5891df55bf334e5a2d6257190eba0eec824eb9679f1a7f4c9d7f9b143868eec33fea149a3878d99380161cd9d0bf3398608e67fdb321824b833c97a5a18e21c1bbf38a53846b1c917803f9984a17550338e718c3cc94095b186870e1935ea8e49e5a3460cbd6ed298a11347548d41455b1bca45a92dbfb7049bada9c3b26ac2dd17976d65b1d9261cd5b935d8a4053f066cc2732cd89a435eca9b5bc6c93e7231ac5fc25afda6c469a12bde2aa80901392ca9f645ed43ea33aaea74400d2dad8692569b53ddb1534343abafc8a9a19fd550cf6a68673594b31aba590dd5ac86663e3b480dbdacee5e1604a9a194cf0b5243255f10a48642be08f8be0dcc9704a9d30f359471fb203554b1ba7da85e1f579f5a53efb7abd3587579ac4efdd4a58e3a0d53a75fea345bdd4250b793d4a98d3a6d54a744ea34469d96f7d65af709d35561ba3a4cd784e9da305d17a6ebc37443986e0cd34d61ba394cb784e9d630dd16a6dbc3744798ee0cd35d61ea1ba6bb83d470daf784e9de2035dcf67d416a28eefb83d430dd0f04a921bc1f0c52c37b0f0952437f0f0d52c3820f0b5243863f14a486131f11a4862a1e19a486361e1da4864756c3948f0d5243a2aba196d5b0cc6a086735b4b31a1a5a0d23ad869c564351aba1ac9f085243643f15a6a783d410dacf86694a989e0bd3f3617a214c2f86e9a530bd1ca4866557c3b5ab61dc6704a961df6705a961e2d5f0f16a587935dcbc1a865e0d4faf86ad57c3d9bf11a637c3f45698de0e528f05d4e310f59840dd8257b788d5639aea2075fb7a51907accac1ebbab6e08aa5b86eaa6b22248756352ddba543737d5ed4f758354dd42553759d56d5875a356ddca55377bf5da817a0d43bd96a25ed351af2da9d7b8d46b6dea353ff5aaa67af551bdcaab5e6dde17a46e4d1f08528f2bd5ed6a755b5adda257b7d03f0dd3b782544c7e274c9f85e9bb61fa5e98be1fa61f04a921a3d5f0d26a786a3594b51ae25a0d87ad86ce56436fab21b93f0f52437daba1c27f13a4861bff224cbf0b52439e7f15a486bbff4398be0ed31fc3f4a730fd394c7f09d35fc3f46f61faf730fd2d4c7f0fd37f84e91f41cdb0e6d89014e8d6e75c3d3f64e2c461a3c74e2c985855307ad2a88923c68e7aac60f28889c30baa1e1936be7254d5645cf8b77a611993bdcff8f1431e2b1831a662d8a3055593261654551694574d1a5351eb40fafff442671dee71484545b4b3bce6ff02e9f1cdebe7b49d5e4e46bbbf317dddce6b5e0f412ea9cf42b7d4b34277eb23985cf2f54d9d0f164c185535b1a0b0604cf8373cf0564d1e56d1a1007f9b108a3c6162c1848943c64f2ca81c5f35baa0a803aeb7f0d87a5462deb16e604a4eaf9f389f9c9dfa5faf107be19c7a28b0e89cfa916e3ae75f20fdb09e4e3fab4f0d7f549f85feab9e84817ef0699165c2a4f289e3870c9d18bd708b7f65e144bb7a54f38c76f5abe6b7eae3ecfbf559e86ff5244c14d4c359e782ba3b0bfe07c2beb575b8020600", + "bytecode": "0x1f8b08000000000000ffed9d07741d45b6ae5bb61ce0481893b3450e06a3e49c64724ec6608c31b62c0b1b073962323643700ee460839c73c638478c6166983b393181811926dd3b7367bdf5e6be77df7a8ff5bacea9bdf4ab5c7daca3e992ff2355af5552f53ed5bdbffa7b7775aaeeca0952d33fc294a3f3cdc3745170e424bf97e9ff85ffda5414e3ba0a5d72e6640967b32ce16c9e259cb959c2d9224b385b660967ab2ce16c9d259cc7c5c8a9d89a05b5a7b8798f77a06bdc8c892cd3342f0b34cdcf324d4fc8024ddb04d9d1469d98259c6db384f3a42ce13c394b384fc912ce53b384f3b42ce13c3d4b38cfc812ce33b384f3ac2ce13c3b4b38cfc912ce73b384f3bc2ce16c97259c0559c2797e96705e90259c176609e74559c2797196705e1223677be0bc54ffbf4cffbf5cffbf42ff97b257eaff57e9ff1d741d73f5fcd58a2b4cea214db1f15b49984ac3d4314c9d8cdf3a87a94b98ba86a99bfead40ffd63d4c3dc2d4334cbdc2d45b6bd0274cd784e9da305d17a6ebc37443986e0cd34d61ba394cb784e9d630dd16a6dbc3744798ee0cd35d61ba3b4cf784a96f98ee0d53bf30dd17a6fbc3d43f4c0f846980c1f260980686e9a1300d0ad3c3611a1ca621612a0fd3d03055846958982ac3f4489886876944981e0dd3c8308d0ad3e8308d09535598c686695c98c68769429826866952981e0bd3e4303d1ea627c2f4a4a1d953617a3a4ccf84e95983f3b9304d09d3d4303d1fa66f85e98530bd18a697c2f47298a685697a9866846966986685697698e684696e98e685697e985e09d3ab617a2d4caf87e98d30bd19a6b7c2f47698de09d3bb615a10a685617a4fb3c88ef07e98aac3b4284c8bc3b4244c4bc3b42c4ccbc3b4224c2bc3b42a4cabc3b4264c6bc3b42e4cebc3b4214c1bc3b4294c9bc3b4254c1f84696b983e0cd3b6306d0fd38e30ed0cd3ae30ed0ed39e30ed0dd3be30ed0fd381301d0cd347613a14a68fc374384c9f84e9d3307d3b4cdf09d377c3f45998be17a67f3334ff7e987e10a61f86e947daf663fdff27baacdcbffb69987ea6f33fd7ff7fa1ffff52ffffdc58e65761fab561fb4d987e6bd8be08d3ef74fe4bfdff2bfdfff7faff1ff4ffaff5ff3feaff7fd2ffffacffff45ffffabfeffeffaff7fe8ff7fd3ffffaeffffa7feff8f303d5490cab70e6aa6b220a636aab432f9ec47c4bf34a83d292d9aebdfe47f81b6e7ea79f92fdab5d0f32d0c7b4b3ddfd2584f6b3ddfdab0b7d5f36d0dfbc97afe64c37eaa9e3fd5b09faee74f37ec17e9f98bc09e08e0deb0b62b5b736dca019bc46b33b0b5d0b6e6606b29ab035b2b6d6b0136d9be2dc1769cb6b502dbf1dad61a6c096d3b4eb40c539eb6950571c54ae110b5defcb8d7ab9f979d103fef50b5de368e784f8c9f77985a6f5b07bc2a3e4ed2eb3a11e2e6646d6b0bb653b4ed24b09daa6d2783ed346d3b056ca76bdba9603b43db4e03db99da763ad8ced2b633c076b6b69d09b673b4ed2cb09dab6d6783ed3c6d3b076cedb4ed5cb01568db79603b5fdbda81ed026d2b00db85da763ed82ed2b60bc076b1b65d08b64bb4ed22b049fb7b31d8e47cf1126d536dc77139b08cb64bbb955c46da6cb05d2eed35d8ae90b61a6ceda59d06db95e05b6c57415b23b60eda26ed96faad9bce970571ed27c5956abddde35e6fb866b5de9ef1af37f9ccb15750a36b19f8e90e5af5d6f918fb3515a1ef1c9dc48fd873217f0b949572a2871c7b845d1d637ae87cef34cb753396cb87323d2cf52f0be2ad7f4f83a7a7c1dc02f26e62b6a4c4c76c9da78c63b63f9435634fce831a63ccde0e1c0e62b6b38fd93a4f19c76c259435634fce851b63cc3e081c0e62b6dc4dcc1617fa984ddd370b027becc9f550638cd911c0117fcc76f4315bf729e3987d1eca9ab127d7c48d3166270347fc31dbb9dc9f1bd479ca3866e7415933f6e4fe4c638cd91781c341cc56fa76b6ce53c631fb1e9435634fee1536c6987d1538e28fd9ae8e62b6c4c76c907a061a04f6d893fbd68d3166170147fc313bd4df9fadfb9471ccee84b266ecc93394c618b31b745e3d67f8b17ece700ed87ea26de7026ffcb15dd1d1516c17fbd84ef50d09027b8ccaf3bcc618dbfb745ec5f1cfa13f82d87ea16de783ed97da7601d83ed7b60ba15e0ef68172bf0fd479ca781ff835943563599e2d37c67de087c0e120662b7cccd679ca3866ff0a65cdd8937e0e8d3166bf000e07315be963b6ce53c631fbbfa1ac197b97e97c638c59e96baace17bed4e70b5780ed2b6d6b0fb6df6bdb9560fb83b65d05b6afb5ad03d8fea86d5783ed4fda5608b63f6b5b11d8fea26dc560fbabb69580eddfb5ad146cffa16d1dc1f6376deb04b6bf6b5b67b0fda7b67501db3fb4adabb6a9e75dd2f74ace5b5b036b5910dfb64d802e32e518f365902f76cb53980f3ce8ab347e5f25aaee2541ddeb5e0a3c1d1dd43d013eeac2d311783ac5cf93ec8bda39fef526b77189a169027c9540bdba38a8570ef89275cbbcf8cb071beee75d2c8c5de3672cce015fb26e99ef0a8c62c37647deff91fd47b5cde7e7d4f03ad89792c767f457061ce22f17cafcb35d4dd98b355b1efc8e6d7027c3e6282e937121be64dd322ffef2a03e9d1a9eb1b8ae8c1d0d46576d440ef892759bbef3205fe4569fb43c9d497c3b38efb6b669a279f706f0ddd5f05d6af8c6b653a674c7b6aec01cfbf58f3eb6f5887fbd8578ae2cd729e207cf1ff07a22ae3aa16fb94e113f62cf85fc4d393565a59ce821edb0b0ab7d58b625b29bcb753196cb8732dd2df52f0be2ad7f0f83a787c1ac8e373de158e8607f48c640778343e64b41bb1e11da7507eda4cc65a09d8373cfa476dd0c1e99ef083cd27e637b56d4c03c4504bef11c16afe5e4773c0f70b5bd8a0c4699b76dafaec0d8d1c2e8e09cb038ddf1b01418c5d60d784a1c6916b55d4b487cbbb8aecc011f726e6e5edbe442993b9bd794adc871ca568ce7ce32d5f59a37feed545c88fb475d781cef43458ee2b110efdf7c13c41b6b66bb64b63751f7785cb5e525068fcc8b3fcfec993db367f6cc9ed9337b66cfec993db367f6cc9ed9337b66cfec993db367f6ccfccc8a479e2760bf2d29d78984d1ecffe6ea3e7ff25b7c7a5df80ce89f4efb831517e2b33fe907718551e75c287372b31ab6ff86fe60665fa2a86de9a26f6cba6d29feb03f58433c432c35784cdf79167df0b9346ae6aa0f94d966c83cf64f13fd8a80c7d5fe586cf098beb1cd2821d52caa9d75d5a72f2ace6cfd090b62f35d3cd4d5735df5dd33f5ed50f3f8d5c9d034f94d52c3a6daa47b9ad7d4dbc573de4c9f3be37143f2713ec7c57e19e82bfe76b6b856ff846641ed6305c6baabbe5ab25f49df88ee86ef5c28737eb39a6d837deaca82238f0dd8c74bd62dcb5c01cbf630d6ddc65d7dd3f643e90edc926f69d4ad33704b994be0d8fd539d77740c2ccef41d093c26c77f7c49f51729c980078f772ece591c1d470b311ee3ee2f62f683b49d2f4b19ec43eaa0ff6eda63b1f8f3cc9ed9337b66cfec993db367f6cc9ed9337b66cfec993db367f6cc9ed9337b66cfcccfac78cc67e8f8ecb79484b181fad8249f67c8f7d9f0b9d8b666357e5d3f0394674eed8d3ae33bcab9f08ef22ecd867d1ff0bb52b66de9ead95ad4b6147f6c7d1ff22cfa28cd7a583473f05dc7b4dfecc06f248a7e3d80c7d5fe18f5ed0e5b9b5144aa59543beba2ef42ba38b3f5532888cd77aabf888be7bad25fc43c7e99df35c27e1262c3e7e051df0b2b366cc7ba0db0f56b933c7e73c1c5183718cf665f41f187fd24bed0da4a3f89f8db81e24297c708d947a54f4889a5ae52e60fcd6acafe51e7b1af5029aceb9f96df654ad72701db5407df8f4d6e5f59976c5fdbb76bfb006b4cbe8b705d393af53134c885fcff6c565356ca4959d15ad8d53e22df95427673b98ec672f950a697a5fe6541bcf537bf25dcdb6056b1f31788b37fc2b99eab36a95784465780465206cf795df5ab35db48b3cf34f6896c6594c1f35329f3ffa08d8aea936eeb53e9ea7c21aa3f279e2fd8ce69cc3a9a7dc79b7a7fc07c7d1de2a23fa0acbb4d50bb4f5e60acbf3dac5fb85a05d1c71629d316d67f2cbf7b65bbf6135eec6f28654e836bbf9b743e936bbf63751d6fbbf6c3e5a2ea8eed42dcc7468c4764c158963205463cf688e0ee6a59f6c28865452bf3db87785d8ae708f17f3732d5def436ea22fb147edf5fca5c6eec37f19f33a5ce3f5d7d2353d6256d50b1a5ae52a603ec6b853a9f80ed84ef14f5b6fc2e53baf34fd14fd5f99af8eb9cdcbed7ea75c9f6bdc6e2fb3a608dc97711fa96f34ff123f65cc8f782e38994133d446b6157fb889cc321bbb95c7763b97c28d3c752ffb220defa5f63f05c6330abd8298138eb0def5ab86aabfb4468d41e34923278efdaf65d63dbbd8e863a4f35bf979e1f1cf9ed5e3c4eba3967b3bf2b67debfb59d9fb437f8f1fce47668671396b2e67d69592ecefee9f83e109e17e2fb40aeae91f283da7ae61b1c2e7db7317cb76940df6d0ddf6d1bd0b7d7dc6bcea439d3983ff81cb21930ba38d6e171b52e8cb6e35f736074f5ce6649068cf8cd6b3cde09a38bef84d7774c213cd769018c2ede37cef47e752760c46f0c08a38b77b433fd4e35beb72dcbb5024617e31ae1184a7561b48d75d41afe3b18d7a8a8bee380e05847c701a38bb1411241edf14c8ec6d80d1865b9e381d1c573a44450fbbedad118f179a52c9770cc98eed8eeb8ef4f71a6f7201aa25f41d4b906fa7670ffbf18fb26d4458b9e6e79d29efba06f07f7bf925ae0589647d3029fcfb9185b3311d47e1676341e7c8628cb9d048c658e187b67c058068cb2dcc9c0d8c7116359068c7d8051eca700a383fb9049c63e1930e2fd3a59ee5460bcd611e33519305e0b8cb2dc69c0e8e29e6202fcd685f13a6094e54e07c6eb1d315e9701e3f5c028cb9d018c373862bc3e03c61b8051963b13186f74c47843068c3702a32c771630dee488f1c60c186f024659ee6c60bcd911e34d1930de0c8cb2dc39c0788b23c69b3360bc051865b97381f156478cb764c0782b30ca72e701e36d8e186fcd80f1366094e5da01e3ed8e186fcb80f1766094e50a80f10e478cb767c0780730ca72e703e39d8e18efc880f14e6094e52e00c6bb1c31de9901e35dc028cb5d088c773b62bc2b03c6bb815196bb0818ef71c47877068cf700a32c773130f675c4784f068c7d815196bb0418ef75c4d83703c67b81b1af85b19f23c67b3360ec078cb2dc95c0785ffc8cc96be97e1930de073cf7c7cf93d4ecbe0c78ee77cb93fc86e27d165f0fc4ef2bb92dfa0775affb03c033207e9ee4b67820031e61c887e550b307e3674c6a362003c607816760fc3c49cd1ecc80672068f6a045b387e2674c6a363003c687806750fc3c49cd1eca80671068f69045b387e3674c6a362803c687816770fc3c49cd1ece80677050a3d9c316cd86c4cf98d46c70068c4380a73c7e9ea4664332e02907cd8658341b1a3f6352b3f20c1887024f45fc3c49cd8666c053019a0db568362c7ec6a4661519300e039ecaf879929a0dcb80a712341b66d1ec91f819939a5566c0f808f00c8f9f27a9d92319f00c07cd1eb16836227ec6a466c333601c013c8fc6cf93d46c44063c8f8266232c9a8d74c4f868068c232d3c717f13fd518bafd18eea3e2aa87bdd85211f96c37e12631c318ece80710c30ca72d84fa2ca11e3980c18ab8051964b38664cd74fa20a7c8f8ddf77b25daa0aeaaecf58b73c69fb49a0ef718eb4181bd45d8b716e79d2f69340dfe31d69312ea8bb16e3816782032d12e0a32e3cc2900fcb613f89898e182764c03811186539ec2731c911e3c40c182701a32c87fd241e73c4382903c6c7805196c37e12931d313e9601e3646094e5b09fc4e38e182767c0f83830ca72d84fe209478c8f67c0f80430ca72d84fe249478c4f64c0f82430ca72d84fe229478c4f66c0f81430ca72d84fe269478c4f65c0f83430ca72d84fe219478c4f67c0f80c30ca72d84fe259478ccf64c0f82c30ca72d84fe239478ccf66c0f81c30ca72d84f628a23c6e732609c028cb21cf69398ea88714a068c538151961be99831ddf5cbd446ee3bea5aa5b1fb8eba2e69ecbe7d9cfb386f0abe7d9cfb386f0abe7d9cfb386f0abe7d9cfb386f0abe7d9cfb386f0abe7d9cfb386f0abe7d9cfb3867f2fdbc03df09f021538e315f067961c887e5467ac646cd883c05f1f11462ddd1d7b708eafe2d0b4f8ea3baa3af1708ea2e0cd9c6f87c16308ecc0246af63aa0f627d1815cf8b8e785ec880e745e079c911cf8b19f0bc043c2fc7cf938ca99732e011867c586e6416303e9f058c5e47af2313a3d7b1e9e8e8193da367f48cc782311bda70cf9815f1585c5f46c5332d7e9ea4662f67c0330d3493e5ee77cb585c5f46c5333d7e9ea466d332e0990e9a4db368e680b1b8be8c8a6746fc3c49cda667c03303349b6ed1cc0163717d1915cfccf879929acdc88067266836c3a29903c6e2fa322a9e59f1f324359b9901cf2cd06ca64533078cc5f565543cb3e3e7496a362b039ed9a0d92c8b660e188bebcba878e6c4cf93d46c76063c7340b3d916cd1c3016d79751f1cc8d9f27a9d99c0c78e68266732c9a39602cae2fa3e299173f4f52b3b919f0cc03cde65a3463651c99058ccf6701a3631d8bebcba878e63be2999701cf7ce079c511cffc0c785e019e57e3e749c6d42b19f008433e2c37320b189fcf0246afa3d79189d1ebd87474f48c9ed13366c6f8ad2c60f4dbda33b2323ab8be4afb0ecd2b8ddc77d43b348ddd77d43b348dddb78f731fe74dc1b78f731fe74dc1b78f731fe74dc1b78f731fe74dc1b78f731fe74dc1b78f731fe74dc1b78f731fe74dc1b78f731fe74dc1b78f731fe74dc1b78f731fe74dc1b78f731fe74dc1b78f731fe74dc1b78f731fe74dc1b78f731fe74dc1b78f731fe74dc1b78f731fe74dc1b78f731fe74dc1b78f731fe74dc1b78f731fe74cbe5f8bdf7771a6efb0be063c2edea97554cf42b5ded7f5babe89513fa5d51b8656af185ae54399d741bf371ce897037e65dd322ffe3265be9480d991efe213c2751c07f5171fcf1b7a28ff6f3aaa7b545bff6623f71dd5d63776df516d7d63f7ede3dcc77953f0ede3dcc77953f0ede3dcc7398b6fccb7086acedbe5fb4a6a1d6fc1ef39505ebe5b960b65fab54afd6f13f87dc8856fbf0ff9634553f0ede3dcc77953f0ede3dcc77953f0ede39c2fce311eae6d009ec0e009d2f03c4dc6d3998c672c19cf50329efbc8786e21e3e945c633998ca7988c671619cfa3643c2f91f10c22e3b99b8ce77a329eabc8789e25e3e94ac6339e8c671819cf03643cb791f19491f13c41c6534ac6339b8c673419cfcb643c83c978fa92f1bc40c6732319cf14329eee643c73c9782e27e39948c6731919cf23643c85643c0f92f19c40c6d3868ce70e329e6bc8789e22e3e944c633878ca78a8c671a194f39194f3f329eabc9786e26e3e949c6339f8ce731329e22329e11643c0f91f1dc45c6d39c8ce73a329e67c878ba90f18c23e3694fc65341c6339d8ca73f19cfad643cbdc9781e27e32921e31945c6f33019cf3d643c0df13d8e4c78a692f1dc40c6f31c194f37329e09643c33c8782e25e3a924e31940c69347c6934fc6d3818ce776329e3e643c4f92f17424e31943c633848ce75e329e17c9786e22e3e941c6338f8c671219cf4c329ee1643c03c978ae20e339918ca72d19cf9d643c39043c89e0c86f2427e0f7d7c0d6cc58567d56aa5b41cdef6f6b7b3358e61d9d6f6e59f7db60936f55bd635916757a1bea52a6f385ffda94d4097d95c1bcf8cb038e774878ee24e3694bc6732219cf15643c03c9788693f1cc24e39944c6338f8ca70719cf4d643c2f92f1dc4bc633848c670c194f47329e27c978fa90f1dc4ec6d3818c279f8c278f8c6700194f2519cfa5643c33c8782690f17423e3798e8ce706329ea9643caf91f1dc43c6f33019cf28329e12329ec7c9787a93f1dc4ac6d39f8c673a194f05194f7b329e71643c5dc8789e21e3b98e8ca73919cf5d643c0f91f18c20e32922e3798c8c673e194f4f329e9bc978ae26e3e947c6534ec6338d8ca78a8c670e194f27329ea7c878ae21e3b9838ca70d19cf09643c0f92f11492f13c42c6731919cf44329ecbc978e692f17427e39942c6732319cf0b643c7dc9780693f1bc4cc6339a8c6736194f2919cf13643c65643cb791f13c40c6338c8c673c194f57329e67c978ae22e3b99e8ce76e329e41643c2f91f13c4ac6338b8ca7988c6732194f2f329e5bc878ee23e3194ac633968ca73319cfd3643cd75a785e73c423efbbcbba65fe3512df0eb643a15aefbb8eeab440afaba55eaff08bbf5c2853747ceabf7a3e84cb0a97f97d02ecfbbd00347acb515dcc313165fead46eebb8de1bb4d13f1ddd6f0ddb689f8f671eee39cc9f782f87d17e3b76d64ca31e6cb208fc71717df047254cf5ac7f66f62d44f69b5d0d0ea2d43ab7c28f32ee8b7d0817eb6f30599177f99325f4ac08c715110c41b17efc55fa762d597e638d0f53d435facd7fb8e348d3a86bcdfc87d471d431abbefa8634863f7ede3dcc77953f0ede3dcc77953f0ede3dcc73993ef6a9d8ff1bab1107db4086aae07aac1ef629dcf89d1af5ad722f09b031ce22f17cabc02f7a2fd3eeff7f9b87cfb639b8ff3a6e09b39cecdbc3c43bc0cd85c3de38d8ac58678be7c2c7d47c56263f71d158b8dddb78f731fe74cbe97c4ef3bf90cf1b5a0f694ee19e212e059e4400b47f54c5e3b2d35eaf49a51a77c28530df55ceaa09e39e057d62df34b613b641bb3e299aaf338be8b949b4ac228b6456e7992fbd7d4a0f6946eff5a0a3c0ef6832247f54cee5fcb8c3a4db5e82e65aaa19ecb1cd4d3b6efc8fc32d80ed9c6ac78e4dd5d614d40b9174818c5b6c42d4f72ff7a21a83da5dbbf96018f8bf6c7513d93fbd772a34e2f58749732d550cfe50eea69db77647e396c876c63563c329689b026a0dc8b248c625bea96a73401759629ddfeb51c785cb43f8eea99dcbf5618757ad1a2bb94a9867aae70504fdbbe23f32b603b7866cf6c63563cf2cea4b026a0dc4b248c625be694a7b430017596295d3bb602785cb4f38e744fb6632b8d3abd64d15dca54433d573aa8a76ddf91f995b01d32615e9085ccd559c8ec75f63a4731576721b3d7d9eb1cc55c9d85cc5e67af7314737516327b9dbdce51ccd559c8ec75f63a4731576721b3d7d9eb1cc55c9d85cc5e67af7314737516327b9dbdce51ccd559c8ec75f63a4731576721b3d7d9eb1cc55c9d85cc5e67af7314737516327b9dbdce51ccd559c8ec75f63a4731576721b3d7d9eb1cc55c9d85cc5e67af73147375163233e8ac785ed679614d40b9974918c5b6dc2d4ff2fd9d9783da538e315f06f995c0b3c2813e8eea99ecf7becaa8d3cb16dda54c35d47395837adaf61d995f05db2113e60559c85c9d85cc0c3a2b9e693a2fac0928378d84516c2bdcf224dbb16941ed295d3bb60a785cb4f38eea996cc7561b759a66d15dca54433d573ba8a76ddf91f9d5b01d3cb367b6312b9ee93a2fac0928379d84516c2b9df21427df439c1ed49ed2b563ab81c7453bef48f7643bb6c6a8d3748bee52a61aeab9c6413d6dfb8eccaf81ed9009f3822c64aece4266afb3d7398ab93a0b99bdce5ee728e6ea2c64f63a7b9da398abb390d9ebec758e62aece4266afb3d7398ab93a0b99bdce5ee728e6ea2c64f63a7b9da398abb390994167c53343e7853501e56690308a6d95539e92e473871941ed29dd738735c0e3e2b98c23dd93cf1dd61a759a61d15dca54433dd73aa8a76ddf91f9b5b01d1a3bf3822c64aef6cc0dc2ec63c3334731fbd8f0cc51cc3e363c7314b38f0dcf1cc5ec63c3334731fbd8f0cc51cc3e363c7314b38f0dcf1cc5ec63c3334731fbd8f0cc51cc3e363c7314b38f0dcf1cc5ec63c3334731fbd8f0cc51cc0cb1a17866eabcb026a0dc4c1246b1ad76cb93fceec1cca0f694aedfce5ae059e3401f47f54cf6db5967d469a6457729530df55ce7a09eb67d47e6d7c176f0cc9ed9c6ac7866e9bcb026a0dc2c1246b1ad71cb936cc76605b5a774edd83ae071d1ce3baa67b21d5b6fd46996457729530df55cefa09eb67d47e6d7c376f0cc9ed9c6ac7866ebbcb026a0dc6c1246b1ad75cb936cc76607b5a774edd87ae071d1ce3baa67b21ddb60d469b6457729530df5dce0a09eb67d47e637c076f0cc9ed9c6ac78e6e8bcb026a0dc1c1246b1ad73cb539c803acb94ae1ddb003c2eda7947f54cb6631b8d3acdb1e82e65aaa19e1b1dd4d3b6efc8fc46d80ed9c6ac78e6eabcb026a0dc5c1246b1ad77cb93dcbfe606b5a774fbd746e071d1fe38aa6772ffda64d469ae457729530df5dce4a09eb67d47e637c176c83666c5334fe7853501e5e691308a6d835b9ee4fe352fa83da5dbbf36018f8bf6c7513d93fbd766a34ef32cba4b996aa8e76607f5b4ed3b32bf19b643b6312b9ef93a2fac0928379f84516c1b1df324a0ce32a5dbbf36038f8bf6c7513d93fbd716a34ef32dba4b99f7a19e5b1cd4d3b6efc8fc16e091e95ae071159781c11358f491e969329ece643c63c9788692f1dc47c6730b194f2f329ec9643cc5643c8f92f10c22e3b99b8ce77a329eabc8789e25e3e94ac6339e8c671819cf03643cb791f19491f13c41c6534ac6339a8c6730194f5f329e1bc978a690f17427e3b99c8c672219cf23643c85643c0f92f1bc4fc67302194f1b329e3bc878ae21e3798a8ca713194f15194f39194f3f329eabc9786e26e3e949c6f318194f1119cf08329e87c878ee22e3694ec6731d19cf33643c5dc878c691f1b427e3a920e3e94fc6b3908ce756329ede643c8f93f19490f18c22e379988ce71e329e1bc8789e23e3e946c633818ce752329e4a329e01643c79643cf9643c1dc8786e27e3e943c6f324194f47329e31643c43c878ee25e3b9898ca70719cf24329ee1643c03c978ae20e339918ca72d19cf9d643c39043c89e0c877f112f0fb42b0c93b63f3c1f681ce6f025b338b0f7916b1056cb93a2feb6815a6eb0b8e5c37eae4ea3d39f45506f3e22f0f383e20e1b9938ca72d19cf89643c5790f10c24e3194ec633898ca70719cf4d643cf792f1c8f5200bcf18329e8e643c4f92f1f421e3b99d8ca703194f3e194f1e19cf00329e4a329e4bc9782690f17423e3798e8ce706329e7bc8781e26e31945c65342c6f338194f6f329e5bc9781692f1f427e3a920e3694fc6338e8ca70b19cf33643cd791f13427e3b98b8ce721329e11643c45643c8f91f1f424e3b9998ce76a329e7e643ce5643c55643c9dc8789e22e3b9868ce70e329e36643c2790f1bc4fc6f320194f2119cf23643c13c9782e27e3e94ec633858ce746329ebe643c83c9784693f19492f13c41c65346c6731b19cf03643cc3c878c693f17425e379968ce72a329eebc978ee26e31944c6f328194f3119cf64329e5e643cb790f1dc47c633948c672c194f67329ea7c978aeb5f02c74c4638e9b20f30b097cabf9eea08b9a12f03b7e67fd7d478c0b0d46997f1f1891d7b5666d0c9e368666c7d2b7aabfbcab23f7c0717be17be70cdbab4d0368d6d6e0696b68762c7d2b2de4d9b6bc3388db0bbf53cbb0bdf0bd6a07ed7369c2e051538e315f06f92d8ef57154cf427ceffa9b18d7abb4da6a68b5d0d02a1fca6c06fdb63ad02f07fccaba655efc7966cf1cc5ac78a42f89ed7b00fd4818c586e3627c183f4f69c2e05153baf6f143c7fa38aa67b21ddb16d875ff1074973218abdb1cd43307fccaba657e9bc5774110af16dbeba0c5760bcff606d642fc65cabc390b991974563cf2ae81b026a05c7f1246b16d059e1df1f394260c1e35a56b1f7738d6c7513d936dc2cec0aefb0ed05dcae0feb5d3413d73c0afac5be677c276c884795b16327b9debc7ac78e41d6d614d40b901248c62db0e3cbb62e7292e4c183c6a4ad78eed72ac8f9b7aa6dab1dd815df75da0bb94c1fd6bb7837ae6805f59b7ccef86ede0993db367f6cc9ed9337b66cfec993db367f6cc9ed9337b66cfec993db367f6cc9e999b59f10cd479614d40b981248c62db093c7b62e7493d77401e35a57beeb0c7b13e6eea997aeeb037b0ebbe0774973218ab7b1dd43307fccaba657e2f6c07cfec993db367f6cc9ed9337b66cfec993db367f6cc9ed9337b66cfec993db367f6ccdccc8a6790ce0b6b02ca0d226114db6ee0d9173f4f69c2e05153bae70efb1cebe3a89ec9e70efb03bbeefb40772983b1badf413d73c0afac5be6f7c376d8ef993db38559f10cd679614d40b9c1248c62db0b3c0762e7493d3f451e35a56bc70e38d6c74d3d53edd8c1c0aefb01d05dca60ac1e7450cf1cf02beb96f983b01d3261de9685cc5e67af7314b3d7d9eb1cc5ec75f63a47317b9dbdce51cc5e67af7314b3d7d9eb1cc5ec75f63a47317b9dbdce51cc5e67af7314b3d7b9e9e8ac78ca755e581350ae9c84516cfb81e7a3d8794a0a13068f9a728cf932c87fe4581f37f54c3d773814d875ff08749732b87f1d7250cf1cf02beb96f943b01d1a3bf3b62c64f6b1d130cc3e363c7314b38f0dcf1cc5ec63c3334731fbd8f0cc51cc3e363c7314b38f0dcf1cc5ec63c3334731fbd8f0cc51cc3e363c7314b38f0dcf1cc5ec63c3334731fbd8f0cc51cc3e363c7314b38f0dcf1cc5cc101b8aa742e7853501e52a4818c57610783e8e9fa73461f0a829c7982f83fcc78ef57154cf64bf9dc3815df78f41772983fbd76107f5cc01bfb26e993f0cdbc1337b661bb3e2a9d479614d40b94a1246b11d029e4fe2e7294e183c6a4ad78e7de2581f47f54cb6639f0676dd3f01dda50cc6eaa70eea99037e65dd32ff296c876c63563cc3755e5813506e3809a3d80e038f83b84bf2e41b3c32ff09816f355fa5f379fa3f6eaf2a6064d85ef90da0591b83a78da1d9b1f4adea3f56e74fd0ff717b8d054686edd5a601346b6bf0b435343b96be9516e374fe44fd1fb7d7386064d85e6dddf214270c1e35a53bdff81478be133f4ff23aeed30c78be033cdf8e9fa7c8513d0bd57abf0bec71ad5769f599a1d5a78656f95006193e73a05f0ef89575cbbcf8f3cc9e398a19db42614d40b94f4818c5f66de071d16ea8ba5fa5d725eb6f11a61f9c5ce3d7c5fd35bcb7d052af5738c45f2e9439b75d0ddb4f345b1efc2edb4dd5e7906173f4ce5b91ed3eafcc8bbfbcc07eadefea1e6ad4bd8743c073c8a2d9418b66071c311e341865fe0030daeef31e74c41375df59fc619b718854337c0ff823e071755e1c1567aef7b94ccf2f3fb2f07c131f4f21c606fa7211abd8b6d5a5eeb67d27c6ba17e1332cf4e5601f481ea73ae875c9fad5b1e0bf4e76aa7929b60f729cea60d43917cafcf779356cff27cd71aa5970e47de1026d9732f2fb37da6eaea340af5be6bbebff182762f3c7c0dacf11bb1b5ab26986fbd6c7161d7b58b87b1070633c36c4b68ebaf781dbba87a1239b66b8ad3fb1e8d8d3c2dd93809b71bfee69e8c8a6d9d1f6eb7e16ee7e04dc8cfb753f434736cd8eb65ff7b770f727e066dcaffb1b3ab26976b4fd7a80857b000137e37e3dc0d0914db3a3edd7032ddc0309b819f7eb81868e6c9a1d6dbf1e64e11e44c0cdb85f0f327464d3ec68fbf5600bf760026ec6fd7a70505b4736cd8eb65f975bb8cb09b819f7eb72434736cd8eb65f5758b82b08b819f7eb0a434736cd8eb65f575ab82b09b819f7eb4a434736cd8eb65f0fb7700f27e066dcaf871b3ab26976b4fdbacac25d45c0cdb85f57193ab26976b4fd7aac857b2c0137e37e3dd6d0914db3a3edd7e32cdce308b819f7eb71868e6c9ad9f66b47fdcb32ee87fcb1537d52e3cf66f21e16f6257111538ee2a0d0515f93643fe40386561f1b5ae177fd0f827eaefa6445f51b137f9ed9337b66cfec993db367f6cc9ed9337b66cfec993db394f1cc9ed9337b66cfec993d332f33bee789cf57a45c43bc035c1746b1e1332917f7f955ddafd6eb92f5b708d39da7d6f88dffb94571f23980e82fef635e6dd43917caec3cb786adaf66c3e78bf85cd4b62d0fc65e87babd738eefe9e3b3a063f9bcf3238b66072c9aed77c468b61932bf1f1845bf03c0e36a7f3c68f098be6def86b36916d5ceba8afba838b3f92e88cd77f15037df42282e54df683b2e38b23d913ae0beeb220e33fd2600ee170e9ebb17b97aff5fd569bf51a743469df2a1cca550cffd0eea59d77d4ba66b81c7557b14183c81451f999a91f13c4dc6d3998c672c19cf50329e8bc878ee23e339838ce716329ee3c8787a91f14c26e32926e379948c6710194f3b329ebbc9784e26e3b99e8c27978ce72a329e67c978ba92f18c27e31946c6730919cf61329e2bc9781e20e3398b8ce736329e04194f1919cf13643ca5643ca3c9780693f19c4fc6d3978ce754329e1bc9785a92f14c21e3e94ec633918ce772329e47c8782e23e32924e379908ce71c329e3bc8784e20e36943c6730d19cf53643c9dc878aac878cac9782e24e3e947c6733a19cfd5643c3793f1b426e3e949c6f318194f1119cf08329e87c878ce23e3b98b8ce724329eebc8789a93f13c43c6d3858c671c194f7b329e0a329e8bc978fa93f19c49c6732b19cff1643cbdc9781e27e32921e31945c6f330194f0119cf3d643ca790f1dc40c6d3828cc7f57b8099f23c47c6d38d8c6702194f2519cfa5643c03c878ce26e3b99d8c278f8c279f8ca703194f1f329e27c9783a92f18c21e31942c6730119cfbd643ca791f1dc44c6d38a8ca70719cf24329ee1643c03c978ce25e3b9828ce74e329e13c978da92f1e410f0248223bfc584dfff3a04b6fd3a8fdf166c66599f3c1796f2ea38747bc191eb6e6659f7010b03eab42fa8a94b99ce17fe6b535227f45506f3e22f0f380e90f0b425e339918ce74e329e2bc878ce25e31948c6339c8c6712194f0f329e56643c3791f19c46c6732f19cf05643c43c878c690f17424e379928ca70f194f07329e7c329e3c329edbc978ce26e31940c67329194f2519cf04329e6e643ccf91f17c44c6d3828ce706329e53c878ee21e32920e379988c6714194f0919cfe3643cbdc9788e27e3b9958ce74c329efe643c1793f15490f1b427e31947c6d3858ce719329ee6643cd791f19c44c6731719cf79643c0f91f18c20e32922e3798c8ca727194f6b329e9bc978ae26e3399d8ca71f19cf85643ce5643c55643c9dc8789e22e3b9868ca70d19cf09643c7790f19c43c6f320194f2119cf65643c8f90f15c4ec633918ca73b19cf14329e96643c3792f19c4ac6d3978ce77c329ec1643ca3c9784ac9789e20e32923e34990f1dc46c6731619cf03643c5792f11c26e3b9848c671819cf78329eae643ccf92f15c45c6934bc6733d19cfc9643c7793f1b423e31944c6f328194f3119cf64329e5e643cc791f1dc42c6730619cf7d643c1791f10c25e3194bc6d3998ce769329e66643cd71a3cf8bb7a174bde0fdbafffe7c2ef5374e3d546af4bcac83311756f69af6153f5dde3a8be7b839aa90ce6f7407d857d2ff0ec75c4b3cfe0317de741be0768b6dbb029c65d8e18771b8c32bf0b1845bfddc0b3db11cf1e83c7f49d07f99ea0d94ec3a618773862dc6930cafc0e6014fd7602cf4e473cbb0c1ed3771ee4fb8166db0d9b62dce68871bbc128f3db8051f4db0e3cdb1df1ec30784cdf7990ef0f9a7d68d814e356478c1f1a8c32bf151845bf0f81e743473cdb0c1ed3771ee40780661f1836c5b8c511e30706a3cc6f0146d1ef03e0f9c011cf5683c7f49d07f981a0d966c3a618373962dc6c30cafc266014fd3603cf66473c5b0c1ed3771ee40781661b0d9b62dce08871a3c128f31b8051f4db083c1b1df16c32784cdf79901f0c9aad376c8a719d23c6f506a3ccaf0346d16f3df0ac77c4b3c1e0317de741be1c345b6bd814e31a478c6b0d46995f038ca2df5ae059eb88679dc163face837c0568b6dab029c6558e18571b8c32bf0a1845bfd5c0b3da11cf1a83c7f49d07f94ad06ca561538c2b1c31ae3418657e05308a7e2b8167a5239e55068fe93b0ff2c341b3e5864d312e73c4b8dc6094f965c028fa2d079ee58e7856183ca6ef3cc85781664b0d9b625ce28871a9c128f34b8051f45b0a3c4b1df12c33784cdf79901f0b9a2d366c8a719123c6c506a3cc2f0246d16f31f02c76c4b3c4e0317de7417e1c68566dd814e3fb8e18ab0d46997f1f1845bf6ae0a976c4b3c8e0317de741be2fd884b7086cefe97c31d816ea7c09d816e87c29d8ded5f98e607b47e73b81ed6d9def0cb6b774be0bd8ded4f9ae607b43e7bb81ed759def05b6d774be37d85ed5f932b0bda2f37dc0365fe7af01db3c9dbf166c7375fe3ab0cdd1f9ebc1365be76f00db2c9dbf116c3375fe26b0cdd0f99bc1365de76f01db349dbf156c2febfc6d607b49e76f07db8b3a7f07d85ed0f93bc1f62d9dbf0b6ccfebfcdd609baaf3f7806da4cedf0bb6fb75fe3eb07daaf30f80eddb3aff20d8bea3f30f81edbb3aff30d83ed3f92160fb9ece0f05dbbfe9fc30b07d5fe71f01db0f747e04d87ea8f38f82ed473a3f0a6c3fd6f9d160fb89ce8f01db4f757e3cd87ea6f313c0f6739d9f08b65fe8fc24b0fd52e71f03dbe73a3f196cbfd2f9c7c1f66b9d7f026cbfd1f927c1f65b9d7f0a6c5fe8fcd360fb9dce3f03b62f75fe59b07da5f3cf81edf73a3f056c7fd07969d7543bfb479d2f08e26d67bf0e6aa602f02dfe54993fe97c2ba38c2c9b0b654af5077dd4330ef52d536987a55d56366987df039bb4c30bc126edf002b0493bfc2ed8a41d7e076cd20ebf0d366987df029bb4c36f824ddae137c026edf0eb609376f835b095e9fcab609376f815b0493b3c1f6cd20ecf039bb4c373c126edf01cb0493b3c1b6cd20ecf029bb4c333c126edf00cb0493b3c1d6cd20e4f039bb4c32f834ddae197c026edf08b609376f805b0493bfc2db0493bfc3cd8a41d9e0a36d95fbe069bb4cd23c1266df3fd6093b6f953b049dbfc6db049dbfc1db049dbfc5db049dbfc19d8a46dfe1ed8a46dfe37b049dbfc7db049dbfc03b049dbfc43b049dbfc23b08dd6f91f834ddae69f804ddae69f824ddae69f814ddae69f834ddae65f804ddae65f824ddae6cfc1266df3afc0266df3afc1266df36fc0266df36fc1266df3176093b6f9776093b6f94bb049dbfc15d8a6e8bcb4d5adc126cf8ad554f82f4e380e4f33f0254c6541bc6d3f4e65907f0eea2ed374329eb1643caf93f15c44c6b3928c670519cf19643c1f90f16c21e3398e8c673f19cf3e329e39643cef90f10c22e36947c67332194f2e19cf55643cd5643caf92f15c42c673988ce74a329eb3c8783693f16c22e3594ec6b38c8c2741c6b3978c670f19cffb643cb3c878de22e3194cc6733e19cfa9643c2dc978ba93f15c4ec6339f8ce732329ea5643c4bc8780ac978ce21e3d948c6b3818c672119cf09643c6dc8787693f1ec22e39941c6f335194f1519cf1b643ce5643c1792f1f423e3399d8ce76a329ed6643c3dc978e692f12c26e35944c6f32e19cf79643cebc978d691f19c44c6b3938c6707194f73329e69643ce3c8785e23e3694fc65341c67331194f7f329e33c9788e27e3994ac6339b8ce76d329edf93f11490f1ac25e35943c6730a19cf76329e6d643c2dc8783e22e379858ca7928ce73d329e01643c6793f1e491f1e493f17420e31949c633938ce74d329e0bc8785693f1ac22e3398d8ce743329ead643cadf47f169e1e643cf3c8788693f12c20e31948c6732e19cf15643c2792f1b425e3c921e04900470036f9bd39d8bed2f9c36093eff57c04b62f75be1a6cbfd3f929607bc6626b66e11386afc026ef5a3f0b36b93ff325d8e41d8edf814d8e8be25fcdf72d3892bf192c237e9a5bf8d1dfef2c5c92c7ed2dcb9405f16e6ff455161cf93da53ce0789684a72d19cf89643c5790f19c4bc633908c670119cf70329e79643c3dc8785a91f16c25e3f9908ce734329e55643cabc9782e20e379938c672619cf48329e0e643cf9643c79643c6793f10c20e3798f8ca7928ce715329e8fc8785a90f16c23e3d94ec6730a19cf1a329eb5643c05643cbf27e3799b8c673619cf54329ee3c978ce24e3e94fc67331194f05194f7b329ed7c878c691f14c23e3694ec6b3838c672719cf49643cebc878d693f19c47c6f32e19cf22329ec5643c73c9787a92f1b426e3b99a8ce774329e7e643c1792f19493f1bc41c65345c6f33519cf0c329e5d643cbbc978da90f19c40c6b3908c670319cf46329e73c8780ac9789690f12c25e3b98c8c673e19cfe5643cddc9785a92f19c4ac6733e19cf60329eb7c8786691f1bc4fc6b3878c672f194f828c671919cf72329e4d643c9bc978ce22e3b9928ce73019cf25643caf92f15493f15c45c6934bc67332194f3b329e41643cef90f1cc21e3d947c6b39f8ce738329e2d643c1f90f19c41c6b3828c672519cf45643caf93f18c25e3994ec6d3ccc273d8118f1c2b65dd327f98c0b77a0f57eec5efd7ff13f03b8edf5ced88f1b0c128f3d5c028b67dc0d3dd11cf1e83678f458b63e55b6921dffed8abff27e077fc5ea1ab98ea6e30cabc2da6f6004f0f473cbb0c9e5d162d8e956fa585f47d943e2409f81dc7c37315533d0c4699b7c5148ee7dad311cf0e836787458b63e55b69217d0da50f7f027ec7f12f5dc5544f8351e66d3185e375f573c4b3cde0d966d1e258f9565ac8bb67f2ce72027ec7f1845cc5543f8351e66d3185e343f477c4b3d5e0d96ad1e258f9565ac8b724e49b4809f81dbfefef2aa6fa1b8c326f8b29fc3ef200473c5b0c9e2d162d8e956fa5857cab4eaed913f03b7edfd6554c0d301865de16535b8067a0239e4d06cf268b16c7cab7d26290cecb33b804fc3e08185dc5d4408351e66d31b509780639e2d960f06cb06871ac7c2b2d06ebbcf4c94cc0ef8381d1554c0d321865de16531b8067b0239e7506cf3a8b16c7cab7d2a25ce7e59dc104fc5e0e8cae626ab0c128f3b698c2f177cb1df1ac3178d658b43856be9516f2eefd5afd3f01bfe3789c831d31961b8c323f1818c586e3bd5538e25965f0acb26871ac7c2b2de45b5af20dc604fc8ee363b98aa90a8351e66d3185e39d543ae25961f0acb06871ac7c2b2d86ebfc4afd3f01bf0f07465731556930cabc2da65600cf0a473ccb0c9e6544be9516f22e9cf4614bc0ef55c0b8d21163544cad0446b12d039e658e7896183c4b887c2b2de4598ebc739180dfc702e372478c5131b51c18c5b60478c63ae25964f02cb26871ac7c2b2de4db318bf5ff04fc8ee3b52f71c438d66094f925c028b645c0b3c8114fd43dbc86f01d753faa217c47dd5b6908df51f7091ac277d43df686f01d75fdd610bea3ae451ac277d47d8686f01d754edf10bea39e6f3784efa867b50de13beab96363dfbffdb1a4691d4b8e65bbd6548f25be3de76ccfc7c5efbb3811d4bea651538e315f0679bc7e59ec400b47f52cc46bc26f625cafed1a7e91a1553e94c16b5457d77fe30c1e99177fd9c88c7191139fefc204f8907794954deeb5bc0736b9c7b1106c720f6401d8e41edabb6093fb59ef804dee77bd0db6e13a3f126c72ef12fb23c9bdcd1d602bd779ec073358e7b7814d9e1361ff0b79d6b7156cf2bc169ffbcb33f72d60937e13f8bc59fabe6c029bf45fc2e79cd2076d03d8a41f213e5fabd6f97560933125f0b9ce973abf066c5fe93c3e4f90b13a5781ed699d9f0ab62f74fe6bb03da5f38bc0f65b9dc77b3e4feafc58b0fd46e7df02dbaf75fe4db03da1f36f80ed719ddf0fb65fe9fc3eb04dd679ec1ffab9ceef01db633a8ffd127fa9f3bbc0f60b9d7f1d6c9374fe35b04dd4f957c1f6739d7f056c13747e3ed87ea6f3f3c0365ee7e782eda73a3f076c3fd1f9d9601ba3f3b3c0f6639d9f09b6d13a3f036ca3747e3ad87ea4f3d3c0f6a8ceff1e6c3fd4f971606ba6f34bc026df4fc67bbaf2cee232b0c9382578af5ebe55520536197f6f05d85aeb3c3e9791f79286834dbe6d5f093679ffbf026c32465239d8641ca7c160936f810d029b7caf6c20d864ccd20160937155fb834dbe5ddc0f6cf23e654fb0c918213dc026df51e90e3619fb0ec70496ef5d56834dde09c27182e5bbfb5f824dde2dff0a6c327e138e092cdfb87a1a6c322ee917603b4fe79f029bbcaff95bb015e8fc93603b5fe77f03b60b74fed76093ef573e013679a7e671b0c977f47f053679377b32d82ed5f9cfc17699ce3f0636f90ed12fc12663c5fe026ced757e12d8e49df98960bb4ae77f0e3619eb6c02d8e4fbaa3f039b7ce36b3cd88a74fea7602bd6f99f80ad44e7c780ad54e77f0cb68e3a3f1a6c9d747e14d83aebfc8fc0d645e71f055b579d977646edcf6a3f3fa4e7cb82f8cecb94bf8f83da53ba6b0361409e38cfb5f381077d1d8cbdeec5c9f37ad9ef9be9f54a0c1d04dffb63f79dbaa638a0d7d542af77bfe13b17ca7caa1b11b5dc5ef8bd0cea20cbe135b6ac5b96b91a96dd67acbb8daeef0147f5dd6f3009f7016092329f9d5b53f629dd58b6866562644b5e1f4bac05a0214e65901706375a1517e2796f5d780e004ffcfb49ea7add454ce0be15f7f5ba798fc98cb57c28b31ff4dbe7403fdcd765dd322ffe3cb367f6cc9ed9337b66cfec993db367f6cc9ed9337b66cfec993db367f6cc9ed933f3332b1e799e80cf95a5dc211246b11d049e03f1f314e2735859bf7aaef3103cd73918bbdfdacff75aeaf5161a75ce8532abcfab611ba2f379f0bb6cb7a86db93ff63aa4df96e22f0fea7300781c6ccb24cf4183c7f49d67d14769b6cfa2d95e478c669b21f37b8171bfceef031e57fbe37e83c7f48d6dc60152cda2da5917fd12d2c599ad0f42416cbe8b87ba7aaeabfa4ca9be1ce6f1eb90a129f681101b3e07cf83653ed1ff13a0cf27a0cfb16c03cc7e09d84e7d0c8cfb63672caef50c58dafeab0d4db10fc48b5a5be903117f3b505ce8f21821fba8d9b702eb2a6566c0716e96ce633fa043b0ae772dbfcb9463cc97411edbd4ddf1d739b97da5ffaa6cdfdd16df3b813526dfb5dee5c8d149fc883d17f2ef9c575356ca891ea2b5b0e3b855c86e2ef7b1b15c3e94d963a97f59106ffd771b3cbb0d66153b7321cede85733d576dd29e088dae068da40c9ef33ae853646d238543fca932b2fd5b1965f0fc54ca2c81364ad545da79a927f663c26380abf3854346fd641ecf176ce734661d557cdc796a0dafeb6b8166815d6b96be7e5ba0bd88bbafdf168821db79a9acbf10d62f5cad82e8638b94d9661c475d5c4fe2b634f53c004c526617b443ffa31ed775c7ea1a3deaba6e8f031ebcd69029ddf11d8f312eda1747f52cb41dbbf61975ca873297423d1d9cc7a47d277537f876b1cd510b3987da6f68910b65be67b41d513aca3af03e80dbba145bcf070b2d7591323f36daa95d0e985c6e373ccf52eb3d68a9ab94f905b47f9fc3f9fc7efd3bb6a57fb1fc2e53baf600bf29bf3dfe3a27b7afbcdf28db77bbc5f787c01a93ef5adfa490f37df123f65cc8ff198edf524ef410ad855ded23f27e27b29bcbed3796cb87323b2cf52f0be2adff768367bbc1ac62e73710677f81f37d57ede68e088d0a41232983cf0accfb2d78ef048ffb0d755d20f31f01a3d87683beffc3e9fdf214db47069b79bfdc763e5868f0e3f9e0ff8276366129ebfe3940eadc06eb25f5088cba06465d1d9dbf96e6187a96819f0e60dfaff3a2b3fc86e7b85226a75deabfbbfb57b5ef630bb7d4039fd7ed35b8f719bae2bda896c0ade2debcb6c0f374c7d7b4a5782e669e0fe1759894c90376db79dc614b5dcce374b3e0c86bc16f8cb2789d9d6e3933ff91b10cde33386861b2b57db1bd9753545868f2dbdabd4306b34d57d90f30e6645de6be82e74352e66cd86e094b59d526fdd7c935fac876c47bedb6fb2cae8e1751f759c49f62b4bd33e9e21946537c37ad756cebed5a6e7bcec6de9fa1b5918fc77771051e2bd269b1d7c2e3ea9e6694167b2dbee3d3a2d3505b3b67d3628f85c7d5356694167b2cbe63d4a2d2766fc1a6c56e0b8fab6b8d282d765b7cc7a745e75af735d269b1cbc213ff3d8df45ae033b14c98f71030b736f2f1f82e2db73dbbb369b1d3c2e3ead95d94163b2dbee3d3a2a893ed9adda6c50e0bcf8e06d66287c5777c5a74e96abba762d362bb85c7c1fdb5b45a6cb7f88e312e86e1fdb5745a6cb3f06c6b602db6597cc7787ed829dd3d43d4e2430b8fab7b7f515a7c68f11da3164394efad75d062ab85676b036bb1d5e23b3e2dca3b2adf1fd4418b0f2c3c1f34b0161f587cc7a7c5902ecaf7963a68b1c5c2b3a581b5d862f11de33554322e36d7418bcd169ecd0dacc5668beff8b4a8489e6b6daa83169b2c3c9b1a588b4d16dff16951983ca66eac83161b2d3c1b1b588b8d16df31c645f27a72431db4d860e1d9d0c05a6cb0f88ef138928c8bf575d062bd85677d036bb1dee23b3e2d2a93f79fd6d5418b75169e750dacc53a8bef18efb924e3626d1db4586be159dbc05aacb5f88e4f8b92e431754d1db45863e159d3c05aacb1f88e4f8b61c96762abeba0c56a0bcfea06d662b5c5778ce79dc9f662551db45865e159d5c05aacb2f88ef1bc3379ff62651db45869e159d9c05aacb4f88eb1ed4c9e77aea883162b2c3caec6888cd2c2363e658ce79d492d96d7418be5161e57631b4669b1dce23bc6f3cee47164591db45866e1713516659416b67130638c8b64dbb9b40e5a2cb5f02c6d602d965a7cc7785f2bd9762ea983164b2c3caec6e688d26289c5778cd723c97b7c8beba0c5620bcfe206d662b1c5778ccf8a92e7e08beaa0c5220bcfa206d66211f83e10bbef547f6ef1217db1ae32b4c88532df31fa6245e928ebc07768b12ed5b1d725d5afecfd88ba54435da4cc0f8cbe7cef3b607254d764ccbca7d7257dd33fb6d455cafcb45d4dd99feb7c02b6c96158d71f2dbfcb9463cc97415ef453755e107f9d93b12ae300c9f65d60f1fd0eb0c6e4bb087de7e8247ec49e0bf9afdbd5949572a287682dec6a1f59a8f3c86e2eb7c8582e1fca2cb4d4bf2c88b7fe0b0c9e050673f2bd0788338923376d578a696184465781465206fbec1d76c4f3b1c1231ce22f2738f25d542923cbe2bba87f37faed4a3f48a967541fc9f71cd52faa8fa4f88b7a17d5aca38a8f1f40df4f191744c60c51361903a404d6d3d9b0a9ba76715457f125eb96f92ec0286392746e78c6e2ba32763218154f37079ae1382b32a53b5e74039eae0e781cd533791cea6ed4a98b51a77c2883ef36767750cf1cf02beb96f9eee0dbc536472de4987cb9a1452e94c92b48fd97f3c7281d651d2a7e3b5beae24ac74e064f278bef5e8e7594754b9bd8ab017cf7307c77347cab7d1b634c4de9f6ed1ec0dcd301b35a6feff8d75b88e78c12cfe2a723d4a90f6810579d705d728ed9c7d03617f21716d494957252568e9dc2aef623d996c86e2ed7cd582e1fcaf4b2d4bf2c88b7febd0d9ede06b33a6f38a3a086c3c1fe908c815e0687cc7704ed7a4768d70bb4933278ecede448bb9e068fcc77021e39bfea0e36394f11fe04fc5ed200dc66bbd7ddc22d361c8fb09385b163fc8cc5e98e0b1d81516c3d81a78723cdcc6d7db9a10f9e13b432cac8b2b950a64b41eabfbcab659655fbddf93935f56aaeedb1bdb7a6dbf4960ef4c2f14003d02730349449185a07356386c6c9737c503326e8848955e3873c32ec9e61a9c79e82966b60e2ff1c4b359a810df3cd2db620a83df4692ed864e8d316606b66c88243ae4a79193ad1855ca887ac3bd7e06c0d2c71fac66163654a173aad80c74528abd091a16375e8dc3f7ec4c461181f2d0ccefac48efaad799a7251eb9238c8755077649275cbbcf853fae4ebfcd8214347f619ffc8a4d1c3c64c9c80b0e6ce85f91c4304f3bf6d190c12dc99643d2d0c718e8f5f9c521ca3d8e40bc09f4cc2d03aa819c738469e64a0ca58c343878c1a75d7a4f2512386de3069ccd08923aac6a0a2ad0de5a2d496df5b82cdd6d4615935e1ee8bcbb6b2d86c138eeadc1a6cd2821f0736e1391e6ccd212fe5cd2de3641fb914d62f61ad7e53e2b4d0156f15d484801c9654fba2f621f51955753aa08696564349abcda9eed8a9a1a1d557e4d4d0cf6aa86735b4b31aca590dddac866a5643339f1ba4865e56772f0b82d450ca1704a9a1922f0a5243215f027cdf01e6cb82d4e9871acab87d901aaa58dd3e54af8fab4fada9f7dbd569acba3c56a77eea52479d86a9d32f759aad6e21a8db49ead4469d36aa5322751aa34ecb7b6badfb84e99a305d1ba6ebc2747d986e08d38d61ba294c3787e99630dd1aa6dbc2747b98ee08d39d61ba2b4c7787e99e30f50dd3bd416a38edfbc2747f901a6efb81203514f783416a98ee8782d410de0f07a9e1bd8704a9a1bf8706a961c18705a921c31f0952c3898f085243158f0c52431b8f0e52c323ab61cac706a921d1d550cb6a58663584b31ada590d0dad869156434eaba1a8d550d64f05a921b29f09d3b3416a08ed29619a1aa6e7c3f4ad30bd10a617c3f452985e0e52c3b2abe1dad530ee3383d4b0efb383d430f16af87835acbc1a6e5e0d43af86a757c3d6abe1ecdf08d39b617a2b4c6f07a9c702ea71887a4ca06ec1ab5bc4ea314d7590ba7dbd38483d66568fdd553704d52d4375535919a4ba31a96e5daa9b9beaf6a7ba41aa6ea1aa9bacea36acba51ab6ee5aa9bbd7aed40bd86a15e4b51afe9a8d796d46b5ceab536f59a9f7a5553bdfaa85ee555af36ef0f52b7a60f06a9c795ea76b5ba2dad6ed1ab5be89f86e9db412a26bf1ba6cfc2f4bd30fd5b98be1fa61f04a921a3d5f0d26a786a3594b51ae25a0d87ad86ce56436fab21b93f0f52437daba1c27f13a4861bff224cbf0b52439e7f15a486bbff4398be0ed31fc3f4a730fd394c7f09d35fc3f4ef61fa8f30fd2d4c7f0fd37f86e91f41cdb0e6d89014e8d6e77c3d3f64e2c461a3c74e2c985855307ad2a88923c68e7aa260f28889c30baa1e1b36be7254d5645cf8b77a611993bdcff8f1439e281831a662d8e3055593261654551694574d1a5351eb40fa7ff542e71ce971484545b4b3bce6ff02e989cdebe7b49d5e4e46bbbf397ddd2e685e0f412eabcf42b7d5b342f7ea23985cf2f54d9d0f164c185535b1a0b0604cf8373cf0564d1e56d1a1007f9b108a3c6162c1848943c64f2ca81c5f35baa0a803aeb7f0f87a5462fef16e604aceac9f389f9c9bfa5faf107be1bc7a28b0f8bcfa916e3eef5f20fdb09e4e3fab4f0d7f549f85feab9e84817ef0699165c2a4f289e3870c9d18bd708b7f65e144bb7a54f3ac76f5abe6b7ebe3ecfbf559e86ff5244c14d4c359e782ba3b0bfe3f8c06861db8020600", "isInternal": false }, { "selector": { "value": 2603445359 }, - "bytecode": "0x1f8b08000000000000ffed9d67741cc791c76701100ccb2508e64c28514c00178b44800994c41c642a8b4a044950224512140925cbb224cb39e71c64fb9c73b6efcebe6cdff97c3e873b6739e7f8e5fceeeedd7b7a573de832fe68f5acb0f014d483ad79afb83d85dea95fd554f7cc76f70c73d1d0f607929c2dd7925c103d7ee3bff7dacfe29fb7b5a678aca224672e239c3519e1accd08675d4638276584b33e239c9333c23925239c5353e4346c35d1c82d6dde6902714d9b319fb1984ecf404c0b198be98c0cc4b421ca461f3533239c8d19e19c9511ced919e19c9311ceb919e19c9711cef919e15c9011ce8519e15c9411cec519e15c9211cea519e15c9611cee519e16cca08e77919e13c3f239c176484f3c28c705e9422e71ae05c613f2fb69f2bede72afbb9da7ef277d6dacf66eb639ddd6f215967d8485a9dbf9548da48da493a9cbf75927491ac27e9b67f6bb27feb21d940b2916413c966922d360e5b492e21b994e432926d24db497690ec24d945b29b640fc95e927d24fb492e27790ac901922b48ae24b98ae46a926b48ae25b98ee47a87e520c90d243792dc447233c92d248748fa480e931c21394ad24f728ce45692db488e939c20b99de424c92992d32403246748ee20394b728e6490e44e92bb48ee26b987e45e27664f25b98fe46924f73b9c4f277980e4419287489e41f230c933499e45f26c92e7903c97e47924cf277901c90b495e44f262929790bc94e465242f277905c92b495e45f26a92d790bc96e47524af277903c91b49de6459b821bc99e42d248f90bc95e46d246f27f90b927790bc93e45d24ef26790fc97b49de47f27e920f907c90e443241f26f908c947493e46f271924f907c92e453249f26f90cc95f92fc15c95f937c96e473247f43f2b7247f47f2f724ff40f28f24ff44f279922f90fc33c9bf907c91e45f49be44f26f4eccbf4cf2ef245f21f9aad57dcd7e7eddd6e571b1ff20f94f5bfe86fdfca6fdfc96fdfcb6f39def907cd7d17d8fe45147f77d921fd8f20fede78fece78fede74fece74fede7cfece7cfede72fece72fede7afece7afede76fece76fede7efece7efeda799537d68ce50794a34bcf54629f551edc78a664e8583bf221ab99958d4dabff16793d5d7d97dfee4d84db2fb931c7dbdddaf778e33c5ee4f71f48d76bfd1d1cfb6fbb31dfd5cbb3fd7d1cfb7fbf31dfd8576ff42d0e7231873b57aa3abb5aa1ce8385f6b4037c9ea6a4157cf8703dd64ab9b043a3ebff5a09b6a75934137cdeaa6802e6f7553399624d3adae374a2b578a7de6b885b48f6be7a166a4cf7bc41cb741887766fabcfde6b88d02bc263f66d963cd84bc996d758da0b3dd4d340b7473ad6e36e8e659dd1cd0cdb7bab9a05b6075f340b7d0eae6836e91d52d00dd62ab5b08ba2556b708744bad6e31e89659dd12d02db7baa5a06bb2ba65a03bcfea9683ee7cab6b021daf71390f74175addf9a0bbc8ea2e001df7b517828eef0d2fb23ad34f4cc9c177ac9efba8f83bdc3f836e25f7cda05bc5fd32e856739f0cba35609b756ba15f615db3d5711f65fed663cbbd515a6da214b7890d691f978e6c8ebb29fde3c6f3769ba3e1b8f6829d0d10ab2db69ce2daa056b49db3c276585f07e55d5097eb713cf83ac3ece67ab2d196b794f95e8ff3bd02d4d9e8f1bf374ad7ff4d0ecf26877912f82f93b36d25cdd9516f15e7ecb550d7cd3dbee7998839bb17380472b6537376d45bc539db0f75dddce3fbde8998b30781432067fb6472b654d49c1d1a238b227feef16f9f8998b3b70147fa39dba1393bfaade29c7d08eabab9c7bf7f2762cede051ce9e76c579fde1b8c7aab38675f0275dddce3b1988998b3cf040e819cedd77e76d45bc539fb26a8ebe61e8f0b4ec49c7d3970a49fb3dd4239dba6391b0dcd7746913ff7788c7a22e6ec23c0917ece1ed1f1d9d16f15e7ec67a0ae9b7b3c5f321173f683b66ce619be66e7199680eeeb56b71478d3cfeda3ed42b95dd2dc1e5a071245fe1ce5b9bb8998db9fb36593c7df80b507acfba6d59d07ba6f59ddf9a0fbb6d55d007e09b4813e6d03a3de2a6e03df85ba6e2ef33cf2446c035f010e819c3da2393beaade29cfd15d475738fd7344cc49cfd3e7008e46cbfe6eca8b78a73f6bfa1ae9b7b2b6d7922e62caf2b35f70b3fb4f70bab41f723ab5b03ba1f5bdd5ad0fdc4ea9a41f753ab6b01ddcfac6e1de87e6e7545d0fdc2ea5a41f74bab2b81ee5756d706ba5f5b5d3be87e63751da0fbadd57582ee7756d705badf5bdd7ad0fdc1eabaadcecc77f1daab2f5a9d39b71c8fde28bd731bafb78a466e3967bf17cacdb23cc54234f25904b6b52e7d5b6dc6f79668f4beaf039ea280ef79b0311a9e22f0b4a6cf13af3b2da57fdcf81cb73831cd83ad16f0ab4dc0af1cd8e263f33edb2b800efb92360f637bfa8ca51cd8e263f37e3b30b20efb36bec670fb317d73536e9857a02dc5d767b4d70b1c6caf0eea2c9d335cf742cb361dfece7dc0742863dfdfeae8847235ce15b6c5c7e6fd1230b28fade3cf581a2d63d16194ea3772608b8fedda9eee898f8959bb27661d428ced0e23ef770023c7af7dfc194ba36574fb05a13ea975b47d12c7a575fc6336aaf35a001ddeff7578183bd3678ccf6b87c3c8fb9dc0c8ba36e091ba1e26b5d7506c4bdc87603ef3358baf3f6caf0eea74d50ed7dd0bd753813eb454e9bd29f6e9e99fa75211af67a3e1113e77ad42f958c4bef3b128dd5c73db7cab132b6cf3d8974bf593497d39db53666556666556666556666556666556666556666556666556666556666556e6f09993e6e57ceb199e4c46d6958047629c3f7e47953d16ce013d0af33ae9cf5b948a3857cfeb1857393ed7419dffcb0db3fdc8b34e02e7ced7393aa1754af1b9c4754abdb0cff670dd06ae9b12587b12f3ac75785cdbd33df109711d49486b3492d6698514b302e8703d5c8b104f529eb5786c37a566bb7444a6ed948ae67d40e69d7adc9fb86d04d7bead7174a64feaa91df65b22072a9d77c6eb0697d39cc7c57c435be9afb7298d589f50138dbc56e03d85c01a9511f3d5bc36a2d3b15d0775a6d6447f3a37ebe1efbdd1e3d708993a5dceb1f93babe0bb5dceb11be4fc2ddb1f76023797eb1ddf9a819bebcca819f6f1b3b62c743f53c2f5b311f0468e4fbce1fa8cf4eff786d68bb455c0d3013c126bd784ee6b8b988f69af17e97262e5bb5fe63a9d10bf2e81f8955bb3c6f694599995599995599995599995599995599995599995599995599995599995397c667cff05b3e233d2a54018c7698d4d3c9fc1ef32c279b1b7d40cdb959e03e439a7d58ecff88cf26f6b86d9de6ecbf88e00dff3ee782ea5e6d692ce25db9b1e3dfe397da17339ea773f747862d6e589d97a2146b7cfe0fdf5c0c8f1eb021ea9f6d8e9f0b8b6b1cfe808346649fdacd4fa95a43cf3ad53684acdf6d07a1189795d5e2fe25ebf4a4e4c719d04eb701e1cdfad12f2fb5fdcb50bd84fe11aadf4fbcdd288396077ad20dbc375125fb0b1e57512e9f703a5a2e43582db28af0969f3f8ca75be04d7b92fdb32ae152ac1b11ef5fc9db7726b12b04f4dfd1d9cc5a1397e7e77259fdf1e8fed8dc09a92ed56b49db3c276585f07e5efd50cd7e57a1c0f8e35b39b36c2ef324476f77badcef70a50a7dbe37f6f94aeff3d0e4f8fc36c72e7ab90678fc2bd9e549fd49d10a3551023ae83f7bc52d72f77cdb6bb5619fbd1c94e1dfe6e1dd4f919f45195bc2b4aea7e21e91a80f70bee7561346bc7ab7d3de01fa1bf487b3de01f21877cf7a57cfcd5707ce69a1c255f5bb8ceff3ad75181f57aa37aef95efb71ff3e27a43aef318f45545bb2e37e9778cef390ba9df0d49cf7db03dbca7aac477ec17d2be36623e220be6f29faed136d69c8f5d09dceb3cdfcd277c9763c5ebcbf177b21b3f13876ef84e6f2a7118ea6f7a1c5fb84d75832f5ca7117c91b9671abaff4cdfd791f743dc07b57b7ce53af3e05d700b6c390fe709fbca8b3d7fe7addcfd27c7cff83cdeef5447db21bc537d45ed705df7dde81ceb4adfa9dee97c2fc477aa2f863cbb189eb590eaab3726c46835c488ebe0b38eeeefffa46bcc93f95e52b7dfc4ebe478b2b9e3b7befb13ae83f7d05ca703fad9bca7ae3b2ecdd79034d7a7e3f3406bc12e3e0fb456289e8568643c0b0e87a4ed06c776c338da6e746c378ea36d8db9c63ca4980bfcdf1363febf30f0ffaca8c900636d0618eb32c03829038cf519609c9c01c62919609c9a01c6691960cc03e393796d17884f29b0ffefa9ecbd06da16789f431c8be668f4b16891e5297bef83b605dea152f1ff3720fc7f61b58ef5ffc22ac0f766658071760618e76480716e0618e76580717e0618176480716106181765807171061897648071690618976580717906189b32c0785e0618cfcf00e3051960bc30038c176580718532a6c2b84696b114daffe39c8f46ae357b221ee1778fc6ef50f4bde754e2ffc6add477e1f70eb78ef53d7db8c642f6ff7afcf3de2528b186a2d2770996fbffb185184b6365945a4b8eeba847c383cfa1fa9e6f11602c8d9551ea19147c2672343cbeffab57f699a0a1988d85516acd58a56b1af159c14e4fcc04184b6365947aee009f891c0d8fefd9c55659c6d25819a5d6e7e6c1c66878ba2166eb3d3113602c8d9551e8f9b23866dd15f0e07358dd9e98093096c6ca68783608c5aca7029e0d10b31e4fcc4262449eb4df89dee3b125f1dc5ea5be3303324ecd00e3b40c30e23a0989feabdc3a891ed9f894c61a1fa9f3556e9d04da16784e248e053e17f044b1d824cb53769d04dade2c140b7c6ee38962b11978249e23c9838dd1f0304301be372b038cb333c03827038c7333c0382f038cf333c0b820038c0b33c0b828038c8b33c0b824038c4b33c0b82c038ccb33c088bf5505ee15cbfe7ed93cc16d27fd5699e8b6937e974c74db9ae79ae7d5605bf35cf3bc1a6c6b9e6b9e57836dcd73cdf36ab0ad79ae795e0db635cf35cfabc1b6e6b9e67948b6b330c6af8c138f11799ad2e329a2ef68ab3700df7b3d3c3921dfd1d6d6007c6786ac316ec900e3860c306a1c87d6208e85d1f05c22c4b3b5029e4b80e752219e4b2ae0b914782e4b9f27cea94b2be06186027c6f430618b7648051e3a8710c8951e3583d715446655446657c3218b3d0872b6326f2b1345646c3b32d7d9e38669755c0b30d62c6df6b95652c8d95d1f06c4f9f278ed9b60a78b643ccb6796226c0581a2ba3e1d9913e4f1cb3ed15f0ec80986df7c44c80b1345646c3b3337d9e38663b2ae0d90931dbe18999006369ac8c866757fa3c71cc7656c0b30b62b6d3133301c6d258190dcfeef479e298edaa806737c46c972766028ca5b1321a9e3de9f3c431db5d01cf1e88d96e4fcc04184b6365343c7bd3e78963b6a7029ebd10b33d9e98093096c6ca6878f6a5cf13c76c6f053cfb20667b3d310b9571430618b7648051388ea5b1321a9efd423cfb2ae0d90f3c970bf1ecaf80e772e0794afa3c714e5d5e010f3314e07b1b32c0b825038c1a478d63488c1ac7ea89a3322aa33256c6d89b01463dd7ca182aa3c0efabb2cfd05c3ec16d3738b61baac476d2333413ddb6e6b9e67935d8d63cd73caf06db9ae79ae7d5605bf35cf3bc1a6c6b9e6b9e57836dcd73cdf36ab0ad79ae795e0db635cf35cfabc1b6e6b9e67935d8d63cd73caf06db9ae79ae7d5605bf35cf3bc1a6c6b9e6b9e57836dcd73cdf36ab0ad79ae795e0db635cf35cfabc1b6e6b9e67935d8d63cd73caf06db9ae79ae721d93e90beed52a5cfb01e001e89676a85fc2c9ae35e618ff5588af133b1bad289d5e54eac0a50e70a88df9502f1cb815d3e36efb3bd4a992f0e8059c87669061d632af8cf36b638f130f6af12f23da9afbf6a82db4eeaeb27baeda4be7ea2dbd63cd73caf06db9ae79ae7d5605bf35cf33c14db58ae8b86efdbf9fd4ae61857dbf224bb8facfc3daeb369f2d06743a46d48c2b6b621bd5654836dcd73cdf36ab0ad79ae795e0db635cfc3ccf36bd2b71dcf8de1ef0bb3959b1bbb0678ae168885909f45e3d3b58e4f57393e15a00ebeb3f65a013f7360978fcdfbd7c279c81ab3e1d96ccbcc9a877a9b036164ddd5b23c71fbda1c8ddccab5af6b8147a01db40af919b7afeb1c9f367be2ce753057af13f0d3d77678ff3a380f5963363c5b6d9959f3506f6b208cacbb4696276e5f5ba3915bb9f6751df048f43f427ec6edeb7ac7a7ad9eb8731dccd5eb05fcf4b51ddebf1ece43d6980dcf25b6ccac79a87749208cacbb5696a73d0f3ef356ae7d5d0f3c12fd8f909f71fb3ae8f8748927ee5c0773f5a0809fbeb6c3fb07e13c28b332fb980d0fff9ff2cc9a877a9706c2c8baeb4479da8b79f099b772fdd841e091e8e785e21ef76337383e5dea893bd7c15cbd41c04f5fdbe1fd1be03c54c2bc2583cc1a678d7312b3c659e39cc4ac71d63827316b9c35ce49cc1a678d7312b3c659e39cc4ac71d63827316b9c35ce49cc1a678d7312b3c659e39cc4ac71d63827316b9c35ce49cc1a678d7312b3c659e39cc4ac71d63827316b9c35ce49cc1a678d7312b3c659e39cc4ac71d63827316b9c35ce49cc1ae7b1311b9ecb6c9959f350efb240185977bd2c4ffcfcce65d1c82de7ecf742f906e03928101f213fe375ef373a3e5de6893bd7c1f675a3809fbeb6c3fb37c279a884794b069935ce6363363cdb6c9959f3506f5b208cac3b28cb13f763dba2915bb97eec46e091e8e785fc8cfbb19b1c9fb679e2ce75b07ddd24e0a7afedf0fe4d701e9459997dcc8667bb2d336b1eea6d0f8491753788f294e2e710b74723b772fdd84dc023d1cf0bc53deec76e767cdaee893bd7c15cbd59c04f5fdbe1fd9be13c54c2bc2583cc1a678d7312b3c659e39cc4ac71d63827316b9c35ce49cc1a678d7312b3c659e39cc4ac71d63827316b9c35ce49cc1a678d7312b3c6b97ae26c7876d832b3e6a1de8e40185977a3284f5b3cefb0231ab9959b77b8197824e66584e21ecf3bdce2f8b4c31377ae83edeb16013f7d6d87f76f81f330d199b764905973637c98353794398959734399939835379439895973439993983537943989597343999398353794398959734399939835379439895973439993983537943989597343999398353794398959734399939843c88d02c94e5b66d63cd4db190823eb6e92e589df7bb0331ab9955bb7730bf0dc2c101f213fe3753b871c9f767ae2ce75b07d1d12f0d3d77678ff109c8743caaccc1e66c3b3cb9699350ff57605c2c8ba9b6579e27e6c5734722bd78f1d021e897e5ec8cfb81feb737cdae5893bd7c15ced13f0d3d776789fed29b33227311b9eddb6ccac79a8b73b1046d6dd22cb13f763bba3915bb97eac0f780e09c447c8cfb81f3becf8b4db1377ae83b97a58c04f5fdbe1fdc3701e9459997dcc86678f2d336b1eeaed098491758764794a79f099b772fdd861e091e8e785fc8cfbb1238e4f7b3c71e73a98ab4704fcf4b51dde3f02e7216bcc8667af2d336b1eeaed0d8491757db23c71fbda1b8ddccab5af23c023d1ff08f919b7afa38e4f7b3d71e73a98ab4705fcf4b51dde3f0ae7216bcc86679f2d336b1eeaed0b849175876579e2f6b52f1ab9956b5f478147a2ff11f2336e5ffd8e4ffb3c71e73a98abfd027efada0eeff7c379c81ab3e1d96fcbcc9a877afb0361641df653bcd500e37e21c6c8618c9cf820cfb2c0780e04c6b320309e5981f14c0d8c6755603cb581f1ac0f8ca723309e52603ccb03e3591818cfecc078a605c6b336309ebac0785604c6b33a309e4581f1cc098c271f184f73603c9302e3e9098ca73b309e9581f17406c6d31618cfbac0781607c63337309e3581f14c0f8ca710184f4b603cf581f16c0c8c6749603cf302e39911184f43603c9303e3d914184f57603ced81f11403e3591a18cffcc0786606c6d31818cf94c0787201f0e4a3c7af63c8c3df0f80aec6f9aeb9be1c9e33fc779e37ae81ef1cb3e55acfb1fb41c7f3ccc73cdfc53849cd85a3ad5ed8677bd381e358203c5302e3690c8c6766603cf303e3591a184f31309ef6c078ba02e3d91418cfe4c0781a02e3991118cfbcc0789604c6b331309efac0785a02e32904c6333d309e3581f1cc0d8c6771603ceb02e3690b8ca733309e9581f17407c6d31318cfa4c0789a03e3c907c63327309e4581f1ac0e8c6745603c7581f1ac0d8c675a603cb303e3591818cff2c0784a81f17404c6b33e309edac0785605c63335309e5981f12c088ce740603ccb02e3a9f1f01c10e2497ab6f94020b605ce43d11cf756219f6eb3c7aab7c7657eb65707752eb0038f66fe03bfcb5ceefc3fb69ddb204652ef9528383cbc7f7482db6e706c375489ed46c7766395d8d63cd73caf06db9ae79ae7d5605bf35cf33c44db8fa567bb43df2f357a1e7d9f53791e7d9f53791e7d9f53791e7d9f53791e7d9f53791e7d9f53791e7d9f53799e1581f1e8fb9ccaf3e8fb9ccaf33407c63329301e7d9f53799e9581f1e8fb9ccaf3e8fb9ccaf3e8fb9ccaf34c0f8c47dfe7549ea73e309ed0dee714dafbe0f5fd52e5796604c6a3ef972acfa3ef972acfa3ef972acfa3ef972acfa3ef972acf3325309e5c003c4ff47e297c2fd46db67c1474bcbeb4dc7ba8f2709cdb40c7e3b97c0c73bd3a35e7f10c35f09de31eae5b3df6d8ce71cf77c723ee68ab17f6d91ebeafea78203c5302e3690c8c6766603cf303e3591a184f31309ef6c078ba02e3d91418cfe4c0781a02e3991118cfbcc0789604c67320309e8d81f1d407c6d312184f21309ee981f1ac098c676e603c8b03e35917184f5b603c9d81f1ac0c8ca73b309e9ec0782605c6d31c184f3e309e3981f12c0a8c6775603c2b02e3a90b8c676d603cd302e3991d18cfc2c0789607c6530a8ca723309ef581f1d406c6b32a309ea981f1cc0a8c6741603ccb02e3a9f1f048bd332ae9f9faf1785fd513d936fb6b212e66cbc3dfc7e339ae030e23efe3ba07e4659eb5423c49ef05581b806de33fff169d613ff3f0777c0e472aa7d63a8cbcefcb295cd7d82cc493f43e83e6006c9b58b4d832af01c8c3df5b80512aa79a1d46def7e554a32c4f7b1e7ce6addc5a236c7312e750c8cf22b6bf14dfa15134b1daefc4aac5895501ea8cc7baf4a4fe80ed29b33227311b1e9e4b6156bc9e8dc77366a361f45d5f0578e2fe715d34722bd73fee071e89eb87909f713f76c2f1699d27ee5c0773f584809fbeb6c3fb273cb69ba2746371fb286271bb87e7f6718e05dbab94f94006994388b3e1e1b588cc8aeb9b8b8130b26ead2c4fdc3f16a3915bb9fef176e091b87e08f919f709271d9f8a9eb8731d6c5f2705fcf4b51dde3f09e7a112e6131964d6388f8dd9f0f01c04b3e6a15e291046d6ed17e52915f3e0336fe5fab193c023d1cf0bc53deec74e393e953c71e73ad8be4e09f8e96b3bbc7f0ace83322bb3322bb3322bb3322bb3322bb3322bb3322bb3322bb3322bb3322bb33287cd6c78f8d95866cd43bdb640185977bb28cfd0bc435b34722b37ef700a7824e66584e21ecf3b9c767c6af3c49deb60ae9e16f0d3d77678ff349c07655666655666655666655666655666655666655666655666655666655666650e9bd9f0f03bdb99350ff5da036164dd49599ef8b9adf668e4566edee134f09c12888f909ff1bcc380e353bb27ee5c07737540c04f5fdbe1fd01380fcaaccc3e66c3c3ef6a63d63cd4eb08849175a7447986e64f3ba2915bb97e6c007824fa79a1b8c7fdd819c7a70e4fdcb90ee6ea19013f7d6d87f7cfc079a884f944069935ce1ae724668db3c6398959e3ac714e62d6386b9c939835ce1ae724668db3c6398959e3ac714e62d6386b9c939835ce1ae724668df3f830871067c3c3ff8720b3e6a15e67208cac3b2dcad316cf3b744623b772f30e678047625e4628eef1bcc31d8e4f9d9eb8731d6c5f7708f8e96b3bbc7f079c8789ce7c2283cc9a1be3c3acb9a1cc49cc9a1bca9cc4acb9a1cc49cc9a1bca9cc4acb9a1cc49cc9a1bca9cc4acb9a1cc49cc9a1bca9cc4acb9a1cc49cc9a1bca9cc4acb9a1cc49cc9a1bca9cc4acb9a1cc49cc9a1bca9cc41c426e189e2e5b66d63cd4eb0a84917503b23cf17b0fbaa2915bb9753b7700cf1981f808f919afdb39ebf8d4e5893bd7c1f67556c04f5fdbe1fdb3701e9459997dcc8667bd2d336b1eeaad0f8491756764794a79f099b772fdd859e091e8e785fc8cfbb1738e4feb3d71e73a98abe704fcf4b51dde3f07e7216bcc86a7db9699350ff5ba0361641d5e97bb85780a0e4fc1138b27cbb6d9efb1e5e9f6330f7fef0146a9feb0db61e47dcc71e4659e1e219e0687a7c1138b27cbb6f17fa32dcfb09f79f8fb466094caa91e8791f77d39d5003c1b85781a1d9e464f2c9e2cdb26169b6c79a6fdccc3df3701a3544e6d741879df97538dc0b3498827a94fda340eb693dad778d84eca95f1b0ad314f8eb940bb8bc707364523b772f7d5786d91e8ab84fc2cfaaedf9b1c9ff0fa8df7a84fd6f5499995398959e83eb73defd8e6f8440e0f6f678563319ebfb37b1c9fb2f03bbb1cf3890c326b9cc7c66c6c0fa66fbb3defd8e6f8440e0f6f83c2b110f233ee0fee8cfc31667b05a883797aa7809f39b0cbc7e6fd3be13c54c27c2283cc1ae7b1311bdb77a56e7be8fdc3689be313393cbcdd251c0b193f87fa83bb237f8cd95e01ea609ede2de0670eecf2b179ff6e380fcaaccccaaccccaaccccaaccccaaccccaaccccaaccccaaccccaaccccaacccca1c36b3b17d4feab687c6efd136c727727878bb473816327e0e8ddfdf1bf963ccf60a5007cff9bd027ee6c02e1f9bf7ef85f3a0cccaaccccaaccccaaccccaaccccaaccccaaccccaaccccaaccccaaccccaaccc61331bdb4f4ddf76fc3c0edae6f8440e0f6f4f158e85909ff1f8fd7d913fc66caf0075f09cdf27e0670eecf2b179ff3e380fcaaccc3e6663fb69a9db1e9acf43db1c9fc8e1e1ed69c2b190f173a83fb83ff2c798ed15a00e9ef3fb05fccc815d3e36efdf0fe7a112e6131964d6386b9c939835ce1ae724668db3c6398959e3ac714e62d6386b9c939835ce1ae724668db3c6398959e3ac714e62d6386b9c939835ced5136763fbe9a9db6e8bc7efd136c7277278787bba702c64fc1c1abf7f20f2c798ed15a00ee6e903027ee6c02e1f9bf71f80f330d1994f64905973637c98353794398959734399939835379439895973439993983537943989597343999398353794398959734399939835379439895973439993983537943989597343999398353794398959734399939843c80d63fbc1f46dc7cfb3a36d8e4fe4f0f0f6a0702c84fc8cd7bf3c14f963ccf60a5007f3f421013f7360978fcdfb6c4f99953989d9d87e46fab64b79c736c7277278787b86702c84fc8cfb8387237f8cd95e01eae0397f58c0cf1cd8e563f3fec3701eb2c68ce72f979eed78dd26dba8b19f46f74c5bae05ddb36cb90e74cfb6e549a07b8e2dd783eeb9b63c1974cf03df58f77c5b5e03ba17d8f226d0bdd0963782ee45b6dc03ba17db7237e85e62cb6741f7525b3e07ba97d9f220e85e6ecb7782ee15b67c17e85e69cb7783ee55b67c0fe85e6dcbf782ee35b6fc54d0bdd696ef03ddeb6cf969a07bbd2ddf0fba37d8f2d341f7465b7e00746fb2e515a07bb347f7165b7e10748fd8f243a07bab2d1f00dddb6c792ae8de6ecbd340f71750e6cf77d8f274d0bdd3960ba07b972dcf00ddbb6db90174efb1e599a07baf2d3782ee7db63c0b74efb7e5d9a0fb802dcf01dd076d792ee83e64cbf340f7615b9e0fba8fd8f202d07dd4961782ee63b6bc08741fb7e5c5a0fb842d2f01dd276d7929e83e65cbcb40f7695b5e0ebacfd8329edfbfb4e567808efb958741c7fdca3341c7fdcab340c7fdcab341c7fdca7340c7fdca7341c7fdcaf340c779f77cd071debd00749c772f041de7dd8b40c779f762d071debd04749c772f051de7ddcb40c779f772d071debd02749c77af041de7ddab40c779f76ad071debd06749c77af051de7ddeb40c779f77ad071debd01749c776f041de7dd9b40c779f766d071debd05749c778f80aec996df0abaf36cf96da03bdf96df0eba0b6c19fb990b6df91da0bbc896df093aee0bdf05ba8b6df9dda05b69cbef01dd2a5b7e2fe856dbf2fb40b7c696df0fbab5b6fc01d035dbf20741d762cb1f02dd3a5bfe30e88ab6fc11d0b5daf2474157b2e58f81aecd963f0eba765bfe04e83a6cf993a0ebb4e54f81aecb963f0dbaf5b6fc19d0f1759cfb19d39e4dbbe438708c8c8e7d6ef1f8c2ba29e04b6f94ee3d1ddbe263f37e1b30f239288d3f6369b48cad0ea3e1e9108819e6156fe57e3375004fbb008f909ff16fa64ec7a736c7a702d4b918fcec14f0330776f9d8bcdf09b625ce39c6a2de1e77a5138b3aa8d36e2f72e67a5a2e8e7c0c93bf258f2f52716c75785a3db6bb85e3c8c7e63eb17b1c6c7739b68b8e6dbc16f056ae6d7701f37a016673dc9ef48f1bb7ed0df6589ccf6ca7083e6d8418a4e513dace59613bacaf83f29e39c375b91ec783af9dcc6eda119f4b6477bfd7e17caf0075ba3dfef746e9fadfe3f0f438cce6f744ef9c610e81f610e740b7c3c1fb45885d4f42ecba21765c07afbdcd42b15beff0f07e33f0f0fd5527e8f83e85f9f11eaf651cb8dd7eafd3c3cdba2e606cf63096d2678cefb39a1d46de2f0123ebd6034f9750ccdc73bdd2890fde134c76eaf077eba0ce21b82ee73d754dbb6bca0dfbc5bfff1f8bd2edd3eb05e285631311c4277262c81b334c8986c72fd2e499160d8f4f9c1b1c38db776bff15fd7d47738056e760e267cee3460de8b05cebd145d1c861181c0ee661181c0eae71c282c33f5cdffc8c336ef15047ffa9e383579fee3f7de4ecbd6706fb8fee1db815a92739f4489ae40192a28eb729d1f080516f94ee4450bd63ab5cf24c81cfc9e9f3b40af9195ff4a63a3ed53b3e15a0ce24f8db54013f7360978fcdfb533db653ec88e2584c1b452ca67978a68d732c70d09d75d852f9ef387153e3f8822d1a7d72f33c5587d8e00a387ecec299bf99c63ec93a33391a3ed9dc7b9a3b5a7312cc68adb96a99d15833fa6aba2033ba6a2e6866f4d48c969ad151331a6a463fcd68a719dd34a39966f4d28c569ad1c9a66868f4d18c369ad145339a7811b07d1178cd2f7a738534a38166f4cf8cf6993b2b730760ee46ccddb7b95334bf1ecd1d82f9556b4638ccd5d6dcc998abb4b9b29a3b45738768eee8cd1dae9921db4cb2c5c67a2bc9252497925c46b28d643bc90e929d24bb487693ec21d94bb28f643fc9e5244f898646f6af20b992e42a92ab49ae21b996e43a92eb490e92dc407223c94d243793dc427288a48fe430c91192a324fd24c7486e25b98de47834b42ae876929324a7484e930c909c21b9231a9aa533b3726616ceccba99593633ab6666d1ccac99992533b3626616cccc7a99592e33abf56034341b656622cccc83996930330b6626c1cc1c3c371a9a193033012f888646facdc8be19c93723f766a4de8ccc9b917833f26e46dacdc8ba19493723e766a4dc8c8c9b917033f26d46bacdc8b619c93623d78f444323d36624da8c3c9b916633b26c4692cdc8f1bba3a1916133126c467ecd48af19d93523b966e4d68cd49a915933126b465ecd48ab19593523a966e4d48c949a91513312fa57247f4df25992cf91fc0dc9df92fc1dc9df93fc03c93f92fc13c9e749be40f2cf24ff120de5e5bf927c89e4df48be4cf2ef245f21f92ac9d748be4ef21f24ff49f20d926f927c8be4db24df21f92ec9f7481e25f93ec90f487e48f223921f93fc84e4a7243f23f939c92f487e49f22b925f93fc86e4b724bf23f93dc91fa2e19915ec44a6d89e8747f9fb0607fb4f9d196c1a1c683a75e7c9c1e3674ededb74f7f1c1db9a06eeea3f7bece4c0ddf8e5cfdb2ff314c6d6b367fbee6d3a7efa68ff3d4d03770e360d1c6b3a3c70e7e9a3e7f04b3fb55f5af2788b7d478f261bfbaf3f87f47fc66874b2ed137972685779dfa6d58e212033c7f2a5f6dab139b4d15e75f8d7fb954377bb4de74e0e0c36159b4ed3bf7d27e93bfd475b9af06fe728c8e7069bce0df69d1d6c3a7676e054536b0b1ef7fce96370a26dce18be74cb9cd17b1efd3fc9de5641f9d90300", + "bytecode": "0x1f8b08000000000000ffed9d67741cc791c76701100ccb2508e64c28514c00178b44800994c41c642a8b4a044950224512140925cbb224cb39e71c64fb9c73b6efcebe6cdff97c3e873b6739e7f8e5fceeeedd7b7a573de832fe68f5acb0f014d483ad79afb83d85dea95fd554f7cc76f70c73d1d0f607929c2dd7925c103d7ee3bff7dacfe29fb7b5a678aca224672e239c3519e1accd08675d4638276584b33e239c9333c23925239c5353e4346c35d1c82d6dde6902714d9b319fb1984ecf404c0b198be98c0cc4b421ca461f3533239c8d19e19c9511ced919e19c9311ceb919e19c9711cef919e15c9011ce8519e15c9411cec519e15c9211cea519e15c9611cee519e16cca08e77919e13c3f239c176484f3c28c705e9422e71ae05c613f2fb69f2bede72afbb9da7ef277d6dacf66eb639ddd6f215967d8485a9dbf9548da48da493a9cbf75927491ac27e9b67f6bb27feb21d940b2916413c966922d360e5b492e21b994e432926d24db497690ec24d945b29b640fc95e927d24fb492e27790ac901922b48ae24b98ae46a926b48ae25b98ee47a87e520c90d243792dc447233c92d248748fa480e931c21394ad24f728ce45692db488e939c20b99de424c92992d32403246748ee20394b728e6490e44e92bb48ee26b987e45e27664f25b98fe46924f73b9c4f277980e4419287489e41f230c933499e45f26c92e7903c97e47924cf277901c90b495e44f262929790bc94e465242f277905c92b495e45f26a92d790bc96e47524af277903c91b49de6459b821bc99e42d248f90bc95e46d246f27f90b927790bc93e45d24ef26790fc97b49de47f27e920f907c90e443241f26f908c947493e46f271924f907c92e453249f26f90cc95f92fc15c95f937c96e473247f43f2b7247f47f2f724ff40f28f24ff44f279922f90fc33c9bf907c91e45f49be44f26f4eccbf4cf2ef245f21f9aad57dcd7e7eddd6e571b1ff20f94f5bfe86fdfca6fdfc96fdfcb6f39def907cd7d17d8fe45147f77d921fd8f20fede78fece78fede74fece74fede7cfece7cfede72fece72fede7afece7afede76fece76fede7efece7efeda799537d68ce50794a34bcf54629f551edc78a664e8583bf221ab99958d4dabff16793d5d7d97dfee4d84db2fb931c7dbdddaf778e33c5ee4f71f48d76bfd1d1cfb6fbb31dfd5cbb3fd7d1cfb7fbf31dfd8576ff42d0e7231873b57aa3abb5aa1ce8385f6b4037c9ea6a4157cf8703dd64ab9b043a3ebff5a09b6a75934137cdeaa6802e6f7553399624d3adae374a2b578a7de6b885b48f6be7a166a4cf7bc41cb741887766fabcfde6b88d02bc263f66d963cd84bc996d758da0b3dd4d340b7473ad6e36e8e659dd1cd0cdb7bab9a05b6075f340b7d0eae6836e91d52d00dd62ab5b08ba2556b708744bad6e31e89659dd12d02db7baa5a06bb2ba65a03bcfea9683ee7cab6b021daf71390f74175addf9a0bbc8ea2e001df7b517828eef0d2fb23ad34f4cc9c177ac9efba8f83bdc3f836e25f7cda05bc5fd32e856739f0cba35609b756ba15f615db3d5711f65fed663cbbd515a6da214b7890d691f978e6c8ebb29fde3c6f3769ba3e1b8f6829d0d10ab2db69ce2daa056b49db3c276585f07e55d5097eb713cf83ac3ece67ab2d196b794f95e8ff3bd02d4d9e8f1bf374ad7ff4d0ecf26877912f82f93b36d25cdd9516f15e7ecb550d7cd3dbee7998839bb17380472b6537376d45bc539db0f75dddce3fbde8998b30781432067fb6472b654d49c1d1a238b227feef16f9f8998b3b70147fa39dba1393bfaade29c7d08eabab9c7bf7f2762cede051ce9e76c579fde1b8c7aab38675f0275dddce3b1988998b3cf040e819cedd77e76d45bc539fb26a8ebe61e8f0b4ec49c7d3970a49fb3dd4239dba6391b0dcd7746913ff7788c7a22e6ec23c0917ece1ed1f1d9d16f15e7ec67a0ae9b7b3c5f321173f683b66ce619be66e7199680eeeb56b71478d3cfeda3ed42b95dd2dc1e5a071245fe1ce5b9bb8998db9fb36593c7df80b507acfba6d59d07ba6f59ddf9a0fbb6d55d007e09b4813e6d03a3de2a6e03df85ba6e2ef33cf2446c035f010e819c3da2393beaade29cfd15d475738fd7344cc49cfd3e7008e46cbfe6eca8b78a73f6bfa1ae9b7b2b6d7922e62caf2b35f70b3fb4f70bab41f723ab5b03ba1f5bdd5ad0fdc4ea9a41f753ab6b01ddcfac6e1de87e6e7545d0fdc2ea5a41f74bab2b81ee5756d706ba5f5b5d3be87e63751da0fbadd57582ee7756d705badf5bdd7ad0fdc1eabaadcecc77f1daab2f5a9d39b71c8fde28bd731bafb78a466e3967bf17cacdb23cc54234f25904b6b52e7d5b6dc6f79668f4beaf039ea280ef79b0311a9e22f0b4a6cf13af3b2da57fdcf81cb73831cd83ad16f0ab4dc0af1cd8e263f33edb2b800efb92360f637bfa8ca51cd8e263f37e3b30b20efb36bec670fb317d73536e9857a02dc5d767b4d70b1c6caf0eea2c9d335cf742cb361dfece7dc0742863dfdfeae8847235ce15b6c5c7e6fd1230b28fade3cf581a2d63d16194ea3772608b8fedda9eee898f8959bb27661d428ced0e23ef770023c7af7dfc194ba36574fb05a13ea975b47d12c7a575fc6336aaf35a001ddeff7578183bd3678ccf6b87c3c8fb9dc0c8ba36e091ba1e26b5d7506c4bdc87603ef3358baf3f6caf0eea74d50ed7dd0bd753813eb454e9bd29f6e9e99fa75211af67a3e1113e77ad42f958c4bef3b128dd5c73db7cab132b6cf3d8974bf593497d39db53666556666556666556666556666556666556666556666556666556666556e6f09993e6e57ceb199e4c46d6958047629c3f7e47953d16ce013d0af33ae9cf5b948a3857cfeb1857393ed7419dffcb0db3fdc8b34e02e7ced7393aa1754af1b9c4754abdb0cff670dd06ae9b12587b12f3ac75785cdbd33df109711d49486b3492d6698514b302e8703d5c8b104f529eb5786c37a566bb7444a6ed948ae67d40e69d7adc9fb86d04d7bead7174a64feaa91df65b22072a9d77c6eb0697d39cc7c57c435be9afb7298d589f50138dbc56e03d85c01a9511f3d5bc36a2d3b15d0775a6d6447f3a37ebe1efbdd1e3d708993a5dceb1f93babe0bb5dceb11be4fc2ddb1f76023797eb1ddf9a819bebcca819f6f1b3b62c743f53c2f5b311f0468e4fbce1fa8cf4eff786d68bb455c0d3013c126bd784ee6b8b988f69af17e97262e5bb5fe63a9d10bf2e81f8955bb3c6f694599995599995599995599995599995599995599995599995599995599995397c667cff05b3e233d2a54018c7698d4d3c9fc1ef32c279b1b7d40cdb959e03e439a7d58ecff88cf26f6b86d9de6ecbf88e00dff3ee782ea5e6d692ce25db9b1e3dfe397da17339ea773f747862d6e589d97a2146b7cfe0fdf5c0c8f1eb021ea9f6d8e9f0b8b6b1cfe808346649fdacd4fa95a43cf3ad53684acdf6d07a1189795d5e2fe25ebf4a4e4c719d04eb701e1cdfad12f2fb5fdcb50bd84fe11aadf4fbcdd288396077ad20dbc375125fb0b1e57512e9f703a5a2e43582db28af0969f3f8ca75be04d7b92fdb32ae152ac1b11ef5fc9db7726b12b04f4dfd1d9cc5a1397e7e77259fdf1e8fed8dc09a92ed56b49db3c276585f07e5efd50cd7e57a1c0f8e35b39b36c2ef324476f77badcef70a50a7dbe37f6f94aeff3d0e4f8fc36c72e7ab90678fc2bd9e549fd49d10a3551023ae83f7bc52d72f77cdb6bb5619fbd1c94e1dfe6e1dd4f919f45195bc2b4aea7e21e91a80f70bee7561346bc7ab7d3de01fa1bf487b3de01f21877cf7a57cfcd5707ce69a1c255f5bb8ceff3ad75181f57aa37aef95efb71ff3e27a43aef318f45545bb2e37e9778cef390ba9df0d49cf7db03dbca7aac477ec17d2be36623e220be6f29faed136d69c8f5d09dceb3cdfcd277c9763c5ebcbf177b21b3f13876ef84e6f2a7118ea6f7a1c5fb84d75832f5ca7117c91b9671abaff4cdfd791f743dc07b57b7ce53af3e05d700b6c390fe709fbca8b3d7fe7addcfd27c7cff83cdeef5447db21bc537d45ed705df7dde81ceb4adfa9dee97c2fc477aa2f863cbb189eb590eaab3726c46835c488ebe0b38eeeefffa46bcc93f95e52b7dfc4ebe478b2b9e3b7befb13ae83f7d05ca703fad9bca7ae3b2ecdd79034d7a7e3f3406bc12e3e0fb456289e8568643c0b0e87a4ed06c776c338da6e746c378ea36d8db9c63ca4980bfcdf1363febf30f0ffaca8c900636d0618eb32c03829038cf519609c9c01c62919609c9a01c6691960cc03e393796d17884f29b0ffefa9ecbd06da16789f431c8be668f4b16891e5297bef83b605dea152f1ff3720fc7f61b58ef5ffc22ac0f766658071760618e76480716e0618e76580717e0618176480716106181765807171061897648071690618976580717906189b32c0785e0618cfcf00e3051960bc30038c176580718532a6c2b84696b114daffe39c8f46ae357b221ee1778fc6ef50f4bde754e2ffc6add477e1f70eb78ef53d7db8c642f6ff7afcf3de2528b186a2d2770996fbffb185184b6365945a4b8eeba847c383cfa1fa9e6f11602c8d9551ea19147c2672343cbeffab57f699a0a1988d85516acd58a56b1af159c14e4fcc04184b6365947aee009f891c0d8fefd9c55659c6d25819a5d6e7e6c1c66878ba2166eb3d3113602c8d9551e8f9b23866dd15f0e07358dd9e98093096c6ca68783608c5aca7029e0d10b31e4fcc4262449eb4df89dee3b125f1dc5ea5be3303324ecd00e3b40c30e23a0989feabdc3a891ed9f894c61a1fa9f3556e9d04da16784e248e053e17f044b1d824cb53769d04dade2c140b7c6ee38962b11978249e23c9838dd1f0304301be372b038cb333c03827038c7333c0382f038cf333c0b820038c0b33c0b828038c8b33c0b824038c4b33c0b82c038ccb33c088bf5505ee15cbfe7ed93cc16d27fd5699e8b6937e974c74db9ae79ae7d5605bf35cf3bc1a6c6b9e6b9e57836dcd73cdf36ab0ad79ae795e0db635cf35cfabc1b6e6b9e67948b6b330c6af8c138f11799ad2e329a2ef68ab3700df7b3d3c3921dfd1d6d6007c6786ac316ec900e3860c306a1c87d6208e85d1f05c22c4b3b5029e4b80e752219e4b2ae0b914782e4b9f27cea94b2be06186027c6f430618b7648051e3a8710c8951e3583d715446655446657c3218b3d0872b6326f2b1345646c3b32d7d9e38669755c0b30d62c6df6b95652c8d95d1f06c4f9f278ed9b60a78b643ccb6796226c0581a2ba3e1d9913e4f1cb3ed15f0ec80986df7c44c80b1345646c3b3337d9e38663b2ae0d90931dbe18999006369ac8c866757fa3c71cc7656c0b30b62b6d3133301c6d258190dcfeef479e298edaa806737c46c972766028ca5b1321a9e3de9f3c431db5d01cf1e88d96e4fcc04184b6365343c7bd3e78963b6a7029ebd10b33d9e98093096c6ca6878f6a5cf13c76c6f053cfb20667b3d310b9571430618b7648051388ea5b1321a9efd423cfb2ae0d90f3c970bf1ecaf80e772e0794afa3c714e5d5e010f3314e07b1b32c0b825038c1a478d63488c1ac7ea89a3322aa33256c6d89b01463dd7ca182aa3c0efabb2cfd05c3ec16d3738b61baac476d2333413ddb6e6b9e67935d8d63cd73caf06db9ae79ae7d5605bf35cf3bc1a6c6b9e6b9e57836dcd73cdf36ab0ad79ae795e0db635cf35cfabc1b6e6b9e67935d8d63cd73caf06db9ae79ae7d5605bf35cf3bc1a6c6b9e6b9e57836dcd73cdf36ab0ad79ae795e0db635cf35cfabc1b6e6b9e67935d8d63cd73caf06db9ae79ae721d93e90beed52a5cfb01e001e89676a85fc2c9ae35e618ff5588af133b1bad289d5e54eac0a50e70a88df9502f1cb815d3e36efb3bd4a992f0e8059c87669061d632af8cf36b638f130f6af12f23da9afbf6a82db4eeaeb27baeda4be7ea2dbd63cd73caf06db9ae79ae7d5605bf35cf33c14db589e140ddfb7f3fb95cc31ae86bfe71c56b3d5419d4d93873e1b226d4312b6b50de9b5a21a6c6b9e6b9e57836dcd73cdf36ab0ad791e669e5f93beed786e0c7f5f98addcdcd835c073b5402c84fc2c1a9fae757cbacaf1a90075f09db5d70af89903bb7c6cdebf16ce43d6980dcf665b66d63cd4db1c0823ebae96e589dbd7e668e456ae7d5d0b3c02eda055c8cfb87d5de7f8b4d91377ae83b97a9d809fbeb6c3fbd7c179c81ab3e1d96acbcc9a877a5b036164dd35b23c71fbda1a8ddccab5afeb8047a2ff11f2336e5fd73b3e6df5c49deb60ae5e2fe0a7afedf0fef5701eb2c66c782eb16566cd43bd4b026164ddb5b23ced79f099b772edeb7ae091e87f84fc8cdbd741c7a74b3c71e73a98ab0705fcf4b51dde3f08e7419995d9c76c78f8ff9467d63cd4bb341046d65d27cad35ecc83cfbc95ebc70e028f443f2f14f7b81fbbc1f1e9524fdcb90ee6ea0d027efada0eefdf00e7a112e62d1964d6386b9c939835ce1ae724668db3c6398959e3ac714e62d6386b9c939835ce1ae724668db3c6398959e3ac714e62d6386b9c939835ce1ae724668db3c6398959e3ac714e62d6386b9c939835ce1ae724668db3c6398959e3ac714e62d6386b9c939835ce1ae724668db3c6398959e3ac714e62d6388f8dd9f05c66cbcc9a877a9705c2c8baeb6579e2e7772e8b466e3967bf17ca3700cf4181f808f919af7bbfd1f1e9324fdcb90eb6af1b05fcf4b51ddebf11ce4325cc5b32c8ac711e1bb3e1d966cbcc9a877adb026164dd41599eb81fdb168ddccaf56337028f443f2fe467dc8fdde4f8b4cd1377ae83edeb26013f7d6d87f76f82f3a0cccaec63363cdb6d9959f3506f7b208cacbb4194a7143f87b83d1ab995ebc76e021e897e5e28ee713f76b3e3d3764fdcb90ee6eacd027efada0eefdf0ce7a112e62d1964d6386b9c939835ce1ae724668db3c6398959e3ac714e62d6386b9c939835ce1ae724668db3c6398959e3ac714e62d6386b9c939835ced51367c3b3c39699350ff57604c2c8ba1b4579dae279871dd1c8addcbcc3cdc023312f2314f778dee116c7a71d9eb8731d6c5fb708f8e96b3bbc7f0b9c8789cebc2583cc9a1be3c3acb9a1cc49cc9a1bca9cc4acb9a1cc49cc9a1bca9cc4acb9a1cc49cc9a1bca9cc4acb9a1cc49cc9a1bca9cc4acb9a1cc49cc9a1bca9cc4acb9a1cc49cc9a1bca9cc4acb9a1cc49cc9a1bca9cc41c426e144876da32b3e6a1dece40185977932c4ffcde839dd1c8addcba9d5b80e76681f808f919afdb39e4f8b4d31377ae83edeb90809fbeb6c3fb87e03c1c526665f6301b9e5db6ccac79a8b72b1046d6dd2ccb13f763bba2915bb97eec10f048f4f3427ec6fd589fe3d32e4fdcb90ee66a9f809fbeb6c3fb6c4f99953989d9f0ecb66566cd43bddd8130b2ee16599eb81fdb1d8ddccaf5637dc07348203e427ec6fdd861c7a7dd9eb8731dccd5c3027efada0eef1f86f3a0cccaec63363c7b6c9959f3506f4f208cac3b24cb53ca83cfbc95ebc70e038f443f2fe467dc8f1d717cdae3893bd7c15c3d22e0a7afedf0fe11380f5963363c7b6d9959f3506f6f208caceb93e589dbd7de68e456ae7d1d011e89fe47c8cfb87d1d757cdaeb893bd7c15c3d2ae0a7afedf0fe51380f5963363cfb6c9959f3506f5f208cac3b2ccb13b7af7dd1c8ad5cfb3a0a3c12fd8f909f71fbea777cdae7893bd7c15ced17f0d3d77678bf1fce43d6980dcf7e5b66d63cd4db1f0823ebb09fe2ad0618f70b31460e63e4c407799605c67320309e0581f1cc0a8c676a603cab02e3a90d8c677d603c1d81f19402e3591e18cfc2c0786607c6332d309eb581f1d405c6b322309ed581f12c0a8c674e603cf9c0789a03e39914184f4f603cdd81f1ac0c8ca733309eb6c078d605c6b338309eb981f1ac098c677a603c85c0785a02e3a90f8c6763603c4b02e3991718cf8cc0781a02e3991c18cfa6c078ba02e3690f8ca71818cfd2c078e607c63333309ec6c078a604c6930b80271f3d7e1d431efe7e007435ce77cdf5e5f09ce1bff3bc710d7ce7982dd77a8edd0f3a9e673ee6f92ec6496a2e1c6df5c23edb9b0e1cc702e19912184f63603c3303e3991f18cfd2c0788a81f1b407c6d31518cfa6c0782607c6d31018cf8cc078e605c6b324309e8d81f1d407c6d312184f21309ee981f1ac098c676e603c8b03e35917184f5b603c9d81f1ac0c8ca73b309e9ec0782605c6d31c184f3e309e3981f12c0a8c6775603c2b02e3a90b8c676d603cd302e3991d18cfc2c0789607c6530a8ca723309ef581f1d406c6b32a309ea981f1cc0a8c6741603c0702e35916184f8d87e780104fd2b3cd0702b12d701e8ae6b8b70af9749b3d56bd3d2ef3b3bd3aa873811d7834f31ff85de672e7ffb1eddc0631927aaf44c1e1e1fda313dc768363bba14a6c373ab61babc4b6e6b9e67935d8d63cd73caf06db9ae79ae721da7e2c3ddb1dfa7ea9d1f3e8fb9ccaf3e8fb9ccaf3e8fb9ccaf3e8fb9ccaf3e8fb9ccaf3e8fb9ccaf3e8fb9ccaf3ac088c47dfe7549e47dfe7549ea739309e4981f1e8fb9ccaf3ac0c8c47dfe7549e47dfe7549e47dfe7549e677a603cfa3ea7f23cf581f184f63ea7d0de07afef972acf3323301e7dbf54791e7dbf54791e7dbf54791e7dbf54791e7dbf54799e2981f1e402e079a2f74be17ba16eb3e5a3a0e3f5a5e5de439587e3dc063a1ecfe56398ebd5a9398f67a881ef1cf770ddeab1c7768e7bbe3b1e71475bbdb0cff6f07d55c703e19912184f63603c3303e3991f18cfd2c0788a81f1b407c6d31518cfa6c0782607c6d31018cf8cc078e605c6b324309e0381f16c0c8ca73e309e96c0780a81f14c0f8c674d603c7303e3591c18cfbac078da02e3e90c8c6765603cdd81f1f404c63329309ee6c078f281f1cc098c6751603cab03e35911184f5d603c6b03e3991618cfecc0781606c6b33c309e52603c1d81f1ac0f8ca736309e5581f14c0d8c6756603c0b02e35916184f8d8747ea9d5149cfd78fc7fbaa9ec8b6d95f0b71315b1efe3e1ecf711d7018791fd73d202ff3ac15e2497a2fc0da006c1bfff9b7e80cfb9987bfe373385239b5d661e47d5f4ee1bac666219ea4f719340760dbc4a2c596790d401efede028c5239d5ec30f2be2fa71a6579daf3e0336fe5d61a619b933887427e16b1fda5f80e8da289d57e27562d4eac0a50673cd6a527f5076c4f99953989d9f0f05c0ab3e2f56c3c9e331b0da3effa2ac013f78feba2915bb9fe713ff0485c3f84fc8cfbb1138e4feb3c71e73a98ab2704fcf4b51dde3fe1b1dd14a51b8bdb47118bdb3d3cb78f732cd85ea5cc0732c81c429c0d0faf4564565cdf5c0c8491756b6579e2feb1188ddccaf58fb7038fc4f543c8cfb84f38e9f854f4c49deb60fb3a29e0a7afedf0fe49380f95309fc820b3c6796ccc8687e72098350ff54a8130b26ebf284fa998079f792bd78f9d041e897e5e28ee713f76caf1a9e4893bd7c1f6754ac04f5fdbe1fd53701e94599995599995599995599995599995599995599995599995599995599995396c66c3c3cfc6326b1eeab505c2c8badb457986e61ddaa2915bb9798753c023312f2314f778dee1b4e3539b27ee5c0773f5b4809fbeb6c3fba7e13c28b3322bb3322bb3322bb3322bb3322bb3322bb3322bb3322bb3322bb3322b73d8cc8687dfd9ceac79a8d71e0823eb4ecaf2c4cf6db54723b772f30ea781e794407c84fc8ce71d061c9fda3d71e73a98ab03027efada0eef0fc079506665f6311b1e7e571bb3e6a15e47208cac3b25ca33347fda118ddccaf56303c023d1cf0bc53deec7ce383e7578e2ce753057cf08f8e96b3bbc7f06ce4325cc2732c8ac71d63827316b9c35ce49cc1a678d7312b3c659e39cc4ac71d63827316b9c35ce49cc1a678d7312b3c659e39cc4ac71d63827316b9cc7873984381b1efe3f0499350ff53a036164dd69519eb678dea1331ab9959b7738033c12f33242718fe71dee707ceaf4c49deb60fbba43c04f5fdbe1fd3be03c4c74e6131964d6dc181f66cd0d654e62d6dc50e62466cd0d654e62d6dc50e62466cd0d654e62d6dc50e62466cd0d654e62d6dc50e62466cd0d654e62d6dc50e62466cd0d654e62d6dc50e62466cd0d654e62d6dc50e624e61072c3f074d932b3e6a15e57208cac1b90e589df7bd0158ddccaaddbb90378ce08c447c8cf78ddce59c7a72e4fdcb90eb6afb3027efada0eef9f85f3a0cccaec63363ceb6d9959f3506f7d208cac3b23cb53ca83cfbc95ebc7ce028f443f2fe467dc8f9d737c5aef893bd7c15c3d27e0a7afedf0fe39380f5963363cddb6ccac79a8d71d0823ebf0badc2dc45370780a9e583c59b6cd7e8f2d4fb79f79f87b0f304af587dd0e23ef638e232ff3f408f134383c0d9e583c59b68dff1b6d7986fdccc3df3702a3544ef5388cbcefcba906e0d928c4d3e8f0347a62f164d936b1d864cb33ed671efebe0918a5726aa3c3c8fbbe9c6a049e4d423c497dd2a671b09dd4bec6c37652ae8c876d8d7972cc05da5d3c3eb0291ab995bbafc66b8b445f25e467d177fddee4f884d76fbc477db2ae4fcaaccc49cc42f7b9ed79c736c7277278783b2b1c8bf1fc9ddde3f89485dfd9e5984f649059e33c3666637b307ddbed79c736c7277278781b148e85909f717f7067e48f31db2b401dccd33b05fccc815d3e36efdf09e7a112e6131964d6388f8dd9d8be2b75db43ef1f46db1c9fc8e1e1ed2ee158c8f839d41fdc1df963ccf60a5007f3f46e013f7360978fcdfb77c37950666556666556666556666556666556666556666556666556666556666556e6b0998ded7b52b73d347e8fb6393e91c3c3db3dc2b190f17368fcfedec81f63b657803a78ceef15f0330776f9d8bc7f2f9c07655666655666655666655666655666655666655666655666655666655666650e9bd9d87e6afab6e3e771d036c7277278787baa702c84fc8cc7efef8bfc31667b05a883e7fc3e013f7360978fcdfbf7c179506665f6311bdb4f4bddf6d07c1edae6f8440e0f6f4f138e858c9f43fdc1fd913fc66caf0075f09cdf2fe0670eecf2b179ff7e380f95309fc820b3c659e39cc4ac71d63827316b9c35ce49cc1a678d7312b3c659e39cc4ac71d63827316b9c35ce49cc1a678d7312b3c659e39cc4ac71ae9e381bdb4f4fdd765b3c7e8fb6393e91c3c3dbd3856321e3e7d0f8fd03913fc66caf0075304f1f10f0330776f9d8bcff009c8789ce7c2283cc9a1be3c3acb9a1cc49cc9a1bca9cc4acb9a1cc49cc9a1bca9cc4acb9a1cc49cc9a1bca9cc4acb9a1cc49cc9a1bca9cc4acb9a1cc49cc9a1bca9cc4acb9a1cc49cc9a1bca9cc4acb9a1cc49cc9a1bca9cc41c426e18db0fa66f3b7e9e1d6d737c228787b707856321e467bcfee5a1c81f63b657803a98a70f09f89903bb7c6cde677bcaaccc49ccc6f633d2b75dca3bb6393e91c3c3db33846321e467dc1f3c1cf963ccf60a5007cff9c3027ee6c02e1f9bf71f86f39035663c7fb9f46cc7eb36d9468dfd34ba67da722de89e65cb75a07bb62d4f02dd736cb91e74cfb5e5c9a07b1ef8c6bae7dbf21ad0bdc0963781ee85b6bc11742fb2e51ed0bdd896bb41f7125b3e0bba97daf239d0bdcc960741f7725bbe1374afb0e5bb40f74a5bbe1b74afb2e57b40f76a5bbe1774afb1e5a782eeb5b67c1fe85e67cb4f03ddeb6df97ed0bdc1969f0eba37daf203a07b932daf00dd9b3dbab7d8f283a07bc4961f02dd5b6df900e8de66cb5341f7765b9e06babf80327fbec396a783ee9db65c00ddbb6c7906e8de6dcb0da07b8f2dcf04dd7b6db91174efb3e559a07bbf2dcf06dd076c790ee83e68cb7341f7215b9e07ba0fdbf27cd07dc4961780eea3b6bc10741fb3e545a0fbb82d2f06dd276c7909e83e69cb4b41f7295b5e06ba4fdbf272d07dc696f1fcfea52d3f0374dcaf3c0c3aee579e093aee579e053aee579e0d3aee579e033aee579e0b3aee579e073acebbe7838ef3ee05a0e3bc7b21e838ef5e043acebb17838ef3ee25a0e3bc7b29e838ef5e063acebb97838ef3ee15a0e3bc7b25e838ef5e053acebb57838ef3ee35a0e3bc7b2de838ef5e073acebbd7838ef3ee0da0e3bc7b23e838efde043acebb37838ef3ee2da0e3bc7b04744db6fc56d09d67cb6f03ddf9b6fc76d05d60cbd8cf5c68cbef00dd45b6fc4ed0715ff82ed05d6ccbef06dd4a5b7e0fe856d9f27b41b7da96df07ba35b6fc7ed0adb5e50f80aed9963f08ba165bfe10e8d6d9f2874157b4e58f80aed5963f0aba922d7f0c746db6fc71d0b5dbf22740d761cb9f045da72d7f0a745db6fc69d0adb7e5cf808eafe3dccf98f66cda25c781636474ec738bc717d64d015f7aa374efe9d8161f9bf7db8091cf4169fc194ba3656c75180d4f8740cc30af782bf79ba90378da057884fc8c7f33753a3eb5393e15a0cec5e067a7809f39b0cbc7e6fd4eb02d71ce3116f5f6b82b9d58d4419d767b9133d7d37271e46398fc2d797c918a63abc3d3eab1dd2d1c473e36f789dde360bbcbb15d746ce3b580b7726dbb0b98d70b309be3f6a47fdcb86d6fb0c7e27c663b45f06923c4202d9fd076ce0adb617d1d94f7cc19aecbf5381e7ced6476d38ef85c22bbfbbd0ee77b05a8d3edf1bf374ad7ff1e87a7c76136bf277ae70c7308b4873807ba1d0ede2f42ec7a1262d70db1e33a78ed6d168add7a8787f79b8187efaf3a41c7f729cc8ff7782de3c0edf67b9d1e6ed6750163b387b1943e637c9fd5ec30f27e091859b71e78ba8462e69eeb954e7cf09e60b25387bf5b07750ec17539efa96bda5d536ed82ffefdff58946e9f5e2f102f1c9b88203e911343de98614a343c7e9126cfb468787ce2dce0c0d9be5bfbafe8ef3b9a03b43a07133f731e376a4087e55a8f2e8a460ec3e070300fc3e070708d13161cfee1fae6679c718b873afa4f1d1fbcfa74ffe92367ef3d33d87f74efc0ad483dc9a147d2240f901475bc4d8986078c7aa3742782ea1d5be592670a7c4e4e9fa755c8cff8a237d5f1a9def1a9007526c1dfa60af89903bb7c6cde9feab19d624714c762da286231cdc3336d9c638183eeacc396ca7fc7899b1ac7176cd1e8939be7a93ac40657c0f17316cefccd34f649d699c9d1f0c9e6ded3dcd19a9360466bcd55cb8cc69ad157d30599d155734133a3a766b4d48c8e9ad15033fa69463bcde8a619cd34a39766b4d28c4e364543a38f66b4d18c2e9ad1c48b80ed8bc06b7ed19b2ba4190d34a37f66b4cfdc59993b00733762eebecd9da2f9f568ee10ccaf5a33c261aeb6e64ec65ca5cd95d5dc299a3b4473476fee70cd0cd966922d36d65b492e21b994e432926d24db497690ec24d945b29b640fc95e927d24fb492e27794a3434b27f05c9952457915c4d720dc9b524d7915c4f7290e406921b496e22b999e4169243247d2487498e901c25e9273946722bc96d24c7a3a15541b7939c243945729a6480e40cc91dd1d02c9d999533b37066d6cdccb2995935338b6666cdcc2c99991533b36066d6cbcc729959ad07a3a1d928331361661ecc4c83995930330966e6e0b9d1d0cc80990978413434d26f46f6cd48be19b93723f56664de8cc49b917733d26e46d6cd48ba19393723e56664dc8c849b916f33d26d46b6cd48b619b97e241a1a993623d166e4d98c349b916533926c468edf1d0d8d0c9b916033f26b467acdc8ae19c93523b766a4d68ccc9a915833f26a465acdc8aa19493523a766a4d48c8c9a91d0bf22f96b92cf927c8ee46f48fe96e4ef48fe9ee41f48fe91e49f483e4ff205927f26f99768282fff95e44b24ff46f265927f27f90ac95749be46f27592ff20f94f926f907c93e45b24df26f90ec97749be47f228c9f7497e40f243921f91fc98e427243f25f919c9cf497e41f24b925f91fc9ae43724bf25f91dc9ef49fe100dcfac602732c5f63c3ccadf3738d87feacc60d3e040d3a93b4f0e1e3f73f2dea6bb8f0fded6347057ffd9632707eec62f7fde7e99a730b69e3ddb776fd3f1d347fbef691ab873b069e058d3e1813b4f1f3d875ffaa9fdd292c75bec3b7a34d9d87ffd39a4ff3346a3936d9fc89343bbcafb36ad760c019939962fb5d78ecda18df6aac3bfdeaf1cbadb6d3a777260b0a9d8749afeed3b49dfe93fdad2847f3b47413e37d8746eb0efec60d3b1b303a79a5a5bf0b8e74f1f83136d73c6f0a55be68cdef3e8ff0117b9177df9d90300", "isInternal": false } ], - "packedBytecode": "0x000000028df71de5000000468d1f8b08000000000000ffed9d07741d45b6ae5bb61ce0481893b3450e06a3e49c64724ec6608c31b62c0b1b0739623298e81cc8c10639e78c718e18c3cc30393381811926dd3b7367ddf5e6be77df7a8f75bbcea9bdf4ab5c7daca3e992ff2355af5552f53ed5bdbffa7b7775aaeeca0952d33fc294a3f3cdc3744170f824bf97e9ff85ffda5414e3ba0a5d72e6640967b32ce16c9e259cb959c2d9224b385b660967ab2ce16c9d259cc7c4c8a9d89a05b5a7b8798f75a06bdc8c892cd3342f0b34cdcf324d8fcb024ddb04d9d1461d9f259c6db384f3842ce13c314b384fca12ce93b384f3942ce13c354b384fcb12ced3b384f38c2ce13c334b38cfca12ceb3b384f39c2ce16c97259c0559c2796e96709e97259ce76709e70559c2796196705e1423677be0bc58ffbf44ffbf54ffbf4cff97b297ebff57e8ff1d741d73f5fc958a2b4cea214db1f15b49984ac3d4314c9d8cdf3a87a94b98ba86a99bfead40ffd63d4c3dc2d4334cbdc2d45b6bd0274c5785e9ea305d13a66bc3745d98ae0fd30d61ba314c3785e9e630dd12a65bc3745b986e0fd31d61ba334c7785a96f98ee0e53bf30dd13a67bc3d43f4cf7856980c1727f980686e981300d0ad383611a1ca621612a0fd3d03055846958982ac3f4509886876944981e0ed3c8308d0ad3e8308d09535598c686695c98c68769429826866952981e09d3e4303d1aa6c7c2f4b8a1d913617a324c4f85e96983f399303d1ba629617a2e4ccf87e98530bd18a697c2f47298a686695a98a68769469866866956986687694e98e686695e985e09d3ab617a2d4caf87e98d30bd19a6b7c2f47698de09d3bb619a1fa605617a4fb3c88ef07e98aac3b4304c8bc2b4384c4bc2b4344ccbc2b43c4c2bc2b4324cabc2b43a4c6bc2b4364cebc2b43e4c1bc2b4314c9bc2b4394c1f84694b983e0cd3d6306d0bd3f630ed08d3ce30ed0ad3ee30ed09d3de30ed0bd3fe301d08d347613a18a68fc374284c9f84e9d3307d2b4cdf0ed377c2f45998be1ba6ef199a7f3f4c3f08d30fc3f4236dfbb1feff135d56eedffd344c3fd3f99febffbfd0ff7fa9ff7f6e2cf3ab30fddab0fd264cbf356c5f84e9773affa5feff95feff7bfdff0ffaffd7faff1ff5ff3fe9ff7fd6ffffa2ffff55ffff37fdffdff5ffbfe9ff7fd7ffff43ffff47981e2848e55b0735535910531b555a997cf623e25f1cd49e9416cdf56ff2bf40db73f5bcfc17ed5ae8f91686bda59e6f69aca7b59e6f6dd8dbeaf9b686fd443d7fa2613f59cf9f6cd84fd5f3a71af60bf4fc05604f04706f58db95adb936e5804de2b519d85a685b73b0b594d581ad95b6b5009b6cdf96603b46db5a81ed586d6b0db684b61d235a86294fdbca82b862a570885a6f7edcebd5cfcb8e8b9f77a85a6f1b47bcc7c7cf3b4cadb7ad035e151f27e8751d0f7173a2b6b505db49da7602d84ed6b613c1768ab69d04b653b5ed64b09da66da780ed746d3b156c6768db69603b53db4e07db59da7606d8ced6b633c1768eb69d05b676da7636d80ab4ed1cb09dab6dedc0769eb61580ed7c6d3b176c1768db7960bb50dbce07db45da7601d8a4fdbd106c72be7891b6a9b6e3981c5846dba5dd4a2e236d36d82e95f61a6c97495b0db6f6d24e83ed72f02db62ba0ad115b076d93764bfdd64de7cb82b8f693e24ab5deee71af375cb35a6fcff8d79b7ce6d82ba8d1b50cfc7407ad7aeb7c8cfd9a8ad0778e4ee247ecb990bf09ca4a39d1438e3dc2ae8e313d74be779ae5ba19cbe543991e96fa9705f1d6bfa7c1d3d3606e017937315b52e263b6ce53c631db1fca9ab127e7418d31666f050e0731dbd9c76c9da78c63b612ca9ab127e7c28d3166ef070e07315bee26668b0b7dcca6ee9b05813df6e47aa831c6ec08e0883f663bfa98adfb9471cc3e0765cdd8936be2c618b3938123fe98ed5ceecf0dea3c651cb373a1ac197b727fa631c6ec8bc0e120662b7d3b5be729e3987d0fca9ab127f70a1b63ccbe0a1cf1c76c5747315be26336483d030d027becc97debc618b30b8123fe981deaefcfd67dca386677405933f6e4194a638cd9f53aaf9e33fc583f67380b6c3fd1b6b38137fed8aee8e828b68b7d6ca7fa8604813d46e5795e638cedbd3aafe2f8e7d01f416cbfd0b673c1f64b6d3b0f6c9f6bdbf9502f07fb40b9df07ea3c65bc0ffc1aca9ab12ccf961be33ef043e07010b3153e66eb3c651cb37f85b266ec493f87c618b35f00878398adf4315be729e398fd3f50d68cbd4b74be31c6acf43555e70b5feaf385cbc0f695b6b507dbefb5ed72b0fd41dbae00dbd7dad6016c7fd4b62bc1f6276d2b04db9fb5ad086c7fd1b662b0fd55db4ac0f66fda560ab67fd7b68e60fb9bb67502dbdfb5ad33d8fe43dbba80ed1fdad655dbd4f32ee97b25e7adad81b52c886fdb26401799728cf932c817bbe529cc071ef4551abfaf1255f792a0ee752f059e8e0eea9e001f75e1e9083c9de2e749f645ed1cff7a93dbb8c4d03401be4aa05e5d1cd42b077cc9ba655efce5830df7f32e16c6aef13316e7802f59b7cc770546b161bb23efffc8fea3dae673736a781dec4bc9e333fa2b030ef1970b65fed9aea6ec859a2d0f7ec736b89361731497c9b8105fb26e99177f79509f4e0dcf585c57c68e06a3ab3622077cc9ba4ddf79902f72ab4f5a9ece24be1d9c775bdb34d1bc7b03f8ee6af82e357c63db2953ba635b57608efdfa471fdb7ac4bfde423c5796eb14f183e70f783d11579dd0b75ca7881fb1e742fe869c9ab2524ef4907658d8d53e2cdb12d9cde5ba18cbe54399ee96fa9705f1d6bf87c1d3c36056c79b9e702c74b03f2463a0bbc121f3a5a05d8f08edba837652e612d0cec1b96752bb6e068fcc77041e69bfb13d2b6a609e2202df780e8bd772f23b9e07b8da5e4506a3ccdbb6575760ec686174704e589cee78580a8c62eb063c258e348bdaae2524be5d5c57e6800f393737af6d72a1ccedcd6bca56e438652bc6736799ea7acd1bff762a2ec4fda32e3c8ef7a12247f15888f76fbe09e28d35b35d32db9ba87b3caedaf2128347e6c59f67f6cc9ed9337b66cfec993db367f6cc9ed9337b66cfec993db367f6cc9ed9337b667e66c523cf13b0df9694eb44c268f67f73759f3ff92d3ebd2e7c06f44fa7fdc18a0bf1d99ff483b8cca8732e9439b1590ddb7f437f30b32f51d4b674d13736ddb6147fd81fac219e21961a3ca6ef3c8b3ef85c1a3573d507ca6c33641efba7897e45c0e36a7f2c36784cdfd86694906a16d5cebaead3171567b6fe8405b1f92e1eeaeab9aefaee99fa76a879fcea64689afc26a961536dd25dcd6beaede2396fa6cf9df1b821f9389fe362bf0cf4157f3b5b5cab7f42b3a0f6b10263dd555f2dd9afa46f4477c3772e9439b759cdb6c13e7565c1e1c706ece325eb96652e83657b18eb6ee3aebe69fba174076ec9b734ead619b8a5cc4570ecfea9ce3b3a061667fa8e041e93e33fbea4fa8b9464c083c73b17e72c8e8ea385188f71f71731fb41dace97a50cf62175d07f37edb158fc7966cfec993db367f6cc9ed9337b66cfec993db367f6cc9ed9337b66cfec993db367e667563ce633747cf65b4ac2d8407d6c92cf33e4fb6cf85c6c6bb31abfae9f01ca33a7f6469df11de55c784779a766c3be0ff85d29dbb674f56c2d6a5b8a3fb6be0f79167d94663d2c9a39f8ae63da6f76e0371245bf1ec0e36a7f8cfa7687adcd2822d52caa9d75d177215d9cd9fa2914c4e63bd55fc4c5735de92f621ebfccef1a613f09b1e173f0a8ef85151bb6a3dd06d8fab5491ebfb9e0628c1b8c67b3afa0f8c37e125f686da59f44fced4071a1cb6384eca3d227a4c4525729f387663565ffa8f3d857a814d6f54fcbef32a5eb93806daa83efc726b7afac4bb6afeddbb57d803526df45b8ae1c9dfa181ae442fe7f35ab292be5a4ac682dec6a1f91ef4a21bbb95c4763b97c28d3cb52ffb220defa9bdf12ee6d30abd8f90bc4d93fe15ccf559bd42b42a3cb40232983e7bcaefad59a6da4d9671afb44b632cae0f9a994f9ffd04645f549b7f5a97475be10d59f13cf176ce734661dcdbee34dbd3f60bebe0e71d11f50d6dd26a8dd272f30d6df1ed62f5cad82e8638b94690beb3f9adfbdb25dfb092ff6379432a7c0b5df0d3a9fc9b5dfd1ba8eb75dfbe1725175c77621ee6323c623b2602c4b9902231e7b447077b52c7b7ec4b2a295f9ed43bc2ec57384f8bf1b996a6f7a1b75917d0abfef2f652e35f69bf8cf9952e79faebe9129eb9236a8d8525729d301f6b5429d4fc076c2778a7a5b7e9729ddf9a7e8a7ea7c55fc754e6edfabf5ba64fb5e65f17d0db0c6e4bb087dcbf9a7f8117b2ee47bc1f144ca891ea2b5b0ab7d44cee190dd5caebbb15c3e94e963a97f59106ffdaf3278ae329855ec94409cf586772d5cb5d57d22346a0f1a4919bc776dfbaeb1ed5e47439da79adf4bcf0f0eff762f1e27dd9cb3d9df9533efdfdace4fda1bfc787e722bb4b3094b59f3beb42c1767ff747c1f08cf0bf17d2057d748f9416d3df30d0e97bedb18bedb34a0efb686efb60de8db6bee3567d29c69cc1f7c0ed90c185d1cebf0b85a1746dbf1af3930ba7a67b3240346fce6351eef84d1c577c2eb3ba6109eebb4004617ef1b677abfba1330e2370684d1c53bda997ea71adfdb96e55a01a38b718d700ca5ba30dac63a6a0dff1d8c6b5454df714070aca36380d1c5d82089a0f678264762ec068cb2dcb1c0e8e2395222a87d5fed488cf8bc52964b38664c776c77dcf7a738d37b100dd1af20ea5c037d3bb8ff5f8c7d13eaa2454fb73c69cf7dd0b783fb5f492d702ccb236981cfe75c8cad99086a3f0b3b120f3e4394e54e00c632478cbd33602c034659ee4460ece388b12c03c63ec028f69380d1c17dc824639f0c18f17e9d2c7732305eed88f1aa0c18af064659ee146074714f31017eebc2780d30ca72a702e3b58e18afc980f15a6094e54e03c6eb1c315e9b01e375c028cb9d0e8cd73b62bc2e03c6eb8151963b03186f70c4787d068c3700a32c772630dee888f1860c186f044659ee2c60bcc911e38d1930de048cb2dcd9c078b323c69b3260bc191865b97380f116478c3767c0780b30ca72ed80f156478cb764c0782b30ca7205c0789b23c65b3360bc0d1865b97381f176478cb765c0783b30ca72e701e31d8e186fcf80f10e6094e5ce07c63b1d31de9101e39dc028cb5d008c773962bc3303c6bb805196bb1018fb3a62bc2b03c6bec028cb5d048c773b62ec9b01e3ddc0d8d7c2d8cf11e3dd1930f6034659ee7260bc277ec6e4b574bf0c18ef019e7be3e7496a764f063cf7bae5497e43f11e8baffbe2f795dc16fd83bad7fd3ee019103f4f725bdc97018f30e4c372a8d9fdf13326351b9001e3fdc033307e9ea466f767c0331034bbdfa2d903f13326351b9801e303c033287e9ea4660f64c03308347bc0a2d983f13326351b9401e383c033387e9ea4660f66c03338a8d1ec418b6643e2674c6a363803c621c0531e3f4f52b32119f0948366432c9a0d8d9f31a95979068c4381a7227e9ea4664333e0a900cd865a341b163f6352b38a0c1887014f65fc3c49cd8665c053099a0db368f650fc8c49cd2a33607c087886c7cf93d4eca10c788683660f59341b113f6352b3e119308e009e87e3e7496a3622039e8741b31116cd463a627c3803c691169eb8bf89feb0c5d76847751f15d4bdeec2900fcb613f89318e184767c03806186539ec2751e588714c068c55c028cb251c33a6eb275105bec7c6ef3bd92e550575d767ac5b9eb4fd24d0f738475a8c0deaaec538b73c69fb49a0eff18eb41817d45d8bf1c033c1811609f051171e61c887e5b09fc444478c1332609c088cb21cf69398e4887162068c93805196c37e128f38629c9401e323c028cb613f89c98e181fc980713230ca72d84fe251478c9333607c14186539ec27f19823c64733607c0c186539ec27f1b823c6c732607c1c186539ec27f18423c6c733607c02186539ec27f1a423c62732607c12186539ec27f19423c62733607c0a186539ec27f1b423c6a732607c1a186539ec27f18c23c6a733607c06186539ec27f1ac23c66732607c16186539ec2731c511e3b319304e0146596ea463c674d72f531ab9efa86b95c6ee3beabaa4b1fbf671eee3bc29f8f671eee3bc29f8f671eee3bc29f8f671eee3bc29f8f671eee3bc29f8f671eee3bc29f8f671eee39cc9f7730e7c27c0874c39c67c19e485211f961be9191b3523f214c4c7538875475fcf13d4fd790b4f8ea3baa3af1708ea2e0cd9c6f85c16308ecc0246af63aa0f627d1815cf8b8e785ec880e745e079c911cf8b19f0bc043c2fc7cf938ca99732e011867c586e6416303e97058c5e47af2313a3d7b1e9e8e8193da367f48c4783311bda70cf9815f1585c5f46c533357e9ea4662f67c033153493e5ee75cb585c5f46c5332d7e9ea4665333e099069a4db568e680b1b8be8c8a677afc3c49cda665c0331d349b66d1cc0163717d1915cf8cf879929a4dcf8067066836dda29903c6e2fa322a9e99f1f324359b9101cf4cd06c864533078cc5f565543cb3e2e7496a3633039e59a0d94c8b660e188bebcba87866c7cf93d46c56063cb341b35916cd1c3016d79751f1cc899f27a9d9ec0c78e68066b32d9a39602cae2fa3e2991b3f4f52b33919f0cc05cde6583463651c99058ccf6501a3631d8bebcba878e639e2999b01cf3ce079c511cfbc0c785e019e57e3e749c6d42b19f008433e2c37320b189fcb0246afa3d79189d1ebd87474f48c9ed13366c6f87c1630fa6ded1959191d5c5fa57d87e69546ee3bea1d9ac6ee3bea1d9ac6eedbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98ff3a6e0dbc7b98f7326dfafc5efbb38d377585f031e17efd43aaa67a15aefeb7a5ddfc4a89fd2ea0d43ab570cadf2a1cceba0df1b0ef4cb01bfb26e99177f99325f4cc0ecc877f171e13a8e81fa8b8fe70c3d94ff371dd53daaad7fb391fb8e6aeb1bbbefa8b6beb1fbf671eee3bc29f8f671eee3bc29f8f671eee39cc537e673839af376f9be925ac75b3adf42cf4bf9e7613929d3af55ea7f9bc0ef432e7cfb7dc81f2b9a826f1fe73ece9b826f1fe73ece9b826f1fe77c718ef1707503f004064f9086e749329ece643c63c9788692f1dc43c67313194f2f329ec9643cc5643c33c9781e26e379898c671019cf9d643cd792f15c41c6f334194f57329ef1643cc3c878ee23e3b9858ca78c8ce731329e52329e59643ca3c9785e26e3194cc6d3978ce705329eebc9789e25e3e94ec633878ce752329e89643c9790f13c44c65348c6733f19cf71643c6dc8786e23e3b98a8ce709329e4e643cb3c978aac878a692f19493f1f423e3b9928ce746329e9e643cf3c8781e21e32922e31941c6f30019cf1d643ccdc978ae21e3798a8ca70b19cf38329ef6643c15643cd3c878fa93f1dc4cc6d39b8ce751329e12329e51643c0f92f1dc45c6d310dfe3c884670a19cf75643ccf90f17423e39940c6339d8ce762329e4a329e01643c79643cf9643c1dc8786e25e3e943c6f338194f47329e31643c43c878ee26e379918ce706329e1e643c73c9782691f1cc20e3194ec633908ce732329ee3c978da92f1dc4ec69343c093080eff4672027e7f0d6ccd8c65d567a5ba15d4fcfeb6b6378365ded1f9e69675bf0d36f956d53b966551a7b7a12e653a5ff8af4d499dd05719cc8bbf3ce0788784e776329eb6643cc793f15c46c633908c673819cf0c329e49643c73c9787a90f1dc40c6f32219cfdd643c43c878c690f17424e3799c8ca70f19cfad643c1dc878f2c978f2c8780690f15492f15c4cc6339d8c6702194f37329e67c878ae23e39942c6f31a19cf5d643c0f92f18c22e32921e379948ca73719cfcd643cfdc978a691f15490f1b427e31947c6d3858ce729329e6bc8789a93f1dc41c6f30019cf08329e22329e47c878e691f1f424e3b9918ce74a329e7e643ce5643c53c978aac8786693f17422e379828ce72a329edbc878da90f11c47c6733f194f2119cf43643c9790f14c24e3b9948c670e194f77329e67c978ae27e379818ca72f19cf60329e97c9784693f1cc22e32925e3798c8ca78c8ce716329efbc8788691f18c27e3e94ac6f33419cf15643cd792f1dc49c633888ce725329e87c9786692f11493f14c26e3e945c6731319cf3d643c43c978c692f17426e379928ce76a0bcf6b8e78e47d7759b7ccbf46e2dbc1762854eb7dd7519de6eb75b5d4eb157ef1970b658a8e4dfd57cf877059e132bf4f807dbfe783466f39aa8b3926a6ccbfd5c87db7317cb76922bedb1abedb3611df3ece7d9c33f99e1fbfef62fcb68d4c39c67c19e4f1f8e2e29b408eea59ebd8fe4d8cfa29ad16185abd6568950f65de05fd1638d0cf76be20f3e22f53e68b0998312e0a8278e3e2bdf8eb54acfad21c03babe67e88bf57adf91a651c790f71bb9efa8634863f71d750c69ecbe7d9cfb386f0abe7d9cfb386f0abe7d9cfb3867f25dadf3315e3716a20f75ef57ae07aac1ef229dcf89d1af5ad742bdae167addc2b10878a4cc2b702fdaeff37e9f8fcbb73fb6f9386f0abe99e3dccccb33c44b80cdd533dea8586c88e7cb47d377542c3676df51b1d8d87dfb38f771cee47b71fcbe93cf105f0b6a4fe99e212e069e850eb47054cfe4b5d312a34eaf1975ca8732d550cf250eea99037e65dd32bf04b643b6312b9e293a8fe3bb48b929248c625be89627b97f4d096a4fe9f6af25c0e3603f287254cfe4feb5d4a8d3148bee52a61aeab9d4413d6dfb8ecc2f85ed906dcc8a47dedd15d604947b8184516c8bddf224f7af1782da53bafd6b29f0b8687f1cd533b97f2d33eaf482457729530df55ce6a09eb67d47e697c176c83666c5236399086b02cabd48c228b6256e794a13506799d2ed5fcb80c745fbe3a89ec9fd6bb951a7172dba4b996aa8e77207f5b4ed3b32bf1cb68367f6cc3666c523ef4c0a6b02cabd44c228b6a54e794a0b13506799d2b563cb81c7453bef48f7643bb6c2a8d34b16dda54c35d47385837adaf61d995f01db2113e6f959c85c9d85cc5e67af7314737516327b9dbdce51ccd559c8ec75f63a4731576721b3d7d9eb1cc55c9d85cc5e67af7314737516327b9dbdce51ccd559c8ec75f63a4731576721b3d7d9eb1cc55c9d85cc5e67af7314737516327b9dbdce51ccd559c8ec75f63a4731576721b3d7d9eb1cc55c9d85cc5e67af7314737516327b9dbdce51ccd559c8ec75f63a47315767213383ce8ae7659d17d604947b9984516ccbdcf224dfdf7939a83de518f365905f013ccb1de8e3a89ec97eef2b8d3abd6cd15dca54433d573aa8a76ddf91f995b01d32619e9f85ccd559c8cca0b3e299aaf3c29a8072534918c5b6dc2d4fb21d9b1ad49ed2b5632b81c7453befa89ec9766c9551a7a916dda54c35d47395837adaf61d995f05dbc1337b661bb3e299a6f3c29a8072d34818c5b6c2294f71f23dc46941ed295d3bb60a785cb4f38e744fb663ab8d3a4db3e82e65aaa19eab1dd4d3b6efc8fc6ad80e9930cfcf42e6ea2c64f63a7b9da398abb390d9ebec758e62aece4266afb3d7398ab93a0b99bdce5ee728e6ea2c64f63a7b9da398abb390d9ebec758e62aece4266afb3d7398ab93a0b991974563cd3755e5813506e3a09a3d8563ae529493e77981ed49ed23d77580d3c2e9ecb38d23df9dc618d51a7e916dda54c35d4738d837adaf61d995f03dba1b133cfcf42e66acfdc20cc3e363c7314b38f0dcf1cc5ec63c3334731fbd8f0cc51cc3e363c7314b38f0dcf1cc5ec63c3334731fbd8f0cc51cc3e363c7314b38f0dcf1cc5ec63c3334731fbd8f0cc51cc3e363c7314b38f0dcf1cc5cc101b8a6786ce0b6b02cacd206114db2ab73cc9ef1ecc086a4fe9faedac019ed50ef47154cf64bf9db5469d6658749732d550cfb50eea69db77647e2d6c07cfec996dcc8a67a6ce0b6b02cacd246114db6ab73cc9766c66507b4ad78ead051e17edbca37a26dbb175469d665a749732d550cf750eea69db77647e1d6c07cfec996dcc8a6796ce0b6b02cacd226114db1ab73cc9766c56507b4ad78ead031e17edbca37a26dbb1f5469d6659749732d550cff50eea69db77647e3d6c07cfec996dcc8a67b6ce0b6b02cacd266114db5ab73cc509a8b34ce9dab1f5c0e3a29d7754cf643bb6c1a8d36c8bee52a61aeab9c1413d6dfb8ecc6f80ed906dcc8a678ece0b6b02cacd216114db3ab73cc9fd6b4e507b4ab77f6d001e17ed8fa37a26f7af8d469de658749732d550cf8d0eea69db77647e236c876c63563c73755e5813506e2e09a3d8d6bbe549ee5f7383da53bafd6b23f0b8687f1cd533b97f6d32ea34d7a2bb94a9867a6e72504fdbbe23f39b603b641bb3e299a7f3c29a8072f34818c5b6c1314f02ea2c53bafd6b13f0b8687f1cd533b97f6d36ea34cfa2bb94791feab9d9413d6dfb8ecc6f061e99ae061e577119183c81451f999e24e3e94cc633968c672819cf3d643c3791f1f422e3994cc6534cc6f33019cf20329e3bc978ae25e3b9828ce769329eae643ce3c9788691f1dc47c6730b194f1919cf63643ca5643ca3c9780693f1f425e3b99e8ce759329eee643c9792f14c24e379888ca7908ce77e329ef7c9788e23e36943c6731b19cf55643c4f90f17422e3a922e32927e3e947c6732519cf8d643c3dc9781e21e32922e31941c6f30019cf1d643ccdc978ae21e3798a8ca70b19cf38329ef6643c15643cfdc9781690f1dc4cc6d39b8ce751329e12329e51643c0f92f1dc45c6731d19cf33643cddc8782690f15c4cc65349c633808c278f8c279f8ca70319cfad643c7dc8781e27e3e948c633868c670819cfdd643c3790f1f420e39944c6339c8c672019cf65643cc793f1b425e3b99d8c27878027111cfe2e5e027e5f003679676c1ed83ed0f98d606b66f121cf2236832d57e7651dadc2746dc1e1eb469d5cbd2787beca605efce501c707243cb793f1b425e3399e8ce732329e81643cc3c9782691f1f420e3b9818ce76e321eb91e64e11943c6d3918ce771329e3e643cb792f17420e3c927e3c923e31940c65349c6733119cf04329e6e643ccf90f15c47c6731719cf83643ca3c8784ac8781e25e3e94dc6733319cf02329efe643c15643cedc978c691f17421e3798a8ce71a329ee6643c7790f13c40c633828ca7888ce711329e9e643c3792f15c49c6d38f8ca79c8ca78a8ca71319cf13643c5791f1dc46c6d3868ce738329ef7c978ee27e32924e379888c672219cfa5643cddc9789e25e3b99e8ca72f19cf60329ed1643ca5643c8f91f19491f1dc42c6731f19cf30329ef1643c5dc9789e26e3b9828ce75a329e3bc9780691f13c4cc6534cc633998ca71719cf4d643cf790f10c25e3194bc6d3998ce749329eab2d3c0b1cf198e326c8fc0202df6abe3be8a2a604fc8edf597fdf11e3028351e6df0746e475ad591b83a78da1d9d1f4adea2fefeac83d70dc5ef8de39c3f66ad3009ab53578da1a9a1d4ddf4a0b79b62def0ce2f6c2efd4326c2f7cafda41fb5c9a3078d49463cc97417eb3637d1cd5b310dfbbfe26c6f52aadb6185a2d30b4ca87329b40bf2d0ef4cb01bfb26e99177f9ed93347312b1ee94b62fb1e403f1246b1e1b8181fc6cf539a3078d494ae7dfcd0b13e8eea996cc7b60676dd3f04dda50cc6ea5607f5cc01bfb26e99df6af15d10c4abc5b63a68b1cdc2b3ad81b5107f99326fca4266069d158fbc6b20ac0928d79f84516c5b80677bfc3ca50983474de9dac7ed8ef57154cf649bb023b0ebbe1d749732b87fed7050cf1cf02beb96f91db01d3261de9a85cc5ee7fa312b1e79475b5813506e0009a3d8b601cfced8798a0b13068f9ad2b5633b1debe3a69ea9766c5760d77d27e82e6570ffdae5a09e39e057d62df3bb603b7866cfec993db367f6cc9ed9337b66cfec993db367f6cc9ed9337b66cfec993db367e666563c03755e5813506e2009a3d87600cfeed87952cf1d90474de99e3bec76ac8f9b7aa69e3bec09ecbaef06dda50cc6ea1e07f5cc01bfb26e99df03dbc1337b66cfec993db367f6cc9ed9337b66cfec993db367f6cc9ed9337b66cfec993d3337b3e219a4f3c29a8072834818c5b60b78f6c6cf539a3078d494eeb9c35ec7fa38aa67f2b9c3bec0aefb5ed05dca60acee7350cf1cf02beb96f97db01df67966cf6c61563c83755e5813506e3009a3d8f600cffed87952cf4f91474de9dab1fd8ef57153cf543b7620b0ebbe1f74973218ab071cd43307fccaba65fe006c874c98b76621b3d7d9eb1cc5ec75f63a47317b9dbdce51cc5e67af7314b3d7d9eb1cc5ec75f63a47317b9dbdce51cc5e67af7314b3d7d9eb1cc5ec756e3a3a2b9e729d17d604942b276114db3ee0f928769e92c284c1a3a61c63be0cf21f39d6c74d3d53cf1d0e0676dd3f02dda50cee5f071dd43307fccaba65fe206c87c6cebc350b997d6c340cb38f0dcf1cc5ec63c3334731fbd8f0cc51cc3e363c7314b38f0dcf1cc5ec63c3334731fbd8f0cc51cc3e363c7314b38f0dcf1cc5ec63c3334731fbd8f0cc51cc3e363c7314b38f0dcf1cc5ec63c333473133c486e2a9d079614d40b90a1246b11d009e8fe3e7294d183c6aca31e6cb20ffb1637d1cd533d96fe75060d7fd63d05dcae0fe75c8413d73c0afac5be60fc176f0cc9ed9c6ac782a755e581350ae9284516c0781e793f8798a13068f9ad2b5639f38d6c7513d93edd8a7815df74f40772983b1faa9837ae6805f59b7cc7f0adb21db9815cf709d17d604941b4ec228b643c0e320ee923cf9068fcc7f42e05bcd57e97c9efe8fdbab0a1819b6577e0368d6c6e069636876347dabfa8fd5f9e3f47fdc5e638191617bb56900cdda1a3c6d0dcd8ea66fa5c5389d3f5effc7ed350e1819b6575bb73cc50983474de9ce373e059e6fc7cf93bc8efb34039e6f03cfb7e2e7297254cf42b5deef007b5ceb555a7d6668f5a9a1553e944186cf1ce897037e65dd322ffe3cb3678e62c6b650581350ee131246b17d0b785cb41baaee57e875c9fa5b84e90727d6f875717f0def2db4d4eb150ef1970b65ce6e57c3f613cd9607bfcb7653f53968d81cbdf35664bbcf2bf3e22f2fb05febbbba871a75efe120f01cb46876c0a2d97e478c070c4699df0f8cb6fbbc071cf144dd77167fd8661c24d50cdf03fe08785c9d1747c599eb7d2ed3f3cb8f2c3cdfc4c75388b181be5cc42ab66d75a9bb6ddf89b1ee45f80c0b7d39d80792c7a90e7a5db27e752cf8af139d6a5e8aed831ca73a1875ce8532ff7d4e0ddbff4d739c6a161c7e5fb840dba58cfcfe8db69beb28d0eb96f9eefa3fc689d8fc31b0f673c4ee86966c9ae1bef5b145c71e16ee1e04dc188f0db1ada3ee7de0b6ee61e8c8a6196eeb4f2c3af6b470f724e066dcaf7b1a3ab26976a4fdba9f85bb1f0137e37eddcfd0914db323edd7fd2ddcfd09b819f7ebfe868e6c9a1d69bf1e60e11e40c0cdb85f0f307464d3ec48fbf5400bf740026ec6fd7aa0a1239b6647daaf0759b807117033eed7830c1dd9343bd27e3dd8c23d98809b71bf1e1cd4d6914db323edd7e516ee72026ec6fdbadcd0914db323edd71516ee0a026ec6fdbac2d0914db323edd79516ee4a026ec6fdbad2d0914db323edd7c32ddcc309b819f7ebe1868e6c9a1d69bfaeb27057117033eed755868e6c9a1d69bf1e6be11e4bc0cdb85f8f357464d3ec48fbf5380bf738026ec6fd7a9ca1239b66b6fdda51ffb28cfb217fec549fd4f8b399bc87857d495cc494a3382874d4d724d90f79bfa1d5c78656f85dff03a09fab3e5951fdc6c49f67f6cc9ed9337b66cfec993db367f6cc9ed9337b66cf2c653cb367f6cc9ed9337b66cfcccb8cef79e2f31529d710ef00d785516cf84ccac57d7e55f72bf5ba64fd2dc274fbc9357ee37f6e519c7c0e20facbfb98571a75ce85323bceae61ebabd9f0f9223e17b56dcb03b1d7a16eef9ce37bfaf82ce8683eeffcc8a2d97e8b66fb1c319a6d86ccef0346d16f3ff0b8da1f0f183ca66fdbbbe16c9a45b5b3aee23e2ace6cbe0b62f35d3cd4cdb7108a0bd537da8e090e6f4fa40eb8efba88c34cbf0980fb8583e7ee45aedeff5775da67d4e9a051a77c287331d4739f837ad675df92e96ae071d51e05064f60d147a666643c4f92f17426e3194bc633948ce702329e7bc8784e23e3b9898ce718329e5e643c93c9788ac9781e26e31944c6d38e8ce74e329e13c978ae25e3c925e3b9828ce769329eae643ce3c9788691f15c44c673888ce772329efbc878ce20e3b9858c2741c65346c6f318194f2919cf68329ec1643ce792f1f425e339998ce77a329e96643ccf92f17427e39948c6732919cf43643c9790f11492f1dc4fc6731619cf6d643cc791f1b421e3b98a8ce709329e4e643c55643ce5643ce793f1f423e339958ce74a329e1bc9785a93f1f424e379848ca7888c670419cf03643ce790f1dc41c6730219cf35643ccdc9789e22e3e942c6338e8ca73d194f0519cf85643cfdc9784e27e3b9998ce758329ede643c8f92f19490f18c22e379908ca7808ce72e329e93c878ae23e36941c6e3fa3dc04c799e21e3e946c633818ca7928ce762329e01643c6792f1dc4ac69347c6934fc6d3818ca70f19cfe3643c1dc978c690f10c21e3398f8ce76e329e53c8786e20e36945c6d3838c671219cf70329e81643c6793f15c46c6733b19cff1643c6dc97872087812c1e1df62c2ef7f1d04db3e9dc76f0b36b3ac4f9e0b4b79751cbab5e0f07537b3ac7bbf850175da1bd4d4a54ce70bffb529a913fa2a8379f197071cfb4978da92f11c4fc6733b19cf65643c6793f10c24e3194ec633898ca707194f2b329e1bc8784e21e3b99b8ce73c329e21643c63c8783a92f13c4ec6d3878ca703194f3e194f1e19cfad643c6792f10c20e3b9988ca7928c6702194f37329e67c8783e22e36941c6731d19cf49643c7791f11490f13c48c6338a8ca7848ce751329ede643cc792f1dc4cc6733a194f7f329e0bc9782ac878da93f18c23e3e942c6f314194f73329e6bc8784e20e3b9838ce71c329e07c8784690f11491f13c42c6d3938ca73519cf8d643c5792f19c4ac6d38f8ce77c329e72329e2a329e4e643c4f90f15c45c6d3868ce738329edbc878ce22e3b99f8ca7908ce712329e87c8782e25e39948c6d39d8ce759329e96643cd793f19c4cc6d3978ce75c329ec1643ca3c9784ac9781e23e32923e34990f1dc42c6730619cf7d643c9793f11c22e3b9888c671819cf78329eae643c4f93f15c41c6934bc6732d19cf89643c7792f1b423e31944c6f330194f3119cf64329e5e643cc790f1dc44c6731a19cf3d643c1790f10c25e3194bc6d3998ce749329e66643c571b3cf8bb3ab796f7c3f6814d7e7f56375e6df4baa48c3c1351f796f6183655dfdd8eeabb27a899ca607e37d457d8f700cf1e473c7b0d1ed3771ee47b8066bb0c9b62dce9887197c128f33b8151f4db053cbb1cf1ec36784cdf7990ef099aed306c8a71bb23c61d06a3cc6f0746d16f07f0ec70c4b3d3e0317de741be1f68b6cdb029c6ad8e18b7198c32bf151845bf6dc0b3cd11cf7683c7f49d07f9fea0d987864d316e71c4f8a1c128f35b8051f4fb10783e74c4b3d5e0317de7417e0068f68161538c9b1d317e6030cafc666014fd3e009e0f1cf16c31784cdf79901f089a6d326c8a71a323c64d06a3cc6f0446d16f13f06c72c4b3d9e0317de7417e1068b6c1b029c6f58e1837188c32bf1e1845bf0dc0b3c111cf4683c7f49d07f9c1a0d93ac3a618d73a625c6730cafc5a6014fdd601cf3a473ceb0d1ed3771ee4cb41b335864d31ae76c4b8c66094f9d5c028faad019e358e78d61a3ca6ef3cc8578066ab0c9b625ce9887195c128f32b8151f45b053cab1cf1ac36784cdf7990af04cd561836c5b8dc11e30a8351e69703a3e8b702785638e25969f098bef3203f1c345b66d814e352478ccb0c46995f0a8ca2df32e059e68867b9c163face837c1568b6c4b029c6c58e1897188c32bf181845bf25c0b3c411cf5283c7f49d07f9b1a0d922c3a618173a625c6430cafc426014fd1601cf22473c8b0d1ed3771ee4c78166d5864d31beef88b1da6094f9f78151f4ab069e6a473c0b0d1ed3771ee4fb824d788bc0f69ece17836d81ce97806dbece9782ed5d9def08b67774be13d8ded6f9ce607b4be7bb80ed4d9def0ab63774be1bd85ed7f95e607b4de77b83ed559d2f03db2b3adf076cf374fe2ab0cdd5f9abc13647e7af01db6c9dbf166cb374fe3ab0cdd4f9ebc13643e76f00db749dbf116cd374fe26b04dd5f99bc1f6b2cedf02b69774fe56b0bda8f3b781ed059dbf1d6ccfebfc1d607b4ee7ef04db149dbf0b6c2375fe6eb0ddabf3f780ed539dbf0f6cdfd2f9fbc1f66d9d7f006cdfd1f907c1f699ce0f01db77757e28d8bea7f3c3c0f67d9d7f086c3fd0f91160fba1ce3f0cb61fe9fc28b0fd58e74783ed273a3f066c3fd5f9f160fb99ce4f00dbcf757e22d87ea1f393c0f64b9d7f046c9febfc64b0fd4ae71f05dbaf75fe31b0fd46e71f07db6f75fe09b07da1f34f82ed773aff14d8bed4f9a7c1f695ce3f03b6dfebfcb360fb83ce4bbba6dad93fea7c41106f3bfb75503315806ff1a7cafc49e75b196564d95c2853aa3fe8a39e71a86f994a3b2cedb2b2493bfc1ed8a41d5e00366987e7834ddae177c126edf03b609376f86db0493bfc16d8a41d7e136cd20ebf013669875f079bb4c3af81ad4ce75f059bb4c3af804ddae179609376782ed8a41d9e0336698767834ddae1596093767826d8a41d9e01366987a7834ddae169609376782ad8a41d7e196cd20ebf043669875f049bb4c32f804ddae1e7c126edf073609376780ad8647ff91a6cd2368f049bb4cdf7824ddae64fc1266df3b7c0266df3b7c1266df377c0266df3676093b6f9bb6093b6f97b6093b6f9fb6093b6f9076093b6f9876093b6f947601badf33f069bb4cd3f019bb4cd3f059bb4cd3f039bb4cd3f079bb4cdbf009bb4cdbf049bb4cd9f834ddae65f814ddae65f834ddae6df804ddae6df824ddae62fc0266df3efc0266df3976093b6f92bb03dabf3d256b7069b3c2b5653e1bf38e1383ccdc097309505f1b6fd389541fe19a8bb4cd3c878c692f1bc4ec6730119cf0a329ee5643ca791f17c40c6b3998ce718329e7d643c7bc9786693f1bc43c633888ca71d19cf89643cb9643c5790f15493f1bc4ac6731119cf21329ecbc978ce20e3d944c6b3918c671919cf52329e0419cf1e329edd643cef93f1cc24e3798b8c673019cfb9643c2793f1b424e3e94ec6732919cf3c329e4bc8789690f12c26e32924e3398b8c670319cf7a329e05643cc791f1b421e3d945c6b3938c673a19cfd7643c55643c6f90f19493f19c4fc6d38f8ce754329e2bc9785a93f1f424e39943c6b3888c672119cfbb643ce790f1ac23e3594bc6730219cf0e329eed643ccdc978a692f18c23e3798d8ca73d194f0519cf85643cfdc9784e27e339968c670a19cf2c329eb7c9787e4fc65340c6b3868c673519cf49643cdbc878b692f1b420e3f9888ce715329e4a329ef7c8780690f19c49c69347c6934fc6d3818c672419cf0c329e37c978ce23e35945c6b3928ce714329e0fc978b690f1b4d2ff59787a90f1cc25e3194ec6339f8c672019cfd9643c9791f11c4fc6d3968c27878027011c01d8e4f7e660fb4ae70f814dbed7f311d8bed4f96ab0fd4ee79f05db53165b330b9f307c053679d7fa69b0c9fd992fc126ef70fc0e6c725c14ff6abe6fc1e1fccd6019f1d3dcc28ffe7e67e1923c6e6f59a62c88777ba3afb2e0f0ef29e501c7d3243c6dc9788e27e3b98c8ce76c329e81643cf3c9788693f1cc25e3e941c6d38a8c670b19cf87643ca790f1ac24e35945c6731e19cf9b643c33c8784692f17420e3c927e3c923e339938c670019cf7b643c95643caf90f17c44c6d3828c672b19cf36329e93c8785693f1ac21e32920e3f93d19cfdb643cb3c878a690f11c4bc6733a194f7f329e0bc9782ac878da93f1bc46c6338e8c672a194f73329eed643c3bc8784e20e3594bc6b38e8ce71c329e77c9781692f12c22e39943c6d3938ca73519cf95643ca792f1f423e3399f8ca79c8ce70d329e2a329eafc978a693f1ec24e3d945c6d3868ce738329e05643cebc9783690f19c45c65348c6b3988c670919cf25643cf3c8782e25e3e94ec6d3928ce764329e73c9780693f1bc45c633938ce77d329edd643c7bc87812643c4bc9789691f16c24e3d944c6730619cfe5643c87c8782e22e379958ca79a8ce70a329e5c329e13c978da91f10c22e379878c673619cf5e329e7d643cc790f16c26e3f9808ce734329ee5643c2bc8782e20e3799d8c672c19cf34329e66169e438e78e45829eb96f94304bed57bb8722f7e9ffe9f80df71fce66a478c870c4699af0646b1ed059eee8e78761b3cbb2d5a1c2ddf4a0bf9f6c71efd3f01bfe3f70a5dc554778351e66d31b51b787a38e2d969f0ecb46871b47c2b2da4efa3f42149c0ef381e9eab98ea6130cabc2da6703cd79e8e78b61b3cdb2d5a1c2ddf4a0be96b287df813f03b8e7fe92aa67a1a8c326f8b291cafab9f239ead06cf568b1647cbb7d242de3d93779613f03b8e27e42aa6fa198c326f8b291c1fa2bf239e2d06cf168b1647cbb7d242be2521df444ac0eff87d7f5731d5df6094795b4ce1f7910738e2d96cf06cb66871b47c2b2de45b7572cd9e80dff1fbb6ae626a80c128f3b698da0c3c031df16c3478365ab4385abe951683745e9ec125e0f741c0e82aa6061a8c326f8ba98dc033c811cf7a8367bd458ba3e55b693158e7a54f66027e1f0c8cae626a90c128f3b6985a0f3c831df1ac3578d65ab4385abe9516e53a2fef0c26e0f77260741553830d4699b7c5148ebf5bee8867b5c1b3daa2c5d1f2adb49077efd7e8ff09f81dc7e31cec88b1dc6094f9c1c028361cefadc211cf4a8367a5458ba3e55b6921dfd2926f3026e0771c1fcb554c55188c326f8b291cefa4d211cf728367b9458ba3e55b69315ce757e8ff09f87d3830ba8aa94a8351e66d31b51c78963be2596af02c25f2adb49077e1a40f5b027eaf02c6158e18a3626a05308a6d29f02c75c4b3d8e0594ce45b6921cf72e49d8b04fc3e16189739628c8aa965c028b6c5c033d611cf428367a1458ba3e55b6921df8e59a4ff27e0771caf7db123c6b106a3cc2f0646b12d049e858e78a2eee13584efa8fb510de13beade4a43f88eba4fd010bea3eeb13784efa8ebb786f01d752dd210bea3ee333484efa873fa86f01df57cbb217c473dab6d08df51cf1d1bfbfeed8f254deb587234dbb5a67a2cf1ed39677b3e2e7edfc589a0f6358d9a728cf932c8e3f5cb22075a38aa67215e137e13e37a6dd7f00b0dadf2a10c5ea3babafe1b67f0c8bcf8cb46668c8b9cf87c1726c087bca3ac6c72afe53db0c93d8e0560937b20f3c126f7d0de059bdccf7a076c72bfeb6db00dd7f99160937b97d81f49ee6d6e075bb9ce633f98c13abf156cf29c08fb5fc8b3be2d6093e7b5f8dc5f9eb96f069bf49bc0e7cdd2f76523d8a4ff123ee7943e68ebc126fd08f1f95ab5ceaf059b8c2981cf75bed4f9d560fb4ae7f179828cd5b9126c4feafc14b07da1f35f83ed099d5f08b6dfea3cdef3795ce7c782ed373aff16d87eadf36f82ed319d7f036c8feafc3eb0fd4ae7f7826db2ce63ffd0cf757e37d81ed179ec97f84b9ddf09b65fe8fceb609ba4f3af816da2cebf0ab69febfc2b609ba0f3f3c0f6339d9f0bb6f13a3f076c3fd5f9d960fb89cecf02db189d9f09b61febfc0cb08dd6f9e9601ba5f3d3c0f6239d9f0ab68775fef760fba1ce8f035b339d5f0c36f97e32ded395771697824dc629c17bf5f2ad922ab0c9f87bcbc1d65ae7f1b98cbc97341c6cf26dfb4ab0c9fbff1560933192cac126e3380d069b7c0b6c10d8e47b6503c12663960e009b8cabda1f6cf2ede27e6093f7297b824dc608e90136f98e4a77b0c9d8773826b07cefb21a6cf24e108e132cdfddff126cf26ef9576093f19b704c60f9c6d59360937149bf00db393aff04d8e47dcddf82ad40e71f07dbb93aff1bb09da7f3bf069b7cbff231b0c93b358f824dbea3ff2bb0c9bbd993c176b1ce7f0eb64b74fe11b0c977887e0936192bf617606baff393c026efcc4f04db153aff73b0c9586713c026df57fd19d8e41b5fe3c156a4f33f055bb1ceff046c253a3f066ca53aff63b075d4f9d160eba4f3a3c0d659e77f04b62e3aff30d8baeabcb4336a7f56fbf9413d5f16c4775ea6fc7d1cd49ed25d1b0803f2c479ae9d0f3ce8eb40ec752f4e9ed7cb7edf4caf5762e800f8de17bbefd435c57ebdae167abdfb0cdfb950e653dd88a8e5f6c0ef655007590eafb165ddb2cc95b0ec5e63dd6d747df73baaef3e8349b8f7039394f9ecec9ab24fe8c6b2352c13235bf2fa58622d000d712a83bc30b8d1aab810cf7bebc2b31f78e2df4f52d7eb2e6202f7adb8afd7cd7b4c66ace543997da0df5e07fae1be2eeb9679f1e7993db367f6cc9ed9337b66cfec993db367f6cc9ed9337b66cfec993db367f6cc9e999f59f1c8f3047cae2ce50e92308aed00f0ec8f9fa7109fc3cafad5739d07e0b9ce81d8fdd67ebed752afb7d0a8732e9459754e0ddb109dcf83df65bb456dcb7db1d721fdb6147f79509ffdc0e3605b26790e183ca6ef3c8b3e4ab3bd16cdf6386234db0c99df038cfb747e2ff0b8da1ff7193ca66f6c33f6936a16d5cebae897902ece6c7d100a62f35d3cd4d5735dd5674af5e5308f5f070d4db10f84d8f039781e2cf389fe9f007d3e017d8e661b60f64bc076ea6360dc173b6371ad67c0d2f65f69688a7d205ed4da4a1f88f8db81e24297c708d947cdbe15585729331d8e7333751efb011d8475bd6bf95da61c63be0cf2d8a6ee8abfcec9ed2bfd5765fbeeb2f8de01ac31f9aef52e478e4ee247ecb9907fe79c9ab2524ef410ad851dc7ad427673b98f8de5f2a1cc6e4bfdcb8278ebbfcbe0d96530abd8990371f62e9cebb96a937647687425682465f09cd7419f226b1b291ce24f9591eddfca2883e7a7526631b451aa2ed2ce4b3db11f131e035c9d2f1c34ea27f378be603ba731eba8e2e3f6936b785d5f0b340bec5ab3f4f5db0ced45dc7dfd36430cd9ce4b65fd85b07ee16a15441f5ba4cc56e338eae27a12b7a5a9e77e6092323ba11dfacf7a5cd71dad6bf4a8ebbadd0e78f05a43a674c7773cc6b8685f1cd5b3d076ecda6bd4291fca5c0cf574701e93f69dd45de0dbc536472de41c6a9fa1452e94f9aed17644e928ebc0fb006eeb526c3d1f2cb4d445cafcd868a7763a6072b9ddf03c4badf780a5ae52e617d0fe7d0ee7f3fbf4efd896fec5f2bb4ce9da03fca6fcb6f8eb9cdcbef27ea36cdf6d16df1f026b4cbe6b7d9342cef7c58fd87321ff67387e4b39d143b41676b58fc8fb9dc86e2eb7cf582e1fca6cb7d4bf2c88b7fedb0c9e6d06b38a9ddf409cfd05cef75db59bdb23342a048da40c3e2b30efb7e0bd133cee37d47581cc7f048c62db05fafea7d3fbe529b68f0c36f37eb9ed7cb0d0e0c7f3c1ff0ded6cc252d6fd7380d4b90dd64bea1118750d8cba3a3a7f2dcd31f42c033f1dc0be4fe74567f90dcf71a54c4ebbd47f77f7af6adfc7166ea9073eafdb6370ef3574c57b512d815bc5bd796d81e7e98eaf694bf15ccc3c1fc2eb30299307ecb6f3b84396ba98c7e966c1e1d782df1865f13a3bdd7266fe236319bc6770c0c2646bfb627b2fa7a8b0d0e4b7b57b070d669baeb21f60ccc9bacc7d05cf87a4cc99b0dd1296b2aa4dfaaf136bf491ed88f7da6df7595c1d2fa2eeb3883fc5687b67d2c5338ca6f86e5aebd8d6dbb5dcf69c8dbd3f436b231f8fefe20a3c56a4d3628f85c7d53dcd282df6587cc7a745a7a1b676cea6c56e0b8fab6bcc282d765b7cc7a845a5edde824d8b5d161e57d71a515aecb2f88e4f8bceb5ee6ba4d362a78527fe7b1ae9b5c067629930ef26606e6de4e3f15d5a6e7b7667d3628785c7d5b3bb282d76587cc7a7455127db35bb4d8bed169eed0dacc5768beff8b4e8d2d5764fc5a6c5360b8f83fb6b69b5d866f11d635c0cc3fb6be9b4d86ae1d9dac05a6cb5f88ef1fcb053ba7b86a8c587161e57f7fea2b4f8d0e23b462d8628df5beaa0c5160bcf9606d6628bc5777c5a947754be3fa883161f58783e68602d3eb0f88e4f8b215d94efcd75d062b3856773036bb1d9e23bc66ba8645c6caa83169b2c3c9b1a588b4d16dff16951913cd7da58072d365a783636b0161b2dbee3d3a230794cdd50072d3658783634b0161b2cbe638c8be4f5e4fa3a68b1dec2b3be81b5586ff11de371241917ebeaa0c53a0bcfba06d6629dc5777c5a5426ef3fadad83166b2d3c6b1b588bb516df31de7349c6c59a3a68b1c6c2b3a681b55863f11d9f1625c963eaea3a68b1dac2b3ba81b5586df11d9f16c392cfc456d5418b55169e550dacc52a8bef18cf3b93edc5ca3a68b1d2c2b3b281b55869f11de37967f2fec58a3a68b1c2c2b3a281b55861f11d63db993cef5c5e072d965b785c8d1119a5856d7cca18cf3b935a2cab8316cb2c3caec6368cd26299c5778ce79dc9e3c8d23a68b1d4c2e36a2cca282d6ce360c61817c9b673491db45862e159d2c05a2cb1f88ef1be56b2ed5c5c072d165b785c8dcd11a5c5628bef18af4792f7f816d5418b45169e450dacc5228bef189f1525cfc117d6418b85169e850dacc542f0bd3f76dfa9fedce243fa625d6168910b65be6df4c58ad251d681efd0625daa63af4baa5fd9fb1175a986ba48991f187df9de77c0e4a8aec998794faf4bfaa67f6ca9ab94f969bb9ab23fd7f9046c9343b0ae3f5a7e9729c7982f83bce8a7ea3c3ffe3a276355c60192ed3bdfe2fb1d608dc97711faced149fc883d17f25fb7ab292be5440fd15ad8d53eb240e791dd5c6ea1b15c3e945960a97f59106ffde71b3cf30de6e47b0f106712476edaae14d382088dae008da40cf6d93be488e763834738c45f4e70f8bba8524696c57751ff6ef4db957e9052cfa83e92ef39aa5f541f49f117f52eaa5947151f3f80be9f322e888c19a26c32064809aca7b3615375ede2a8aee24bd62df35d8051c624e9dcf08cc57565ec64302a9e6e0e34c37156644a77bce8063c5d1df038aa67f238d4dda85317a34ef95006df6deceea09e39e057d62df3ddc1b78b6d8e5ac831f952438b5c28935790fa2fe78f513aca3a54fc76b6d4c5958e9d0c9e4e16dfbd1ceb28eb9636b15703f8ee61f8ee68f856fb36c6989ad2eddb3d80b9a70366b5dedef1afb710cf19259ec54f47a8531fd020ae3ae1bae41cb38fa16d2ee4cf2fa8292be5a4ac1c3b855ded47b22d91dd5cae9bb15c3e94e965a97f59106ffd7b1b3cbd0d6675de705a410d8783fd211903bd0c0e99ef08daf58ed0ae17682765f0d8dbc991763d0d1e99ef043c727ed51d6c729e22fc09f8bda401b8cd76afbb855b6c381e61270b63c7f8198bd31d173a02a3d87a024f0f479a99dbfa52431f3c27686594916573a14c9782d47f7957cb2cabf6bb73736aead55cdb637b6f4db7e92d1de885e38106a04f6068289330b40e6ac60c8d93e7d8a0664cd00913abc60f7968d85dc3528f3d052dd7c0c4ff39966a34031be69b5b6c41507be8d35cb0c9d0a72dc0d6cc9005875c95f23274a20bb9500f5977aec1d91a58e2f48dc3c6ca942e745a018f8b5056a12343c7ead0b977fc8889c3303e5a189cf5891df55bf334e5a2d6257190eba0eec824eb9679f1a7f4c9d7f9b143868eec33fea149a3878d99380161cd9d0bf3398608e67fdb321824b833c97a5a18e21c1bbf38a53846b1c917803f9984a17550338e718c3cc94095b186870e1935ea8e49e5a3460cbd6ed298a11347548d41455b1bca45a92dbfb7049bada9c3b26ac2dd17976d65b1d9261cd5b935d8a4053f066cc2732cd89a435eca9b5bc6c93e7231ac5fc25afda6c469a12bde2aa80901392ca9f645ed43ea33aaea74400d2dad8692569b53ddb1534343abafc8a9a19fd550cf6a68673594b31aba590dd5ac86663e3b480dbdacee5e1604a9a194cf0b5243255f10a48642be08f8be0dcc9704a9d30f359471fb203554b1ba7da85e1f579f5a53efb7abd3587579ac4efdd4a58e3a0d53a75fea345bdd4250b793d4a98d3a6d54a744ea34469d96f7d65af709d35561ba3a4cd784e9da305d17a6ebc37443986e0cd34d61ba394cb784e9d630dd16a6dbc3744798ee0cd35d61ea1ba6bb83d470daf784e9de2035dcf67d416a28eefb83d430dd0f04a921bc1f0c52c37b0f0952437f0f0d52c3820f0b5243863f14a486131f11a4862a1e19a486361e1da4864756c3948f0d5243a2aba196d5b0cc6a086735b4b31a1a5a0d23ad869c564351aba1ac9f085243643f15a6a783d410dacf86694a989e0bd3f3617a214c2f86e9a530bd1ca4866557c3b5ab61dc6704a961df6705a961e2d5f0f16a587935dcbc1a865e0d4faf86ad57c3d9bf11a637c3f45698de0e528f05d4e310f59840dd8257b788d5639aea2075fb7a51907accac1ebbab6e08aa5b86eaa6b22248756352ddba543737d5ed4f758354dd42553759d56d5875a356ddca55377bf5da817a0d43bd96a25ed351af2da9d7b8d46b6dea353ff5aaa67af551bdcaab5e6dde17a46e4d1f08528f2bd5ed6a755b5adda257b7d03f0dd3b782544c7e274c9f85e9bb61fa5e98be1fa61f04a921a3d5f0d26a786a3594b51ae25a0d87ad86ce56436fab21b93f0f52437daba1c27f13a4861bff224cbf0b52439e7f15a486bbff4398be0ed31fc3f4a730fd394c7f09d35fc3f46f61faf730fd2d4c7f0fd37f84e91f41cdb0e6d89014e8d6e75c3d3f64e2c461a3c74e2c985855307ad2a88923c68e7aac60f28889c30baa1e1936be7254d5645cf8b77a611993bdcff8f1431e2b1831a662d8a3055593261654551694574d1a5351eb40fafff442671dee71484545b4b3bce6ff02e9f1cdebe7b49d5e4e46bbbf317dddce6b5e0f412ea9cf42b7d4b34277eb23985cf2f54d9d0f164c185535b1a0b0604cf8373cf0564d1e56d1a1007f9b108a3c6162c1848943c64f2ca81c5f35baa0a803aeb7f0d87a5462deb16e604a4eaf9f389f9c9dfa5faf107be19c7a28b0e89cfa916e3ae75f20fdb09e4e3fab4f0d7f549f85feab9e84817ef0699165c2a4f289e3870c9d18bd708b7f65e144bb7a54f38c76f5abe6b7eae3ecfbf559e86ff5244c14d4c359e782ba3b0bfe07c2beb575b80206009b2d6c6f000000275e1f8b08000000000000ffed9d67741cc791c76701100ccb2508e64c28514c00178b44800994c41c642a8b4a044950224512140925cbb224cb39e71c64fb9c73b6efcebe6cdff97c3e873b6739e7f8e5fceeeedd7b7a573de832fe68f5acb0f014d483ad79afb83d85dea95fd554f7cc76f70c73d1d0f607929c2dd7925c103d7ee3bff7dacfe29fb7b5a678aca224672e239c3519e1accd08675d4638276584b33e239c9333c23925239c5353e4346c35d1c82d6dde6902714d9b319fb1984ecf404c0b198be98c0cc4b421ca461f3533239c8d19e19c9511ced919e19c9311ceb919e19c9711cef919e15c9011ce8519e15c9411cec519e15c9211cea519e15c9611cee519e16cca08e77919e13c3f239c176484f3c28c705e9422e71ae05c613f2fb69f2bede72afbb9da7ef277d6dacf66eb639ddd6f215967d8485a9dbf9548da48da493a9cbf75927491ac27e9b67f6bb27feb21d940b2916413c966922d360e5b492e21b994e432926d24db497690ec24d945b29b640fc95e927d24fb492e27790ac901922b48ae24b98ae46a926b48ae25b98ee47a87e520c90d243792dc447233c92d248748fa480e931c21394ad24f728ce45692db488e939c20b99de424c92992d32403246748ee20394b728e6490e44e92bb48ee26b987e45e27664f25b98fe46924f73b9c4f277980e4419287489e41f230c933499e45f26c92e7903c97e47924cf277901c90b495e44f262929790bc94e465242f277905c92b495e45f26a92d790bc96e47524af277903c91b49de6459b821bc99e42d248f90bc95e46d246f27f90b927790bc93e45d24ef26790fc97b49de47f27e920f907c90e443241f26f908c947493e46f271924f907c92e453249f26f90cc95f92fc15c95f937c96e473247f43f2b7247f47f2f724ff40f28f24ff44f279922f90fc33c9bf907c91e45f49be44f26f4eccbf4cf2ef245f21f9aad57dcd7e7eddd6e571b1ff20f94f5bfe86fdfca6fdfc96fdfcb6f39def907cd7d17d8fe45147f77d921fd8f20fede78fece78fede74fece74fede7cfece7cfede72fece72fede7afece7afede76fece76fede7efece7efeda799537d68ce50794a34bcf54629f551edc78a664e8583bf221ab99958d4dabff16793d5d7d97dfee4d84db2fb931c7dbdddaf778e33c5ee4f71f48d76bfd1d1cfb6fbb31dfd5cbb3fd7d1cfb7fbf31dfd8576ff42d0e7231873b57aa3abb5aa1ce8385f6b4037c9ea6a4157cf8703dd64ab9b043a3ebff5a09b6a75934137cdeaa6802e6f7553399624d3adae374a2b578a7de6b885b48f6be7a166a4cf7bc41cb741887766fabcfde6b88d02bc263f66d963cd84bc996d758da0b3dd4d340b7473ad6e36e8e659dd1cd0cdb7bab9a05b6075f340b7d0eae6836e91d52d00dd62ab5b08ba2556b708744bad6e31e89659dd12d02db7baa5a06bb2ba65a03bcfea9683ee7cab6b021daf71390f74175addf9a0bbc8ea2e001df7b517828eef0d2fb23ad34f4cc9c177ac9efba8f83bdc3f836e25f7cda05bc5fd32e856739f0cba35609b756ba15f615db3d5711f65fed663cbbd515a6da214b7890d691f978e6c8ebb29fde3c6f3769ba3e1b8f6829d0d10ab2db69ce2daa056b49db3c276585f07e55d5097eb713cf83ac3ece67ab2d196b794f95e8ff3bd02d4d9e8f1bf374ad7ff4d0ecf26877912f82f93b36d25cdd9516f15e7ecb550d7cd3dbee7998839bb17380472b6537376d45bc539db0f75dddce3fbde8998b30781432067fb6472b654d49c1d1a238b227feef16f9f8998b3b70147fa39dba1393bfaade29c7d08eabab9c7bf7f2762cede051ce9e76c579fde1b8c7aab38675f0275dddce3b1988998b3cf040e819cedd77e76d45bc539fb26a8ebe61e8f0b4ec49c7d3970a49fb3dd4239dba6391b0dcd7746913ff7788c7a22e6ec23c0917ece1ed1f1d9d16f15e7ec67a0ae9b7b3c5f321173f683b66ce619be66e7199680eeeb56b71478d3cfeda3ed42b95dd2dc1e5a071245fe1ce5b9bb8998db9fb36593c7df80b507acfba6d59d07ba6f59ddf9a0fbb6d55d007e09b4813e6d03a3de2a6e03df85ba6e2ef33cf2446c035f010e819c3da2393beaade29cfd15d475738fd7344cc49cfd3e7008e46cbfe6eca8b78a73f6bfa1ae9b7b2b6d7922e62caf2b35f70b3fb4f70bab41f723ab5b03ba1f5bdd5ad0fdc4ea9a41f753ab6b01ddcfac6e1de87e6e7545d0fdc2ea5a41f74bab2b81ee5756d706ba5f5b5d3be87e63751da0fbadd57582ee7756d705badf5bdd7ad0fdc1eabaadcecc77f1daab2f5a9d39b71c8fde28bd731bafb78a466e3967bf17cacdb23cc54234f25904b6b52e7d5b6dc6f79668f4beaf039ea280ef79b0311a9e22f0b4a6cf13af3b2da57fdcf81cb73831cd83ad16f0ab4dc0af1cd8e263f33edb2b800efb92360f637bfa8ca51cd8e263f37e3b30b20efb36bec670fb317d73536e9857a02dc5d767b4d70b1c6caf0eea2c9d335cf742cb361dfece7dc0742863dfdfeae8847235ce15b6c5c7e6fd1230b28fade3cf581a2d63d16194ea3772608b8fedda9eee898f8959bb27661d428ced0e23ef770023c7af7dfc194ba36574fb05a13ea975b47d12c7a575fc6336aaf35a001ddeff7578183bd3678ccf6b87c3c8fb9dc0c8ba36e091ba1e26b5d7506c4bdc87603ef3358baf3f6caf0eea74d50ed7dd0bd753813eb454e9bd29f6e9e99fa75211af67a3e1113e77ad42f958c4bef3b128dd5c73db7cab132b6cf3d8974bf593497d39db53666556666556666556666556666556666556666556666556666556666556e6f09993e6e57ceb199e4c46d6958047629c3f7e47953d16ce013d0af33ae9cf5b948a3857cfeb1857393ed7419dffcb0db3fdc8b34e02e7ced7393aa1754af1b9c4754abdb0cff670dd06ae9b12587b12f3ac75785cdbd33df109711d49486b3492d6698514b302e8703d5c8b104f529eb5786c37a566bb7444a6ed948ae67d40e69d7adc9fb86d04d7bead7174a64feaa91df65b22072a9d77c6eb0697d39cc7c57c435be9afb7298d589f50138dbc56e03d85c01a9511f3d5bc36a2d3b15d0775a6d6447f3a37ebe1efbdd1e3d708993a5dceb1f93babe0bb5dceb11be4fc2ddb1f76023797eb1ddf9a819bebcca819f6f1b3b62c743f53c2f5b311f0468e4fbce1fa8cf4eff786d68bb455c0d3013c126bd784ee6b8b988f69af17e97262e5bb5fe63a9d10bf2e81f8955bb3c6f694599995599995599995599995599995599995599995599995599995599995397c667cff05b3e233d2a54018c7698d4d3c9fc1ef32c279b1b7d40cdb959e03e439a7d58ecff88cf26f6b86d9de6ecbf88e00dff3ee782ea5e6d692ce25db9b1e3dfe397da17339ea773f747862d6e589d97a2146b7cfe0fdf5c0c8f1eb021ea9f6d8e9f0b8b6b1cfe808346649fdacd4fa95a43cf3ad53684acdf6d07a1189795d5e2fe25ebf4a4e4c719d04eb701e1cdfad12f2fb5fdcb50bd84fe11aadf4fbcdd288396077ad20dbc375125fb0b1e57512e9f703a5a2e43582db28af0969f3f8ca75be04d7b92fdb32ae152ac1b11ef5fc9db7726b12b04f4dfd1d9cc5a1397e7e77259fdf1e8fed8dc09a92ed56b49db3c276585f07e5efd50cd7e57a1c0f8e35b39b36c2ef324476f77badcef70a50a7dbe37f6f94aeff3d0e4f8fc36c72e7ab90678fc2bd9e549fd49d10a3551023ae83f7bc52d72f77cdb6bb5619fbd1c94e1dfe6e1dd4f919f45195bc2b4aea7e21e91a80f70bee7561346bc7ab7d3de01fa1bf487b3de01f21877cf7a57cfcd5707ce69a1c255f5bb8ceff3ad75181f57aa37aef95efb71ff3e27a43aef318f45545bb2e37e9778cef390ba9df0d49cf7db03dbca7aac477ec17d2be36623e220be6f29faed136d69c8f5d09dceb3cdfcd277c9763c5ebcbf177b21b3f13876ef84e6f2a7118ea6f7a1c5fb84d75832f5ca7117c91b9671abaff4cdfd791f743dc07b57b7ce53af3e05d700b6c390fe709fbca8b3d7fe7addcfd27c7cff83cdeef5447db21bc537d45ed705df7dde81ceb4adfa9dee97c2fc477aa2f863cbb189eb590eaab3726c46835c488ebe0b38eeeefffa46bcc93f95e52b7dfc4ebe478b2b9e3b7befb13ae83f7d05ca703fad9bca7ae3b2ecdd79034d7a7e3f3406bc12e3e0fb456289e8568643c0b0e87a4ed06c776c338da6e746c378ea36d8db9c63ca4980bfcdf1363febf30f0ffaca8c900636d0618eb32c03829038cf519609c9c01c62919609c9a01c6691960cc03e393796d17884f29b0ffefa9ecbd06da16789f431c8be668f4b16891e5297bef83b605dea152f1ff3720fc7f61b58ef5ffc22ac0f766658071760618e76480716e0618e76580717e0618176480716106181765807171061897648071690618976580717906189b32c0785e0618cfcf00e3051960bc30038c176580718532a6c2b84696b114daffe39c8f46ae357b221ee1778fc6ef50f4bde754e2ffc6add477e1f70eb78ef53d7db8c642f6ff7afcf3de2528b186a2d2770996fbffb185184b6365945a4b8eeba847c383cfa1fa9e6f11602c8d9551ea19147c2672343cbeffab57f699a0a1988d85516acd58a56b1af159c14e4fcc04184b6365947aee009f891c0d8fefd9c55659c6d25819a5d6e7e6c1c66878ba2166eb3d3113602c8d9551e8f9b23866dd15f0e07358dd9e98093096c6ca68783608c5aca7029e0d10b31e4fcc4262449eb4df89dee3b125f1dc5ea5be3303324ecd00e3b40c30e23a0989feabdc3a891ed9f894c61a1fa9f3556e9d04da16784e248e053e17f044b1d824cb53769d04dade2c140b7c6ee38962b11978249e23c9838dd1f0304301be372b038cb333c03827038c7333c0382f038cf333c0b820038c0b33c0b828038c8b33c0b824038c4b33c0b82c038ccb33c088bf5505ee15cbfe7ed93cc16d27fd5699e8b6937e974c74db9ae79ae7d5605bf35cf3bc1a6c6b9e6b9e57836dcd73cdf36ab0ad79ae795e0db635cf35cfabc1b6e6b9e67948b6b330c6af8c138f11799ad2e329a2ef68ab3700df7b3d3c3921dfd1d6d6007c6786ac316ec900e3860c306a1c87d6208e85d1f05c22c4b3b5029e4b80e752219e4b2ae0b914782e4b9f27cea94b2be06186027c6f430618b7648051e3a8710c8951e3583d715446655446657c3218b3d0872b6326f2b1345646c3b32d7d9e38669755c0b30d62c6df6b95652c8d95d1f06c4f9f278ed9b60a78b643ccb6796226c0581a2ba3e1d9913e4f1cb3ed15f0ec80986df7c44c80b1345646c3b3337d9e38663b2ae0d90931dbe18999006369ac8c866757fa3c71cc7656c0b30b62b6d3133301c6d258190dcfeef479e298edaa806737c46c972766028ca5b1321a9e3de9f3c431db5d01cf1e88d96e4fcc04184b6365343c7bd3e78963b6a7029ebd10b33d9e98093096c6ca6878f6a5cf13c76c6f053cfb20667b3d310b9571430618b7648051388ea5b1321a9efd423cfb2ae0d90f3c970bf1ecaf80e772e0794afa3c714e5d5e010f3314e07b1b32c0b825038c1a478d63488c1ac7ea89a3322aa33256c6d89b01463dd7ca182aa3c0efabb2cfd05c3ec16d3738b61baac476d2333413ddb6e6b9e67935d8d63cd73caf06db9ae79ae7d5605bf35cf3bc1a6c6b9e6b9e57836dcd73cdf36ab0ad79ae795e0db635cf35cfabc1b6e6b9e67935d8d63cd73caf06db9ae79ae7d5605bf35cf3bc1a6c6b9e6b9e57836dcd73cdf36ab0ad79ae795e0db635cf35cfabc1b6e6b9e67935d8d63cd73caf06db9ae79ae721d93e90beed52a5cfb01e001e89676a85fc2c9ae35e618ff5588af133b1bad289d5e54eac0a50e70a88df9502f1cb815d3e36efb3bd4a992f0e8059c87669061d632af8cf36b638f130f6af12f23da9afbf6a82db4eeaeb27baeda4be7ea2dbd63cd73caf06db9ae79ae7d5605bf35cf33c14db58ae8b86efdbf9fd4ae61857dbf224bb8facfc3daeb369f2d06743a46d48c2b6b621bd5654836dcd73cdf36ab0ad79ae795e0db635cfc3ccf36bd2b71dcf8de1ef0bb3959b1bbb0678ae168885909f45e3d3b58e4f57393e15a00ebeb3f65a013f7360978fcdfbd7c279c81ab3e1d96ccbcc9a877a9b036164ddd5b23c71fbda1c8ddccab5af6b8147a01db40af919b7afeb1c9f367be2ce753057af13f0d3d77678ff3a380f5963363c5b6d9959f3506f6b208cacbb4696276e5f5ba3915bb9f6751df048f43f427ec6edeb7ac7a7ad9eb8731dccd5eb05fcf4b51ddebf1ece43d6980dcf25b6ccac79a87749208cacbb5696a73d0f3ef356ae7d5d0f3c12fd8f909f71fb3ae8f8748927ee5c0773f5a0809fbeb6c3fb07e13c28b332fb980d0fff9ff2cc9a877a9706c2c8baeb4479da8b79f099b772fdd841e091e8e785e21ef76337383e5dea893bd7c15cbd41c04f5fdbe1fd1be03c54c2bc2583cc1a678d7312b3c659e39cc4ac71d63827316b9c35ce49cc1a678d7312b3c659e39cc4ac71d63827316b9c35ce49cc1a678d7312b3c659e39cc4ac71d63827316b9c35ce49cc1a678d7312b3c659e39cc4ac71d63827316b9c35ce49cc1a678d7312b3c659e39cc4ac71d63827316b9c35ce49cc1ae7b1311b9ecb6c9959f350efb240185977bd2c4ffcfcce65d1c82de7ecf742f906e03928101f213fe375ef373a3e5de6893bd7c1f675a3809fbeb6c3fb37c279a884794b069935ce6363363cdb6c9959f3506f5b208cac3b28cb13f763dba2915bb97eec46e091e8e785fc8cfbb19b1c9fb679e2ce75b07ddd24e0a7afedf0fe4d701e9459997dcc8667bb2d336b1eea6d0f8491753788f294e2e710b74723b772fdd84dc023d1cf0bc53deec76e767cdaee893bd7c15cbd59c04f5fdbe1fd9be13c54c2bc2583cc1a678d7312b3c659e39cc4ac71d63827316b9c35ce49cc1a678d7312b3c659e39cc4ac71d63827316b9c35ce49cc1a678d7312b3c6b97ae26c7876d832b3e6a1de8e40185977a3284f5b3cefb0231ab9959b77b8197824e66584e21ecf3bdce2f8b4c31377ae83edeb16013f7d6d87f76f81f330d199b764905973637c98353794398959734399939835379439895973439993983537943989597343999398353794398959734399939835379439895973439993983537943989597343999398353794398959734399939843c88d02c94e5b66d63cd4db190823eb6e92e589df7bb0331ab9955bb7730bf0dc2c101f213fe3753b871c9f767ae2ce75b07d1d12f0d3d77678ff109c8743caaccc1e66c3b3cb9699350ff57605c2c8ba9b6579e27e6c5734722bd78f1d021e897e5ec8cfb81feb737cdae5893bd7c15ced13f0d3d776789fed29b33227311b9eddb6ccac79a8b73b1046d6dd22cb13f763bba3915bb97eac0f780e09c447c8cfb81f3becf8b4db1377ae83b97a58c04f5fdbe1fdc3701e9459997dcc86678f2d336b1eeaed098491758764794a79f099b772fdd861e091e8e785fc8cfbb1238e4f7b3c71e73a98ab4704fcf4b51dde3f02e7216bcc8667af2d336b1eeaed0d8491757db23c71fbda1b8ddccab5af23c023d1ff08f919b7afa38e4f7b3d71e73a98ab4705fcf4b51dde3f0ae7216bcc86679f2d336b1eeaed0b849175876579e2f6b52f1ab9956b5f478147a2ff11f2336e5ffd8e4ffb3c71e73a98abfd027efada0eeff7c379c81ab3e1d96fcbcc9a877afb0361641df653bcd500e37e21c6c8618c9cf820cfb2c0780e04c6b320309e5981f14c0d8c6755603cb581f1ac0f8ca723309e52603ccb03e3591818cfecc078a605c6b336309ebac0785604c6b33a309e4581f1cc098c271f184f73603c9302e3e9098ca73b309e9581f17406c6d31618cfbac0781607c63337309e3581f14c0f8ca710184f4b603cf581f16c0c8c6749603cf302e39911184f43603c9303e3d914184f57603ced81f11403e3591a18cffcc0786606c6d31818cf94c0787201f0e4a3c7af63c8c3df0f80aec6f9aeb9be1c9e33fc779e37ae81ef1cb3e55acfb1fb41c7f3ccc73cdfc53849cd85a3ad5ed8677bd381e358203c5302e3690c8c6766603cf303e3591a184f31309ef6c078ba02e3d91418cfe4c0781a02e3991118cfbcc0789604c6b331309efac0785a02e32904c6333d309e3581f1cc0d8c6771603ceb02e3690b8ca733309e9581f17407c6d31318cfa4c0789a03e3c907c63327309e4581f1ac0e8c6745603c7581f1ac0d8c675a603cb303e3591818cff2c0784a81f17404c6b33e309edac0785605c63335309e5981f12c088ce740603ccb02e3a9f1f01c10e2497ab6f94020b605ce43d11cf756219f6eb3c7aab7c7657eb65707752eb0038f66fe03bfcb5ceefc3fb69ddb204652ef9528383cbc7f7482db6e706c375489ed46c7766395d8d63cd73caf06db9ae79ae7d5605bf35cf33c44db8fa567bb43df2f357a1e7d9f53791e7d9f53791e7d9f53791e7d9f53791e7d9f53791e7d9f53791e7d9f53799e1581f1e8fb9ccaf3e8fb9ccaf33407c63329301e7d9f53799e9581f1e8fb9ccaf3e8fb9ccaf3e8fb9ccaf34c0f8c47dfe7549ea73e309ed0dee714dafbe0f5fd52e5796604c6a3ef972acfa3ef972acfa3ef972acfa3ef972acfa3ef972acf3325309e5c003c4ff47e297c2fd46db67c1474bcbeb4dc7ba8f2709cdb40c7e3b97c0c73bd3a35e7f10c35f09de31eae5b3df6d8ce71cf77c723ee68ab17f6d91ebeafea78203c5302e3690c8c6766603cf303e3591a184f31309ef6c078ba02e3d91418cfe4c0781a02e3991118cfbcc0789604c67320309e8d81f1d407c6d312184f21309ee981f1ac098c676e603c8b03e35917184f5b603c9d81f1ac0c8ca73b309e9ec0782605c6d31c184f3e309e3981f12c0a8c6775603c2b02e3a90b8c676d603cd302e3991d18cfc2c0789607c6530a8ca723309ef581f1d406c6b32a309ea981f1cc0a8c6741603ccb02e3a9f1f048bd332ae9f9faf1785fd513d936fb6b212e66cbc3dfc7e339ae030e23efe3ba07e4659eb5423c49ef05581b806de33fff169d613ff3f0777c0e472aa7d63a8cbcefcb295cd7d82cc493f43e83e6006c9b58b4d832af01c8c3df5b80512aa79a1d46def7e554a32c4f7b1e7ce6addc5a236c7312e750c8cf22b6bf14dfa15134b1daefc4aac5895501ea8cc7baf4a4fe80ed29b33227311b1e9e4b6156bc9e8dc77366a361f45d5f0578e2fe715d34722bd73fee071e89eb87909f713f76c2f1699d27ee5c0773f584809fbeb6c3fb273cb69ba2746371fb286271bb87e7f6718e05dbab94f94006994388b3e1e1b588cc8aeb9b8b8130b26ead2c4fdc3f16a3915bb9fef176e091b87e08f919f709271d9f8a9eb8731d6c5f2705fcf4b51dde3f09e7a112e6131964d6388f8dd9f0f01c04b3e6a15e291046d6ed17e52915f3e0336fe5fab193c023d1cf0bc53deec74e393e953c71e73ad8be4e09f8e96b3bbc7f0ace83322bb3322bb3322bb3322bb3322bb3322bb3322bb3322bb3322bb3322bb33287cd6c78f8d95866cd43bdb640185977bb28cfd0bc435b34722b37ef700a7824e66584e21ecf3b9c767c6af3c49deb60ae9e16f0d3d77678ff349c07655666655666655666655666655666655666655666655666655666655666650e9bd9f0f03bdb99350ff5da036164dd49599ef8b9adf668e4566edee134f09c12888f909ff1bcc380e353bb27ee5c07737540c04f5fdbe1fd01380fcaaccc3e66c3c3ef6a63d63cd4eb08849175a7447986e64f3ba2915bb97e6c007824fa79a1b8c7fdd819c7a70e4fdcb90ee6ea19013f7d6d87f7cfc079a884f944069935ce1ae724668db3c6398959e3ac714e62d6386b9c939835ce1ae724668db3c6398959e3ac714e62d6386b9c939835ce1ae724668df3f830871067c3c3ff8720b3e6a15e67208cac3b2dcad316cf3b744623b772f30e678047625e4628eef1bcc31d8e4f9d9eb8731d6c5f7708f8e96b3bbc7f079c8789ce7c2283cc9a1be3c3acb9a1cc49cc9a1bca9cc4acb9a1cc49cc9a1bca9cc4acb9a1cc49cc9a1bca9cc4acb9a1cc49cc9a1bca9cc4acb9a1cc49cc9a1bca9cc4acb9a1cc49cc9a1bca9cc4acb9a1cc49cc9a1bca9cc41c426e189e2e5b66d63cd4eb0a84917503b23cf17b0fbaa2915bb9753b7700cf1981f808f919afdb39ebf8d4e5893bd7c1f67556c04f5fdbe1fdb3701e9459997dcc8667bd2d336b1eeaad0f8491756764794a79f099b772fdd859e091e8e785fc8cfbb1738e4feb3d71e73a98abe704fcf4b51dde3f07e7216bcc86a7db9699350ff5ba0361641d5e97bb85780a0e4fc1138b27cbb6d9efb1e5e9f6330f7fef0146a9feb0db61e47dcc71e4659e1e219e0687a7c1138b27cbb6f17fa32dcfb09f79f8fb466094caa91e8791f77d39d5003c1b85781a1d9e464f2c9e2cdb26169b6c79a6fdccc3df3701a3544e6d741879df97538dc0b3498827a94fda340eb693dad778d84eca95f1b0ad314f8eb940bb8bc707364523b772f7d5786d91e8ab84fc2cfaaedf9b1c9ff0fa8df7a84fd6f5499995398959e83eb73defd8e6f8440e0f6f678563319ebfb37b1c9fb2f03bbb1cf3890c326b9cc7c66c6c0fa66fbb3defd8e6f8440e0f6f83c2b110f233ee0fee8cfc31667b05a883797aa7809f39b0cbc7e6fd3be13c54c27c2283cc1ae7b1311bdb77a56e7be8fdc3689be313393cbcdd251c0b193f87fa83bb237f8cd95e01ea609ede2de0670eecf2b179ff6e380fcaaccccaaccccaaccccaaccccaaccccaaccccaaccccaaccccaaccccaacccca1c36b3b17d4feab687c6efd136c727727878bb473816327e0e8ddfdf1bf963ccf60a5007cff9bd027ee6c02e1f9bf7ef85f3a0cccaaccccaaccccaaccccaaccccaaccccaaccccaaccccaaccccaaccccaaccc61331bdb4f4ddf76fc3c0edae6f8440e0f6f4f158e85909ff1f8fd7d913fc66caf0075f09cdf27e0670eecf2b179ff3e380fcaaccc3e6663fb69a9db1e9acf43db1c9fc8e1e1ed69c2b190f173a83fb83ff2c798ed15a00e9ef3fb05fccc815d3e36efdf0fe7a112e6131964d6386b9c939835ce1ae724668db3c6398959e3ac714e62d6386b9c939835ce1ae724668db3c6398959e3ac714e62d6386b9c939835ced5136763fbe9a9db6e8bc7efd136c7277278787bba702c64fc1c1abf7f20f2c798ed15a00ee6e903027ee6c02e1f9bf71f80f330d1994f64905973637c98353794398959734399939835379439895973439993983537943989597343999398353794398959734399939835379439895973439993983537943989597343999398353794398959734399939843c80d63fbc1f46dc7cfb3a36d8e4fe4f0f0f6a0702c84fc8cd7bf3c14f963ccf60a5007f3f421013f7360978fcdfb6c4f99953989d9d87e46fab64b79c736c7277278787b86702c84fc8cfb8387237f8cd95e01eae0397f58c0cf1cd8e563f3fec3701eb2c68ce72f979eed78dd26dba8b19f46f74c5bae05ddb36cb90e74cfb6e549a07b8e2dd783eeb9b63c1974cf03df58f77c5b5e03ba17d8f226d0bdd0963782ee45b6dc03ba17db7237e85e62cb6741f7525b3e07ba97d9f220e85e6ecb7782ee15b67c17e85e69cb7783ee55b67c0fe85e6dcbf782ee35b6fc54d0bdd696ef03ddeb6cf969a07bbd2ddf0fba37d8f2d341f7465b7e00746fb2e515a07bb347f7165b7e10748fd8f243a07bab2d1f00dddb6c792ae8de6ecbd340f71750e6cf77d8f274d0bdd3960ba07b972dcf00ddbb6db90174efb1e599a07baf2d3782ee7db63c0b74efb7e5d9a0fb802dcf01dd076d792ee83e64cbf340f7615b9e0fba8fd8f202d07dd4961782ee63b6bc08741fb7e5c5a0fb842d2f01dd276d7929e83e65cbcb40f7695b5e0ebacfd8329edfbfb4e567808efb958741c7fdca3341c7fdcab340c7fdcab341c7fdca7340c7fdca7341c7fdcaf340c779f77cd071debd00749c772f041de7dd8b40c779f762d071debd04749c772f051de7ddcb40c779f772d071debd02749c77af041de7ddab40c779f76ad071debd06749c77af051de7ddeb40c779f77ad071debd01749c776f041de7dd9b40c779f766d071debd05749c778f80aec996df0abaf36cf96da03bdf96df0eba0b6c19fb990b6df91da0bbc896df093aee0bdf05ba8b6df9dda05b69cbef01dd2a5b7e2fe856dbf2fb40b7c696df0fbab5b6fc01d035dbf20741d762cb1f02dd3a5bfe30e88ab6fc11d0b5daf2474157b2e58f81aecd963f0eba765bfe04e83a6cf993a0ebb4e54f81aecb963f0dbaf5b6fc19d0f1759cfb19d39e4dbbe438708c8c8e7d6ef1f8c2ba29e04b6f94ee3d1ddbe263f37e1b30f239288d3f6369b48cad0ea3e1e9108819e6156fe57e3375004fbb008f909ff16fa64ec7a736c7a702d4b918fcec14f0330776f9d8bcdf09b625ce39c6a2de1e77a5138b3aa8d36e2f72e67a5a2e8e7c0c93bf258f2f52716c75785a3db6bb85e3c8c7e63eb17b1c6c7739b68b8e6dbc16f056ae6d7701f37a016673dc9ef48f1bb7ed0df6589ccf6ca7083e6d8418a4e513dace59613bacaf83f29e39c375b91ec783af9dcc6eda119f4b6477bfd7e17caf0075ba3dfef746e9fadfe3f0f438cce6f744ef9c610e81f610e740b7c3c1fb45885d4f42ecba21765c07afbdcd42b15beff0f07e33f0f0fd5527e8f83e85f9f11eaf651cb8dd7eafd3c3cdba2e606cf63096d2678cefb39a1d46de2f0123ebd6034f9750ccdc73bdd2890fde134c76eaf077eba0ce21b82ee73d754dbb6bca0dfbc5bfff1f8bd2edd3eb05e285631311c4277262c81b334c8986c72fd2e499160d8f4f9c1b1c38db776bff15fd7d47738056e760e267cee3460de8b05cebd145d1c861181c0ee661181c0eae71c282c33f5cdffc8c336ef15047ffa9e383579fee3f7de4ecbd6706fb8fee1db815a92739f4489ae40192a28eb729d1f080516f94ee4450bd63ab5cf24c81cfc9e9f3b40af9195ff4a63a3ed53b3e15a0ce24f8db54013f7360978fcdfb533db653ec88e2584c1b452ca67978a68d732c70d09d75d852f9ef387153e3f8822d1a7d72f33c5587d8e00a387ecec299bf99c63ec93a33391a3ed9dc7b9a3b5a7312cc68adb96a99d15833fa6aba2033ba6a2e6866f4d48c969ad151331a6a463fcd68a719dd34a39966f4d28c569ad1c9a66868f4d18c369ad145339a7811b07d1178cd2f7a738534a38166f4cf8cf6993b2b730760ee46ccddb7b95334bf1ecd1d82f9556b4638ccd5d6dcc998abb4b9b29a3b45738768eee8cd1dae9921db4cb2c5c67a2bc9252497925c46b28d643bc90e929d24bb487693ec21d94bb28f643fc9e5244f898646f6af20b992e42a92ab49ae21b996e43a92eb490e92dc407223c94d243793dc427288a48fe430c91192a324fd24c7486e25b98de47834b42ae876929324a7484e930c909c21b9231a9aa533b3726616ceccba99593633ab6666d1ccac99992533b3626616cccc7a99592e33abf56034341b656622cccc83996930330b6626c1cc1c3c371a9a193033012f888646facdc8be19c93723f766a4de8ccc9b917833f26e46dacdc8ba19493723e766a4dc8c8c9b917033f26d46bacdc8b619c93623d78f444323d36624da8c3c9b916633b26c4692cdc8f1bba3a1916133126c467ecd48af19d93523b966e4d68cd49a915933126b465ecd48ab19593523a966e4d48c949a91513312fa57247f4df25992cf91fc0dc9df92fc1dc9df93fc03c93f92fc13c9e749be40f2cf24ff120de5e5bf927c89e4df48be4cf2ef245f21f92ac9d748be4ef21f24ff49f20d926f927c8be4db24df21f92ec9f7481e25f93ec90f487e48f223921f93fc84e4a7243f23f939c92f487e49f22b925f93fc86e4b724bf23f93dc91fa2e19915ec44a6d89e8747f9fb0607fb4f9d196c1a1c683a75e7c9c1e3674ededb74f7f1c1db9a06eeea3f7bece4c0ddf8e5cfdb2ff314c6d6b367fbee6d3a7efa68ff3d4d03770e360d1c6b3a3c70e7e9a3e7f04b3fb55f5af2788b7d478f261bfbaf3f87f47fc66874b2ed137972685779dfa6d58e212033c7f2a5f6dab139b4d15e75f8d7fb954377bb4de74e0e0c36159b4ed3bf7d27e93bfd475b9af06fe728c8e7069bce0df69d1d6c3a7676e054536b0b1ef7fce96370a26dce18be74cb9cd17b1efd3fc9de5641f9d90300", + "packedBytecode": "0x000000028df71de5000000468d1f8b08000000000000ffed9d07741d45b6ae5bb61ce0481893b3450e06a3e49c64724ec6608c31b62c0b1b073962323643700ee460839c73c638478c6166983b393181811926dd3b7367bdf5e6be77df7a8ff5bacea9bdf4ab5c7daca3e992ff2355af5552f53ed5bdbffa7b7775aaeeca0952d33fc294a3f3cdc3745170e424bf97e9ff85ffda5414e3ba0a5d72e6640967b32ce16c9e259cb959c2d9224b385b660967ab2ce16c9d259cc7c5c8a9d89a05b5a7b8798f77a06bdc8c892cd3342f0b34cdcf324d4fc8024ddb04d9d1469d98259c6db384f3a42ce13c394b384fc912ce53b384f3b42ce13c3d4b38cfc812ce33b384f3ac2ce13c3b4b38cfc912ce73b384f3bc2ce16c97259c0559c2797e96705e90259c176609e74559c2797196705e1223677be0bc54ffbf4cffbf5cffbf42ff97b257eaff57e9ff1d741d73f5fcd58a2b4cea214db1f15b49984ac3d4314c9d8cdf3a87a94b98ba86a99bfead40ffd63d4c3dc2d4334cbdc2d45b6bd0274cd784e9da305d17a6ebc37443986e0cd34d61ba394cb784e9d630dd16a6dbc3744798ee0cd35d61ba3b4cf784a96f98ee0d53bf30dd17a6fbc3d43f4c0f846980c1f260980686e9a1300d0ad3c3611a1ca621612a0fd3d03055846958982ac3f4489886876944981e0dd3c8308d0ad3e8308d09535598c686695c98c68769429826866952981e0bd3e4303d1ea627c2f4a4a1d953617a3a4ccf84e95983f3b9304d09d3d4303d1fa66f85e98530bd18a697c2f47298a685697a9866846966986685697698e684696e98e685697e985e09d3ab617a2d4caf87e98d30bd19a6b7c2f47698de09d3bb615a10a685617a4fb3c88ef07e98aac3b4284c8bc3b4244c4bc3b42c4ccbc3b4224c2bc3b42a4cabc3b4264c6bc3b42e4cebc3b4214c1bc3b4294c9bc3b4254c1f84696b983e0cd3b6306d0fd38e30ed0cd3ae30ed0ed39e30ed0dd3be30ed0fd381301d0cd347613a14a68fc374384c9f84e9d3307d3b4cdf09d377c3f45998be17a67f3334ff7e987e10a61f86e947daf663fdff27baacdcbffb69987ea6f33fd7ff7fa1ffff52ffffdc58e65761fab561fb4d987e6bd8be08d3ef74fe4bfdff2bfdfff7faff1ff4ffaff5ff3feaff7fd2ffffacffff45ffffabfeffeffaff7fe8ff7fd3ffffaeffffa7feff8f303d5490cab70e6aa6b220a636aab432f9ec47c4bf34a83d292d9aebdfe47f81b6e7ea79f92fdab5d0f32d0c7b4b3ddfd2584f6b3ddfdab0b7d5f36d0dfbc97afe64c37eaa9e3fd5b09faee74f37ec17e9f98bc09e08e0deb0b62b5b736dca019bc46b33b0b5d0b6e6606b29ab035b2b6d6b0136d9be2dc1769cb6b502dbf1dad61a6c096d3b4eb40c539eb6950571c54ae110b5defcb8d7ab9f979d103fef50b5de368e784f8c9f77985a6f5b07bc2a3e4ed2eb3a11e2e6646d6b0bb653b4ed24b09daa6d2783ed346d3b056ca76bdba9603b43db4e03db99da763ad8ced2b633c076b6b69d09b673b4ed2cb09dab6d6783ed3c6d3b076cedb4ed5cb01568db79603b5fdbda81ed026d2b00db85da763ed82ed2b60bc076b1b65d08b64bb4ed22b049fb7b31d8e47cf1126d536dc77139b08cb64bbb955c46da6cb05d2eed35d8ae90b61a6ceda59d06db95e05b6c57415b23b60eda26ed96faad9bce970571ed27c5956abddde35e6fb866b5de9ef1af37f9ccb15750a36b19f8e90e5af5d6f918fb3515a1ef1c9dc48fd873217f0b949572a2871c7b845d1d637ae87cef34cb753396cb87323d2cf52f0be2ad7f4f83a7a7c1dc02f26e62b6a4c4c76c9da78c63b63f9435634fce831a63ccde0e1c0e62b6b38fd93a4f19c76c259435634fce851b63cc3e081c0e62b6dc4dcc1617fa984ddd370b027becc9f550638cd911c0117fcc76f4315bf729e3987d1eca9ab127d7c48d3166270347fc31dbb9dc9f1bd479ca3866e7415933f6e4fe4c638cd91781c341cc56fa76b6ce53c631fb1e9435634fee1536c6987d1538e28fd9ae8e62b6c4c76c907a061a04f6d893fbd68d3166170147fc313bd4df9fadfb9471ccee84b266ecc93394c618b31b745e3d67f8b17ece700ed87ea26de7026ffcb15dd1d1516c17fbd84ef50d09027b8ccaf3bcc618dbfb745ec5f1cfa13f82d87ea16de783ed97da7601d83ed7b60ba15e0ef68172bf0fd479ca781ff835943563599e2d37c67de087c0e120662b7cccd679ca3866ff0a65cdd8937e0e8d3166bf000e07315be963b6ce53c631fbbfa1ac197b97e97c638c59e96baace17bed4e70b5780ed2b6d6b0fb6df6bdb9560fb83b65d05b6afb5ad03d8fea86d5783ed4fda5608b63f6b5b11d8fea26dc560fbabb69580eddfb5ad146cffa16d1dc1f6376deb04b6bf6b5b67b0fda7b67501db3fb4adabb6a9e75dd2f74ace5b5b036b5910dfb64d802e32e518f365902f76cb53980f3ce8ab347e5f25aaee2541ddeb5e0a3c1d1dd43d013eeac2d311783ac5cf93ec8bda39fef526b77189a169027c9540bdba38a8570ef89275cbbcf8cb071beee75d2c8c5de3672cce015fb26e99ef0a8c62c37647deff91fd47b5cde7e7d4f03ad89792c767f457061ce22f17cafcb35d4dd98b355b1efc8e6d7027c3e6282e937121be64dd322ffef2a03e9d1a9eb1b8ae8c1d0d46576d440ef892759bbef3205fe4569fb43c9d497c3b38efb6b669a279f706f0ddd5f05d6af8c6b653a674c7b6aec01cfbf58f3eb6f5887fbd8578ae2cd729e207cf1ff07a22ae3aa16fb94e113f62cf85fc4d393565a59ce821edb0b0ab7d58b625b29bcb753196cb8732dd2df52f0be2ad7f0f83a787c1ac8e373de158e8607f48c640778343e64b41bb1e11da7507eda4cc65a09d8373cfa476dd0c1e99ef083cd27e637b56d4c03c4504bef11c16afe5e4773c0f70b5bd8a0c4699b76dafaec0d8d1c2e8e09cb038ddf1b01418c5d60d784a1c6916b55d4b487cbbb8aecc011f726e6e5edbe442993b9bd794adc871ca568ce7ce32d5f59a37feed545c88fb475d781cef43458ee2b110efdf7c13c41b6b66bb64b63751f7785cb5e525068fcc8b3fcfec993db367f6cc9ed9337b66cfec993db367f6cc9ed9337b66cfec993db367f6ccfccc8a479e2760bf2d29d78984d1ecffe6ea3e7ff25b7c7a5df80ce89f4efb831517e2b33fe907718551e75c287372b31ab6ff86fe60665fa2a86de9a26f6cba6d29feb03f58433c432c35784cdf79167df0b9346ae6aa0f94d966c83cf64f13fd8a80c7d5fe586cf098beb1cd2821d52caa9d75d5a72f2ace6cfd090b62f35d3cd4d5735df5dd33f5ed50f3f8d5c9d034f94d52c3a6daa47b9ad7d4dbc573de4c9f3be37143f2713ec7c57e19e82bfe76b6b856ff846641ed6305c6baabbe5ab25f49df88ee86ef5c28737eb39a6d837deaca82238f0dd8c74bd62dcb5c01cbf630d6ddc65d7dd3f643e90edc926f69d4ad33704b994be0d8fd539d77740c2ccef41d093c26c77f7c49f51729c980078f772ece591c1d470b311ee3ee2f62f683b49d2f4b19ec43eaa0ff6eda63b1f8f3cc9ed9337b66cfec993db367f6cc9ed9337b66cfec993db367f6cc9ed9337b66cfcccfac78cc67e8f8ecb79484b181fad8249f67c8f7d9f0b9d8b666357e5d3f0394674eed8d3ae33bcab9f08ef22ecd867d1ff0bb52b66de9ead95ad4b6147f6c7d1ff22cfa28cd7a583473f05dc7b4dfecc06f248a7e3d80c7d5fe18f5ed0e5b9b5144aa59543beba2ef42ba38b3f5532888cd77aabf888be7bad25fc43c7e99df35c27e1262c3e7e051df0b2b366cc7ba0db0f56b933c7e73c1c5183718cf665f41f187fd24bed0da4a3f89f8db81e24297c708d947a54f4889a5ae52e60fcd6acafe51e7b1af5029aceb9f96df654ad72701db5407df8f4d6e5f59976c5fdbb76bfb006b4cbe8b705d393af53134c885fcff6c565356ca4959d15ad8d53e22df95427673b98ec672f950a697a5fe6541bcf537bf25dcdb6056b1f31788b37fc2b99eab36a95784465780465206cf795df5ab35db48b3cf34f6896c6594c1f35329f3ffa08d8aea936eeb53e9ea7c21aa3f279e2fd8ce69cc3a9a7dc79b7a7fc07c7d1de2a23fa0acbb4d50bb4f5e60acbf3dac5fb85a05d1c71629d316d67f2cbf7b65bbf6135eec6f28654e836bbf9b743e936bbf63751d6fbbf6c3e5a2ea8eed42dcc7468c4764c158963205463cf688e0ee6a59f6c28865452bf3db87785d8ae708f17f3732d5def436ea22fb147edf5fca5c6eec37f19f33a5ce3f5d7d2353d6256d50b1a5ae52a603ec6b853a9f80ed84ef14f5b6fc2e53baf34fd14fd5f99af8eb9cdcbed7ea75c9f6bdc6e2fb3a608dc97711fa96f34ff123f65cc8f782e38994133d446b6157fb889cc321bbb95c7763b97c28d3c752ffb220defa5f63f05c6330abd8298138eb0def5ab86aabfb4468d41e34923278efdaf65d63dbbd8e863a4f35bf979e1f1cf9ed5e3c4eba3967b3bf2b67debfb59d9fb437f8f1fce47668671396b2e67d69592ecefee9f83e109e17e2fb40aeae91f283da7ae61b1c2e7db7317cb76940df6d0ddf6d1bd0b7d7dc6bcea439d3983ff81cb21930ba38d6e171b52e8cb6e35f736074f5ce6649068cf8cd6b3cde09a38bef84d7774c213cd769018c2ede37cef47e752760c46f0c08a38b77b433fd4e35beb72dcbb5024617e31ae1184a7561b48d75d41afe3b18d7a8a8bee380e05847c701a38bb1411241edf14c8ec6d80d1865b9e381d1c573a44450fbbedad118f179a52c9770cc98eed8eeb8ef4f71a6f7201aa25f41d4b906fa7670ffbf18fb26d4458b9e6e79d29efba06f07f7bf925ae0589647d3029fcfb9185b3311d47e1676341e7c8628cb9d048c658e187b67c058068cb2dcc9c0d8c7116359068c7d8051eca700a383fb9049c63e1930e2fd3a59ee5460bcd611e33519305e0b8cb2dc69c0e8e29e6202fcd685f13a6094e54e07c6eb1d315e9701e3f5c028cb9d018c373862bc3e03c61b8051963b13186f74c47843068c3702a32c771630dee488f1c60c186f024659ee6c60bcd911e34d1930de0c8cb2dc39c0788b23c69b3360bc051865b97381f156478cb764c0782b30ca72e701e36d8e186fcd80f1366094e5da01e3ed8e186fcb80f1766094e50a80f10e478cb767c0780730ca72e703e39d8e18efc880f14e6094e52e00c6bb1c31de9901e35dc028cb5d088c773b62bc2b03c6bb815196bb0818ef71c47877068cf700a32c773130f675c4784f068c7d815196bb0418ef75c4d83703c67b81b1af85b19f23c67b3360ec078cb2dc95c0785ffc8cc96be97e1930de073cf7c7cf93d4ecbe0c78ee77cb93fc86e27d165f0fc4ef2bb92dfa0775affb03c033207e9ee4b67820031e61c887e550b307e3674c6a362003c607816760fc3c49cd1ecc80672068f6a045b387e2674c6a363003c687806750fc3c49cd1eca80671068f69045b387e3674c6a362803c687816770fc3c49cd1ece80677050a3d9c316cd86c4cf98d46c70068c4380a73c7e9ea4664332e02907cd8658341b1a3f6352b3f20c1887024f45fc3c49cd8666c053019a0db568362c7ec6a4661519300e039ecaf879929a0dcb80a712341b66d1ec91f819939a5566c0f808f00c8f9f27a9d92319f00c07cd1eb16836227ec6a466c333601c013c8fc6cf93d46c44063c8f8266232c9a8d74c4f868068c232d3c717f13fd518bafd18eea3e2aa87bdd85211f96c37e12631c318ece80710c30ca72d84fa2ca11e3980c18ab8051964b38664cd74fa20a7c8f8ddf77b25daa0aeaaecf58b73c69fb49a0ef718eb4181bd45d8b716e79d2f69340dfe31d69312ea8bb16e3816782032d12e0a32e3cc2900fcb613f89898e182764c03811186539ec2731c911e3c40c182701a32c87fd241e73c4382903c6c7805196c37e12931d313e9601e3646094e5b09fc4e38e182767c0f83830ca72d84fe209478c8f67c0f80430ca72d84fe249478c4f64c0f82430ca72d84fe229478c4f66c0f81430ca72d84fe269478c4f65c0f83430ca72d84fe219478c4f67c0f80c30ca72d84fe259478ccf64c0f82c30ca72d84fe239478ccf66c0f81c30ca72d84f628a23c6e732609c028cb21cf69398ea88714a068c538151961be99831ddf5cbd446ee3bea5aa5b1fb8eba2e69ecbe7d9cfb386f0abe7d9cfb386f0abe7d9cfb386f0abe7d9cfb386f0abe7d9cfb386f0abe7d9cfb386f0abe7d9cfb3867f2fdbc03df09f021538e315f067961c887e5467ac646cd883c05f1f11462ddd1d7b708eafe2d0b4f8ea3baa3af1708ea2e0cd9c6f87c16308ecc0246af63aa0f627d1815cf8b8e785ec880e745e079c911cf8b19f0bc043c2fc7cf938ca99732e011867c586e6416303e9f058c5e47af2313a3d7b1e9e8e8193da367f48cc782311bda70cf9815f1585c5f46c5332d7e9ea4662f67c0330d3493e5ee77cb585c5f46c5333d7e9ea466d332e0990e9a4db368e680b1b8be8c8a6746fc3c49cda667c03303349b6ed1cc0163717d1915cfccf879929acdc88067266836c3a29903c6e2fa322a9e59f1f324359b9901cf2cd06ca64533078cc5f565543cb3e3e7496a362b039ed9a0d92c8b660e188bebcba878e6c4cf93d46c76063c7340b3d916cd1c3016d79751f1cc8d9f27a9d99c0c78e68266732c9a39602cae2fa3e299173f4f52b3b919f0cc03cde65a3463651c99058ccf6701a3631d8bebcba878e63be2999701cf7ce079c511cffc0c785e019e57e3e749c6d42b19f008433e2c37320b189fcf0246afa3d79189d1ebd87474f48c9ed13366c6f8ad2c60f4dbda33b2323ab8be4afb0ecd2b8ddc77d43b348ddd77d43b348dddb78f731fe74dc1b78f731fe74dc1b78f731fe74dc1b78f731fe74dc1b78f731fe74dc1b78f731fe74dc1b78f731fe74dc1b78f731fe74dc1b78f731fe74dc1b78f731fe74dc1b78f731fe74dc1b78f731fe74dc1b78f731fe74dc1b78f731fe74dc1b78f731fe74dc1b78f731fe74dc1b78f731fe74dc1b78f731fe74dc1b78f731fe74cbe5f8bdf7771a6efb0be063c2edea97554cf42b5ded7f5babe89513fa5d51b8656af185ae54399d741bf371ce897037e65dd322ffe3265be9480d991efe213c2751c07f5171fcf1b7a28ff6f3aaa7b545bff6623f71dd5d63776df516d7d63f7ede3dcc77953f0ede3dcc77953f0ede3dcc7398b6fccb7086acedbe5fb4a6a1d6fc1ef39505ebe5b960b65fab54afd6f13f87dc8856fbf0ff9634553f0ede3dcc77953f0ede3dcc77953f0ede39c2fce311eae6d009ec0e009d2f03c4dc6d3998c672c19cf50329efbc8786e21e3e945c633998ca7988c671619cfa3643c2f91f10c22e3b99b8ce77a329eabc8789e25e3e94ac6339e8c671819cf03643cb791f19491f13c41c6534ac6339b8c673419cfcb643c83c978fa92f1bc40c6732319cf14329eee643c73c9782e27e39948c6731919cf23643c85643c0f92f19c40c6d3868ce70e329e6bc8789e22e3e944c633878ca78a8c671a194f39194f3f329eabc9786e26e3e949c6339f8ce731329e22329e11643c0f91f1dc45c6d39c8ce73a329e67c878ba90f18c23e3694fc65341c6339d8ca73f19cfad643cbdc9781e27e32921e31945c6f33019cf3d643c0df13d8e4c78a692f1dc40c6f31c194f37329e09643c33c8782e25e3a924e31940c69347c6934fc6d3818ce776329e3e643c4f92f17424e31943c633848ce75e329e17c9786e22e3e941c6338f8c671219cf4c329ee1643c03c978ae20e339918ca72d19cf9d643c39043c89e0c86f2427e0f7d7c0d6cc58567d56aa5b41cdef6f6b7b3358e61d9d6f6e59f7db60936f55bd635916757a1bea52a6f385ffda94d4097d95c1bcf8cb038e774878ee24e3694bc6732219cf15643c03c9788693f1cc24e39944c6338f8ca70719cf4d643c2f92f1dc4bc633848c670c194f47329e27c978fa90f1dc4ec6d3818c279f8c278f8c6700194f2519cfa5643c33c8782690f17423e3798e8ce706329ea9643caf91f1dc43c6f33019cf28329e12329ec7c9787a93f1dc4ac6d39f8c673a194f05194f7b329e71643c5dc8789e21e3b98e8ca73919cf5d643c0f91f18c20e32922e3798c8c673e194f4f329e9bc978ae26e3e947c6534ec6338d8ca78a8c670e194f27329ea7c878ae21e3b9838ca70d19cf09643c0f92f11492f13c42c6731919cf44329ecbc978e692f17427e39942c6732319cf0b643c7dc9780693f1bc4cc6339a8c6736194f2919cf13643c65643cb791f13c40c6338c8c673c194f57329e67c978ae22e3b99e8ce76e329e41643c2f91f13c4ac6338b8ca7988c6732194f2f329e5bc878ee23e3194ac633968ca73319cfd3643cd75a785e73c423efbbcbba65fe3512df0eb643a15aefbb8eeab440afaba55eaff08bbf5c2853747ceabf7a3e84cb0a97f97d02ecfbbd00347acb515dcc313165fead46eebb8de1bb4d13f1ddd6f0ddb689f8f671eee39cc9f782f87d17e3b76d64ca31e6cb208fc71717df047254cf5ac7f66f62d44f69b5d0d0ea2d43ab7c28f32ee8b7d0817eb6f30599177f99325f4ac08c715110c41b17efc55fa762d597e638d0f53d435facd7fb8e348d3a86bcdfc87d471d431abbefa8634863f7ede3dcc77953f0ede3dcc77953f0ede3dcc73993ef6a9d8ff1bab1107db4086aae07aac1ef629dcf89d1af5ad722f09b031ce22f17cabc02f7a2fd3eeff7f9b87cfb639b8ff3a6e09b39cecdbc3c43bc0cd85c3de38d8ac58678be7c2c7d47c56263f71d158b8dddb78f731fe74cbe97c4ef3bf90cf1b5a0f694ee19e212e059e4400b47f54c5e3b2d35eaf49a51a77c28530df55ceaa09e39e057d62df34b613b641bb3e299aaf338be8b949b4ac228b6456e7992fbd7d4a0f6946eff5a0a3c0ef6832247f54cee5fcb8c3a4db5e82e65aaa19ecb1cd4d3b6efc8fc32d80ed9c6ac78e4dd5d614d40b9174818c5b6c42d4f72ff7a21a83da5dbbf96018f8bf6c7513d93fbd772a34e2f58749732d550cfe50eea69db77647e396c876c63563c329689b026a0dc8b248c625bea96a73401759629ddfeb51c785cb43f8eea99dcbf5618757ad1a2bb94a9867aae70504fdbbe23f32b603b7866cf6c63563cf2cea4b026a0dc4b248c625be694a7b430017596295d3bb602785cb4f38e744fb6632b8d3abd64d15dca54433d573aa8a76ddf91f995b01d32615e9085ccd559c8ec75f63a4731576721b3d7d9eb1cc55c9d85cc5e67af7314737516327b9dbdce51ccd559c8ec75f63a4731576721b3d7d9eb1cc55c9d85cc5e67af7314737516327b9dbdce51ccd559c8ec75f63a4731576721b3d7d9eb1cc55c9d85cc5e67af7314737516327b9dbdce51ccd559c8ec75f63a4731576721b3d7d9eb1cc55c9d85cc5e67af73147375163233e8ac785ed679614d40b9974918c5b6dc2d4ff2fd9d9783da538e315f06f995c0b3c2813e8eea99ecf7becaa8d3cb16dda54c35d47395837adaf61d995f05db2113e60559c85c9d85cc0c3a2b9e693a2fac0928378d84516c2bdcf224dbb16941ed295d3bb60a785cb4f38eea996cc7561b759a66d15dca54433d573ba8a76ddf91f9d5b01d3cb367b6312b9ee93a2fac0928379d84516c2b9df21427df439c1ed49ed2b563ab81c7453bef48f7643bb6c6a8d3748bee52a61aeab9c6413d6dfb8eccaf81ed9009f3822c64aece4266afb3d7398ab93a0b99bdce5ee728e6ea2c64f63a7b9da398abb390d9ebec758e62aece4266afb3d7398ab93a0b99bdce5ee728e6ea2c64f63a7b9da398abb390994167c53343e7853501e56690308a6d95539e92e473871941ed29dd738735c0e3e2b98c23dd93cf1dd61a759a61d15dca54433dd73aa8a76ddf91f9b5b01d1a3bf3822c64aef6cc0dc2ec63c3334731fbd8f0cc51cc3e363c7314b38f0dcf1cc5ec63c3334731fbd8f0cc51cc3e363c7314b38f0dcf1cc5ec63c3334731fbd8f0cc51cc3e363c7314b38f0dcf1cc5ec63c3334731fbd8f0cc51cc0cb1a17866eabcb026a0dc4c1246b1ad76cb93fceec1cca0f694aedfce5ae059e3401f47f54cf6db5967d469a6457729530df55ce7a09eb67d47e6d7c176f0cc9ed9c6ac7866e9bcb026a0dc2c1246b1ad71cb936cc76605b5a774edd83ae071d1ce3baa67b21d5b6fd46996457729530df55cefa09eb67d47e6d7c376f0cc9ed9c6ac7866ebbcb026a0dc6c1246b1ad75cb936cc76607b5a774edd87ae071d1ce3baa67b21ddb60d469b6457729530df5dce0a09eb67d47e637c076f0cc9ed9c6ac78e6e8bcb026a0dc1c1246b1ad73cb539c803acb94ae1ddb003c2eda7947f54cb6631b8d3acdb1e82e65aaa19e1b1dd4d3b6efc8fc46d80ed9c6ac78e6eabcb026a0dc5c1246b1ad77cb93dcbfe606b5a774fbd746e071d1fe38aa6772ffda64d469ae457729530df5dce4a09eb67d47e637c176c83666c5334fe7853501e5e691308a6d835b9ee4fe352fa83da5dbbf36018f8bf6c7513d93fbd766a34ef32cba4b996aa8e76607f5b4ed3b32bf19b643b6312b9ef93a2fac0928379f84516c1b1df324a0ce32a5dbbf36038f8bf6c7513d93fbd716a34ef32dba4b99f7a19e5b1cd4d3b6efc8fc16e091e95ae071159781c11358f491e969329ece643c63c9788692f1dc47c6730b194f2f329ec9643cc5643c8f92f10c22e3b99b8ce77a329eabc8789e25e3e94ac6339e8c671819cf03643cb791f19491f13c41c6534ac6339a8c6730194f5f329e1bc978a690f17427e3b99c8c672219cf23643c85643c0f92f1bc4fc67302194f1b329e3bc878ae21e3798a8ca713194f15194f39194f3f329eabc9786e26e3e949c6f318194f1119cf08329e87c878ee22e3694ec6731d19cf33643c5dc878c691f1b427e3a920e3e94fc6b3908ce756329ede643c8f93f19490f18c22e379988ce71e329e1bc8789e23e3e946c633818ce752329e4a329e01643c79643cf9643c1dc8786e27e3e943c6f324194f47329e31643c43c878ee25e3b9898ca70719cf24329ee1643c03c978ae20e339918ca72d19cf9d643c39043c89e0c877f112f0fb42b0c93b63f3c1f681ce6f025b338b0f7916b1056cb93a2feb6815a6eb0b8e5c37eae4ea3d39f45506f3e22f0f383e20e1b9938ca72d19cf89643c5790f10c24e3194ec633898ca70719cf4d643cf792f1c8f5200bcf18329e8e643c4f92f1f421e3b99d8ca703194f3e194f1e19cf00329e4a329e4bc9782690f17423e3798e8ce706329e7bc8781e26e31945c65342c6f338194f6f329e5bc9781692f1f427e3a920e3694fc6338e8ca70b19cf33643cd791f13427e3b98b8ce721329e11643c45643c8f91f1f424e3b9998ce76a329e7e643ce5643c55643c9dc8789e22e3b9868ce70e329e36643c2790f1bc4fc6f320194f2119cf23643c13c9782e27e3e94ec633858ce746329ebe643c83c9784693f19492f13c41c65346c6731b19cf03643cc3c878c693f17425e379968ce72a329eebc978ee26e31944c6f328194f3119cf64329e5e643cb790f1dc47c633948c672c194f67329ea7c978aeb5f02c74c4638e9b20f30b097cabf9eea08b9a12f03b7e67fd7d478c0b0d46997f1f1891d7b5666d0c9e368666c7d2b7aabfbcab23f7c0717be17be70cdbab4d0368d6d6e0696b68762c7d2b2de4d9b6bc3388db0bbf53cbb0bdf0bd6a07ed7369c2e051538e315f06f92d8ef57154cf427ceffa9b18d7abb4da6a68b5d0d02a1fca6c06fdb63ad02f07fccaba655efc7966cf1cc5ac78a42f89ed7b00fd4818c586e3627c183f4f69c2e05153baf6f143c7fa38aa67b21ddb16d875ff1074973218abdb1cd43307fccaba657e9bc5774110af16dbeba0c5760bcff606d642fc65cabc390b991974563cf2ae81b026a05c7f1246b16d059e1df1f394260c1e35a56b1f7738d6c7513d936dc2cec0aefb0ed05dcae0feb5d3413d73c0afac5be677c276c884795b16327b9debc7ac78e41d6d614d40b901248c62db0e3cbb62e7292e4c183c6a4ad78eed72ac8f9b7aa6dab1dd815df75da0bb94c1fd6bb7837ae6805f59b7ccef86ede0993db367f6cc9ed9337b66cfec993db367f6cc9ed9337b66cfec993db367f6cc9e999b59f10cd479614d40b981248c62db093c7b62e7493d77401e35a57beeb0c7b13e6eea997aeeb037b0ebbe0774973218ab7b1dd43307fccaba657e2f6c07cfec993db367f6cc9ed9337b66cfec993db367f6cc9ed9337b66cfec993db367f6ccdccc8a6790ce0b6b02ca0d226114db6ee0d9173f4f69c2e05153bae70efb1cebe3a89ec9e70efb03bbeefb40772983b1badf413d73c0afac5be6f7c376d8ef993db38559f10cd679614d40b9c1248c62db0b3c0762e7493d3f451e35a56bc70e38d6c74d3d53edd8c1c0aefb01d05dca60ac1e7450cf1cf02beb96f983b01d3261de9685cc5e67af7314b3d7d9eb1cc5ec75f63a47317b9dbdce51cc5e67af7314b3d7d9eb1cc5ec75f63a47317b9dbdce51cc5e67af7314b3d7b9e9e8ac78ca755e581350ae9c84516cfb81e7a3d8794a0a13068f9a728cf932c87fe4581f37f54c3d773814d875ff08749732b87f1d7250cf1cf02beb96f943b01d1a3bf3b62c64f6b1d130cc3e363c7314b38f0dcf1cc5ec63c3334731fbd8f0cc51cc3e363c7314b38f0dcf1cc5ec63c3334731fbd8f0cc51cc3e363c7314b38f0dcf1cc5ec63c3334731fbd8f0cc51cc3e363c7314b38f0dcf1cc5cc101b8aa742e7853501e52a4818c57610783e8e9fa73461f0a829c7982f83fcc78ef57154cf64bf9dc3815df78f41772983fbd76107f5cc01bfb26e993f0cdbc1337b661bb3e2a9d479614d40b94a1246b11d029e4fe2e7294e183c6a4ad78e7de2581f47f54cb6639f0676dd3f01dda50cc6eaa70eea99037e65dd32ff296c876c63563cc3755e5813506e3809a3d80e038f83b84bf2e41b3c32ff09816f355fa5f379fa3f6eaf2a6064d85ef90da0591b83a78da1d9b1f4adea3f56e74fd0ff717b8d054686edd5a601346b6bf0b435343b96be9516e374fe44fd1fb7d7386064d85e6dddf214270c1e35a53bdff81478be133f4ff23aeed30c78be033cdf8e9fa7c8513d0bd57abf0bec71ad5769f599a1d5a78656f95006193e73a05f0ef89575cbbcf8f3cc9e398a19db42614d40b94f4818c5f66de071d16ea8ba5fa5d725eb6f11a61f9c5ce3d7c5fd35bcb7d052af5738c45f2e9439b75d0ddb4f345b1efc2edb4dd5e7906173f4ce5b91ed3eafcc8bbfbcc07eadefea1e6ad4bd8743c073c8a2d9418b66071c311e341865fe0030daeef31e74c41375df59fc619b718854337c0ff823e071755e1c1567aef7b94ccf2f3fb2f07c131f4f21c606fa7211abd8b6d5a5eeb67d27c6ba17e1332cf4e5601f481ea73ae875c9fad5b1e0bf4e76aa7929b60f729cea60d43917cafcf779356cff27cd71aa5970e47de1026d9732f2fb37da6eaea340af5be6bbebff182762f3c7c0dacf11bb1b5ab26986fbd6c7161d7b58b87b1070633c36c4b68ebaf781dbba87a1239b66b8ad3fb1e8d8d3c2dd93809b71bfee69e8c8a6d9d1f6eb7e16ee7e04dc8cfb753f434736cd8eb65ff7b770f727e066dcaffb1b3ab26976b4fd7a80857b000137e37e3dc0d0914db3a3edd7032ddc0309b819f7eb81868e6c9a1d6dbf1e64e11e44c0cdb85f0f327464d3ec68fbf5600bf760026ec6fd7a70505b4736cd8eb65f975bb8cb09b819f7eb72434736cd8eb65f5758b82b08b819f7eb0a434736cd8eb65f575ab82b09b819f7eb4a434736cd8eb65f0fb7700f27e066dcaf871b3ab26976b4fdbacac25d45c0cdb85f57193ab26976b4fd7aac857b2c0137e37e3dd6d0914db3a3edd7e32cdce308b819f7eb71868e6c9ad9f66b47fdcb32ee87fcb1537d52e3cf66f21e16f6257111538ee2a0d0515f93643fe40386561f1b5ae177fd0f827eaefa6445f51b137f9ed9337b66cfec993db367f6cc9ed9337b66cfec993db394f1cc9ed9337b66cfec993d332f33bee789cf57a45c43bc035c1746b1e1332917f7f955ddafd6eb92f5b708d39da7d6f88dffb94571f23980e82fef635e6dd43917caec3cb786adaf66c3e78bf85cd4b62d0fc65e87babd738eefe9e3b3a063f9bcf3238b66072c9aed77c468b61932bf1f1845bf03c0e36a7f3c68f098be6def86b36916d5ceba8afba838b3f92e88cd77f15037df42282e54df683b2e38b23d913ae0beeb220e33fd2600ee170e9ebb17b97aff5fd569bf51a743469df2a1cca550cffd0eea59d77d4ba66b81c7557b14183c81451f999a91f13c4dc6d3998c672c19cf50329e8bc878ee23e339838ce716329ee3c8787a91f14c26e32926e379948c6710194f3b329ebbc9784e26e3b99e8c27978ce72a329e67c978ba92f18c27e31946c6730919cf61329e2bc9781e20e3398b8ce736329e04194f1919cf13643ca5643ca3c9780693f19c4fc6d3978ce754329e1bc9785a92f14c21e3e94ec633918ce772329e47c8782e23e32924e379908ce71c329e3bc8784e20e36943c6730d19cf53643c9dc878aac878cac9782e24e3e947c6733a19cfd5643c3793f1b426e3e949c6f318194f1119cf08329e87c878ce23e3b98b8ce724329eebc8789a93f13c43c6d3858c671c194f7b329e0a329e8bc978fa93f19c49c6732b19cff1643cbdc9781e27e32921e31945c6f330194f0119cf3d643ca790f1dc40c6d3828cc7f57b8099f23c47c6d38d8c6702194f2519cfa5643c03c878ce26e3b99d8c278f8c279f8ca703194f1f329e27c9783a92f18c21e31942c6730119cfbd643ca791f1dc44c6d38a8ca70719cf24329ee1643c03c978ce25e3b9828ce74e329e13c978da92f1e410f0248223bfc584dfff3a04b6fd3a8fdf166c66599f3c1796f2ea38747bc191eb6e6659f7010b03eab42fa8a94b99ce17fe6b535227f45506f3e22f0f380e90f0b425e339918ce74e329e2bc878ce25e31948c6339c8c6712194f0f329e56643c3791f19c46c6732f19cf05643c43c878c690f17424e379928ca70f194f07329e7c329e3c329edbc978ce26e31940c67329194f2519cf04329e6e643ccf91f17c44c6d3828ce706329e53c878ee21e32920e379988c6714194f0919cfe3643cbdc9788e27e3b9958ce74c329efe643c1793f15490f1b427e31947c6d3858ce719329ee6643cd791f19c44c6731719cf79643c0f91f18c20e32922e3798c8ca727194f6b329e9bc978ae26e3399d8ca71f19cf85643ce5643c55643c9dc8789e22e3b9868ca70d19cf09643c7790f19c43c6f320194f2119cf65643c8f90f15c4ec633918ca73b19cf14329e96643c3792f19c4ac6d3978ce77c329ec1643ca3c9784ac9789e20e32923e34990f1dc46c6731619cf03643c5792f11c26e3b9848c671819cf78329eae643ccf92f15c45c6934bc6733d19cfc9643c7793f1b423e31944c6f328194f3119cf64329e5e643cc791f1dc42c6730619cf7d643c1791f10c25e3194bc6d3998ce769329e66643cd71a3cf8bb7a174bde0fdbafffe7c2ef5374e3d546af4bcac83311756f69af6153f5dde3a8be7b839aa90ce6f7407d857d2ff0ec75c4b3cfe0317de741be0768b6dbb029c65d8e18771b8c32bf0b1845bfddc0b3db11cf1e83c7f49d07f99ea0d94ec3a618773862dc6930cafc0e6014fd7602cf4e473cbb0c1ed3771ee4fb8166db0d9b62dce68871bbc128f3db8051f4db0e3cdb1df1ec30784cdf7990ef0f9a7d68d814e356478c1f1a8c32bf151845bf0f81e743473cdb0c1ed3771ee40780661f1836c5b8c511e30706a3cc6f0146d1ef03e0f9c011cf5683c7f49d07f981a0d966c3a618373962dc6c30cafc266014fd3603cf66473c5b0c1ed3771ee40781661b0d9b62dce08871a3c128f31b8051f4db083c1b1df16c32784cdf79901f0c9aad376c8a719d23c6f506a3ccaf0346d16f3df0ac77c4b3c1e0317de741be1c345b6bd814e31a478c6b0d46995f038ca2df5ae059eb88679dc163face837c0568b6dab029c6558e18571b8c32bf0a1845bfd5c0b3da11cf1a83c7f49d07f94ad06ca561538c2b1c31ae3418657e05308a7e2b8167a5239e55068fe93b0ff2c341b3e5864d312e73c4b8dc6094f965c028fa2d079ee58e7856183ca6ef3cc85781664b0d9b625ce28871a9c128f34b8051f45b0a3c4b1df12c33784cdf79901f0b9a2d366c8a719123c6c506a3cc2f0246d16f31f02c76c4b3c4e0317de7417e1c68566dd814e3fb8e18ab0d46997f1f1845bf6ae0a976c4b3c8e0317de741be2fd884b7086cefe97c31d816ea7c09d816e87c29d8ded5f98e607b47e73b81ed6d9def0cb6b774be0bd8ded4f9ae607b43e7bb81ed759def05b6d774be37d85ed5f932b0bda2f37dc0365fe7af01db3c9dbf166c7375fe3ab0cdd1f9ebc1365be76f00db2c9dbf116c3375fe26b0cdd0f99bc1365de76f01db349dbf156c2febfc6d607b49e76f07db8b3a7f07d85ed0f93bc1f62d9dbf0b6ccfebfcdd609baaf3f7806da4cedf0bb6fb75fe3eb07daaf30f80eddb3aff20d8bea3f30f81edbb3aff30d83ed3f92160fb9ece0f05dbbfe9fc30b07d5fe71f01db0f747e04d87ea8f38f82ed473a3f0a6c3fd6f9d160fb89ce8f01db4f757e3cd87ea6f313c0f6739d9f08b65fe8fc24b0fd52e71f03dbe73a3f196cbfd2f9c7c1f66b9d7f026cbfd1f927c1f65b9d7f0a6c5fe8fcd360fb9dce3f03b62f75fe59b07da5f3cf81edf73a3f056c7fd07969d7543bfb479d2f08e26d67bf0e6aa602f02dfe54993fe97c2ba38c2c9b0b654af5077dd4330ef52d536987a55d56366987df039bb4c30bc126edf002b0493bfc2ed8a41d7e076cd20ebf0d366987df029bb4c36f824ddae137c026edf0eb609376f835b095e9fcab609376f815b0493b3c1f6cd20ecf039bb4c373c126edf01cb0493b3c1b6cd20ecf029bb4c333c126edf00cb0493b3c1d6cd20e4f039bb4c32f834ddae197c026edf08b609376f805b0493bfc2db0493bfc3cd8a41d9e0a36d95fbe069bb4cd23c1266df3fd6093b6f953b049dbfc6db049dbfc1db049dbfc5db049dbfc19d8a46dfe1ed8a46dfe37b049dbfc7db049dbfc03b049dbfc43b049dbfc23b08dd6f91f834ddae69f804ddae69f824ddae69f814ddae69f834ddae65f804ddae65f824ddae6cfc1266df3afc0266df3afc1266df36fc0266df36fc1266df3176093b6f9776093b6f94bb049dbfc15d8a6e8bcb4d5adc126cf8ad554f82f4e380e4f33f0254c6541bc6d3f4e65907f0eea2ed374329eb1643caf93f15c44c6b3928c670519cf19643c1f90f16c21e3398e8c673f19cf3e329e39643cef90f10c22e36947c67332194f2e19cf55643cd5643caf92f15c42c673988ce74a329eb3c8783693f16c22e3594ec6b38c8c2741c6b3978c670f19cffb643cb3c878de22e3194cc6733e19cfa9643c2dc978ba93f15c4ec6339f8ce732329ea5643c4bc8780ac978ce21e3d948c6b3818c672119cf09643c6dc8787693f1ec22e39941c6f335194f1519cf1b643ce5643c1792f1f423e3399d8ce76a329ed6643c3dc978e692f12c26e35944c6f32e19cf79643cebc978d691f19c44c6b3938c6707194f73329e69643ce3c8785e23e3694fc65341c67331194f7f329e33c9788e27e3994ac6339b8ce76d329edf93f11490f1ac25e35943c6730a19cf76329e6d643c2dc8783e22e379858ca7928ce73d329e01643c6793f1e491f1e493f17420e31949c633938ce74d329e0bc8785693f1ac22e3398d8ce743329ead643cadf47f169e1e643cf3c8788693f12c20e31948c6732e19cf15643c2792f1b425e3c921e04900470036f9bd39d8bed2f9c36093eff57c04b62f75be1a6cbfd3f929607bc6626b66e11386afc026ef5a3f0b36b93ff325d8e41d8edf814d8e8be25fcdf72d3892bf192c237e9a5bf8d1dfef2c5c92c7ed2dcb9405f16e6ff455161cf93da53ce0789684a72d19cf89643c5790f19c4bc633908c670119cf70329e79643c3dc8785a91f16c25e3f9908ce734329e55643cabc9782e20e379938c672619cf48329e0e643cf9643c79643c6793f10c20e3798f8ca7928ce715329e8fc8785a90f16c23e3d94ec6730a19cf1a329eb5643c05643cbf27e3799b8c673619cf54329ee3c978ce24e3e94fc67331194f05194f7b329ed7c878c691f14c23e3694ec6b3838c672719cf49643cebc878d693f19c47c6f32e19cf22329ec5643c73c9787a92f1b426e3b99a8ce774329e7e643c1792f19493f1bc41c65345c6f33519cf0c329e5d643cbbc978da90f19c40c6b3908c670319cf46329e73c8780ac9789690f12c25e3b98c8c673e19cfe5643cddc9785a92f19c4ac6733e19cf60329eb7c8786691f1bc4fc6b3878c672f194f828c671919cf72329e4d643c9bc978ce22e3b9928ce73019cf25643caf92f15493f15c45c6934bc67332194f3b329e41643cef90f1cc21e3d947c6b39f8ce738329e2d643c1f90f19c41c6b3828c672519cf45643caf93f18c25e3994ec6d3ccc273d8118f1c2b65dd327f98c0b77a0f57eec5efd7ff13f03b8edf5ced88f1b0c128f3d5c028b67dc0d3dd11cf1e83678f458b63e55b6921dffed8abff27e077fc5ea1ab98ea6e30cabc2da6f6004f0f473cbb0c9e5d162d8e956fa585f47d943e2409f81dc7c37315533d0c4699b7c5148ee7dad311cf0e836787458b63e55b69217d0da50f7f027ec7f12f5dc5544f8351e66d3185e375f573c4b3cde0d966d1e258f9565ac8bb67f2ce72027ec7f1845cc5543f8351e66d3185e343f477c4b3d5e0d96ad1e258f9565ac8b724e49b4809f81dbfefef2aa6fa1b8c326f8b29fc3ef200473c5b0c9e2d162d8e956fa5857cab4eaed913f03b7edfd6554c0d301865de16535b8067a0239e4d06cf268b16c7cab7d26290cecb33b804fc3e08185dc5d4408351e66d31b509780639e2d960f06cb06871ac7c2b2d06ebbcf4c94cc0ef8381d1554c0d321865de16531b8067b0239e7506cf3a8b16c7cab7d2a25ce7e59dc104fc5e0e8cae626ab0c128f3b698c2f177cb1df1ac3178d658b43856be9516f2eefd5afd3f01bfe3789c831d31961b8c323f1818c586e3bd5538e25965f0acb26871ac7c2b2de45b5af20dc604fc8ee363b98aa90a8351e66d3185e39d543ae25961f0acb06871ac7c2b2d86ebfc4afd3f01bf0f07465731556930cabc2da65600cf0a473ccb0c9e6544be9516f22e9cf4614bc0ef55c0b8d21163544cad0446b12d039e658e7896183c4b887c2b2de4598ebc739180dfc702e372478c5131b51c18c5b60478c63ae25964f02cb26871ac7c2b2de4db318bf5ff04fc8ee3b52f71c438d66094f925c028b645c0b3c8114fd43dbc86f01d753faa217c47dd5b6908df51f7091ac277d43df686f01d75fdd610bea3ae451ac277d47d8686f01d754edf10bea39e6f3784efa867b50de13beab96363dfbffdb1a4691d4b8e65bbd6548f25be3de76ccfc7c5efbb3811d4bea651538e315f0679bc7e59ec400b47f52cc46bc26f625cafed1a7e91a1553e94c16b5457d77fe30c1e99177fd9c88c7191139fefc204f8907794954deeb5bc0736b9c7b1106c720f6401d8e41edabb6093fb59ef804dee77bd0db6e13a3f126c72ef12fb23c9bdcd1d602bd779ec073358e7b7814d9e1361ff0b79d6b7156cf2bc169ffbcb33f72d60937e13f8bc59fabe6c029bf45fc2e79cd2076d03d8a41f213e5fabd6f97560933125f0b9ce973abf066c5fe93c3e4f90b13a5781ed699d9f0ab62f74fe6bb03da5f38bc0f65b9dc77b3e4feafc58b0fd46e7df02dbaf75fe4db03da1f36f80ed719ddf0fb65fe9fc3eb04dd679ec1ffab9ceef01db633a8ffd127fa9f3bbc0f60b9d7f1d6c9374fe35b04dd4f957c1f6739d7f056c13747e3ed87ea6f3f3c0365ee7e782eda73a3f076c3fd1f9d9601ba3f3b3c0f6639d9f09b6d13a3f036ca3747e3ad87ea4f3d3c0f6a8ceff1e6c3fd4f971606ba6f34bc026df4fc67bbaf2cee232b0c9382578af5ebe55520536197f6f05d85aeb3c3e9791f79286834dbe6d5f093679ffbf026c32465239d8641ca7c160936f810d029b7caf6c20d864ccd20160937155fb834dbe5ddc0f6cf23e654fb0c918213dc026df51e90e3619fb0ec70496ef5d56834dde09c27182e5bbfb5f824dde2dff0a6c327e138e092cdfb87a1a6c322ee917603b4fe79f029bbcaff95bb015e8fc93603b5fe77f03b60b74fed76093ef573e013679a7e671b0c977f47f053679377b32d82ed5f9cfc17699ce3f0636f90ed12fc12663c5fe026ced757e12d8e49df98960bb4ae77f0e3619eb6c02d8e4fbaa3f039b7ce36b3cd88a74fea7602bd6f99f80ad44e7c780ad54e77f0cb68e3a3f1a6c9d747e14d83aebfc8fc0d645e71f055b579d977646edcf6a3f3fa4e7cb82f8cecb94bf8f83da53ba6b0361409e38cfb5f381077d1d8cbdeec5c9f37ad9ef9be9f54a0c1d04dffb63f79dbaa638a0d7d542af77bfe13b17ca7caa1b11b5dc5ef8bd0cea20cbe135b6ac5b96b91a96dd67acbb8daeef0147f5dd6f3009f7016092329f9d5b53f629dd58b6866562644b5e1f4bac05a0214e65901706375a1517e2796f5d780e004ffcfb49ea7add454ce0be15f7f5ba798fc98cb57c28b31ff4dbe7403fdcd765dd322ffe3cb367f6cc9ed9337b66cfec993db367f6cc9ed9337b66cfec993db367f6cc9ed933f3332b1e799e80cf95a5dc211246b11d049e03f1f314e2735859bf7aaef3103cd73918bbdfdacff75aeaf5161a75ce8532abcfab611ba2f379f0bb6cb7a86db93ff63aa4df96e22f0fea7300781c6ccb24cf4183c7f49d67d14769b6cfa2d95e478c669b21f37b8171bfceef031e57fbe37e83c7f48d6dc60152cda2da5917fd12d2c599ad0f42416cbe8b87ba7aaeabfa4ca9be1ce6f1eb90a129f681101b3e07cf83653ed1ff13a0cf27a0cfb16c03cc7e09d84e7d0c8cfb63672caef50c58dafeab0d4db10fc48b5a5be903117f3b505ce8f21821fba8d9b702eb2a6566c0716e96ce633fa043b0ae772dbfcb9463cc97411edbd4ddf1d739b97da5ffaa6cdfdd16df3b813526dfb5dee5c8d149fc883d17f2ef9c575356ca891ea2b5b0e3b855c86e2ef7b1b15c3e94d963a97f59106ffd771b3cbb0d66153b7321cede85733d576dd29e088dae068da40c9ef33ae853646d238543fca932b2fd5b1965f0fc54ca2c81364ad545da79a927f663c26380abf3854346fd641ecf176ce734661d557cdc796a0dafeb6b8166815d6b96be7e5ba0bd88bbafdf168821db79a9acbf10d62f5cad82e8638b94d9661c475d5c4fe2b634f53c004c526617b443ffa31ed775c7ea1a3deaba6e8f031ebcd69029ddf11d8f312eda1747f52cb41dbbf61975ca873297423d1d9cc7a47d277537f876b1cd510b3987da6f68910b65be67b41d513aca3af03e80dbba145bcf070b2d7591323f36daa95d0e985c6e373ccf52eb3d68a9ab94f905b47f9fc3f9fc7efd3bb6a57fb1fc2e53baf600bf29bf3dfe3a27b7afbcdf28db77bbc5f787c01a93ef5adfa490f37df123f65cc8ff198edf524ef410ad855ded23f27e27b29bcbed3796cb87323b2cf52f0be2adff768367bbc1ac62e73710677f81f37d57ede68e088d0a41232983cf0accfb2d78ef048ffb0d755d20f31f01a3d87683beffc3e9fdf214db47069b79bfdc763e5868f0e3f9e0ff8276366129ebfe3940eadc06eb25f5088cba06465d1d9dbf96e6187a96819f0e60dfaff3a2b3fc86e7b85226a75deabfbbfb57b5ef630bb7d4039fd7ed35b8f719bae2bda896c0ade2debcb6c0f374c7d7b4a5782e669e0fe1759894c90376db79dc614b5dcce374b3e0c86bc16f8cb2789d9d6e3933ff91b10cde33386861b2b57db1bd9753545868f2dbdabd4306b34d57d90f30e6645de6be82e74352e66cd86e094b59d526fdd7c935fac876c47bedb6fb2cae8e1751f759c49f62b4bd33e9e21946537c37ad756cebed5a6e7bcec6de9fa1b5918fc77771051e2bd269b1d7c2e3ea9e6694167b2dbee3d3a2d3505b3b67d3628f85c7d5356694167b2cbe63d4a2d2766fc1a6c56e0b8fab6b8d282d765b7cc7a745e75af735d269b1cbc213ff3d8df45ae033b14c98f71030b736f2f1f82e2db73dbbb369b1d3c2e3ead95d94163b2dbee3d3a2a893ed9adda6c50e0bcf8e06d66287c5777c5a74e96abba762d362bb85c7c1fdb5b45a6cb7f88e312e86e1fdb5745a6cb3f06c6b602db6597cc7787ed829dd3d43d4e2430b8fab7b7f515a7c68f11da3164394efad75d062ab85676b036bb1d5e23b3e2dca3b2adf1fd4418b0f2c3c1f34b0161f587cc7a7c5902ecaf7963a68b1c5c2b3a581b5d862f11de33554322e36d7418bcd169ecd0dacc5668beff8b4a8489e6b6daa83169b2c3c9b1a588b4d16dff16951983ca66eac83161b2d3c1b1b588b8d16df31c645f27a72431db4d860e1d9d0c05a6cb0f88ef138928c8bf575d062bd85677d036bb1dee23b3e2d2a93f79fd6d5418b75169e750dacc53a8bef18efb924e3626d1db4586be159dbc05aacb5f88e4f8b92e431754d1db45863e159d3c05aacb1f88e4f8b61c96762abeba0c56a0bcfea06d662b5c5778ce79dc9f662551db45865e159d5c05aacb2f88ef1bc3379ff62651db45869e159d9c05aacb4f88eb1ed4c9e77aea883162b2c3caec6888cd2c2363e658ce79d492d96d7418be5161e57631b4669b1dce23bc6f3cee47164591db45866e1713516659416b67130638c8b64dbb9b40e5a2cb5f02c6d602d965a7cc7785f2bd9762ea983164b2c3caec6e688d26289c5778cd723c97b7c8beba0c5620bcfe206d662b1c5778ccf8a92e7e08beaa0c5220bcfa206d66211f83e10bbef547f6ef1217db1ae32b4c88532df31fa6245e928ebc07768b12ed5b1d725d5afecfd88ba54435da4cc0f8cbe7cef3b607254d764ccbca7d7257dd33fb6d455cafcb45d4dd99feb7c02b6c96158d71f2dbfcb9463cc97415ef453755e107f9d93b12ae300c9f65d60f1fd0eb0c6e4bb087de7e8247ec49e0bf9afdbd5949572a287682dec6a1f59a8f3c86e2eb7c8582e1fca2cb4d4bf2c88b7fe0b0c9e050673f2bd0788338923376d578a696184465781465206fbec1d76c4f3b1c1231ce22f2738f25d542923cbe2bba87f37faed4a3f48a967541fc9f71cd52faa8fa4f88b7a17d5aca38a8f1f40df4f191744c60c51361903a404d6d3d9b0a9ba76715457f125eb96f92ec0286392746e78c6e2ba32763218154f37079ae1382b32a53b5e74039eae0e781cd533791cea6ed4a98b51a77c2883ef36767750cf1cf02beb96f9eee0dbc536472de4987cb9a1452e94c92b48fd97f3c7281d651d2a7e3b5beae24ac74e064f278bef5e8e7594754b9bd8ab017cf7307c77347cab7d1b634c4de9f6ed1ec0dcd301b35a6feff8d75b88e78c12cfe2a723d4a90f6810579d705d728ed9c7d03617f21716d494957252568e9dc2aef623d996c86e2ed7cd582e1fcaf4b2d4bf2c88b7febd0d9ede06b33a6f38a3a086c3c1fe908c815e0687cc7704ed7a4768d70bb4933278ecede448bb9e068fcc77021e39bfea0e36394f11fe04fc5ed200dc66bbd7ddc22d361c8fb09385b163fc8cc5e98e0b1d81516c3d81a78723cdcc6d7db9a10f9e13b432cac8b2b950a64b41eabfbcab659655fbddf93935f56aaeedb1bdb7a6dbf4960ef4c2f14003d02730349449185a07356386c6c9737c503326e8848955e3873c32ec9e61a9c79e82966b60e2ff1c4b359a810df3cd2db620a83df4692ed864e8d316606b66c88243ae4a79193ad1855ca887ac3bd7e06c0d2c71fac66163654a173aad80c74528abd091a16375e8dc3f7ec4c461181f2d0ccefac48efaad799a7251eb9238c8755077649275cbbcf853fae4ebfcd8214347f619ffc8a4d1c3c64c9c80b0e6ce85f91c4304f3bf6d190c12dc99643d2d0c718e8f5f9c521ca3d8e40bc09f4cc2d03aa819c738469e64a0ca58c343878c1a75d7a4f2512386de3069ccd08923aac6a0a2ad0de5a2d496df5b82cdd6d4615935e1ee8bcbb6b2d86c138eeadc1a6cd2821f0736e1391e6ccd212fe5cd2de3641fb914d62f61ad7e53e2b4d0156f15d484801c9654fba2f621f51955753aa08696564349abcda9eed8a9a1a1d557e4d4d0cf6aa86735b4b31aca590dddac866a5643339f1ba4865e56772f0b82d450ca1704a9a1922f0a5243215f027cdf01e6cb82d4e9871acab87d901aaa58dd3e54af8fab4fada9f7dbd569acba3c56a77eea52479d86a9d32f759aad6e21a8db49ead4469d36aa5322751aa34ecb7b6badfb84e99a305d1ba6ebc2747d986e08d38d61ba294c3787e99630dd1aa6dbc2747b98ee08d39d61ba2b4c7787e99e30f50dd3bd416a38edfbc2747f901a6efb81203514f783416a98ee8782d410de0f07a9e1bd8704a9a1bf8706a961c18705a921c31f0952c3898f085243158f0c52431b8f0e52c323ab61cac706a921d1d550cb6a58663584b31ada590d0dad869156434eaba1a8d550d64f05a921b29f09d3b3416a08ed29619a1aa6e7c3f4ad30bd10a617c3f452985e0e52c3b2abe1dad530ee3383d4b0efb383d430f16af87835acbc1a6e5e0d43af86a757c3d6abe1ecdf08d39b617a2b4c6f07a9c702ea71887a4ca06ec1ab5bc4ea314d7590ba7dbd38483d66568fdd553704d52d4375535919a4ba31a96e5daa9b9beaf6a7ba41aa6ea1aa9bacea36acba51ab6ee5aa9bbd7aed40bd86a15e4b51afe9a8d796d46b5ceab536f59a9f7a5553bdfaa85ee555af36ef0f52b7a60f06a9c795ea76b5ba2dad6ed1ab5be89f86e9db412a26bf1ba6cfc2f4bd30fd5b98be1fa61f04a921a3d5f0d26a786a3594b51ae25a0d87ad86ce56436fab21b93f0f52437daba1c27f13a4861bff224cbf0b52439e7f15a486bbff4398be0ed31fc3f4a730fd394c7f09d35fc3f4ef61fa8f30fd2d4c7f0fd37f86e91f41cdb0e6d89014e8d6e77c3d3f64e2c461a3c74e2c985855307ad2a88923c68e7aa260f28889c30baa1e1b36be7254d5645cf8b77a611993bdcff8f1439e281831a662d8e3055593261654551694574d1a5351eb40fa7ff542e71ce971484545b4b3bce6ff02e989cdebe7b49d5e4e46bbbf397ddd2e685e0f412eabcf42b7d5b342f7ea23985cf2f54d9d0f164c185535b1a0b0604cf8373cf0564d1e56d1a1007f9b108a3c6162c1848943c64f2ca81c5f35baa0a803aeb7f0f87a5462fef16e604aceac9f389f9c9bfa5faf107be1bc7a28b0f8bcfa916e3eef5f20fdb09e4e3fab4f0d7f549f85feab9e84817ef0699165c2a4f289e3870c9d18bd708b7f65e144bb7a54f3ac76f5abe6b7ebe3ecfbf559e86ff5244c14d4c359e782ba3b0bfe3f8c06861db80206009b2d6c6f000000275e1f8b08000000000000ffed9d67741cc791c76701100ccb2508e64c28514c00178b44800994c41c642a8b4a044950224512140925cbb224cb39e71c64fb9c73b6efcebe6cdff97c3e873b6739e7f8e5fceeeedd7b7a573de832fe68f5acb0f014d483ad79afb83d85dea95fd554f7cc76f70c73d1d0f607929c2dd7925c103d7ee3bff7dacfe29fb7b5a678aca224672e239c3519e1accd08675d4638276584b33e239c9333c23925239c5353e4346c35d1c82d6dde6902714d9b319fb1984ecf404c0b198be98c0cc4b421ca461f3533239c8d19e19c9511ced919e19c9311ceb919e19c9711cef919e15c9011ce8519e15c9411cec519e15c9211cea519e15c9611cee519e16cca08e77919e13c3f239c176484f3c28c705e9422e71ae05c613f2fb69f2bede72afbb9da7ef277d6dacf66eb639ddd6f215967d8485a9dbf9548da48da493a9cbf75927491ac27e9b67f6bb27feb21d940b2916413c966922d360e5b492e21b994e432926d24db497690ec24d945b29b640fc95e927d24fb492e27790ac901922b48ae24b98ae46a926b48ae25b98ee47a87e520c90d243792dc447233c92d248748fa480e931c21394ad24f728ce45692db488e939c20b99de424c92992d32403246748ee20394b728e6490e44e92bb48ee26b987e45e27664f25b98fe46924f73b9c4f277980e4419287489e41f230c933499e45f26c92e7903c97e47924cf277901c90b495e44f262929790bc94e465242f277905c92b495e45f26a92d790bc96e47524af277903c91b49de6459b821bc99e42d248f90bc95e46d246f27f90b927790bc93e45d24ef26790fc97b49de47f27e920f907c90e443241f26f908c947493e46f271924f907c92e453249f26f90cc95f92fc15c95f937c96e473247f43f2b7247f47f2f724ff40f28f24ff44f279922f90fc33c9bf907c91e45f49be44f26f4eccbf4cf2ef245f21f9aad57dcd7e7eddd6e571b1ff20f94f5bfe86fdfca6fdfc96fdfcb6f39def907cd7d17d8fe45147f77d921fd8f20fede78fece78fede74fece74fede7cfece7cfede72fece72fede7afece7afede76fece76fede7efece7efeda799537d68ce50794a34bcf54629f551edc78a664e8583bf221ab99958d4dabff16793d5d7d97dfee4d84db2fb931c7dbdddaf778e33c5ee4f71f48d76bfd1d1cfb6fbb31dfd5cbb3fd7d1cfb7fbf31dfd8576ff42d0e7231873b57aa3abb5aa1ce8385f6b4037c9ea6a4157cf8703dd64ab9b043a3ebff5a09b6a75934137cdeaa6802e6f7553399624d3adae374a2b578a7de6b885b48f6be7a166a4cf7bc41cb741887766fabcfde6b88d02bc263f66d963cd84bc996d758da0b3dd4d340b7473ad6e36e8e659dd1cd0cdb7bab9a05b6075f340b7d0eae6836e91d52d00dd62ab5b08ba2556b708744bad6e31e89659dd12d02db7baa5a06bb2ba65a03bcfea9683ee7cab6b021daf71390f74175addf9a0bbc8ea2e001df7b517828eef0d2fb23ad34f4cc9c177ac9efba8f83bdc3f836e25f7cda05bc5fd32e856739f0cba35609b756ba15f615db3d5711f65fed663cbbd515a6da214b7890d691f978e6c8ebb29fde3c6f3769ba3e1b8f6829d0d10ab2db69ce2daa056b49db3c276585f07e55d5097eb713cf83ac3ece67ab2d196b794f95e8ff3bd02d4d9e8f1bf374ad7ff4d0ecf26877912f82f93b36d25cdd9516f15e7ecb550d7cd3dbee7998839bb17380472b6537376d45bc539db0f75dddce3fbde8998b30781432067fb6472b654d49c1d1a238b227feef16f9f8998b3b70147fa39dba1393bfaade29c7d08eabab9c7bf7f2762cede051ce9e76c579fde1b8c7aab38675f0275dddce3b1988998b3cf040e819cedd77e76d45bc539fb26a8ebe61e8f0b4ec49c7d3970a49fb3dd4239dba6391b0dcd7746913ff7788c7a22e6ec23c0917ece1ed1f1d9d16f15e7ec67a0ae9b7b3c5f321173f683b66ce619be66e7199680eeeb56b71478d3cfeda3ed42b95dd2dc1e5a071245fe1ce5b9bb8998db9fb36593c7df80b507acfba6d59d07ba6f59ddf9a0fbb6d55d007e09b4813e6d03a3de2a6e03df85ba6e2ef33cf2446c035f010e819c3da2393beaade29cfd15d475738fd7344cc49cfd3e7008e46cbfe6eca8b78a73f6bfa1ae9b7b2b6d7922e62caf2b35f70b3fb4f70bab41f723ab5b03ba1f5bdd5ad0fdc4ea9a41f753ab6b01ddcfac6e1de87e6e7545d0fdc2ea5a41f74bab2b81ee5756d706ba5f5b5d3be87e63751da0fbadd57582ee7756d705badf5bdd7ad0fdc1eabaadcecc77f1daab2f5a9d39b71c8fde28bd731bafb78a466e3967bf17cacdb23cc54234f25904b6b52e7d5b6dc6f79668f4beaf039ea280ef79b0311a9e22f0b4a6cf13af3b2da57fdcf81cb73831cd83ad16f0ab4dc0af1cd8e263f33edb2b800efb92360f637bfa8ca51cd8e263f37e3b30b20efb36bec670fb317d73536e9857a02dc5d767b4d70b1c6caf0eea2c9d335cf742cb361dfece7dc0742863dfdfeae8847235ce15b6c5c7e6fd1230b28fade3cf581a2d63d16194ea3772608b8fedda9eee898f8959bb27661d428ced0e23ef770023c7af7dfc194ba36574fb05a13ea975b47d12c7a575fc6336aaf35a001ddeff7578183bd3678ccf6b87c3c8fb9dc0c8ba36e091ba1e26b5d7506c4bdc87603ef3358baf3f6caf0eea74d50ed7dd0bd753813eb454e9bd29f6e9e99fa75211af67a3e1113e77ad42f958c4bef3b128dd5c73db7cab132b6cf3d8974bf593497d39db53666556666556666556666556666556666556666556666556666556666556e6f09993e6e57ceb199e4c46d6958047629c3f7e47953d16ce013d0af33ae9cf5b948a3857cfeb1857393ed7419dffcb0db3fdc8b34e02e7ced7393aa1754af1b9c4754abdb0cff670dd06ae9b12587b12f3ac75785cdbd33df109711d49486b3492d6698514b302e8703d5c8b104f529eb5786c37a566bb7444a6ed948ae67d40e69d7adc9fb86d04d7bead7174a64feaa91df65b22072a9d77c6eb0697d39cc7c57c435be9afb7298d589f50138dbc56e03d85c01a9511f3d5bc36a2d3b15d0775a6d6447f3a37ebe1efbdd1e3d708993a5dceb1f93babe0bb5dceb11be4fc2ddb1f76023797eb1ddf9a819bebcca819f6f1b3b62c743f53c2f5b311f0468e4fbce1fa8cf4eff786d68bb455c0d3013c126bd784ee6b8b988f69af17e97262e5bb5fe63a9d10bf2e81f8955bb3c6f694599995599995599995599995599995599995599995599995599995599995397c667cff05b3e233d2a54018c7698d4d3c9fc1ef32c279b1b7d40cdb959e03e439a7d58ecff88cf26f6b86d9de6ecbf88e00dff3ee782ea5e6d692ce25db9b1e3dfe397da17339ea773f747862d6e589d97a2146b7cfe0fdf5c0c8f1eb021ea9f6d8e9f0b8b6b1cfe808346649fdacd4fa95a43cf3ad53684acdf6d07a1189795d5e2fe25ebf4a4e4c719d04eb701e1cdfad12f2fb5fdcb50bd84fe11aadf4fbcdd288396077ad20dbc375125fb0b1e57512e9f703a5a2e43582db28af0969f3f8ca75be04d7b92fdb32ae152ac1b11ef5fc9db7726b12b04f4dfd1d9cc5a1397e7e77259fdf1e8fed8dc09a92ed56b49db3c276585f07e5efd50cd7e57a1c0f8e35b39b36c2ef324476f77badcef70a50a7dbe37f6f94aeff3d0e4f8fc36c72e7ab90678fc2bd9e549fd49d10a3551023ae83f7bc52d72f77cdb6bb5619fbd1c94e1dfe6e1dd4f919f45195bc2b4aea7e21e91a80f70bee7561346bc7ab7d3de01fa1bf487b3de01f21877cf7a57cfcd5707ce69a1c255f5bb8ceff3ad75181f57aa37aef95efb71ff3e27a43aef318f45545bb2e37e9778cef390ba9df0d49cf7db03dbca7aac477ec17d2be36623e220be6f29faed136d69c8f5d09dceb3cdfcd277c9763c5ebcbf177b21b3f13876ef84e6f2a7118ea6f7a1c5fb84d75832f5ca7117c91b9671abaff4cdfd791f743dc07b57b7ce53af3e05d700b6c390fe709fbca8b3d7fe7addcfd27c7cff83cdeef5447db21bc537d45ed705df7dde81ceb4adfa9dee97c2fc477aa2f863cbb189eb590eaab3726c46835c488ebe0b38eeeefffa46bcc93f95e52b7dfc4ebe478b2b9e3b7befb13ae83f7d05ca703fad9bca7ae3b2ecdd79034d7a7e3f3406bc12e3e0fb456289e8568643c0b0e87a4ed06c776c338da6e746c378ea36d8db9c63ca4980bfcdf1363febf30f0ffaca8c900636d0618eb32c03829038cf519609c9c01c62919609c9a01c6691960cc03e393796d17884f29b0ffefa9ecbd06da16789f431c8be668f4b16891e5297bef83b605dea152f1ff3720fc7f61b58ef5ffc22ac0f766658071760618e76480716e0618e76580717e0618176480716106181765807171061897648071690618976580717906189b32c0785e0618cfcf00e3051960bc30038c176580718532a6c2b84696b114daffe39c8f46ae357b221ee1778fc6ef50f4bde754e2ffc6add477e1f70eb78ef53d7db8c642f6ff7afcf3de2528b186a2d2770996fbffb185184b6365945a4b8eeba847c383cfa1fa9e6f11602c8d9551ea19147c2672343cbeffab57f699a0a1988d85516acd58a56b1af159c14e4fcc04184b6365947aee009f891c0d8fefd9c55659c6d25819a5d6e7e6c1c66878ba2166eb3d3113602c8d9551e8f9b23866dd15f0e07358dd9e98093096c6ca68783608c5aca7029e0d10b31e4fcc4262449eb4df89dee3b125f1dc5ea5be3303324ecd00e3b40c30e23a0989feabdc3a891ed9f894c61a1fa9f3556e9d04da16784e248e053e17f044b1d824cb53769d04dade2c140b7c6ee38962b11978249e23c9838dd1f0304301be372b038cb333c03827038c7333c0382f038cf333c0b820038c0b33c0b828038c8b33c0b824038c4b33c0b82c038ccb33c088bf5505ee15cbfe7ed93cc16d27fd5699e8b6937e974c74db9ae79ae7d5605bf35cf3bc1a6c6b9e6b9e57836dcd73cdf36ab0ad79ae795e0db635cf35cfabc1b6e6b9e67948b6b330c6af8c138f11799ad2e329a2ef68ab3700df7b3d3c3921dfd1d6d6007c6786ac316ec900e3860c306a1c87d6208e85d1f05c22c4b3b5029e4b80e752219e4b2ae0b914782e4b9f27cea94b2be06186027c6f430618b7648051e3a8710c8951e3583d715446655446657c3218b3d0872b6326f2b1345646c3b32d7d9e38669755c0b30d62c6df6b95652c8d95d1f06c4f9f278ed9b60a78b643ccb6796226c0581a2ba3e1d9913e4f1cb3ed15f0ec80986df7c44c80b1345646c3b3337d9e38663b2ae0d90931dbe18999006369ac8c866757fa3c71cc7656c0b30b62b6d3133301c6d258190dcfeef479e298edaa806737c46c972766028ca5b1321a9e3de9f3c431db5d01cf1e88d96e4fcc04184b6365343c7bd3e78963b6a7029ebd10b33d9e98093096c6ca6878f6a5cf13c76c6f053cfb20667b3d310b9571430618b7648051388ea5b1321a9efd423cfb2ae0d90f3c970bf1ecaf80e772e0794afa3c714e5d5e010f3314e07b1b32c0b825038c1a478d63488c1ac7ea89a3322aa33256c6d89b01463dd7ca182aa3c0efabb2cfd05c3ec16d3738b61baac476d2333413ddb6e6b9e67935d8d63cd73caf06db9ae79ae7d5605bf35cf3bc1a6c6b9e6b9e57836dcd73cdf36ab0ad79ae795e0db635cf35cfabc1b6e6b9e67935d8d63cd73caf06db9ae79ae7d5605bf35cf3bc1a6c6b9e6b9e57836dcd73cdf36ab0ad79ae795e0db635cf35cfabc1b6e6b9e67935d8d63cd73caf06db9ae79ae721d93e90beed52a5cfb01e001e89676a85fc2c9ae35e618ff5588af133b1bad289d5e54eac0a50e70a88df9502f1cb815d3e36efb3bd4a992f0e8059c87669061d632af8cf36b638f130f6af12f23da9afbf6a82db4eeaeb27baeda4be7ea2dbd63cd73caf06db9ae79ae7d5605bf35cf33c14db589e140ddfb7f3fb95cc31ae86bfe71c56b3d5419d4d93873e1b226d4312b6b50de9b5a21a6c6b9e6b9e57836dcd73cdf36ab0ad791e669e5f93beed786e0c7f5f98addcdcd835c073b5402c84fc2c1a9fae757cbacaf1a90075f09db5d70af89903bb7c6cdebf16ce43d6980dcf665b66d63cd4db1c0823ebae96e589dbd7e668e456ae7d5d0b3c02eda055c8cfb87d5de7f8b4d91377ae83b97a9d809fbeb6c3fbd7c179c81ab3e1d96acbcc9a877a5b036164dd35b23c71fbda1a8ddccab5afeb8047a2ff11f2336e5fd73b3e6df5c49deb60ae5e2fe0a7afedf0fef5701eb2c66c782eb16566cd43bd4b026164ddb5b23ced79f099b772edeb7ae091e87f84fc8cdbd741c7a74b3c71e73a98ab0705fcf4b51dde3f08e7419995d9c76c78f8ff9467d63cd4bb341046d65d27cad35ecc83cfbc95ebc70e028f443f2f14f7b81fbbc1f1e9524fdcb90ee6ea0d027efada0eefdf00e7a112e62d1964d6386b9c939835ce1ae724668db3c6398959e3ac714e62d6386b9c939835ce1ae724668db3c6398959e3ac714e62d6386b9c939835ce1ae724668db3c6398959e3ac714e62d6386b9c939835ce1ae724668db3c6398959e3ac714e62d6386b9c939835ce1ae724668db3c6398959e3ac714e62d6388f8dd9f05c66cbcc9a877a9705c2c8baeb6579e2e7772e8b466e3967bf17ca3700cf4181f808f919af7bbfd1f1e9324fdcb90eb6af1b05fcf4b51ddebf11ce4325cc5b32c8ac711e1bb3e1d966cbcc9a877adb026164dd41599eb81fdb168ddccaf56337028f443f2fe467dc8fdde4f8b4cd1377ae83edeb26013f7d6d87f76f82f3a0cccaec63363cdb6d9959f3506f7b208cacbb4194a7143f87b83d1ab995ebc76e021e897e5e28ee713f76b3e3d3764fdcb90ee6eacd027efada0eefdf0ce7a112e62d1964d6386b9c939835ce1ae724668db3c6398959e3ac714e62d6386b9c939835ce1ae724668db3c6398959e3ac714e62d6386b9c939835ced51367c3b3c39699350ff57604c2c8ba1b4579dae279871dd1c8addcbcc3cdc023312f2314f778dee116c7a71d9eb8731d6c5fb708f8e96b3bbc7f0b9c8789cebc2583cc9a1be3c3acb9a1cc49cc9a1bca9cc4acb9a1cc49cc9a1bca9cc4acb9a1cc49cc9a1bca9cc4acb9a1cc49cc9a1bca9cc4acb9a1cc49cc9a1bca9cc4acb9a1cc49cc9a1bca9cc4acb9a1cc49cc9a1bca9cc41c426e144876da32b3e6a1dece40185977932c4ffcde839dd1c8addcba9d5b80e76681f808f919afdb39e4f8b4d31377ae83edeb90809fbeb6c3fb87e03c1c526665f6301b9e5db6ccac79a8b72b1046d6dd2ccb13f763bba2915bb97eec10f048f4f3427ec6fd589fe3d32e4fdcb90ee66a9f809fbeb6c3fb6c4f99953989d9f0ecb66566cd43bddd8130b2ee16599eb81fdb1d8ddccaf5637dc07348203e427ec6fdd861c7a7dd9eb8731dccd5c3027efada0eef1f86f3a0cccaec63363c7b6c9959f3506f4f208cac3b24cb53ca83cfbc95ebc70e038f443f2fe467dc8f1d717cdae3893bd7c15c3d22e0a7afedf0fe11380f5963363c7b6d9959f3506f6f208caceb93e589dbd7de68e456ae7d1d011e89fe47c8cfb87d1d757cdaeb893bd7c15c3d2ae0a7afedf0fe51380f5963363cfb6c9959f3506f5f208cac3b2ccb13b7af7dd1c8ad5cfb3a0a3c12fd8f909f71fbea777cdae7893bd7c15ced17f0d3d77678bf1fce43d6980dcf7e5b66d63cd4db1f0823ebb09fe2ad0618f70b31460e63e4c407799605c67320309e0581f1cc0a8c676a603cab02e3a90d8c677d603c1d81f19402e3591e18cfc2c0786607c6332d309eb581f1d405c6b322309ed581f12c0a8c674e603cf9c0789a03e39914184f4f603cdd81f1ac0c8ca733309eb6c078d605c6b338309eb981f1ac098c677a603c85c0785a02e3a90f8c6763603c4b02e3991718cf8cc0781a02e3991c18cfa6c078ba02e3690f8ca71818cfd2c078e607c63333309ec6c078a604c6930b80271f3d7e1d431efe7e007435ce77cdf5e5f09ce1bff3bc710d7ce7982dd77a8edd0f3a9e673ee6f92ec6496a2e1c6df5c23edb9b0e1cc702e19912184f63603c3303e3991f18cfd2c0788a81f1b407c6d31518cfa6c0782607c6d31018cf8cc078e605c6b324309e8d81f1d407c6d312184f21309ee981f1ac098c676e603c8b03e35917184f5b603c9d81f1ac0c8ca73b309e9ec0782605c6d31c184f3e309e3981f12c0a8c6775603c2b02e3a90b8c676d603cd302e3991d18cfc2c0789607c6530a8ca723309ef581f1d406c6b32a309ea981f1cc0a8c6741603c0702e35916184f8d87e780104fd2b3cd0702b12d701e8ae6b8b70af9749b3d56bd3d2ef3b3bd3aa873811d7834f31ff85de672e7ffb1eddc0631927aaf44c1e1e1fda313dc768363bba14a6c373ab61babc4b6e6b9e67935d8d63cd73caf06db9ae79ae721da7e2c3ddb1dfa7ea9d1f3e8fb9ccaf3e8fb9ccaf3e8fb9ccaf3e8fb9ccaf3e8fb9ccaf3e8fb9ccaf3e8fb9ccaf3ac088c47dfe7549e47dfe7549ea739309e4981f1e8fb9ccaf3ac0c8c47dfe7549e47dfe7549e47dfe7549e677a603cfa3ea7f23cf581f184f63ea7d0de07afef972acf3323301e7dbf54791e7dbf54791e7dbf54791e7dbf54791e7dbf54799e2981f1e402e079a2f74be17ba16eb3e5a3a0e3f5a5e5de439587e3dc063a1ecfe56398ebd5a9398f67a881ef1cf770ddeab1c7768e7bbe3b1e71475bbdb0cff6f07d55c703e19912184f63603c3303e3991f18cfd2c0788a81f1b407c6d31518cfa6c0782607c6d31018cf8cc078e605c6b324309e0381f16c0c8ca73e309e96c0780a81f14c0f8c674d603c7303e3591c18cfbac078da02e3e90c8c6765603cdd81f1f404c63329309ee6c078f281f1cc098c6751603cab03e35911184f5d603c6b03e3991618cfecc0781606c6b33c309e52603c1d81f1ac0f8ca736309e5581f14c0d8c6756603c0b02e35916184f8d8747ea9d5149cfd78fc7fbaa9ec8b6d95f0b71315b1efe3e1ecf711d7018791fd73d202ff3ac15e2497a2fc0da006c1bfff9b7e80cfb9987bfe373385239b5d661e47d5f4ee1bac666219ea4f719340760dbc4a2c596790d401efede028c5239d5ec30f2be2fa71a6579daf3e0336fe5d61a619b933887427e16b1fda5f80e8da289d57e27562d4eac0a50673cd6a527f5076c4f99953989d9f0f05c0ab3e2f56c3c9e331b0da3effa2ac013f78feba2915bb9fe713ff0485c3f84fc8cfbb1138e4feb3c71e73a98ab2704fcf4b51dde3fe1b1dd14a51b8bdb47118bdb3d3cb78f732cd85ea5cc0732c81c429c0d0faf4564565cdf5c0c8491756b6579e2feb1188ddccaf58fb7038fc4f543c8cfb84f38e9f854f4c49deb60fb3a29e0a7afedf0fe49380f95309fc820b3c6796ccc8687e72098350ff54a8130b26ebf284fa998079f792bd78f9d041e897e5e28ee713f76caf1a9e4893bd7c1f6754ac04f5fdbe1fd53701e94599995599995599995599995599995599995599995599995599995599995396c66c3c3cfc6326b1eeab505c2c8badb457986e61ddaa2915bb9798753c023312f2314f778dee1b4e3539b27ee5c0773f5b4809fbeb6c3fba7e13c28b3322bb3322bb3322bb3322bb3322bb3322bb3322bb3322bb3322bb3322b73d8cc8687dfd9ceac79a8d71e0823eb4ecaf2c4cf6db54723b772f30ea781e794407c84fc8ce71d061c9fda3d71e73a98ab03027efada0eef0fc079506665f6311b1e7e571bb3e6a15e47208cac3b25ca33347fda118ddccaf56303c023d1cf0bc53deec7ce383e7578e2ce753057cf08f8e96b3bbc7f06ce4325cc2732c8ac71d63827316b9c35ce49cc1a678d7312b3c659e39cc4ac71d63827316b9c35ce49cc1a678d7312b3c659e39cc4ac71d63827316b9cc7873984381b1efe3f0499350ff53a036164dd69519eb678dea1331ab9959b7738033c12f33242718fe71dee707ceaf4c49deb60fbba43c04f5fdbe1fd3be03c4c74e6131964d6dc181f66cd0d654e62d6dc50e62466cd0d654e62d6dc50e62466cd0d654e62d6dc50e62466cd0d654e62d6dc50e62466cd0d654e62d6dc50e62466cd0d654e62d6dc50e62466cd0d654e62d6dc50e624e61072c3f074d932b3e6a15e57208cac1b90e589df7bd0158ddccaaddbb90378ce08c447c8cf78ddce59c7a72e4fdcb90eb6afb3027efada0eef9f85f3a0cccaec63363ceb6d9959f3506f7d208cac3b23cb53ca83cfbc95ebc7ce028f443f2fe467dc8f9d737c5aef893bd7c15c3d27e0a7afedf0fe39380f5963363cddb6ccac79a8d71d0823ebf0badc2dc45370780a9e583c59b6cd7e8f2d4fb79f79f87b0f304af587dd0e23ef638e232ff3f408f134383c0d9e583c59b68dff1b6d7986fdccc3df3702a3544ef5388cbcefcba906e0d928c4d3e8f0347a62f164d936b1d864cb33ed671efebe0918a5726aa3c3c8fbbe9c6a049e4d423c497dd2a671b09dd4bec6c37652ae8c876d8d7972cc05da5d3c3eb0291ab995bbafc66b8b445f25e467d177fddee4f884d76fbc477db2ae4fcaaccc49cc42f7b9ed79c736c7277278783b2b1c8bf1fc9ddde3f89485dfd9e5984f649059e33c3666637b307ddbed79c736c7277278781b148e85909f717f7067e48f31db2b401dccd33b05fccc815d3e36efdf09e7a112e6131964d6388f8dd9d8be2b75db43ef1f46db1c9fc8e1e1ed2ee158c8f839d41fdc1df963ccf60a5007f3f46e013f7360978fcdfb77c37950666556666556666556666556666556666556666556666556666556666556e6b0998ded7b52b73d347e8fb6393e91c3c3db3dc2b190f17368fcfedec81f63b657803a78ceef15f0330776f9d8bc7f2f9c07655666655666655666655666655666655666655666655666655666655666650e9bd9d87e6afab6e3e771d036c7277278787baa702c84fc8cc7efef8bfc31667b05a883e7fc3e013f7360978fcdfbf7c179506665f6311bdb4f4bddf6d07c1edae6f8440e0f6f4f138e858c9f43fdc1fd913fc66caf0075f09cdf2fe0670eecf2b179ff7e380f95309fc820b3c659e39cc4ac71d63827316b9c35ce49cc1a678d7312b3c659e39cc4ac71d63827316b9c35ce49cc1a678d7312b3c659e39cc4ac71ae9e381bdb4f4fdd765b3c7e8fb6393e91c3c3dbd3856321e3e7d0f8fd03913fc66caf0075304f1f10f0330776f9d8bcff009c8789ce7c2283cc9a1be3c3acb9a1cc49cc9a1bca9cc4acb9a1cc49cc9a1bca9cc4acb9a1cc49cc9a1bca9cc4acb9a1cc49cc9a1bca9cc4acb9a1cc49cc9a1bca9cc4acb9a1cc49cc9a1bca9cc4acb9a1cc49cc9a1bca9cc41c426e18db0fa66f3b7e9e1d6d737c228787b707856321e467bcfee5a1c81f63b657803a98a70f09f89903bb7c6cde677bcaaccc49ccc6f633d2b75dca3bb6393e91c3c3db33846321e467dc1f3c1cf963ccf60a5007cff9c3027ee6c02e1f9bf71f86f39035663c7fb9f46cc7eb36d9468dfd34ba67da722de89e65cb75a07bb62d4f02dd736cb91e74cfb5e5c9a07b1ef8c6bae7dbf21ad0bdc0963781ee85b6bc11742fb2e51ed0bdd896bb41f7125b3e0bba97daf239d0bdcc960741f7725bbe1374afb0e5bb40f74a5bbe1b74afb2e57b40f76a5bbe1774afb1e5a782eeb5b67c1fe85e67cb4f03ddeb6df97ed0bdc1969f0eba37daf203a07b932daf00dd9b3dbab7d8f283a07bc4961f02dd5b6df900e8de66cb5341f7765b9e06babf80327fbec396a783ee9db65c00ddbb6c7906e8de6dcb0da07b8f2dcf04dd7b6db91174efb3e559a07bbf2dcf06dd076c790ee83e68cb7341f7215b9e07ba0fdbf27cd07dc4961780eea3b6bc10741fb3e545a0fbb82d2f06dd276c7909e83e69cb4b41f7295b5e06ba4fdbf272d07dc696f1fcfea52d3f0374dcaf3c0c3aee579e093aee579e053aee579e0d3aee579e033aee579e0b3aee579e073acebbe7838ef3ee05a0e3bc7b21e838ef5e043acebb17838ef3ee25a0e3bc7b29e838ef5e063acebb97838ef3ee15a0e3bc7b25e838ef5e053acebb57838ef3ee35a0e3bc7b2de838ef5e073acebbd7838ef3ee0da0e3bc7b23e838efde043acebb37838ef3ee2da0e3bc7b04744db6fc56d09d67cb6f03ddf9b6fc76d05d60cbd8cf5c68cbef00dd45b6fc4ed0715ff82ed05d6ccbef06dd4a5b7e0fe856d9f27b41b7da96df07ba35b6fc7ed0adb5e50f80aed9963f08ba165bfe10e8d6d9f2874157b4e58f80aed5963f0aba922d7f0c746db6fc71d0b5dbf22740d761cb9f045da72d7f0a745db6fc69d0adb7e5cf808eafe3dccf98f66cda25c781636474ec738bc717d64d015f7aa374efe9d8161f9bf7db8091cf4169fc194ba3656c75180d4f8740cc30af782bf79ba90378da057884fc8c7f33753a3eb5393e15a0cec5e067a7809f39b0cbc7e6fd4eb02d71ce3116f5f6b82b9d58d4419d767b9133d7d37271e46398fc2d797c918a63abc3d3eab1dd2d1c473e36f789dde360bbcbb15d746ce3b580b7726dbb0b98d70b309be3f6a47fdcb86d6fb0c7e27c663b45f06923c4202d9fd076ce0adb617d1d94f7cc19aecbf5381e7ced6476d38ef85c22bbfbbd0ee77b05a8d3edf1bf374ad7ff1e87a7c76136bf277ae70c7308b4873807ba1d0ede2f42ec7a1262d70db1e33a78ed6d168add7a8787f79b8187efaf3a41c7f729cc8ff7782de3c0edf67b9d1e6ed6750163b387b1943e637c9fd5ec30f27e091859b71e78ba8462e69eeb954e7cf09e60b25387bf5b07750ec17539efa96bda5d536ed82ffefdff58946e9f5e2f102f1c9b88203e911343de98614a343c7e9126cfb468787ce2dce0c0d9be5bfbafe8ef3b9a03b43a07133f731e376a4087e55a8f2e8a460ec3e070300fc3e070708d13161cfee1fae6679c718b873afa4f1d1fbcfa74ffe92367ef3d33d87f74efc0ad483dc9a147d2240f901475bc4d8986078c7aa3742782ea1d5be592670a7c4e4e9fa755c8cff8a237d5f1a9def1a9007526c1dfa60af89903bb7c6cde9feab19d624714c762da286231cdc3336d9c638183eeacc396ca7fc7899b1ac7176cd1e8939be7a93ac40657c0f17316cefccd34f649d699c9d1f0c9e6ded3dcd19a9360466bcd55cb8cc69ad157d30599d155734133a3a766b4d48c8e9ad15033fa69463bcde8a619cd34a39766b4d28c4e364543a38f66b4d18c2e9ad1c48b80ed8bc06b7ed19b2ba4190d34a37f66b4cfdc59993b00733762eebecd9da2f9f568ee10ccaf5a33c261aeb6e64ec65ca5cd95d5dc299a3b4473476fee70cd0cd966922d36d65b492e21b994e432926d24db497690ec24d945b29b640fc95e927d24fb492e27794a3434b27f05c9952457915c4d720dc9b524d7915c4f7290e406921b496e22b999e4169243247d2487498e901c25e9273946722bc96d24c7a3a15541b7939c243945729a6480e40cc91dd1d02c9d999533b37066d6cdccb2995935338b6666cdcc2c99991533b36066d6cbcc729959ad07a3a1d928331361661ecc4c83995930330966e6e0b9d1d0cc80990978413434d26f46f6cd48be19b93723f56664de8cc49b917733d26e46d6cd48ba19393723e56664dc8c849b916f33d26d46b6cd48b619b97e241a1a993623d166e4d98c349b916533926c468edf1d0d8d0c9b916033f26b467acdc8ae19c93523b766a4d68ccc9a915833f26a465acdc8aa19493523a766a4d48c8c9a91d0bf22f96b92cf927c8ee46f48fe96e4ef48fe9ee41f48fe91e49f483e4ff205927f26f99768282fff95e44b24ff46f265927f27f90ac95749be46f27592ff20f94f926f907c93e45b24df26f90ec97749be47f228c9f7497e40f243921f91fc98e427243f25f919c9cf497e41f24b925f91fc9ae43724bf25f91dc9ef49fe100dcfac602732c5f63c3ccadf3738d87feacc60d3e040d3a93b4f0e1e3f73f2dea6bb8f0fded6347057ffd9632707eec62f7fde7e99a730b69e3ddb776fd3f1d347fbef691ab873b069e058d3e1813b4f1f3d875ffaa9fdd292c75bec3b7a34d9d87ffd39a4ff3346a3936d9fc89343bbcafb36ad760c019939962fb5d78ecda18df6aac3bfdeaf1cbadb6d3a777260b0a9d8749afeed3b49dfe93fdad2847f3b47413e37d8746eb0efec60d3b1b303a79a5a5bf0b8e74f1f83136d73c6f0a55be68cdef3e8ff0117b9177df9d90300", "privateFunctions": [ { "selector": { @@ -37,8 +37,8 @@ exports[`ContractClass creates a contract class from a contract compilation arti "isInternal": false } ], - "id": "0x01d273e0c02fb9a303814be7a40a168c5bc1604e452f678af77d5feb119dec2f", - "privateFunctionsRoot": "0x05fa82a96814b6294d557d507151f7ccc12f70522ec4d9d0395a90e87e8087c6", - "publicBytecodeCommitment": "0x0084bda5b128cd65dbe6d5d9b4e57417838565f6e7437aa697c8fa607a305c42" + "id": "0x2b12563e1077ddd2c9bf9744b3821b10527f5f53eb2d7e19c9127a2d54950d7c", + "privateFunctionsRoot": "0x2dc1f38d7be98a8e72227d6f8aec393c60db813a1819c9c86b02a00cc18f6687", + "publicBytecodeCommitment": "0x007bba6cd51becafe96d612dd43867a5887d064f5e30abb1ba341b475c013048" }" `; diff --git a/yarn-project/protocol-contracts/src/gas-token/__snapshots__/index.test.ts.snap b/yarn-project/protocol-contracts/src/gas-token/__snapshots__/index.test.ts.snap index 27a07f0273c1..307813e73c5b 100644 --- a/yarn-project/protocol-contracts/src/gas-token/__snapshots__/index.test.ts.snap +++ b/yarn-project/protocol-contracts/src/gas-token/__snapshots__/index.test.ts.snap @@ -2,11 +2,11 @@ exports[`GasToken returns canonical protocol contract 1`] = ` { - "address": AztecAddress<0x1ad6b44772790199d32f045454767652210040229e609aff0eaf3efb5caaf430>, + "address": AztecAddress<0x0edd48e2b72e1bc45f77a192b7ef4d9caef653566124c140724b99f8497c7882>, "instance": { - "address": AztecAddress<0x1ad6b44772790199d32f045454767652210040229e609aff0eaf3efb5caaf430>, - "contractClassId": Fr<0x26930ec0721619c525633357b71f7fa0f8009472bd5243a628e1bf26bed82831>, - "initializationHash": Fr<0x0bf6e812f14bb029f7cb9c8da8367dd97c068e788d4f21007fd97014eba8cf9f>, + "address": AztecAddress<0x0edd48e2b72e1bc45f77a192b7ef4d9caef653566124c140724b99f8497c7882>, + "contractClassId": Fr<0x1808ee042362366356e656b9b4cbd3dde68e4153805d336ea244eb5d1a96afc8>, + "initializationHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "portalContractAddress": EthAddress<0x0000000000000000000000000000000000000000>, "publicKeysHash": Fr<0x27b1d0839a5b23baf12a8d195b18ac288fcf401afb2f70b8a4b529ede5fa9fed>, "salt": Fr<0x0000000000000000000000000000000000000000000000000000000000000001>, @@ -17,17 +17,11 @@ exports[`GasToken returns canonical protocol contract 1`] = ` exports[`GasToken returns canonical protocol contract 2`] = ` { - "artifactHash": Fr<0x076fb6d7493b075a880eeed90fec7c4c01e0a24d442522449e4d56c26357205f>, - "id": Fr<0x26930ec0721619c525633357b71f7fa0f8009472bd5243a628e1bf26bed82831>, - "privateFunctions": [ - { - "isInternal": false, - "selector": Selector<0x90fa17bb>, - "vkHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - }, - ], - "privateFunctionsRoot": Fr<0x13b29c3f4a96eb14d5d3539a6308ff9736ad5d67e3f61ffbb7da908e14980828>, - "publicBytecodeCommitment": Fr<0x0814d00c42baccb4f02771bea96111ca7c8f5fe6025694db72218e26da78e7ee>, + "artifactHash": Fr<0x18af4bb0ca6fe07d0ae6da493b2c7b1af038ee904721dbba9b6e571e6d495726>, + "id": Fr<0x1808ee042362366356e656b9b4cbd3dde68e4153805d336ea244eb5d1a96afc8>, + "privateFunctions": [], + "privateFunctionsRoot": Fr<0x15d28cad4c0736decea8997cb324cf0a0e0602f4d74472cd977bce2c8dd9923f>, + "publicBytecodeCommitment": Fr<0x15e2c81e6653a3f622f40fa10a5ccb9bf85415cc96441fd7917e656acc04c422>, "version": 1, } `; From 9818d7e7c6a8a1ef899d62bce2626835b02fca64 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Thu, 14 Mar 2024 19:24:55 +0000 Subject: [PATCH 086/139] fixup readme --- barretenberg/cpp/src/barretenberg/dsl/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/barretenberg/cpp/src/barretenberg/dsl/README.md b/barretenberg/cpp/src/barretenberg/dsl/README.md index 0e91448b61f4..9a76586bde52 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/README.md +++ b/barretenberg/cpp/src/barretenberg/dsl/README.md @@ -24,7 +24,7 @@ A full change is when you attempt to change the object whose buffer we are actua Even if you correctly update all serialization in [acvm_js](../../../../../noir/noir-repo/acvm-repo/acvm_js/README.md) such as during [execution](../../../../../noir/noir-repo/acvm-repo/acvm_js/src/execute.rs#57), there is multiple places the `yarn-project` uses the ACIR top-level serialization. The `yarn-project` sequencer also uses the native `acvm_cli tool` that has an execute method that [expects raw byte code](../../../../../noir/noir-repo/tooling/acvm_cli/src/cli/execute_cmd.rs#63). -In the context of Aztec we need to regenerate all the artifacts in [noir-projects](../../../../../noir-projects/bootstrap.sh). This regeneration assumes that we have rebuilt the compiler from which we got the original ACIR object from to use the new serialization. After regenerating these artifacts we can bootstrap the yarn-project. There are multiple packages in the yarn-project that rely on pre-computed artifacts such as `yarn-project/circuits.js` and `yarn-project/protocol-contracts`. +In the context of Aztec we need to regenerate all the artifacts in [noir-projects](../../../../../noir-projects/bootstrap.sh). This regeneration assumes that we have rebuilt the compilers (Noir compiler and AVM transpiler) to use the new serialization. After regenerating these artifacts we can bootstrap the yarn-project. There are multiple packages in the yarn-project that rely on pre-computed artifacts such as `yarn-project/circuits.js` and `yarn-project/protocol-contracts`. The Aztec artifacts can be individually regenerated as well using `yarn test -u`. You can also run the command on the relevant workspaces, which at the time are the following: From fc4a158cd410db30378973681b0a8b4406cb8bcc Mon Sep 17 00:00:00 2001 From: vezenovm Date: Thu, 14 Mar 2024 19:46:34 +0000 Subject: [PATCH 087/139] re-run serde for acir after bad merge --- .../dsl/acir_format/serde/acir.hpp | 32 +++++++++---------- .../noir-repo/acvm-repo/acir/codegen/acir.cpp | 30 ++++++++--------- 2 files changed, 31 insertions(+), 31 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 aaa518cd4f3e..47e6b615b833 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/acir.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/acir.hpp @@ -1465,24 +1465,24 @@ inline BinaryFieldOp::IntegerDiv BinaryFieldOp::IntegerDiv::bincodeDeserialize(s return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryFieldOp::IntegerDiv& obj, +void serde::Serializable::serialize(const Program::BinaryFieldOp::IntegerDiv& obj, Serializer& serializer) {} template <> template -Circuit::BinaryFieldOp::IntegerDiv serde::Deserializable::deserialize( +Program::BinaryFieldOp::IntegerDiv serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BinaryFieldOp::IntegerDiv obj; + Program::BinaryFieldOp::IntegerDiv obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryFieldOp::Equals& lhs, const BinaryFieldOp::Equals& rhs) { @@ -1547,24 +1547,24 @@ inline BinaryFieldOp::LessThan BinaryFieldOp::LessThan::bincodeDeserialize(std:: return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryFieldOp::LessThan& obj, +void serde::Serializable::serialize(const Program::BinaryFieldOp::LessThan& obj, Serializer& serializer) {} template <> template -Circuit::BinaryFieldOp::LessThan serde::Deserializable::deserialize( +Program::BinaryFieldOp::LessThan serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BinaryFieldOp::LessThan obj; + Program::BinaryFieldOp::LessThan obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryFieldOp::LessThanEquals& lhs, const BinaryFieldOp::LessThanEquals& rhs) { @@ -1588,24 +1588,24 @@ inline BinaryFieldOp::LessThanEquals BinaryFieldOp::LessThanEquals::bincodeDeser return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize( - const Circuit::BinaryFieldOp::LessThanEquals& obj, Serializer& serializer) +void serde::Serializable::serialize( + const Program::BinaryFieldOp::LessThanEquals& obj, Serializer& serializer) {} template <> template -Circuit::BinaryFieldOp::LessThanEquals serde::Deserializable::deserialize( +Program::BinaryFieldOp::LessThanEquals serde::Deserializable::deserialize( Deserializer& deserializer) { - Circuit::BinaryFieldOp::LessThanEquals obj; + Program::BinaryFieldOp::LessThanEquals obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp& lhs, const BinaryIntOp& rhs) { diff --git a/noir/noir-repo/acvm-repo/acir/codegen/acir.cpp b/noir/noir-repo/acvm-repo/acir/codegen/acir.cpp index c9fa442d94d0..f5bbf587583c 100644 --- a/noir/noir-repo/acvm-repo/acir/codegen/acir.cpp +++ b/noir/noir-repo/acvm-repo/acir/codegen/acir.cpp @@ -1374,21 +1374,21 @@ namespace Program { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryFieldOp::IntegerDiv &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BinaryFieldOp::IntegerDiv &obj, Serializer &serializer) { } template <> template -Circuit::BinaryFieldOp::IntegerDiv serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BinaryFieldOp::IntegerDiv obj; +Program::BinaryFieldOp::IntegerDiv serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryFieldOp::IntegerDiv obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryFieldOp::Equals &lhs, const BinaryFieldOp::Equals &rhs) { return true; @@ -1444,21 +1444,21 @@ namespace Program { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryFieldOp::LessThan &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BinaryFieldOp::LessThan &obj, Serializer &serializer) { } template <> template -Circuit::BinaryFieldOp::LessThan serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BinaryFieldOp::LessThan obj; +Program::BinaryFieldOp::LessThan serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryFieldOp::LessThan obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryFieldOp::LessThanEquals &lhs, const BinaryFieldOp::LessThanEquals &rhs) { return true; @@ -1479,21 +1479,21 @@ namespace Circuit { return value; } -} // end of namespace Circuit +} // end of namespace Program template <> template -void serde::Serializable::serialize(const Circuit::BinaryFieldOp::LessThanEquals &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BinaryFieldOp::LessThanEquals &obj, Serializer &serializer) { } template <> template -Circuit::BinaryFieldOp::LessThanEquals serde::Deserializable::deserialize(Deserializer &deserializer) { - Circuit::BinaryFieldOp::LessThanEquals obj; +Program::BinaryFieldOp::LessThanEquals serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryFieldOp::LessThanEquals obj; return obj; } -namespace Circuit { +namespace Program { inline bool operator==(const BinaryIntOp &lhs, const BinaryIntOp &rhs) { if (!(lhs.value == rhs.value)) { return false; } From 9ebf404b957c80305e88ed326225a07a504e1fde Mon Sep 17 00:00:00 2001 From: Tom French Date: Thu, 14 Mar 2024 20:04:45 +0000 Subject: [PATCH 088/139] chore: add dependency on bb.js job to noir-packages jobs --- .circleci/config.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 8a9da4e30b2a..8aa589a09b43 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1283,10 +1283,14 @@ workflows: - noir-arm64 <<: *defaults - noir-tests: *defaults - - noir-packages: *defaults + - noir-packages: + requires: + - bb.js + <<: *defaults - noir-packages-tests: requires: - noir-ecr-manifest + - bb.js <<: *defaults - noir-compile-acir-tests: requires: From aa6c4307690ad93f3dd8d0e4cf9f21827c5eba7d Mon Sep 17 00:00:00 2001 From: Tom French Date: Thu, 14 Mar 2024 20:06:05 +0000 Subject: [PATCH 089/139] chore: fix job name --- .circleci/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 8aa589a09b43..2c756c4810f7 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1285,12 +1285,12 @@ workflows: - noir-tests: *defaults - noir-packages: requires: - - bb.js + - bb-js <<: *defaults - noir-packages-tests: requires: - noir-ecr-manifest - - bb.js + - bb-js <<: *defaults - noir-compile-acir-tests: requires: From d1c4bee5cd37706186abbf93533dc22082a607c7 Mon Sep 17 00:00:00 2001 From: Tom French Date: Thu, 14 Mar 2024 20:11:35 +0000 Subject: [PATCH 090/139] chore: `noir-packages-tests` depends on `noir-packages` --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 2c756c4810f7..008b16f6a83c 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1285,7 +1285,7 @@ workflows: - noir-tests: *defaults - noir-packages: requires: - - bb-js + - noir-packages <<: *defaults - noir-packages-tests: requires: From 301f4b87391b6683e4f427be1857c0c069df7f70 Mon Sep 17 00:00:00 2001 From: Tom French Date: Thu, 14 Mar 2024 20:13:45 +0000 Subject: [PATCH 091/139] chore: modified wrong job --- .circleci/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 008b16f6a83c..8fba2e0238d2 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1285,12 +1285,12 @@ workflows: - noir-tests: *defaults - noir-packages: requires: - - noir-packages + - bb-js <<: *defaults - noir-packages-tests: requires: - noir-ecr-manifest - - bb-js + - noir-packages <<: *defaults - noir-compile-acir-tests: requires: From 8b17313e9fba31b6922bcfc65f332ac2f3ea06dc Mon Sep 17 00:00:00 2001 From: vezenovm Date: Tue, 19 Mar 2024 19:09:38 +0000 Subject: [PATCH 092/139] initial compilation of non-inlined acir functions working for basic calls --- .../acvm-repo/acir/src/circuit/opcodes.rs | 4 +- .../acvm/src/compiler/transformers/mod.rs | 7 +- .../compiler/noirc_driver/src/lib.rs | 21 +- .../compiler/noirc_evaluator/src/lib.rs | 1 + .../compiler/noirc_evaluator/src/ssa.rs | 139 ++++++++- .../src/ssa/acir_gen/acir_ir/acir_variable.rs | 30 +- .../ssa/acir_gen/acir_ir/generated_acir.rs | 6 +- .../noirc_evaluator/src/ssa/acir_gen/mod.rs | 265 ++++++++++++++++-- .../src/ssa/function_builder/mod.rs | 25 +- .../noirc_evaluator/src/ssa/ir/dom.rs | 8 +- .../noirc_evaluator/src/ssa/ir/function.rs | 42 ++- .../noirc_evaluator/src/ssa/ir/post_order.rs | 5 +- .../src/ssa/opt/bubble_up_constrains.rs | 5 +- .../src/ssa/opt/constant_folding.rs | 20 +- .../src/ssa/opt/defunctionalize.rs | 5 +- .../noirc_evaluator/src/ssa/opt/die.rs | 5 +- .../src/ssa/opt/flatten_cfg.rs | 29 +- .../ssa/opt/flatten_cfg/branch_analysis.rs | 13 +- .../noirc_evaluator/src/ssa/opt/inlining.rs | 56 ++-- .../noirc_evaluator/src/ssa/opt/mem2reg.rs | 17 +- .../src/ssa/opt/simplify_cfg.rs | 8 +- .../noirc_evaluator/src/ssa/opt/unrolling.rs | 16 +- .../src/ssa/ssa_gen/context.rs | 8 +- .../noirc_evaluator/src/ssa/ssa_gen/mod.rs | 9 +- .../src/ssa/ssa_gen/program.rs | 5 +- .../src/hir/resolution/resolver.rs | 7 +- .../noirc_frontend/src/hir_def/function.rs | 2 +- .../noirc_frontend/src/lexer/lexer.rs | 5 +- .../src/monomorphization/ast.rs | 4 + .../src/monomorphization/mod.rs | 48 +++- .../execution_success/fold_basic/Prover.toml | 2 + 31 files changed, 668 insertions(+), 149 deletions(-) create mode 100644 noir/noir-repo/test_programs/execution_success/fold_basic/Prover.toml diff --git a/noir/noir-repo/acvm-repo/acir/src/circuit/opcodes.rs b/noir/noir-repo/acvm-repo/acir/src/circuit/opcodes.rs index 064a9d1244ae..68d28b287e66 100644 --- a/noir/noir-repo/acvm-repo/acir/src/circuit/opcodes.rs +++ b/noir/noir-repo/acvm-repo/acir/src/circuit/opcodes.rs @@ -99,8 +99,8 @@ impl std::fmt::Display for Opcode { } Opcode::Call { id, inputs, outputs } => { write!(f, "CALL func {}: ", id)?; - writeln!(f, "inputs: {:?}", inputs)?; - writeln!(f, "outputs: {:?}", outputs) + write!(f, "inputs: {:?}, ", inputs)?; + write!(f, "outputs: {:?}", outputs) } } } diff --git a/noir/noir-repo/acvm-repo/acvm/src/compiler/transformers/mod.rs b/noir/noir-repo/acvm-repo/acvm/src/compiler/transformers/mod.rs index 2e549854521a..f6d78c542448 100644 --- a/noir/noir-repo/acvm-repo/acvm/src/compiler/transformers/mod.rs +++ b/noir/noir-repo/acvm-repo/acvm/src/compiler/transformers/mod.rs @@ -145,7 +145,12 @@ pub(super) fn transform_internal( new_acir_opcode_positions.push(acir_opcode_positions[index]); transformed_opcodes.push(opcode); } - Opcode::Call { .. } => todo!("Handle Call opcodes in the ACVM"), + Opcode::Call { .. } => { + // `Call` does not write values to the `WitnessMap` + // A separate ACIR function should have its own respective `WitnessMap` + new_acir_opcode_positions.push(acir_opcode_positions[index]); + transformed_opcodes.push(opcode); + } } } diff --git a/noir/noir-repo/compiler/noirc_driver/src/lib.rs b/noir/noir-repo/compiler/noirc_driver/src/lib.rs index bc3062e5807e..2426ec1078dd 100644 --- a/noir/noir-repo/compiler/noirc_driver/src/lib.rs +++ b/noir/noir-repo/compiler/noirc_driver/src/lib.rs @@ -10,6 +10,7 @@ use iter_extended::vecmap; use noirc_abi::{AbiParameter, AbiType, ContractEvent}; use noirc_errors::{CustomDiagnostic, FileDiagnostic}; use noirc_evaluator::create_circuit; +use noirc_evaluator::create_program; use noirc_evaluator::errors::RuntimeError; use noirc_frontend::debug::build_debug_crate_file; use noirc_frontend::graph::{CrateId, CrateName}; @@ -290,7 +291,8 @@ pub fn compile_main( compile_no_check(context, options, main, cached_program, options.force_compile) .map_err(FileDiagnostic::from)?; - let compilation_warnings = vecmap(compiled_program.warnings.clone(), FileDiagnostic::from); + let compilation_warnings = + vecmap(compiled_program.warnings.clone(), |warnings| FileDiagnostic::from(warnings)); if options.deny_warnings && !compilation_warnings.is_empty() { return Err(compilation_warnings); } @@ -478,21 +480,26 @@ pub fn compile_no_check( return Ok(cached_program.expect("cache must exist for hashes to match")); } let visibility = program.return_visibility; - let (circuit, debug, input_witnesses, return_witnesses, warnings) = - create_circuit(program, options.show_ssa, options.show_brillig, options.force_brillig)?; + // let (circuit, debug, input_witnesses, return_witnesses, warnings) = + // create_circuit(program, options.show_ssa, options.show_brillig, options.force_brillig)?; + + let (program, debug, warnings, input_witnesses, return_witnesses) = + create_program(program, options.show_ssa, options.show_brillig, options.force_brillig)?; let abi = abi_gen::gen_abi(context, &main_function, input_witnesses, return_witnesses, visibility); - let file_map = filter_relevant_files(&[debug.clone()], &context.file_manager); + // let file_map = filter_relevant_files(&[debug.clone()], &context.file_manager); + let file_map = filter_relevant_files(&debug, &context.file_manager); Ok(CompiledProgram { hash, // TODO(https://github.com/noir-lang/noir/issues/4428) - program: Program { functions: vec![circuit] }, - debug, + program, + // TODO(https://github.com/noir-lang/noir/issues/4428) + debug: debug[0].clone(), abi, file_map, noir_version: NOIR_ARTIFACT_VERSION_STRING.to_string(), - warnings, + warnings: warnings[0].clone(), }) } diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/lib.rs b/noir/noir-repo/compiler/noirc_evaluator/src/lib.rs index 70751d3e5414..085822e2dff8 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/lib.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/lib.rs @@ -12,3 +12,4 @@ pub mod ssa; pub mod brillig; pub use ssa::create_circuit; +pub use ssa::create_program; diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs index 56cb76adbe48..9290601b215e 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs @@ -14,11 +14,12 @@ use crate::{ errors::{RuntimeError, SsaReport}, }; use acvm::acir::{ - circuit::{Circuit, ExpressionWidth, PublicInputs}, + circuit::{Circuit, ExpressionWidth, Program as AcirProgram, PublicInputs}, native_types::Witness, }; -use noirc_errors::debug_info::DebugInfo; +use iter_extended::vecmap; +use noirc_errors::debug_info::{DebugFunctions, DebugInfo, DebugTypes, DebugVariables}; use noirc_frontend::{ hir_def::function::FunctionSignature, monomorphization::ast::Program, Visibility, @@ -41,7 +42,7 @@ pub(crate) fn optimize_into_acir( print_ssa_passes: bool, print_brillig_trace: bool, force_brillig_output: bool, -) -> Result { +) -> Result, RuntimeError> { let abi_distinctness = program.return_distinctness; let ssa_gen_span = span!(Level::TRACE, "ssa_generation"); @@ -72,6 +73,10 @@ pub(crate) fn optimize_into_acir( let last_array_uses = ssa.find_last_array_uses(); + // map(|(i, (id, _)| { + // ssa.id_to_index.insert(*id, *i); + // }); + ssa.into_acir(brillig, abi_distinctness, &last_array_uses) } @@ -89,7 +94,11 @@ pub fn create_circuit( let debug_variables = program.debug_variables.clone(); let debug_types = program.debug_types.clone(); let debug_functions = program.debug_functions.clone(); + + // let func_sigs = program.function_signatures; let func_sig = program.main_function_signature.clone(); + // let func_sigs = program.functions. + // TODO: handle `recursive` being marked on a program with multiple ACIRs that is looking to fold let recursive = program.recursive; let mut generated_acir = optimize_into_acir( program, @@ -97,6 +106,124 @@ pub fn create_circuit( enable_brillig_logging, force_brillig_output, )?; + + // let acir_functions = vecmap(generated_acir.iter().zip(func_sigs), |(acir, func_sig)| convert_generated_acir_into_circuit(acir, func_sig, recursive)); + let opcodes = generated_acir[0].take_opcodes(); + let current_witness_index = generated_acir[0].current_witness_index().0; + let GeneratedAcir { + return_witnesses, + locations, + input_witnesses, + assert_messages, + warnings, + .. + } = generated_acir[0].clone(); + + let (public_parameter_witnesses, private_parameters) = + split_public_and_private_inputs(&func_sig, &input_witnesses); + + let public_parameters = PublicInputs(public_parameter_witnesses); + let return_values = PublicInputs(return_witnesses.iter().copied().collect()); + + let circuit = Circuit { + current_witness_index, + expression_width: ExpressionWidth::Unbounded, + opcodes, + private_parameters, + public_parameters, + return_values, + assert_messages: assert_messages.into_iter().collect(), + recursive, + }; + + // This converts each im::Vector in the BTreeMap to a Vec + let locations = locations + .into_iter() + .map(|(index, locations)| (index, locations.into_iter().collect())) + .collect(); + + let mut debug_info = DebugInfo::new(locations, debug_variables, debug_functions, debug_types); + + // Perform any ACIR-level optimizations + let (optimized_circuit, transformation_map) = acvm::compiler::optimize(circuit); + debug_info.update_acir(transformation_map); + + Ok((optimized_circuit, debug_info, input_witnesses, return_witnesses, warnings)) +} + +/// Compiles the [`Program`] into [`ACIR``][acvm::acir::circuit::Program]. +/// +/// The output ACIR is is backend-agnostic and so must go through a transformation pass before usage in proof generation. +#[allow(clippy::type_complexity)] +#[tracing::instrument(level = "trace", skip_all)] +pub fn create_program( + program: Program, + enable_ssa_logging: bool, + enable_brillig_logging: bool, + force_brillig_output: bool, +) -> Result< + (AcirProgram, Vec, Vec>, Vec, Vec), + RuntimeError, +> { + // TODO: Check whether the debug tracker stores information across the program and not just main + let debug_variables = program.debug_variables.clone(); + let debug_types = program.debug_types.clone(); + let debug_functions = program.debug_functions.clone(); + + let func_sigs = program.function_signatures.clone(); + + let recursive = program.recursive; + let generated_acir = optimize_into_acir( + program, + enable_ssa_logging, + enable_brillig_logging, + force_brillig_output, + )?; + + // let main_generated_acir = generated_acir.get(0).expect("ICE: Must have a main function"); + // let main_input_witnesses = main_generated_acir.input_witnesses; + // let main_return_witnesses = main_generated_acir.return_witnesses; + + let mut functions = vec![]; + let mut debug_infos = vec![]; + let mut warning_infos = vec![]; + let mut main_input_witnesses = Vec::new(); + let mut main_return_witnesses = Vec::new(); + // Using a flag here to avoid enumarting the loop as main is expected to be the first circuit + let mut is_main = true; + for (acir, func_sig) in generated_acir.into_iter().zip(func_sigs) { + let (circuit, debug_info, warnings, input_witnesses, return_witnesses) = + convert_generated_acir_into_circuit( + acir, + func_sig, + recursive, + debug_variables.clone(), + debug_functions.clone(), + debug_types.clone(), + ); + functions.push(circuit); + debug_infos.push(debug_info); + warning_infos.push(warnings); + if is_main { + main_input_witnesses = input_witnesses; + main_return_witnesses = return_witnesses; + } + is_main = false; + } + + let program = AcirProgram { functions }; + + Ok((program, debug_infos, warning_infos, main_input_witnesses, main_return_witnesses)) +} + +fn convert_generated_acir_into_circuit( + mut generated_acir: GeneratedAcir, + func_sig: FunctionSignature, + recursive: bool, + debug_variables: DebugVariables, + debug_functions: DebugFunctions, + debug_types: DebugTypes, +) -> (Circuit, DebugInfo, Vec, Vec, Vec) { let opcodes = generated_acir.take_opcodes(); let current_witness_index = generated_acir.current_witness_index().0; let GeneratedAcir { @@ -108,6 +235,8 @@ pub fn create_circuit( .. } = generated_acir; + let locations = locations.clone(); + let (public_parameter_witnesses, private_parameters) = split_public_and_private_inputs(&func_sig, &input_witnesses); @@ -121,7 +250,7 @@ pub fn create_circuit( private_parameters, public_parameters, return_values, - assert_messages: assert_messages.into_iter().collect(), + assert_messages: assert_messages.clone().into_iter().collect(), recursive, }; @@ -137,7 +266,7 @@ pub fn create_circuit( let (optimized_circuit, transformation_map) = acvm::compiler::optimize(circuit); debug_info.update_acir(transformation_map); - Ok((optimized_circuit, debug_info, input_witnesses, return_witnesses, warnings)) + (optimized_circuit, debug_info, warnings, input_witnesses, return_witnesses) } // Takes each function argument and partitions the circuit's inputs witnesses according to its visibility. diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs index fb11bae556c9..60d6afb6a96f 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs @@ -101,6 +101,12 @@ impl From for AcirType { } } +/// An identifier for a location in the code. +/// +/// It is assumed that an entity will keep a map +/// of labels to opcode locations. +pub(crate) type Label = String; + #[derive(Debug, Default)] /// Context object which holds the relationship between /// `Variables`(AcirVar) and types such as `Expression` and `Witness` @@ -124,6 +130,9 @@ pub(crate) struct AcirContext { /// The BigIntContext, used to generate identifiers for BigIntegers big_int_ctx: BigIntContext, + + /// Set of labels (function identifiers) which are external to the bytecode + unresolved_external_call_labels: Vec<(usize, Label)>, } impl AcirContext { @@ -1443,13 +1452,13 @@ impl AcirContext { /// Terminates the context and takes the resulting `GeneratedAcir` pub(crate) fn finish( - mut self, + &mut self, inputs: Vec, warnings: Vec, ) -> GeneratedAcir { self.acir_ir.input_witnesses = inputs; self.acir_ir.warnings = warnings; - self.acir_ir + self.acir_ir.clone() } /// Adds `Data` into the context and assigns it a Variable. @@ -1757,6 +1766,23 @@ impl AcirContext { } Ok(()) } + + pub(crate) fn call_acir_function( + &mut self, + id: u32, + inputs: Vec, + output_count: usize, + ) -> Result<(), RuntimeError> { + let inputs = self.prepare_inputs_for_black_box_func_call(inputs)?; + let inputs = inputs + .iter() + .flat_map(|input| vecmap(input, |input| input.witness)) + .collect::>(); + let outputs = vecmap(0..output_count, |_| self.acir_ir.next_witness_index()); + + self.acir_ir.push_opcode(Opcode::Call { id, inputs, outputs }); + Ok(()) + } } /// Enum representing the possible values that a diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs index 1d05e998b13b..09dabe09f8a2 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs @@ -24,7 +24,7 @@ use acvm::{ use iter_extended::vecmap; use num_bigint::BigUint; -#[derive(Debug, Default)] +#[derive(Debug, Default, Clone)] /// The output of the Acir-gen pass pub(crate) struct GeneratedAcir { /// The next witness index that may be declared. @@ -82,6 +82,10 @@ impl GeneratedAcir { std::mem::take(&mut self.opcodes) } + pub(crate) fn next_opcode_index(&self) -> usize { + self.opcodes.len() + } + /// Updates the witness index counter and returns /// the next witness index. pub(crate) fn next_witness_index(&mut self) -> Witness { diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs index 140ed0b53ff5..4ee1e127a066 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs @@ -25,6 +25,7 @@ use crate::brillig::brillig_ir::artifact::GeneratedBrillig; use crate::brillig::brillig_ir::BrilligContext; use crate::brillig::{brillig_gen::brillig_fn::FunctionContext as BrilligFunctionContext, Brillig}; use crate::errors::{InternalError, InternalWarning, RuntimeError, SsaReport}; +use crate::ssa::ir::function::InlineType; pub(crate) use acir_ir::generated_acir::GeneratedAcir; use acvm::acir::native_types::Witness; @@ -181,28 +182,46 @@ impl Ssa { brillig: Brillig, abi_distinctness: Distinctness, last_array_uses: &HashMap, - ) -> Result { - let context = Context::new(); - let mut generated_acir = context.convert_ssa(self, brillig, last_array_uses)?; + ) -> Result, RuntimeError> { + // let x = ssa.functions.iter().enumerate().map(|(i, (id, _))| { + // ssa.id_to_index.insert(*id, *i); + // }); + + let mut acirs = Vec::new(); + for (_, function) in &self.functions { + let context = Context::new(); + let generated_acir = + context.convert_ssa_function(&self, function, &brillig, last_array_uses)?; + + acirs.push(generated_acir); + } + // dbg!(acirs.clone()); + // TODO: check wheter doing this for a single circuit's return witnessese is correct. + // We may need it for all foldable circuits, as any circuit being folded is essentially an entry point. However, I do not know how that + // plays a part when we potentially want not inlined functions normally as part of the compiler. + let main_func_acir = &mut acirs[0]; + // Previous code + // let mut context = Context::new(); + // let mut generated_acir = context.convert_ssa(self, brillig, last_array_uses)?; match abi_distinctness { Distinctness::Distinct => { // Create a witness for each return witness we have // to guarantee that the return witnesses are distinct - let distinct_return_witness: Vec<_> = generated_acir + let distinct_return_witness: Vec<_> = main_func_acir .return_witnesses .clone() .into_iter() .map(|return_witness| { - generated_acir + main_func_acir .create_witness_for_expression(&Expression::from(return_witness)) }) .collect(); - generated_acir.return_witnesses = distinct_return_witness; - Ok(generated_acir) + main_func_acir.return_witnesses = distinct_return_witness; + Ok(acirs) } - Distinctness::DuplicationAllowed => Ok(generated_acir), + Distinctness::DuplicationAllowed => Ok(acirs), } } } @@ -225,17 +244,49 @@ impl Context { } } - /// Converts SSA into ACIR - fn convert_ssa( + // /// Converts SSA into ACIR + // fn convert_ssa( + // &mut self, + // ssa: Ssa, + // brillig: Brillig, + // last_array_uses: &HashMap, + // ) -> Result { + // let mut acirs = Vec::new(); + // for (id, function) in &ssa.functions { + // let x = match function.runtime() { + // RuntimeType::Acir(_) => { + // // TODO: remove this brillig clone + // self.convert_acir_main(function, &ssa, &brillig, last_array_uses) + // } + // RuntimeType::Brillig => { + // self.convert_brillig_main(function, &brillig) + // } + // }; + // // println!("acir for {id}: {}",); + // println!("acir for {id}"); + // dbg!(x.clone()); + // acirs.push(x); + // } + // acirs[0].clone() + // // let main_func = ssa.main(); + // // match main_func.runtime() { + // // // TODO: hanlde this shit + // // RuntimeType::Acir(_) => self.convert_acir_main(main_func, &ssa, &brillig, last_array_uses), + // // RuntimeType::Brillig => self.convert_brillig_main(main_func, &brillig), + // // } + // } + + fn convert_ssa_function( self, - ssa: Ssa, - brillig: Brillig, + ssa: &Ssa, + function: &Function, + brillig: &Brillig, last_array_uses: &HashMap, ) -> Result { - let main_func = ssa.main(); - match main_func.runtime() { - RuntimeType::Acir => self.convert_acir_main(main_func, &ssa, brillig, last_array_uses), - RuntimeType::Brillig => self.convert_brillig_main(main_func, brillig), + match function.runtime() { + // TODO: hanlde this shit + RuntimeType::Acir(_) => self.convert_acir_main(function, ssa, brillig, last_array_uses), + RuntimeType::Brillig => self.convert_brillig_main(function, brillig), } } @@ -243,7 +294,7 @@ impl Context { mut self, main_func: &Function, ssa: &Ssa, - brillig: Brillig, + brillig: &Brillig, last_array_uses: &HashMap, ) -> Result { let dfg = &main_func.dfg; @@ -257,7 +308,7 @@ impl Context { *instruction_id, dfg, ssa, - &brillig, + brillig, last_array_uses, )?); } @@ -269,7 +320,7 @@ impl Context { fn convert_brillig_main( mut self, main_func: &Function, - brillig: Brillig, + brillig: &Brillig, ) -> Result { let dfg = &main_func.dfg; @@ -282,7 +333,7 @@ impl Context { let outputs: Vec = vecmap(main_func.returns(), |result_id| dfg.type_of_value(*result_id).into()); - let code = self.gen_brillig_for(main_func, &brillig)?; + let code = self.gen_brillig_for(main_func, brillig)?; // We specifically do not attempt execution of the brillig code being generated as this can result in it being // replaced with constraints on witnesses to the program outputs. @@ -537,15 +588,34 @@ impl Context { Value::Function(id) => { let func = &ssa.functions[id]; match func.runtime() { - RuntimeType::Acir => unimplemented!( - "expected an intrinsic/brillig call, but found {func:?}. All ACIR methods should be inlined" - ), + RuntimeType::Acir(inline_type) => { + assert!(!matches!(inline_type, InlineType::Inline), "ICE: Got an ACIR function named {} that should have already been inlined", func.name()); + + let inputs = vecmap(arguments, |arg| self.convert_value(*arg, dfg)); + let output_count = result_ids.iter().fold(0usize, |sum, result_id| { + sum + dfg.try_get_array_length(*result_id).expect("ICE: need to implement returning slices from folded functions") + }); + + let final_program_id = ssa + .id_to_index + .get(id) + .expect("ICE: should have an associated final index"); + self.acir_context.call_acir_function( + *final_program_id, + inputs, + output_count, + )?; + } RuntimeType::Brillig => { - // Check that we are not attempting to return a slice from + // Check that we are not attempting to return a slice from // an unconstrained runtime to a constrained runtime for result_id in result_ids { if dfg.type_of_value(*result_id).contains_slice_element() { - return Err(RuntimeError::UnconstrainedSliceReturnToConstrained { call_stack: self.acir_context.get_call_stack() }) + return Err( + RuntimeError::UnconstrainedSliceReturnToConstrained { + call_stack: self.acir_context.get_call_stack(), + }, + ); } } @@ -553,9 +623,18 @@ impl Context { let code = self.gen_brillig_for(func, brillig)?; - let outputs: Vec = vecmap(result_ids, |result_id| dfg.type_of_value(*result_id).into()); + let outputs: Vec = vecmap(result_ids, |result_id| { + dfg.type_of_value(*result_id).into() + }); - let output_values = self.acir_context.brillig(self.current_side_effects_enabled_var, code, inputs, outputs, true, false)?; + let output_values = self.acir_context.brillig( + self.current_side_effects_enabled_var, + code, + inputs, + outputs, + true, + false, + )?; // Compiler sanity check assert_eq!(result_ids.len(), output_values.len(), "ICE: The number of Brillig output values should match the result ids in SSA"); @@ -565,7 +644,11 @@ impl Context { let array_id = dfg.resolve(*result.0); let block_id = self.block_id(&array_id); let array_typ = dfg.type_of_value(array_id); - self.initialize_array(block_id, array_typ.flattened_size(), Some(result.1.clone()))?; + self.initialize_array( + block_id, + array_typ.flattened_size(), + Some(result.1.clone()), + )?; } self.ssa_values.insert(*result.0, result.1); } @@ -2275,3 +2358,129 @@ fn can_omit_element_sizes_array(array_typ: &Type) -> bool { !types.iter().any(|typ| typ.contains_an_array()) } + +#[cfg(test)] +mod test { + use acvm::acir::{circuit::Opcode, native_types::Witness}; + + use crate::{ + brillig::Brillig, + ssa::{ + function_builder::FunctionBuilder, + ir::{ + function::{InlineType, RuntimeType}, + instruction::BinaryOp, + map::Id, + types::Type, + }, + }, + }; + use fxhash::FxHashMap as HashMap; + + #[test] + fn basic_call_codegen() { + // acir(inline) fn main f0 { + // b0(v0: Field, v1: Field): + // call f1(v0, v1) + // call f1(v0, v1) + // return + // } + // acir(fold) fn foo f1 { + // b0(v0: Field, v1: Field): + // v13 = eq v0, v1 + // constrain v13 == u1 0 + // return + // } + + let foo_id = Id::test_new(0); + let mut builder = + FunctionBuilder::new("main".into(), foo_id, RuntimeType::Acir(InlineType::default())); + let main_v0 = builder.add_parameter(Type::field()); + let main_v1 = builder.add_parameter(Type::field()); + + let foo_id = Id::test_new(1); + let foo = builder.import_function(foo_id); + builder.insert_call(foo, vec![main_v0, main_v1], vec![]).to_vec(); + builder.insert_call(foo, vec![main_v0, main_v1], vec![]).to_vec(); + builder.terminate_with_return(vec![]); + + builder.new_function("foo".into(), foo_id, InlineType::Fold); + let foo_v0 = builder.add_parameter(Type::field()); + let foo_v1 = builder.add_parameter(Type::field()); + + let foo_equality_check = builder.insert_binary(foo_v0, BinaryOp::Eq, foo_v1); + let zero = builder.field_constant(0u128); + builder.insert_constrain(foo_equality_check, zero, None); + builder.terminate_with_return(vec![]); + + let ssa = builder.finish(); + + let acir_functions = ssa + .into_acir( + Brillig::default(), + noirc_frontend::Distinctness::Distinct, + &HashMap::default(), + ) + .expect("Should compile manually written SSA into ACIR"); + // Expected result: + // main f0 + // GeneratedAcir { + // ... + // opcodes: [ + // CALL func 1: inputs: [Witness(0), Witness(1)], outputs: [], + // CALL func 1: inputs: [Witness(0), Witness(1)], outputs: [], + // ], + // return_witnesses: [], + // input_witnesses: [ + // Witness( + // 0, + // ), + // Witness( + // 1, + // ), + // ], + // ... + // } + // foo f1 + // GeneratedAcir { + // ... + // opcodes: [ + // EXPR [ (-1, _0) (1, _1) (-1, _2) 0 ], + // BRILLIG: inputs: [Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(2))], q_c: 0 })] + // outputs: [Simple(Witness(3))] + // [Brillig opcodes...] + // EXPR [ (1, _2, _3) (1, _4) -1 ], + // EXPR [ (1, _2, _4) 0 ], + // EXPR [ (1, _4) 0 ], + // ], + // return_witnesses: [], + // input_witnesses: [ + // Witness( + // 0, + // ), + // Witness( + // 1, + // ), + // ], + // ... + // } + + let main = &acir_functions[0]; + assert_eq!(main.opcodes().len(), 2, "Should have two calls to `foo`"); + for opcode in main.opcodes() { + match opcode { + Opcode::Call { id, inputs, outputs } => { + assert_eq!(*id, 1, "Main was expected to call the same function"); + assert_eq!(inputs[0], Witness(0), "First input was not the first witness"); + assert_eq!(inputs[1], Witness(1), "Second input was not the second witness"); + assert!(outputs.is_empty(), "Expected `foo` to return nothing"); + } + _ => panic!("Expected only Call opcodes in main"), + } + } + + let foo = &acir_functions[1]; + assert_eq!(foo.input_witnesses[0], Witness(0), "First input was not the first witness"); + assert_eq!(foo.input_witnesses[1], Witness(1), "Second input was not the second witness"); + } +} diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs index 18a8a486816f..f8326bf86651 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs @@ -17,7 +17,7 @@ use super::{ ir::{ basic_block::BasicBlock, dfg::{CallStack, InsertInstructionResult}, - function::RuntimeType, + function::{InlineType, RuntimeType}, instruction::{ConstrainError, InstructionId, Intrinsic}, }, ssa_gen::Ssa, @@ -46,10 +46,10 @@ impl FunctionBuilder { function_name: String, function_id: FunctionId, runtime: RuntimeType, - should_fold: bool, ) -> Self { - let mut new_function = Function::new(function_name, function_id, should_fold); + let mut new_function = Function::new(function_name, function_id); new_function.set_runtime(runtime); + let current_block = new_function.entry_block(); Self { @@ -70,9 +70,8 @@ impl FunctionBuilder { name: String, function_id: FunctionId, runtime_type: RuntimeType, - should_fold: bool, ) { - let mut new_function = Function::new(name, function_id, should_fold); + let mut new_function = Function::new(name, function_id); new_function.set_runtime(runtime_type); self.current_block = new_function.entry_block(); @@ -81,13 +80,18 @@ impl FunctionBuilder { } /// Finish the current function and create a new ACIR function. - pub(crate) fn new_function(&mut self, name: String, function_id: FunctionId, should_fold: bool,) { - self.new_function_with_type(name, function_id, RuntimeType::Acir, should_fold); + pub(crate) fn new_function( + &mut self, + name: String, + function_id: FunctionId, + inline_type: InlineType, + ) { + self.new_function_with_type(name, function_id, RuntimeType::Acir(inline_type)); } /// Finish the current function and create a new unconstrained function. pub(crate) fn new_brillig_function(&mut self, name: String, function_id: FunctionId) { - self.new_function_with_type(name, function_id, RuntimeType::Brillig, false); + self.new_function_with_type(name, function_id, RuntimeType::Brillig); } /// Consume the FunctionBuilder returning all the functions it has generated. @@ -450,7 +454,7 @@ mod tests { use acvm::FieldElement; use crate::ssa::ir::{ - function::RuntimeType, + function::{InlineType, RuntimeType}, instruction::{Endian, Intrinsic}, map::Id, types::Type, @@ -465,7 +469,8 @@ mod tests { // let x = 7; // let bits = x.to_le_bits(8); let func_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("func".into(), func_id, RuntimeType::Acir, false); + let mut builder = + FunctionBuilder::new("func".into(), func_id, RuntimeType::Acir(InlineType::default())); let one = builder.numeric_constant(FieldElement::one(), Type::bool()); let zero = builder.numeric_constant(FieldElement::zero(), Type::bool()); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/dom.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/dom.rs index c1df0428c644..1ce552e6104a 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/dom.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/dom.rs @@ -252,7 +252,7 @@ mod tests { basic_block::BasicBlockId, dfg::CallStack, dom::DominatorTree, - function::{Function, RuntimeType}, + function::{Function, InlineType, RuntimeType}, instruction::TerminatorInstruction, map::Id, types::Type, @@ -286,7 +286,8 @@ mod tests { // return () // } let func_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("func".into(), func_id, RuntimeType::Acir); + let mut builder = + FunctionBuilder::new("func".into(), func_id, RuntimeType::Acir(InlineType::default())); let cond = builder.add_parameter(Type::unsigned(1)); let block1_id = builder.insert_block(); @@ -395,7 +396,8 @@ mod tests { // jump block1() // } let func_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("func".into(), func_id, RuntimeType::Acir); + let mut builder = + FunctionBuilder::new("func".into(), func_id, RuntimeType::Acir(InlineType::default())); let block1_id = builder.insert_block(); let block2_id = builder.insert_block(); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/function.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/function.rs index e1b8773c117c..fb306ecf9dcc 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/function.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/function.rs @@ -12,20 +12,28 @@ use super::value::ValueId; #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] pub(crate) enum RuntimeType { // A noir function, to be compiled in ACIR and executed by ACVM - Acir, + Acir(InlineType), // Unconstrained function, to be compiled to brillig and executed by the Brillig VM Brillig, } +/// Represents how a RuntimeType::Acir function should be inlined. +/// This type is only relevant for ACIR functions as we do not inline any Brillig functions #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] pub(crate) enum InlineType { - /// The most basic entry point can expect all its functions to be inlined. + /// The most basic entry point can expect all its functions to be inlined. /// All function calls are expected to be inlined into a single ACIR. Inline, /// Functions marked as foldable will not be inlined and compiled separately into ACIR Fold, } +impl Default for InlineType { + fn default() -> Self { + InlineType::Inline + } +} + /// A function holds a list of instructions. /// These instructions are further grouped into Basic blocks /// @@ -44,10 +52,6 @@ pub(crate) struct Function { runtime: RuntimeType, - /// Represents how an ACIR function should be inlined. - /// This type should only be accessed when operating on a function of RuntimeType::Acir - inline_type: InlineType, - /// The DataFlowGraph holds the majority of data pertaining to the function /// including its blocks, instructions, and values. pub(crate) dfg: DataFlowGraph, @@ -60,7 +64,7 @@ impl Function { pub(crate) fn new(name: String, id: FunctionId) -> Self { let mut dfg = DataFlowGraph::default(); let entry_block = dfg.make_block(); - Self { name, id, entry_block, dfg, runtime: RuntimeType::Acir, inline_type: InlineType::Inline } + Self { name, id, entry_block, dfg, runtime: RuntimeType::Acir(InlineType::default()) } } /// The name of the function. @@ -84,13 +88,18 @@ impl Function { self.runtime = runtime; } - pub(crate) fn inline_type(&self) -> InlineType { - assert!(matches!(self.runtime, RuntimeType::Acir), "ICE: We should only check the inline type for ACIR functions. All Brillig functions are expected to not be inlined"); - self.inline_type + pub(crate) fn inline_type(&self) -> Option { + if let RuntimeType::Acir(inline_type) = self.runtime { + Some(inline_type) + } else { + None + } } pub(crate) fn set_inline_type(&mut self, inline_type: InlineType) { - self.inline_type = inline_type + if let RuntimeType::Acir(old_inline_type) = &mut self.runtime { + *old_inline_type = inline_type; + } } /// Retrieves the entry block of a function. @@ -151,12 +160,21 @@ impl Function { impl std::fmt::Display for RuntimeType { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - RuntimeType::Acir => write!(f, "acir"), + RuntimeType::Acir(inline_type) => write!(f, "acir({inline_type})"), RuntimeType::Brillig => write!(f, "brillig"), } } } +impl std::fmt::Display for InlineType { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + InlineType::Inline => write!(f, "inline"), + InlineType::Fold => write!(f, "fold"), + } + } +} + /// FunctionId is a reference for a function /// /// This Id is how each function refers to other functions diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/post_order.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/post_order.rs index 3cae86829edb..65327be3f589 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/post_order.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/post_order.rs @@ -74,7 +74,7 @@ mod tests { use crate::ssa::{ function_builder::FunctionBuilder, ir::{ - function::{Function, RuntimeType}, + function::{Function, InlineType, RuntimeType}, map::Id, post_order::PostOrder, types::Type, @@ -112,7 +112,8 @@ mod tests { // D, F, E, B, A, (C dropped as unreachable) let func_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("func".into(), func_id, RuntimeType::Acir); + let mut builder = + FunctionBuilder::new("func".into(), func_id, RuntimeType::Acir(InlineType::default())); let block_b_id = builder.insert_block(); let block_c_id = builder.insert_block(); let block_d_id = builder.insert_block(); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/bubble_up_constrains.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/bubble_up_constrains.rs index 17e1593199ee..8d36a9010c93 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/bubble_up_constrains.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/bubble_up_constrains.rs @@ -77,7 +77,7 @@ mod test { use crate::ssa::{ function_builder::FunctionBuilder, ir::{ - function::RuntimeType, + function::{InlineType, RuntimeType}, instruction::{Binary, BinaryOp, Instruction}, map::Id, types::Type, @@ -100,7 +100,8 @@ mod test { let main_id = Id::test_new(0); // Compiling main - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir, false); + let mut builder = + FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir(InlineType::default())); let v0 = builder.add_parameter(Type::field()); let one = builder.field_constant(1u128); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/constant_folding.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/constant_folding.rs index 4efcbaa03aab..b798df16a01b 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/constant_folding.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/constant_folding.rs @@ -283,7 +283,7 @@ mod test { use crate::ssa::{ function_builder::FunctionBuilder, ir::{ - function::RuntimeType, + function::{InlineType, RuntimeType}, instruction::{Binary, BinaryOp, Instruction, TerminatorInstruction}, map::Id, types::Type, @@ -305,7 +305,8 @@ mod test { let main_id = Id::test_new(0); // Compiling main - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir, false); + let mut builder = + FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir(InlineType::default())); let v0 = builder.add_parameter(Type::field()); let one = builder.field_constant(1u128); @@ -361,7 +362,8 @@ mod test { let main_id = Id::test_new(0); // Compiling main - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir, false); + let mut builder = + FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir(InlineType::default())); let v0 = builder.add_parameter(Type::unsigned(16)); let v1 = builder.add_parameter(Type::unsigned(16)); @@ -415,7 +417,8 @@ mod test { let main_id = Id::test_new(0); // Compiling main - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir, false); + let mut builder = + FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir(InlineType::default())); let v0 = builder.add_parameter(Type::unsigned(16)); let v1 = builder.add_parameter(Type::unsigned(16)); @@ -471,7 +474,8 @@ mod test { let main_id = Id::test_new(0); // Compiling main - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir, false); + let mut builder = + FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir(InlineType::default())); let v0 = builder.add_parameter(Type::field()); let one = builder.field_constant(1u128); let v1 = builder.insert_binary(v0, BinaryOp::Add, one); @@ -518,7 +522,8 @@ mod test { let main_id = Id::test_new(0); // Compiling main - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir, false); + let mut builder = + FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir(InlineType::default())); let v0 = builder.add_parameter(Type::unsigned(16)); let v1 = builder.insert_cast(v0, Type::unsigned(32)); @@ -562,7 +567,8 @@ mod test { let main_id = Id::test_new(0); // Compiling main - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir, false); + let mut builder = + FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir(InlineType::default())); let v0 = builder.add_parameter(Type::bool()); let v1 = builder.add_parameter(Type::bool()); let v2 = builder.add_parameter(Type::bool()); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/defunctionalize.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/defunctionalize.rs index e8fbc164ba70..e25d98c9bd0f 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/defunctionalize.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/defunctionalize.rs @@ -13,7 +13,7 @@ use crate::ssa::{ function_builder::FunctionBuilder, ir::{ basic_block::BasicBlockId, - function::{Function, FunctionId, RuntimeType, Signature}, + function::{Function, FunctionId, InlineType, RuntimeType, Signature}, instruction::{BinaryOp, ConstrainError, Instruction}, types::{NumericType, Type}, value::{Value, ValueId}, @@ -304,7 +304,8 @@ fn create_apply_function( ) -> FunctionId { assert!(!function_ids.is_empty()); ssa.add_fn(|id| { - let mut function_builder = FunctionBuilder::new("apply".to_string(), id, RuntimeType::Acir, false); + let mut function_builder = + FunctionBuilder::new("apply".to_string(), id, RuntimeType::Acir(InlineType::default())); let target_id = function_builder.add_parameter(Type::field()); let params_ids = vecmap(signature.params, |typ| function_builder.add_parameter(typ)); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/die.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/die.rs index 754130bff049..26ec7cfc3d76 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/die.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/die.rs @@ -165,7 +165,7 @@ mod test { use crate::ssa::{ function_builder::FunctionBuilder, ir::{ - function::RuntimeType, + function::{InlineType, RuntimeType}, instruction::{BinaryOp, Intrinsic}, map::Id, types::Type, @@ -195,7 +195,8 @@ mod test { let main_id = Id::test_new(0); // Compiling main - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir, false); + let mut builder = + FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir(InlineType::default())); let v0 = builder.add_parameter(Type::field()); let b1 = builder.insert_block(); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs index 91d75d22d137..662e6898c6d7 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs @@ -839,7 +839,7 @@ mod test { function_builder::FunctionBuilder, ir::{ dfg::DataFlowGraph, - function::{Function, RuntimeType}, + function::{Function, InlineType, RuntimeType}, instruction::{BinaryOp, Instruction, Intrinsic, TerminatorInstruction}, map::Id, types::Type, @@ -860,7 +860,8 @@ mod test { // return v1 // } let main_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir, false); + let mut builder = + FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir(InlineType::default())); let b1 = builder.insert_block(); let b2 = builder.insert_block(); @@ -914,7 +915,8 @@ mod test { // return // } let main_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir, false); + let mut builder = + FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir(InlineType::default())); let b1 = builder.insert_block(); let b2 = builder.insert_block(); @@ -963,7 +965,8 @@ mod test { // return // } let main_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir, false); + let mut builder = + FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir(InlineType::default())); let b1 = builder.insert_block(); let b2 = builder.insert_block(); @@ -1024,7 +1027,8 @@ mod test { // return // } let main_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir, false); + let mut builder = + FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir(InlineType::default())); let b1 = builder.insert_block(); let b2 = builder.insert_block(); @@ -1114,7 +1118,8 @@ mod test { // ↘ ↙ // b9 let main_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir, false); + let mut builder = + FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir(InlineType::default())); let b1 = builder.insert_block(); let b2 = builder.insert_block(); @@ -1271,7 +1276,8 @@ mod test { // before the first store to allocate, which loaded an uninitialized value. // In this test we assert the ordering is strictly Allocate then Store then Load. let main_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir, false); + let mut builder = + FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir(InlineType::default())); let b1 = builder.insert_block(); let b2 = builder.insert_block(); @@ -1370,7 +1376,8 @@ mod test { // return // } let main_id = Id::test_new(1); - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir, false); + let mut builder = + FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir(InlineType::default())); builder.insert_block(); // entry @@ -1423,7 +1430,8 @@ mod test { // jmp b3() // } let main_id = Id::test_new(1); - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir, false); + let mut builder = + FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir(InlineType::default())); builder.insert_block(); // b0 let b1 = builder.insert_block(); @@ -1533,7 +1541,8 @@ mod test { // jmp b5() // } let main_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir, false); + let mut builder = + FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir(InlineType::default())); let b1 = builder.insert_block(); let b2 = builder.insert_block(); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg/branch_analysis.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg/branch_analysis.rs index e2b0e931de6b..4db13fdc0ef5 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg/branch_analysis.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg/branch_analysis.rs @@ -114,7 +114,12 @@ mod test { use crate::ssa::{ function_builder::FunctionBuilder, - ir::{cfg::ControlFlowGraph, function::RuntimeType, map::Id, types::Type}, + ir::{ + cfg::ControlFlowGraph, + function::{InlineType, RuntimeType}, + map::Id, + types::Type, + }, opt::flatten_cfg::branch_analysis::find_branch_ends, }; @@ -134,7 +139,8 @@ mod test { // ↘ ↙ // b9 let main_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir, false); + let mut builder = + FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir(InlineType::default())); let b1 = builder.insert_block(); let b2 = builder.insert_block(); @@ -195,7 +201,8 @@ mod test { // ↘ ↙ // b15 let main_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir, false); + let mut builder = + FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir(InlineType::default())); let b1 = builder.insert_block(); let b2 = builder.insert_block(); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/inlining.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/inlining.rs index c81ab4054d3a..d93d98ee229c 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/inlining.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/inlining.rs @@ -11,7 +11,7 @@ use crate::ssa::{ ir::{ basic_block::BasicBlockId, dfg::{CallStack, InsertInstructionResult}, - function::{Function, FunctionId, RuntimeType}, + function::{Function, FunctionId, InlineType, RuntimeType}, instruction::{Instruction, InstructionId, TerminatorInstruction}, value::{Value, ValueId}, }, @@ -100,9 +100,18 @@ fn get_entry_point_functions(ssa: &Ssa) -> BTreeSet { let functions = ssa.functions.iter(); let mut entry_points = functions .filter(|(_, function)| { - dbg!(function.foldable()); + dbg!(function.runtime()); dbg!(function.id()); - function.runtime() == RuntimeType::Brillig + let inline_filter = match function.runtime() { + RuntimeType::Acir(inline_type) => match inline_type { + InlineType::Inline => false, + InlineType::Fold => true, + }, + RuntimeType::Brillig => true, + }; + dbg!(inline_filter); + inline_filter + // function.runtime() == RuntimeType::Brillig }) .map(|(id, _)| *id) .collect::>(); @@ -119,7 +128,7 @@ impl InlineContext { /// that could not be inlined calling it. fn new(ssa: &Ssa, entry_point: FunctionId) -> InlineContext { let source = &ssa.functions[&entry_point]; - let builder = FunctionBuilder::new(source.name().to_owned(), entry_point, source.runtime(), false); + let builder = FunctionBuilder::new(source.name().to_owned(), entry_point, source.runtime()); Self { builder, recursion_level: 0, entry_point, call_stack: CallStack::new() } } @@ -354,8 +363,15 @@ impl<'function> PerFunctionContext<'function> { match &self.source_function.dfg[*id] { Instruction::Call { func, arguments } => match self.get_function(*func) { Some(function) => match ssa.functions[&function].runtime() { - RuntimeType::Acir => self.inline_function(ssa, *id, function, arguments), - RuntimeType::Brillig => self.push_instruction(*id), + // TODO: update this to differentiate the inline types + RuntimeType::Acir(InlineType::Inline) => { + dbg!(function); + self.inline_function(ssa, *id, function, arguments) + } + RuntimeType::Acir(InlineType::Fold) | RuntimeType::Brillig => { + dbg!(function); + self.push_instruction(*id) + } }, None => self.push_instruction(*id), }, @@ -518,7 +534,7 @@ mod test { function_builder::FunctionBuilder, ir::{ basic_block::BasicBlockId, - function::RuntimeType, + function::{InlineType, RuntimeType}, instruction::{BinaryOp, Intrinsic, TerminatorInstruction}, map::Id, types::Type, @@ -537,14 +553,15 @@ mod test { // return 72 // } let foo_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("foo".into(), foo_id, RuntimeType::Acir, false); + let mut builder = + FunctionBuilder::new("foo".into(), foo_id, RuntimeType::Acir(InlineType::default())); let bar_id = Id::test_new(1); let bar = builder.import_function(bar_id); let results = builder.insert_call(bar, Vec::new(), vec![Type::field()]).to_vec(); builder.terminate_with_return(results); - builder.new_function("bar".into(), bar_id, false); + builder.new_function("bar".into(), bar_id, InlineType::default()); let expected_return = 72u128; let seventy_two = builder.field_constant(expected_return); builder.terminate_with_return(vec![seventy_two]); @@ -586,7 +603,8 @@ mod test { let id2_id = Id::test_new(3); // Compiling main - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir, false); + let mut builder = + FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir(InlineType::default())); let main_v0 = builder.add_parameter(Type::field()); let main_f1 = builder.import_function(square_id); @@ -599,18 +617,18 @@ mod test { builder.terminate_with_return(vec![main_v16]); // Compiling square f1 - builder.new_function("square".into(), square_id, false); + builder.new_function("square".into(), square_id, InlineType::default()); let square_v0 = builder.add_parameter(Type::field()); let square_v2 = builder.insert_binary(square_v0, BinaryOp::Mul, square_v0); builder.terminate_with_return(vec![square_v2]); // Compiling id1 f2 - builder.new_function("id1".into(), id1_id, false); + builder.new_function("id1".into(), id1_id, InlineType::default()); let id1_v0 = builder.add_parameter(Type::Function); builder.terminate_with_return(vec![id1_v0]); // Compiling id2 f3 - builder.new_function("id2".into(), id2_id, false); + builder.new_function("id2".into(), id2_id, InlineType::default()); let id2_v0 = builder.add_parameter(Type::Function); builder.terminate_with_return(vec![id2_v0]); @@ -642,7 +660,8 @@ mod test { // return v4 // } let main_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir, false); + let mut builder = + FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir(InlineType::default())); let factorial_id = Id::test_new(1); let factorial = builder.import_function(factorial_id); @@ -651,7 +670,7 @@ mod test { let results = builder.insert_call(factorial, vec![five], vec![Type::field()]).to_vec(); builder.terminate_with_return(results); - builder.new_function("factorial".into(), factorial_id, false); + builder.new_function("factorial".into(), factorial_id, InlineType::default()); let b1 = builder.insert_block(); let b2 = builder.insert_block(); @@ -742,7 +761,8 @@ mod test { // jmp b3(Field 2) // } let main_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir, false); + let mut builder = + FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir(InlineType::default())); let main_cond = builder.add_parameter(Type::bool()); let inner1_id = Id::test_new(1); @@ -752,14 +772,14 @@ mod test { builder.insert_call(assert_constant, vec![main_v2], vec![]); builder.terminate_with_return(vec![]); - builder.new_function("inner1".into(), inner1_id, false); + builder.new_function("inner1".into(), inner1_id, InlineType::default()); let inner1_cond = builder.add_parameter(Type::bool()); let inner2_id = Id::test_new(2); let inner2 = builder.import_function(inner2_id); let inner1_v2 = builder.insert_call(inner2, vec![inner1_cond], vec![Type::field()])[0]; builder.terminate_with_return(vec![inner1_v2]); - builder.new_function("inner2".into(), inner2_id, false); + builder.new_function("inner2".into(), inner2_id, InlineType::default()); let inner2_cond = builder.add_parameter(Type::bool()); let then_block = builder.insert_block(); let else_block = builder.insert_block(); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/mem2reg.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/mem2reg.rs index c6cc39bb495c..b47d6594bc5d 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/mem2reg.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/mem2reg.rs @@ -414,7 +414,7 @@ mod tests { ir::{ basic_block::BasicBlockId, dfg::DataFlowGraph, - function::RuntimeType, + function::{InlineType, RuntimeType}, instruction::{BinaryOp, Instruction, Intrinsic, TerminatorInstruction}, map::Id, types::Type, @@ -433,7 +433,8 @@ mod tests { // } let func_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("func".into(), func_id, RuntimeType::Acir, false); + let mut builder = + FunctionBuilder::new("func".into(), func_id, RuntimeType::Acir(InlineType::default())); let v0 = builder.insert_allocate(Type::Array(Rc::new(vec![Type::field()]), 2)); let one = builder.field_constant(FieldElement::one()); let two = builder.field_constant(FieldElement::one()); @@ -474,7 +475,8 @@ mod tests { // } let func_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("func".into(), func_id, RuntimeType::Acir, false); + let mut builder = + FunctionBuilder::new("func".into(), func_id, RuntimeType::Acir(InlineType::default())); let v0 = builder.insert_allocate(Type::field()); let one = builder.field_constant(FieldElement::one()); builder.insert_store(v0, one); @@ -508,7 +510,8 @@ mod tests { // } let func_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("func".into(), func_id, RuntimeType::Acir, false); + let mut builder = + FunctionBuilder::new("func".into(), func_id, RuntimeType::Acir(InlineType::default())); let v0 = builder.insert_allocate(Type::field()); let const_one = builder.field_constant(FieldElement::one()); builder.insert_store(v0, const_one); @@ -567,7 +570,8 @@ mod tests { // return v2, v3, v4 // } let main_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir, false); + let mut builder = + FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir(InlineType::default())); let v0 = builder.insert_allocate(Type::field()); @@ -647,7 +651,8 @@ mod tests { // return // } let main_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir, false); + let mut builder = + FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir(InlineType::default())); let v0 = builder.insert_allocate(Type::field()); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/simplify_cfg.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/simplify_cfg.rs index 9e15ca32c8eb..f4b32b6bafad 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/simplify_cfg.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/simplify_cfg.rs @@ -154,7 +154,7 @@ mod test { use crate::ssa::{ function_builder::FunctionBuilder, ir::{ - function::RuntimeType, + function::{InlineType, RuntimeType}, instruction::{BinaryOp, TerminatorInstruction}, map::Id, types::Type, @@ -172,7 +172,8 @@ mod test { // return v1 // } let main_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir, false); + let mut builder = + FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir(InlineType::default())); let b1 = builder.insert_block(); let b2 = builder.insert_block(); @@ -228,7 +229,8 @@ mod test { // return Field 2 // } let main_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir, false); + let mut builder = + FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir(InlineType::default())); let v0 = builder.add_parameter(Type::bool()); let b1 = builder.insert_block(); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/unrolling.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/unrolling.rs index ad02e2330678..61aed1a2cbaa 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/unrolling.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/unrolling.rs @@ -48,7 +48,8 @@ impl Ssa { // This check is always true with the addition of the above guard, but I'm // keeping it in case the guard on brillig functions is ever removed. - let abort_on_error = function.runtime() == RuntimeType::Acir; + let abort_on_error = + if let RuntimeType::Acir(_) = function.runtime() { true } else { false }; find_all_loops(function).unroll_each_loop(function, abort_on_error)?; } Ok(self) @@ -464,7 +465,12 @@ impl<'f> LoopIteration<'f> { mod tests { use crate::ssa::{ function_builder::FunctionBuilder, - ir::{function::RuntimeType, instruction::BinaryOp, map::Id, types::Type}, + ir::{ + function::{InlineType, RuntimeType}, + instruction::BinaryOp, + map::Id, + types::Type, + }, }; #[test] @@ -503,7 +509,8 @@ mod tests { let main_id = Id::test_new(0); // Compiling main - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir, false); + let mut builder = + FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir(InlineType::default())); let b1 = builder.insert_block(); let b2 = builder.insert_block(); @@ -605,7 +612,8 @@ mod tests { // return Field 0 // } let main_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir, false); + let mut builder = + FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir(InlineType::default())); let b1 = builder.insert_block(); let b2 = builder.insert_block(); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs index a7fb5acbc314..06e8a823c54c 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs @@ -11,8 +11,8 @@ use noirc_frontend::{BinaryOpKind, Signedness}; use crate::errors::RuntimeError; use crate::ssa::function_builder::FunctionBuilder; use crate::ssa::ir::dfg::DataFlowGraph; -use crate::ssa::ir::function::FunctionId as IrFunctionId; use crate::ssa::ir::function::{Function, RuntimeType}; +use crate::ssa::ir::function::{FunctionId as IrFunctionId, InlineType}; use crate::ssa::ir::instruction::BinaryOp; use crate::ssa::ir::instruction::Instruction; use crate::ssa::ir::map::AtomicCounter; @@ -89,14 +89,13 @@ impl<'a> FunctionContext<'a> { parameters: &Parameters, runtime: RuntimeType, shared_context: &'a SharedContext, - should_fold: bool, ) -> Self { let function_id = shared_context .pop_next_function_in_queue() .expect("No function in queue for the FunctionContext to compile") .1; - let builder = FunctionBuilder::new(function_name, function_id, runtime, should_fold); + let builder = FunctionBuilder::new(function_name, function_id, runtime); let mut this = Self { definitions: HashMap::default(), builder, shared_context }; this.add_parameters_to_scope(parameters); this @@ -112,7 +111,8 @@ impl<'a> FunctionContext<'a> { if func.unconstrained { self.builder.new_brillig_function(func.name.clone(), id); } else { - self.builder.new_function(func.name.clone(), id, func.should_fold); + let inline_type = if func.should_fold { InlineType::Fold } else { InlineType::Inline }; + self.builder.new_function(func.name.clone(), id, inline_type); } self.add_parameters_to_scope(&func.parameters); } diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs index e5f89e961f1a..5748e31a05c2 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs @@ -14,7 +14,10 @@ use noirc_frontend::{ use crate::{ errors::{InternalError, RuntimeError}, - ssa::{function_builder::data_bus::DataBusBuilder, ir::instruction::Intrinsic}, + ssa::{ + function_builder::data_bus::DataBusBuilder, + ir::{function::InlineType, instruction::Intrinsic}, + }, }; use self::{ @@ -53,16 +56,16 @@ pub(crate) fn generate_ssa( // Queue the main function for compilation context.get_or_queue_function(main_id); dbg!(main.should_fold); + let main_inline_type = if main.should_fold { InlineType::Fold } else { InlineType::Inline }; let mut function_context = FunctionContext::new( main.name.clone(), &main.parameters, if force_brillig_runtime || main.unconstrained { RuntimeType::Brillig } else { - RuntimeType::Acir + RuntimeType::Acir(main_inline_type) }, &context, - main.should_fold, ); // Generate the call_data bus from the relevant parameters. We create it *before* processing the function body diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/program.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/program.rs index 509f778f3b03..9995c031145e 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/program.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/program.rs @@ -12,6 +12,7 @@ pub(crate) struct Ssa { pub(crate) functions: BTreeMap, pub(crate) main_id: FunctionId, pub(crate) next_id: AtomicCounter, + pub(crate) id_to_index: BTreeMap, } impl Ssa { @@ -26,7 +27,9 @@ impl Ssa { (f.id(), f) }); - Self { functions, main_id, next_id: AtomicCounter::starting_after(max_id) } + let id_to_index = btree_map(functions.iter().enumerate(), |(i, (id, _))| (*id, i as u32)); + + Self { functions, main_id, next_id: AtomicCounter::starting_after(max_id), id_to_index } } /// Returns the entry-point function of the program diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/resolver.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/resolver.rs index 16a23aca854c..df5f3155a914 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/resolver.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/resolver.rs @@ -897,7 +897,7 @@ impl<'a> Resolver<'a> { let name_ident = HirIdent::non_trait_method(id, location); let attributes = func.attributes().clone(); - + let mut generics = vecmap(&self.generics, |(_, typevar, _)| typevar.clone()); let mut parameters = vec![]; let mut parameter_types = vec![]; @@ -977,7 +977,10 @@ impl<'a> Resolver<'a> { .map(|(name, typevar, _span)| (name.clone(), typevar.clone())) .collect(); - let should_inline = attributes.function.as_ref().map_or(true, |func_attribute| !func_attribute.is_foldable()); + let should_inline = attributes + .function + .as_ref() + .map_or(true, |func_attribute| !func_attribute.is_foldable()); if func.name() == "basic_func" { dbg!(attributes.clone()); } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir_def/function.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir_def/function.rs index 825bae30a9e2..e3a842a86d84 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir_def/function.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir_def/function.rs @@ -125,7 +125,7 @@ pub struct FuncMeta { /// For non-contracts, this means the function is `main`. pub is_entry_point: bool, - /// False if this function is marked with an attribute + /// False if this function is marked with an attribute /// that indicates it should not be inlined, such as for folding. pub should_inline: bool, } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/lexer/lexer.rs b/noir/noir-repo/compiler/noirc_frontend/src/lexer/lexer.rs index 41433e81acaf..363ca767a89a 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/lexer/lexer.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/lexer/lexer.rs @@ -733,10 +733,7 @@ mod tests { let mut lexer = Lexer::new(input); let token = lexer.next_token().unwrap(); - assert_eq!( - token.token(), - &Token::Attribute(Attribute::Function(FunctionAttribute::Fold)) - ); + assert_eq!(token.token(), &Token::Attribute(Attribute::Function(FunctionAttribute::Fold))); } #[test] diff --git a/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/ast.rs b/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/ast.rs index 532c95f9a22f..729e61cf08f1 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/ast.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/ast.rs @@ -209,6 +209,7 @@ pub struct Function { pub return_type: Type, pub unconstrained: bool, pub should_fold: bool, + pub func_sig: FunctionSignature, } /// Compared to hir_def::types::Type, this monomorphized Type has: @@ -243,6 +244,7 @@ impl Type { #[derive(Debug, Clone, Hash)] pub struct Program { pub functions: Vec, + pub function_signatures: Vec, pub main_function_signature: FunctionSignature, /// Indicates whether witness indices are allowed to reoccur in the ABI of the resulting ACIR. /// @@ -262,6 +264,7 @@ impl Program { #[allow(clippy::too_many_arguments)] pub fn new( functions: Vec, + function_signatures: Vec, main_function_signature: FunctionSignature, return_distinctness: Distinctness, return_location: Option, @@ -273,6 +276,7 @@ impl Program { ) -> Program { Program { functions, + function_signatures, main_function_signature, return_distinctness, return_location, diff --git a/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/mod.rs b/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/mod.rs index df0aac4bfc0a..934c4e06e388 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/mod.rs @@ -160,8 +160,10 @@ pub fn monomorphize_debug( undo_instantiation_bindings(impl_bindings); undo_instantiation_bindings(bindings); } + let func_sigs = vecmap(monomorphizer.finished_functions.iter(), |(_, f)| f.func_sig.clone()); let functions = vecmap(monomorphizer.finished_functions, |(_, f)| f); + // let (functions, func_sigs) = monomorphizer.finished_functions.into_iter().map(|(_, f)| (f, f.func_sig.clone())).unzip(); let FuncMeta { return_distinctness, return_visibility, kind, .. } = monomorphizer.interner.function_meta(&main); @@ -169,6 +171,7 @@ pub fn monomorphize_debug( monomorphizer.debug_type_tracker.extract_vars_and_types(); let program = Program::new( functions, + func_sigs, function_sig, *return_distinctness, monomorphizer.return_location, @@ -303,6 +306,7 @@ impl<'interner> Monomorphizer<'interner> { } let meta = self.interner.function_meta(&f).clone(); + let func_sig = meta.function_signature(); let modifiers = self.interner.function_modifiers(&f); let name = self.interner.function_name(&f).to_owned(); @@ -319,7 +323,16 @@ impl<'interner> Monomorphizer<'interner> { let parameters = self.parameters(&meta.parameters); let body = self.expr(body_expr_id)?; - let function = ast::Function { id, name, parameters, body, return_type, unconstrained, should_fold }; + let function = ast::Function { + id, + name, + parameters, + body, + return_type, + unconstrained, + should_fold, + func_sig, + }; self.push_function(id, function); Ok(()) @@ -1339,7 +1352,16 @@ impl<'interner> Monomorphizer<'interner> { let name = lambda_name.to_owned(); let unconstrained = false; - let function = ast::Function { id, name, parameters, body, return_type, unconstrained, should_fold: false }; + let function = ast::Function { + id, + name, + parameters, + body, + return_type, + unconstrained, + should_fold: false, + func_sig: FunctionSignature::default(), + }; self.push_function(id, function); let typ = @@ -1453,7 +1475,16 @@ impl<'interner> Monomorphizer<'interner> { parameters.append(&mut converted_parameters); let unconstrained = false; - let function = ast::Function { id, name, parameters, body, return_type, unconstrained, should_fold: false }; + let function = ast::Function { + id, + name, + parameters, + body, + return_type, + unconstrained, + should_fold: false, + func_sig: FunctionSignature::default(), + }; self.push_function(id, function); let lambda_value = @@ -1571,7 +1602,16 @@ impl<'interner> Monomorphizer<'interner> { let name = lambda_name.to_owned(); let unconstrained = false; - let function = ast::Function { id, name, parameters, body, return_type, unconstrained, should_fold: false }; + let function = ast::Function { + id, + name, + parameters, + body, + return_type, + unconstrained, + should_fold: false, + func_sig: FunctionSignature::default(), + }; self.push_function(id, function); ast::Expression::Ident(ast::Ident { diff --git a/noir/noir-repo/test_programs/execution_success/fold_basic/Prover.toml b/noir/noir-repo/test_programs/execution_success/fold_basic/Prover.toml new file mode 100644 index 000000000000..f28f2f8cc48f --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/fold_basic/Prover.toml @@ -0,0 +1,2 @@ +x = "5" +y = "10" From b7111ccc887a15a6fdccda189a5f934dbad46fca Mon Sep 17 00:00:00 2001 From: vezenovm Date: Tue, 19 Mar 2024 19:18:46 +0000 Subject: [PATCH 093/139] fix acir cpp after merge conflicts --- .../noir-repo/acvm-repo/acir/codegen/acir.cpp | 11033 +++++++--------- 1 file changed, 4667 insertions(+), 6366 deletions(-) diff --git a/noir/noir-repo/acvm-repo/acir/codegen/acir.cpp b/noir/noir-repo/acvm-repo/acir/codegen/acir.cpp index 04a6ac7d3b8e..32525007e2ad 100644 --- a/noir/noir-repo/acvm-repo/acir/codegen/acir.cpp +++ b/noir/noir-repo/acvm-repo/acir/codegen/acir.cpp @@ -1,8301 +1,6602 @@ #pragma once -#include "bincode.hpp" #include "serde.hpp" +#include "bincode.hpp" namespace Program { -struct BinaryFieldOp { - - struct Add { - friend bool operator==(const Add &, const Add &); - std::vector bincodeSerialize() const; - static Add bincodeDeserialize(std::vector); - }; - - struct Sub { - friend bool operator==(const Sub &, const Sub &); - std::vector bincodeSerialize() const; - static Sub bincodeDeserialize(std::vector); - }; - - struct Mul { - friend bool operator==(const Mul &, const Mul &); - std::vector bincodeSerialize() const; - static Mul bincodeDeserialize(std::vector); - }; - - struct Div { - friend bool operator==(const Div &, const Div &); - std::vector bincodeSerialize() const; - static Div bincodeDeserialize(std::vector); - }; - - struct IntegerDiv { - friend bool operator==(const IntegerDiv &, const IntegerDiv &); - std::vector bincodeSerialize() const; - static IntegerDiv bincodeDeserialize(std::vector); - }; - - struct Equals { - friend bool operator==(const Equals &, const Equals &); - std::vector bincodeSerialize() const; - static Equals bincodeDeserialize(std::vector); - }; - - struct LessThan { - friend bool operator==(const LessThan &, const LessThan &); - std::vector bincodeSerialize() const; - static LessThan bincodeDeserialize(std::vector); - }; - - struct LessThanEquals { - friend bool operator==(const LessThanEquals &, const LessThanEquals &); - std::vector bincodeSerialize() const; - static LessThanEquals bincodeDeserialize(std::vector); - }; - - std::variant - value; - - friend bool operator==(const BinaryFieldOp &, const BinaryFieldOp &); - std::vector bincodeSerialize() const; - static BinaryFieldOp bincodeDeserialize(std::vector); -}; - -struct BinaryIntOp { - - struct Add { - friend bool operator==(const Add &, const Add &); - std::vector bincodeSerialize() const; - static Add bincodeDeserialize(std::vector); - }; - - struct Sub { - friend bool operator==(const Sub &, const Sub &); - std::vector bincodeSerialize() const; - static Sub bincodeDeserialize(std::vector); - }; - - struct Mul { - friend bool operator==(const Mul &, const Mul &); - std::vector bincodeSerialize() const; - static Mul bincodeDeserialize(std::vector); - }; - - struct Div { - friend bool operator==(const Div &, const Div &); - std::vector bincodeSerialize() const; - static Div bincodeDeserialize(std::vector); - }; - - struct Equals { - friend bool operator==(const Equals &, const Equals &); - std::vector bincodeSerialize() const; - static Equals bincodeDeserialize(std::vector); - }; - - struct LessThan { - friend bool operator==(const LessThan &, const LessThan &); - std::vector bincodeSerialize() const; - static LessThan bincodeDeserialize(std::vector); - }; - - struct LessThanEquals { - friend bool operator==(const LessThanEquals &, const LessThanEquals &); - std::vector bincodeSerialize() const; - static LessThanEquals bincodeDeserialize(std::vector); - }; - - struct And { - friend bool operator==(const And &, const And &); - std::vector bincodeSerialize() const; - static And bincodeDeserialize(std::vector); - }; - - struct Or { - friend bool operator==(const Or &, const Or &); - std::vector bincodeSerialize() const; - static Or bincodeDeserialize(std::vector); - }; - - struct Xor { - friend bool operator==(const Xor &, const Xor &); - std::vector bincodeSerialize() const; - static Xor bincodeDeserialize(std::vector); - }; - - struct Shl { - friend bool operator==(const Shl &, const Shl &); - std::vector bincodeSerialize() const; - static Shl bincodeDeserialize(std::vector); - }; - - struct Shr { - friend bool operator==(const Shr &, const Shr &); - std::vector bincodeSerialize() const; - static Shr bincodeDeserialize(std::vector); - }; - - std::variant - value; - - friend bool operator==(const BinaryIntOp &, const BinaryIntOp &); - std::vector bincodeSerialize() const; - static BinaryIntOp bincodeDeserialize(std::vector); -}; - -struct MemoryAddress { - uint64_t value; - - friend bool operator==(const MemoryAddress &, const MemoryAddress &); - std::vector bincodeSerialize() const; - static MemoryAddress bincodeDeserialize(std::vector); -}; - -struct HeapArray { - Program::MemoryAddress pointer; - uint64_t size; - - friend bool operator==(const HeapArray &, const HeapArray &); - std::vector bincodeSerialize() const; - static HeapArray bincodeDeserialize(std::vector); -}; - -struct HeapVector { - Program::MemoryAddress pointer; - Program::MemoryAddress size; - - friend bool operator==(const HeapVector &, const HeapVector &); - std::vector bincodeSerialize() const; - static HeapVector bincodeDeserialize(std::vector); -}; - -struct BlackBoxOp { - - struct Sha256 { - Program::HeapVector message; - Program::HeapArray output; - - friend bool operator==(const Sha256 &, const Sha256 &); - std::vector bincodeSerialize() const; - static Sha256 bincodeDeserialize(std::vector); - }; - - struct Blake2s { - Program::HeapVector message; - Program::HeapArray output; - - friend bool operator==(const Blake2s &, const Blake2s &); - std::vector bincodeSerialize() const; - static Blake2s bincodeDeserialize(std::vector); - }; - - struct Blake3 { - Program::HeapVector message; - Program::HeapArray output; - - friend bool operator==(const Blake3 &, const Blake3 &); - std::vector bincodeSerialize() const; - static Blake3 bincodeDeserialize(std::vector); - }; - - struct Keccak256 { - Program::HeapVector message; - Program::HeapArray output; - - friend bool operator==(const Keccak256 &, const Keccak256 &); - std::vector bincodeSerialize() const; - static Keccak256 bincodeDeserialize(std::vector); - }; - - struct Keccakf1600 { - Program::HeapVector message; - Program::HeapArray output; - - friend bool operator==(const Keccakf1600 &, const Keccakf1600 &); - std::vector bincodeSerialize() const; - static Keccakf1600 bincodeDeserialize(std::vector); - }; - - struct EcdsaSecp256k1 { - Program::HeapVector hashed_msg; - Program::HeapArray public_key_x; - Program::HeapArray public_key_y; - Program::HeapArray signature; - Program::MemoryAddress result; - - friend bool operator==(const EcdsaSecp256k1 &, const EcdsaSecp256k1 &); - std::vector bincodeSerialize() const; - static EcdsaSecp256k1 bincodeDeserialize(std::vector); - }; - - struct EcdsaSecp256r1 { - Program::HeapVector hashed_msg; - Program::HeapArray public_key_x; - Program::HeapArray public_key_y; - Program::HeapArray signature; - Program::MemoryAddress result; - - friend bool operator==(const EcdsaSecp256r1 &, const EcdsaSecp256r1 &); - std::vector bincodeSerialize() const; - static EcdsaSecp256r1 bincodeDeserialize(std::vector); - }; - - struct SchnorrVerify { - Program::MemoryAddress public_key_x; - Program::MemoryAddress public_key_y; - Program::HeapVector message; - Program::HeapVector signature; - Program::MemoryAddress result; - - friend bool operator==(const SchnorrVerify &, const SchnorrVerify &); - std::vector bincodeSerialize() const; - static SchnorrVerify bincodeDeserialize(std::vector); - }; - - struct PedersenCommitment { - Program::HeapVector inputs; - Program::MemoryAddress domain_separator; - Program::HeapArray output; - - friend bool operator==(const PedersenCommitment &, - const PedersenCommitment &); - std::vector bincodeSerialize() const; - static PedersenCommitment bincodeDeserialize(std::vector); - }; - - struct PedersenHash { - Program::HeapVector inputs; - Program::MemoryAddress domain_separator; - Program::MemoryAddress output; - - friend bool operator==(const PedersenHash &, const PedersenHash &); - std::vector bincodeSerialize() const; - static PedersenHash bincodeDeserialize(std::vector); - }; - - struct FixedBaseScalarMul { - Program::MemoryAddress low; - Program::MemoryAddress high; - Program::HeapArray result; - - friend bool operator==(const FixedBaseScalarMul &, - const FixedBaseScalarMul &); - std::vector bincodeSerialize() const; - static FixedBaseScalarMul bincodeDeserialize(std::vector); - }; - - struct EmbeddedCurveAdd { - Program::MemoryAddress input1_x; - Program::MemoryAddress input1_y; - Program::MemoryAddress input2_x; - Program::MemoryAddress input2_y; - Program::HeapArray result; - - friend bool operator==(const EmbeddedCurveAdd &, const EmbeddedCurveAdd &); - std::vector bincodeSerialize() const; - static EmbeddedCurveAdd bincodeDeserialize(std::vector); - }; - - struct BigIntAdd { - Program::MemoryAddress lhs; - Program::MemoryAddress rhs; - Program::MemoryAddress output; - - friend bool operator==(const BigIntAdd &, const BigIntAdd &); - std::vector bincodeSerialize() const; - static BigIntAdd bincodeDeserialize(std::vector); - }; - - struct BigIntSub { - Program::MemoryAddress lhs; - Program::MemoryAddress rhs; - Program::MemoryAddress output; - - friend bool operator==(const BigIntSub &, const BigIntSub &); - std::vector bincodeSerialize() const; - static BigIntSub bincodeDeserialize(std::vector); - }; - - struct BigIntMul { - Program::MemoryAddress lhs; - Program::MemoryAddress rhs; - Program::MemoryAddress output; - - friend bool operator==(const BigIntMul &, const BigIntMul &); - std::vector bincodeSerialize() const; - static BigIntMul bincodeDeserialize(std::vector); - }; - - struct BigIntDiv { - Program::MemoryAddress lhs; - Program::MemoryAddress rhs; - Program::MemoryAddress output; - - friend bool operator==(const BigIntDiv &, const BigIntDiv &); - std::vector bincodeSerialize() const; - static BigIntDiv bincodeDeserialize(std::vector); - }; - - struct BigIntFromLeBytes { - Program::HeapVector inputs; - Program::HeapVector modulus; - Program::MemoryAddress output; - - friend bool operator==(const BigIntFromLeBytes &, - const BigIntFromLeBytes &); - std::vector bincodeSerialize() const; - static BigIntFromLeBytes bincodeDeserialize(std::vector); - }; - - struct BigIntToLeBytes { - Program::MemoryAddress input; - Program::HeapVector output; - - friend bool operator==(const BigIntToLeBytes &, const BigIntToLeBytes &); - std::vector bincodeSerialize() const; - static BigIntToLeBytes bincodeDeserialize(std::vector); - }; - - struct Poseidon2Permutation { - Program::HeapVector message; - Program::HeapArray output; - Program::MemoryAddress len; - - friend bool operator==(const Poseidon2Permutation &, - const Poseidon2Permutation &); - std::vector bincodeSerialize() const; - static Poseidon2Permutation bincodeDeserialize(std::vector); - }; - - struct Sha256Compression { - Program::HeapVector input; - Program::HeapVector hash_values; - Program::HeapArray output; - - friend bool operator==(const Sha256Compression &, - const Sha256Compression &); - std::vector bincodeSerialize() const; - static Sha256Compression bincodeDeserialize(std::vector); - }; - - std::variant - value; - - friend bool operator==(const BlackBoxOp &, const BlackBoxOp &); - std::vector bincodeSerialize() const; - static BlackBoxOp bincodeDeserialize(std::vector); -}; - -struct HeapValueType; - -struct HeapValueType { - - struct Simple { - friend bool operator==(const Simple &, const Simple &); - std::vector bincodeSerialize() const; - static Simple bincodeDeserialize(std::vector); - }; - - struct Array { - std::vector value_types; - uint64_t size; - - friend bool operator==(const Array &, const Array &); - std::vector bincodeSerialize() const; - static Array bincodeDeserialize(std::vector); - }; - - struct Vector { - std::vector value_types; - - friend bool operator==(const Vector &, const Vector &); - std::vector bincodeSerialize() const; - static Vector bincodeDeserialize(std::vector); - }; - - std::variant value; - - friend bool operator==(const HeapValueType &, const HeapValueType &); - std::vector bincodeSerialize() const; - static HeapValueType bincodeDeserialize(std::vector); -}; - -struct Value { - std::string inner; - - friend bool operator==(const Value &, const Value &); - std::vector bincodeSerialize() const; - static Value bincodeDeserialize(std::vector); -}; - -struct ValueOrArray { - - struct MemoryAddress { - Program::MemoryAddress value; - - friend bool operator==(const MemoryAddress &, const MemoryAddress &); - std::vector bincodeSerialize() const; - static MemoryAddress bincodeDeserialize(std::vector); - }; - - struct HeapArray { - Program::HeapArray value; - - friend bool operator==(const HeapArray &, const HeapArray &); - std::vector bincodeSerialize() const; - static HeapArray bincodeDeserialize(std::vector); - }; - - struct HeapVector { - Program::HeapVector value; - - friend bool operator==(const HeapVector &, const HeapVector &); - std::vector bincodeSerialize() const; - static HeapVector bincodeDeserialize(std::vector); - }; - - std::variant value; - - friend bool operator==(const ValueOrArray &, const ValueOrArray &); - std::vector bincodeSerialize() const; - static ValueOrArray bincodeDeserialize(std::vector); -}; - -struct BrilligOpcode { - - struct BinaryFieldOp { - Program::MemoryAddress destination; - Program::BinaryFieldOp op; - Program::MemoryAddress lhs; - Program::MemoryAddress rhs; - - friend bool operator==(const BinaryFieldOp &, const BinaryFieldOp &); - std::vector bincodeSerialize() const; - static BinaryFieldOp bincodeDeserialize(std::vector); - }; - - struct BinaryIntOp { - Program::MemoryAddress destination; - Program::BinaryIntOp op; - uint32_t bit_size; - Program::MemoryAddress lhs; - Program::MemoryAddress rhs; - - friend bool operator==(const BinaryIntOp &, const BinaryIntOp &); - std::vector bincodeSerialize() const; - static BinaryIntOp bincodeDeserialize(std::vector); - }; - - struct Cast { - Program::MemoryAddress destination; - Program::MemoryAddress source; - uint32_t bit_size; - - friend bool operator==(const Cast &, const Cast &); - std::vector bincodeSerialize() const; - static Cast bincodeDeserialize(std::vector); - }; - - struct JumpIfNot { - Program::MemoryAddress condition; - uint64_t location; - - friend bool operator==(const JumpIfNot &, const JumpIfNot &); - std::vector bincodeSerialize() const; - static JumpIfNot bincodeDeserialize(std::vector); - }; - - struct JumpIf { - Program::MemoryAddress condition; - uint64_t location; - - friend bool operator==(const JumpIf &, const JumpIf &); - std::vector bincodeSerialize() const; - static JumpIf bincodeDeserialize(std::vector); - }; - - struct Jump { - uint64_t location; - - friend bool operator==(const Jump &, const Jump &); - std::vector bincodeSerialize() const; - static Jump bincodeDeserialize(std::vector); - }; - - struct CalldataCopy { - Program::MemoryAddress destination_address; - uint64_t size; - uint64_t offset; - - friend bool operator==(const CalldataCopy &, const CalldataCopy &); - std::vector bincodeSerialize() const; - static CalldataCopy bincodeDeserialize(std::vector); - }; - - struct Call { - uint64_t location; - - friend bool operator==(const Call &, const Call &); - std::vector bincodeSerialize() const; - static Call bincodeDeserialize(std::vector); - }; - - struct Const { - Program::MemoryAddress destination; - uint32_t bit_size; - Program::Value value; - - friend bool operator==(const Const &, const Const &); - std::vector bincodeSerialize() const; - static Const bincodeDeserialize(std::vector); - }; - - struct Return { - friend bool operator==(const Return &, const Return &); - std::vector bincodeSerialize() const; - static Return bincodeDeserialize(std::vector); - }; - - struct ForeignCall { - std::string function; - std::vector destinations; - std::vector destination_value_types; - std::vector inputs; - std::vector input_value_types; - - friend bool operator==(const ForeignCall &, const ForeignCall &); - std::vector bincodeSerialize() const; - static ForeignCall bincodeDeserialize(std::vector); - }; - - struct Mov { - Program::MemoryAddress destination; - Program::MemoryAddress source; - - friend bool operator==(const Mov &, const Mov &); - std::vector bincodeSerialize() const; - static Mov bincodeDeserialize(std::vector); - }; - - struct Load { - Program::MemoryAddress destination; - Program::MemoryAddress source_pointer; - - friend bool operator==(const Load &, const Load &); - std::vector bincodeSerialize() const; - static Load bincodeDeserialize(std::vector); - }; - - struct Store { - Program::MemoryAddress destination_pointer; - Program::MemoryAddress source; - - friend bool operator==(const Store &, const Store &); - std::vector bincodeSerialize() const; - static Store bincodeDeserialize(std::vector); - }; - - struct BlackBox { - Program::BlackBoxOp value; - - friend bool operator==(const BlackBox &, const BlackBox &); - std::vector bincodeSerialize() const; - static BlackBox bincodeDeserialize(std::vector); - }; - - struct Trap { - friend bool operator==(const Trap &, const Trap &); - std::vector bincodeSerialize() const; - static Trap bincodeDeserialize(std::vector); - }; - - struct Stop { - uint64_t return_data_offset; - uint64_t return_data_size; - - friend bool operator==(const Stop &, const Stop &); - std::vector bincodeSerialize() const; - static Stop bincodeDeserialize(std::vector); - }; - - std::variant - value; - - friend bool operator==(const BrilligOpcode &, const BrilligOpcode &); - std::vector bincodeSerialize() const; - static BrilligOpcode bincodeDeserialize(std::vector); -}; - -struct Witness { - uint32_t value; - - friend bool operator==(const Witness &, const Witness &); - std::vector bincodeSerialize() const; - static Witness bincodeDeserialize(std::vector); -}; - -struct FunctionInput { - Program::Witness witness; - uint32_t num_bits; - - friend bool operator==(const FunctionInput &, const FunctionInput &); - std::vector bincodeSerialize() const; - static FunctionInput bincodeDeserialize(std::vector); -}; - -struct BlackBoxFuncCall { - - struct AND { - Program::FunctionInput lhs; - Program::FunctionInput rhs; - Program::Witness output; - - friend bool operator==(const AND &, const AND &); - std::vector bincodeSerialize() const; - static AND bincodeDeserialize(std::vector); - }; - - struct XOR { - Program::FunctionInput lhs; - Program::FunctionInput rhs; - Program::Witness output; - - friend bool operator==(const XOR &, const XOR &); - std::vector bincodeSerialize() const; - static XOR bincodeDeserialize(std::vector); - }; - - struct RANGE { - Program::FunctionInput input; - - friend bool operator==(const RANGE &, const RANGE &); - std::vector bincodeSerialize() const; - static RANGE bincodeDeserialize(std::vector); - }; - - struct SHA256 { - std::vector inputs; - std::vector outputs; - - friend bool operator==(const SHA256 &, const SHA256 &); - std::vector bincodeSerialize() const; - static SHA256 bincodeDeserialize(std::vector); - }; - - struct Blake2s { - std::vector inputs; - std::vector outputs; - - friend bool operator==(const Blake2s &, const Blake2s &); - std::vector bincodeSerialize() const; - static Blake2s bincodeDeserialize(std::vector); - }; - - struct Blake3 { - std::vector inputs; - std::vector outputs; - - friend bool operator==(const Blake3 &, const Blake3 &); - std::vector bincodeSerialize() const; - static Blake3 bincodeDeserialize(std::vector); - }; - - struct SchnorrVerify { - Program::FunctionInput public_key_x; - Program::FunctionInput public_key_y; - std::vector signature; - std::vector message; - Program::Witness output; - - friend bool operator==(const SchnorrVerify &, const SchnorrVerify &); - std::vector bincodeSerialize() const; - static SchnorrVerify bincodeDeserialize(std::vector); - }; - - struct PedersenCommitment { - std::vector inputs; - uint32_t domain_separator; - std::array outputs; - - friend bool operator==(const PedersenCommitment &, - const PedersenCommitment &); - std::vector bincodeSerialize() const; - static PedersenCommitment bincodeDeserialize(std::vector); - }; - - struct PedersenHash { - std::vector inputs; - uint32_t domain_separator; - Program::Witness output; - - friend bool operator==(const PedersenHash &, const PedersenHash &); - std::vector bincodeSerialize() const; - static PedersenHash bincodeDeserialize(std::vector); - }; - - struct EcdsaSecp256k1 { - std::vector public_key_x; - std::vector public_key_y; - std::vector signature; - std::vector hashed_message; - Program::Witness output; - - friend bool operator==(const EcdsaSecp256k1 &, const EcdsaSecp256k1 &); - std::vector bincodeSerialize() const; - static EcdsaSecp256k1 bincodeDeserialize(std::vector); - }; - - struct EcdsaSecp256r1 { - std::vector public_key_x; - std::vector public_key_y; - std::vector signature; - std::vector hashed_message; - Program::Witness output; - - friend bool operator==(const EcdsaSecp256r1 &, const EcdsaSecp256r1 &); - std::vector bincodeSerialize() const; - static EcdsaSecp256r1 bincodeDeserialize(std::vector); - }; - - struct FixedBaseScalarMul { - Program::FunctionInput low; - Program::FunctionInput high; - std::array outputs; - - friend bool operator==(const FixedBaseScalarMul &, - const FixedBaseScalarMul &); - std::vector bincodeSerialize() const; - static FixedBaseScalarMul bincodeDeserialize(std::vector); - }; - - struct EmbeddedCurveAdd { - Program::FunctionInput input1_x; - Program::FunctionInput input1_y; - Program::FunctionInput input2_x; - Program::FunctionInput input2_y; - std::array outputs; - - friend bool operator==(const EmbeddedCurveAdd &, const EmbeddedCurveAdd &); - std::vector bincodeSerialize() const; - static EmbeddedCurveAdd bincodeDeserialize(std::vector); - }; - - struct Keccak256 { - std::vector inputs; - std::vector outputs; - - friend bool operator==(const Keccak256 &, const Keccak256 &); - std::vector bincodeSerialize() const; - static Keccak256 bincodeDeserialize(std::vector); - }; - - struct Keccak256VariableLength { - std::vector inputs; - Program::FunctionInput var_message_size; - std::vector outputs; - - friend bool operator==(const Keccak256VariableLength &, - const Keccak256VariableLength &); - std::vector bincodeSerialize() const; - static Keccak256VariableLength bincodeDeserialize(std::vector); - }; - - struct Keccakf1600 { - std::vector inputs; - std::vector outputs; - - friend bool operator==(const Keccakf1600 &, const Keccakf1600 &); - std::vector bincodeSerialize() const; - static Keccakf1600 bincodeDeserialize(std::vector); - }; - - struct RecursiveAggregation { - std::vector verification_key; - std::vector proof; - std::vector public_inputs; - Program::FunctionInput key_hash; - - friend bool operator==(const RecursiveAggregation &, - const RecursiveAggregation &); - std::vector bincodeSerialize() const; - static RecursiveAggregation bincodeDeserialize(std::vector); - }; - - struct BigIntAdd { - uint32_t lhs; - uint32_t rhs; - uint32_t output; - - friend bool operator==(const BigIntAdd &, const BigIntAdd &); - std::vector bincodeSerialize() const; - static BigIntAdd bincodeDeserialize(std::vector); - }; - - struct BigIntSub { - uint32_t lhs; - uint32_t rhs; - uint32_t output; - - friend bool operator==(const BigIntSub &, const BigIntSub &); - std::vector bincodeSerialize() const; - static BigIntSub bincodeDeserialize(std::vector); - }; - - struct BigIntMul { - uint32_t lhs; - uint32_t rhs; - uint32_t output; - - friend bool operator==(const BigIntMul &, const BigIntMul &); - std::vector bincodeSerialize() const; - static BigIntMul bincodeDeserialize(std::vector); - }; - - struct BigIntDiv { - uint32_t lhs; - uint32_t rhs; - uint32_t output; - - friend bool operator==(const BigIntDiv &, const BigIntDiv &); - std::vector bincodeSerialize() const; - static BigIntDiv bincodeDeserialize(std::vector); - }; - - struct BigIntFromLeBytes { - std::vector inputs; - std::vector modulus; - uint32_t output; - - friend bool operator==(const BigIntFromLeBytes &, - const BigIntFromLeBytes &); - std::vector bincodeSerialize() const; - static BigIntFromLeBytes bincodeDeserialize(std::vector); - }; - - struct BigIntToLeBytes { - uint32_t input; - std::vector outputs; - - friend bool operator==(const BigIntToLeBytes &, const BigIntToLeBytes &); - std::vector bincodeSerialize() const; - static BigIntToLeBytes bincodeDeserialize(std::vector); - }; - - struct Poseidon2Permutation { - std::vector inputs; - std::vector outputs; - uint32_t len; - - friend bool operator==(const Poseidon2Permutation &, - const Poseidon2Permutation &); - std::vector bincodeSerialize() const; - static Poseidon2Permutation bincodeDeserialize(std::vector); - }; - - struct Sha256Compression { - std::vector inputs; - std::vector hash_values; - std::vector outputs; - - friend bool operator==(const Sha256Compression &, - const Sha256Compression &); - std::vector bincodeSerialize() const; - static Sha256Compression bincodeDeserialize(std::vector); - }; - - std::variant - value; - - friend bool operator==(const BlackBoxFuncCall &, const BlackBoxFuncCall &); - std::vector bincodeSerialize() const; - static BlackBoxFuncCall bincodeDeserialize(std::vector); -}; - -struct BlockId { - uint32_t value; - - friend bool operator==(const BlockId &, const BlockId &); - std::vector bincodeSerialize() const; - static BlockId bincodeDeserialize(std::vector); -}; - -struct Expression { - std::vector> - mul_terms; - std::vector> linear_combinations; - std::string q_c; - - friend bool operator==(const Expression &, const Expression &); - std::vector bincodeSerialize() const; - static Expression bincodeDeserialize(std::vector); -}; - -struct BrilligInputs { - - struct Single { - Program::Expression value; - - friend bool operator==(const Single &, const Single &); - std::vector bincodeSerialize() const; - static Single bincodeDeserialize(std::vector); - }; - - struct Array { - std::vector value; - - friend bool operator==(const Array &, const Array &); - std::vector bincodeSerialize() const; - static Array bincodeDeserialize(std::vector); - }; - - struct MemoryArray { - Program::BlockId value; - - friend bool operator==(const MemoryArray &, const MemoryArray &); - std::vector bincodeSerialize() const; - static MemoryArray bincodeDeserialize(std::vector); - }; - - std::variant value; - - friend bool operator==(const BrilligInputs &, const BrilligInputs &); - std::vector bincodeSerialize() const; - static BrilligInputs bincodeDeserialize(std::vector); -}; - -struct BrilligOutputs { - - struct Simple { - Program::Witness value; - - friend bool operator==(const Simple &, const Simple &); - std::vector bincodeSerialize() const; - static Simple bincodeDeserialize(std::vector); - }; - - struct Array { - std::vector value; - - friend bool operator==(const Array &, const Array &); - std::vector bincodeSerialize() const; - static Array bincodeDeserialize(std::vector); - }; - - std::variant value; - - friend bool operator==(const BrilligOutputs &, const BrilligOutputs &); - std::vector bincodeSerialize() const; - static BrilligOutputs bincodeDeserialize(std::vector); -}; - -struct Brillig { - std::vector inputs; - std::vector outputs; - std::vector bytecode; - std::optional predicate; - - friend bool operator==(const Brillig &, const Brillig &); - std::vector bincodeSerialize() const; - static Brillig bincodeDeserialize(std::vector); -}; - -struct Directive { - - struct ToLeRadix { - Program::Expression a; - std::vector b; - uint32_t radix; - - friend bool operator==(const ToLeRadix &, const ToLeRadix &); - std::vector bincodeSerialize() const; - static ToLeRadix bincodeDeserialize(std::vector); - }; + struct BinaryFieldOp { + + struct Add { + friend bool operator==(const Add&, const Add&); + std::vector bincodeSerialize() const; + static Add bincodeDeserialize(std::vector); + }; + + struct Sub { + friend bool operator==(const Sub&, const Sub&); + std::vector bincodeSerialize() const; + static Sub bincodeDeserialize(std::vector); + }; + + struct Mul { + friend bool operator==(const Mul&, const Mul&); + std::vector bincodeSerialize() const; + static Mul bincodeDeserialize(std::vector); + }; + + struct Div { + friend bool operator==(const Div&, const Div&); + std::vector bincodeSerialize() const; + static Div bincodeDeserialize(std::vector); + }; + + struct IntegerDiv { + friend bool operator==(const IntegerDiv&, const IntegerDiv&); + std::vector bincodeSerialize() const; + static IntegerDiv bincodeDeserialize(std::vector); + }; + + struct Equals { + friend bool operator==(const Equals&, const Equals&); + std::vector bincodeSerialize() const; + static Equals bincodeDeserialize(std::vector); + }; + + struct LessThan { + friend bool operator==(const LessThan&, const LessThan&); + std::vector bincodeSerialize() const; + static LessThan bincodeDeserialize(std::vector); + }; + + struct LessThanEquals { + friend bool operator==(const LessThanEquals&, const LessThanEquals&); + std::vector bincodeSerialize() const; + static LessThanEquals bincodeDeserialize(std::vector); + }; + + std::variant value; + + friend bool operator==(const BinaryFieldOp&, const BinaryFieldOp&); + std::vector bincodeSerialize() const; + static BinaryFieldOp bincodeDeserialize(std::vector); + }; + + struct BinaryIntOp { + + struct Add { + friend bool operator==(const Add&, const Add&); + std::vector bincodeSerialize() const; + static Add bincodeDeserialize(std::vector); + }; + + struct Sub { + friend bool operator==(const Sub&, const Sub&); + std::vector bincodeSerialize() const; + static Sub bincodeDeserialize(std::vector); + }; + + struct Mul { + friend bool operator==(const Mul&, const Mul&); + std::vector bincodeSerialize() const; + static Mul bincodeDeserialize(std::vector); + }; + + struct Div { + friend bool operator==(const Div&, const Div&); + std::vector bincodeSerialize() const; + static Div bincodeDeserialize(std::vector); + }; + + struct Equals { + friend bool operator==(const Equals&, const Equals&); + std::vector bincodeSerialize() const; + static Equals bincodeDeserialize(std::vector); + }; + + struct LessThan { + friend bool operator==(const LessThan&, const LessThan&); + std::vector bincodeSerialize() const; + static LessThan bincodeDeserialize(std::vector); + }; + + struct LessThanEquals { + friend bool operator==(const LessThanEquals&, const LessThanEquals&); + std::vector bincodeSerialize() const; + static LessThanEquals bincodeDeserialize(std::vector); + }; + + struct And { + friend bool operator==(const And&, const And&); + std::vector bincodeSerialize() const; + static And bincodeDeserialize(std::vector); + }; + + struct Or { + friend bool operator==(const Or&, const Or&); + std::vector bincodeSerialize() const; + static Or bincodeDeserialize(std::vector); + }; + + struct Xor { + friend bool operator==(const Xor&, const Xor&); + std::vector bincodeSerialize() const; + static Xor bincodeDeserialize(std::vector); + }; + + struct Shl { + friend bool operator==(const Shl&, const Shl&); + std::vector bincodeSerialize() const; + static Shl bincodeDeserialize(std::vector); + }; + + struct Shr { + friend bool operator==(const Shr&, const Shr&); + std::vector bincodeSerialize() const; + static Shr bincodeDeserialize(std::vector); + }; + + std::variant value; + + friend bool operator==(const BinaryIntOp&, const BinaryIntOp&); + std::vector bincodeSerialize() const; + static BinaryIntOp bincodeDeserialize(std::vector); + }; + + struct MemoryAddress { + uint64_t value; + + friend bool operator==(const MemoryAddress&, const MemoryAddress&); + std::vector bincodeSerialize() const; + static MemoryAddress bincodeDeserialize(std::vector); + }; + + struct HeapArray { + Program::MemoryAddress pointer; + uint64_t size; + + friend bool operator==(const HeapArray&, const HeapArray&); + std::vector bincodeSerialize() const; + static HeapArray bincodeDeserialize(std::vector); + }; + + struct HeapVector { + Program::MemoryAddress pointer; + Program::MemoryAddress size; + + friend bool operator==(const HeapVector&, const HeapVector&); + std::vector bincodeSerialize() const; + static HeapVector bincodeDeserialize(std::vector); + }; + + struct BlackBoxOp { + + struct Sha256 { + Program::HeapVector message; + Program::HeapArray output; + + friend bool operator==(const Sha256&, const Sha256&); + std::vector bincodeSerialize() const; + static Sha256 bincodeDeserialize(std::vector); + }; + + struct Blake2s { + Program::HeapVector message; + Program::HeapArray output; + + friend bool operator==(const Blake2s&, const Blake2s&); + std::vector bincodeSerialize() const; + static Blake2s bincodeDeserialize(std::vector); + }; + + struct Blake3 { + Program::HeapVector message; + Program::HeapArray output; + + friend bool operator==(const Blake3&, const Blake3&); + std::vector bincodeSerialize() const; + static Blake3 bincodeDeserialize(std::vector); + }; + + struct Keccak256 { + Program::HeapVector message; + Program::HeapArray output; + + friend bool operator==(const Keccak256&, const Keccak256&); + std::vector bincodeSerialize() const; + static Keccak256 bincodeDeserialize(std::vector); + }; + + struct Keccakf1600 { + Program::HeapVector message; + Program::HeapArray output; + + friend bool operator==(const Keccakf1600&, const Keccakf1600&); + std::vector bincodeSerialize() const; + static Keccakf1600 bincodeDeserialize(std::vector); + }; + + struct EcdsaSecp256k1 { + Program::HeapVector hashed_msg; + Program::HeapArray public_key_x; + Program::HeapArray public_key_y; + Program::HeapArray signature; + Program::MemoryAddress result; + + friend bool operator==(const EcdsaSecp256k1&, const EcdsaSecp256k1&); + std::vector bincodeSerialize() const; + static EcdsaSecp256k1 bincodeDeserialize(std::vector); + }; + + struct EcdsaSecp256r1 { + Program::HeapVector hashed_msg; + Program::HeapArray public_key_x; + Program::HeapArray public_key_y; + Program::HeapArray signature; + Program::MemoryAddress result; + + friend bool operator==(const EcdsaSecp256r1&, const EcdsaSecp256r1&); + std::vector bincodeSerialize() const; + static EcdsaSecp256r1 bincodeDeserialize(std::vector); + }; + + struct SchnorrVerify { + Program::MemoryAddress public_key_x; + Program::MemoryAddress public_key_y; + Program::HeapVector message; + Program::HeapVector signature; + Program::MemoryAddress result; + + friend bool operator==(const SchnorrVerify&, const SchnorrVerify&); + std::vector bincodeSerialize() const; + static SchnorrVerify bincodeDeserialize(std::vector); + }; + + struct PedersenCommitment { + Program::HeapVector inputs; + Program::MemoryAddress domain_separator; + Program::HeapArray output; + + friend bool operator==(const PedersenCommitment&, const PedersenCommitment&); + std::vector bincodeSerialize() const; + static PedersenCommitment bincodeDeserialize(std::vector); + }; + + struct PedersenHash { + Program::HeapVector inputs; + Program::MemoryAddress domain_separator; + Program::MemoryAddress output; + + friend bool operator==(const PedersenHash&, const PedersenHash&); + std::vector bincodeSerialize() const; + static PedersenHash bincodeDeserialize(std::vector); + }; + + struct FixedBaseScalarMul { + Program::MemoryAddress low; + Program::MemoryAddress high; + Program::HeapArray result; + + friend bool operator==(const FixedBaseScalarMul&, const FixedBaseScalarMul&); + std::vector bincodeSerialize() const; + static FixedBaseScalarMul bincodeDeserialize(std::vector); + }; + + struct EmbeddedCurveAdd { + Program::MemoryAddress input1_x; + Program::MemoryAddress input1_y; + Program::MemoryAddress input2_x; + Program::MemoryAddress input2_y; + Program::HeapArray result; + + friend bool operator==(const EmbeddedCurveAdd&, const EmbeddedCurveAdd&); + std::vector bincodeSerialize() const; + static EmbeddedCurveAdd bincodeDeserialize(std::vector); + }; + + struct BigIntAdd { + Program::MemoryAddress lhs; + Program::MemoryAddress rhs; + Program::MemoryAddress output; + + friend bool operator==(const BigIntAdd&, const BigIntAdd&); + std::vector bincodeSerialize() const; + static BigIntAdd bincodeDeserialize(std::vector); + }; + + struct BigIntSub { + Program::MemoryAddress lhs; + Program::MemoryAddress rhs; + Program::MemoryAddress output; + + friend bool operator==(const BigIntSub&, const BigIntSub&); + std::vector bincodeSerialize() const; + static BigIntSub bincodeDeserialize(std::vector); + }; + + struct BigIntMul { + Program::MemoryAddress lhs; + Program::MemoryAddress rhs; + Program::MemoryAddress output; + + friend bool operator==(const BigIntMul&, const BigIntMul&); + std::vector bincodeSerialize() const; + static BigIntMul bincodeDeserialize(std::vector); + }; + + struct BigIntDiv { + Program::MemoryAddress lhs; + Program::MemoryAddress rhs; + Program::MemoryAddress output; + + friend bool operator==(const BigIntDiv&, const BigIntDiv&); + std::vector bincodeSerialize() const; + static BigIntDiv bincodeDeserialize(std::vector); + }; + + struct BigIntFromLeBytes { + Program::HeapVector inputs; + Program::HeapVector modulus; + Program::MemoryAddress output; + + friend bool operator==(const BigIntFromLeBytes&, const BigIntFromLeBytes&); + std::vector bincodeSerialize() const; + static BigIntFromLeBytes bincodeDeserialize(std::vector); + }; + + struct BigIntToLeBytes { + Program::MemoryAddress input; + Program::HeapVector output; + + friend bool operator==(const BigIntToLeBytes&, const BigIntToLeBytes&); + std::vector bincodeSerialize() const; + static BigIntToLeBytes bincodeDeserialize(std::vector); + }; + + struct Poseidon2Permutation { + Program::HeapVector message; + Program::HeapArray output; + Program::MemoryAddress len; + + friend bool operator==(const Poseidon2Permutation&, const Poseidon2Permutation&); + std::vector bincodeSerialize() const; + static Poseidon2Permutation bincodeDeserialize(std::vector); + }; + + struct Sha256Compression { + Program::HeapVector input; + Program::HeapVector hash_values; + Program::HeapArray output; + + friend bool operator==(const Sha256Compression&, const Sha256Compression&); + std::vector bincodeSerialize() const; + static Sha256Compression bincodeDeserialize(std::vector); + }; + + std::variant value; + + friend bool operator==(const BlackBoxOp&, const BlackBoxOp&); + std::vector bincodeSerialize() const; + static BlackBoxOp bincodeDeserialize(std::vector); + }; + + struct HeapValueType; + + struct HeapValueType { + + struct Simple { + friend bool operator==(const Simple&, const Simple&); + std::vector bincodeSerialize() const; + static Simple bincodeDeserialize(std::vector); + }; + + struct Array { + std::vector value_types; + uint64_t size; + + friend bool operator==(const Array&, const Array&); + std::vector bincodeSerialize() const; + static Array bincodeDeserialize(std::vector); + }; + + struct Vector { + std::vector value_types; + + friend bool operator==(const Vector&, const Vector&); + std::vector bincodeSerialize() const; + static Vector bincodeDeserialize(std::vector); + }; + + std::variant value; + + friend bool operator==(const HeapValueType&, const HeapValueType&); + std::vector bincodeSerialize() const; + static HeapValueType bincodeDeserialize(std::vector); + }; + + struct Value { + std::string inner; + + friend bool operator==(const Value&, const Value&); + std::vector bincodeSerialize() const; + static Value bincodeDeserialize(std::vector); + }; + + struct ValueOrArray { + + struct MemoryAddress { + Program::MemoryAddress value; + + friend bool operator==(const MemoryAddress&, const MemoryAddress&); + std::vector bincodeSerialize() const; + static MemoryAddress bincodeDeserialize(std::vector); + }; + + struct HeapArray { + Program::HeapArray value; + + friend bool operator==(const HeapArray&, const HeapArray&); + std::vector bincodeSerialize() const; + static HeapArray bincodeDeserialize(std::vector); + }; + + struct HeapVector { + Program::HeapVector value; + + friend bool operator==(const HeapVector&, const HeapVector&); + std::vector bincodeSerialize() const; + static HeapVector bincodeDeserialize(std::vector); + }; + + std::variant value; + + friend bool operator==(const ValueOrArray&, const ValueOrArray&); + std::vector bincodeSerialize() const; + static ValueOrArray bincodeDeserialize(std::vector); + }; + + struct BrilligOpcode { + + struct BinaryFieldOp { + Program::MemoryAddress destination; + Program::BinaryFieldOp op; + Program::MemoryAddress lhs; + Program::MemoryAddress rhs; + + friend bool operator==(const BinaryFieldOp&, const BinaryFieldOp&); + std::vector bincodeSerialize() const; + static BinaryFieldOp bincodeDeserialize(std::vector); + }; + + struct BinaryIntOp { + Program::MemoryAddress destination; + Program::BinaryIntOp op; + uint32_t bit_size; + Program::MemoryAddress lhs; + Program::MemoryAddress rhs; + + friend bool operator==(const BinaryIntOp&, const BinaryIntOp&); + std::vector bincodeSerialize() const; + static BinaryIntOp bincodeDeserialize(std::vector); + }; + + struct Cast { + Program::MemoryAddress destination; + Program::MemoryAddress source; + uint32_t bit_size; + + friend bool operator==(const Cast&, const Cast&); + std::vector bincodeSerialize() const; + static Cast bincodeDeserialize(std::vector); + }; + + struct JumpIfNot { + Program::MemoryAddress condition; + uint64_t location; + + friend bool operator==(const JumpIfNot&, const JumpIfNot&); + std::vector bincodeSerialize() const; + static JumpIfNot bincodeDeserialize(std::vector); + }; + + struct JumpIf { + Program::MemoryAddress condition; + uint64_t location; + + friend bool operator==(const JumpIf&, const JumpIf&); + std::vector bincodeSerialize() const; + static JumpIf bincodeDeserialize(std::vector); + }; + + struct Jump { + uint64_t location; + + friend bool operator==(const Jump&, const Jump&); + std::vector bincodeSerialize() const; + static Jump bincodeDeserialize(std::vector); + }; + + struct CalldataCopy { + Program::MemoryAddress destination_address; + uint64_t size; + uint64_t offset; + + friend bool operator==(const CalldataCopy&, const CalldataCopy&); + std::vector bincodeSerialize() const; + static CalldataCopy bincodeDeserialize(std::vector); + }; + + struct Call { + uint64_t location; + + friend bool operator==(const Call&, const Call&); + std::vector bincodeSerialize() const; + static Call bincodeDeserialize(std::vector); + }; + + struct Const { + Program::MemoryAddress destination; + uint32_t bit_size; + Program::Value value; + + friend bool operator==(const Const&, const Const&); + std::vector bincodeSerialize() const; + static Const bincodeDeserialize(std::vector); + }; + + struct Return { + friend bool operator==(const Return&, const Return&); + std::vector bincodeSerialize() const; + static Return bincodeDeserialize(std::vector); + }; + + struct ForeignCall { + std::string function; + std::vector destinations; + std::vector destination_value_types; + std::vector inputs; + std::vector input_value_types; + + friend bool operator==(const ForeignCall&, const ForeignCall&); + std::vector bincodeSerialize() const; + static ForeignCall bincodeDeserialize(std::vector); + }; + + struct Mov { + Program::MemoryAddress destination; + Program::MemoryAddress source; + + friend bool operator==(const Mov&, const Mov&); + std::vector bincodeSerialize() const; + static Mov bincodeDeserialize(std::vector); + }; + + struct Load { + Program::MemoryAddress destination; + Program::MemoryAddress source_pointer; + + friend bool operator==(const Load&, const Load&); + std::vector bincodeSerialize() const; + static Load bincodeDeserialize(std::vector); + }; + + struct Store { + Program::MemoryAddress destination_pointer; + Program::MemoryAddress source; + + friend bool operator==(const Store&, const Store&); + std::vector bincodeSerialize() const; + static Store bincodeDeserialize(std::vector); + }; + + struct BlackBox { + Program::BlackBoxOp value; + + friend bool operator==(const BlackBox&, const BlackBox&); + std::vector bincodeSerialize() const; + static BlackBox bincodeDeserialize(std::vector); + }; + + struct Trap { + friend bool operator==(const Trap&, const Trap&); + std::vector bincodeSerialize() const; + static Trap bincodeDeserialize(std::vector); + }; + + struct Stop { + uint64_t return_data_offset; + uint64_t return_data_size; + + friend bool operator==(const Stop&, const Stop&); + std::vector bincodeSerialize() const; + static Stop bincodeDeserialize(std::vector); + }; + + std::variant value; + + friend bool operator==(const BrilligOpcode&, const BrilligOpcode&); + std::vector bincodeSerialize() const; + static BrilligOpcode bincodeDeserialize(std::vector); + }; + + struct Witness { + uint32_t value; + + friend bool operator==(const Witness&, const Witness&); + std::vector bincodeSerialize() const; + static Witness bincodeDeserialize(std::vector); + }; + + struct FunctionInput { + Program::Witness witness; + uint32_t num_bits; + + friend bool operator==(const FunctionInput&, const FunctionInput&); + std::vector bincodeSerialize() const; + static FunctionInput bincodeDeserialize(std::vector); + }; + + struct BlackBoxFuncCall { + + struct AND { + Program::FunctionInput lhs; + Program::FunctionInput rhs; + Program::Witness output; + + friend bool operator==(const AND&, const AND&); + std::vector bincodeSerialize() const; + static AND bincodeDeserialize(std::vector); + }; + + struct XOR { + Program::FunctionInput lhs; + Program::FunctionInput rhs; + Program::Witness output; + + friend bool operator==(const XOR&, const XOR&); + std::vector bincodeSerialize() const; + static XOR bincodeDeserialize(std::vector); + }; + + struct RANGE { + Program::FunctionInput input; + + friend bool operator==(const RANGE&, const RANGE&); + std::vector bincodeSerialize() const; + static RANGE bincodeDeserialize(std::vector); + }; + + struct SHA256 { + std::vector inputs; + std::vector outputs; + + friend bool operator==(const SHA256&, const SHA256&); + std::vector bincodeSerialize() const; + static SHA256 bincodeDeserialize(std::vector); + }; + + struct Blake2s { + std::vector inputs; + std::vector outputs; + + friend bool operator==(const Blake2s&, const Blake2s&); + std::vector bincodeSerialize() const; + static Blake2s bincodeDeserialize(std::vector); + }; + + struct Blake3 { + std::vector inputs; + std::vector outputs; + + friend bool operator==(const Blake3&, const Blake3&); + std::vector bincodeSerialize() const; + static Blake3 bincodeDeserialize(std::vector); + }; + + struct SchnorrVerify { + Program::FunctionInput public_key_x; + Program::FunctionInput public_key_y; + std::vector signature; + std::vector message; + Program::Witness output; + + friend bool operator==(const SchnorrVerify&, const SchnorrVerify&); + std::vector bincodeSerialize() const; + static SchnorrVerify bincodeDeserialize(std::vector); + }; + + struct PedersenCommitment { + std::vector inputs; + uint32_t domain_separator; + std::array outputs; + + friend bool operator==(const PedersenCommitment&, const PedersenCommitment&); + std::vector bincodeSerialize() const; + static PedersenCommitment bincodeDeserialize(std::vector); + }; + + struct PedersenHash { + std::vector inputs; + uint32_t domain_separator; + Program::Witness output; + + friend bool operator==(const PedersenHash&, const PedersenHash&); + std::vector bincodeSerialize() const; + static PedersenHash bincodeDeserialize(std::vector); + }; + + struct EcdsaSecp256k1 { + std::vector public_key_x; + std::vector public_key_y; + std::vector signature; + std::vector hashed_message; + Program::Witness output; + + friend bool operator==(const EcdsaSecp256k1&, const EcdsaSecp256k1&); + std::vector bincodeSerialize() const; + static EcdsaSecp256k1 bincodeDeserialize(std::vector); + }; + + struct EcdsaSecp256r1 { + std::vector public_key_x; + std::vector public_key_y; + std::vector signature; + std::vector hashed_message; + Program::Witness output; + + friend bool operator==(const EcdsaSecp256r1&, const EcdsaSecp256r1&); + std::vector bincodeSerialize() const; + static EcdsaSecp256r1 bincodeDeserialize(std::vector); + }; + + struct FixedBaseScalarMul { + Program::FunctionInput low; + Program::FunctionInput high; + std::array outputs; + + friend bool operator==(const FixedBaseScalarMul&, const FixedBaseScalarMul&); + std::vector bincodeSerialize() const; + static FixedBaseScalarMul bincodeDeserialize(std::vector); + }; + + struct EmbeddedCurveAdd { + Program::FunctionInput input1_x; + Program::FunctionInput input1_y; + Program::FunctionInput input2_x; + Program::FunctionInput input2_y; + std::array outputs; + + friend bool operator==(const EmbeddedCurveAdd&, const EmbeddedCurveAdd&); + std::vector bincodeSerialize() const; + static EmbeddedCurveAdd bincodeDeserialize(std::vector); + }; + + struct Keccak256 { + std::vector inputs; + std::vector outputs; + + friend bool operator==(const Keccak256&, const Keccak256&); + std::vector bincodeSerialize() const; + static Keccak256 bincodeDeserialize(std::vector); + }; + + struct Keccak256VariableLength { + std::vector inputs; + Program::FunctionInput var_message_size; + std::vector outputs; + + friend bool operator==(const Keccak256VariableLength&, const Keccak256VariableLength&); + std::vector bincodeSerialize() const; + static Keccak256VariableLength bincodeDeserialize(std::vector); + }; + + struct Keccakf1600 { + std::vector inputs; + std::vector outputs; + + friend bool operator==(const Keccakf1600&, const Keccakf1600&); + std::vector bincodeSerialize() const; + static Keccakf1600 bincodeDeserialize(std::vector); + }; + + struct RecursiveAggregation { + std::vector verification_key; + std::vector proof; + std::vector public_inputs; + Program::FunctionInput key_hash; + + friend bool operator==(const RecursiveAggregation&, const RecursiveAggregation&); + std::vector bincodeSerialize() const; + static RecursiveAggregation bincodeDeserialize(std::vector); + }; + + struct BigIntAdd { + uint32_t lhs; + uint32_t rhs; + uint32_t output; + + friend bool operator==(const BigIntAdd&, const BigIntAdd&); + std::vector bincodeSerialize() const; + static BigIntAdd bincodeDeserialize(std::vector); + }; + + struct BigIntSub { + uint32_t lhs; + uint32_t rhs; + uint32_t output; + + friend bool operator==(const BigIntSub&, const BigIntSub&); + std::vector bincodeSerialize() const; + static BigIntSub bincodeDeserialize(std::vector); + }; + + struct BigIntMul { + uint32_t lhs; + uint32_t rhs; + uint32_t output; + + friend bool operator==(const BigIntMul&, const BigIntMul&); + std::vector bincodeSerialize() const; + static BigIntMul bincodeDeserialize(std::vector); + }; + + struct BigIntDiv { + uint32_t lhs; + uint32_t rhs; + uint32_t output; + + friend bool operator==(const BigIntDiv&, const BigIntDiv&); + std::vector bincodeSerialize() const; + static BigIntDiv bincodeDeserialize(std::vector); + }; + + struct BigIntFromLeBytes { + std::vector inputs; + std::vector modulus; + uint32_t output; + + friend bool operator==(const BigIntFromLeBytes&, const BigIntFromLeBytes&); + std::vector bincodeSerialize() const; + static BigIntFromLeBytes bincodeDeserialize(std::vector); + }; + + struct BigIntToLeBytes { + uint32_t input; + std::vector outputs; + + friend bool operator==(const BigIntToLeBytes&, const BigIntToLeBytes&); + std::vector bincodeSerialize() const; + static BigIntToLeBytes bincodeDeserialize(std::vector); + }; + + struct Poseidon2Permutation { + std::vector inputs; + std::vector outputs; + uint32_t len; + + friend bool operator==(const Poseidon2Permutation&, const Poseidon2Permutation&); + std::vector bincodeSerialize() const; + static Poseidon2Permutation bincodeDeserialize(std::vector); + }; + + struct Sha256Compression { + std::vector inputs; + std::vector hash_values; + std::vector outputs; + + friend bool operator==(const Sha256Compression&, const Sha256Compression&); + std::vector bincodeSerialize() const; + static Sha256Compression bincodeDeserialize(std::vector); + }; + + std::variant value; + + friend bool operator==(const BlackBoxFuncCall&, const BlackBoxFuncCall&); + std::vector bincodeSerialize() const; + static BlackBoxFuncCall bincodeDeserialize(std::vector); + }; + + struct BlockId { + uint32_t value; + + friend bool operator==(const BlockId&, const BlockId&); + std::vector bincodeSerialize() const; + static BlockId bincodeDeserialize(std::vector); + }; + + struct Expression { + std::vector> mul_terms; + std::vector> linear_combinations; + std::string q_c; + + friend bool operator==(const Expression&, const Expression&); + std::vector bincodeSerialize() const; + static Expression bincodeDeserialize(std::vector); + }; + + struct BrilligInputs { + + struct Single { + Program::Expression value; + + friend bool operator==(const Single&, const Single&); + std::vector bincodeSerialize() const; + static Single bincodeDeserialize(std::vector); + }; + + struct Array { + std::vector value; + + friend bool operator==(const Array&, const Array&); + std::vector bincodeSerialize() const; + static Array bincodeDeserialize(std::vector); + }; + + struct MemoryArray { + Program::BlockId value; + + friend bool operator==(const MemoryArray&, const MemoryArray&); + std::vector bincodeSerialize() const; + static MemoryArray bincodeDeserialize(std::vector); + }; + + std::variant value; + + friend bool operator==(const BrilligInputs&, const BrilligInputs&); + std::vector bincodeSerialize() const; + static BrilligInputs bincodeDeserialize(std::vector); + }; + + struct BrilligOutputs { + + struct Simple { + Program::Witness value; + + friend bool operator==(const Simple&, const Simple&); + std::vector bincodeSerialize() const; + static Simple bincodeDeserialize(std::vector); + }; + + struct Array { + std::vector value; + + friend bool operator==(const Array&, const Array&); + std::vector bincodeSerialize() const; + static Array bincodeDeserialize(std::vector); + }; + + std::variant value; + + friend bool operator==(const BrilligOutputs&, const BrilligOutputs&); + std::vector bincodeSerialize() const; + static BrilligOutputs bincodeDeserialize(std::vector); + }; + + struct Brillig { + std::vector inputs; + std::vector outputs; + std::vector bytecode; + std::optional predicate; + + friend bool operator==(const Brillig&, const Brillig&); + std::vector bincodeSerialize() const; + static Brillig bincodeDeserialize(std::vector); + }; + + struct Directive { + + struct ToLeRadix { + Program::Expression a; + std::vector b; + uint32_t radix; + + friend bool operator==(const ToLeRadix&, const ToLeRadix&); + std::vector bincodeSerialize() const; + static ToLeRadix bincodeDeserialize(std::vector); + }; + + std::variant value; + + friend bool operator==(const Directive&, const Directive&); + std::vector bincodeSerialize() const; + static Directive bincodeDeserialize(std::vector); + }; - std::variant value; - - friend bool operator==(const Directive &, const Directive &); - std::vector bincodeSerialize() const; - static Directive bincodeDeserialize(std::vector); -}; + struct MemOp { + Program::Expression operation; + Program::Expression index; + Program::Expression value; -struct MemOp { - Program::Expression operation; - Program::Expression index; - Program::Expression value; + friend bool operator==(const MemOp&, const MemOp&); + std::vector bincodeSerialize() const; + static MemOp bincodeDeserialize(std::vector); + }; - friend bool operator==(const MemOp &, const MemOp &); - std::vector bincodeSerialize() const; - static MemOp bincodeDeserialize(std::vector); -}; + struct Opcode { -struct Opcode { + struct AssertZero { + Program::Expression value; - struct AssertZero { - Program::Expression value; + friend bool operator==(const AssertZero&, const AssertZero&); + std::vector bincodeSerialize() const; + static AssertZero bincodeDeserialize(std::vector); + }; - friend bool operator==(const AssertZero &, const AssertZero &); - std::vector bincodeSerialize() const; - static AssertZero bincodeDeserialize(std::vector); - }; + struct BlackBoxFuncCall { + Program::BlackBoxFuncCall value; - struct BlackBoxFuncCall { - Program::BlackBoxFuncCall value; - - friend bool operator==(const BlackBoxFuncCall &, const BlackBoxFuncCall &); - std::vector bincodeSerialize() const; - static BlackBoxFuncCall bincodeDeserialize(std::vector); - }; + friend bool operator==(const BlackBoxFuncCall&, const BlackBoxFuncCall&); + std::vector bincodeSerialize() const; + static BlackBoxFuncCall bincodeDeserialize(std::vector); + }; - struct Directive { - Program::Directive value; + struct Directive { + Program::Directive value; - friend bool operator==(const Directive &, const Directive &); - std::vector bincodeSerialize() const; - static Directive bincodeDeserialize(std::vector); - }; + friend bool operator==(const Directive&, const Directive&); + std::vector bincodeSerialize() const; + static Directive bincodeDeserialize(std::vector); + }; - struct Brillig { - Program::Brillig value; + struct Brillig { + Program::Brillig value; - friend bool operator==(const Brillig &, const Brillig &); - std::vector bincodeSerialize() const; - static Brillig bincodeDeserialize(std::vector); - }; - - struct MemoryOp { - Program::BlockId block_id; - Program::MemOp op; - std::optional predicate; - - friend bool operator==(const MemoryOp &, const MemoryOp &); - std::vector bincodeSerialize() const; - static MemoryOp bincodeDeserialize(std::vector); - }; - - struct MemoryInit { - Program::BlockId block_id; - std::vector init; - - friend bool operator==(const MemoryInit &, const MemoryInit &); - std::vector bincodeSerialize() const; - static MemoryInit bincodeDeserialize(std::vector); - }; - - struct Call { - uint32_t id; - std::vector inputs; - std::vector outputs; + friend bool operator==(const Brillig&, const Brillig&); + std::vector bincodeSerialize() const; + static Brillig bincodeDeserialize(std::vector); + }; + + struct MemoryOp { + Program::BlockId block_id; + Program::MemOp op; + std::optional predicate; + + friend bool operator==(const MemoryOp&, const MemoryOp&); + std::vector bincodeSerialize() const; + static MemoryOp bincodeDeserialize(std::vector); + }; + + struct MemoryInit { + Program::BlockId block_id; + std::vector init; + + friend bool operator==(const MemoryInit&, const MemoryInit&); + std::vector bincodeSerialize() const; + static MemoryInit bincodeDeserialize(std::vector); + }; - friend bool operator==(const Call &, const Call &); - std::vector bincodeSerialize() const; - static Call bincodeDeserialize(std::vector); - }; + struct Call { + uint32_t id; + std::vector inputs; + std::vector outputs; - std::variant - value; + friend bool operator==(const Call&, const Call&); + std::vector bincodeSerialize() const; + static Call bincodeDeserialize(std::vector); + }; - friend bool operator==(const Opcode &, const Opcode &); - std::vector bincodeSerialize() const; - static Opcode bincodeDeserialize(std::vector); -}; + std::variant value; -struct ExpressionWidth { + friend bool operator==(const Opcode&, const Opcode&); + std::vector bincodeSerialize() const; + static Opcode bincodeDeserialize(std::vector); + }; - struct Unbounded { - friend bool operator==(const Unbounded &, const Unbounded &); - std::vector bincodeSerialize() const; - static Unbounded bincodeDeserialize(std::vector); - }; + struct ExpressionWidth { - struct Bounded { - uint64_t width; + struct Unbounded { + friend bool operator==(const Unbounded&, const Unbounded&); + std::vector bincodeSerialize() const; + static Unbounded bincodeDeserialize(std::vector); + }; - friend bool operator==(const Bounded &, const Bounded &); - std::vector bincodeSerialize() const; - static Bounded bincodeDeserialize(std::vector); - }; + struct Bounded { + uint64_t width; - std::variant value; + friend bool operator==(const Bounded&, const Bounded&); + std::vector bincodeSerialize() const; + static Bounded bincodeDeserialize(std::vector); + }; - friend bool operator==(const ExpressionWidth &, const ExpressionWidth &); - std::vector bincodeSerialize() const; - static ExpressionWidth bincodeDeserialize(std::vector); -}; + std::variant value; -struct OpcodeLocation { + friend bool operator==(const ExpressionWidth&, const ExpressionWidth&); + std::vector bincodeSerialize() const; + static ExpressionWidth bincodeDeserialize(std::vector); + }; - struct Acir { - uint64_t value; + struct OpcodeLocation { - friend bool operator==(const Acir &, const Acir &); - std::vector bincodeSerialize() const; - static Acir bincodeDeserialize(std::vector); - }; + struct Acir { + uint64_t value; - struct Brillig { - uint64_t acir_index; - uint64_t brillig_index; + friend bool operator==(const Acir&, const Acir&); + std::vector bincodeSerialize() const; + static Acir bincodeDeserialize(std::vector); + }; - friend bool operator==(const Brillig &, const Brillig &); - std::vector bincodeSerialize() const; - static Brillig bincodeDeserialize(std::vector); - }; + struct Brillig { + uint64_t acir_index; + uint64_t brillig_index; - std::variant value; + friend bool operator==(const Brillig&, const Brillig&); + std::vector bincodeSerialize() const; + static Brillig bincodeDeserialize(std::vector); + }; - friend bool operator==(const OpcodeLocation &, const OpcodeLocation &); - std::vector bincodeSerialize() const; - static OpcodeLocation bincodeDeserialize(std::vector); -}; + std::variant value; -struct PublicInputs { - std::vector value; + friend bool operator==(const OpcodeLocation&, const OpcodeLocation&); + std::vector bincodeSerialize() const; + static OpcodeLocation bincodeDeserialize(std::vector); + }; - friend bool operator==(const PublicInputs &, const PublicInputs &); - std::vector bincodeSerialize() const; - static PublicInputs bincodeDeserialize(std::vector); -}; + struct PublicInputs { + std::vector value; -struct Circuit { - uint32_t current_witness_index; - std::vector opcodes; - Program::ExpressionWidth expression_width; - std::vector private_parameters; - Program::PublicInputs public_parameters; - Program::PublicInputs return_values; - std::vector> assert_messages; - bool recursive; + friend bool operator==(const PublicInputs&, const PublicInputs&); + std::vector bincodeSerialize() const; + static PublicInputs bincodeDeserialize(std::vector); + }; - friend bool operator==(const Circuit &, const Circuit &); - std::vector bincodeSerialize() const; - static Circuit bincodeDeserialize(std::vector); -}; + struct Circuit { + uint32_t current_witness_index; + std::vector opcodes; + Program::ExpressionWidth expression_width; + std::vector private_parameters; + Program::PublicInputs public_parameters; + Program::PublicInputs return_values; + std::vector> assert_messages; + bool recursive; -struct Program { - std::vector functions; + friend bool operator==(const Circuit&, const Circuit&); + std::vector bincodeSerialize() const; + static Circuit bincodeDeserialize(std::vector); + }; - friend bool operator==(const Program &, const Program &); - std::vector bincodeSerialize() const; - static Program bincodeDeserialize(std::vector); -}; + struct Program { + std::vector functions; + + friend bool operator==(const Program&, const Program&); + std::vector bincodeSerialize() const; + static Program bincodeDeserialize(std::vector); + }; } // end of namespace Program + namespace Program { -inline bool operator==(const BinaryFieldOp &lhs, const BinaryFieldOp &rhs) { - if (!(lhs.value == rhs.value)) { - return false; - } - return true; -} + inline bool operator==(const BinaryFieldOp &lhs, const BinaryFieldOp &rhs) { + if (!(lhs.value == rhs.value)) { return false; } + return true; + } -inline std::vector BinaryFieldOp::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BinaryFieldOp::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BinaryFieldOp -BinaryFieldOp::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; -} + inline BinaryFieldOp BinaryFieldOp::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BinaryFieldOp &obj, Serializer &serializer) { - serializer.increase_container_depth(); - serde::Serializable::serialize(obj.value, serializer); - serializer.decrease_container_depth(); +void serde::Serializable::serialize(const Program::BinaryFieldOp &obj, Serializer &serializer) { + serializer.increase_container_depth(); + serde::Serializable::serialize(obj.value, serializer); + serializer.decrease_container_depth(); } template <> template -Program::BinaryFieldOp -serde::Deserializable::deserialize( - Deserializer &deserializer) { - deserializer.increase_container_depth(); - Program::BinaryFieldOp obj; - obj.value = - serde::Deserializable::deserialize(deserializer); - deserializer.decrease_container_depth(); - return obj; +Program::BinaryFieldOp serde::Deserializable::deserialize(Deserializer &deserializer) { + deserializer.increase_container_depth(); + Program::BinaryFieldOp obj; + obj.value = serde::Deserializable::deserialize(deserializer); + deserializer.decrease_container_depth(); + return obj; } namespace Program { -inline bool operator==(const BinaryFieldOp::Add &lhs, - const BinaryFieldOp::Add &rhs) { - return true; -} + inline bool operator==(const BinaryFieldOp::Add &lhs, const BinaryFieldOp::Add &rhs) { + return true; + } -inline std::vector BinaryFieldOp::Add::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BinaryFieldOp::Add::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BinaryFieldOp::Add -BinaryFieldOp::Add::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; -} + inline BinaryFieldOp::Add BinaryFieldOp::Add::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BinaryFieldOp::Add &obj, Serializer &serializer) {} +void serde::Serializable::serialize(const Program::BinaryFieldOp::Add &obj, Serializer &serializer) { +} template <> template -Program::BinaryFieldOp::Add -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BinaryFieldOp::Add obj; - return obj; +Program::BinaryFieldOp::Add serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryFieldOp::Add obj; + return obj; } namespace Program { -inline bool operator==(const BinaryFieldOp::Sub &lhs, - const BinaryFieldOp::Sub &rhs) { - return true; -} + inline bool operator==(const BinaryFieldOp::Sub &lhs, const BinaryFieldOp::Sub &rhs) { + return true; + } -inline std::vector BinaryFieldOp::Sub::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BinaryFieldOp::Sub::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BinaryFieldOp::Sub -BinaryFieldOp::Sub::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; -} + inline BinaryFieldOp::Sub BinaryFieldOp::Sub::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BinaryFieldOp::Sub &obj, Serializer &serializer) {} +void serde::Serializable::serialize(const Program::BinaryFieldOp::Sub &obj, Serializer &serializer) { +} template <> template -Program::BinaryFieldOp::Sub -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BinaryFieldOp::Sub obj; - return obj; +Program::BinaryFieldOp::Sub serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryFieldOp::Sub obj; + return obj; } namespace Program { -inline bool operator==(const BinaryFieldOp::Mul &lhs, - const BinaryFieldOp::Mul &rhs) { - return true; -} + inline bool operator==(const BinaryFieldOp::Mul &lhs, const BinaryFieldOp::Mul &rhs) { + return true; + } -inline std::vector BinaryFieldOp::Mul::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BinaryFieldOp::Mul::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BinaryFieldOp::Mul -BinaryFieldOp::Mul::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; -} + inline BinaryFieldOp::Mul BinaryFieldOp::Mul::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BinaryFieldOp::Mul &obj, Serializer &serializer) {} +void serde::Serializable::serialize(const Program::BinaryFieldOp::Mul &obj, Serializer &serializer) { +} template <> template -Program::BinaryFieldOp::Mul -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BinaryFieldOp::Mul obj; - return obj; +Program::BinaryFieldOp::Mul serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryFieldOp::Mul obj; + return obj; } namespace Program { -inline bool operator==(const BinaryFieldOp::Div &lhs, - const BinaryFieldOp::Div &rhs) { - return true; -} + inline bool operator==(const BinaryFieldOp::Div &lhs, const BinaryFieldOp::Div &rhs) { + return true; + } -inline std::vector BinaryFieldOp::Div::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BinaryFieldOp::Div::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BinaryFieldOp::Div -BinaryFieldOp::Div::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; -} + inline BinaryFieldOp::Div BinaryFieldOp::Div::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BinaryFieldOp::Div &obj, Serializer &serializer) {} +void serde::Serializable::serialize(const Program::BinaryFieldOp::Div &obj, Serializer &serializer) { +} template <> template -Program::BinaryFieldOp::Div -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BinaryFieldOp::Div obj; - return obj; +Program::BinaryFieldOp::Div serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryFieldOp::Div obj; + return obj; } namespace Program { -inline bool operator==(const BinaryFieldOp::IntegerDiv &lhs, - const BinaryFieldOp::IntegerDiv &rhs) { - return true; -} + inline bool operator==(const BinaryFieldOp::IntegerDiv &lhs, const BinaryFieldOp::IntegerDiv &rhs) { + return true; + } -inline std::vector -BinaryFieldOp::IntegerDiv::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BinaryFieldOp::IntegerDiv::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BinaryFieldOp::IntegerDiv -BinaryFieldOp::IntegerDiv::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; -} + inline BinaryFieldOp::IntegerDiv BinaryFieldOp::IntegerDiv::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BinaryFieldOp::IntegerDiv &obj, Serializer &serializer) {} +void serde::Serializable::serialize(const Program::BinaryFieldOp::IntegerDiv &obj, Serializer &serializer) { +} template <> template -Program::BinaryFieldOp::IntegerDiv -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BinaryFieldOp::IntegerDiv obj; - return obj; +Program::BinaryFieldOp::IntegerDiv serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryFieldOp::IntegerDiv obj; + return obj; } namespace Program { -inline bool operator==(const BinaryFieldOp::Equals &lhs, - const BinaryFieldOp::Equals &rhs) { - return true; -} + inline bool operator==(const BinaryFieldOp::Equals &lhs, const BinaryFieldOp::Equals &rhs) { + return true; + } -inline std::vector BinaryFieldOp::Equals::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BinaryFieldOp::Equals::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BinaryFieldOp::Equals -BinaryFieldOp::Equals::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; -} + inline BinaryFieldOp::Equals BinaryFieldOp::Equals::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BinaryFieldOp::Equals &obj, Serializer &serializer) {} +void serde::Serializable::serialize(const Program::BinaryFieldOp::Equals &obj, Serializer &serializer) { +} template <> template -Program::BinaryFieldOp::Equals -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BinaryFieldOp::Equals obj; - return obj; +Program::BinaryFieldOp::Equals serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryFieldOp::Equals obj; + return obj; } namespace Program { -inline bool operator==(const BinaryFieldOp::LessThan &lhs, - const BinaryFieldOp::LessThan &rhs) { - return true; -} + inline bool operator==(const BinaryFieldOp::LessThan &lhs, const BinaryFieldOp::LessThan &rhs) { + return true; + } -inline std::vector BinaryFieldOp::LessThan::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BinaryFieldOp::LessThan::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BinaryFieldOp::LessThan -BinaryFieldOp::LessThan::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; -} + inline BinaryFieldOp::LessThan BinaryFieldOp::LessThan::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BinaryFieldOp::LessThan &obj, Serializer &serializer) {} +void serde::Serializable::serialize(const Program::BinaryFieldOp::LessThan &obj, Serializer &serializer) { +} template <> template -Program::BinaryFieldOp::LessThan -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BinaryFieldOp::LessThan obj; - return obj; +Program::BinaryFieldOp::LessThan serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryFieldOp::LessThan obj; + return obj; } namespace Program { -inline bool operator==(const BinaryFieldOp::LessThanEquals &lhs, - const BinaryFieldOp::LessThanEquals &rhs) { - return true; -} + inline bool operator==(const BinaryFieldOp::LessThanEquals &lhs, const BinaryFieldOp::LessThanEquals &rhs) { + return true; + } -inline std::vector -BinaryFieldOp::LessThanEquals::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, - serializer); - return std::move(serializer).bytes(); -} + inline std::vector BinaryFieldOp::LessThanEquals::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BinaryFieldOp::LessThanEquals -BinaryFieldOp::LessThanEquals::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; -} + inline BinaryFieldOp::LessThanEquals BinaryFieldOp::LessThanEquals::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BinaryFieldOp::LessThanEquals &obj, Serializer &serializer) { +void serde::Serializable::serialize(const Program::BinaryFieldOp::LessThanEquals &obj, Serializer &serializer) { } template <> template -Program::BinaryFieldOp::LessThanEquals -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BinaryFieldOp::LessThanEquals obj; - return obj; +Program::BinaryFieldOp::LessThanEquals serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryFieldOp::LessThanEquals obj; + return obj; } namespace Program { -inline bool operator==(const BinaryIntOp &lhs, const BinaryIntOp &rhs) { - if (!(lhs.value == rhs.value)) { - return false; - } - return true; -} + inline bool operator==(const BinaryIntOp &lhs, const BinaryIntOp &rhs) { + if (!(lhs.value == rhs.value)) { return false; } + return true; + } -inline std::vector BinaryIntOp::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BinaryIntOp::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BinaryIntOp BinaryIntOp::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; -} + inline BinaryIntOp BinaryIntOp::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BinaryIntOp &obj, Serializer &serializer) { - serializer.increase_container_depth(); - serde::Serializable::serialize(obj.value, serializer); - serializer.decrease_container_depth(); +void serde::Serializable::serialize(const Program::BinaryIntOp &obj, Serializer &serializer) { + serializer.increase_container_depth(); + serde::Serializable::serialize(obj.value, serializer); + serializer.decrease_container_depth(); } template <> template -Program::BinaryIntOp serde::Deserializable::deserialize( - Deserializer &deserializer) { - deserializer.increase_container_depth(); - Program::BinaryIntOp obj; - obj.value = - serde::Deserializable::deserialize(deserializer); - deserializer.decrease_container_depth(); - return obj; +Program::BinaryIntOp serde::Deserializable::deserialize(Deserializer &deserializer) { + deserializer.increase_container_depth(); + Program::BinaryIntOp obj; + obj.value = serde::Deserializable::deserialize(deserializer); + deserializer.decrease_container_depth(); + return obj; } namespace Program { -inline bool operator==(const BinaryIntOp::Add &lhs, - const BinaryIntOp::Add &rhs) { - return true; -} + inline bool operator==(const BinaryIntOp::Add &lhs, const BinaryIntOp::Add &rhs) { + return true; + } -inline std::vector BinaryIntOp::Add::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BinaryIntOp::Add::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BinaryIntOp::Add -BinaryIntOp::Add::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; -} + inline BinaryIntOp::Add BinaryIntOp::Add::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BinaryIntOp::Add &obj, Serializer &serializer) {} +void serde::Serializable::serialize(const Program::BinaryIntOp::Add &obj, Serializer &serializer) { +} template <> template -Program::BinaryIntOp::Add -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BinaryIntOp::Add obj; - return obj; +Program::BinaryIntOp::Add serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryIntOp::Add obj; + return obj; } namespace Program { -inline bool operator==(const BinaryIntOp::Sub &lhs, - const BinaryIntOp::Sub &rhs) { - return true; -} + inline bool operator==(const BinaryIntOp::Sub &lhs, const BinaryIntOp::Sub &rhs) { + return true; + } -inline std::vector BinaryIntOp::Sub::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BinaryIntOp::Sub::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BinaryIntOp::Sub -BinaryIntOp::Sub::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; -} + inline BinaryIntOp::Sub BinaryIntOp::Sub::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BinaryIntOp::Sub &obj, Serializer &serializer) {} +void serde::Serializable::serialize(const Program::BinaryIntOp::Sub &obj, Serializer &serializer) { +} template <> template -Program::BinaryIntOp::Sub -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BinaryIntOp::Sub obj; - return obj; +Program::BinaryIntOp::Sub serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryIntOp::Sub obj; + return obj; } namespace Program { -inline bool operator==(const BinaryIntOp::Mul &lhs, - const BinaryIntOp::Mul &rhs) { - return true; -} + inline bool operator==(const BinaryIntOp::Mul &lhs, const BinaryIntOp::Mul &rhs) { + return true; + } -inline std::vector BinaryIntOp::Mul::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BinaryIntOp::Mul::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BinaryIntOp::Mul -BinaryIntOp::Mul::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; -} + inline BinaryIntOp::Mul BinaryIntOp::Mul::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BinaryIntOp::Mul &obj, Serializer &serializer) {} +void serde::Serializable::serialize(const Program::BinaryIntOp::Mul &obj, Serializer &serializer) { +} template <> template -Program::BinaryIntOp::Mul -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BinaryIntOp::Mul obj; - return obj; +Program::BinaryIntOp::Mul serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryIntOp::Mul obj; + return obj; } namespace Program { -inline bool operator==(const BinaryIntOp::Div &lhs, - const BinaryIntOp::Div &rhs) { - return true; -} + inline bool operator==(const BinaryIntOp::Div &lhs, const BinaryIntOp::Div &rhs) { + return true; + } -inline std::vector BinaryIntOp::Div::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BinaryIntOp::Div::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BinaryIntOp::Div -BinaryIntOp::Div::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; -} + inline BinaryIntOp::Div BinaryIntOp::Div::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BinaryIntOp::Div &obj, Serializer &serializer) {} +void serde::Serializable::serialize(const Program::BinaryIntOp::Div &obj, Serializer &serializer) { +} template <> template -Program::BinaryIntOp::Div -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BinaryIntOp::Div obj; - return obj; +Program::BinaryIntOp::Div serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryIntOp::Div obj; + return obj; } namespace Program { -inline bool operator==(const BinaryIntOp::Equals &lhs, - const BinaryIntOp::Equals &rhs) { - return true; -} + inline bool operator==(const BinaryIntOp::Equals &lhs, const BinaryIntOp::Equals &rhs) { + return true; + } -inline std::vector BinaryIntOp::Equals::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BinaryIntOp::Equals::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BinaryIntOp::Equals -BinaryIntOp::Equals::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; -} + inline BinaryIntOp::Equals BinaryIntOp::Equals::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BinaryIntOp::Equals &obj, Serializer &serializer) {} +void serde::Serializable::serialize(const Program::BinaryIntOp::Equals &obj, Serializer &serializer) { +} template <> template -Program::BinaryIntOp::Equals -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BinaryIntOp::Equals obj; - return obj; +Program::BinaryIntOp::Equals serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryIntOp::Equals obj; + return obj; } namespace Program { -inline bool operator==(const BinaryIntOp::LessThan &lhs, - const BinaryIntOp::LessThan &rhs) { - return true; -} + inline bool operator==(const BinaryIntOp::LessThan &lhs, const BinaryIntOp::LessThan &rhs) { + return true; + } -inline std::vector BinaryIntOp::LessThan::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BinaryIntOp::LessThan::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BinaryIntOp::LessThan -BinaryIntOp::LessThan::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; -} + inline BinaryIntOp::LessThan BinaryIntOp::LessThan::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BinaryIntOp::LessThan &obj, Serializer &serializer) {} +void serde::Serializable::serialize(const Program::BinaryIntOp::LessThan &obj, Serializer &serializer) { +} template <> template -Program::BinaryIntOp::LessThan -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BinaryIntOp::LessThan obj; - return obj; +Program::BinaryIntOp::LessThan serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryIntOp::LessThan obj; + return obj; } namespace Program { -inline bool operator==(const BinaryIntOp::LessThanEquals &lhs, - const BinaryIntOp::LessThanEquals &rhs) { - return true; -} + inline bool operator==(const BinaryIntOp::LessThanEquals &lhs, const BinaryIntOp::LessThanEquals &rhs) { + return true; + } -inline std::vector -BinaryIntOp::LessThanEquals::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, - serializer); - return std::move(serializer).bytes(); -} + inline std::vector BinaryIntOp::LessThanEquals::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BinaryIntOp::LessThanEquals -BinaryIntOp::LessThanEquals::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; -} + inline BinaryIntOp::LessThanEquals BinaryIntOp::LessThanEquals::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BinaryIntOp::LessThanEquals &obj, Serializer &serializer) {} +void serde::Serializable::serialize(const Program::BinaryIntOp::LessThanEquals &obj, Serializer &serializer) { +} template <> template -Program::BinaryIntOp::LessThanEquals -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BinaryIntOp::LessThanEquals obj; - return obj; +Program::BinaryIntOp::LessThanEquals serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryIntOp::LessThanEquals obj; + return obj; } namespace Program { -inline bool operator==(const BinaryIntOp::And &lhs, - const BinaryIntOp::And &rhs) { - return true; -} + inline bool operator==(const BinaryIntOp::And &lhs, const BinaryIntOp::And &rhs) { + return true; + } -inline std::vector BinaryIntOp::And::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BinaryIntOp::And::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BinaryIntOp::And -BinaryIntOp::And::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; -} + inline BinaryIntOp::And BinaryIntOp::And::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BinaryIntOp::And &obj, Serializer &serializer) {} +void serde::Serializable::serialize(const Program::BinaryIntOp::And &obj, Serializer &serializer) { +} template <> template -Program::BinaryIntOp::And -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BinaryIntOp::And obj; - return obj; +Program::BinaryIntOp::And serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryIntOp::And obj; + return obj; } namespace Program { -inline bool operator==(const BinaryIntOp::Or &lhs, const BinaryIntOp::Or &rhs) { - return true; -} + inline bool operator==(const BinaryIntOp::Or &lhs, const BinaryIntOp::Or &rhs) { + return true; + } -inline std::vector BinaryIntOp::Or::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BinaryIntOp::Or::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BinaryIntOp::Or -BinaryIntOp::Or::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; -} + inline BinaryIntOp::Or BinaryIntOp::Or::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BinaryIntOp::Or &obj, Serializer &serializer) {} +void serde::Serializable::serialize(const Program::BinaryIntOp::Or &obj, Serializer &serializer) { +} template <> template -Program::BinaryIntOp::Or -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BinaryIntOp::Or obj; - return obj; +Program::BinaryIntOp::Or serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryIntOp::Or obj; + return obj; } namespace Program { -inline bool operator==(const BinaryIntOp::Xor &lhs, - const BinaryIntOp::Xor &rhs) { - return true; -} + inline bool operator==(const BinaryIntOp::Xor &lhs, const BinaryIntOp::Xor &rhs) { + return true; + } -inline std::vector BinaryIntOp::Xor::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BinaryIntOp::Xor::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BinaryIntOp::Xor -BinaryIntOp::Xor::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; -} + inline BinaryIntOp::Xor BinaryIntOp::Xor::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BinaryIntOp::Xor &obj, Serializer &serializer) {} +void serde::Serializable::serialize(const Program::BinaryIntOp::Xor &obj, Serializer &serializer) { +} template <> template -Program::BinaryIntOp::Xor -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BinaryIntOp::Xor obj; - return obj; +Program::BinaryIntOp::Xor serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryIntOp::Xor obj; + return obj; } namespace Program { -inline bool operator==(const BinaryIntOp::Shl &lhs, - const BinaryIntOp::Shl &rhs) { - return true; -} + inline bool operator==(const BinaryIntOp::Shl &lhs, const BinaryIntOp::Shl &rhs) { + return true; + } -inline std::vector BinaryIntOp::Shl::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BinaryIntOp::Shl::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BinaryIntOp::Shl -BinaryIntOp::Shl::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; -} + inline BinaryIntOp::Shl BinaryIntOp::Shl::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BinaryIntOp::Shl &obj, Serializer &serializer) {} +void serde::Serializable::serialize(const Program::BinaryIntOp::Shl &obj, Serializer &serializer) { +} template <> template -Program::BinaryIntOp::Shl -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BinaryIntOp::Shl obj; - return obj; +Program::BinaryIntOp::Shl serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryIntOp::Shl obj; + return obj; } namespace Program { -inline bool operator==(const BinaryIntOp::Shr &lhs, - const BinaryIntOp::Shr &rhs) { - return true; -} + inline bool operator==(const BinaryIntOp::Shr &lhs, const BinaryIntOp::Shr &rhs) { + return true; + } -inline std::vector BinaryIntOp::Shr::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BinaryIntOp::Shr::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BinaryIntOp::Shr -BinaryIntOp::Shr::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; -} + inline BinaryIntOp::Shr BinaryIntOp::Shr::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BinaryIntOp::Shr &obj, Serializer &serializer) {} +void serde::Serializable::serialize(const Program::BinaryIntOp::Shr &obj, Serializer &serializer) { +} template <> template -Program::BinaryIntOp::Shr -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BinaryIntOp::Shr obj; - return obj; +Program::BinaryIntOp::Shr serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BinaryIntOp::Shr obj; + return obj; } namespace Program { -inline bool operator==(const BlackBoxFuncCall &lhs, - const BlackBoxFuncCall &rhs) { - if (!(lhs.value == rhs.value)) { - return false; - } - return true; -} + inline bool operator==(const BlackBoxFuncCall &lhs, const BlackBoxFuncCall &rhs) { + if (!(lhs.value == rhs.value)) { return false; } + return true; + } -inline std::vector BlackBoxFuncCall::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BlackBoxFuncCall::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BlackBoxFuncCall -BlackBoxFuncCall::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; -} + inline BlackBoxFuncCall BlackBoxFuncCall::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BlackBoxFuncCall &obj, Serializer &serializer) { - serializer.increase_container_depth(); - serde::Serializable::serialize(obj.value, serializer); - serializer.decrease_container_depth(); +void serde::Serializable::serialize(const Program::BlackBoxFuncCall &obj, Serializer &serializer) { + serializer.increase_container_depth(); + serde::Serializable::serialize(obj.value, serializer); + serializer.decrease_container_depth(); } template <> template -Program::BlackBoxFuncCall -serde::Deserializable::deserialize( - Deserializer &deserializer) { - deserializer.increase_container_depth(); - Program::BlackBoxFuncCall obj; - obj.value = - serde::Deserializable::deserialize(deserializer); - deserializer.decrease_container_depth(); - return obj; +Program::BlackBoxFuncCall serde::Deserializable::deserialize(Deserializer &deserializer) { + deserializer.increase_container_depth(); + Program::BlackBoxFuncCall obj; + obj.value = serde::Deserializable::deserialize(deserializer); + deserializer.decrease_container_depth(); + return obj; } namespace Program { -inline bool operator==(const BlackBoxFuncCall::AND &lhs, - const BlackBoxFuncCall::AND &rhs) { - if (!(lhs.lhs == rhs.lhs)) { - return false; - } - if (!(lhs.rhs == rhs.rhs)) { - return false; - } - if (!(lhs.output == rhs.output)) { - return false; - } - return true; -} + inline bool operator==(const BlackBoxFuncCall::AND &lhs, const BlackBoxFuncCall::AND &rhs) { + if (!(lhs.lhs == rhs.lhs)) { return false; } + if (!(lhs.rhs == rhs.rhs)) { return false; } + if (!(lhs.output == rhs.output)) { return false; } + return true; + } -inline std::vector BlackBoxFuncCall::AND::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BlackBoxFuncCall::AND::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BlackBoxFuncCall::AND -BlackBoxFuncCall::AND::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; -} + inline BlackBoxFuncCall::AND BlackBoxFuncCall::AND::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BlackBoxFuncCall::AND &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.lhs, serializer); - serde::Serializable::serialize(obj.rhs, serializer); - serde::Serializable::serialize(obj.output, serializer); +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::AND &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.lhs, serializer); + serde::Serializable::serialize(obj.rhs, serializer); + serde::Serializable::serialize(obj.output, serializer); } template <> template -Program::BlackBoxFuncCall::AND -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BlackBoxFuncCall::AND obj; - obj.lhs = serde::Deserializable::deserialize(deserializer); - obj.rhs = serde::Deserializable::deserialize(deserializer); - obj.output = - serde::Deserializable::deserialize(deserializer); - return obj; +Program::BlackBoxFuncCall::AND serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::AND obj; + obj.lhs = serde::Deserializable::deserialize(deserializer); + obj.rhs = serde::Deserializable::deserialize(deserializer); + obj.output = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -inline bool operator==(const BlackBoxFuncCall::XOR &lhs, - const BlackBoxFuncCall::XOR &rhs) { - if (!(lhs.lhs == rhs.lhs)) { - return false; - } - if (!(lhs.rhs == rhs.rhs)) { - return false; - } - if (!(lhs.output == rhs.output)) { - return false; - } - return true; -} + inline bool operator==(const BlackBoxFuncCall::XOR &lhs, const BlackBoxFuncCall::XOR &rhs) { + if (!(lhs.lhs == rhs.lhs)) { return false; } + if (!(lhs.rhs == rhs.rhs)) { return false; } + if (!(lhs.output == rhs.output)) { return false; } + return true; + } -inline std::vector BlackBoxFuncCall::XOR::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BlackBoxFuncCall::XOR::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BlackBoxFuncCall::XOR -BlackBoxFuncCall::XOR::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; -} + inline BlackBoxFuncCall::XOR BlackBoxFuncCall::XOR::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BlackBoxFuncCall::XOR &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.lhs, serializer); - serde::Serializable::serialize(obj.rhs, serializer); - serde::Serializable::serialize(obj.output, serializer); +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::XOR &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.lhs, serializer); + serde::Serializable::serialize(obj.rhs, serializer); + serde::Serializable::serialize(obj.output, serializer); } template <> template -Program::BlackBoxFuncCall::XOR -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BlackBoxFuncCall::XOR obj; - obj.lhs = serde::Deserializable::deserialize(deserializer); - obj.rhs = serde::Deserializable::deserialize(deserializer); - obj.output = - serde::Deserializable::deserialize(deserializer); - return obj; +Program::BlackBoxFuncCall::XOR serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::XOR obj; + obj.lhs = serde::Deserializable::deserialize(deserializer); + obj.rhs = serde::Deserializable::deserialize(deserializer); + obj.output = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -inline bool operator==(const BlackBoxFuncCall::RANGE &lhs, - const BlackBoxFuncCall::RANGE &rhs) { - if (!(lhs.input == rhs.input)) { - return false; - } - return true; -} + inline bool operator==(const BlackBoxFuncCall::RANGE &lhs, const BlackBoxFuncCall::RANGE &rhs) { + if (!(lhs.input == rhs.input)) { return false; } + return true; + } -inline std::vector BlackBoxFuncCall::RANGE::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BlackBoxFuncCall::RANGE::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BlackBoxFuncCall::RANGE -BlackBoxFuncCall::RANGE::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; -} + inline BlackBoxFuncCall::RANGE BlackBoxFuncCall::RANGE::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BlackBoxFuncCall::RANGE &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.input, serializer); +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::RANGE &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.input, serializer); } template <> template -Program::BlackBoxFuncCall::RANGE -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BlackBoxFuncCall::RANGE obj; - obj.input = - serde::Deserializable::deserialize(deserializer); - return obj; +Program::BlackBoxFuncCall::RANGE serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::RANGE obj; + obj.input = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -inline bool operator==(const BlackBoxFuncCall::SHA256 &lhs, - const BlackBoxFuncCall::SHA256 &rhs) { - if (!(lhs.inputs == rhs.inputs)) { - return false; - } - if (!(lhs.outputs == rhs.outputs)) { - return false; - } - return true; -} + inline bool operator==(const BlackBoxFuncCall::SHA256 &lhs, const BlackBoxFuncCall::SHA256 &rhs) { + if (!(lhs.inputs == rhs.inputs)) { return false; } + if (!(lhs.outputs == rhs.outputs)) { return false; } + return true; + } -inline std::vector BlackBoxFuncCall::SHA256::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BlackBoxFuncCall::SHA256::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BlackBoxFuncCall::SHA256 -BlackBoxFuncCall::SHA256::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; -} + inline BlackBoxFuncCall::SHA256 BlackBoxFuncCall::SHA256::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BlackBoxFuncCall::SHA256 &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.inputs, serializer); - serde::Serializable::serialize(obj.outputs, - serializer); +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::SHA256 &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.inputs, serializer); + serde::Serializable::serialize(obj.outputs, serializer); } template <> template -Program::BlackBoxFuncCall::SHA256 -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BlackBoxFuncCall::SHA256 obj; - obj.inputs = - serde::Deserializable::deserialize(deserializer); - obj.outputs = - serde::Deserializable::deserialize(deserializer); - return obj; +Program::BlackBoxFuncCall::SHA256 serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::SHA256 obj; + obj.inputs = serde::Deserializable::deserialize(deserializer); + obj.outputs = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -inline bool operator==(const BlackBoxFuncCall::Blake2s &lhs, - const BlackBoxFuncCall::Blake2s &rhs) { - if (!(lhs.inputs == rhs.inputs)) { - return false; - } - if (!(lhs.outputs == rhs.outputs)) { - return false; - } - return true; -} + inline bool operator==(const BlackBoxFuncCall::Blake2s &lhs, const BlackBoxFuncCall::Blake2s &rhs) { + if (!(lhs.inputs == rhs.inputs)) { return false; } + if (!(lhs.outputs == rhs.outputs)) { return false; } + return true; + } -inline std::vector -BlackBoxFuncCall::Blake2s::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BlackBoxFuncCall::Blake2s::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BlackBoxFuncCall::Blake2s -BlackBoxFuncCall::Blake2s::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; -} + inline BlackBoxFuncCall::Blake2s BlackBoxFuncCall::Blake2s::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BlackBoxFuncCall::Blake2s &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.inputs, serializer); - serde::Serializable::serialize(obj.outputs, - serializer); +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::Blake2s &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.inputs, serializer); + serde::Serializable::serialize(obj.outputs, serializer); } template <> template -Program::BlackBoxFuncCall::Blake2s -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BlackBoxFuncCall::Blake2s obj; - obj.inputs = - serde::Deserializable::deserialize(deserializer); - obj.outputs = - serde::Deserializable::deserialize(deserializer); - return obj; +Program::BlackBoxFuncCall::Blake2s serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::Blake2s obj; + obj.inputs = serde::Deserializable::deserialize(deserializer); + obj.outputs = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -inline bool operator==(const BlackBoxFuncCall::Blake3 &lhs, - const BlackBoxFuncCall::Blake3 &rhs) { - if (!(lhs.inputs == rhs.inputs)) { - return false; - } - if (!(lhs.outputs == rhs.outputs)) { - return false; - } - return true; -} + inline bool operator==(const BlackBoxFuncCall::Blake3 &lhs, const BlackBoxFuncCall::Blake3 &rhs) { + if (!(lhs.inputs == rhs.inputs)) { return false; } + if (!(lhs.outputs == rhs.outputs)) { return false; } + return true; + } -inline std::vector BlackBoxFuncCall::Blake3::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BlackBoxFuncCall::Blake3::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BlackBoxFuncCall::Blake3 -BlackBoxFuncCall::Blake3::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; -} + inline BlackBoxFuncCall::Blake3 BlackBoxFuncCall::Blake3::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BlackBoxFuncCall::Blake3 &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.inputs, serializer); - serde::Serializable::serialize(obj.outputs, - serializer); +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::Blake3 &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.inputs, serializer); + serde::Serializable::serialize(obj.outputs, serializer); } template <> template -Program::BlackBoxFuncCall::Blake3 -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BlackBoxFuncCall::Blake3 obj; - obj.inputs = - serde::Deserializable::deserialize(deserializer); - obj.outputs = - serde::Deserializable::deserialize(deserializer); - return obj; +Program::BlackBoxFuncCall::Blake3 serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::Blake3 obj; + obj.inputs = serde::Deserializable::deserialize(deserializer); + obj.outputs = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -inline bool operator==(const BlackBoxFuncCall::SchnorrVerify &lhs, - const BlackBoxFuncCall::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.signature == rhs.signature)) { - return false; - } - if (!(lhs.message == rhs.message)) { - return false; - } - if (!(lhs.output == rhs.output)) { - return false; - } - return true; -} + inline bool operator==(const BlackBoxFuncCall::SchnorrVerify &lhs, const BlackBoxFuncCall::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.signature == rhs.signature)) { return false; } + if (!(lhs.message == rhs.message)) { return false; } + if (!(lhs.output == rhs.output)) { return false; } + return true; + } -inline std::vector -BlackBoxFuncCall::SchnorrVerify::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, - serializer); - return std::move(serializer).bytes(); -} + inline std::vector BlackBoxFuncCall::SchnorrVerify::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BlackBoxFuncCall::SchnorrVerify -BlackBoxFuncCall::SchnorrVerify::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; -} + inline BlackBoxFuncCall::SchnorrVerify BlackBoxFuncCall::SchnorrVerify::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BlackBoxFuncCall::SchnorrVerify &obj, - Serializer &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.message, - serializer); - serde::Serializable::serialize(obj.output, serializer); +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::SchnorrVerify &obj, Serializer &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.message, serializer); + serde::Serializable::serialize(obj.output, serializer); } template <> template -Program::BlackBoxFuncCall::SchnorrVerify -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BlackBoxFuncCall::SchnorrVerify obj; - obj.public_key_x = - serde::Deserializable::deserialize( - deserializer); - obj.public_key_y = - serde::Deserializable::deserialize( - deserializer); - obj.signature = - serde::Deserializable::deserialize(deserializer); - obj.message = - serde::Deserializable::deserialize(deserializer); - obj.output = - serde::Deserializable::deserialize(deserializer); - return obj; -} - -namespace Program { - -inline bool operator==(const BlackBoxFuncCall::PedersenCommitment &lhs, - const BlackBoxFuncCall::PedersenCommitment &rhs) { - if (!(lhs.inputs == rhs.inputs)) { - return false; - } - if (!(lhs.domain_separator == rhs.domain_separator)) { - return false; - } - if (!(lhs.outputs == rhs.outputs)) { - return false; - } - return true; +Program::BlackBoxFuncCall::SchnorrVerify serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::SchnorrVerify obj; + obj.public_key_x = serde::Deserializable::deserialize(deserializer); + obj.public_key_y = serde::Deserializable::deserialize(deserializer); + obj.signature = serde::Deserializable::deserialize(deserializer); + obj.message = serde::Deserializable::deserialize(deserializer); + obj.output = serde::Deserializable::deserialize(deserializer); + return obj; } -inline std::vector -BlackBoxFuncCall::PedersenCommitment::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize( - *this, serializer); - return std::move(serializer).bytes(); -} +namespace Program { -inline BlackBoxFuncCall::PedersenCommitment -BlackBoxFuncCall::PedersenCommitment::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; -} + inline bool operator==(const BlackBoxFuncCall::PedersenCommitment &lhs, const BlackBoxFuncCall::PedersenCommitment &rhs) { + if (!(lhs.inputs == rhs.inputs)) { return false; } + if (!(lhs.domain_separator == rhs.domain_separator)) { return false; } + if (!(lhs.outputs == rhs.outputs)) { return false; } + return true; + } + + inline std::vector BlackBoxFuncCall::PedersenCommitment::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } + + inline BlackBoxFuncCall::PedersenCommitment BlackBoxFuncCall::PedersenCommitment::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable:: - serialize(const Program::BlackBoxFuncCall::PedersenCommitment &obj, - Serializer &serializer) { - serde::Serializable::serialize(obj.inputs, serializer); - serde::Serializable::serialize( - obj.domain_separator, serializer); - serde::Serializable::serialize(obj.outputs, - serializer); +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::PedersenCommitment &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.inputs, serializer); + serde::Serializable::serialize(obj.domain_separator, serializer); + serde::Serializable::serialize(obj.outputs, serializer); } template <> template -Program::BlackBoxFuncCall::PedersenCommitment -serde::Deserializable:: - deserialize(Deserializer &deserializer) { - Program::BlackBoxFuncCall::PedersenCommitment obj; - obj.inputs = - serde::Deserializable::deserialize(deserializer); - obj.domain_separator = - serde::Deserializable::deserialize( - deserializer); - obj.outputs = - serde::Deserializable::deserialize(deserializer); - return obj; -} - -namespace Program { - -inline bool operator==(const BlackBoxFuncCall::PedersenHash &lhs, - const BlackBoxFuncCall::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; +Program::BlackBoxFuncCall::PedersenCommitment serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::PedersenCommitment obj; + obj.inputs = serde::Deserializable::deserialize(deserializer); + obj.domain_separator = serde::Deserializable::deserialize(deserializer); + obj.outputs = serde::Deserializable::deserialize(deserializer); + return obj; } -inline std::vector -BlackBoxFuncCall::PedersenHash::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, - serializer); - return std::move(serializer).bytes(); -} +namespace Program { -inline BlackBoxFuncCall::PedersenHash -BlackBoxFuncCall::PedersenHash::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; -} + inline bool operator==(const BlackBoxFuncCall::PedersenHash &lhs, const BlackBoxFuncCall::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 BlackBoxFuncCall::PedersenHash::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } + + inline BlackBoxFuncCall::PedersenHash BlackBoxFuncCall::PedersenHash::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BlackBoxFuncCall::PedersenHash &obj, - Serializer &serializer) { - serde::Serializable::serialize(obj.inputs, serializer); - serde::Serializable::serialize( - obj.domain_separator, serializer); - serde::Serializable::serialize(obj.output, serializer); +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::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 -Program::BlackBoxFuncCall::PedersenHash -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BlackBoxFuncCall::PedersenHash obj; - obj.inputs = - serde::Deserializable::deserialize(deserializer); - obj.domain_separator = - serde::Deserializable::deserialize( - deserializer); - obj.output = - serde::Deserializable::deserialize(deserializer); - return obj; +Program::BlackBoxFuncCall::PedersenHash serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::PedersenHash obj; + obj.inputs = serde::Deserializable::deserialize(deserializer); + obj.domain_separator = serde::Deserializable::deserialize(deserializer); + obj.output = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -inline bool operator==(const BlackBoxFuncCall::EcdsaSecp256k1 &lhs, - const BlackBoxFuncCall::EcdsaSecp256k1 &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.signature == rhs.signature)) { - return false; - } - if (!(lhs.hashed_message == rhs.hashed_message)) { - return false; - } - if (!(lhs.output == rhs.output)) { - return false; - } - return true; -} - -inline std::vector -BlackBoxFuncCall::EcdsaSecp256k1::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, - serializer); - return std::move(serializer).bytes(); -} - -inline BlackBoxFuncCall::EcdsaSecp256k1 -BlackBoxFuncCall::EcdsaSecp256k1::bincodeDeserialize( - std::vector input) { - auto deserializer = serde::BincodeDeserializer(input); - auto value = - serde::Deserializable::deserialize( - deserializer); - if (deserializer.get_buffer_offset() < input.size()) { - throw serde::deserialization_error("Some input bytes were not read"); - } - return value; -} - -} // end of namespace Program + inline bool operator==(const BlackBoxFuncCall::EcdsaSecp256k1 &lhs, const BlackBoxFuncCall::EcdsaSecp256k1 &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.signature == rhs.signature)) { return false; } + if (!(lhs.hashed_message == rhs.hashed_message)) { return false; } + if (!(lhs.output == rhs.output)) { return false; } + return true; + } + + inline std::vector BlackBoxFuncCall::EcdsaSecp256k1::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } + + inline BlackBoxFuncCall::EcdsaSecp256k1 BlackBoxFuncCall::EcdsaSecp256k1::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } + +} // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BlackBoxFuncCall::EcdsaSecp256k1 &obj, - Serializer &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.hashed_message, serializer); - serde::Serializable::serialize(obj.output, serializer); -} - -template <> -template -Program::BlackBoxFuncCall::EcdsaSecp256k1 -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BlackBoxFuncCall::EcdsaSecp256k1 obj; - obj.public_key_x = - serde::Deserializable::deserialize( - deserializer); - obj.public_key_y = - serde::Deserializable::deserialize( - deserializer); - obj.signature = - serde::Deserializable::deserialize(deserializer); - obj.hashed_message = - serde::Deserializable::deserialize( - deserializer); - obj.output = - serde::Deserializable::deserialize(deserializer); - return obj; -} - -namespace Program { - -inline bool operator==(const BlackBoxFuncCall::EcdsaSecp256r1 &lhs, - const BlackBoxFuncCall::EcdsaSecp256r1 &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.signature == rhs.signature)) { - return false; - } - if (!(lhs.hashed_message == rhs.hashed_message)) { - return false; - } - if (!(lhs.output == rhs.output)) { - return false; - } - return true; -} - -inline std::vector -BlackBoxFuncCall::EcdsaSecp256r1::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, - serializer); - return std::move(serializer).bytes(); -} - -inline BlackBoxFuncCall::EcdsaSecp256r1 -BlackBoxFuncCall::EcdsaSecp256r1::bincodeDeserialize( - std::vector input) { - auto deserializer = serde::BincodeDeserializer(input); - auto value = - serde::Deserializable::deserialize( - deserializer); - if (deserializer.get_buffer_offset() < input.size()) { - throw serde::deserialization_error("Some input bytes were not read"); - } - return value; -} - -} // end of namespace Program - -template <> -template -void serde::Serializable::serialize( - const Program::BlackBoxFuncCall::EcdsaSecp256r1 &obj, - Serializer &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.hashed_message, serializer); - serde::Serializable::serialize(obj.output, serializer); -} - -template <> -template -Program::BlackBoxFuncCall::EcdsaSecp256r1 -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BlackBoxFuncCall::EcdsaSecp256r1 obj; - obj.public_key_x = - serde::Deserializable::deserialize( - deserializer); - obj.public_key_y = - serde::Deserializable::deserialize( - deserializer); - obj.signature = - serde::Deserializable::deserialize(deserializer); - obj.hashed_message = - serde::Deserializable::deserialize( - deserializer); - obj.output = - serde::Deserializable::deserialize(deserializer); - return obj; -} - -namespace Program { - -inline bool operator==(const BlackBoxFuncCall::FixedBaseScalarMul &lhs, - const BlackBoxFuncCall::FixedBaseScalarMul &rhs) { - if (!(lhs.low == rhs.low)) { - return false; - } - if (!(lhs.high == rhs.high)) { - return false; - } - if (!(lhs.outputs == rhs.outputs)) { - return false; - } - return true; +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::EcdsaSecp256k1 &obj, Serializer &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.hashed_message, serializer); + serde::Serializable::serialize(obj.output, serializer); } -inline std::vector -BlackBoxFuncCall::FixedBaseScalarMul::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize( - *this, serializer); - return std::move(serializer).bytes(); -} - -inline BlackBoxFuncCall::FixedBaseScalarMul -BlackBoxFuncCall::FixedBaseScalarMul::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; +template <> +template +Program::BlackBoxFuncCall::EcdsaSecp256k1 serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::EcdsaSecp256k1 obj; + obj.public_key_x = serde::Deserializable::deserialize(deserializer); + obj.public_key_y = serde::Deserializable::deserialize(deserializer); + obj.signature = serde::Deserializable::deserialize(deserializer); + obj.hashed_message = serde::Deserializable::deserialize(deserializer); + obj.output = serde::Deserializable::deserialize(deserializer); + return obj; } +namespace Program { + + inline bool operator==(const BlackBoxFuncCall::EcdsaSecp256r1 &lhs, const BlackBoxFuncCall::EcdsaSecp256r1 &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.signature == rhs.signature)) { return false; } + if (!(lhs.hashed_message == rhs.hashed_message)) { return false; } + if (!(lhs.output == rhs.output)) { return false; } + return true; + } + + inline std::vector BlackBoxFuncCall::EcdsaSecp256r1::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } + + inline BlackBoxFuncCall::EcdsaSecp256r1 BlackBoxFuncCall::EcdsaSecp256r1::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } + } // end of namespace Program - -template <> -template -void serde::Serializable:: - serialize(const Program::BlackBoxFuncCall::FixedBaseScalarMul &obj, - Serializer &serializer) { - serde::Serializable::serialize(obj.low, serializer); - serde::Serializable::serialize(obj.high, serializer); - serde::Serializable::serialize(obj.outputs, - serializer); + +template <> +template +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::EcdsaSecp256r1 &obj, Serializer &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.hashed_message, serializer); + serde::Serializable::serialize(obj.output, serializer); } template <> template -Program::BlackBoxFuncCall::FixedBaseScalarMul -serde::Deserializable:: - deserialize(Deserializer &deserializer) { - Program::BlackBoxFuncCall::FixedBaseScalarMul obj; - obj.low = serde::Deserializable::deserialize(deserializer); - obj.high = - serde::Deserializable::deserialize(deserializer); - obj.outputs = - serde::Deserializable::deserialize(deserializer); - return obj; -} - -namespace Program { - -inline bool operator==(const BlackBoxFuncCall::EmbeddedCurveAdd &lhs, - const BlackBoxFuncCall::EmbeddedCurveAdd &rhs) { - if (!(lhs.input1_x == rhs.input1_x)) { - return false; - } - if (!(lhs.input1_y == rhs.input1_y)) { - return false; - } - if (!(lhs.input2_x == rhs.input2_x)) { - return false; - } - if (!(lhs.input2_y == rhs.input2_y)) { - return false; - } - if (!(lhs.outputs == rhs.outputs)) { - return false; - } - return true; +Program::BlackBoxFuncCall::EcdsaSecp256r1 serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::EcdsaSecp256r1 obj; + obj.public_key_x = serde::Deserializable::deserialize(deserializer); + obj.public_key_y = serde::Deserializable::deserialize(deserializer); + obj.signature = serde::Deserializable::deserialize(deserializer); + obj.hashed_message = serde::Deserializable::deserialize(deserializer); + obj.output = serde::Deserializable::deserialize(deserializer); + return obj; } -inline std::vector -BlackBoxFuncCall::EmbeddedCurveAdd::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize( - *this, serializer); - return std::move(serializer).bytes(); -} +namespace Program { -inline BlackBoxFuncCall::EmbeddedCurveAdd -BlackBoxFuncCall::EmbeddedCurveAdd::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; -} + inline bool operator==(const BlackBoxFuncCall::FixedBaseScalarMul &lhs, const BlackBoxFuncCall::FixedBaseScalarMul &rhs) { + if (!(lhs.low == rhs.low)) { return false; } + if (!(lhs.high == rhs.high)) { return false; } + if (!(lhs.outputs == rhs.outputs)) { return false; } + return true; + } + + inline std::vector BlackBoxFuncCall::FixedBaseScalarMul::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } + + inline BlackBoxFuncCall::FixedBaseScalarMul BlackBoxFuncCall::FixedBaseScalarMul::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable:: - serialize(const Program::BlackBoxFuncCall::EmbeddedCurveAdd &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.outputs, - serializer); +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::FixedBaseScalarMul &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.low, serializer); + serde::Serializable::serialize(obj.high, serializer); + serde::Serializable::serialize(obj.outputs, serializer); } template <> template -Program::BlackBoxFuncCall::EmbeddedCurveAdd -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BlackBoxFuncCall::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.outputs = - serde::Deserializable::deserialize(deserializer); - return obj; +Program::BlackBoxFuncCall::FixedBaseScalarMul serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::FixedBaseScalarMul obj; + obj.low = serde::Deserializable::deserialize(deserializer); + obj.high = serde::Deserializable::deserialize(deserializer); + obj.outputs = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -inline bool operator==(const BlackBoxFuncCall::Keccak256 &lhs, - const BlackBoxFuncCall::Keccak256 &rhs) { - if (!(lhs.inputs == rhs.inputs)) { - return false; - } - if (!(lhs.outputs == rhs.outputs)) { - return false; - } - return true; -} + inline bool operator==(const BlackBoxFuncCall::EmbeddedCurveAdd &lhs, const BlackBoxFuncCall::EmbeddedCurveAdd &rhs) { + if (!(lhs.input1_x == rhs.input1_x)) { return false; } + if (!(lhs.input1_y == rhs.input1_y)) { return false; } + if (!(lhs.input2_x == rhs.input2_x)) { return false; } + if (!(lhs.input2_y == rhs.input2_y)) { return false; } + if (!(lhs.outputs == rhs.outputs)) { return false; } + return true; + } -inline std::vector -BlackBoxFuncCall::Keccak256::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, - serializer); - return std::move(serializer).bytes(); -} + inline std::vector BlackBoxFuncCall::EmbeddedCurveAdd::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BlackBoxFuncCall::Keccak256 -BlackBoxFuncCall::Keccak256::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; -} + inline BlackBoxFuncCall::EmbeddedCurveAdd BlackBoxFuncCall::EmbeddedCurveAdd::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BlackBoxFuncCall::Keccak256 &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.inputs, serializer); - serde::Serializable::serialize(obj.outputs, - serializer); +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::EmbeddedCurveAdd &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.outputs, serializer); } template <> template -Program::BlackBoxFuncCall::Keccak256 -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BlackBoxFuncCall::Keccak256 obj; - obj.inputs = - serde::Deserializable::deserialize(deserializer); - obj.outputs = - serde::Deserializable::deserialize(deserializer); - return obj; +Program::BlackBoxFuncCall::EmbeddedCurveAdd serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::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.outputs = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -inline bool operator==(const BlackBoxFuncCall::Keccak256VariableLength &lhs, - const BlackBoxFuncCall::Keccak256VariableLength &rhs) { - if (!(lhs.inputs == rhs.inputs)) { - return false; - } - if (!(lhs.var_message_size == rhs.var_message_size)) { - return false; - } - if (!(lhs.outputs == rhs.outputs)) { - return false; - } - return true; -} + inline bool operator==(const BlackBoxFuncCall::Keccak256 &lhs, const BlackBoxFuncCall::Keccak256 &rhs) { + if (!(lhs.inputs == rhs.inputs)) { return false; } + if (!(lhs.outputs == rhs.outputs)) { return false; } + return true; + } -inline std::vector -BlackBoxFuncCall::Keccak256VariableLength::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize( - *this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BlackBoxFuncCall::Keccak256::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BlackBoxFuncCall::Keccak256VariableLength -BlackBoxFuncCall::Keccak256VariableLength::bincodeDeserialize( - std::vector input) { - auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable< - BlackBoxFuncCall::Keccak256VariableLength>::deserialize(deserializer); - if (deserializer.get_buffer_offset() < input.size()) { - throw serde::deserialization_error("Some input bytes were not read"); - } - return value; -} + inline BlackBoxFuncCall::Keccak256 BlackBoxFuncCall::Keccak256::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable:: - serialize(const Program::BlackBoxFuncCall::Keccak256VariableLength &obj, - Serializer &serializer) { - serde::Serializable::serialize(obj.inputs, serializer); - serde::Serializable::serialize( - obj.var_message_size, serializer); - serde::Serializable::serialize(obj.outputs, - serializer); +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::Keccak256 &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.inputs, serializer); + serde::Serializable::serialize(obj.outputs, serializer); } template <> template -Program::BlackBoxFuncCall::Keccak256VariableLength -serde::Deserializable:: - deserialize(Deserializer &deserializer) { - Program::BlackBoxFuncCall::Keccak256VariableLength obj; - obj.inputs = - serde::Deserializable::deserialize(deserializer); - obj.var_message_size = - serde::Deserializable::deserialize( - deserializer); - obj.outputs = - serde::Deserializable::deserialize(deserializer); - return obj; +Program::BlackBoxFuncCall::Keccak256 serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::Keccak256 obj; + obj.inputs = serde::Deserializable::deserialize(deserializer); + obj.outputs = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -inline bool operator==(const BlackBoxFuncCall::Keccakf1600 &lhs, - const BlackBoxFuncCall::Keccakf1600 &rhs) { - if (!(lhs.inputs == rhs.inputs)) { - return false; - } - if (!(lhs.outputs == rhs.outputs)) { - return false; - } - return true; -} + inline bool operator==(const BlackBoxFuncCall::Keccak256VariableLength &lhs, const BlackBoxFuncCall::Keccak256VariableLength &rhs) { + if (!(lhs.inputs == rhs.inputs)) { return false; } + if (!(lhs.var_message_size == rhs.var_message_size)) { return false; } + if (!(lhs.outputs == rhs.outputs)) { return false; } + return true; + } -inline std::vector -BlackBoxFuncCall::Keccakf1600::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, - serializer); - return std::move(serializer).bytes(); -} + inline std::vector BlackBoxFuncCall::Keccak256VariableLength::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BlackBoxFuncCall::Keccakf1600 -BlackBoxFuncCall::Keccakf1600::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; -} + inline BlackBoxFuncCall::Keccak256VariableLength BlackBoxFuncCall::Keccak256VariableLength::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BlackBoxFuncCall::Keccakf1600 &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.inputs, serializer); - serde::Serializable::serialize(obj.outputs, - serializer); +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::Keccak256VariableLength &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.inputs, serializer); + serde::Serializable::serialize(obj.var_message_size, serializer); + serde::Serializable::serialize(obj.outputs, serializer); } template <> template -Program::BlackBoxFuncCall::Keccakf1600 -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BlackBoxFuncCall::Keccakf1600 obj; - obj.inputs = - serde::Deserializable::deserialize(deserializer); - obj.outputs = - serde::Deserializable::deserialize(deserializer); - return obj; +Program::BlackBoxFuncCall::Keccak256VariableLength serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::Keccak256VariableLength obj; + obj.inputs = serde::Deserializable::deserialize(deserializer); + obj.var_message_size = serde::Deserializable::deserialize(deserializer); + obj.outputs = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -inline bool operator==(const BlackBoxFuncCall::RecursiveAggregation &lhs, - const BlackBoxFuncCall::RecursiveAggregation &rhs) { - if (!(lhs.verification_key == rhs.verification_key)) { - return false; - } - if (!(lhs.proof == rhs.proof)) { - return false; - } - if (!(lhs.public_inputs == rhs.public_inputs)) { - return false; - } - if (!(lhs.key_hash == rhs.key_hash)) { - return false; - } - return true; -} + inline bool operator==(const BlackBoxFuncCall::Keccakf1600 &lhs, const BlackBoxFuncCall::Keccakf1600 &rhs) { + if (!(lhs.inputs == rhs.inputs)) { return false; } + if (!(lhs.outputs == rhs.outputs)) { return false; } + return true; + } -inline std::vector -BlackBoxFuncCall::RecursiveAggregation::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize( - *this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BlackBoxFuncCall::Keccakf1600::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BlackBoxFuncCall::RecursiveAggregation -BlackBoxFuncCall::RecursiveAggregation::bincodeDeserialize( - std::vector input) { - auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable< - BlackBoxFuncCall::RecursiveAggregation>::deserialize(deserializer); - if (deserializer.get_buffer_offset() < input.size()) { - throw serde::deserialization_error("Some input bytes were not read"); - } - return value; -} + inline BlackBoxFuncCall::Keccakf1600 BlackBoxFuncCall::Keccakf1600::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable:: - serialize(const Program::BlackBoxFuncCall::RecursiveAggregation &obj, - Serializer &serializer) { - serde::Serializable::serialize( - obj.verification_key, serializer); - serde::Serializable::serialize(obj.proof, serializer); - serde::Serializable::serialize(obj.public_inputs, - serializer); - serde::Serializable::serialize(obj.key_hash, - serializer); +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::Keccakf1600 &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.inputs, serializer); + serde::Serializable::serialize(obj.outputs, serializer); } template <> template -Program::BlackBoxFuncCall::RecursiveAggregation -serde::Deserializable:: - deserialize(Deserializer &deserializer) { - Program::BlackBoxFuncCall::RecursiveAggregation obj; - obj.verification_key = - serde::Deserializable::deserialize( - deserializer); - obj.proof = - serde::Deserializable::deserialize(deserializer); - obj.public_inputs = - serde::Deserializable::deserialize( - deserializer); - obj.key_hash = - serde::Deserializable::deserialize(deserializer); - return obj; +Program::BlackBoxFuncCall::Keccakf1600 serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::Keccakf1600 obj; + obj.inputs = serde::Deserializable::deserialize(deserializer); + obj.outputs = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -inline bool operator==(const BlackBoxFuncCall::BigIntAdd &lhs, - const BlackBoxFuncCall::BigIntAdd &rhs) { - if (!(lhs.lhs == rhs.lhs)) { - return false; - } - if (!(lhs.rhs == rhs.rhs)) { - return false; - } - if (!(lhs.output == rhs.output)) { - return false; - } - return true; -} + inline bool operator==(const BlackBoxFuncCall::RecursiveAggregation &lhs, const BlackBoxFuncCall::RecursiveAggregation &rhs) { + if (!(lhs.verification_key == rhs.verification_key)) { return false; } + if (!(lhs.proof == rhs.proof)) { return false; } + if (!(lhs.public_inputs == rhs.public_inputs)) { return false; } + if (!(lhs.key_hash == rhs.key_hash)) { return false; } + return true; + } -inline std::vector -BlackBoxFuncCall::BigIntAdd::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, - serializer); - return std::move(serializer).bytes(); -} + inline std::vector BlackBoxFuncCall::RecursiveAggregation::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; -} + inline BlackBoxFuncCall::RecursiveAggregation BlackBoxFuncCall::RecursiveAggregation::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BlackBoxFuncCall::BigIntAdd &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.lhs, serializer); - serde::Serializable::serialize(obj.rhs, serializer); - serde::Serializable::serialize(obj.output, serializer); +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::RecursiveAggregation &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.verification_key, serializer); + serde::Serializable::serialize(obj.proof, serializer); + serde::Serializable::serialize(obj.public_inputs, serializer); + serde::Serializable::serialize(obj.key_hash, serializer); } template <> template -Program::BlackBoxFuncCall::BigIntAdd -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BlackBoxFuncCall::BigIntAdd obj; - obj.lhs = serde::Deserializable::deserialize(deserializer); - obj.rhs = serde::Deserializable::deserialize(deserializer); - obj.output = - serde::Deserializable::deserialize(deserializer); - return obj; +Program::BlackBoxFuncCall::RecursiveAggregation serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::RecursiveAggregation obj; + obj.verification_key = serde::Deserializable::deserialize(deserializer); + obj.proof = serde::Deserializable::deserialize(deserializer); + obj.public_inputs = serde::Deserializable::deserialize(deserializer); + obj.key_hash = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -inline bool operator==(const BlackBoxFuncCall::BigIntSub &lhs, - const BlackBoxFuncCall::BigIntSub &rhs) { - if (!(lhs.lhs == rhs.lhs)) { - return false; - } - if (!(lhs.rhs == rhs.rhs)) { - return false; - } - if (!(lhs.output == rhs.output)) { - return false; - } - return true; -} + inline bool operator==(const BlackBoxFuncCall::BigIntAdd &lhs, const BlackBoxFuncCall::BigIntAdd &rhs) { + if (!(lhs.lhs == rhs.lhs)) { return false; } + if (!(lhs.rhs == rhs.rhs)) { return false; } + if (!(lhs.output == rhs.output)) { return false; } + return true; + } -inline std::vector -BlackBoxFuncCall::BigIntSub::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, - serializer); - return std::move(serializer).bytes(); -} + inline std::vector BlackBoxFuncCall::BigIntAdd::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BlackBoxFuncCall::BigIntSub -BlackBoxFuncCall::BigIntSub::bincodeDeserialize(std::vector input) { - auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize( - deserializer); - if (deserializer.get_buffer_offset() < input.size()) { - throw serde::deserialization_error("Some input bytes were not read"); - } - return value; -} + 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 Program template <> template -void serde::Serializable::serialize( - const Program::BlackBoxFuncCall::BigIntSub &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.lhs, serializer); - serde::Serializable::serialize(obj.rhs, serializer); - serde::Serializable::serialize(obj.output, serializer); +void serde::Serializable::serialize(const Program::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 -Program::BlackBoxFuncCall::BigIntSub -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BlackBoxFuncCall::BigIntSub obj; - obj.lhs = serde::Deserializable::deserialize(deserializer); - obj.rhs = serde::Deserializable::deserialize(deserializer); - obj.output = - serde::Deserializable::deserialize(deserializer); - return obj; +Program::BlackBoxFuncCall::BigIntAdd serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::BigIntAdd obj; + obj.lhs = serde::Deserializable::deserialize(deserializer); + obj.rhs = serde::Deserializable::deserialize(deserializer); + obj.output = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -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 bool operator==(const BlackBoxFuncCall::BigIntSub &lhs, const BlackBoxFuncCall::BigIntSub &rhs) { + if (!(lhs.lhs == rhs.lhs)) { return false; } + if (!(lhs.rhs == rhs.rhs)) { return false; } + if (!(lhs.output == rhs.output)) { return false; } + return true; + } -inline std::vector -BlackBoxFuncCall::BigIntMul::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, - serializer); - return std::move(serializer).bytes(); -} + inline std::vector BlackBoxFuncCall::BigIntSub::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; -} + inline BlackBoxFuncCall::BigIntSub BlackBoxFuncCall::BigIntSub::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BlackBoxFuncCall::BigIntMul &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.lhs, serializer); - serde::Serializable::serialize(obj.rhs, serializer); - serde::Serializable::serialize(obj.output, serializer); +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::BigIntSub &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.lhs, serializer); + serde::Serializable::serialize(obj.rhs, serializer); + serde::Serializable::serialize(obj.output, serializer); } template <> template -Program::BlackBoxFuncCall::BigIntMul -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BlackBoxFuncCall::BigIntMul obj; - obj.lhs = serde::Deserializable::deserialize(deserializer); - obj.rhs = serde::Deserializable::deserialize(deserializer); - obj.output = - serde::Deserializable::deserialize(deserializer); - return obj; +Program::BlackBoxFuncCall::BigIntSub serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::BigIntSub obj; + obj.lhs = serde::Deserializable::deserialize(deserializer); + obj.rhs = serde::Deserializable::deserialize(deserializer); + obj.output = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -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 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::BigIntDiv::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, - serializer); - return std::move(serializer).bytes(); -} + inline std::vector BlackBoxFuncCall::BigIntMul::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; -} + 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 Program template <> template -void serde::Serializable::serialize( - const Program::BlackBoxFuncCall::BigIntDiv &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.lhs, serializer); - serde::Serializable::serialize(obj.rhs, serializer); - serde::Serializable::serialize(obj.output, serializer); +void serde::Serializable::serialize(const Program::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 -Program::BlackBoxFuncCall::BigIntDiv -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BlackBoxFuncCall::BigIntDiv obj; - obj.lhs = serde::Deserializable::deserialize(deserializer); - obj.rhs = serde::Deserializable::deserialize(deserializer); - obj.output = - serde::Deserializable::deserialize(deserializer); - return obj; +Program::BlackBoxFuncCall::BigIntMul serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::BigIntMul obj; + obj.lhs = serde::Deserializable::deserialize(deserializer); + obj.rhs = serde::Deserializable::deserialize(deserializer); + obj.output = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -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 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::BigIntFromLeBytes::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize( - *this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BlackBoxFuncCall::BigIntDiv::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; -} + 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 Program template <> template -void serde::Serializable:: - serialize(const Program::BlackBoxFuncCall::BigIntFromLeBytes &obj, - Serializer &serializer) { - serde::Serializable::serialize(obj.inputs, serializer); - serde::Serializable::serialize(obj.modulus, - serializer); - serde::Serializable::serialize(obj.output, serializer); +void serde::Serializable::serialize(const Program::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 -Program::BlackBoxFuncCall::BigIntFromLeBytes -serde::Deserializable:: - deserialize(Deserializer &deserializer) { - Program::BlackBoxFuncCall::BigIntFromLeBytes obj; - obj.inputs = - serde::Deserializable::deserialize(deserializer); - obj.modulus = - serde::Deserializable::deserialize(deserializer); - obj.output = - serde::Deserializable::deserialize(deserializer); - return obj; +Program::BlackBoxFuncCall::BigIntDiv serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::BigIntDiv obj; + obj.lhs = serde::Deserializable::deserialize(deserializer); + obj.rhs = serde::Deserializable::deserialize(deserializer); + obj.output = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -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 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::BigIntToLeBytes::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, - serializer); - return std::move(serializer).bytes(); -} + inline std::vector BlackBoxFuncCall::BigIntFromLeBytes::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; -} + 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 Program template <> template -void serde::Serializable::serialize( - const Program::BlackBoxFuncCall::BigIntToLeBytes &obj, - Serializer &serializer) { - serde::Serializable::serialize(obj.input, serializer); - serde::Serializable::serialize(obj.outputs, - serializer); +void serde::Serializable::serialize(const Program::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 -Program::BlackBoxFuncCall::BigIntToLeBytes -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BlackBoxFuncCall::BigIntToLeBytes obj; - obj.input = - serde::Deserializable::deserialize(deserializer); - obj.outputs = - serde::Deserializable::deserialize(deserializer); - return obj; +Program::BlackBoxFuncCall::BigIntFromLeBytes serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::BigIntFromLeBytes obj; + obj.inputs = serde::Deserializable::deserialize(deserializer); + obj.modulus = serde::Deserializable::deserialize(deserializer); + obj.output = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -inline bool operator==(const BlackBoxFuncCall::Poseidon2Permutation &lhs, - const BlackBoxFuncCall::Poseidon2Permutation &rhs) { - if (!(lhs.inputs == rhs.inputs)) { - return false; - } - if (!(lhs.outputs == rhs.outputs)) { - return false; - } - if (!(lhs.len == rhs.len)) { - return false; - } - return true; -} + inline 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::Poseidon2Permutation::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize( - *this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BlackBoxFuncCall::BigIntToLeBytes::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BlackBoxFuncCall::Poseidon2Permutation -BlackBoxFuncCall::Poseidon2Permutation::bincodeDeserialize( - std::vector input) { - auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable< - BlackBoxFuncCall::Poseidon2Permutation>::deserialize(deserializer); - if (deserializer.get_buffer_offset() < input.size()) { - throw serde::deserialization_error("Some input bytes were not read"); - } - return value; -} + 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 Program template <> template -void serde::Serializable:: - serialize(const Program::BlackBoxFuncCall::Poseidon2Permutation &obj, - Serializer &serializer) { - serde::Serializable::serialize(obj.inputs, serializer); - serde::Serializable::serialize(obj.outputs, - serializer); - serde::Serializable::serialize(obj.len, serializer); +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::BigIntToLeBytes &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.input, serializer); + serde::Serializable::serialize(obj.outputs, serializer); } template <> template -Program::BlackBoxFuncCall::Poseidon2Permutation -serde::Deserializable:: - deserialize(Deserializer &deserializer) { - Program::BlackBoxFuncCall::Poseidon2Permutation obj; - obj.inputs = - serde::Deserializable::deserialize(deserializer); - obj.outputs = - serde::Deserializable::deserialize(deserializer); - obj.len = serde::Deserializable::deserialize(deserializer); - return obj; +Program::BlackBoxFuncCall::BigIntToLeBytes serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::BigIntToLeBytes obj; + obj.input = serde::Deserializable::deserialize(deserializer); + obj.outputs = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -inline bool operator==(const BlackBoxFuncCall::Sha256Compression &lhs, - const BlackBoxFuncCall::Sha256Compression &rhs) { - if (!(lhs.inputs == rhs.inputs)) { - return false; - } - if (!(lhs.hash_values == rhs.hash_values)) { - return false; - } - if (!(lhs.outputs == rhs.outputs)) { - return false; - } - return true; -} + inline bool operator==(const BlackBoxFuncCall::Poseidon2Permutation &lhs, const BlackBoxFuncCall::Poseidon2Permutation &rhs) { + if (!(lhs.inputs == rhs.inputs)) { return false; } + if (!(lhs.outputs == rhs.outputs)) { return false; } + if (!(lhs.len == rhs.len)) { return false; } + return true; + } -inline std::vector -BlackBoxFuncCall::Sha256Compression::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize( - *this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BlackBoxFuncCall::Poseidon2Permutation::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BlackBoxFuncCall::Sha256Compression -BlackBoxFuncCall::Sha256Compression::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; -} + inline BlackBoxFuncCall::Poseidon2Permutation BlackBoxFuncCall::Poseidon2Permutation::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable:: - serialize(const Program::BlackBoxFuncCall::Sha256Compression &obj, - Serializer &serializer) { - serde::Serializable::serialize(obj.inputs, serializer); - serde::Serializable::serialize(obj.hash_values, - serializer); - serde::Serializable::serialize(obj.outputs, - serializer); +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::Poseidon2Permutation &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.inputs, serializer); + serde::Serializable::serialize(obj.outputs, serializer); + serde::Serializable::serialize(obj.len, serializer); } template <> template -Program::BlackBoxFuncCall::Sha256Compression -serde::Deserializable:: - deserialize(Deserializer &deserializer) { - Program::BlackBoxFuncCall::Sha256Compression obj; - obj.inputs = - serde::Deserializable::deserialize(deserializer); - obj.hash_values = - serde::Deserializable::deserialize( - deserializer); - obj.outputs = - serde::Deserializable::deserialize(deserializer); - return obj; +Program::BlackBoxFuncCall::Poseidon2Permutation serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::Poseidon2Permutation obj; + obj.inputs = serde::Deserializable::deserialize(deserializer); + obj.outputs = serde::Deserializable::deserialize(deserializer); + obj.len = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -inline bool operator==(const BlackBoxOp &lhs, const BlackBoxOp &rhs) { - if (!(lhs.value == rhs.value)) { - return false; - } - return true; -} + inline bool operator==(const BlackBoxFuncCall::Sha256Compression &lhs, const BlackBoxFuncCall::Sha256Compression &rhs) { + if (!(lhs.inputs == rhs.inputs)) { return false; } + if (!(lhs.hash_values == rhs.hash_values)) { return false; } + if (!(lhs.outputs == rhs.outputs)) { return false; } + return true; + } -inline std::vector BlackBoxOp::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BlackBoxFuncCall::Sha256Compression::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BlackBoxOp BlackBoxOp::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; -} + inline BlackBoxFuncCall::Sha256Compression BlackBoxFuncCall::Sha256Compression::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BlackBoxOp &obj, Serializer &serializer) { - serializer.increase_container_depth(); - serde::Serializable::serialize(obj.value, serializer); - serializer.decrease_container_depth(); +void serde::Serializable::serialize(const Program::BlackBoxFuncCall::Sha256Compression &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.inputs, serializer); + serde::Serializable::serialize(obj.hash_values, serializer); + serde::Serializable::serialize(obj.outputs, serializer); } template <> template -Program::BlackBoxOp serde::Deserializable::deserialize( - Deserializer &deserializer) { - deserializer.increase_container_depth(); - Program::BlackBoxOp obj; - obj.value = - serde::Deserializable::deserialize(deserializer); - deserializer.decrease_container_depth(); - return obj; +Program::BlackBoxFuncCall::Sha256Compression serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxFuncCall::Sha256Compression obj; + obj.inputs = serde::Deserializable::deserialize(deserializer); + obj.hash_values = serde::Deserializable::deserialize(deserializer); + obj.outputs = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -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 bool operator==(const BlackBoxOp &lhs, const BlackBoxOp &rhs) { + if (!(lhs.value == rhs.value)) { 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 std::vector BlackBoxOp::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 serde::deserialization_error("Some input bytes were not read"); - } - return value; -} + inline BlackBoxOp BlackBoxOp::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BlackBoxOp::Sha256 &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.message, - serializer); - serde::Serializable::serialize(obj.output, serializer); +void serde::Serializable::serialize(const Program::BlackBoxOp &obj, Serializer &serializer) { + serializer.increase_container_depth(); + serde::Serializable::serialize(obj.value, serializer); + serializer.decrease_container_depth(); } template <> template -Program::BlackBoxOp::Sha256 -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BlackBoxOp::Sha256 obj; - obj.message = - serde::Deserializable::deserialize(deserializer); - obj.output = - serde::Deserializable::deserialize(deserializer); - return obj; +Program::BlackBoxOp serde::Deserializable::deserialize(Deserializer &deserializer) { + deserializer.increase_container_depth(); + Program::BlackBoxOp obj; + obj.value = serde::Deserializable::deserialize(deserializer); + deserializer.decrease_container_depth(); + return obj; } namespace Program { -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 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::Blake2s::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BlackBoxOp::Sha256::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 serde::deserialization_error("Some input bytes were not read"); - } - return value; -} + 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 serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BlackBoxOp::Blake2s &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.message, - serializer); - serde::Serializable::serialize(obj.output, serializer); +void serde::Serializable::serialize(const Program::BlackBoxOp::Sha256 &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.message, serializer); + serde::Serializable::serialize(obj.output, serializer); } template <> template -Program::BlackBoxOp::Blake2s -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BlackBoxOp::Blake2s obj; - obj.message = - serde::Deserializable::deserialize(deserializer); - obj.output = - serde::Deserializable::deserialize(deserializer); - return obj; +Program::BlackBoxOp::Sha256 serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxOp::Sha256 obj; + obj.message = serde::Deserializable::deserialize(deserializer); + obj.output = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -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 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::Blake3::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BlackBoxOp::Blake2s::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 serde::deserialization_error("Some input bytes were not read"); - } - return value; -} + 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 serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BlackBoxOp::Blake3 &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.message, - serializer); - serde::Serializable::serialize(obj.output, serializer); +void serde::Serializable::serialize(const Program::BlackBoxOp::Blake2s &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.message, serializer); + serde::Serializable::serialize(obj.output, serializer); } template <> template -Program::BlackBoxOp::Blake3 -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BlackBoxOp::Blake3 obj; - obj.message = - serde::Deserializable::deserialize(deserializer); - obj.output = - serde::Deserializable::deserialize(deserializer); - return obj; +Program::BlackBoxOp::Blake2s serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxOp::Blake2s obj; + obj.message = serde::Deserializable::deserialize(deserializer); + obj.output = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -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 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::Keccak256::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BlackBoxOp::Blake3::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 serde::deserialization_error("Some input bytes were not read"); - } - return value; -} + 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 serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BlackBoxOp::Keccak256 &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.message, - serializer); - serde::Serializable::serialize(obj.output, serializer); +void serde::Serializable::serialize(const Program::BlackBoxOp::Blake3 &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.message, serializer); + serde::Serializable::serialize(obj.output, serializer); } template <> template -Program::BlackBoxOp::Keccak256 -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BlackBoxOp::Keccak256 obj; - obj.message = - serde::Deserializable::deserialize(deserializer); - obj.output = - serde::Deserializable::deserialize(deserializer); - return obj; +Program::BlackBoxOp::Blake3 serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxOp::Blake3 obj; + obj.message = serde::Deserializable::deserialize(deserializer); + obj.output = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -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 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::Keccakf1600::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BlackBoxOp::Keccak256::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 serde::deserialization_error("Some input bytes were not read"); - } - return value; -} + 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 serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BlackBoxOp::Keccakf1600 &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.message, - serializer); - serde::Serializable::serialize(obj.output, serializer); +void serde::Serializable::serialize(const Program::BlackBoxOp::Keccak256 &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.message, serializer); + serde::Serializable::serialize(obj.output, serializer); } template <> template -Program::BlackBoxOp::Keccakf1600 -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BlackBoxOp::Keccakf1600 obj; - obj.message = - serde::Deserializable::deserialize(deserializer); - obj.output = - serde::Deserializable::deserialize(deserializer); - return obj; +Program::BlackBoxOp::Keccak256 serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxOp::Keccak256 obj; + obj.message = serde::Deserializable::deserialize(deserializer); + obj.output = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -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 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::EcdsaSecp256k1::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BlackBoxOp::Keccakf1600::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 serde::deserialization_error("Some input bytes were not read"); - } - return value; -} + 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 serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::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); +void serde::Serializable::serialize(const Program::BlackBoxOp::Keccakf1600 &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.message, serializer); + serde::Serializable::serialize(obj.output, serializer); } template <> template -Program::BlackBoxOp::EcdsaSecp256k1 -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::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 Program { - -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 serde::deserialization_error("Some input bytes were not read"); - } - return value; +Program::BlackBoxOp::Keccakf1600 serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxOp::Keccakf1600 obj; + obj.message = serde::Deserializable::deserialize(deserializer); + obj.output = serde::Deserializable::deserialize(deserializer); + return obj; } +namespace Program { + + 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 serde::deserialization_error("Some input bytes were not read"); + } + return value; + } + } // end of namespace Program template <> -template -void serde::Serializable::serialize( - const Program::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 +void serde::Serializable::serialize(const Program::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 -Program::BlackBoxOp::EcdsaSecp256r1 -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::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 Program { - -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(); +Program::BlackBoxOp::EcdsaSecp256k1 serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::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; } -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 serde::deserialization_error("Some input bytes were not read"); - } - return value; -} +namespace Program { + + 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 serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::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); +void serde::Serializable::serialize(const Program::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 -Program::BlackBoxOp::SchnorrVerify -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::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; +Program::BlackBoxOp::EcdsaSecp256r1 serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::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 Program { -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 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::PedersenCommitment::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, - serializer); - return std::move(serializer).bytes(); -} + inline std::vector BlackBoxOp::SchnorrVerify::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 serde::deserialization_error("Some input bytes were not read"); - } - return value; -} + 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 serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BlackBoxOp::PedersenCommitment &obj, - Serializer &serializer) { - serde::Serializable::serialize(obj.inputs, serializer); - serde::Serializable::serialize( - obj.domain_separator, serializer); - serde::Serializable::serialize(obj.output, serializer); +void serde::Serializable::serialize(const Program::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 -Program::BlackBoxOp::PedersenCommitment -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BlackBoxOp::PedersenCommitment obj; - obj.inputs = - serde::Deserializable::deserialize(deserializer); - obj.domain_separator = - serde::Deserializable::deserialize( - deserializer); - obj.output = - serde::Deserializable::deserialize(deserializer); - return obj; +Program::BlackBoxOp::SchnorrVerify serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::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 Program { -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 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::PedersenHash::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BlackBoxOp::PedersenCommitment::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 serde::deserialization_error("Some input bytes were not read"); - } - return value; -} + 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 serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BlackBoxOp::PedersenHash &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.inputs, serializer); - serde::Serializable::serialize( - obj.domain_separator, serializer); - serde::Serializable::serialize(obj.output, serializer); +void serde::Serializable::serialize(const Program::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 -Program::BlackBoxOp::PedersenHash -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BlackBoxOp::PedersenHash obj; - obj.inputs = - serde::Deserializable::deserialize(deserializer); - obj.domain_separator = - serde::Deserializable::deserialize( - deserializer); - obj.output = - serde::Deserializable::deserialize(deserializer); - return obj; +Program::BlackBoxOp::PedersenCommitment serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::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 Program { -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 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::FixedBaseScalarMul::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, - serializer); - return std::move(serializer).bytes(); -} + inline std::vector BlackBoxOp::PedersenHash::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 serde::deserialization_error("Some input bytes were not read"); - } - return value; -} + 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 serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BlackBoxOp::FixedBaseScalarMul &obj, - Serializer &serializer) { - serde::Serializable::serialize(obj.low, serializer); - serde::Serializable::serialize(obj.high, serializer); - serde::Serializable::serialize(obj.result, serializer); +void serde::Serializable::serialize(const Program::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 -Program::BlackBoxOp::FixedBaseScalarMul -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BlackBoxOp::FixedBaseScalarMul obj; - obj.low = serde::Deserializable::deserialize(deserializer); - obj.high = - serde::Deserializable::deserialize(deserializer); - obj.result = - serde::Deserializable::deserialize(deserializer); - return obj; +Program::BlackBoxOp::PedersenHash serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::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 Program { -inline bool operator==(const BlackBoxOp::EmbeddedCurveAdd &lhs, - const BlackBoxOp::EmbeddedCurveAdd &rhs) { - if (!(lhs.input1_x == rhs.input1_x)) { - return false; - } - if (!(lhs.input1_y == rhs.input1_y)) { - return false; - } - if (!(lhs.input2_x == rhs.input2_x)) { - return false; - } - if (!(lhs.input2_y == rhs.input2_y)) { - return false; - } - if (!(lhs.result == rhs.result)) { - return false; - } - return true; -} + 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::EmbeddedCurveAdd::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, - serializer); - return std::move(serializer).bytes(); -} + inline std::vector BlackBoxOp::FixedBaseScalarMul::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BlackBoxOp::EmbeddedCurveAdd -BlackBoxOp::EmbeddedCurveAdd::bincodeDeserialize(std::vector input) { - auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize( - deserializer); - if (deserializer.get_buffer_offset() < input.size()) { - throw serde::deserialization_error("Some input bytes were not read"); - } - return value; -} + 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 serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BlackBoxOp::EmbeddedCurveAdd &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); +void serde::Serializable::serialize(const Program::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 -Program::BlackBoxOp::EmbeddedCurveAdd -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::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; +Program::BlackBoxOp::FixedBaseScalarMul serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxOp::FixedBaseScalarMul obj; + obj.low = serde::Deserializable::deserialize(deserializer); + obj.high = serde::Deserializable::deserialize(deserializer); + obj.result = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -inline bool operator==(const BlackBoxOp::BigIntAdd &lhs, - const BlackBoxOp::BigIntAdd &rhs) { - if (!(lhs.lhs == rhs.lhs)) { - return false; - } - if (!(lhs.rhs == rhs.rhs)) { - return false; - } - if (!(lhs.output == rhs.output)) { - return false; - } - return true; -} + inline bool operator==(const BlackBoxOp::EmbeddedCurveAdd &lhs, const BlackBoxOp::EmbeddedCurveAdd &rhs) { + if (!(lhs.input1_x == rhs.input1_x)) { return false; } + if (!(lhs.input1_y == rhs.input1_y)) { return false; } + if (!(lhs.input2_x == rhs.input2_x)) { return false; } + if (!(lhs.input2_y == rhs.input2_y)) { return false; } + if (!(lhs.result == rhs.result)) { return false; } + return true; + } -inline std::vector BlackBoxOp::BigIntAdd::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BlackBoxOp::EmbeddedCurveAdd::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; -} + inline BlackBoxOp::EmbeddedCurveAdd BlackBoxOp::EmbeddedCurveAdd::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BlackBoxOp::BigIntAdd &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.lhs, serializer); - serde::Serializable::serialize(obj.rhs, serializer); - serde::Serializable::serialize(obj.output, serializer); +void serde::Serializable::serialize(const Program::BlackBoxOp::EmbeddedCurveAdd &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); } template <> template -Program::BlackBoxOp::BigIntAdd -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BlackBoxOp::BigIntAdd obj; - obj.lhs = serde::Deserializable::deserialize(deserializer); - obj.rhs = serde::Deserializable::deserialize(deserializer); - obj.output = - serde::Deserializable::deserialize(deserializer); - return obj; +Program::BlackBoxOp::EmbeddedCurveAdd serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::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 Program { -inline bool operator==(const BlackBoxOp::BigIntSub &lhs, - const BlackBoxOp::BigIntSub &rhs) { - if (!(lhs.lhs == rhs.lhs)) { - return false; - } - if (!(lhs.rhs == rhs.rhs)) { - return false; - } - if (!(lhs.output == rhs.output)) { - return false; - } - return true; -} + inline bool operator==(const BlackBoxOp::BigIntAdd &lhs, const BlackBoxOp::BigIntAdd &rhs) { + if (!(lhs.lhs == rhs.lhs)) { return false; } + if (!(lhs.rhs == rhs.rhs)) { return false; } + if (!(lhs.output == rhs.output)) { return false; } + return true; + } -inline std::vector BlackBoxOp::BigIntSub::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BlackBoxOp::BigIntAdd::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BlackBoxOp::BigIntSub -BlackBoxOp::BigIntSub::bincodeDeserialize(std::vector input) { - auto deserializer = serde::BincodeDeserializer(input); - auto value = - serde::Deserializable::deserialize(deserializer); - if (deserializer.get_buffer_offset() < input.size()) { - throw serde::deserialization_error("Some input bytes were not read"); - } - return value; -} + 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 Program template <> template -void serde::Serializable::serialize( - const Program::BlackBoxOp::BigIntSub &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.lhs, serializer); - serde::Serializable::serialize(obj.rhs, serializer); - serde::Serializable::serialize(obj.output, serializer); +void serde::Serializable::serialize(const Program::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 -Program::BlackBoxOp::BigIntSub -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BlackBoxOp::BigIntSub obj; - obj.lhs = serde::Deserializable::deserialize(deserializer); - obj.rhs = serde::Deserializable::deserialize(deserializer); - obj.output = - serde::Deserializable::deserialize(deserializer); - return obj; +Program::BlackBoxOp::BigIntAdd serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxOp::BigIntAdd obj; + obj.lhs = serde::Deserializable::deserialize(deserializer); + obj.rhs = serde::Deserializable::deserialize(deserializer); + obj.output = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -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 bool operator==(const BlackBoxOp::BigIntSub &lhs, const BlackBoxOp::BigIntSub &rhs) { + if (!(lhs.lhs == rhs.lhs)) { return false; } + if (!(lhs.rhs == rhs.rhs)) { return false; } + if (!(lhs.output == rhs.output)) { return false; } + return true; + } -inline std::vector BlackBoxOp::BigIntMul::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BlackBoxOp::BigIntSub::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; -} + inline BlackBoxOp::BigIntSub BlackBoxOp::BigIntSub::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BlackBoxOp::BigIntMul &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.lhs, serializer); - serde::Serializable::serialize(obj.rhs, serializer); - serde::Serializable::serialize(obj.output, serializer); +void serde::Serializable::serialize(const Program::BlackBoxOp::BigIntSub &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.lhs, serializer); + serde::Serializable::serialize(obj.rhs, serializer); + serde::Serializable::serialize(obj.output, serializer); } template <> template -Program::BlackBoxOp::BigIntMul -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BlackBoxOp::BigIntMul obj; - obj.lhs = serde::Deserializable::deserialize(deserializer); - obj.rhs = serde::Deserializable::deserialize(deserializer); - obj.output = - serde::Deserializable::deserialize(deserializer); - return obj; +Program::BlackBoxOp::BigIntSub serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxOp::BigIntSub obj; + obj.lhs = serde::Deserializable::deserialize(deserializer); + obj.rhs = serde::Deserializable::deserialize(deserializer); + obj.output = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -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 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::BigIntDiv::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BlackBoxOp::BigIntMul::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; -} + 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 Program template <> template -void serde::Serializable::serialize( - const Program::BlackBoxOp::BigIntDiv &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.lhs, serializer); - serde::Serializable::serialize(obj.rhs, serializer); - serde::Serializable::serialize(obj.output, serializer); +void serde::Serializable::serialize(const Program::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 -Program::BlackBoxOp::BigIntDiv -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BlackBoxOp::BigIntDiv obj; - obj.lhs = serde::Deserializable::deserialize(deserializer); - obj.rhs = serde::Deserializable::deserialize(deserializer); - obj.output = - serde::Deserializable::deserialize(deserializer); - return obj; +Program::BlackBoxOp::BigIntMul serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxOp::BigIntMul obj; + obj.lhs = serde::Deserializable::deserialize(deserializer); + obj.rhs = serde::Deserializable::deserialize(deserializer); + obj.output = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -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 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::BigIntFromLeBytes::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, - serializer); - return std::move(serializer).bytes(); -} + inline std::vector BlackBoxOp::BigIntDiv::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; -} + 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 Program template <> template -void serde::Serializable::serialize( - const Program::BlackBoxOp::BigIntFromLeBytes &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.inputs, serializer); - serde::Serializable::serialize(obj.modulus, - serializer); - serde::Serializable::serialize(obj.output, serializer); +void serde::Serializable::serialize(const Program::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 -Program::BlackBoxOp::BigIntFromLeBytes -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BlackBoxOp::BigIntFromLeBytes obj; - obj.inputs = - serde::Deserializable::deserialize(deserializer); - obj.modulus = - serde::Deserializable::deserialize(deserializer); - obj.output = - serde::Deserializable::deserialize(deserializer); - return obj; +Program::BlackBoxOp::BigIntDiv serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxOp::BigIntDiv obj; + obj.lhs = serde::Deserializable::deserialize(deserializer); + obj.rhs = serde::Deserializable::deserialize(deserializer); + obj.output = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -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 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::BigIntToLeBytes::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, - serializer); - return std::move(serializer).bytes(); -} + inline std::vector BlackBoxOp::BigIntFromLeBytes::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; -} + 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 Program template <> template -void serde::Serializable::serialize( - const Program::BlackBoxOp::BigIntToLeBytes &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.input, serializer); - serde::Serializable::serialize(obj.output, serializer); +void serde::Serializable::serialize(const Program::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 -Program::BlackBoxOp::BigIntToLeBytes -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BlackBoxOp::BigIntToLeBytes obj; - obj.input = - serde::Deserializable::deserialize(deserializer); - obj.output = - serde::Deserializable::deserialize(deserializer); - return obj; +Program::BlackBoxOp::BigIntFromLeBytes serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxOp::BigIntFromLeBytes obj; + obj.inputs = serde::Deserializable::deserialize(deserializer); + obj.modulus = serde::Deserializable::deserialize(deserializer); + obj.output = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -inline bool operator==(const BlackBoxOp::Poseidon2Permutation &lhs, - const BlackBoxOp::Poseidon2Permutation &rhs) { - if (!(lhs.message == rhs.message)) { - return false; - } - if (!(lhs.output == rhs.output)) { - return false; - } - if (!(lhs.len == rhs.len)) { - return false; - } - return true; -} + 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::Poseidon2Permutation::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, - serializer); - return std::move(serializer).bytes(); -} + inline std::vector BlackBoxOp::BigIntToLeBytes::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BlackBoxOp::Poseidon2Permutation -BlackBoxOp::Poseidon2Permutation::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; -} + 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 Program template <> template -void serde::Serializable::serialize( - const Program::BlackBoxOp::Poseidon2Permutation &obj, - Serializer &serializer) { - serde::Serializable::serialize(obj.message, - serializer); - serde::Serializable::serialize(obj.output, serializer); - serde::Serializable::serialize(obj.len, serializer); +void serde::Serializable::serialize(const Program::BlackBoxOp::BigIntToLeBytes &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.input, serializer); + serde::Serializable::serialize(obj.output, serializer); } template <> template -Program::BlackBoxOp::Poseidon2Permutation -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BlackBoxOp::Poseidon2Permutation obj; - obj.message = - serde::Deserializable::deserialize(deserializer); - obj.output = - serde::Deserializable::deserialize(deserializer); - obj.len = serde::Deserializable::deserialize(deserializer); - return obj; +Program::BlackBoxOp::BigIntToLeBytes serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxOp::BigIntToLeBytes obj; + obj.input = serde::Deserializable::deserialize(deserializer); + obj.output = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -inline bool operator==(const BlackBoxOp::Sha256Compression &lhs, - const BlackBoxOp::Sha256Compression &rhs) { - if (!(lhs.input == rhs.input)) { - return false; - } - if (!(lhs.hash_values == rhs.hash_values)) { - return false; - } - if (!(lhs.output == rhs.output)) { - return false; - } - return true; -} + inline bool operator==(const BlackBoxOp::Poseidon2Permutation &lhs, const BlackBoxOp::Poseidon2Permutation &rhs) { + if (!(lhs.message == rhs.message)) { return false; } + if (!(lhs.output == rhs.output)) { return false; } + if (!(lhs.len == rhs.len)) { return false; } + return true; + } -inline std::vector -BlackBoxOp::Sha256Compression::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, - serializer); - return std::move(serializer).bytes(); -} + inline std::vector BlackBoxOp::Poseidon2Permutation::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BlackBoxOp::Sha256Compression -BlackBoxOp::Sha256Compression::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; -} + inline BlackBoxOp::Poseidon2Permutation BlackBoxOp::Poseidon2Permutation::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BlackBoxOp::Sha256Compression &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.input, serializer); - serde::Serializable::serialize(obj.hash_values, - serializer); - serde::Serializable::serialize(obj.output, serializer); +void serde::Serializable::serialize(const Program::BlackBoxOp::Poseidon2Permutation &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.message, serializer); + serde::Serializable::serialize(obj.output, serializer); + serde::Serializable::serialize(obj.len, serializer); } template <> template -Program::BlackBoxOp::Sha256Compression -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BlackBoxOp::Sha256Compression obj; - obj.input = - serde::Deserializable::deserialize(deserializer); - obj.hash_values = - serde::Deserializable::deserialize( - deserializer); - obj.output = - serde::Deserializable::deserialize(deserializer); - return obj; +Program::BlackBoxOp::Poseidon2Permutation serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxOp::Poseidon2Permutation obj; + obj.message = serde::Deserializable::deserialize(deserializer); + obj.output = serde::Deserializable::deserialize(deserializer); + obj.len = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -inline bool operator==(const BlockId &lhs, const BlockId &rhs) { - if (!(lhs.value == rhs.value)) { - return false; - } - return true; -} + inline bool operator==(const BlackBoxOp::Sha256Compression &lhs, const BlackBoxOp::Sha256Compression &rhs) { + if (!(lhs.input == rhs.input)) { return false; } + if (!(lhs.hash_values == rhs.hash_values)) { return false; } + if (!(lhs.output == rhs.output)) { return false; } + return true; + } -inline std::vector BlockId::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BlackBoxOp::Sha256Compression::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BlockId BlockId::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; -} + inline BlackBoxOp::Sha256Compression BlackBoxOp::Sha256Compression::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BlockId &obj, Serializer &serializer) { - serializer.increase_container_depth(); - serde::Serializable::serialize(obj.value, serializer); - serializer.decrease_container_depth(); +void serde::Serializable::serialize(const Program::BlackBoxOp::Sha256Compression &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.input, serializer); + serde::Serializable::serialize(obj.hash_values, serializer); + serde::Serializable::serialize(obj.output, serializer); } template <> template -Program::BlockId serde::Deserializable::deserialize( - Deserializer &deserializer) { - deserializer.increase_container_depth(); - Program::BlockId obj; - obj.value = - serde::Deserializable::deserialize(deserializer); - deserializer.decrease_container_depth(); - return obj; +Program::BlackBoxOp::Sha256Compression serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BlackBoxOp::Sha256Compression obj; + obj.input = serde::Deserializable::deserialize(deserializer); + obj.hash_values = serde::Deserializable::deserialize(deserializer); + obj.output = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -inline bool operator==(const Brillig &lhs, const Brillig &rhs) { - if (!(lhs.inputs == rhs.inputs)) { - return false; - } - if (!(lhs.outputs == rhs.outputs)) { - return false; - } - if (!(lhs.bytecode == rhs.bytecode)) { - return false; - } - if (!(lhs.predicate == rhs.predicate)) { - return false; - } - return true; -} + inline bool operator==(const BlockId &lhs, const BlockId &rhs) { + if (!(lhs.value == rhs.value)) { return false; } + return true; + } -inline std::vector Brillig::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BlockId::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline Brillig Brillig::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; -} + inline BlockId BlockId::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::Brillig &obj, Serializer &serializer) { - serializer.increase_container_depth(); - serde::Serializable::serialize(obj.inputs, serializer); - serde::Serializable::serialize(obj.outputs, - serializer); - serde::Serializable::serialize(obj.bytecode, - serializer); - serde::Serializable::serialize(obj.predicate, - serializer); - serializer.decrease_container_depth(); +void serde::Serializable::serialize(const Program::BlockId &obj, Serializer &serializer) { + serializer.increase_container_depth(); + serde::Serializable::serialize(obj.value, serializer); + serializer.decrease_container_depth(); } template <> template -Program::Brillig serde::Deserializable::deserialize( - Deserializer &deserializer) { - deserializer.increase_container_depth(); - Program::Brillig obj; - obj.inputs = - serde::Deserializable::deserialize(deserializer); - obj.outputs = - serde::Deserializable::deserialize(deserializer); - obj.bytecode = - serde::Deserializable::deserialize(deserializer); - obj.predicate = - serde::Deserializable::deserialize(deserializer); - deserializer.decrease_container_depth(); - return obj; +Program::BlockId serde::Deserializable::deserialize(Deserializer &deserializer) { + deserializer.increase_container_depth(); + Program::BlockId obj; + obj.value = serde::Deserializable::deserialize(deserializer); + deserializer.decrease_container_depth(); + return obj; } namespace Program { -inline bool operator==(const BrilligInputs &lhs, const BrilligInputs &rhs) { - if (!(lhs.value == rhs.value)) { - return false; - } - return true; -} + inline bool operator==(const Brillig &lhs, const Brillig &rhs) { + if (!(lhs.inputs == rhs.inputs)) { return false; } + if (!(lhs.outputs == rhs.outputs)) { return false; } + if (!(lhs.bytecode == rhs.bytecode)) { return false; } + if (!(lhs.predicate == rhs.predicate)) { return false; } + return true; + } -inline std::vector BrilligInputs::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector Brillig::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BrilligInputs -BrilligInputs::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; -} + inline Brillig Brillig::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BrilligInputs &obj, Serializer &serializer) { - serializer.increase_container_depth(); - serde::Serializable::serialize(obj.value, serializer); - serializer.decrease_container_depth(); +void serde::Serializable::serialize(const Program::Brillig &obj, Serializer &serializer) { + serializer.increase_container_depth(); + serde::Serializable::serialize(obj.inputs, serializer); + serde::Serializable::serialize(obj.outputs, serializer); + serde::Serializable::serialize(obj.bytecode, serializer); + serde::Serializable::serialize(obj.predicate, serializer); + serializer.decrease_container_depth(); } template <> template -Program::BrilligInputs -serde::Deserializable::deserialize( - Deserializer &deserializer) { - deserializer.increase_container_depth(); - Program::BrilligInputs obj; - obj.value = - serde::Deserializable::deserialize(deserializer); - deserializer.decrease_container_depth(); - return obj; +Program::Brillig serde::Deserializable::deserialize(Deserializer &deserializer) { + deserializer.increase_container_depth(); + Program::Brillig obj; + obj.inputs = serde::Deserializable::deserialize(deserializer); + obj.outputs = serde::Deserializable::deserialize(deserializer); + obj.bytecode = serde::Deserializable::deserialize(deserializer); + obj.predicate = serde::Deserializable::deserialize(deserializer); + deserializer.decrease_container_depth(); + return obj; } namespace Program { -inline bool operator==(const BrilligInputs::Single &lhs, - const BrilligInputs::Single &rhs) { - if (!(lhs.value == rhs.value)) { - return false; - } - return true; -} + inline bool operator==(const BrilligInputs &lhs, const BrilligInputs &rhs) { + if (!(lhs.value == rhs.value)) { return false; } + return true; + } -inline std::vector BrilligInputs::Single::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BrilligInputs::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BrilligInputs::Single -BrilligInputs::Single::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; -} + inline BrilligInputs BrilligInputs::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BrilligInputs::Single &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.value, serializer); +void serde::Serializable::serialize(const Program::BrilligInputs &obj, Serializer &serializer) { + serializer.increase_container_depth(); + serde::Serializable::serialize(obj.value, serializer); + serializer.decrease_container_depth(); } template <> template -Program::BrilligInputs::Single -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BrilligInputs::Single obj; - obj.value = - serde::Deserializable::deserialize(deserializer); - return obj; +Program::BrilligInputs serde::Deserializable::deserialize(Deserializer &deserializer) { + deserializer.increase_container_depth(); + Program::BrilligInputs obj; + obj.value = serde::Deserializable::deserialize(deserializer); + deserializer.decrease_container_depth(); + return obj; } namespace Program { -inline bool operator==(const BrilligInputs::Array &lhs, - const BrilligInputs::Array &rhs) { - if (!(lhs.value == rhs.value)) { - return false; - } - return true; -} + inline bool operator==(const BrilligInputs::Single &lhs, const BrilligInputs::Single &rhs) { + if (!(lhs.value == rhs.value)) { return false; } + return true; + } -inline std::vector BrilligInputs::Array::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BrilligInputs::Single::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BrilligInputs::Array -BrilligInputs::Array::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; -} + inline BrilligInputs::Single BrilligInputs::Single::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BrilligInputs::Array &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.value, serializer); +void serde::Serializable::serialize(const Program::BrilligInputs::Single &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.value, serializer); } template <> template -Program::BrilligInputs::Array -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BrilligInputs::Array obj; - obj.value = - serde::Deserializable::deserialize(deserializer); - return obj; +Program::BrilligInputs::Single serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligInputs::Single obj; + obj.value = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -inline bool operator==(const BrilligInputs::MemoryArray &lhs, - const BrilligInputs::MemoryArray &rhs) { - if (!(lhs.value == rhs.value)) { - return false; - } - return true; -} + inline bool operator==(const BrilligInputs::Array &lhs, const BrilligInputs::Array &rhs) { + if (!(lhs.value == rhs.value)) { return false; } + return true; + } -inline std::vector -BrilligInputs::MemoryArray::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BrilligInputs::Array::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BrilligInputs::MemoryArray -BrilligInputs::MemoryArray::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; -} + inline BrilligInputs::Array BrilligInputs::Array::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BrilligInputs::MemoryArray &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.value, serializer); +void serde::Serializable::serialize(const Program::BrilligInputs::Array &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.value, serializer); } template <> template -Program::BrilligInputs::MemoryArray -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BrilligInputs::MemoryArray obj; - obj.value = - serde::Deserializable::deserialize(deserializer); - return obj; +Program::BrilligInputs::Array serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligInputs::Array obj; + obj.value = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -inline bool operator==(const BrilligOpcode &lhs, const BrilligOpcode &rhs) { - if (!(lhs.value == rhs.value)) { - return false; - } - return true; -} + inline bool operator==(const BrilligInputs::MemoryArray &lhs, const BrilligInputs::MemoryArray &rhs) { + if (!(lhs.value == rhs.value)) { return false; } + return true; + } -inline std::vector BrilligOpcode::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BrilligInputs::MemoryArray::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BrilligOpcode -BrilligOpcode::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; -} + inline BrilligInputs::MemoryArray BrilligInputs::MemoryArray::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BrilligOpcode &obj, Serializer &serializer) { - serializer.increase_container_depth(); - serde::Serializable::serialize(obj.value, serializer); - serializer.decrease_container_depth(); +void serde::Serializable::serialize(const Program::BrilligInputs::MemoryArray &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.value, serializer); } template <> template -Program::BrilligOpcode -serde::Deserializable::deserialize( - Deserializer &deserializer) { - deserializer.increase_container_depth(); - Program::BrilligOpcode obj; - obj.value = - serde::Deserializable::deserialize(deserializer); - deserializer.decrease_container_depth(); - return obj; +Program::BrilligInputs::MemoryArray serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligInputs::MemoryArray obj; + obj.value = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -inline bool operator==(const BrilligOpcode::BinaryFieldOp &lhs, - const BrilligOpcode::BinaryFieldOp &rhs) { - if (!(lhs.destination == rhs.destination)) { - return false; - } - if (!(lhs.op == rhs.op)) { - return false; - } - if (!(lhs.lhs == rhs.lhs)) { - return false; - } - if (!(lhs.rhs == rhs.rhs)) { - return false; - } - return true; -} + inline bool operator==(const BrilligOpcode &lhs, const BrilligOpcode &rhs) { + if (!(lhs.value == rhs.value)) { return false; } + return true; + } -inline std::vector -BrilligOpcode::BinaryFieldOp::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, - serializer); - return std::move(serializer).bytes(); -} + inline std::vector BrilligOpcode::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BrilligOpcode::BinaryFieldOp -BrilligOpcode::BinaryFieldOp::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; -} + inline BrilligOpcode BrilligOpcode::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BrilligOpcode::BinaryFieldOp &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.destination, - serializer); - serde::Serializable::serialize(obj.op, serializer); - serde::Serializable::serialize(obj.lhs, serializer); - serde::Serializable::serialize(obj.rhs, serializer); +void serde::Serializable::serialize(const Program::BrilligOpcode &obj, Serializer &serializer) { + serializer.increase_container_depth(); + serde::Serializable::serialize(obj.value, serializer); + serializer.decrease_container_depth(); } template <> template -Program::BrilligOpcode::BinaryFieldOp -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BrilligOpcode::BinaryFieldOp obj; - obj.destination = - serde::Deserializable::deserialize( - deserializer); - obj.op = serde::Deserializable::deserialize(deserializer); - obj.lhs = serde::Deserializable::deserialize(deserializer); - obj.rhs = serde::Deserializable::deserialize(deserializer); - return obj; +Program::BrilligOpcode serde::Deserializable::deserialize(Deserializer &deserializer) { + deserializer.increase_container_depth(); + Program::BrilligOpcode obj; + obj.value = serde::Deserializable::deserialize(deserializer); + deserializer.decrease_container_depth(); + return obj; } namespace Program { -inline bool operator==(const BrilligOpcode::BinaryIntOp &lhs, - const BrilligOpcode::BinaryIntOp &rhs) { - if (!(lhs.destination == rhs.destination)) { - return false; - } - if (!(lhs.op == rhs.op)) { - return false; - } - if (!(lhs.bit_size == rhs.bit_size)) { - return false; - } - if (!(lhs.lhs == rhs.lhs)) { - return false; - } - if (!(lhs.rhs == rhs.rhs)) { - return false; - } - return true; -} + inline bool operator==(const BrilligOpcode::BinaryFieldOp &lhs, const BrilligOpcode::BinaryFieldOp &rhs) { + if (!(lhs.destination == rhs.destination)) { return false; } + if (!(lhs.op == rhs.op)) { return false; } + if (!(lhs.lhs == rhs.lhs)) { return false; } + if (!(lhs.rhs == rhs.rhs)) { return false; } + return true; + } -inline std::vector -BrilligOpcode::BinaryIntOp::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BrilligOpcode::BinaryFieldOp::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BrilligOpcode::BinaryIntOp -BrilligOpcode::BinaryIntOp::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; -} + inline BrilligOpcode::BinaryFieldOp BrilligOpcode::BinaryFieldOp::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BrilligOpcode::BinaryIntOp &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.destination, - serializer); - serde::Serializable::serialize(obj.op, serializer); - serde::Serializable::serialize(obj.bit_size, - serializer); - serde::Serializable::serialize(obj.lhs, serializer); - serde::Serializable::serialize(obj.rhs, serializer); +void serde::Serializable::serialize(const Program::BrilligOpcode::BinaryFieldOp &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.destination, serializer); + serde::Serializable::serialize(obj.op, serializer); + serde::Serializable::serialize(obj.lhs, serializer); + serde::Serializable::serialize(obj.rhs, serializer); } template <> template -Program::BrilligOpcode::BinaryIntOp -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BrilligOpcode::BinaryIntOp obj; - obj.destination = - serde::Deserializable::deserialize( - deserializer); - obj.op = serde::Deserializable::deserialize(deserializer); - obj.bit_size = - serde::Deserializable::deserialize(deserializer); - obj.lhs = serde::Deserializable::deserialize(deserializer); - obj.rhs = serde::Deserializable::deserialize(deserializer); - return obj; +Program::BrilligOpcode::BinaryFieldOp serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::BinaryFieldOp obj; + obj.destination = serde::Deserializable::deserialize(deserializer); + obj.op = serde::Deserializable::deserialize(deserializer); + obj.lhs = serde::Deserializable::deserialize(deserializer); + obj.rhs = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -inline bool operator==(const BrilligOpcode::Cast &lhs, - const BrilligOpcode::Cast &rhs) { - if (!(lhs.destination == rhs.destination)) { - return false; - } - if (!(lhs.source == rhs.source)) { - return false; - } - if (!(lhs.bit_size == rhs.bit_size)) { - return false; - } - return true; -} + inline bool operator==(const BrilligOpcode::BinaryIntOp &lhs, const BrilligOpcode::BinaryIntOp &rhs) { + if (!(lhs.destination == rhs.destination)) { return false; } + if (!(lhs.op == rhs.op)) { return false; } + if (!(lhs.bit_size == rhs.bit_size)) { return false; } + if (!(lhs.lhs == rhs.lhs)) { return false; } + if (!(lhs.rhs == rhs.rhs)) { return false; } + return true; + } -inline std::vector BrilligOpcode::Cast::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BrilligOpcode::BinaryIntOp::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BrilligOpcode::Cast -BrilligOpcode::Cast::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; -} + inline BrilligOpcode::BinaryIntOp BrilligOpcode::BinaryIntOp::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BrilligOpcode::Cast &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.destination, - serializer); - serde::Serializable::serialize(obj.source, serializer); - serde::Serializable::serialize(obj.bit_size, - serializer); +void serde::Serializable::serialize(const Program::BrilligOpcode::BinaryIntOp &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.destination, serializer); + serde::Serializable::serialize(obj.op, serializer); + serde::Serializable::serialize(obj.bit_size, serializer); + serde::Serializable::serialize(obj.lhs, serializer); + serde::Serializable::serialize(obj.rhs, serializer); } template <> template -Program::BrilligOpcode::Cast -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BrilligOpcode::Cast obj; - obj.destination = - serde::Deserializable::deserialize( - deserializer); - obj.source = - serde::Deserializable::deserialize(deserializer); - obj.bit_size = - serde::Deserializable::deserialize(deserializer); - return obj; +Program::BrilligOpcode::BinaryIntOp serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::BinaryIntOp obj; + obj.destination = serde::Deserializable::deserialize(deserializer); + obj.op = serde::Deserializable::deserialize(deserializer); + obj.bit_size = serde::Deserializable::deserialize(deserializer); + obj.lhs = serde::Deserializable::deserialize(deserializer); + obj.rhs = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -inline bool operator==(const BrilligOpcode::JumpIfNot &lhs, - const BrilligOpcode::JumpIfNot &rhs) { - if (!(lhs.condition == rhs.condition)) { - return false; - } - if (!(lhs.location == rhs.location)) { - return false; - } - return true; -} + inline bool operator==(const BrilligOpcode::Cast &lhs, const BrilligOpcode::Cast &rhs) { + if (!(lhs.destination == rhs.destination)) { return false; } + if (!(lhs.source == rhs.source)) { return false; } + if (!(lhs.bit_size == rhs.bit_size)) { return false; } + return true; + } -inline std::vector BrilligOpcode::JumpIfNot::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BrilligOpcode::Cast::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BrilligOpcode::JumpIfNot -BrilligOpcode::JumpIfNot::bincodeDeserialize(std::vector input) { - auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize( - deserializer); - if (deserializer.get_buffer_offset() < input.size()) { - throw serde::deserialization_error("Some input bytes were not read"); - } - return value; -} + inline BrilligOpcode::Cast BrilligOpcode::Cast::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BrilligOpcode::JumpIfNot &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.condition, - serializer); - serde::Serializable::serialize(obj.location, - serializer); +void serde::Serializable::serialize(const Program::BrilligOpcode::Cast &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.destination, serializer); + serde::Serializable::serialize(obj.source, serializer); + serde::Serializable::serialize(obj.bit_size, serializer); } template <> template -Program::BrilligOpcode::JumpIfNot -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BrilligOpcode::JumpIfNot obj; - obj.condition = - serde::Deserializable::deserialize(deserializer); - obj.location = - serde::Deserializable::deserialize(deserializer); - return obj; +Program::BrilligOpcode::Cast serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::Cast obj; + obj.destination = serde::Deserializable::deserialize(deserializer); + obj.source = serde::Deserializable::deserialize(deserializer); + obj.bit_size = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -inline bool operator==(const BrilligOpcode::JumpIf &lhs, - const BrilligOpcode::JumpIf &rhs) { - if (!(lhs.condition == rhs.condition)) { - return false; - } - if (!(lhs.location == rhs.location)) { - return false; - } - return true; -} + inline bool operator==(const BrilligOpcode::JumpIfNot &lhs, const BrilligOpcode::JumpIfNot &rhs) { + if (!(lhs.condition == rhs.condition)) { return false; } + if (!(lhs.location == rhs.location)) { return false; } + return true; + } -inline std::vector BrilligOpcode::JumpIf::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BrilligOpcode::JumpIfNot::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BrilligOpcode::JumpIf -BrilligOpcode::JumpIf::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; -} + inline BrilligOpcode::JumpIfNot BrilligOpcode::JumpIfNot::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BrilligOpcode::JumpIf &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.condition, - serializer); - serde::Serializable::serialize(obj.location, - serializer); +void serde::Serializable::serialize(const Program::BrilligOpcode::JumpIfNot &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.condition, serializer); + serde::Serializable::serialize(obj.location, serializer); } template <> template -Program::BrilligOpcode::JumpIf -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BrilligOpcode::JumpIf obj; - obj.condition = - serde::Deserializable::deserialize(deserializer); - obj.location = - serde::Deserializable::deserialize(deserializer); - return obj; +Program::BrilligOpcode::JumpIfNot serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::JumpIfNot obj; + obj.condition = serde::Deserializable::deserialize(deserializer); + obj.location = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -inline bool operator==(const BrilligOpcode::Jump &lhs, - const BrilligOpcode::Jump &rhs) { - if (!(lhs.location == rhs.location)) { - return false; - } - return true; -} + inline bool operator==(const BrilligOpcode::JumpIf &lhs, const BrilligOpcode::JumpIf &rhs) { + if (!(lhs.condition == rhs.condition)) { return false; } + if (!(lhs.location == rhs.location)) { return false; } + return true; + } -inline std::vector BrilligOpcode::Jump::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BrilligOpcode::JumpIf::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BrilligOpcode::Jump -BrilligOpcode::Jump::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; -} + inline BrilligOpcode::JumpIf BrilligOpcode::JumpIf::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BrilligOpcode::Jump &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.location, - serializer); +void serde::Serializable::serialize(const Program::BrilligOpcode::JumpIf &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.condition, serializer); + serde::Serializable::serialize(obj.location, serializer); } template <> template -Program::BrilligOpcode::Jump -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BrilligOpcode::Jump obj; - obj.location = - serde::Deserializable::deserialize(deserializer); - return obj; +Program::BrilligOpcode::JumpIf serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::JumpIf obj; + obj.condition = serde::Deserializable::deserialize(deserializer); + obj.location = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -inline bool operator==(const BrilligOpcode::CalldataCopy &lhs, - const BrilligOpcode::CalldataCopy &rhs) { - if (!(lhs.destination_address == rhs.destination_address)) { - return false; - } - if (!(lhs.size == rhs.size)) { - return false; - } - if (!(lhs.offset == rhs.offset)) { - return false; - } - return true; -} + inline bool operator==(const BrilligOpcode::Jump &lhs, const BrilligOpcode::Jump &rhs) { + if (!(lhs.location == rhs.location)) { return false; } + return true; + } -inline std::vector -BrilligOpcode::CalldataCopy::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, - serializer); - return std::move(serializer).bytes(); -} + inline std::vector BrilligOpcode::Jump::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BrilligOpcode::CalldataCopy -BrilligOpcode::CalldataCopy::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; -} + inline BrilligOpcode::Jump BrilligOpcode::Jump::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BrilligOpcode::CalldataCopy &obj, Serializer &serializer) { - serde::Serializable::serialize( - obj.destination_address, serializer); - serde::Serializable::serialize(obj.size, serializer); - serde::Serializable::serialize(obj.offset, serializer); +void serde::Serializable::serialize(const Program::BrilligOpcode::Jump &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.location, serializer); } template <> template -Program::BrilligOpcode::CalldataCopy -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BrilligOpcode::CalldataCopy obj; - obj.destination_address = - serde::Deserializable::deserialize( - deserializer); - obj.size = - serde::Deserializable::deserialize(deserializer); - obj.offset = - serde::Deserializable::deserialize(deserializer); - return obj; +Program::BrilligOpcode::Jump serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::Jump obj; + obj.location = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -inline bool operator==(const BrilligOpcode::Call &lhs, - const BrilligOpcode::Call &rhs) { - if (!(lhs.location == rhs.location)) { - return false; - } - return true; -} + inline bool operator==(const BrilligOpcode::CalldataCopy &lhs, const BrilligOpcode::CalldataCopy &rhs) { + if (!(lhs.destination_address == rhs.destination_address)) { return false; } + if (!(lhs.size == rhs.size)) { return false; } + if (!(lhs.offset == rhs.offset)) { return false; } + return true; + } -inline std::vector BrilligOpcode::Call::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BrilligOpcode::CalldataCopy::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BrilligOpcode::Call -BrilligOpcode::Call::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; -} + inline BrilligOpcode::CalldataCopy BrilligOpcode::CalldataCopy::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BrilligOpcode::Call &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.location, - serializer); +void serde::Serializable::serialize(const Program::BrilligOpcode::CalldataCopy &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.destination_address, serializer); + serde::Serializable::serialize(obj.size, serializer); + serde::Serializable::serialize(obj.offset, serializer); } template <> template -Program::BrilligOpcode::Call -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BrilligOpcode::Call obj; - obj.location = - serde::Deserializable::deserialize(deserializer); - return obj; +Program::BrilligOpcode::CalldataCopy serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::CalldataCopy obj; + obj.destination_address = serde::Deserializable::deserialize(deserializer); + obj.size = serde::Deserializable::deserialize(deserializer); + obj.offset = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -inline bool operator==(const BrilligOpcode::Const &lhs, - const BrilligOpcode::Const &rhs) { - if (!(lhs.destination == rhs.destination)) { - return false; - } - if (!(lhs.bit_size == rhs.bit_size)) { - return false; - } - if (!(lhs.value == rhs.value)) { - return false; - } - return true; -} + inline bool operator==(const BrilligOpcode::Call &lhs, const BrilligOpcode::Call &rhs) { + if (!(lhs.location == rhs.location)) { return false; } + return true; + } -inline std::vector BrilligOpcode::Const::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BrilligOpcode::Call::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BrilligOpcode::Const -BrilligOpcode::Const::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; -} + inline BrilligOpcode::Call BrilligOpcode::Call::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BrilligOpcode::Const &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.destination, - serializer); - serde::Serializable::serialize(obj.bit_size, - serializer); - serde::Serializable::serialize(obj.value, serializer); +void serde::Serializable::serialize(const Program::BrilligOpcode::Call &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.location, serializer); } template <> template -Program::BrilligOpcode::Const -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BrilligOpcode::Const obj; - obj.destination = - serde::Deserializable::deserialize( - deserializer); - obj.bit_size = - serde::Deserializable::deserialize(deserializer); - obj.value = - serde::Deserializable::deserialize(deserializer); - return obj; +Program::BrilligOpcode::Call serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::Call obj; + obj.location = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -inline bool operator==(const BrilligOpcode::Return &lhs, - const BrilligOpcode::Return &rhs) { - return true; -} + inline bool operator==(const BrilligOpcode::Const &lhs, const BrilligOpcode::Const &rhs) { + if (!(lhs.destination == rhs.destination)) { return false; } + if (!(lhs.bit_size == rhs.bit_size)) { return false; } + if (!(lhs.value == rhs.value)) { return false; } + return true; + } -inline std::vector BrilligOpcode::Return::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BrilligOpcode::Const::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BrilligOpcode::Return -BrilligOpcode::Return::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; -} + inline BrilligOpcode::Const BrilligOpcode::Const::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BrilligOpcode::Return &obj, Serializer &serializer) {} +void serde::Serializable::serialize(const Program::BrilligOpcode::Const &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.destination, serializer); + serde::Serializable::serialize(obj.bit_size, serializer); + serde::Serializable::serialize(obj.value, serializer); +} template <> template -Program::BrilligOpcode::Return -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BrilligOpcode::Return obj; - return obj; +Program::BrilligOpcode::Const serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::Const obj; + obj.destination = serde::Deserializable::deserialize(deserializer); + obj.bit_size = serde::Deserializable::deserialize(deserializer); + obj.value = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -inline bool operator==(const BrilligOpcode::ForeignCall &lhs, - const BrilligOpcode::ForeignCall &rhs) { - if (!(lhs.function == rhs.function)) { - return false; - } - if (!(lhs.destinations == rhs.destinations)) { - return false; - } - if (!(lhs.destination_value_types == rhs.destination_value_types)) { - return false; - } - if (!(lhs.inputs == rhs.inputs)) { - return false; - } - if (!(lhs.input_value_types == rhs.input_value_types)) { - return false; - } - return true; -} + inline bool operator==(const BrilligOpcode::Return &lhs, const BrilligOpcode::Return &rhs) { + return true; + } -inline std::vector -BrilligOpcode::ForeignCall::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BrilligOpcode::Return::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BrilligOpcode::ForeignCall -BrilligOpcode::ForeignCall::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; -} + inline BrilligOpcode::Return BrilligOpcode::Return::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BrilligOpcode::ForeignCall &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.function, - serializer); - serde::Serializable::serialize(obj.destinations, - serializer); - serde::Serializable::serialize( - obj.destination_value_types, serializer); - serde::Serializable::serialize(obj.inputs, serializer); - serde::Serializable::serialize( - obj.input_value_types, serializer); +void serde::Serializable::serialize(const Program::BrilligOpcode::Return &obj, Serializer &serializer) { } template <> template -Program::BrilligOpcode::ForeignCall -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BrilligOpcode::ForeignCall obj; - obj.function = - serde::Deserializable::deserialize(deserializer); - obj.destinations = - serde::Deserializable::deserialize( - deserializer); - obj.destination_value_types = - serde::Deserializable::deserialize( - deserializer); - obj.inputs = - serde::Deserializable::deserialize(deserializer); - obj.input_value_types = - serde::Deserializable::deserialize( - deserializer); - return obj; +Program::BrilligOpcode::Return serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::Return obj; + return obj; } namespace Program { -inline bool operator==(const BrilligOpcode::Mov &lhs, - const BrilligOpcode::Mov &rhs) { - if (!(lhs.destination == rhs.destination)) { - return false; - } - if (!(lhs.source == rhs.source)) { - return false; - } - return true; -} + inline bool operator==(const BrilligOpcode::ForeignCall &lhs, const BrilligOpcode::ForeignCall &rhs) { + if (!(lhs.function == rhs.function)) { return false; } + if (!(lhs.destinations == rhs.destinations)) { return false; } + if (!(lhs.destination_value_types == rhs.destination_value_types)) { return false; } + if (!(lhs.inputs == rhs.inputs)) { return false; } + if (!(lhs.input_value_types == rhs.input_value_types)) { return false; } + return true; + } -inline std::vector BrilligOpcode::Mov::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BrilligOpcode::ForeignCall::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BrilligOpcode::Mov -BrilligOpcode::Mov::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; -} + inline BrilligOpcode::ForeignCall BrilligOpcode::ForeignCall::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BrilligOpcode::Mov &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.destination, - serializer); - serde::Serializable::serialize(obj.source, serializer); +void serde::Serializable::serialize(const Program::BrilligOpcode::ForeignCall &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.function, serializer); + serde::Serializable::serialize(obj.destinations, serializer); + serde::Serializable::serialize(obj.destination_value_types, serializer); + serde::Serializable::serialize(obj.inputs, serializer); + serde::Serializable::serialize(obj.input_value_types, serializer); } template <> template -Program::BrilligOpcode::Mov -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BrilligOpcode::Mov obj; - obj.destination = - serde::Deserializable::deserialize( - deserializer); - obj.source = - serde::Deserializable::deserialize(deserializer); - return obj; +Program::BrilligOpcode::ForeignCall serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::ForeignCall obj; + obj.function = serde::Deserializable::deserialize(deserializer); + obj.destinations = serde::Deserializable::deserialize(deserializer); + obj.destination_value_types = serde::Deserializable::deserialize(deserializer); + obj.inputs = serde::Deserializable::deserialize(deserializer); + obj.input_value_types = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -inline bool operator==(const BrilligOpcode::Load &lhs, - const BrilligOpcode::Load &rhs) { - if (!(lhs.destination == rhs.destination)) { - return false; - } - if (!(lhs.source_pointer == rhs.source_pointer)) { - return false; - } - return true; -} + inline bool operator==(const BrilligOpcode::Mov &lhs, const BrilligOpcode::Mov &rhs) { + if (!(lhs.destination == rhs.destination)) { return false; } + if (!(lhs.source == rhs.source)) { return false; } + return true; + } -inline std::vector BrilligOpcode::Load::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BrilligOpcode::Mov::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BrilligOpcode::Load -BrilligOpcode::Load::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; -} + inline BrilligOpcode::Mov BrilligOpcode::Mov::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BrilligOpcode::Load &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.destination, - serializer); - serde::Serializable::serialize( - obj.source_pointer, serializer); +void serde::Serializable::serialize(const Program::BrilligOpcode::Mov &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.destination, serializer); + serde::Serializable::serialize(obj.source, serializer); } template <> template -Program::BrilligOpcode::Load -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BrilligOpcode::Load obj; - obj.destination = - serde::Deserializable::deserialize( - deserializer); - obj.source_pointer = - serde::Deserializable::deserialize( - deserializer); - return obj; +Program::BrilligOpcode::Mov serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::Mov obj; + obj.destination = serde::Deserializable::deserialize(deserializer); + obj.source = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -inline bool operator==(const BrilligOpcode::Store &lhs, - const BrilligOpcode::Store &rhs) { - if (!(lhs.destination_pointer == rhs.destination_pointer)) { - return false; - } - if (!(lhs.source == rhs.source)) { - return false; - } - return true; -} + inline bool operator==(const BrilligOpcode::Load &lhs, const BrilligOpcode::Load &rhs) { + if (!(lhs.destination == rhs.destination)) { return false; } + if (!(lhs.source_pointer == rhs.source_pointer)) { return false; } + return true; + } -inline std::vector BrilligOpcode::Store::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BrilligOpcode::Load::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BrilligOpcode::Store -BrilligOpcode::Store::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; -} + inline BrilligOpcode::Load BrilligOpcode::Load::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BrilligOpcode::Store &obj, Serializer &serializer) { - serde::Serializable::serialize( - obj.destination_pointer, serializer); - serde::Serializable::serialize(obj.source, serializer); +void serde::Serializable::serialize(const Program::BrilligOpcode::Load &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.destination, serializer); + serde::Serializable::serialize(obj.source_pointer, serializer); } template <> template -Program::BrilligOpcode::Store -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BrilligOpcode::Store obj; - obj.destination_pointer = - serde::Deserializable::deserialize( - deserializer); - obj.source = - serde::Deserializable::deserialize(deserializer); - return obj; +Program::BrilligOpcode::Load serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::Load obj; + obj.destination = serde::Deserializable::deserialize(deserializer); + obj.source_pointer = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -inline bool operator==(const BrilligOpcode::BlackBox &lhs, - const BrilligOpcode::BlackBox &rhs) { - if (!(lhs.value == rhs.value)) { - return false; - } - return true; -} + inline bool operator==(const BrilligOpcode::Store &lhs, const BrilligOpcode::Store &rhs) { + if (!(lhs.destination_pointer == rhs.destination_pointer)) { return false; } + if (!(lhs.source == rhs.source)) { return false; } + return true; + } -inline std::vector BrilligOpcode::BlackBox::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BrilligOpcode::Store::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BrilligOpcode::BlackBox -BrilligOpcode::BlackBox::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; -} + inline BrilligOpcode::Store BrilligOpcode::Store::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BrilligOpcode::BlackBox &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.value, serializer); +void serde::Serializable::serialize(const Program::BrilligOpcode::Store &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.destination_pointer, serializer); + serde::Serializable::serialize(obj.source, serializer); } template <> template -Program::BrilligOpcode::BlackBox -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BrilligOpcode::BlackBox obj; - obj.value = - serde::Deserializable::deserialize(deserializer); - return obj; +Program::BrilligOpcode::Store serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::Store obj; + obj.destination_pointer = serde::Deserializable::deserialize(deserializer); + obj.source = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -inline bool operator==(const BrilligOpcode::Trap &lhs, - const BrilligOpcode::Trap &rhs) { - return true; -} + inline bool operator==(const BrilligOpcode::BlackBox &lhs, const BrilligOpcode::BlackBox &rhs) { + if (!(lhs.value == rhs.value)) { return false; } + return true; + } -inline std::vector BrilligOpcode::Trap::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BrilligOpcode::BlackBox::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BrilligOpcode::Trap -BrilligOpcode::Trap::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; -} + inline BrilligOpcode::BlackBox BrilligOpcode::BlackBox::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BrilligOpcode::Trap &obj, Serializer &serializer) {} +void serde::Serializable::serialize(const Program::BrilligOpcode::BlackBox &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.value, serializer); +} template <> template -Program::BrilligOpcode::Trap -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BrilligOpcode::Trap obj; - return obj; +Program::BrilligOpcode::BlackBox serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::BlackBox obj; + obj.value = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -inline bool operator==(const BrilligOpcode::Stop &lhs, - const BrilligOpcode::Stop &rhs) { - if (!(lhs.return_data_offset == rhs.return_data_offset)) { - return false; - } - if (!(lhs.return_data_size == rhs.return_data_size)) { - return false; - } - return true; -} + inline bool operator==(const BrilligOpcode::Trap &lhs, const BrilligOpcode::Trap &rhs) { + return true; + } -inline std::vector BrilligOpcode::Stop::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BrilligOpcode::Trap::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BrilligOpcode::Stop -BrilligOpcode::Stop::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; -} + inline BrilligOpcode::Trap BrilligOpcode::Trap::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BrilligOpcode::Stop &obj, Serializer &serializer) { - serde::Serializable::serialize( - obj.return_data_offset, serializer); - serde::Serializable::serialize( - obj.return_data_size, serializer); +void serde::Serializable::serialize(const Program::BrilligOpcode::Trap &obj, Serializer &serializer) { } template <> template -Program::BrilligOpcode::Stop -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BrilligOpcode::Stop obj; - obj.return_data_offset = - serde::Deserializable::deserialize( - deserializer); - obj.return_data_size = - serde::Deserializable::deserialize( - deserializer); - return obj; +Program::BrilligOpcode::Trap serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::Trap obj; + return obj; } namespace Program { -inline bool operator==(const BrilligOutputs &lhs, const BrilligOutputs &rhs) { - if (!(lhs.value == rhs.value)) { - return false; - } - return true; -} + inline bool operator==(const BrilligOpcode::Stop &lhs, const BrilligOpcode::Stop &rhs) { + if (!(lhs.return_data_offset == rhs.return_data_offset)) { return false; } + if (!(lhs.return_data_size == rhs.return_data_size)) { return false; } + return true; + } -inline std::vector BrilligOutputs::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BrilligOpcode::Stop::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BrilligOutputs -BrilligOutputs::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; -} + inline BrilligOpcode::Stop BrilligOpcode::Stop::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BrilligOutputs &obj, Serializer &serializer) { - serializer.increase_container_depth(); - serde::Serializable::serialize(obj.value, serializer); - serializer.decrease_container_depth(); +void serde::Serializable::serialize(const Program::BrilligOpcode::Stop &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.return_data_offset, serializer); + serde::Serializable::serialize(obj.return_data_size, serializer); } template <> template -Program::BrilligOutputs -serde::Deserializable::deserialize( - Deserializer &deserializer) { - deserializer.increase_container_depth(); - Program::BrilligOutputs obj; - obj.value = - serde::Deserializable::deserialize(deserializer); - deserializer.decrease_container_depth(); - return obj; +Program::BrilligOpcode::Stop serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOpcode::Stop obj; + obj.return_data_offset = serde::Deserializable::deserialize(deserializer); + obj.return_data_size = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -inline bool operator==(const BrilligOutputs::Simple &lhs, - const BrilligOutputs::Simple &rhs) { - if (!(lhs.value == rhs.value)) { - return false; - } - return true; -} + inline bool operator==(const BrilligOutputs &lhs, const BrilligOutputs &rhs) { + if (!(lhs.value == rhs.value)) { return false; } + return true; + } -inline std::vector BrilligOutputs::Simple::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BrilligOutputs::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BrilligOutputs::Simple -BrilligOutputs::Simple::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; -} + inline BrilligOutputs BrilligOutputs::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BrilligOutputs::Simple &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.value, serializer); +void serde::Serializable::serialize(const Program::BrilligOutputs &obj, Serializer &serializer) { + serializer.increase_container_depth(); + serde::Serializable::serialize(obj.value, serializer); + serializer.decrease_container_depth(); } template <> template -Program::BrilligOutputs::Simple -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BrilligOutputs::Simple obj; - obj.value = - serde::Deserializable::deserialize(deserializer); - return obj; +Program::BrilligOutputs serde::Deserializable::deserialize(Deserializer &deserializer) { + deserializer.increase_container_depth(); + Program::BrilligOutputs obj; + obj.value = serde::Deserializable::deserialize(deserializer); + deserializer.decrease_container_depth(); + return obj; } namespace Program { -inline bool operator==(const BrilligOutputs::Array &lhs, - const BrilligOutputs::Array &rhs) { - if (!(lhs.value == rhs.value)) { - return false; - } - return true; -} + inline bool operator==(const BrilligOutputs::Simple &lhs, const BrilligOutputs::Simple &rhs) { + if (!(lhs.value == rhs.value)) { return false; } + return true; + } -inline std::vector BrilligOutputs::Array::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BrilligOutputs::Simple::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline BrilligOutputs::Array -BrilligOutputs::Array::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; -} + inline BrilligOutputs::Simple BrilligOutputs::Simple::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::BrilligOutputs::Array &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.value, serializer); +void serde::Serializable::serialize(const Program::BrilligOutputs::Simple &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.value, serializer); } template <> template -Program::BrilligOutputs::Array -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::BrilligOutputs::Array obj; - obj.value = - serde::Deserializable::deserialize(deserializer); - return obj; +Program::BrilligOutputs::Simple serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOutputs::Simple obj; + obj.value = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -inline bool operator==(const Circuit &lhs, const Circuit &rhs) { - if (!(lhs.current_witness_index == rhs.current_witness_index)) { - return false; - } - if (!(lhs.opcodes == rhs.opcodes)) { - return false; - } - if (!(lhs.expression_width == rhs.expression_width)) { - return false; - } - if (!(lhs.private_parameters == rhs.private_parameters)) { - return false; - } - if (!(lhs.public_parameters == rhs.public_parameters)) { - return false; - } - if (!(lhs.return_values == rhs.return_values)) { - return false; - } - if (!(lhs.assert_messages == rhs.assert_messages)) { - return false; - } - if (!(lhs.recursive == rhs.recursive)) { - return false; - } - return true; -} + inline bool operator==(const BrilligOutputs::Array &lhs, const BrilligOutputs::Array &rhs) { + if (!(lhs.value == rhs.value)) { return false; } + return true; + } -inline std::vector Circuit::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector BrilligOutputs::Array::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline Circuit Circuit::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; -} + inline BrilligOutputs::Array BrilligOutputs::Array::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::Circuit &obj, Serializer &serializer) { - serializer.increase_container_depth(); - serde::Serializable::serialize( - obj.current_witness_index, serializer); - serde::Serializable::serialize(obj.opcodes, - serializer); - serde::Serializable::serialize( - obj.expression_width, serializer); - serde::Serializable::serialize( - obj.private_parameters, serializer); - serde::Serializable::serialize( - obj.public_parameters, serializer); - serde::Serializable::serialize(obj.return_values, - serializer); - serde::Serializable::serialize( - obj.assert_messages, serializer); - serde::Serializable::serialize(obj.recursive, - serializer); - serializer.decrease_container_depth(); +void serde::Serializable::serialize(const Program::BrilligOutputs::Array &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.value, serializer); } template <> template -Program::Circuit serde::Deserializable::deserialize( - Deserializer &deserializer) { - deserializer.increase_container_depth(); - Program::Circuit obj; - obj.current_witness_index = - serde::Deserializable::deserialize( - deserializer); - obj.opcodes = - serde::Deserializable::deserialize(deserializer); - obj.expression_width = - serde::Deserializable::deserialize( - deserializer); - obj.private_parameters = - serde::Deserializable::deserialize( - deserializer); - obj.public_parameters = - serde::Deserializable::deserialize( - deserializer); - obj.return_values = - serde::Deserializable::deserialize( - deserializer); - obj.assert_messages = - serde::Deserializable::deserialize( - deserializer); - obj.recursive = - serde::Deserializable::deserialize(deserializer); - deserializer.decrease_container_depth(); - return obj; +Program::BrilligOutputs::Array serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::BrilligOutputs::Array obj; + obj.value = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -inline bool operator==(const Directive &lhs, const Directive &rhs) { - if (!(lhs.value == rhs.value)) { - return false; - } - return true; -} + inline bool operator==(const Circuit &lhs, const Circuit &rhs) { + if (!(lhs.current_witness_index == rhs.current_witness_index)) { return false; } + if (!(lhs.opcodes == rhs.opcodes)) { return false; } + if (!(lhs.expression_width == rhs.expression_width)) { return false; } + if (!(lhs.private_parameters == rhs.private_parameters)) { return false; } + if (!(lhs.public_parameters == rhs.public_parameters)) { return false; } + if (!(lhs.return_values == rhs.return_values)) { return false; } + if (!(lhs.assert_messages == rhs.assert_messages)) { return false; } + if (!(lhs.recursive == rhs.recursive)) { return false; } + return true; + } -inline std::vector Directive::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector Circuit::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline Directive Directive::bincodeDeserialize(std::vector input) { - auto deserializer = serde::BincodeDeserializer(input); - auto value = serde::Deserializable::deserialize(deserializer); - if (deserializer.get_buffer_offset() < input.size()) { - throw serde::deserialization_error("Some input bytes were not read"); - } - return value; -} + inline Circuit Circuit::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::Directive &obj, Serializer &serializer) { - serializer.increase_container_depth(); - serde::Serializable::serialize(obj.value, serializer); - serializer.decrease_container_depth(); +void serde::Serializable::serialize(const Program::Circuit &obj, Serializer &serializer) { + serializer.increase_container_depth(); + serde::Serializable::serialize(obj.current_witness_index, serializer); + serde::Serializable::serialize(obj.opcodes, serializer); + serde::Serializable::serialize(obj.expression_width, serializer); + serde::Serializable::serialize(obj.private_parameters, serializer); + serde::Serializable::serialize(obj.public_parameters, serializer); + serde::Serializable::serialize(obj.return_values, serializer); + serde::Serializable::serialize(obj.assert_messages, serializer); + serde::Serializable::serialize(obj.recursive, serializer); + serializer.decrease_container_depth(); } template <> template -Program::Directive serde::Deserializable::deserialize( - Deserializer &deserializer) { - deserializer.increase_container_depth(); - Program::Directive obj; - obj.value = - serde::Deserializable::deserialize(deserializer); - deserializer.decrease_container_depth(); - return obj; +Program::Circuit serde::Deserializable::deserialize(Deserializer &deserializer) { + deserializer.increase_container_depth(); + Program::Circuit obj; + obj.current_witness_index = serde::Deserializable::deserialize(deserializer); + obj.opcodes = serde::Deserializable::deserialize(deserializer); + obj.expression_width = serde::Deserializable::deserialize(deserializer); + obj.private_parameters = serde::Deserializable::deserialize(deserializer); + obj.public_parameters = serde::Deserializable::deserialize(deserializer); + obj.return_values = serde::Deserializable::deserialize(deserializer); + obj.assert_messages = serde::Deserializable::deserialize(deserializer); + obj.recursive = serde::Deserializable::deserialize(deserializer); + deserializer.decrease_container_depth(); + return obj; } namespace Program { -inline bool operator==(const Directive::ToLeRadix &lhs, - const Directive::ToLeRadix &rhs) { - if (!(lhs.a == rhs.a)) { - return false; - } - if (!(lhs.b == rhs.b)) { - return false; - } - if (!(lhs.radix == rhs.radix)) { - return false; - } - return true; -} + inline bool operator==(const Directive &lhs, const Directive &rhs) { + if (!(lhs.value == rhs.value)) { return false; } + return true; + } -inline std::vector Directive::ToLeRadix::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector Directive::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline Directive::ToLeRadix -Directive::ToLeRadix::bincodeDeserialize(std::vector input) { - auto deserializer = serde::BincodeDeserializer(input); - auto value = - serde::Deserializable::deserialize(deserializer); - if (deserializer.get_buffer_offset() < input.size()) { - throw serde::deserialization_error("Some input bytes were not read"); - } - return value; -} + inline Directive Directive::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::Directive::ToLeRadix &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.a, serializer); - serde::Serializable::serialize(obj.b, serializer); - serde::Serializable::serialize(obj.radix, serializer); +void serde::Serializable::serialize(const Program::Directive &obj, Serializer &serializer) { + serializer.increase_container_depth(); + serde::Serializable::serialize(obj.value, serializer); + serializer.decrease_container_depth(); } template <> template -Program::Directive::ToLeRadix -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::Directive::ToLeRadix obj; - obj.a = serde::Deserializable::deserialize(deserializer); - obj.b = serde::Deserializable::deserialize(deserializer); - obj.radix = - serde::Deserializable::deserialize(deserializer); - return obj; +Program::Directive serde::Deserializable::deserialize(Deserializer &deserializer) { + deserializer.increase_container_depth(); + Program::Directive obj; + obj.value = serde::Deserializable::deserialize(deserializer); + deserializer.decrease_container_depth(); + return obj; } namespace Program { -inline bool operator==(const Expression &lhs, const Expression &rhs) { - if (!(lhs.mul_terms == rhs.mul_terms)) { - return false; - } - if (!(lhs.linear_combinations == rhs.linear_combinations)) { - return false; - } - if (!(lhs.q_c == rhs.q_c)) { - return false; - } - return true; -} + inline bool operator==(const Directive::ToLeRadix &lhs, const Directive::ToLeRadix &rhs) { + if (!(lhs.a == rhs.a)) { return false; } + if (!(lhs.b == rhs.b)) { return false; } + if (!(lhs.radix == rhs.radix)) { return false; } + return true; + } -inline std::vector Expression::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector Directive::ToLeRadix::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline Expression Expression::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; -} + inline Directive::ToLeRadix Directive::ToLeRadix::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::Expression &obj, Serializer &serializer) { - serializer.increase_container_depth(); - serde::Serializable::serialize(obj.mul_terms, - serializer); - serde::Serializable::serialize( - obj.linear_combinations, serializer); - serde::Serializable::serialize(obj.q_c, serializer); - serializer.decrease_container_depth(); +void serde::Serializable::serialize(const Program::Directive::ToLeRadix &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.a, serializer); + serde::Serializable::serialize(obj.b, serializer); + serde::Serializable::serialize(obj.radix, serializer); } template <> template -Program::Expression serde::Deserializable::deserialize( - Deserializer &deserializer) { - deserializer.increase_container_depth(); - Program::Expression obj; - obj.mul_terms = - serde::Deserializable::deserialize(deserializer); - obj.linear_combinations = - serde::Deserializable::deserialize( - deserializer); - obj.q_c = serde::Deserializable::deserialize(deserializer); - deserializer.decrease_container_depth(); - return obj; +Program::Directive::ToLeRadix serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::Directive::ToLeRadix obj; + obj.a = serde::Deserializable::deserialize(deserializer); + obj.b = serde::Deserializable::deserialize(deserializer); + obj.radix = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -inline bool operator==(const ExpressionWidth &lhs, const ExpressionWidth &rhs) { - if (!(lhs.value == rhs.value)) { - return false; - } - return true; -} + inline bool operator==(const Expression &lhs, const Expression &rhs) { + if (!(lhs.mul_terms == rhs.mul_terms)) { return false; } + if (!(lhs.linear_combinations == rhs.linear_combinations)) { return false; } + if (!(lhs.q_c == rhs.q_c)) { return false; } + return true; + } -inline std::vector ExpressionWidth::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector Expression::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline ExpressionWidth -ExpressionWidth::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; -} + inline Expression Expression::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::ExpressionWidth &obj, Serializer &serializer) { - serializer.increase_container_depth(); - serde::Serializable::serialize(obj.value, serializer); - serializer.decrease_container_depth(); +void serde::Serializable::serialize(const Program::Expression &obj, Serializer &serializer) { + serializer.increase_container_depth(); + serde::Serializable::serialize(obj.mul_terms, serializer); + serde::Serializable::serialize(obj.linear_combinations, serializer); + serde::Serializable::serialize(obj.q_c, serializer); + serializer.decrease_container_depth(); } template <> template -Program::ExpressionWidth -serde::Deserializable::deserialize( - Deserializer &deserializer) { - deserializer.increase_container_depth(); - Program::ExpressionWidth obj; - obj.value = - serde::Deserializable::deserialize(deserializer); - deserializer.decrease_container_depth(); - return obj; +Program::Expression serde::Deserializable::deserialize(Deserializer &deserializer) { + deserializer.increase_container_depth(); + Program::Expression obj; + obj.mul_terms = serde::Deserializable::deserialize(deserializer); + obj.linear_combinations = serde::Deserializable::deserialize(deserializer); + obj.q_c = serde::Deserializable::deserialize(deserializer); + deserializer.decrease_container_depth(); + return obj; } namespace Program { -inline bool operator==(const ExpressionWidth::Unbounded &lhs, - const ExpressionWidth::Unbounded &rhs) { - return true; -} + inline bool operator==(const ExpressionWidth &lhs, const ExpressionWidth &rhs) { + if (!(lhs.value == rhs.value)) { return false; } + return true; + } -inline std::vector -ExpressionWidth::Unbounded::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector ExpressionWidth::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline ExpressionWidth::Unbounded -ExpressionWidth::Unbounded::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; -} + inline ExpressionWidth ExpressionWidth::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::ExpressionWidth::Unbounded &obj, Serializer &serializer) {} +void serde::Serializable::serialize(const Program::ExpressionWidth &obj, Serializer &serializer) { + serializer.increase_container_depth(); + serde::Serializable::serialize(obj.value, serializer); + serializer.decrease_container_depth(); +} template <> template -Program::ExpressionWidth::Unbounded -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::ExpressionWidth::Unbounded obj; - return obj; +Program::ExpressionWidth serde::Deserializable::deserialize(Deserializer &deserializer) { + deserializer.increase_container_depth(); + Program::ExpressionWidth obj; + obj.value = serde::Deserializable::deserialize(deserializer); + deserializer.decrease_container_depth(); + return obj; } namespace Program { -inline bool operator==(const ExpressionWidth::Bounded &lhs, - const ExpressionWidth::Bounded &rhs) { - if (!(lhs.width == rhs.width)) { - return false; - } - return true; -} + inline bool operator==(const ExpressionWidth::Unbounded &lhs, const ExpressionWidth::Unbounded &rhs) { + return true; + } -inline std::vector ExpressionWidth::Bounded::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector ExpressionWidth::Unbounded::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline ExpressionWidth::Bounded -ExpressionWidth::Bounded::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; -} + inline ExpressionWidth::Unbounded ExpressionWidth::Unbounded::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::ExpressionWidth::Bounded &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.width, serializer); +void serde::Serializable::serialize(const Program::ExpressionWidth::Unbounded &obj, Serializer &serializer) { } template <> template -Program::ExpressionWidth::Bounded -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::ExpressionWidth::Bounded obj; - obj.width = - serde::Deserializable::deserialize(deserializer); - return obj; +Program::ExpressionWidth::Unbounded serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::ExpressionWidth::Unbounded obj; + return obj; } namespace Program { -inline bool operator==(const FunctionInput &lhs, const FunctionInput &rhs) { - if (!(lhs.witness == rhs.witness)) { - return false; - } - if (!(lhs.num_bits == rhs.num_bits)) { - return false; - } - return true; -} + inline bool operator==(const ExpressionWidth::Bounded &lhs, const ExpressionWidth::Bounded &rhs) { + if (!(lhs.width == rhs.width)) { return false; } + return true; + } -inline std::vector FunctionInput::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector ExpressionWidth::Bounded::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline FunctionInput -FunctionInput::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; -} + inline ExpressionWidth::Bounded ExpressionWidth::Bounded::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::FunctionInput &obj, Serializer &serializer) { - serializer.increase_container_depth(); - serde::Serializable::serialize(obj.witness, - serializer); - serde::Serializable::serialize(obj.num_bits, - serializer); - serializer.decrease_container_depth(); +void serde::Serializable::serialize(const Program::ExpressionWidth::Bounded &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.width, serializer); } template <> template -Program::FunctionInput -serde::Deserializable::deserialize( - Deserializer &deserializer) { - deserializer.increase_container_depth(); - Program::FunctionInput obj; - obj.witness = - serde::Deserializable::deserialize(deserializer); - obj.num_bits = - serde::Deserializable::deserialize(deserializer); - deserializer.decrease_container_depth(); - return obj; +Program::ExpressionWidth::Bounded serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::ExpressionWidth::Bounded obj; + obj.width = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -inline bool operator==(const HeapArray &lhs, const HeapArray &rhs) { - if (!(lhs.pointer == rhs.pointer)) { - return false; - } - if (!(lhs.size == rhs.size)) { - return false; - } - return true; -} + inline bool operator==(const FunctionInput &lhs, const FunctionInput &rhs) { + if (!(lhs.witness == rhs.witness)) { return false; } + if (!(lhs.num_bits == rhs.num_bits)) { return false; } + return true; + } -inline std::vector HeapArray::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector FunctionInput::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline HeapArray HeapArray::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; -} + inline FunctionInput FunctionInput::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::HeapArray &obj, Serializer &serializer) { - serializer.increase_container_depth(); - serde::Serializable::serialize(obj.pointer, - serializer); - serde::Serializable::serialize(obj.size, serializer); - serializer.decrease_container_depth(); +void serde::Serializable::serialize(const Program::FunctionInput &obj, Serializer &serializer) { + serializer.increase_container_depth(); + serde::Serializable::serialize(obj.witness, serializer); + serde::Serializable::serialize(obj.num_bits, serializer); + serializer.decrease_container_depth(); } template <> template -Program::HeapArray serde::Deserializable::deserialize( - Deserializer &deserializer) { - deserializer.increase_container_depth(); - Program::HeapArray obj; - obj.pointer = - serde::Deserializable::deserialize(deserializer); - obj.size = - serde::Deserializable::deserialize(deserializer); - deserializer.decrease_container_depth(); - return obj; +Program::FunctionInput serde::Deserializable::deserialize(Deserializer &deserializer) { + deserializer.increase_container_depth(); + Program::FunctionInput obj; + obj.witness = serde::Deserializable::deserialize(deserializer); + obj.num_bits = serde::Deserializable::deserialize(deserializer); + deserializer.decrease_container_depth(); + return obj; } namespace Program { -inline bool operator==(const HeapValueType &lhs, const HeapValueType &rhs) { - if (!(lhs.value == rhs.value)) { - return false; - } - return true; -} + inline bool operator==(const HeapArray &lhs, const HeapArray &rhs) { + if (!(lhs.pointer == rhs.pointer)) { return false; } + if (!(lhs.size == rhs.size)) { return false; } + return true; + } -inline std::vector HeapValueType::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector HeapArray::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline HeapValueType -HeapValueType::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; -} + inline HeapArray HeapArray::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::HeapValueType &obj, Serializer &serializer) { - serializer.increase_container_depth(); - serde::Serializable::serialize(obj.value, serializer); - serializer.decrease_container_depth(); +void serde::Serializable::serialize(const Program::HeapArray &obj, Serializer &serializer) { + serializer.increase_container_depth(); + serde::Serializable::serialize(obj.pointer, serializer); + serde::Serializable::serialize(obj.size, serializer); + serializer.decrease_container_depth(); } template <> template -Program::HeapValueType -serde::Deserializable::deserialize( - Deserializer &deserializer) { - deserializer.increase_container_depth(); - Program::HeapValueType obj; - obj.value = - serde::Deserializable::deserialize(deserializer); - deserializer.decrease_container_depth(); - return obj; +Program::HeapArray serde::Deserializable::deserialize(Deserializer &deserializer) { + deserializer.increase_container_depth(); + Program::HeapArray obj; + obj.pointer = serde::Deserializable::deserialize(deserializer); + obj.size = serde::Deserializable::deserialize(deserializer); + deserializer.decrease_container_depth(); + return obj; } namespace Program { -inline bool operator==(const HeapValueType::Simple &lhs, - const HeapValueType::Simple &rhs) { - return true; -} + inline bool operator==(const HeapValueType &lhs, const HeapValueType &rhs) { + if (!(lhs.value == rhs.value)) { return false; } + return true; + } -inline std::vector HeapValueType::Simple::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector HeapValueType::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline HeapValueType::Simple -HeapValueType::Simple::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; -} + inline HeapValueType HeapValueType::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::HeapValueType::Simple &obj, Serializer &serializer) {} +void serde::Serializable::serialize(const Program::HeapValueType &obj, Serializer &serializer) { + serializer.increase_container_depth(); + serde::Serializable::serialize(obj.value, serializer); + serializer.decrease_container_depth(); +} template <> template -Program::HeapValueType::Simple -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::HeapValueType::Simple obj; - return obj; +Program::HeapValueType serde::Deserializable::deserialize(Deserializer &deserializer) { + deserializer.increase_container_depth(); + Program::HeapValueType obj; + obj.value = serde::Deserializable::deserialize(deserializer); + deserializer.decrease_container_depth(); + return obj; } namespace Program { -inline bool operator==(const HeapValueType::Array &lhs, - const HeapValueType::Array &rhs) { - if (!(lhs.value_types == rhs.value_types)) { - return false; - } - if (!(lhs.size == rhs.size)) { - return false; - } - return true; -} + inline bool operator==(const HeapValueType::Simple &lhs, const HeapValueType::Simple &rhs) { + return true; + } -inline std::vector HeapValueType::Array::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector HeapValueType::Simple::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline HeapValueType::Array -HeapValueType::Array::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; -} + inline HeapValueType::Simple HeapValueType::Simple::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::HeapValueType::Array &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.value_types, - serializer); - serde::Serializable::serialize(obj.size, serializer); +void serde::Serializable::serialize(const Program::HeapValueType::Simple &obj, Serializer &serializer) { } template <> template -Program::HeapValueType::Array -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::HeapValueType::Array obj; - obj.value_types = - serde::Deserializable::deserialize( - deserializer); - obj.size = - serde::Deserializable::deserialize(deserializer); - return obj; +Program::HeapValueType::Simple serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::HeapValueType::Simple obj; + return obj; } namespace Program { -inline bool operator==(const HeapValueType::Vector &lhs, - const HeapValueType::Vector &rhs) { - if (!(lhs.value_types == rhs.value_types)) { - return false; - } - return true; -} + inline bool operator==(const HeapValueType::Array &lhs, const HeapValueType::Array &rhs) { + if (!(lhs.value_types == rhs.value_types)) { return false; } + if (!(lhs.size == rhs.size)) { return false; } + return true; + } -inline std::vector HeapValueType::Vector::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector HeapValueType::Array::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline HeapValueType::Vector -HeapValueType::Vector::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; -} + inline HeapValueType::Array HeapValueType::Array::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::HeapValueType::Vector &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.value_types, - serializer); +void serde::Serializable::serialize(const Program::HeapValueType::Array &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.value_types, serializer); + serde::Serializable::serialize(obj.size, serializer); } template <> template -Program::HeapValueType::Vector -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::HeapValueType::Vector obj; - obj.value_types = - serde::Deserializable::deserialize( - deserializer); - return obj; +Program::HeapValueType::Array serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::HeapValueType::Array obj; + obj.value_types = serde::Deserializable::deserialize(deserializer); + obj.size = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -inline bool operator==(const HeapVector &lhs, const HeapVector &rhs) { - if (!(lhs.pointer == rhs.pointer)) { - return false; - } - if (!(lhs.size == rhs.size)) { - return false; - } - return true; -} + inline bool operator==(const HeapValueType::Vector &lhs, const HeapValueType::Vector &rhs) { + if (!(lhs.value_types == rhs.value_types)) { return false; } + return true; + } -inline std::vector HeapVector::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector HeapValueType::Vector::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline HeapVector HeapVector::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; -} + inline HeapValueType::Vector HeapValueType::Vector::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::HeapVector &obj, Serializer &serializer) { - serializer.increase_container_depth(); - serde::Serializable::serialize(obj.pointer, - serializer); - serde::Serializable::serialize(obj.size, serializer); - serializer.decrease_container_depth(); +void serde::Serializable::serialize(const Program::HeapValueType::Vector &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.value_types, serializer); } template <> template -Program::HeapVector serde::Deserializable::deserialize( - Deserializer &deserializer) { - deserializer.increase_container_depth(); - Program::HeapVector obj; - obj.pointer = - serde::Deserializable::deserialize(deserializer); - obj.size = - serde::Deserializable::deserialize(deserializer); - deserializer.decrease_container_depth(); - return obj; +Program::HeapValueType::Vector serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::HeapValueType::Vector obj; + obj.value_types = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -inline bool operator==(const MemOp &lhs, const MemOp &rhs) { - if (!(lhs.operation == rhs.operation)) { - return false; - } - if (!(lhs.index == rhs.index)) { - return false; - } - if (!(lhs.value == rhs.value)) { - return false; - } - return true; -} + inline bool operator==(const HeapVector &lhs, const HeapVector &rhs) { + if (!(lhs.pointer == rhs.pointer)) { return false; } + if (!(lhs.size == rhs.size)) { return false; } + return true; + } -inline std::vector MemOp::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector HeapVector::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline MemOp MemOp::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; -} + inline HeapVector HeapVector::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize(const Program::MemOp &obj, - Serializer &serializer) { - serializer.increase_container_depth(); - serde::Serializable::serialize(obj.operation, - serializer); - serde::Serializable::serialize(obj.index, serializer); - serde::Serializable::serialize(obj.value, serializer); - serializer.decrease_container_depth(); +void serde::Serializable::serialize(const Program::HeapVector &obj, Serializer &serializer) { + serializer.increase_container_depth(); + serde::Serializable::serialize(obj.pointer, serializer); + serde::Serializable::serialize(obj.size, serializer); + serializer.decrease_container_depth(); } template <> template -Program::MemOp -serde::Deserializable::deserialize(Deserializer &deserializer) { - deserializer.increase_container_depth(); - Program::MemOp obj; - obj.operation = - serde::Deserializable::deserialize(deserializer); - obj.index = - serde::Deserializable::deserialize(deserializer); - obj.value = - serde::Deserializable::deserialize(deserializer); - deserializer.decrease_container_depth(); - return obj; +Program::HeapVector serde::Deserializable::deserialize(Deserializer &deserializer) { + deserializer.increase_container_depth(); + Program::HeapVector obj; + obj.pointer = serde::Deserializable::deserialize(deserializer); + obj.size = serde::Deserializable::deserialize(deserializer); + deserializer.decrease_container_depth(); + return obj; } namespace Program { -inline bool operator==(const MemoryAddress &lhs, const MemoryAddress &rhs) { - if (!(lhs.value == rhs.value)) { - return false; - } - return true; -} + inline bool operator==(const MemOp &lhs, const MemOp &rhs) { + if (!(lhs.operation == rhs.operation)) { return false; } + if (!(lhs.index == rhs.index)) { return false; } + if (!(lhs.value == rhs.value)) { return false; } + return true; + } -inline std::vector MemoryAddress::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector MemOp::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline MemoryAddress -MemoryAddress::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; -} + inline MemOp MemOp::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::MemoryAddress &obj, Serializer &serializer) { - serializer.increase_container_depth(); - serde::Serializable::serialize(obj.value, serializer); - serializer.decrease_container_depth(); +void serde::Serializable::serialize(const Program::MemOp &obj, Serializer &serializer) { + serializer.increase_container_depth(); + serde::Serializable::serialize(obj.operation, serializer); + serde::Serializable::serialize(obj.index, serializer); + serde::Serializable::serialize(obj.value, serializer); + serializer.decrease_container_depth(); } template <> template -Program::MemoryAddress -serde::Deserializable::deserialize( - Deserializer &deserializer) { - deserializer.increase_container_depth(); - Program::MemoryAddress obj; - obj.value = - serde::Deserializable::deserialize(deserializer); - deserializer.decrease_container_depth(); - return obj; +Program::MemOp serde::Deserializable::deserialize(Deserializer &deserializer) { + deserializer.increase_container_depth(); + Program::MemOp obj; + obj.operation = serde::Deserializable::deserialize(deserializer); + obj.index = serde::Deserializable::deserialize(deserializer); + obj.value = serde::Deserializable::deserialize(deserializer); + deserializer.decrease_container_depth(); + return obj; } namespace Program { -inline bool operator==(const Opcode &lhs, const Opcode &rhs) { - if (!(lhs.value == rhs.value)) { - return false; - } - return true; -} + inline bool operator==(const MemoryAddress &lhs, const MemoryAddress &rhs) { + if (!(lhs.value == rhs.value)) { return false; } + return true; + } -inline std::vector Opcode::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector MemoryAddress::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline Opcode Opcode::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; -} + inline MemoryAddress MemoryAddress::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize(const Program::Opcode &obj, - Serializer &serializer) { - serializer.increase_container_depth(); - serde::Serializable::serialize(obj.value, serializer); - serializer.decrease_container_depth(); +void serde::Serializable::serialize(const Program::MemoryAddress &obj, Serializer &serializer) { + serializer.increase_container_depth(); + serde::Serializable::serialize(obj.value, serializer); + serializer.decrease_container_depth(); } template <> template -Program::Opcode serde::Deserializable::deserialize( - Deserializer &deserializer) { - deserializer.increase_container_depth(); - Program::Opcode obj; - obj.value = - serde::Deserializable::deserialize(deserializer); - deserializer.decrease_container_depth(); - return obj; +Program::MemoryAddress serde::Deserializable::deserialize(Deserializer &deserializer) { + deserializer.increase_container_depth(); + Program::MemoryAddress obj; + obj.value = serde::Deserializable::deserialize(deserializer); + deserializer.decrease_container_depth(); + return obj; } namespace Program { -inline bool operator==(const Opcode::AssertZero &lhs, - const Opcode::AssertZero &rhs) { - if (!(lhs.value == rhs.value)) { - return false; - } - return true; -} + inline bool operator==(const Opcode &lhs, const Opcode &rhs) { + if (!(lhs.value == rhs.value)) { return false; } + return true; + } -inline std::vector Opcode::AssertZero::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector Opcode::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline Opcode::AssertZero -Opcode::AssertZero::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; -} + inline Opcode Opcode::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::Opcode::AssertZero &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.value, serializer); +void serde::Serializable::serialize(const Program::Opcode &obj, Serializer &serializer) { + serializer.increase_container_depth(); + serde::Serializable::serialize(obj.value, serializer); + serializer.decrease_container_depth(); } template <> template -Program::Opcode::AssertZero -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::Opcode::AssertZero obj; - obj.value = - serde::Deserializable::deserialize(deserializer); - return obj; +Program::Opcode serde::Deserializable::deserialize(Deserializer &deserializer) { + deserializer.increase_container_depth(); + Program::Opcode obj; + obj.value = serde::Deserializable::deserialize(deserializer); + deserializer.decrease_container_depth(); + return obj; } namespace Program { -inline bool operator==(const Opcode::BlackBoxFuncCall &lhs, - const Opcode::BlackBoxFuncCall &rhs) { - if (!(lhs.value == rhs.value)) { - return false; - } - return true; -} + inline bool operator==(const Opcode::AssertZero &lhs, const Opcode::AssertZero &rhs) { + if (!(lhs.value == rhs.value)) { return false; } + return true; + } -inline std::vector Opcode::BlackBoxFuncCall::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector Opcode::AssertZero::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline Opcode::BlackBoxFuncCall -Opcode::BlackBoxFuncCall::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; -} + inline Opcode::AssertZero Opcode::AssertZero::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::Opcode::BlackBoxFuncCall &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.value, serializer); +void serde::Serializable::serialize(const Program::Opcode::AssertZero &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.value, serializer); } template <> template -Program::Opcode::BlackBoxFuncCall -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::Opcode::BlackBoxFuncCall obj; - obj.value = - serde::Deserializable::deserialize(deserializer); - return obj; +Program::Opcode::AssertZero serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::Opcode::AssertZero obj; + obj.value = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -inline bool operator==(const Opcode::Directive &lhs, - const Opcode::Directive &rhs) { - if (!(lhs.value == rhs.value)) { - return false; - } - return true; -} + inline bool operator==(const Opcode::BlackBoxFuncCall &lhs, const Opcode::BlackBoxFuncCall &rhs) { + if (!(lhs.value == rhs.value)) { return false; } + return true; + } -inline std::vector Opcode::Directive::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector Opcode::BlackBoxFuncCall::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline Opcode::Directive -Opcode::Directive::bincodeDeserialize(std::vector input) { - auto deserializer = serde::BincodeDeserializer(input); - auto value = - serde::Deserializable::deserialize(deserializer); - if (deserializer.get_buffer_offset() < input.size()) { - throw serde::deserialization_error("Some input bytes were not read"); - } - return value; -} + inline Opcode::BlackBoxFuncCall Opcode::BlackBoxFuncCall::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::Opcode::Directive &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.value, serializer); +void serde::Serializable::serialize(const Program::Opcode::BlackBoxFuncCall &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.value, serializer); } template <> template -Program::Opcode::Directive -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::Opcode::Directive obj; - obj.value = - serde::Deserializable::deserialize(deserializer); - return obj; +Program::Opcode::BlackBoxFuncCall serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::Opcode::BlackBoxFuncCall obj; + obj.value = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -inline bool operator==(const Opcode::Brillig &lhs, const Opcode::Brillig &rhs) { - if (!(lhs.value == rhs.value)) { - return false; - } - return true; -} + inline bool operator==(const Opcode::Directive &lhs, const Opcode::Directive &rhs) { + if (!(lhs.value == rhs.value)) { return false; } + return true; + } -inline std::vector Opcode::Brillig::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector Opcode::Directive::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline Opcode::Brillig -Opcode::Brillig::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; -} + inline Opcode::Directive Opcode::Directive::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::Opcode::Brillig &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.value, serializer); +void serde::Serializable::serialize(const Program::Opcode::Directive &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.value, serializer); } template <> template -Program::Opcode::Brillig -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::Opcode::Brillig obj; - obj.value = - serde::Deserializable::deserialize(deserializer); - return obj; +Program::Opcode::Directive serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::Opcode::Directive obj; + obj.value = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -inline bool operator==(const Opcode::MemoryOp &lhs, - const Opcode::MemoryOp &rhs) { - if (!(lhs.block_id == rhs.block_id)) { - return false; - } - if (!(lhs.op == rhs.op)) { - return false; - } - if (!(lhs.predicate == rhs.predicate)) { - return false; - } - return true; -} + inline bool operator==(const Opcode::Brillig &lhs, const Opcode::Brillig &rhs) { + if (!(lhs.value == rhs.value)) { return false; } + return true; + } -inline std::vector Opcode::MemoryOp::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector Opcode::Brillig::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline Opcode::MemoryOp -Opcode::MemoryOp::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; -} + inline Opcode::Brillig Opcode::Brillig::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::Opcode::MemoryOp &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.block_id, - serializer); - serde::Serializable::serialize(obj.op, serializer); - serde::Serializable::serialize(obj.predicate, - serializer); +void serde::Serializable::serialize(const Program::Opcode::Brillig &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.value, serializer); } template <> template -Program::Opcode::MemoryOp -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::Opcode::MemoryOp obj; - obj.block_id = - serde::Deserializable::deserialize(deserializer); - obj.op = serde::Deserializable::deserialize(deserializer); - obj.predicate = - serde::Deserializable::deserialize(deserializer); - return obj; +Program::Opcode::Brillig serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::Opcode::Brillig obj; + obj.value = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -inline bool operator==(const Opcode::MemoryInit &lhs, - const Opcode::MemoryInit &rhs) { - if (!(lhs.block_id == rhs.block_id)) { - return false; - } - if (!(lhs.init == rhs.init)) { - return false; - } - return true; -} + inline bool operator==(const Opcode::MemoryOp &lhs, const Opcode::MemoryOp &rhs) { + if (!(lhs.block_id == rhs.block_id)) { return false; } + if (!(lhs.op == rhs.op)) { return false; } + if (!(lhs.predicate == rhs.predicate)) { return false; } + return true; + } -inline std::vector Opcode::MemoryInit::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector Opcode::MemoryOp::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline Opcode::MemoryInit -Opcode::MemoryInit::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; -} + inline Opcode::MemoryOp Opcode::MemoryOp::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::Opcode::MemoryInit &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.block_id, - serializer); - serde::Serializable::serialize(obj.init, serializer); +void serde::Serializable::serialize(const Program::Opcode::MemoryOp &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.block_id, serializer); + serde::Serializable::serialize(obj.op, serializer); + serde::Serializable::serialize(obj.predicate, serializer); } template <> template -Program::Opcode::MemoryInit -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::Opcode::MemoryInit obj; - obj.block_id = - serde::Deserializable::deserialize(deserializer); - obj.init = - serde::Deserializable::deserialize(deserializer); - return obj; +Program::Opcode::MemoryOp serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::Opcode::MemoryOp obj; + obj.block_id = serde::Deserializable::deserialize(deserializer); + obj.op = serde::Deserializable::deserialize(deserializer); + obj.predicate = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -inline bool operator==(const Opcode::Call &lhs, const Opcode::Call &rhs) { - if (!(lhs.id == rhs.id)) { - return false; - } - if (!(lhs.inputs == rhs.inputs)) { - return false; - } - if (!(lhs.outputs == rhs.outputs)) { - return false; - } - return true; -} + inline bool operator==(const Opcode::MemoryInit &lhs, const Opcode::MemoryInit &rhs) { + if (!(lhs.block_id == rhs.block_id)) { return false; } + if (!(lhs.init == rhs.init)) { return false; } + return true; + } -inline std::vector Opcode::Call::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector Opcode::MemoryInit::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline Opcode::Call -Opcode::Call::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; -} + inline Opcode::MemoryInit Opcode::MemoryInit::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::Opcode::Call &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.id, serializer); - serde::Serializable::serialize(obj.inputs, serializer); - serde::Serializable::serialize(obj.outputs, - serializer); +void serde::Serializable::serialize(const Program::Opcode::MemoryInit &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.block_id, serializer); + serde::Serializable::serialize(obj.init, serializer); } template <> template -Program::Opcode::Call serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::Opcode::Call obj; - obj.id = serde::Deserializable::deserialize(deserializer); - obj.inputs = - serde::Deserializable::deserialize(deserializer); - obj.outputs = - serde::Deserializable::deserialize(deserializer); - return obj; +Program::Opcode::MemoryInit serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::Opcode::MemoryInit obj; + obj.block_id = serde::Deserializable::deserialize(deserializer); + obj.init = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -inline bool operator==(const OpcodeLocation &lhs, const OpcodeLocation &rhs) { - if (!(lhs.value == rhs.value)) { - return false; - } - return true; -} + inline bool operator==(const Opcode::Call &lhs, const Opcode::Call &rhs) { + if (!(lhs.id == rhs.id)) { return false; } + if (!(lhs.inputs == rhs.inputs)) { return false; } + if (!(lhs.outputs == rhs.outputs)) { return false; } + return true; + } -inline std::vector OpcodeLocation::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector Opcode::Call::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline OpcodeLocation -OpcodeLocation::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; -} + inline Opcode::Call Opcode::Call::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::OpcodeLocation &obj, Serializer &serializer) { - serializer.increase_container_depth(); - serde::Serializable::serialize(obj.value, serializer); - serializer.decrease_container_depth(); +void serde::Serializable::serialize(const Program::Opcode::Call &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.id, serializer); + serde::Serializable::serialize(obj.inputs, serializer); + serde::Serializable::serialize(obj.outputs, serializer); } template <> template -Program::OpcodeLocation -serde::Deserializable::deserialize( - Deserializer &deserializer) { - deserializer.increase_container_depth(); - Program::OpcodeLocation obj; - obj.value = - serde::Deserializable::deserialize(deserializer); - deserializer.decrease_container_depth(); - return obj; +Program::Opcode::Call serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::Opcode::Call obj; + obj.id = serde::Deserializable::deserialize(deserializer); + obj.inputs = serde::Deserializable::deserialize(deserializer); + obj.outputs = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -inline bool operator==(const OpcodeLocation::Acir &lhs, - const OpcodeLocation::Acir &rhs) { - if (!(lhs.value == rhs.value)) { - return false; - } - return true; -} + inline bool operator==(const OpcodeLocation &lhs, const OpcodeLocation &rhs) { + if (!(lhs.value == rhs.value)) { return false; } + return true; + } -inline std::vector OpcodeLocation::Acir::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector OpcodeLocation::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline OpcodeLocation::Acir -OpcodeLocation::Acir::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; -} + inline OpcodeLocation OpcodeLocation::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::OpcodeLocation::Acir &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.value, serializer); +void serde::Serializable::serialize(const Program::OpcodeLocation &obj, Serializer &serializer) { + serializer.increase_container_depth(); + serde::Serializable::serialize(obj.value, serializer); + serializer.decrease_container_depth(); } template <> template -Program::OpcodeLocation::Acir -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::OpcodeLocation::Acir obj; - obj.value = - serde::Deserializable::deserialize(deserializer); - return obj; +Program::OpcodeLocation serde::Deserializable::deserialize(Deserializer &deserializer) { + deserializer.increase_container_depth(); + Program::OpcodeLocation obj; + obj.value = serde::Deserializable::deserialize(deserializer); + deserializer.decrease_container_depth(); + return obj; } namespace Program { -inline bool operator==(const OpcodeLocation::Brillig &lhs, - const OpcodeLocation::Brillig &rhs) { - if (!(lhs.acir_index == rhs.acir_index)) { - return false; - } - if (!(lhs.brillig_index == rhs.brillig_index)) { - return false; - } - return true; -} + inline bool operator==(const OpcodeLocation::Acir &lhs, const OpcodeLocation::Acir &rhs) { + if (!(lhs.value == rhs.value)) { return false; } + return true; + } -inline std::vector OpcodeLocation::Brillig::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector OpcodeLocation::Acir::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline OpcodeLocation::Brillig -OpcodeLocation::Brillig::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; -} + inline OpcodeLocation::Acir OpcodeLocation::Acir::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::OpcodeLocation::Brillig &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.acir_index, - serializer); - serde::Serializable::serialize(obj.brillig_index, - serializer); +void serde::Serializable::serialize(const Program::OpcodeLocation::Acir &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.value, serializer); } template <> template -Program::OpcodeLocation::Brillig -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::OpcodeLocation::Brillig obj; - obj.acir_index = serde::Deserializable::deserialize( - deserializer); - obj.brillig_index = - serde::Deserializable::deserialize( - deserializer); - return obj; +Program::OpcodeLocation::Acir serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::OpcodeLocation::Acir obj; + obj.value = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -inline bool operator==(const Program &lhs, const Program &rhs) { - if (!(lhs.functions == rhs.functions)) { - return false; - } - return true; -} + inline bool operator==(const OpcodeLocation::Brillig &lhs, const OpcodeLocation::Brillig &rhs) { + if (!(lhs.acir_index == rhs.acir_index)) { return false; } + if (!(lhs.brillig_index == rhs.brillig_index)) { return false; } + return true; + } -inline std::vector Program::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector OpcodeLocation::Brillig::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline Program Program::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; -} + inline OpcodeLocation::Brillig OpcodeLocation::Brillig::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::Program &obj, Serializer &serializer) { - serializer.increase_container_depth(); - serde::Serializable::serialize(obj.functions, - serializer); - serializer.decrease_container_depth(); +void serde::Serializable::serialize(const Program::OpcodeLocation::Brillig &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.acir_index, serializer); + serde::Serializable::serialize(obj.brillig_index, serializer); } template <> template -Program::Program serde::Deserializable::deserialize( - Deserializer &deserializer) { - deserializer.increase_container_depth(); - Program::Program obj; - obj.functions = - serde::Deserializable::deserialize(deserializer); - deserializer.decrease_container_depth(); - return obj; +Program::OpcodeLocation::Brillig serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::OpcodeLocation::Brillig obj; + obj.acir_index = serde::Deserializable::deserialize(deserializer); + obj.brillig_index = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -inline bool operator==(const PublicInputs &lhs, const PublicInputs &rhs) { - if (!(lhs.value == rhs.value)) { - return false; - } - return true; -} + inline bool operator==(const Program &lhs, const Program &rhs) { + if (!(lhs.functions == rhs.functions)) { return false; } + return true; + } -inline std::vector PublicInputs::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector Program::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline PublicInputs -PublicInputs::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; -} + inline Program Program::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::PublicInputs &obj, Serializer &serializer) { - serializer.increase_container_depth(); - serde::Serializable::serialize(obj.value, serializer); - serializer.decrease_container_depth(); +void serde::Serializable::serialize(const Program::Program &obj, Serializer &serializer) { + serializer.increase_container_depth(); + serde::Serializable::serialize(obj.functions, serializer); + serializer.decrease_container_depth(); } template <> template -Program::PublicInputs serde::Deserializable::deserialize( - Deserializer &deserializer) { - deserializer.increase_container_depth(); - Program::PublicInputs obj; - obj.value = - serde::Deserializable::deserialize(deserializer); - deserializer.decrease_container_depth(); - return obj; +Program::Program serde::Deserializable::deserialize(Deserializer &deserializer) { + deserializer.increase_container_depth(); + Program::Program obj; + obj.functions = serde::Deserializable::deserialize(deserializer); + deserializer.decrease_container_depth(); + return obj; } namespace Program { -inline bool operator==(const Value &lhs, const Value &rhs) { - if (!(lhs.inner == rhs.inner)) { - return false; - } - return true; -} + inline bool operator==(const PublicInputs &lhs, const PublicInputs &rhs) { + if (!(lhs.value == rhs.value)) { return false; } + return true; + } -inline std::vector Value::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector PublicInputs::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline Value Value::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; -} + inline PublicInputs PublicInputs::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize(const Program::Value &obj, - Serializer &serializer) { - serializer.increase_container_depth(); - serde::Serializable::serialize(obj.inner, serializer); - serializer.decrease_container_depth(); +void serde::Serializable::serialize(const Program::PublicInputs &obj, Serializer &serializer) { + serializer.increase_container_depth(); + serde::Serializable::serialize(obj.value, serializer); + serializer.decrease_container_depth(); } template <> template -Program::Value -serde::Deserializable::deserialize(Deserializer &deserializer) { - deserializer.increase_container_depth(); - Program::Value obj; - obj.inner = - serde::Deserializable::deserialize(deserializer); - deserializer.decrease_container_depth(); - return obj; +Program::PublicInputs serde::Deserializable::deserialize(Deserializer &deserializer) { + deserializer.increase_container_depth(); + Program::PublicInputs obj; + obj.value = serde::Deserializable::deserialize(deserializer); + deserializer.decrease_container_depth(); + return obj; } namespace Program { -inline bool operator==(const ValueOrArray &lhs, const ValueOrArray &rhs) { - if (!(lhs.value == rhs.value)) { - return false; - } - return true; -} + inline bool operator==(const Value &lhs, const Value &rhs) { + if (!(lhs.inner == rhs.inner)) { return false; } + return true; + } -inline std::vector ValueOrArray::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector Value::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline ValueOrArray -ValueOrArray::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; -} + inline Value Value::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::ValueOrArray &obj, Serializer &serializer) { - serializer.increase_container_depth(); - serde::Serializable::serialize(obj.value, serializer); - serializer.decrease_container_depth(); +void serde::Serializable::serialize(const Program::Value &obj, Serializer &serializer) { + serializer.increase_container_depth(); + serde::Serializable::serialize(obj.inner, serializer); + serializer.decrease_container_depth(); } template <> template -Program::ValueOrArray serde::Deserializable::deserialize( - Deserializer &deserializer) { - deserializer.increase_container_depth(); - Program::ValueOrArray obj; - obj.value = - serde::Deserializable::deserialize(deserializer); - deserializer.decrease_container_depth(); - return obj; +Program::Value serde::Deserializable::deserialize(Deserializer &deserializer) { + deserializer.increase_container_depth(); + Program::Value obj; + obj.inner = serde::Deserializable::deserialize(deserializer); + deserializer.decrease_container_depth(); + return obj; } namespace Program { -inline bool operator==(const ValueOrArray::MemoryAddress &lhs, - const ValueOrArray::MemoryAddress &rhs) { - if (!(lhs.value == rhs.value)) { - return false; - } - return true; -} + inline bool operator==(const ValueOrArray &lhs, const ValueOrArray &rhs) { + if (!(lhs.value == rhs.value)) { return false; } + return true; + } -inline std::vector -ValueOrArray::MemoryAddress::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, - serializer); - return std::move(serializer).bytes(); -} + inline std::vector ValueOrArray::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline ValueOrArray::MemoryAddress -ValueOrArray::MemoryAddress::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; -} + inline ValueOrArray ValueOrArray::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::ValueOrArray::MemoryAddress &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.value, serializer); +void serde::Serializable::serialize(const Program::ValueOrArray &obj, Serializer &serializer) { + serializer.increase_container_depth(); + serde::Serializable::serialize(obj.value, serializer); + serializer.decrease_container_depth(); } template <> template -Program::ValueOrArray::MemoryAddress -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::ValueOrArray::MemoryAddress obj; - obj.value = - serde::Deserializable::deserialize(deserializer); - return obj; +Program::ValueOrArray serde::Deserializable::deserialize(Deserializer &deserializer) { + deserializer.increase_container_depth(); + Program::ValueOrArray obj; + obj.value = serde::Deserializable::deserialize(deserializer); + deserializer.decrease_container_depth(); + return obj; } namespace Program { -inline bool operator==(const ValueOrArray::HeapArray &lhs, - const ValueOrArray::HeapArray &rhs) { - if (!(lhs.value == rhs.value)) { - return false; - } - return true; -} + inline bool operator==(const ValueOrArray::MemoryAddress &lhs, const ValueOrArray::MemoryAddress &rhs) { + if (!(lhs.value == rhs.value)) { return false; } + return true; + } -inline std::vector ValueOrArray::HeapArray::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector ValueOrArray::MemoryAddress::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline ValueOrArray::HeapArray -ValueOrArray::HeapArray::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; -} + inline ValueOrArray::MemoryAddress ValueOrArray::MemoryAddress::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::ValueOrArray::HeapArray &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.value, serializer); +void serde::Serializable::serialize(const Program::ValueOrArray::MemoryAddress &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.value, serializer); } template <> template -Program::ValueOrArray::HeapArray -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::ValueOrArray::HeapArray obj; - obj.value = - serde::Deserializable::deserialize(deserializer); - return obj; +Program::ValueOrArray::MemoryAddress serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::ValueOrArray::MemoryAddress obj; + obj.value = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -inline bool operator==(const ValueOrArray::HeapVector &lhs, - const ValueOrArray::HeapVector &rhs) { - if (!(lhs.value == rhs.value)) { - return false; - } - return true; -} + inline bool operator==(const ValueOrArray::HeapArray &lhs, const ValueOrArray::HeapArray &rhs) { + if (!(lhs.value == rhs.value)) { return false; } + return true; + } -inline std::vector ValueOrArray::HeapVector::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); -} + inline std::vector ValueOrArray::HeapArray::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline ValueOrArray::HeapVector -ValueOrArray::HeapVector::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; -} + inline ValueOrArray::HeapArray ValueOrArray::HeapArray::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::ValueOrArray::HeapVector &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.value, serializer); +void serde::Serializable::serialize(const Program::ValueOrArray::HeapArray &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.value, serializer); } template <> template -Program::ValueOrArray::HeapVector -serde::Deserializable::deserialize( - Deserializer &deserializer) { - Program::ValueOrArray::HeapVector obj; - obj.value = - serde::Deserializable::deserialize(deserializer); - return obj; +Program::ValueOrArray::HeapArray serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::ValueOrArray::HeapArray obj; + obj.value = serde::Deserializable::deserialize(deserializer); + return obj; } namespace Program { -inline bool operator==(const Witness &lhs, const Witness &rhs) { - if (!(lhs.value == rhs.value)) { - return false; - } - return true; -} + inline bool operator==(const ValueOrArray::HeapVector &lhs, const ValueOrArray::HeapVector &rhs) { + if (!(lhs.value == rhs.value)) { return false; } + return true; + } + + inline std::vector ValueOrArray::HeapVector::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } -inline std::vector Witness::bincodeSerialize() const { - auto serializer = serde::BincodeSerializer(); - serde::Serializable::serialize(*this, serializer); - return std::move(serializer).bytes(); + inline ValueOrArray::HeapVector ValueOrArray::HeapVector::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } + +} // end of namespace Program + +template <> +template +void serde::Serializable::serialize(const Program::ValueOrArray::HeapVector &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.value, serializer); } -inline Witness Witness::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; +template <> +template +Program::ValueOrArray::HeapVector serde::Deserializable::deserialize(Deserializer &deserializer) { + Program::ValueOrArray::HeapVector obj; + obj.value = serde::Deserializable::deserialize(deserializer); + return obj; } +namespace Program { + + inline bool operator==(const Witness &lhs, const Witness &rhs) { + if (!(lhs.value == rhs.value)) { return false; } + return true; + } + + inline std::vector Witness::bincodeSerialize() const { + auto serializer = serde::BincodeSerializer(); + serde::Serializable::serialize(*this, serializer); + return std::move(serializer).bytes(); + } + + inline Witness Witness::bincodeDeserialize(std::vector input) { + auto deserializer = serde::BincodeDeserializer(input); + auto value = serde::Deserializable::deserialize(deserializer); + if (deserializer.get_buffer_offset() < input.size()) { + throw serde::deserialization_error("Some input bytes were not read"); + } + return value; + } + } // end of namespace Program template <> template -void serde::Serializable::serialize( - const Program::Witness &obj, Serializer &serializer) { - serializer.increase_container_depth(); - serde::Serializable::serialize(obj.value, serializer); - serializer.decrease_container_depth(); +void serde::Serializable::serialize(const Program::Witness &obj, Serializer &serializer) { + serializer.increase_container_depth(); + serde::Serializable::serialize(obj.value, serializer); + serializer.decrease_container_depth(); } template <> template -Program::Witness serde::Deserializable::deserialize( - Deserializer &deserializer) { - deserializer.increase_container_depth(); - Program::Witness obj; - obj.value = - serde::Deserializable::deserialize(deserializer); - deserializer.decrease_container_depth(); - return obj; +Program::Witness serde::Deserializable::deserialize(Deserializer &deserializer) { + deserializer.increase_container_depth(); + Program::Witness obj; + obj.value = serde::Deserializable::deserialize(deserializer); + deserializer.decrease_container_depth(); + return obj; } From 6dd0f09eaf44b803a6bd52c658224ef984998aab Mon Sep 17 00:00:00 2001 From: vezenovm Date: Wed, 20 Mar 2024 02:58:11 +0000 Subject: [PATCH 094/139] do not acir gen non-brillig main funcs as they can contain references --- .../compiler/noirc_evaluator/src/ssa.rs | 16 ++-- .../src/ssa/acir_gen/acir_ir/acir_variable.rs | 13 ++- .../noirc_evaluator/src/ssa/acir_gen/mod.rs | 83 ++++++++++--------- .../noirc_evaluator/src/ssa/opt/inlining.rs | 7 -- .../noirc_evaluator/src/ssa/ssa_gen/mod.rs | 1 - .../src/hir/resolution/resolver.rs | 6 -- .../src/monomorphization/mod.rs | 2 +- .../execution_success/fold_basic/src/main.nr | 13 ++- 8 files changed, 74 insertions(+), 67 deletions(-) diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs index 9290601b215e..dba4f3e5497a 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs @@ -73,10 +73,6 @@ pub(crate) fn optimize_into_acir( let last_array_uses = ssa.find_last_array_uses(); - // map(|(i, (id, _)| { - // ssa.id_to_index.insert(*id, *i); - // }); - ssa.into_acir(brillig, abi_distinctness, &last_array_uses) } @@ -165,6 +161,7 @@ pub fn create_program( (AcirProgram, Vec, Vec>, Vec, Vec), RuntimeError, > { + let func_names = program.functions.iter().map(|function| function.name.clone()).collect::>(); // TODO: Check whether the debug tracker stores information across the program and not just main let debug_variables = program.debug_variables.clone(); let debug_types = program.debug_types.clone(); @@ -191,7 +188,9 @@ pub fn create_program( let mut main_return_witnesses = Vec::new(); // Using a flag here to avoid enumarting the loop as main is expected to be the first circuit let mut is_main = true; + let mut index = 0; for (acir, func_sig) in generated_acir.into_iter().zip(func_sigs) { + // dbg!(func_names[index].clone()); let (circuit, debug_info, warnings, input_witnesses, return_witnesses) = convert_generated_acir_into_circuit( acir, @@ -200,6 +199,7 @@ pub fn create_program( debug_variables.clone(), debug_functions.clone(), debug_types.clone(), + is_main, ); functions.push(circuit); debug_infos.push(debug_info); @@ -209,6 +209,7 @@ pub fn create_program( main_return_witnesses = return_witnesses; } is_main = false; + index += 1; } let program = AcirProgram { functions }; @@ -223,6 +224,7 @@ fn convert_generated_acir_into_circuit( debug_variables: DebugVariables, debug_functions: DebugFunctions, debug_types: DebugTypes, + is_main: bool, ) -> (Circuit, DebugInfo, Vec, Vec, Vec) { let opcodes = generated_acir.take_opcodes(); let current_witness_index = generated_acir.current_witness_index().0; @@ -237,8 +239,10 @@ fn convert_generated_acir_into_circuit( let locations = locations.clone(); - let (public_parameter_witnesses, private_parameters) = - split_public_and_private_inputs(&func_sig, &input_witnesses); + // let (public_parameter_witnesses, private_parameters) = + // split_public_and_private_inputs(&func_sig, &input_witnesses); + + let (public_parameter_witnesses, private_parameters) = if is_main { split_public_and_private_inputs(&func_sig, &input_witnesses) } else { (BTreeSet::default(), BTreeSet::default()) }; let public_parameters = PublicInputs(public_parameter_witnesses); let return_values = PublicInputs(return_witnesses.iter().copied().collect()); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs index 60d6afb6a96f..e60c1cdff2cc 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs @@ -1772,7 +1772,7 @@ impl AcirContext { id: u32, inputs: Vec, output_count: usize, - ) -> Result<(), RuntimeError> { + ) -> Result, RuntimeError> { let inputs = self.prepare_inputs_for_black_box_func_call(inputs)?; let inputs = inputs .iter() @@ -1780,8 +1780,17 @@ impl AcirContext { .collect::>(); let outputs = vecmap(0..output_count, |_| self.acir_ir.next_witness_index()); + // 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 + let results = vecmap(&outputs, |witness_index| { + self.add_data(AcirVarData::Witness(*witness_index)) + }); + self.acir_ir.push_opcode(Opcode::Call { id, inputs, outputs }); - Ok(()) + Ok(results) } } diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs index 4b54e7f54b12..e0d8e2c1cb9d 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs @@ -190,10 +190,12 @@ impl Ssa { let mut acirs = Vec::new(); for (_, function) in &self.functions { let context = Context::new(); - let generated_acir = - context.convert_ssa_function(&self, function, &brillig, last_array_uses)?; + // let generated_acir = + // // context.convert_ssa_function(&self, function, &brillig, last_array_uses)?; - acirs.push(generated_acir); + if let Some(generated_acir) = context.convert_ssa_function(&self, function, &brillig, last_array_uses)? { + acirs.push(generated_acir); + } } // dbg!(acirs.clone()); // TODO: check wheter doing this for a single circuit's return witnessese is correct. @@ -244,49 +246,23 @@ impl Context { } } - // /// Converts SSA into ACIR - // fn convert_ssa( - // &mut self, - // ssa: Ssa, - // brillig: Brillig, - // last_array_uses: &HashMap, - // ) -> Result { - // let mut acirs = Vec::new(); - // for (id, function) in &ssa.functions { - // let x = match function.runtime() { - // RuntimeType::Acir(_) => { - // // TODO: remove this brillig clone - // self.convert_acir_main(function, &ssa, &brillig, last_array_uses) - // } - // RuntimeType::Brillig => { - // self.convert_brillig_main(function, &brillig) - // } - // }; - // // println!("acir for {id}: {}",); - // println!("acir for {id}"); - // dbg!(x.clone()); - // acirs.push(x); - // } - // acirs[0].clone() - // // let main_func = ssa.main(); - // // match main_func.runtime() { - // // // TODO: hanlde this shit - // // RuntimeType::Acir(_) => self.convert_acir_main(main_func, &ssa, &brillig, last_array_uses), - // // RuntimeType::Brillig => self.convert_brillig_main(main_func, &brillig), - // // } - // } - fn convert_ssa_function( self, ssa: &Ssa, function: &Function, brillig: &Brillig, last_array_uses: &HashMap, - ) -> Result { + ) -> Result, RuntimeError> { match function.runtime() { // TODO: hanlde this shit - RuntimeType::Acir(_) => self.convert_acir_main(function, ssa, brillig, last_array_uses), - RuntimeType::Brillig => self.convert_brillig_main(function, brillig), + RuntimeType::Acir(_) => Ok(Some(self.convert_acir_main(function, ssa, brillig, last_array_uses)?)), + RuntimeType::Brillig => { + if function.id() == ssa.main_id { + Ok(Some(self.convert_brillig_main(function, brillig)?)) + } else { + Ok(None) + } + } } } @@ -323,7 +299,7 @@ impl Context { brillig: &Brillig, ) -> Result { let dfg = &main_func.dfg; - + let inputs = try_vecmap(dfg[main_func.entry_block()].parameters(), |param_id| { let typ = dfg.type_of_value(*param_id); self.create_value_from_type(&typ, &mut |this, _| Ok(this.acir_context.add_variable())) @@ -593,18 +569,43 @@ impl Context { let inputs = vecmap(arguments, |arg| self.convert_value(*arg, dfg)); let output_count = result_ids.iter().fold(0usize, |sum, result_id| { - sum + dfg.try_get_array_length(*result_id).expect("ICE: need to implement returning slices from folded functions") + // TODO: handle complex return types from ACIR functions + sum + dfg.try_get_array_length(*result_id).unwrap_or(1) }); let final_program_id = ssa .id_to_index .get(id) .expect("ICE: should have an associated final index"); - self.acir_context.call_acir_function( + let result_vars = self.acir_context.call_acir_function( *final_program_id, inputs, output_count, )?; + let result_values = self.convert_vars_to_values(result_vars, dfg, result_ids); + for (result, output) in result_ids.iter().zip(result_values) { + match &output { + // We need to make sure we initialize arrays returned from intrinsic calls + // or else they will fail if accessed with a dynamic index + AcirValue::Array(_) => { + let block_id = self.block_id(result); + let array_typ = dfg.type_of_value(*result); + let len = if matches!(array_typ, Type::Array(_, _)) { + array_typ.flattened_size() + } else { + Self::flattened_value_size(&output) + }; + self.initialize_array(block_id, len, Some(output.clone()))?; + } + AcirValue::DynamicArray(_) => { + // Do nothing as a dynamic array returned from a slice intrinsic should already be initialized + } + AcirValue::Var(_, _) => { + // Do nothing + } + } + self.ssa_values.insert(*result, output); + } } RuntimeType::Brillig => { // Check that we are not attempting to return a slice from diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/inlining.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/inlining.rs index d93d98ee229c..e88ea149ff8f 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/inlining.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/inlining.rs @@ -100,8 +100,6 @@ fn get_entry_point_functions(ssa: &Ssa) -> BTreeSet { let functions = ssa.functions.iter(); let mut entry_points = functions .filter(|(_, function)| { - dbg!(function.runtime()); - dbg!(function.id()); let inline_filter = match function.runtime() { RuntimeType::Acir(inline_type) => match inline_type { InlineType::Inline => false, @@ -109,9 +107,7 @@ fn get_entry_point_functions(ssa: &Ssa) -> BTreeSet { }, RuntimeType::Brillig => true, }; - dbg!(inline_filter); inline_filter - // function.runtime() == RuntimeType::Brillig }) .map(|(id, _)| *id) .collect::>(); @@ -363,13 +359,10 @@ impl<'function> PerFunctionContext<'function> { match &self.source_function.dfg[*id] { Instruction::Call { func, arguments } => match self.get_function(*func) { Some(function) => match ssa.functions[&function].runtime() { - // TODO: update this to differentiate the inline types RuntimeType::Acir(InlineType::Inline) => { - dbg!(function); self.inline_function(ssa, *id, function, arguments) } RuntimeType::Acir(InlineType::Fold) | RuntimeType::Brillig => { - dbg!(function); self.push_instruction(*id) } }, diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs index 6d71cfc3abb2..22581ba448d9 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs @@ -55,7 +55,6 @@ pub(crate) fn generate_ssa( // Queue the main function for compilation context.get_or_queue_function(main_id); - dbg!(main.should_fold); let main_inline_type = if main.should_fold { InlineType::Fold } else { InlineType::Inline }; let mut function_context = FunctionContext::new( main.name.clone(), diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/resolver.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/resolver.rs index 6281b1d55085..b299026a3fbe 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/resolver.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/resolver.rs @@ -981,12 +981,6 @@ impl<'a> Resolver<'a> { .function .as_ref() .map_or(true, |func_attribute| !func_attribute.is_foldable()); - if func.name() == "basic_func" { - dbg!(attributes.clone()); - } - // if matches!(attributes.function, Some(FunctionAttribute::Fold)) { - // dbg!(name_ident.clone()); - // } FuncMeta { name: name_ident, diff --git a/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/mod.rs b/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/mod.rs index 934c4e06e388..1e877ef26cc3 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/mod.rs @@ -307,6 +307,7 @@ impl<'interner> Monomorphizer<'interner> { let meta = self.interner.function_meta(&f).clone(); let func_sig = meta.function_signature(); + let modifiers = self.interner.function_modifiers(&f); let name = self.interner.function_name(&f).to_owned(); @@ -319,7 +320,6 @@ impl<'interner> Monomorphizer<'interner> { let unconstrained = modifiers.is_unconstrained; let should_fold = !meta.should_inline; - dbg!(should_fold); let parameters = self.parameters(&meta.parameters); let body = self.expr(body_expr_id)?; diff --git a/noir/noir-repo/test_programs/execution_success/fold_basic/src/main.nr b/noir/noir-repo/test_programs/execution_success/fold_basic/src/main.nr index 946f2528f788..266262c48b9d 100644 --- a/noir/noir-repo/test_programs/execution_success/fold_basic/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/fold_basic/src/main.nr @@ -1,9 +1,16 @@ fn main(x: Field, y: pub Field) { - basic_func(x, y); - basic_func(x, y); + let z = basic_func(x, y); + let z2 = basic_func(x, y); + assert(z == z2); } +// #[fold] +// fn basic_func(x: Field, y: Field) { +// assert(x != y); +// } + #[fold] -fn basic_func(x: Field, y: Field) { +fn basic_func(x: Field, y: Field) -> Field { assert(x != y); + x + y } From 2ed634a31df543c2d3036f6dc188046d37340b66 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Wed, 20 Mar 2024 17:05:34 +0000 Subject: [PATCH 095/139] clippy and other fixups --- .../compiler/noirc_driver/src/lib.rs | 5 +- .../compiler/noirc_evaluator/src/ssa.rs | 24 +- .../src/ssa/acir_gen/acir_ir/acir_variable.rs | 5 +- .../noirc_evaluator/src/ssa/acir_gen/mod.rs | 357 ++++++++++++++---- .../noirc_evaluator/src/ssa/ir/function.rs | 9 +- .../noirc_evaluator/src/ssa/opt/inlining.rs | 13 +- .../noirc_evaluator/src/ssa/opt/unrolling.rs | 3 +- .../execution_success/fold_basic/src/main.nr | 11 +- 8 files changed, 324 insertions(+), 103 deletions(-) diff --git a/noir/noir-repo/compiler/noirc_driver/src/lib.rs b/noir/noir-repo/compiler/noirc_driver/src/lib.rs index 2426ec1078dd..431c5c4926ed 100644 --- a/noir/noir-repo/compiler/noirc_driver/src/lib.rs +++ b/noir/noir-repo/compiler/noirc_driver/src/lib.rs @@ -3,13 +3,12 @@ #![warn(unreachable_pub)] #![warn(clippy::semicolon_if_nothing_returned)] -use acvm::acir::circuit::{ExpressionWidth, Program}; +use acvm::acir::circuit::ExpressionWidth; use clap::Args; use fm::{FileId, FileManager}; use iter_extended::vecmap; use noirc_abi::{AbiParameter, AbiType, ContractEvent}; use noirc_errors::{CustomDiagnostic, FileDiagnostic}; -use noirc_evaluator::create_circuit; use noirc_evaluator::create_program; use noirc_evaluator::errors::RuntimeError; use noirc_frontend::debug::build_debug_crate_file; @@ -292,7 +291,7 @@ pub fn compile_main( .map_err(FileDiagnostic::from)?; let compilation_warnings = - vecmap(compiled_program.warnings.clone(), |warnings| FileDiagnostic::from(warnings)); + vecmap(compiled_program.warnings.clone(), FileDiagnostic::from); if options.deny_warnings && !compilation_warnings.is_empty() { return Err(compilation_warnings); } diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs index dba4f3e5497a..6f7bf4ea9f6b 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs @@ -18,7 +18,6 @@ use acvm::acir::{ native_types::Witness, }; -use iter_extended::vecmap; use noirc_errors::debug_info::{DebugFunctions, DebugInfo, DebugTypes, DebugVariables}; use noirc_frontend::{ @@ -161,7 +160,6 @@ pub fn create_program( (AcirProgram, Vec, Vec>, Vec, Vec), RuntimeError, > { - let func_names = program.functions.iter().map(|function| function.name.clone()).collect::>(); // TODO: Check whether the debug tracker stores information across the program and not just main let debug_variables = program.debug_variables.clone(); let debug_types = program.debug_types.clone(); @@ -177,18 +175,21 @@ pub fn create_program( force_brillig_output, )?; - // let main_generated_acir = generated_acir.get(0).expect("ICE: Must have a main function"); - // let main_input_witnesses = main_generated_acir.input_witnesses; - // let main_return_witnesses = main_generated_acir.return_witnesses; - let mut functions = vec![]; let mut debug_infos = vec![]; let mut warning_infos = vec![]; let mut main_input_witnesses = Vec::new(); let mut main_return_witnesses = Vec::new(); - // Using a flag here to avoid enumarting the loop as main is expected to be the first circuit + // TODO: Using a flag here to avoid enumarting the loop as main is expected to be the first circuit + // We need function signatures to accurately set-up the `public_parameters` and `private_parameters` + // fields of a `Circuit`. However, a func_sig is restricted to what the main ABI allows. We need to be able + // to discern whether we have an ACIR function without an `InlineType::Inline` and treat that as an entry point function. + // For now we only treat main as an entry point function. + // Probably will need something like this: + // ``` + // let entry_point_funcs = program.functions.iter().map(|function| function.should_fold).collect::>(); + // ``` let mut is_main = true; - let mut index = 0; for (acir, func_sig) in generated_acir.into_iter().zip(func_sigs) { // dbg!(func_names[index].clone()); let (circuit, debug_info, warnings, input_witnesses, return_witnesses) = @@ -209,7 +210,6 @@ pub fn create_program( main_return_witnesses = return_witnesses; } is_main = false; - index += 1; } let program = AcirProgram { functions }; @@ -242,7 +242,11 @@ fn convert_generated_acir_into_circuit( // let (public_parameter_witnesses, private_parameters) = // split_public_and_private_inputs(&func_sig, &input_witnesses); - let (public_parameter_witnesses, private_parameters) = if is_main { split_public_and_private_inputs(&func_sig, &input_witnesses) } else { (BTreeSet::default(), BTreeSet::default()) }; + let (public_parameter_witnesses, private_parameters) = if is_main { + split_public_and_private_inputs(&func_sig, &input_witnesses) + } else { + (BTreeSet::default(), BTreeSet::default()) + }; let public_parameters = PublicInputs(public_parameter_witnesses); let return_values = PublicInputs(return_witnesses.iter().copied().collect()); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs index e60c1cdff2cc..09ea47dd5f26 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs @@ -1785,9 +1785,8 @@ impl AcirContext { // // We do not apply range information on the output of the black box function. // See issue #1439 - let results = vecmap(&outputs, |witness_index| { - self.add_data(AcirVarData::Witness(*witness_index)) - }); + let results = + vecmap(&outputs, |witness_index| self.add_data(AcirVarData::Witness(*witness_index))); self.acir_ir.push_opcode(Opcode::Call { id, inputs, outputs }); Ok(results) diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs index e0d8e2c1cb9d..ac9f2c2cdb98 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs @@ -183,22 +183,17 @@ impl Ssa { abi_distinctness: Distinctness, last_array_uses: &HashMap, ) -> Result, RuntimeError> { - // let x = ssa.functions.iter().enumerate().map(|(i, (id, _))| { - // ssa.id_to_index.insert(*id, *i); - // }); - let mut acirs = Vec::new(); - for (_, function) in &self.functions { + for function in self.functions.values() { let context = Context::new(); - // let generated_acir = - // // context.convert_ssa_function(&self, function, &brillig, last_array_uses)?; - - if let Some(generated_acir) = context.convert_ssa_function(&self, function, &brillig, last_array_uses)? { + if let Some(generated_acir) = + context.convert_ssa_function(&self, function, &brillig, last_array_uses)? + { acirs.push(generated_acir); } } - // dbg!(acirs.clone()); - // TODO: check wheter doing this for a single circuit's return witnessese is correct. + + // TODO: check wheter doing this for a single circuit's return witnesses is correct. // We may need it for all foldable circuits, as any circuit being folded is essentially an entry point. However, I do not know how that // plays a part when we potentially want not inlined functions normally as part of the compiler. let main_func_acir = &mut acirs[0]; @@ -254,8 +249,18 @@ impl Context { last_array_uses: &HashMap, ) -> Result, RuntimeError> { match function.runtime() { - // TODO: hanlde this shit - RuntimeType::Acir(_) => Ok(Some(self.convert_acir_main(function, ssa, brillig, last_array_uses)?)), + RuntimeType::Acir(inline_type) => { + match inline_type { + InlineType::Fold => {} + InlineType::Inline => { + if function.id() != ssa.main_id { + panic!("ACIR function should have been inlined earlier if not marked otherwise"); + } + } + } + // We only want to convert entry point functions. This being `main` and those marked with `#[fold]` + Ok(Some(self.convert_acir_main(function, ssa, brillig, last_array_uses)?)) + } RuntimeType::Brillig => { if function.id() == ssa.main_id { Ok(Some(self.convert_brillig_main(function, brillig)?)) @@ -299,7 +304,7 @@ impl Context { brillig: &Brillig, ) -> Result { let dfg = &main_func.dfg; - + let inputs = try_vecmap(dfg[main_func.entry_block()].parameters(), |param_id| { let typ = dfg.type_of_value(*param_id); self.create_value_from_type(&typ, &mut |this, _| Ok(this.acir_context.add_variable())) @@ -568,10 +573,11 @@ impl Context { assert!(!matches!(inline_type, InlineType::Inline), "ICE: Got an ACIR function named {} that should have already been inlined", func.name()); let inputs = vecmap(arguments, |arg| self.convert_value(*arg, dfg)); - let output_count = result_ids.iter().fold(0usize, |sum, result_id| { - // TODO: handle complex return types from ACIR functions - sum + dfg.try_get_array_length(*result_id).unwrap_or(1) - }); + let output_count = + result_ids.iter().fold(0usize, |sum, result_id| { + // TODO: handle complex return types from ACIR functions + sum + dfg.try_get_array_length(*result_id).unwrap_or(1) + }); let final_program_id = ssa .id_to_index @@ -582,7 +588,8 @@ impl Context { inputs, output_count, )?; - let result_values = self.convert_vars_to_values(result_vars, dfg, result_ids); + let result_values = + self.convert_vars_to_values(result_vars, dfg, result_ids); for (result, output) in result_ids.iter().zip(result_values) { match &output { // We need to make sure we initialize arrays returned from intrinsic calls @@ -595,7 +602,11 @@ impl Context { } else { Self::flattened_value_size(&output) }; - self.initialize_array(block_id, len, Some(output.clone()))?; + self.initialize_array( + block_id, + len, + Some(output.clone()), + )?; } AcirValue::DynamicArray(_) => { // Do nothing as a dynamic array returned from a slice intrinsic should already be initialized @@ -2412,14 +2423,17 @@ fn can_omit_element_sizes_array(array_typ: &Type) -> bool { #[cfg(test)] mod test { - use acvm::acir::{circuit::Opcode, native_types::Witness}; + use acvm::{ + acir::{circuit::Opcode, native_types::Witness}, + FieldElement, + }; use crate::{ brillig::Brillig, ssa::{ function_builder::FunctionBuilder, ir::{ - function::{InlineType, RuntimeType}, + function::{FunctionId, InlineType, RuntimeType}, instruction::BinaryOp, map::Id, types::Type, @@ -2428,21 +2442,38 @@ mod test { }; use fxhash::FxHashMap as HashMap; - #[test] - fn basic_call_codegen() { - // acir(inline) fn main f0 { - // b0(v0: Field, v1: Field): - // call f1(v0, v1) - // call f1(v0, v1) - // return - // } + fn build_basic_foo_with_return(builder: &mut FunctionBuilder, foo_id: FunctionId) { // acir(fold) fn foo f1 { // b0(v0: Field, v1: Field): - // v13 = eq v0, v1 - // constrain v13 == u1 0 - // return + // v2 = eq v0, v1 + // constrain v2 == u1 0 + // return v0 // } + builder.new_function("foo".into(), foo_id, InlineType::Fold); + let foo_v0 = builder.add_parameter(Type::field()); + let foo_v1 = builder.add_parameter(Type::field()); + + let foo_equality_check = builder.insert_binary(foo_v0, BinaryOp::Eq, foo_v1); + let zero = builder.field_constant(0u128); + builder.insert_constrain(foo_equality_check, zero, None); + builder.terminate_with_return(vec![foo_v0]); + } + #[test] + fn basic_call_with_outputs_assert() { + // acir(inline) fn main f0 { + // b0(v0: Field, v1: Field): + // v2 = call f1(v0, v1) + // v3 = call f1(v0, v1) + // constrain v2 == v3 + // return + // } + // acir(fold) fn foo f1 { + // b0(v0: Field, v1: Field): + // v2 = eq v0, v1 + // constrain v2 == u1 0 + // return v0 + // } let foo_id = Id::test_new(0); let mut builder = FunctionBuilder::new("main".into(), foo_id, RuntimeType::Acir(InlineType::default())); @@ -2451,18 +2482,14 @@ mod test { let foo_id = Id::test_new(1); let foo = builder.import_function(foo_id); - builder.insert_call(foo, vec![main_v0, main_v1], vec![]).to_vec(); - builder.insert_call(foo, vec![main_v0, main_v1], vec![]).to_vec(); + let main_call1_results = + builder.insert_call(foo, vec![main_v0, main_v1], vec![Type::field()]).to_vec(); + let main_call2_results = + builder.insert_call(foo, vec![main_v0, main_v1], vec![Type::field()]).to_vec(); + builder.insert_constrain(main_call1_results[0], main_call2_results[0], None); builder.terminate_with_return(vec![]); - builder.new_function("foo".into(), foo_id, InlineType::Fold); - let foo_v0 = builder.add_parameter(Type::field()); - let foo_v1 = builder.add_parameter(Type::field()); - - let foo_equality_check = builder.insert_binary(foo_v0, BinaryOp::Eq, foo_v1); - let zero = builder.field_constant(0u128); - builder.insert_constrain(foo_equality_check, zero, None); - builder.terminate_with_return(vec![]); + build_basic_foo_with_return(&mut builder, foo_id); let ssa = builder.finish(); @@ -2478,8 +2505,9 @@ mod test { // GeneratedAcir { // ... // opcodes: [ - // CALL func 1: inputs: [Witness(0), Witness(1)], outputs: [], - // CALL func 1: inputs: [Witness(0), Witness(1)], outputs: [], + // CALL func 1: inputs: [Witness(0), Witness(1)], outputs: [Witness(2)], + // CALL func 1: inputs: [Witness(0), Witness(1)], outputs: [Witness(3)], + // EXPR [ (1, _2) (-1, _3) 0 ], // ], // return_witnesses: [], // input_witnesses: [ @@ -2496,15 +2524,13 @@ mod test { // GeneratedAcir { // ... // opcodes: [ - // EXPR [ (-1, _0) (1, _1) (-1, _2) 0 ], - // BRILLIG: inputs: [Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(2))], q_c: 0 })] - // outputs: [Simple(Witness(3))] - // [Brillig opcodes...] - // EXPR [ (1, _2, _3) (1, _4) -1 ], - // EXPR [ (1, _2, _4) 0 ], - // EXPR [ (1, _4) 0 ], + // Same as opcodes as the expected result of `basic_call_codegen` + // ], + // return_witnesses: [ + // Witness( + // 0, + // ), // ], - // return_witnesses: [], // input_witnesses: [ // Witness( // 0, @@ -2514,24 +2540,221 @@ mod test { // ), // ], // ... + // }, + + let main_acir = &acir_functions[0]; + let main_opcodes = main_acir.opcodes(); + assert_eq!(main_opcodes.len(), 3, "Should have two calls to `foo`"); + + check_call_opcode(&main_opcodes[0], 1, vec![Witness(0), Witness(1)], vec![Witness(2)]); + check_call_opcode(&main_opcodes[1], 1, vec![Witness(0), Witness(1)], vec![Witness(3)]); + + match &main_opcodes[2] { + Opcode::AssertZero(expr) => { + assert_eq!(expr.linear_combinations[0].0, FieldElement::from(1u128)); + assert_eq!(expr.linear_combinations[0].1, Witness(2)); + + assert_eq!(expr.linear_combinations[1].0, FieldElement::from(-1i128)); + assert_eq!(expr.linear_combinations[1].1, Witness(3)); + assert_eq!(expr.q_c, FieldElement::from(0u128)); + } + _ => {} + } + } + + #[test] + fn call_output_as_next_call_input() { + // acir(inline) fn main f0 { + // b0(v0: Field, v1: Field): + // v3 = call f1(v0, v1) + // v4 = call f1(v3, v1) + // constrain v3 == v4 + // return + // } + // acir(fold) fn foo f1 { + // b0(v0: Field, v1: Field): + // v2 = eq v0, v1 + // constrain v2 == u1 0 + // return v0 + // } + let foo_id = Id::test_new(0); + let mut builder = + FunctionBuilder::new("main".into(), foo_id, RuntimeType::Acir(InlineType::default())); + let main_v0 = builder.add_parameter(Type::field()); + let main_v1 = builder.add_parameter(Type::field()); + + let foo_id = Id::test_new(1); + let foo = builder.import_function(foo_id); + let main_call1_results = + builder.insert_call(foo, vec![main_v0, main_v1], vec![Type::field()]).to_vec(); + let main_call2_results = builder + .insert_call(foo, vec![main_call1_results[0], main_v1], vec![Type::field()]) + .to_vec(); + builder.insert_constrain(main_call1_results[0], main_call2_results[0], None); + builder.terminate_with_return(vec![]); + + build_basic_foo_with_return(&mut builder, foo_id); + + let ssa = builder.finish(); + + let acir_functions = ssa + .into_acir( + Brillig::default(), + noirc_frontend::Distinctness::Distinct, + &HashMap::default(), + ) + .expect("Should compile manually written SSA into ACIR"); + // The expected result should look very similar to the abvoe test expect that the input witnesses of the `Call` + // opcodes will be different. The changes can discerned from the checks below. + + let main_acir = &acir_functions[0]; + let main_opcodes = main_acir.opcodes(); + assert_eq!(main_opcodes.len(), 3, "Should have two calls to `foo` and an assert"); + + check_call_opcode(&main_opcodes[0], 1, vec![Witness(0), Witness(1)], vec![Witness(2)]); + // The output of the first call should be the input of the second call + check_call_opcode(&main_opcodes[1], 1, vec![Witness(2), Witness(1)], vec![Witness(3)]); + } + + #[test] + fn basic_nested_call() { + // SSA for the following Noir program: + // fn main(x: Field, y: pub Field) { + // let z = func_with_nested_foo_call(x, y); + // let z2 = func_with_nested_foo_call(x, y); + // assert(z == z2); + // } + // #[fold] + // fn func_with_nested_foo_call(x: Field, y: Field) -> Field { + // nested_call(x + 2, y) // } + // #[fold] + // fn foo(x: Field, y: Field) -> Field { + // assert(x != y); + // x + // } + // + // SSA: + // acir(inline) fn main f0 { + // b0(v0: Field, v1: Field): + // v3 = call f1(v0, v1) + // v4 = call f1(v0, v1) + // constrain v3 == v4 + // return + // } + // acir(fold) fn func_with_nested_foo_call f1 { + // b0(v0: Field, v1: Field): + // v3 = add v0, Field 2 + // v5 = call f2(v3, v1) + // return v5 + // } + // acir(fold) fn foo f2 { + // b0(v0: Field, v1: Field): + // v2 = eq v0, v1 + // constrain v2 == Field 0 + // return v0 + // } + let foo_id = Id::test_new(0); + let mut builder = + FunctionBuilder::new("main".into(), foo_id, RuntimeType::Acir(InlineType::default())); + let main_v0 = builder.add_parameter(Type::field()); + let main_v1 = builder.add_parameter(Type::field()); + + let func_with_nested_foo_call_id = Id::test_new(1); + let func_with_nested_foo_call = builder.import_function(func_with_nested_foo_call_id); + let main_call1_results = builder + .insert_call(func_with_nested_foo_call, vec![main_v0, main_v1], vec![Type::field()]) + .to_vec(); + let main_call2_results = builder + .insert_call(func_with_nested_foo_call, vec![main_v0, main_v1], vec![Type::field()]) + .to_vec(); + builder.insert_constrain(main_call1_results[0], main_call2_results[0], None); + builder.terminate_with_return(vec![]); - let main = &acir_functions[0]; - assert_eq!(main.opcodes().len(), 2, "Should have two calls to `foo`"); - for opcode in main.opcodes() { - match opcode { - Opcode::Call { id, inputs, outputs } => { - assert_eq!(*id, 1, "Main was expected to call the same function"); - assert_eq!(inputs[0], Witness(0), "First input was not the first witness"); - assert_eq!(inputs[1], Witness(1), "Second input was not the second witness"); - assert!(outputs.is_empty(), "Expected `foo` to return nothing"); + builder.new_function( + "func_with_nested_foo_call".into(), + func_with_nested_foo_call_id, + InlineType::Fold, + ); + let func_with_nested_call_v0 = builder.add_parameter(Type::field()); + let func_with_nested_call_v1 = builder.add_parameter(Type::field()); + + let two = builder.field_constant(2u128); + let v0_plus_two = builder.insert_binary(func_with_nested_call_v0, BinaryOp::Add, two); + + let foo_id = Id::test_new(2); + let foo_call = builder.import_function(foo_id); + let foo_call = builder + .insert_call(foo_call, vec![v0_plus_two, func_with_nested_call_v1], vec![Type::field()]) + .to_vec(); + builder.terminate_with_return(vec![foo_call[0]]); + + build_basic_foo_with_return(&mut builder, foo_id); + + let ssa = builder.finish(); + + let acir_functions = ssa + .into_acir( + Brillig::default(), + noirc_frontend::Distinctness::Distinct, + &HashMap::default(), + ) + .expect("Should compile manually written SSA into ACIR"); + + assert_eq!(acir_functions.len(), 3, "Should have three ACIR functions"); + + let main_acir = &acir_functions[0]; + let main_opcodes = main_acir.opcodes(); + assert_eq!(main_opcodes.len(), 3, "Should have two calls to `foo` and an assert"); + + // Both of these should call func_with_nested_foo_call f1 + check_call_opcode(&main_opcodes[0], 1, vec![Witness(0), Witness(1)], vec![Witness(2)]); + // The output of the first call should be the input of the second call + check_call_opcode(&main_opcodes[1], 1, vec![Witness(0), Witness(1)], vec![Witness(3)]); + + let func_with_nested_call_acir = &acir_functions[1]; + let func_with_nested_call_opcodes = func_with_nested_call_acir.opcodes(); + assert_eq!( + func_with_nested_call_opcodes.len(), + 2, + "Should have an expression and a call to a nested `foo`" + ); + // Should call foo f2 + check_call_opcode( + &func_with_nested_call_opcodes[1], + 2, + vec![Witness(2), Witness(1)], + vec![Witness(3)], + ); + } + + fn check_call_opcode( + opcode: &Opcode, + expected_id: u32, + expected_inputs: Vec, + expected_outputs: Vec, + ) { + match opcode { + Opcode::Call { id, inputs, outputs } => { + assert_eq!( + *id, expected_id, + "Main was expected to call {expected_id} but got {}", + *id + ); + for (expected_input, input) in expected_inputs.iter().zip(inputs) { + assert_eq!( + expected_input, input, + "Expected witness {expected_input:?} but got {input:?}" + ); + } + for (expected_output, output) in expected_outputs.iter().zip(outputs) { + assert_eq!( + expected_output, output, + "Expected witness {expected_output:?} but got {output:?}" + ); } - _ => panic!("Expected only Call opcodes in main"), } + _ => panic!("Expected only Call opcode"), } - - let foo = &acir_functions[1]; - assert_eq!(foo.input_witnesses[0], Witness(0), "First input was not the first witness"); - assert_eq!(foo.input_witnesses[1], Witness(1), "Second input was not the second witness"); } } diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/function.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/function.rs index fb306ecf9dcc..95e627351cfa 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/function.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/function.rs @@ -19,21 +19,16 @@ pub(crate) enum RuntimeType { /// Represents how a RuntimeType::Acir function should be inlined. /// This type is only relevant for ACIR functions as we do not inline any Brillig functions -#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] +#[derive(Default, Clone, Copy, PartialEq, Eq, Debug, Hash)] pub(crate) enum InlineType { /// The most basic entry point can expect all its functions to be inlined. /// All function calls are expected to be inlined into a single ACIR. + #[default] Inline, /// Functions marked as foldable will not be inlined and compiled separately into ACIR Fold, } -impl Default for InlineType { - fn default() -> Self { - InlineType::Inline - } -} - /// A function holds a list of instructions. /// These instructions are further grouped into Basic blocks /// diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/inlining.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/inlining.rs index e88ea149ff8f..4ce32d78daec 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/inlining.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/inlining.rs @@ -100,14 +100,13 @@ fn get_entry_point_functions(ssa: &Ssa) -> BTreeSet { let functions = ssa.functions.iter(); let mut entry_points = functions .filter(|(_, function)| { - let inline_filter = match function.runtime() { + match function.runtime() { RuntimeType::Acir(inline_type) => match inline_type { InlineType::Inline => false, InlineType::Fold => true, }, RuntimeType::Brillig => true, - }; - inline_filter + } }) .map(|(id, _)| *id) .collect::>(); @@ -359,12 +358,8 @@ impl<'function> PerFunctionContext<'function> { match &self.source_function.dfg[*id] { Instruction::Call { func, arguments } => match self.get_function(*func) { Some(function) => match ssa.functions[&function].runtime() { - RuntimeType::Acir(InlineType::Inline) => { - self.inline_function(ssa, *id, function, arguments) - } - RuntimeType::Acir(InlineType::Fold) | RuntimeType::Brillig => { - self.push_instruction(*id) - } + RuntimeType::Acir(InlineType::Inline) => self.inline_function(ssa, *id, function, arguments), + RuntimeType::Acir(InlineType::Fold) | RuntimeType::Brillig => self.push_instruction(*id), }, None => self.push_instruction(*id), }, diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/unrolling.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/unrolling.rs index 61aed1a2cbaa..4ebdfd04e45d 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/unrolling.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/unrolling.rs @@ -48,8 +48,7 @@ impl Ssa { // This check is always true with the addition of the above guard, but I'm // keeping it in case the guard on brillig functions is ever removed. - let abort_on_error = - if let RuntimeType::Acir(_) = function.runtime() { true } else { false }; + let abort_on_error = matches!(function.runtime(), RuntimeType::Acir(_)); find_all_loops(function).unroll_each_loop(function, abort_on_error)?; } Ok(self) diff --git a/noir/noir-repo/test_programs/execution_success/fold_basic/src/main.nr b/noir/noir-repo/test_programs/execution_success/fold_basic/src/main.nr index 266262c48b9d..6aae3cea1855 100644 --- a/noir/noir-repo/test_programs/execution_success/fold_basic/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/fold_basic/src/main.nr @@ -10,7 +10,14 @@ fn main(x: Field, y: pub Field) { // } #[fold] -fn basic_func(x: Field, y: Field) -> Field { +fn basic_func(x: Field, y: Field) -> Field{ + // assert(x != y); + nested_call(x + 2, y) + // let q = basic_func(x, y); +} + +#[fold] +fn nested_call(x: Field, y: Field) -> Field { assert(x != y); - x + y + x } From f3a210f4cd703946fc321c17d2faeab355d09c71 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Wed, 20 Mar 2024 17:06:48 +0000 Subject: [PATCH 096/139] remove noir test with fold --- .../execution_success/fold_basic/Nargo.toml | 7 ------ .../execution_success/fold_basic/Prover.toml | 2 -- .../execution_success/fold_basic/src/main.nr | 23 ------------------- 3 files changed, 32 deletions(-) delete mode 100644 noir/noir-repo/test_programs/execution_success/fold_basic/Nargo.toml delete mode 100644 noir/noir-repo/test_programs/execution_success/fold_basic/Prover.toml delete mode 100644 noir/noir-repo/test_programs/execution_success/fold_basic/src/main.nr diff --git a/noir/noir-repo/test_programs/execution_success/fold_basic/Nargo.toml b/noir/noir-repo/test_programs/execution_success/fold_basic/Nargo.toml deleted file mode 100644 index 575ba1f3ad14..000000000000 --- a/noir/noir-repo/test_programs/execution_success/fold_basic/Nargo.toml +++ /dev/null @@ -1,7 +0,0 @@ -[package] -name = "fold_basic" -type = "bin" -authors = [""] -compiler_version = ">=0.25.0" - -[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/execution_success/fold_basic/Prover.toml b/noir/noir-repo/test_programs/execution_success/fold_basic/Prover.toml deleted file mode 100644 index f28f2f8cc48f..000000000000 --- a/noir/noir-repo/test_programs/execution_success/fold_basic/Prover.toml +++ /dev/null @@ -1,2 +0,0 @@ -x = "5" -y = "10" diff --git a/noir/noir-repo/test_programs/execution_success/fold_basic/src/main.nr b/noir/noir-repo/test_programs/execution_success/fold_basic/src/main.nr deleted file mode 100644 index 6aae3cea1855..000000000000 --- a/noir/noir-repo/test_programs/execution_success/fold_basic/src/main.nr +++ /dev/null @@ -1,23 +0,0 @@ -fn main(x: Field, y: pub Field) { - let z = basic_func(x, y); - let z2 = basic_func(x, y); - assert(z == z2); -} - -// #[fold] -// fn basic_func(x: Field, y: Field) { -// assert(x != y); -// } - -#[fold] -fn basic_func(x: Field, y: Field) -> Field{ - // assert(x != y); - nested_call(x + 2, y) - // let q = basic_func(x, y); -} - -#[fold] -fn nested_call(x: Field, y: Field) -> Field { - assert(x != y); - x -} From 5dedc1d021b97787da19f9830d78aa53bf076022 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Wed, 20 Mar 2024 17:21:35 +0000 Subject: [PATCH 097/139] cargo fmt --- .../compiler/noirc_driver/src/lib.rs | 3 +-- .../noirc_evaluator/src/ssa/opt/inlining.rs | 22 ++++++++++--------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/noir/noir-repo/compiler/noirc_driver/src/lib.rs b/noir/noir-repo/compiler/noirc_driver/src/lib.rs index 431c5c4926ed..6b9c0d650e45 100644 --- a/noir/noir-repo/compiler/noirc_driver/src/lib.rs +++ b/noir/noir-repo/compiler/noirc_driver/src/lib.rs @@ -290,8 +290,7 @@ pub fn compile_main( compile_no_check(context, options, main, cached_program, options.force_compile) .map_err(FileDiagnostic::from)?; - let compilation_warnings = - vecmap(compiled_program.warnings.clone(), FileDiagnostic::from); + let compilation_warnings = vecmap(compiled_program.warnings.clone(), FileDiagnostic::from); if options.deny_warnings && !compilation_warnings.is_empty() { return Err(compilation_warnings); } diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/inlining.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/inlining.rs index 4ce32d78daec..cd4c54a0e56c 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/inlining.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/inlining.rs @@ -99,14 +99,12 @@ struct PerFunctionContext<'function> { fn get_entry_point_functions(ssa: &Ssa) -> BTreeSet { let functions = ssa.functions.iter(); let mut entry_points = functions - .filter(|(_, function)| { - match function.runtime() { - RuntimeType::Acir(inline_type) => match inline_type { - InlineType::Inline => false, - InlineType::Fold => true, - }, - RuntimeType::Brillig => true, - } + .filter(|(_, function)| match function.runtime() { + RuntimeType::Acir(inline_type) => match inline_type { + InlineType::Inline => false, + InlineType::Fold => true, + }, + RuntimeType::Brillig => true, }) .map(|(id, _)| *id) .collect::>(); @@ -358,8 +356,12 @@ impl<'function> PerFunctionContext<'function> { match &self.source_function.dfg[*id] { Instruction::Call { func, arguments } => match self.get_function(*func) { Some(function) => match ssa.functions[&function].runtime() { - RuntimeType::Acir(InlineType::Inline) => self.inline_function(ssa, *id, function, arguments), - RuntimeType::Acir(InlineType::Fold) | RuntimeType::Brillig => self.push_instruction(*id), + RuntimeType::Acir(InlineType::Inline) => { + self.inline_function(ssa, *id, function, arguments) + } + RuntimeType::Acir(InlineType::Fold) | RuntimeType::Brillig => { + self.push_instruction(*id) + } }, None => self.push_instruction(*id), }, From d7c9dbb85b31867ee3ac2f0fc83a7995f1847e59 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Wed, 20 Mar 2024 18:11:59 +0000 Subject: [PATCH 098/139] cargo clippy --- .../compiler/noirc_evaluator/src/ssa/opt/inlining.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/inlining.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/inlining.rs index cd4c54a0e56c..97d035632bd8 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/inlining.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/inlining.rs @@ -356,12 +356,8 @@ impl<'function> PerFunctionContext<'function> { match &self.source_function.dfg[*id] { Instruction::Call { func, arguments } => match self.get_function(*func) { Some(function) => match ssa.functions[&function].runtime() { - RuntimeType::Acir(InlineType::Inline) => { - self.inline_function(ssa, *id, function, arguments) - } - RuntimeType::Acir(InlineType::Fold) | RuntimeType::Brillig => { - self.push_instruction(*id) - } + RuntimeType::Acir(InlineType::Inline) => self.inline_function(ssa, *id, function, arguments), + RuntimeType::Acir(InlineType::Fold) | RuntimeType::Brillig => self.push_instruction(*id), }, None => self.push_instruction(*id), }, From 5394619cd93598d7ffa6b2cdf3390cf98e9eac3b Mon Sep 17 00:00:00 2001 From: vezenovm Date: Wed, 20 Mar 2024 18:17:09 +0000 Subject: [PATCH 099/139] fmt and resulting clippy --- .../compiler/noirc_evaluator/src/ssa/opt/inlining.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/inlining.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/inlining.rs index 97d035632bd8..c7c280a4b109 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/inlining.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/inlining.rs @@ -356,8 +356,12 @@ impl<'function> PerFunctionContext<'function> { match &self.source_function.dfg[*id] { Instruction::Call { func, arguments } => match self.get_function(*func) { Some(function) => match ssa.functions[&function].runtime() { - RuntimeType::Acir(InlineType::Inline) => self.inline_function(ssa, *id, function, arguments), - RuntimeType::Acir(InlineType::Fold) | RuntimeType::Brillig => self.push_instruction(*id), + RuntimeType::Acir(InlineType::Inline) => { + self.inline_function(ssa, *id, function, arguments); + } + RuntimeType::Acir(InlineType::Fold) | RuntimeType::Brillig => { + self.push_instruction(*id); + } }, None => self.push_instruction(*id), }, From 84f5495d2d6e619bb587626743522c8373058d05 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Wed, 20 Mar 2024 18:20:52 +0000 Subject: [PATCH 100/139] remove unused label --- .../src/ssa/acir_gen/acir_ir/acir_variable.rs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs index 09ea47dd5f26..963ca45d2341 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs @@ -101,12 +101,6 @@ impl From for AcirType { } } -/// An identifier for a location in the code. -/// -/// It is assumed that an entity will keep a map -/// of labels to opcode locations. -pub(crate) type Label = String; - #[derive(Debug, Default)] /// Context object which holds the relationship between /// `Variables`(AcirVar) and types such as `Expression` and `Witness` @@ -130,9 +124,6 @@ pub(crate) struct AcirContext { /// The BigIntContext, used to generate identifiers for BigIntegers big_int_ctx: BigIntContext, - - /// Set of labels (function identifiers) which are external to the bytecode - unresolved_external_call_labels: Vec<(usize, Label)>, } impl AcirContext { From 4cd1a7d0fd927c7eec62ecc2a38a333ac9d66d74 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Wed, 20 Mar 2024 18:23:40 +0000 Subject: [PATCH 101/139] remove unused inline_type funcs --- .../src/ssa/acir_gen/acir_ir/acir_variable.rs | 4 ++-- .../noirc_evaluator/src/ssa/ir/function.rs | 14 -------------- 2 files changed, 2 insertions(+), 16 deletions(-) diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs index 963ca45d2341..73d3e4dad26d 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs @@ -1443,13 +1443,13 @@ impl AcirContext { /// Terminates the context and takes the resulting `GeneratedAcir` pub(crate) fn finish( - &mut self, + mut self, inputs: Vec, warnings: Vec, ) -> GeneratedAcir { self.acir_ir.input_witnesses = inputs; self.acir_ir.warnings = warnings; - self.acir_ir.clone() + self.acir_ir } /// Adds `Data` into the context and assigns it a Variable. diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/function.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/function.rs index 95e627351cfa..c17738e30d8a 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/function.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/function.rs @@ -83,20 +83,6 @@ impl Function { self.runtime = runtime; } - pub(crate) fn inline_type(&self) -> Option { - if let RuntimeType::Acir(inline_type) = self.runtime { - Some(inline_type) - } else { - None - } - } - - pub(crate) fn set_inline_type(&mut self, inline_type: InlineType) { - if let RuntimeType::Acir(old_inline_type) = &mut self.runtime { - *old_inline_type = inline_type; - } - } - /// Retrieves the entry block of a function. /// /// A function's entry block contains the instructions From 34ad9e22eb5471e09773e9c3bacfe5c399920d9e Mon Sep 17 00:00:00 2001 From: vezenovm Date: Wed, 20 Mar 2024 18:27:45 +0000 Subject: [PATCH 102/139] remove create_circuit for create_program --- .../compiler/noirc_driver/src/lib.rs | 3 - .../compiler/noirc_evaluator/src/lib.rs | 1 - .../compiler/noirc_evaluator/src/ssa.rs | 71 ------------------- 3 files changed, 75 deletions(-) diff --git a/noir/noir-repo/compiler/noirc_driver/src/lib.rs b/noir/noir-repo/compiler/noirc_driver/src/lib.rs index 6b9c0d650e45..b6bf715c6c00 100644 --- a/noir/noir-repo/compiler/noirc_driver/src/lib.rs +++ b/noir/noir-repo/compiler/noirc_driver/src/lib.rs @@ -478,15 +478,12 @@ pub fn compile_no_check( return Ok(cached_program.expect("cache must exist for hashes to match")); } let visibility = program.return_visibility; - // let (circuit, debug, input_witnesses, return_witnesses, warnings) = - // create_circuit(program, options.show_ssa, options.show_brillig, options.force_brillig)?; let (program, debug, warnings, input_witnesses, return_witnesses) = create_program(program, options.show_ssa, options.show_brillig, options.force_brillig)?; let abi = abi_gen::gen_abi(context, &main_function, input_witnesses, return_witnesses, visibility); - // let file_map = filter_relevant_files(&[debug.clone()], &context.file_manager); let file_map = filter_relevant_files(&debug, &context.file_manager); Ok(CompiledProgram { diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/lib.rs b/noir/noir-repo/compiler/noirc_evaluator/src/lib.rs index 085822e2dff8..543769633381 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/lib.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/lib.rs @@ -11,5 +11,4 @@ pub mod ssa; pub mod brillig; -pub use ssa::create_circuit; pub use ssa::create_program; diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs index 6f7bf4ea9f6b..f6a34229d5ed 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs @@ -75,77 +75,6 @@ pub(crate) fn optimize_into_acir( ssa.into_acir(brillig, abi_distinctness, &last_array_uses) } -/// Compiles the [`Program`] into [`ACIR`][acvm::acir::circuit::Circuit]. -/// -/// The output ACIR is is backend-agnostic and so must go through a transformation pass before usage in proof generation. -#[allow(clippy::type_complexity)] -#[tracing::instrument(level = "trace", skip_all)] -pub fn create_circuit( - program: Program, - enable_ssa_logging: bool, - enable_brillig_logging: bool, - force_brillig_output: bool, -) -> Result<(Circuit, DebugInfo, Vec, Vec, Vec), RuntimeError> { - let debug_variables = program.debug_variables.clone(); - let debug_types = program.debug_types.clone(); - let debug_functions = program.debug_functions.clone(); - - // let func_sigs = program.function_signatures; - let func_sig = program.main_function_signature.clone(); - // let func_sigs = program.functions. - // TODO: handle `recursive` being marked on a program with multiple ACIRs that is looking to fold - let recursive = program.recursive; - let mut generated_acir = optimize_into_acir( - program, - enable_ssa_logging, - enable_brillig_logging, - force_brillig_output, - )?; - - // let acir_functions = vecmap(generated_acir.iter().zip(func_sigs), |(acir, func_sig)| convert_generated_acir_into_circuit(acir, func_sig, recursive)); - let opcodes = generated_acir[0].take_opcodes(); - let current_witness_index = generated_acir[0].current_witness_index().0; - let GeneratedAcir { - return_witnesses, - locations, - input_witnesses, - assert_messages, - warnings, - .. - } = generated_acir[0].clone(); - - let (public_parameter_witnesses, private_parameters) = - split_public_and_private_inputs(&func_sig, &input_witnesses); - - let public_parameters = PublicInputs(public_parameter_witnesses); - let return_values = PublicInputs(return_witnesses.iter().copied().collect()); - - let circuit = Circuit { - current_witness_index, - expression_width: ExpressionWidth::Unbounded, - opcodes, - private_parameters, - public_parameters, - return_values, - assert_messages: assert_messages.into_iter().collect(), - recursive, - }; - - // This converts each im::Vector in the BTreeMap to a Vec - let locations = locations - .into_iter() - .map(|(index, locations)| (index, locations.into_iter().collect())) - .collect(); - - let mut debug_info = DebugInfo::new(locations, debug_variables, debug_functions, debug_types); - - // Perform any ACIR-level optimizations - let (optimized_circuit, transformation_map) = acvm::compiler::optimize(circuit); - debug_info.update_acir(transformation_map); - - Ok((optimized_circuit, debug_info, input_witnesses, return_witnesses, warnings)) -} - /// Compiles the [`Program`] into [`ACIR``][acvm::acir::circuit::Program]. /// /// The output ACIR is is backend-agnostic and so must go through a transformation pass before usage in proof generation. From 5e5285fa609d288c9a7acb9c2138e9b8a95d8029 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Wed, 20 Mar 2024 19:41:01 +0000 Subject: [PATCH 103/139] empty commit cause earthly is wokring locally From 36a9ec1680095c611880b87dc3adcba17d2b3f2f Mon Sep 17 00:00:00 2001 From: vezenovm Date: Thu, 21 Mar 2024 02:05:35 +0000 Subject: [PATCH 104/139] a bunch of cleanup --- .../compiler/noirc_driver/src/lib.rs | 5 +- .../compiler/noirc_evaluator/src/ssa.rs | 15 +-- .../src/ssa/acir_gen/acir_ir/acir_variable.rs | 5 +- .../ssa/acir_gen/acir_ir/generated_acir.rs | 4 - .../noirc_evaluator/src/ssa/acir_gen/mod.rs | 123 ++++++------------ .../noirc_evaluator/src/ssa/ssa_gen/mod.rs | 3 +- .../src/hir/resolution/resolver.rs | 6 +- .../noirc_frontend/src/hir/type_check/mod.rs | 2 +- .../noirc_frontend/src/hir_def/function.rs | 4 +- .../src/monomorphization/mod.rs | 4 +- 10 files changed, 64 insertions(+), 107 deletions(-) diff --git a/noir/noir-repo/compiler/noirc_driver/src/lib.rs b/noir/noir-repo/compiler/noirc_driver/src/lib.rs index b6bf715c6c00..2cffaa54e38c 100644 --- a/noir/noir-repo/compiler/noirc_driver/src/lib.rs +++ b/noir/noir-repo/compiler/noirc_driver/src/lib.rs @@ -491,10 +491,13 @@ pub fn compile_no_check( // TODO(https://github.com/noir-lang/noir/issues/4428) program, // TODO(https://github.com/noir-lang/noir/issues/4428) + // Debug info is only relevant for errors at execution time which this PR does not yet support + // The CompileProgram `debug` field is used in multiple places and is better + // left to be updated once execution of multiple ACIR functions is enabled debug: debug[0].clone(), abi, file_map, noir_version: NOIR_ARTIFACT_VERSION_STRING.to_string(), - warnings: warnings[0].clone(), + warnings, }) } diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs index f6a34229d5ed..4b2edd59055f 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs @@ -72,7 +72,7 @@ pub(crate) fn optimize_into_acir( let last_array_uses = ssa.find_last_array_uses(); - ssa.into_acir(brillig, abi_distinctness, &last_array_uses) + ssa.into_acir(&brillig, abi_distinctness, &last_array_uses) } /// Compiles the [`Program`] into [`ACIR``][acvm::acir::circuit::Program]. @@ -85,11 +85,8 @@ pub fn create_program( enable_ssa_logging: bool, enable_brillig_logging: bool, force_brillig_output: bool, -) -> Result< - (AcirProgram, Vec, Vec>, Vec, Vec), - RuntimeError, -> { - // TODO: Check whether the debug tracker stores information across the program and not just main +) -> Result<(AcirProgram, Vec, Vec, Vec, Vec), RuntimeError> +{ let debug_variables = program.debug_variables.clone(); let debug_types = program.debug_types.clone(); let debug_functions = program.debug_functions.clone(); @@ -126,6 +123,7 @@ pub fn create_program( acir, func_sig, recursive, + // TODO: get rid of these clones debug_variables.clone(), debug_functions.clone(), debug_types.clone(), @@ -133,7 +131,7 @@ pub fn create_program( ); functions.push(circuit); debug_infos.push(debug_info); - warning_infos.push(warnings); + warning_infos.extend(warnings); if is_main { main_input_witnesses = input_witnesses; main_return_witnesses = return_witnesses; @@ -168,9 +166,6 @@ fn convert_generated_acir_into_circuit( let locations = locations.clone(); - // let (public_parameter_witnesses, private_parameters) = - // split_public_and_private_inputs(&func_sig, &input_witnesses); - let (public_parameter_witnesses, private_parameters) = if is_main { split_public_and_private_inputs(&func_sig, &input_witnesses) } else { diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs index 73d3e4dad26d..40b13e4583ab 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs @@ -1772,9 +1772,8 @@ impl AcirContext { let outputs = vecmap(0..output_count, |_| self.acir_ir.next_witness_index()); // 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. + // ACIR function call into `AcirVar`s. + // Similar to black box functions, we do not apply range information on the output of the function. // See issue #1439 let results = vecmap(&outputs, |witness_index| self.add_data(AcirVarData::Witness(*witness_index))); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs index 09dabe09f8a2..5299df175bd8 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs @@ -82,10 +82,6 @@ impl GeneratedAcir { std::mem::take(&mut self.opcodes) } - pub(crate) fn next_opcode_index(&self) -> usize { - self.opcodes.len() - } - /// Updates the witness index counter and returns /// the next witness index. pub(crate) fn next_witness_index(&mut self) -> Witness { diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs index ac9f2c2cdb98..f531008fb4fb 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs @@ -179,7 +179,7 @@ impl Ssa { #[tracing::instrument(level = "trace", skip_all)] pub(crate) fn into_acir( self, - brillig: Brillig, + brillig: &Brillig, abi_distinctness: Distinctness, last_array_uses: &HashMap, ) -> Result, RuntimeError> { @@ -187,20 +187,18 @@ impl Ssa { for function in self.functions.values() { let context = Context::new(); if let Some(generated_acir) = - context.convert_ssa_function(&self, function, &brillig, last_array_uses)? + context.convert_ssa_function(&self, function, brillig, last_array_uses)? { acirs.push(generated_acir); } } - // TODO: check wheter doing this for a single circuit's return witnesses is correct. - // We may need it for all foldable circuits, as any circuit being folded is essentially an entry point. However, I do not know how that + // TODO: check whether doing this for a single circuit's return witnesses is correct. + // We probably need it for all foldable circuits, as any circuit being folded is essentially an entry point. However, I do not know how that // plays a part when we potentially want not inlined functions normally as part of the compiler. + // Also at the moment we specify Distinctness as part of the ABI exclusively rather than the function itself + // so this will need to be updated. let main_func_acir = &mut acirs[0]; - // Previous code - // let mut context = Context::new(); - // let mut generated_acir = context.convert_ssa(self, brillig, last_array_uses)?; - match abi_distinctness { Distinctness::Distinct => { // Create a witness for each return witness we have @@ -579,44 +577,19 @@ impl Context { sum + dfg.try_get_array_length(*result_id).unwrap_or(1) }); - let final_program_id = ssa + let acir_program_id = ssa .id_to_index .get(id) .expect("ICE: should have an associated final index"); - let result_vars = self.acir_context.call_acir_function( - *final_program_id, + let output_vars = self.acir_context.call_acir_function( + *acir_program_id, inputs, output_count, )?; - let result_values = - self.convert_vars_to_values(result_vars, dfg, result_ids); - for (result, output) in result_ids.iter().zip(result_values) { - match &output { - // We need to make sure we initialize arrays returned from intrinsic calls - // or else they will fail if accessed with a dynamic index - AcirValue::Array(_) => { - let block_id = self.block_id(result); - let array_typ = dfg.type_of_value(*result); - let len = if matches!(array_typ, Type::Array(_, _)) { - array_typ.flattened_size() - } else { - Self::flattened_value_size(&output) - }; - self.initialize_array( - block_id, - len, - Some(output.clone()), - )?; - } - AcirValue::DynamicArray(_) => { - // Do nothing as a dynamic array returned from a slice intrinsic should already be initialized - } - AcirValue::Var(_, _) => { - // Do nothing - } - } - self.ssa_values.insert(*result, output); - } + let output_values = + self.convert_vars_to_values(output_vars, dfg, result_ids); + + self.handle_ssa_call_outputs(result_ids, output_values, dfg)?; } RuntimeType::Brillig => { // Check that we are not attempting to return a slice from @@ -651,19 +624,7 @@ impl Context { // Compiler sanity check assert_eq!(result_ids.len(), output_values.len(), "ICE: The number of Brillig output values should match the result ids in SSA"); - for result in result_ids.iter().zip(output_values) { - if let AcirValue::Array(_) = &result.1 { - let array_id = dfg.resolve(*result.0); - let block_id = self.block_id(&array_id); - let array_typ = dfg.type_of_value(array_id); - self.initialize_array( - block_id, - array_typ.flattened_size(), - Some(result.1.clone()), - )?; - } - self.ssa_values.insert(*result.0, result.1); - } + self.handle_ssa_call_outputs(result_ids, output_values, dfg)?; } } } @@ -682,30 +643,7 @@ impl Context { // Issue #1438 causes this check to fail with intrinsics that return 0 // results but the ssa form instead creates 1 unit result value. // assert_eq!(result_ids.len(), outputs.len()); - - for (result, output) in result_ids.iter().zip(outputs) { - match &output { - // We need to make sure we initialize arrays returned from intrinsic calls - // or else they will fail if accessed with a dynamic index - AcirValue::Array(_) => { - let block_id = self.block_id(result); - let array_typ = dfg.type_of_value(*result); - let len = if matches!(array_typ, Type::Array(_, _)) { - array_typ.flattened_size() - } else { - Self::flattened_value_size(&output) - }; - self.initialize_array(block_id, len, Some(output.clone()))?; - } - AcirValue::DynamicArray(_) => { - // Do nothing as a dynamic array returned from a slice intrinsic should already be initialized - } - AcirValue::Var(_, _) => { - // Do nothing - } - } - self.ssa_values.insert(*result, output); - } + self.handle_ssa_call_outputs(result_ids, outputs, dfg)?; } Value::ForeignFunction(_) => unreachable!( "All `oracle` methods should be wrapped in an unconstrained fn" @@ -718,6 +656,31 @@ impl Context { Ok(warnings) } + fn handle_ssa_call_outputs( + &mut self, + result_ids: &[ValueId], + output_values: Vec, + dfg: &DataFlowGraph, + ) -> Result<(), RuntimeError> { + for result in result_ids.iter().zip(output_values) { + if let AcirValue::Array(_) = &result.1 { + let array_id = dfg.resolve(*result.0); + let block_id = self.block_id(&array_id); + let array_typ = dfg.type_of_value(array_id); + self.initialize_array( + block_id, + array_typ.flattened_size(), + Some(result.1.clone()), + )?; + } + // Do nothing for AcirValue::DynamicArray and AcirValue::Var + // A dynamic array returned from a function call should already be initialized + // and a single variable does not require any extra initialization. + self.ssa_values.insert(*result.0, result.1); + } + Ok(()) + } + fn gen_brillig_for( &self, func: &Function, @@ -2495,7 +2458,7 @@ mod test { let acir_functions = ssa .into_acir( - Brillig::default(), + &Brillig::default(), noirc_frontend::Distinctness::Distinct, &HashMap::default(), ) @@ -2599,7 +2562,7 @@ mod test { let acir_functions = ssa .into_acir( - Brillig::default(), + &Brillig::default(), noirc_frontend::Distinctness::Distinct, &HashMap::default(), ) @@ -2695,7 +2658,7 @@ mod test { let acir_functions = ssa .into_acir( - Brillig::default(), + &Brillig::default(), noirc_frontend::Distinctness::Distinct, &HashMap::default(), ) diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs index 22581ba448d9..e54a9d95ce52 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs @@ -55,13 +55,14 @@ pub(crate) fn generate_ssa( // Queue the main function for compilation context.get_or_queue_function(main_id); - let main_inline_type = if main.should_fold { InlineType::Fold } else { InlineType::Inline }; let mut function_context = FunctionContext::new( main.name.clone(), &main.parameters, if force_brillig_runtime || main.unconstrained { RuntimeType::Brillig } else { + let main_inline_type = + if main.should_fold { InlineType::Fold } else { InlineType::Inline }; RuntimeType::Acir(main_inline_type) }, &context, diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/resolver.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/resolver.rs index b299026a3fbe..3dfb85bcc93e 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/resolver.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/resolver.rs @@ -977,10 +977,10 @@ impl<'a> Resolver<'a> { .map(|(name, typevar, _span)| (name.clone(), typevar.clone())) .collect(); - let should_inline = attributes + let should_fold = attributes .function .as_ref() - .map_or(true, |func_attribute| !func_attribute.is_foldable()); + .map_or(true, |func_attribute| func_attribute.is_foldable()); FuncMeta { name: name_ident, @@ -996,7 +996,7 @@ impl<'a> Resolver<'a> { has_body: !func.def.body.is_empty(), trait_constraints: self.resolve_trait_constraints(&func.def.where_clause), is_entry_point: self.is_entry_point_function(func), - should_inline, + should_fold, } } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/mod.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/mod.rs index 7eb3642f7218..39ebb9f02453 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/mod.rs @@ -502,7 +502,7 @@ mod test { trait_constraints: Vec::new(), direct_generics: Vec::new(), is_entry_point: true, - should_inline: true, + should_fold: true, }; interner.push_fn_meta(func_meta, func_id); diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir_def/function.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir_def/function.rs index e3a842a86d84..a3bbc9445a82 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir_def/function.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir_def/function.rs @@ -125,9 +125,9 @@ pub struct FuncMeta { /// For non-contracts, this means the function is `main`. pub is_entry_point: bool, - /// False if this function is marked with an attribute + /// True if this function is marked with an attribute /// that indicates it should not be inlined, such as for folding. - pub should_inline: bool, + pub should_fold: bool, } impl FuncMeta { diff --git a/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/mod.rs b/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/mod.rs index 1e877ef26cc3..85eb2fbf07ec 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/mod.rs @@ -160,10 +160,10 @@ pub fn monomorphize_debug( undo_instantiation_bindings(impl_bindings); undo_instantiation_bindings(bindings); } + let func_sigs = vecmap(monomorphizer.finished_functions.iter(), |(_, f)| f.func_sig.clone()); let functions = vecmap(monomorphizer.finished_functions, |(_, f)| f); - // let (functions, func_sigs) = monomorphizer.finished_functions.into_iter().map(|(_, f)| (f, f.func_sig.clone())).unzip(); let FuncMeta { return_distinctness, return_visibility, kind, .. } = monomorphizer.interner.function_meta(&main); @@ -319,7 +319,7 @@ impl<'interner> Monomorphizer<'interner> { }); let unconstrained = modifiers.is_unconstrained; - let should_fold = !meta.should_inline; + let should_fold = meta.should_fold; let parameters = self.parameters(&meta.parameters); let body = self.expr(body_expr_id)?; From 4b05cffc51bd413221e6299e0c3b54cd6adb0630 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Thu, 21 Mar 2024 03:05:10 +0000 Subject: [PATCH 105/139] handle func_sigs correctly --- .../compiler/noirc_evaluator/src/ssa.rs | 27 +++++++++++-------- .../src/ssa/acir_gen/acir_ir/acir_variable.rs | 1 + .../ssa/acir_gen/acir_ir/generated_acir.rs | 2 ++ .../noirc_evaluator/src/ssa/acir_gen/mod.rs | 7 ++++- .../noirc_evaluator/src/ssa/ir/function.rs | 2 ++ .../src/hir/resolution/resolver.rs | 2 +- .../src/monomorphization/mod.rs | 8 +++++- 7 files changed, 35 insertions(+), 14 deletions(-) diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs index 4b2edd59055f..ec73d0a17299 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs @@ -87,6 +87,10 @@ pub fn create_program( force_brillig_output: bool, ) -> Result<(AcirProgram, Vec, Vec, Vec, Vec), RuntimeError> { + // let entry_point_funcs = program.functions.iter().map(|function| { + // function.should_fold | function. + // }).collect::>(); + let debug_variables = program.debug_variables.clone(); let debug_types = program.debug_types.clone(); let debug_functions = program.debug_functions.clone(); @@ -94,12 +98,13 @@ pub fn create_program( let func_sigs = program.function_signatures.clone(); let recursive = program.recursive; - let generated_acir = optimize_into_acir( + let generated_acirs = optimize_into_acir( program, enable_ssa_logging, enable_brillig_logging, force_brillig_output, )?; + assert_eq!(generated_acirs.len(), func_sigs.len(), "The generated ACIRs should match the supplied function signatures"); let mut functions = vec![]; let mut debug_infos = vec![]; @@ -116,8 +121,8 @@ pub fn create_program( // let entry_point_funcs = program.functions.iter().map(|function| function.should_fold).collect::>(); // ``` let mut is_main = true; - for (acir, func_sig) in generated_acir.into_iter().zip(func_sigs) { - // dbg!(func_names[index].clone()); + // TODO: need to appropriately handle fetching these `func_sigs` so that we do not have more func sigs than generated acirs + for (acir, func_sig) in generated_acirs.into_iter().zip(func_sigs) { let (circuit, debug_info, warnings, input_witnesses, return_witnesses) = convert_generated_acir_into_circuit( acir, @@ -127,7 +132,6 @@ pub fn create_program( debug_variables.clone(), debug_functions.clone(), debug_types.clone(), - is_main, ); functions.push(circuit); debug_infos.push(debug_info); @@ -151,7 +155,6 @@ fn convert_generated_acir_into_circuit( debug_variables: DebugVariables, debug_functions: DebugFunctions, debug_types: DebugTypes, - is_main: bool, ) -> (Circuit, DebugInfo, Vec, Vec, Vec) { let opcodes = generated_acir.take_opcodes(); let current_witness_index = generated_acir.current_witness_index().0; @@ -161,16 +164,18 @@ fn convert_generated_acir_into_circuit( input_witnesses, assert_messages, warnings, + is_entry_point, .. } = generated_acir; - + // dbg!(is_entry_point); let locations = locations.clone(); - let (public_parameter_witnesses, private_parameters) = if is_main { - split_public_and_private_inputs(&func_sig, &input_witnesses) - } else { - (BTreeSet::default(), BTreeSet::default()) - }; + // let (public_parameter_witnesses, private_parameters) = if is_entry_point { + // split_public_and_private_inputs(&func_sig, &input_witnesses) + // } else { + // (BTreeSet::default(), BTreeSet::default()) + // }; + let (public_parameter_witnesses, private_parameters) = split_public_and_private_inputs(&func_sig, &input_witnesses); let public_parameters = PublicInputs(public_parameter_witnesses); let return_values = PublicInputs(return_witnesses.iter().copied().collect()); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs index 40b13e4583ab..519e9ed51bb0 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs @@ -1449,6 +1449,7 @@ impl AcirContext { ) -> GeneratedAcir { self.acir_ir.input_witnesses = inputs; self.acir_ir.warnings = warnings; + self.acir_ir.is_entry_point = true; self.acir_ir } diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs index 5299df175bd8..581380ca9236 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs @@ -58,6 +58,8 @@ pub(crate) struct GeneratedAcir { pub(crate) assert_messages: BTreeMap, pub(crate) warnings: Vec, + + pub(crate) is_entry_point: bool, } impl GeneratedAcir { diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs index f531008fb4fb..948425923bcb 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs @@ -667,9 +667,14 @@ impl Context { let array_id = dfg.resolve(*result.0); let block_id = self.block_id(&array_id); let array_typ = dfg.type_of_value(array_id); + let len = if matches!(array_typ, Type::Array(_, _)) { + array_typ.flattened_size() + } else { + Self::flattened_value_size(&result.1) + }; self.initialize_array( block_id, - array_typ.flattened_size(), + len, Some(result.1.clone()), )?; } diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/function.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/function.rs index c17738e30d8a..97a5bf71646a 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/function.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/function.rs @@ -78,6 +78,8 @@ impl Function { self.runtime } + // TODO: make is_entry_point func + /// Set runtime type of the function. pub(crate) fn set_runtime(&mut self, runtime: RuntimeType) { self.runtime = runtime; diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/resolver.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/resolver.rs index 3dfb85bcc93e..66c9fee5c80e 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/resolver.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/resolver.rs @@ -980,7 +980,7 @@ impl<'a> Resolver<'a> { let should_fold = attributes .function .as_ref() - .map_or(true, |func_attribute| func_attribute.is_foldable()); + .map_or(false, |func_attribute| func_attribute.is_foldable()); FuncMeta { name: name_ident, diff --git a/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/mod.rs b/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/mod.rs index 85eb2fbf07ec..9605f20b4974 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/mod.rs @@ -161,7 +161,13 @@ pub fn monomorphize_debug( undo_instantiation_bindings(bindings); } - let func_sigs = vecmap(monomorphizer.finished_functions.iter(), |(_, f)| f.func_sig.clone()); + let func_sigs = monomorphizer.finished_functions.iter().flat_map(|(_, f)| { + if f.should_fold || f.id == Program::main_id() { + Some(f.func_sig.clone()) + } else { + None + } + }).collect(); let functions = vecmap(monomorphizer.finished_functions, |(_, f)| f); let FuncMeta { return_distinctness, return_visibility, kind, .. } = From c9389017479e817ae753d0084a838bca57619edc Mon Sep 17 00:00:00 2001 From: vezenovm Date: Thu, 21 Mar 2024 03:08:46 +0000 Subject: [PATCH 106/139] cleanup --- .../compiler/noirc_evaluator/src/ssa.rs | 32 ++++++------------- .../src/ssa/acir_gen/acir_ir/acir_variable.rs | 1 - .../ssa/acir_gen/acir_ir/generated_acir.rs | 2 -- .../noirc_evaluator/src/ssa/acir_gen/mod.rs | 6 +--- .../src/monomorphization/mod.rs | 18 +++++++---- 5 files changed, 21 insertions(+), 38 deletions(-) diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs index ec73d0a17299..2aedc2f337f2 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs @@ -87,10 +87,6 @@ pub fn create_program( force_brillig_output: bool, ) -> Result<(AcirProgram, Vec, Vec, Vec, Vec), RuntimeError> { - // let entry_point_funcs = program.functions.iter().map(|function| { - // function.should_fold | function. - // }).collect::>(); - let debug_variables = program.debug_variables.clone(); let debug_types = program.debug_types.clone(); let debug_functions = program.debug_functions.clone(); @@ -104,24 +100,19 @@ pub fn create_program( enable_brillig_logging, force_brillig_output, )?; - assert_eq!(generated_acirs.len(), func_sigs.len(), "The generated ACIRs should match the supplied function signatures"); + assert_eq!( + generated_acirs.len(), + func_sigs.len(), + "The generated ACIRs should match the supplied function signatures" + ); let mut functions = vec![]; let mut debug_infos = vec![]; let mut warning_infos = vec![]; let mut main_input_witnesses = Vec::new(); let mut main_return_witnesses = Vec::new(); - // TODO: Using a flag here to avoid enumarting the loop as main is expected to be the first circuit - // We need function signatures to accurately set-up the `public_parameters` and `private_parameters` - // fields of a `Circuit`. However, a func_sig is restricted to what the main ABI allows. We need to be able - // to discern whether we have an ACIR function without an `InlineType::Inline` and treat that as an entry point function. - // For now we only treat main as an entry point function. - // Probably will need something like this: - // ``` - // let entry_point_funcs = program.functions.iter().map(|function| function.should_fold).collect::>(); - // ``` + // For setting up the ABI we need separately specify the input and return witnesses let mut is_main = true; - // TODO: need to appropriately handle fetching these `func_sigs` so that we do not have more func sigs than generated acirs for (acir, func_sig) in generated_acirs.into_iter().zip(func_sigs) { let (circuit, debug_info, warnings, input_witnesses, return_witnesses) = convert_generated_acir_into_circuit( @@ -164,18 +155,13 @@ fn convert_generated_acir_into_circuit( input_witnesses, assert_messages, warnings, - is_entry_point, .. } = generated_acir; - // dbg!(is_entry_point); + let locations = locations.clone(); - // let (public_parameter_witnesses, private_parameters) = if is_entry_point { - // split_public_and_private_inputs(&func_sig, &input_witnesses) - // } else { - // (BTreeSet::default(), BTreeSet::default()) - // }; - let (public_parameter_witnesses, private_parameters) = split_public_and_private_inputs(&func_sig, &input_witnesses); + let (public_parameter_witnesses, private_parameters) = + split_public_and_private_inputs(&func_sig, &input_witnesses); let public_parameters = PublicInputs(public_parameter_witnesses); let return_values = PublicInputs(return_witnesses.iter().copied().collect()); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs index 519e9ed51bb0..40b13e4583ab 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs @@ -1449,7 +1449,6 @@ impl AcirContext { ) -> GeneratedAcir { self.acir_ir.input_witnesses = inputs; self.acir_ir.warnings = warnings; - self.acir_ir.is_entry_point = true; self.acir_ir } diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs index 581380ca9236..5299df175bd8 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs @@ -58,8 +58,6 @@ pub(crate) struct GeneratedAcir { pub(crate) assert_messages: BTreeMap, pub(crate) warnings: Vec, - - pub(crate) is_entry_point: bool, } impl GeneratedAcir { diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs index 948425923bcb..59ded807e952 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs @@ -672,11 +672,7 @@ impl Context { } else { Self::flattened_value_size(&result.1) }; - self.initialize_array( - block_id, - len, - Some(result.1.clone()), - )?; + self.initialize_array(block_id, len, Some(result.1.clone()))?; } // Do nothing for AcirValue::DynamicArray and AcirValue::Var // A dynamic array returned from a function call should already be initialized diff --git a/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/mod.rs b/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/mod.rs index 9605f20b4974..e8c6ecbb6a6e 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/mod.rs @@ -161,13 +161,17 @@ pub fn monomorphize_debug( undo_instantiation_bindings(bindings); } - let func_sigs = monomorphizer.finished_functions.iter().flat_map(|(_, f)| { - if f.should_fold || f.id == Program::main_id() { - Some(f.func_sig.clone()) - } else { - None - } - }).collect(); + let func_sigs = monomorphizer + .finished_functions + .iter() + .flat_map(|(_, f)| { + if f.should_fold || f.id == Program::main_id() { + Some(f.func_sig.clone()) + } else { + None + } + }) + .collect(); let functions = vecmap(monomorphizer.finished_functions, |(_, f)| f); let FuncMeta { return_distinctness, return_visibility, kind, .. } = From 6c4222d9549309f57c1ccd555d2e48b345d7af9f Mon Sep 17 00:00:00 2001 From: vezenovm Date: Thu, 21 Mar 2024 14:05:14 +0000 Subject: [PATCH 107/139] comment improvement --- noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs | 2 +- noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/function.rs | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs index 59ded807e952..809973fc8268 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs @@ -571,9 +571,9 @@ impl Context { assert!(!matches!(inline_type, InlineType::Inline), "ICE: Got an ACIR function named {} that should have already been inlined", func.name()); let inputs = vecmap(arguments, |arg| self.convert_value(*arg, dfg)); + // TODO(https://github.com/noir-lang/noir/issues/4608): handle complex return types from ACIR functions let output_count = result_ids.iter().fold(0usize, |sum, result_id| { - // TODO: handle complex return types from ACIR functions sum + dfg.try_get_array_length(*result_id).unwrap_or(1) }); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/function.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/function.rs index 97a5bf71646a..c17738e30d8a 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/function.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/function.rs @@ -78,8 +78,6 @@ impl Function { self.runtime } - // TODO: make is_entry_point func - /// Set runtime type of the function. pub(crate) fn set_runtime(&mut self, runtime: RuntimeType) { self.runtime = runtime; From c2571b73550f4a5fb91c36622aa9cd7132348c37 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Thu, 21 Mar 2024 14:16:58 +0000 Subject: [PATCH 108/139] minor cleanup --- noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs | 2 +- .../noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs index 2aedc2f337f2..7ca9f7ff7c6e 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs @@ -111,7 +111,7 @@ pub fn create_program( let mut warning_infos = vec![]; let mut main_input_witnesses = Vec::new(); let mut main_return_witnesses = Vec::new(); - // For setting up the ABI we need separately specify the input and return witnesses + // For setting up the ABI we need separately specify main's input and return witnesses let mut is_main = true; for (acir, func_sig) in generated_acirs.into_iter().zip(func_sigs) { let (circuit, debug_info, warnings, input_witnesses, return_witnesses) = diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs index 5299df175bd8..1d05e998b13b 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs @@ -24,7 +24,7 @@ use acvm::{ use iter_extended::vecmap; use num_bigint::BigUint; -#[derive(Debug, Default, Clone)] +#[derive(Debug, Default)] /// The output of the Acir-gen pass pub(crate) struct GeneratedAcir { /// The next witness index that may be declared. From 8e077d05160b7bc4b84b4752f016539a5ff986b1 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Thu, 21 Mar 2024 21:31:44 +0000 Subject: [PATCH 109/139] basic acir calls working in the ACVM: --- .../acir/src/native_types/witness_map.rs | 3 + .../acir/src/native_types/witness_stack.rs | 6 + noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs | 81 ++++++++++- .../noirc_evaluator/src/ssa/acir_gen/mod.rs | 1 + .../execution_success/fold_basic/Nargo.toml | 7 + .../execution_success/fold_basic/Prover.toml | 2 + .../execution_success/fold_basic/src/main.nr | 11 ++ .../fold_basic_nested_call/Nargo.toml | 7 + .../fold_basic_nested_call/Prover.toml | 2 + .../fold_basic_nested_call/src/main.nr | 16 +++ .../fold_fibonacci/Nargo.toml | 7 + .../fold_fibonacci/Prover.toml | 1 + .../fold_fibonacci/src/main.nr | 13 ++ .../noir-repo/tooling/debugger/src/context.rs | 3 + .../tooling/nargo/src/ops/execute.rs | 128 ++++++++++++++++++ noir/noir-repo/tooling/nargo/src/ops/mod.rs | 1 + .../tooling/nargo_cli/src/cli/execute_cmd.rs | 20 ++- 17 files changed, 303 insertions(+), 6 deletions(-) create mode 100644 noir/noir-repo/test_programs/execution_success/fold_basic/Nargo.toml create mode 100644 noir/noir-repo/test_programs/execution_success/fold_basic/Prover.toml create mode 100644 noir/noir-repo/test_programs/execution_success/fold_basic/src/main.nr create mode 100644 noir/noir-repo/test_programs/execution_success/fold_basic_nested_call/Nargo.toml create mode 100644 noir/noir-repo/test_programs/execution_success/fold_basic_nested_call/Prover.toml create mode 100644 noir/noir-repo/test_programs/execution_success/fold_basic_nested_call/src/main.nr create mode 100644 noir/noir-repo/test_programs/execution_success/fold_fibonacci/Nargo.toml create mode 100644 noir/noir-repo/test_programs/execution_success/fold_fibonacci/Prover.toml create mode 100644 noir/noir-repo/test_programs/execution_success/fold_fibonacci/src/main.nr diff --git a/noir/noir-repo/acvm-repo/acir/src/native_types/witness_map.rs b/noir/noir-repo/acvm-repo/acir/src/native_types/witness_map.rs index 00245d5842ca..227c117f6b01 100644 --- a/noir/noir-repo/acvm-repo/acir/src/native_types/witness_map.rs +++ b/noir/noir-repo/acvm-repo/acir/src/native_types/witness_map.rs @@ -43,6 +43,9 @@ impl WitnessMap { pub fn insert(&mut self, key: Witness, value: FieldElement) -> Option { self.0.insert(key, value) } + pub fn values(&self) -> Vec { + self.0.values().copied().collect() + } } impl Index<&Witness> for WitnessMap { diff --git a/noir/noir-repo/acvm-repo/acir/src/native_types/witness_stack.rs b/noir/noir-repo/acvm-repo/acir/src/native_types/witness_stack.rs index 9592d90b014b..7f58213c81e7 100644 --- a/noir/noir-repo/acvm-repo/acir/src/native_types/witness_stack.rs +++ b/noir/noir-repo/acvm-repo/acir/src/native_types/witness_stack.rs @@ -32,6 +32,12 @@ pub struct StackItem { pub witness: WitnessMap, } +impl WitnessStack { + pub fn push(&mut self, index: u32, witness: WitnessMap) { + self.stack.push(StackItem { index, witness }); + } +} + impl From for WitnessStack { fn from(witness: WitnessMap) -> Self { let stack = vec![StackItem { index: 0, witness }]; diff --git a/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs b/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs index 0fd733a63368..d5a0ef6ce558 100644 --- a/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs +++ b/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs @@ -49,6 +49,12 @@ pub enum ACVMStatus { /// /// Once this is done, the ACVM can be restarted to solve the remaining opcodes. RequiresForeignCall(ForeignCallWaitInfo), + + /// The ACVM has encountered a request for an ACIR [call][acir::circuit::Opcode] + /// to execute a separate ACVM instance. The result of the ACIR call must be passd back to the ACVM. + /// + /// Once this is done, the ACVM can be restarted to solve the remaining opcodes. + RequiresAcirCall(AcirCallWaitInfo), } impl std::fmt::Display for ACVMStatus { @@ -58,6 +64,7 @@ impl std::fmt::Display for ACVMStatus { ACVMStatus::InProgress => write!(f, "In progress"), ACVMStatus::Failure(_) => write!(f, "Execution failure"), ACVMStatus::RequiresForeignCall(_) => write!(f, "Waiting on foreign call"), + ACVMStatus::RequiresAcirCall(_) => write!(f, "Waiting on acir call"), } } } @@ -147,6 +154,13 @@ pub struct ACVM<'a, B: BlackBoxFunctionSolver> { witness_map: WitnessMap, brillig_solver: Option>, + + /// A counter maintained throughout an ACVM process that determines + /// whether the caller has resolved the results of an ACIR [call][Opcode::Call]. + acir_call_counter: usize, + /// Represents the outputs of all ACIR calls during an ACVM process + /// List is appended onto by the caller upon reaching a [ACVMStatus::RequiresAcirCall] + acir_call_results: Vec>, } impl<'a, B: BlackBoxFunctionSolver> ACVM<'a, B> { @@ -161,6 +175,8 @@ impl<'a, B: BlackBoxFunctionSolver> ACVM<'a, B> { instruction_pointer: 0, witness_map: initial_witness, brillig_solver: None, + acir_call_counter: 0, + acir_call_results: Vec::default(), } } @@ -244,6 +260,29 @@ impl<'a, B: BlackBoxFunctionSolver> ACVM<'a, B> { self.status(ACVMStatus::InProgress); } + /// Sets the status of the VM to `RequriesAcirCall` + /// Indicating that the VM is now waiting for an ACIR call to be resolved + fn wait_for_acir_call(&mut self, acir_call: AcirCallWaitInfo) -> ACVMStatus { + self.status(ACVMStatus::RequiresAcirCall(acir_call)) + } + + /// Resolves a foreign call's [result][acir::brillig_vm::ForeignCallResult] using a result calculated outside of the ACVM. + /// + /// The ACVM can then be restarted to solve the remaining Brillig VM process as well as the remaining ACIR opcodes. + pub fn resolve_pending_acir_call(&mut self, call_result: Vec) { + if !matches!(self.status, ACVMStatus::RequiresAcirCall(_)) { + panic!("ACVM is not expecting an ACIR call response as no call was made"); + } + + if self.acir_call_counter < self.acir_call_results.len() { + panic!("No unresolved foreign calls"); + } + self.acir_call_results.push(call_result); + + // Now that the ACIR call has been resolved then we can resume execution. + self.status(ACVMStatus::InProgress); + } + /// Executes the ACVM's circuit until execution halts. /// /// Execution can halt due to three reasons: @@ -281,7 +320,12 @@ impl<'a, B: BlackBoxFunctionSolver> ACVM<'a, B> { Ok(Some(foreign_call)) => return self.wait_for_foreign_call(foreign_call), res => res.map(|_| ()), }, - Opcode::Call { .. } => todo!("Handle Call opcodes in the ACVM"), + Opcode::Call { .. } => { + match self.solve_call_opcode() { + Ok(Some(input_values)) => return self.wait_for_acir_call(input_values), + res => res.map(|_| ()), + } + } }; self.handle_opcode_resolution(resolution) } @@ -400,6 +444,33 @@ impl<'a, B: BlackBoxFunctionSolver> ACVM<'a, B> { self.brillig_solver = Some(solver); self.solve_opcode() } + + pub fn solve_call_opcode(&mut self) -> Result, OpcodeResolutionError> { + let Opcode::Call{ id, inputs, outputs }= &self.opcodes[self.instruction_pointer] else { + unreachable!("Not executing a Call opcode"); + }; + // TODO: add a resolution opcode error for this assert + assert!(*id != 0, "Attempting to call main, not allowed"); + + if self.acir_call_counter >= self.acir_call_results.len() { + let mut initial_witness = WitnessMap::default(); + for (i, input_witness) in inputs.iter().enumerate() { + let input_value = *witness_to_value(&self.witness_map, *input_witness)?; + initial_witness.insert(Witness(i as u32), input_value); + } + return Ok(Some(AcirCallWaitInfo { id: *id, initial_witness })) + } + + let result_values = &self.acir_call_results[self.acir_call_counter]; + // TODO: add a resolution opcode error for this assert + assert_eq!(outputs.len(), result_values.len(), "{} result values were provided for ACIR {} call output witnesses, most likely due to codegen", result_values.len(), outputs.len()); + + for (output_witness, result_value) in outputs.iter().zip(result_values) { + insert_value(output_witness, *result_value, &mut self.witness_map)?; + } + + Ok(None) + } } // Returns the concrete value for a particular witness @@ -469,3 +540,11 @@ fn any_witness_from_expression(expr: &Expression) -> Option { Some(expr.linear_combinations[0].1) } } + +#[derive(Debug, Clone, PartialEq)] +pub struct AcirCallWaitInfo { + /// Index in the list of ACIR function's that should be called + pub id: u32, + /// Initial witness for the given circuit to be called + pub initial_witness: WitnessMap +} diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs index 809973fc8268..439d9d1abb47 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs @@ -1430,6 +1430,7 @@ impl Context { TerminatorInstruction::Return { return_values, call_stack } => { (return_values, call_stack) } + // TODO: need to handle this for recursion _ => unreachable!("ICE: Program must have a singular return"), }; diff --git a/noir/noir-repo/test_programs/execution_success/fold_basic/Nargo.toml b/noir/noir-repo/test_programs/execution_success/fold_basic/Nargo.toml new file mode 100644 index 000000000000..575ba1f3ad14 --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/fold_basic/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "fold_basic" +type = "bin" +authors = [""] +compiler_version = ">=0.25.0" + +[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/execution_success/fold_basic/Prover.toml b/noir/noir-repo/test_programs/execution_success/fold_basic/Prover.toml new file mode 100644 index 000000000000..f28f2f8cc48f --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/fold_basic/Prover.toml @@ -0,0 +1,2 @@ +x = "5" +y = "10" diff --git a/noir/noir-repo/test_programs/execution_success/fold_basic/src/main.nr b/noir/noir-repo/test_programs/execution_success/fold_basic/src/main.nr new file mode 100644 index 000000000000..6c17120660bf --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/fold_basic/src/main.nr @@ -0,0 +1,11 @@ +fn main(x: Field, y: pub Field) { + let z = foo(x, y); + let z2 = foo(x, y); + assert(z == z2); +} + +#[fold] +fn foo(x: Field, y: Field) -> Field { + assert(x != y); + x +} diff --git a/noir/noir-repo/test_programs/execution_success/fold_basic_nested_call/Nargo.toml b/noir/noir-repo/test_programs/execution_success/fold_basic_nested_call/Nargo.toml new file mode 100644 index 000000000000..1b3c32999ae6 --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/fold_basic_nested_call/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "fold_basic_nested_call" +type = "bin" +authors = [""] +compiler_version = ">=0.25.0" + +[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/execution_success/fold_basic_nested_call/Prover.toml b/noir/noir-repo/test_programs/execution_success/fold_basic_nested_call/Prover.toml new file mode 100644 index 000000000000..f28f2f8cc48f --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/fold_basic_nested_call/Prover.toml @@ -0,0 +1,2 @@ +x = "5" +y = "10" diff --git a/noir/noir-repo/test_programs/execution_success/fold_basic_nested_call/src/main.nr b/noir/noir-repo/test_programs/execution_success/fold_basic_nested_call/src/main.nr new file mode 100644 index 000000000000..3eb16b409ff9 --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/fold_basic_nested_call/src/main.nr @@ -0,0 +1,16 @@ +fn main(x: Field, y: pub Field) { + let z = func_with_nested_foo_call(x, y); + let z2 = func_with_nested_foo_call(x, y); + assert(z == z2); +} + +#[fold] +fn func_with_nested_foo_call(x: Field, y: Field) -> Field { + foo(x + 2, y) +} + +#[fold] +fn foo(x: Field, y: Field) -> Field { + assert(x != y); + x +} \ No newline at end of file diff --git a/noir/noir-repo/test_programs/execution_success/fold_fibonacci/Nargo.toml b/noir/noir-repo/test_programs/execution_success/fold_fibonacci/Nargo.toml new file mode 100644 index 000000000000..1c43a7dedd09 --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/fold_fibonacci/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "fold_fibonacci" +type = "bin" +authors = [""] +compiler_version = ">=0.25.0" + +[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/execution_success/fold_fibonacci/Prover.toml b/noir/noir-repo/test_programs/execution_success/fold_fibonacci/Prover.toml new file mode 100644 index 000000000000..3a627b9188b9 --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/fold_fibonacci/Prover.toml @@ -0,0 +1 @@ +x = "10" diff --git a/noir/noir-repo/test_programs/execution_success/fold_fibonacci/src/main.nr b/noir/noir-repo/test_programs/execution_success/fold_fibonacci/src/main.nr new file mode 100644 index 000000000000..6abd80cb8c01 --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/fold_fibonacci/src/main.nr @@ -0,0 +1,13 @@ +// fn main(x: u32) { +// assert(fibonacci(x) == 55); +// } + +// TODO: handle recursion +// #[fold] +// fn fibonacci(x: u32) -> u32 { +// if x <= 1 { +// x +// } else { +// fibonacci(x - 1) + fibonacci(x - 2) +// } +// } diff --git a/noir/noir-repo/tooling/debugger/src/context.rs b/noir/noir-repo/tooling/debugger/src/context.rs index a3ee89263a48..7ce7b83627a6 100644 --- a/noir/noir-repo/tooling/debugger/src/context.rs +++ b/noir/noir-repo/tooling/debugger/src/context.rs @@ -381,6 +381,9 @@ impl<'a, B: BlackBoxFunctionSolver> DebugContext<'a, B> { ACVMStatus::RequiresForeignCall(_) => { unreachable!("Unexpected pending foreign call resolution"); } + ACVMStatus::RequiresAcirCall(_) => { + todo!("Multiple ACIR calls is not supported"); + } } } diff --git a/noir/noir-repo/tooling/nargo/src/ops/execute.rs b/noir/noir-repo/tooling/nargo/src/ops/execute.rs index 370393fea091..563bc3de58bb 100644 --- a/noir/noir-repo/tooling/nargo/src/ops/execute.rs +++ b/noir/noir-repo/tooling/nargo/src/ops/execute.rs @@ -1,3 +1,5 @@ +use acvm::acir::circuit::Program; +use acvm::acir::native_types::WitnessStack; use acvm::brillig_vm::brillig::ForeignCallResult; use acvm::pwg::{ACVMStatus, ErrorLocation, OpcodeResolutionError, ACVM}; use acvm::BlackBoxFunctionSolver; @@ -73,8 +75,134 @@ pub fn execute_circuit( } } } + ACVMStatus::RequiresAcirCall(acir_call) => { + dbg!(acir_call); + todo!("hit RequiresAcirCall status, handle it!"); + } } } Ok(acvm.finalize()) } + +struct ProgramExecutor<'a> { + functions: &'a [Circuit], + // This gets built as we run through the program looking at each function call + witness_stack: WitnessStack, +} + +impl<'a> ProgramExecutor<'a> { + fn new(functions: &'a [Circuit]) -> Self { + ProgramExecutor { + functions, + witness_stack: WitnessStack::default(), + } + } + + fn finalize(self) -> WitnessStack { + self.witness_stack + } + + #[tracing::instrument(level = "trace", skip_all)] + fn execute_circuit( + &mut self, + circuit: &Circuit, + initial_witness: WitnessMap, + blackbox_solver: &B, + foreign_call_executor: &mut F, + ) -> Result { + let mut acvm = ACVM::new(blackbox_solver, &circuit.opcodes, initial_witness); + + // This message should be resolved by a nargo foreign call only when we have an unsatisfied assertion. + let mut assert_message: Option = None; + loop { + let solver_status = acvm.solve(); + + match solver_status { + ACVMStatus::Solved => break, + ACVMStatus::InProgress => { + unreachable!("Execution should not stop while in `InProgress` state.") + } + ACVMStatus::Failure(error) => { + let call_stack = match &error { + OpcodeResolutionError::UnsatisfiedConstrain { + opcode_location: ErrorLocation::Resolved(opcode_location), + } => Some(vec![*opcode_location]), + OpcodeResolutionError::BrilligFunctionFailed { call_stack, .. } => { + Some(call_stack.clone()) + } + _ => None, + }; + + return Err(NargoError::ExecutionError(match call_stack { + Some(call_stack) => { + // First check whether we have a runtime assertion message that should be resolved on an ACVM failure + // If we do not have a runtime assertion message, we should check whether the circuit has any hardcoded + // messages associated with a specific `OpcodeLocation`. + // Otherwise return the provided opcode resolution error. + if let Some(assert_message) = assert_message { + ExecutionError::AssertionFailed(assert_message.to_owned(), call_stack) + } else if let Some(assert_message) = circuit.get_assert_message( + *call_stack.last().expect("Call stacks should not be empty"), + ) { + ExecutionError::AssertionFailed(assert_message.to_owned(), call_stack) + } else { + ExecutionError::SolvingError(error) + } + } + None => ExecutionError::SolvingError(error), + })); + } + ACVMStatus::RequiresForeignCall(foreign_call) => { + let foreign_call_result = foreign_call_executor.execute(&foreign_call)?; + match foreign_call_result { + NargoForeignCallResult::BrilligOutput(foreign_call_result) => { + acvm.resolve_pending_foreign_call(foreign_call_result); + } + NargoForeignCallResult::ResolvedAssertMessage(message) => { + if assert_message.is_some() { + unreachable!("Resolving an assert message should happen only once as the VM should have failed"); + } + assert_message = Some(message); + + acvm.resolve_pending_foreign_call(ForeignCallResult::default()); + } + } + } + ACVMStatus::RequiresAcirCall(acir_call) => { + dbg!(acir_call.clone()); + let acir_to_call = &self.functions[acir_call.id as usize]; + dbg!(acir_to_call.clone()); + let initial_witness = acir_call.initial_witness; + let call_solved_witness = self.execute_circuit(acir_to_call, initial_witness, blackbox_solver, foreign_call_executor)?; + dbg!(call_solved_witness.clone()); + let mut call_resolved_outputs = Vec::new(); + for witness_index in acir_to_call.return_values.indices() { + // TODO: turn this into a real execution error + call_resolved_outputs.push(*call_solved_witness.get_index(witness_index).expect("ACVM Error: should have return index")); + } + acvm.resolve_pending_acir_call(call_resolved_outputs); + self.witness_stack.push(acir_call.id, call_solved_witness); + } + } + } + + Ok(acvm.finalize()) + } +} + +#[tracing::instrument(level = "trace", skip_all)] +pub fn execute_program( + program: &Program, + initial_witness: WitnessMap, + blackbox_solver: &B, + foreign_call_executor: &mut F, +) -> Result { + let main = &program.functions[0]; + + let mut executor = ProgramExecutor::new(&program.functions); + let main_witness = executor.execute_circuit(main, initial_witness, blackbox_solver, foreign_call_executor)?; + executor.witness_stack.push(0, main_witness); + + Ok(executor.finalize()) +} diff --git a/noir/noir-repo/tooling/nargo/src/ops/mod.rs b/noir/noir-repo/tooling/nargo/src/ops/mod.rs index 55e9e927800f..924a225b12f7 100644 --- a/noir/noir-repo/tooling/nargo/src/ops/mod.rs +++ b/noir/noir-repo/tooling/nargo/src/ops/mod.rs @@ -3,6 +3,7 @@ pub use self::compile::{ compile_workspace, report_errors, }; pub use self::execute::execute_circuit; +pub use self::execute::execute_program; pub use self::foreign_calls::{ DefaultForeignCallExecutor, ForeignCall, ForeignCallExecutor, NargoForeignCallResult, }; diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/execute_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/execute_cmd.rs index 022bf7b761ec..1299f07fb1db 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/execute_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/execute_cmd.rs @@ -137,14 +137,24 @@ pub(crate) fn execute_program( let initial_witness = compiled_program.abi.encode(inputs_map, None)?; // TODO(https://github.com/noir-lang/noir/issues/4428) - let solved_witness_err = nargo::ops::execute_circuit( - &compiled_program.program.functions[0], - initial_witness, - &blackbox_solver, + let solved_witness_err = nargo::ops::execute_program( + &compiled_program.program, + initial_witness, + &blackbox_solver, &mut DefaultForeignCallExecutor::new(true, foreign_call_resolver_url), ); + // let solved_witness_err = nargo::ops::execute_circuit( + // &compiled_program.program.functions[0], + // initial_witness, + // &blackbox_solver, + // &mut DefaultForeignCallExecutor::new(true, foreign_call_resolver_url), + // ); match solved_witness_err { - Ok(solved_witness) => Ok(solved_witness), + // TODO(https://github.com/noir-lang/noir/issues/4428) + Ok(solved_witness) => { + dbg!(solved_witness.clone()); + Ok(solved_witness.stack[0].witness.clone()) + } Err(err) => { let debug_artifact = DebugArtifact { debug_symbols: vec![compiled_program.debug.clone()], From 1702856138f7194acf809d86e77bc73001d3de79 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Thu, 21 Mar 2024 21:44:26 +0000 Subject: [PATCH 110/139] add bb-js for dep for flaky test in config and todo in acir mod --- .circleci/config.yml | 1 + noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 124695b7e886..be77594e9c0d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1302,6 +1302,7 @@ workflows: <<: *defaults - noir-packages-tests: requires: + - bb-js - noir-ecr-manifest - noir-packages <<: *defaults diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs index 809973fc8268..47b1c74644c7 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs @@ -1430,6 +1430,7 @@ impl Context { TerminatorInstruction::Return { return_values, call_stack } => { (return_values, call_stack) } + // TODO(https://github.com/noir-lang/noir/issues/4616): Enable recursion on foldable/non-inlined ACIR functions _ => unreachable!("ICE: Program must have a singular return"), }; From e97b1524bf298acb2d2248b768109eb820f2c35b Mon Sep 17 00:00:00 2001 From: vezenovm Date: Thu, 21 Mar 2024 22:12:45 +0000 Subject: [PATCH 111/139] nested calls working --- noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs | 1 + noir/noir-repo/tooling/nargo/src/ops/execute.rs | 6 +----- noir/noir-repo/tooling/nargo_cli/src/cli/execute_cmd.rs | 1 - 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs b/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs index d5a0ef6ce558..b5518cec2c1b 100644 --- a/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs +++ b/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs @@ -469,6 +469,7 @@ impl<'a, B: BlackBoxFunctionSolver> ACVM<'a, B> { insert_value(output_witness, *result_value, &mut self.witness_map)?; } + self.acir_call_counter += 1; Ok(None) } } diff --git a/noir/noir-repo/tooling/nargo/src/ops/execute.rs b/noir/noir-repo/tooling/nargo/src/ops/execute.rs index 563bc3de58bb..9aa69f0d2073 100644 --- a/noir/noir-repo/tooling/nargo/src/ops/execute.rs +++ b/noir/noir-repo/tooling/nargo/src/ops/execute.rs @@ -76,8 +76,7 @@ pub fn execute_circuit( } } ACVMStatus::RequiresAcirCall(acir_call) => { - dbg!(acir_call); - todo!("hit RequiresAcirCall status, handle it!"); + unreachable!("hit RequiresAcirCall status, should have used program executor"); } } } @@ -170,12 +169,9 @@ impl<'a> ProgramExecutor<'a> { } } ACVMStatus::RequiresAcirCall(acir_call) => { - dbg!(acir_call.clone()); let acir_to_call = &self.functions[acir_call.id as usize]; - dbg!(acir_to_call.clone()); let initial_witness = acir_call.initial_witness; let call_solved_witness = self.execute_circuit(acir_to_call, initial_witness, blackbox_solver, foreign_call_executor)?; - dbg!(call_solved_witness.clone()); let mut call_resolved_outputs = Vec::new(); for witness_index in acir_to_call.return_values.indices() { // TODO: turn this into a real execution error diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/execute_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/execute_cmd.rs index 1299f07fb1db..53f29b3750df 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/execute_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/execute_cmd.rs @@ -152,7 +152,6 @@ pub(crate) fn execute_program( match solved_witness_err { // TODO(https://github.com/noir-lang/noir/issues/4428) Ok(solved_witness) => { - dbg!(solved_witness.clone()); Ok(solved_witness.stack[0].witness.clone()) } Err(err) => { From 6ea3ba93d0be712548de884307905601148b2cdb Mon Sep 17 00:00:00 2001 From: vezenovm Date: Thu, 21 Mar 2024 22:25:52 +0000 Subject: [PATCH 112/139] move WitnessStack returned from execute cmd --- .../acir/src/native_types/witness_stack.rs | 4 +++ .../backend_interface/src/proof_system.rs | 6 ++-- .../tooling/nargo_cli/src/cli/debug_cmd.rs | 4 +-- .../tooling/nargo_cli/src/cli/execute_cmd.rs | 34 +++++++------------ .../tooling/nargo_cli/src/cli/fs/witness.rs | 6 ++-- .../tooling/nargo_cli/src/cli/prove_cmd.rs | 8 +++-- 6 files changed, 29 insertions(+), 33 deletions(-) diff --git a/noir/noir-repo/acvm-repo/acir/src/native_types/witness_stack.rs b/noir/noir-repo/acvm-repo/acir/src/native_types/witness_stack.rs index 7f58213c81e7..3874594b6fd6 100644 --- a/noir/noir-repo/acvm-repo/acir/src/native_types/witness_stack.rs +++ b/noir/noir-repo/acvm-repo/acir/src/native_types/witness_stack.rs @@ -36,6 +36,10 @@ impl WitnessStack { pub fn push(&mut self, index: u32, witness: WitnessMap) { self.stack.push(StackItem { index, witness }); } + + pub fn peek(&self) -> Option<&StackItem> { + self.stack.last() + } } impl From for WitnessStack { diff --git a/noir/noir-repo/tooling/backend_interface/src/proof_system.rs b/noir/noir-repo/tooling/backend_interface/src/proof_system.rs index 211708aa846c..3b47a7ced3a7 100644 --- a/noir/noir-repo/tooling/backend_interface/src/proof_system.rs +++ b/noir/noir-repo/tooling/backend_interface/src/proof_system.rs @@ -4,7 +4,7 @@ use std::path::Path; use acvm::acir::{ circuit::{ExpressionWidth, Program}, - native_types::WitnessMap, + native_types::{WitnessMap, WitnessStack}, }; use acvm::FieldElement; use tempfile::tempdir; @@ -56,7 +56,7 @@ impl Backend { pub fn prove( &self, program: &Program, - witness_values: WitnessMap, + witness_stack: WitnessStack, ) -> Result, BackendError> { let binary_path = self.assert_binary_exists()?; self.assert_correct_version()?; @@ -66,7 +66,7 @@ impl Backend { // Create a temporary file for the witness let serialized_witnesses: Vec = - witness_values.try_into().expect("could not serialize witness map"); + witness_stack.try_into().expect("could not serialize witness map"); let witness_path = temp_directory.join("witness").with_extension("tr"); write_to_file(&serialized_witnesses, &witness_path); diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/debug_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/debug_cmd.rs index 1f448105ee25..86e7f0cdfe77 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/debug_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/debug_cmd.rs @@ -1,6 +1,6 @@ use std::path::PathBuf; -use acvm::acir::native_types::WitnessMap; +use acvm::acir::native_types::{WitnessMap, WitnessStack}; use bn254_blackbox_solver::Bn254BlackBoxSolver; use clap::Args; @@ -187,7 +187,7 @@ fn run_async( } if let Some(witness_name) = witness_name { - let witness_path = save_witness_to_dir(solved_witness, witness_name, target_dir)?; + let witness_path = save_witness_to_dir(WitnessStack::from(solved_witness), witness_name, target_dir)?; println!("[{}] Witness saved to {}", package.name, witness_path.display()); } diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/execute_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/execute_cmd.rs index 53f29b3750df..50cd138bac82 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/execute_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/execute_cmd.rs @@ -1,4 +1,4 @@ -use acvm::acir::native_types::WitnessMap; +use acvm::acir::native_types::{WitnessMap, WitnessStack}; use bn254_blackbox_solver::Bn254BlackBoxSolver; use clap::Args; @@ -91,7 +91,7 @@ pub(crate) fn run( let compiled_program = nargo::ops::transform_program(compiled_program, expression_width); - let (return_value, solved_witness) = execute_program_and_decode( + let (return_value, witness_stack) = execute_program_and_decode( compiled_program, package, &args.prover_name, @@ -103,7 +103,7 @@ pub(crate) fn run( println!("[{}] Circuit output: {return_value:?}", package.name); } if let Some(witness_name) = &args.witness_name { - let witness_path = save_witness_to_dir(solved_witness, witness_name, target_dir)?; + let witness_path = save_witness_to_dir(witness_stack, witness_name, target_dir)?; println!("[{}] Witness saved to {}", package.name, witness_path.display()); } @@ -116,44 +116,36 @@ fn execute_program_and_decode( package: &Package, prover_name: &str, foreign_call_resolver_url: Option<&str>, -) -> Result<(Option, WitnessMap), CliError> { +) -> Result<(Option, WitnessStack), CliError> { // Parse the initial witness values from Prover.toml let (inputs_map, _) = read_inputs_from_file(&package.root_dir, prover_name, Format::Toml, &program.abi)?; - let solved_witness = execute_program(&program, &inputs_map, foreign_call_resolver_url)?; + let witness_stack = execute_program(&program, &inputs_map, foreign_call_resolver_url)?; let public_abi = program.abi.public_abi(); - let (_, return_value) = public_abi.decode(&solved_witness)?; + // Get the entry point witness for the ABI + let main_witness = &witness_stack.peek().expect("Should have at least one witness on the stack").witness; + let (_, return_value) = public_abi.decode(main_witness)?; - Ok((return_value, solved_witness)) + Ok((return_value, witness_stack)) } pub(crate) fn execute_program( compiled_program: &CompiledProgram, inputs_map: &InputMap, foreign_call_resolver_url: Option<&str>, -) -> Result { +) -> Result { let blackbox_solver = Bn254BlackBoxSolver::new(); let initial_witness = compiled_program.abi.encode(inputs_map, None)?; - // TODO(https://github.com/noir-lang/noir/issues/4428) - let solved_witness_err = nargo::ops::execute_program( + let solved_witness_stack_err = nargo::ops::execute_program( &compiled_program.program, initial_witness, &blackbox_solver, &mut DefaultForeignCallExecutor::new(true, foreign_call_resolver_url), ); - // let solved_witness_err = nargo::ops::execute_circuit( - // &compiled_program.program.functions[0], - // initial_witness, - // &blackbox_solver, - // &mut DefaultForeignCallExecutor::new(true, foreign_call_resolver_url), - // ); - match solved_witness_err { - // TODO(https://github.com/noir-lang/noir/issues/4428) - Ok(solved_witness) => { - Ok(solved_witness.stack[0].witness.clone()) - } + match solved_witness_stack_err { + Ok(solved_witness_stack) => Ok(solved_witness_stack), Err(err) => { let debug_artifact = DebugArtifact { debug_symbols: vec![compiled_program.debug.clone()], diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/fs/witness.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/fs/witness.rs index 52b5c385e5df..613cdec28da3 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/fs/witness.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/fs/witness.rs @@ -1,21 +1,19 @@ use std::path::{Path, PathBuf}; -use acvm::acir::native_types::{WitnessMap, WitnessStack}; +use acvm::acir::native_types::WitnessStack; use nargo::constants::WITNESS_EXT; use super::{create_named_dir, write_to_file}; use crate::errors::FilesystemError; pub(crate) fn save_witness_to_dir>( - witnesses: WitnessMap, + witness_stack: WitnessStack, witness_name: &str, witness_dir: P, ) -> Result { create_named_dir(witness_dir.as_ref(), "witness"); let witness_path = witness_dir.as_ref().join(witness_name).with_extension(WITNESS_EXT); - // TODO(https://github.com/noir-lang/noir/issues/4428) - let witness_stack: WitnessStack = witnesses.into(); let buf: Vec = witness_stack.try_into()?; write_to_file(buf.as_slice(), &witness_path); diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/prove_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/prove_cmd.rs index 9847977deeff..02ed47f3bd54 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/prove_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/prove_cmd.rs @@ -122,12 +122,14 @@ pub(crate) fn prove_package( let (inputs_map, _) = read_inputs_from_file(&package.root_dir, prover_name, Format::Toml, &compiled_program.abi)?; - let solved_witness = + let witness_stack = execute_program(&compiled_program, &inputs_map, foreign_call_resolver_url)?; // Write public inputs into Verifier.toml let public_abi = compiled_program.abi.public_abi(); - let (public_inputs, return_value) = public_abi.decode(&solved_witness)?; + // Get the entry point witness for the ABI + let main_witness = &witness_stack.peek().expect("Should have at least one witness on the stack").witness; + let (public_inputs, return_value) = public_abi.decode(main_witness)?; write_inputs_to_file( &public_inputs, @@ -138,7 +140,7 @@ pub(crate) fn prove_package( Format::Toml, )?; - let proof = backend.prove(&compiled_program.program, solved_witness)?; + let proof = backend.prove(&compiled_program.program, witness_stack)?; if check_proof { let public_inputs = public_abi.encode(&public_inputs, return_value)?; From 7d7026a65a0b10d10dece3dc9ccc5f1a62343f35 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Thu, 21 Mar 2024 22:26:58 +0000 Subject: [PATCH 113/139] Cargo fmt --- noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs | 20 ++++----- .../tooling/nargo/src/ops/execute.rs | 41 ++++++++++++------- .../tooling/nargo_cli/src/cli/debug_cmd.rs | 6 ++- .../tooling/nargo_cli/src/cli/execute_cmd.rs | 9 ++-- .../tooling/nargo_cli/src/cli/prove_cmd.rs | 6 +-- 5 files changed, 49 insertions(+), 33 deletions(-) diff --git a/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs b/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs index b5518cec2c1b..5a288d3ca3c2 100644 --- a/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs +++ b/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs @@ -52,7 +52,7 @@ pub enum ACVMStatus { /// The ACVM has encountered a request for an ACIR [call][acir::circuit::Opcode] /// to execute a separate ACVM instance. The result of the ACIR call must be passd back to the ACVM. - /// + /// /// Once this is done, the ACVM can be restarted to solve the remaining opcodes. RequiresAcirCall(AcirCallWaitInfo), } @@ -320,12 +320,10 @@ impl<'a, B: BlackBoxFunctionSolver> ACVM<'a, B> { Ok(Some(foreign_call)) => return self.wait_for_foreign_call(foreign_call), res => res.map(|_| ()), }, - Opcode::Call { .. } => { - match self.solve_call_opcode() { - Ok(Some(input_values)) => return self.wait_for_acir_call(input_values), - res => res.map(|_| ()), - } - } + Opcode::Call { .. } => match self.solve_call_opcode() { + Ok(Some(input_values)) => return self.wait_for_acir_call(input_values), + res => res.map(|_| ()), + }, }; self.handle_opcode_resolution(resolution) } @@ -446,9 +444,9 @@ impl<'a, B: BlackBoxFunctionSolver> ACVM<'a, B> { } pub fn solve_call_opcode(&mut self) -> Result, OpcodeResolutionError> { - let Opcode::Call{ id, inputs, outputs }= &self.opcodes[self.instruction_pointer] else { + let Opcode::Call { id, inputs, outputs } = &self.opcodes[self.instruction_pointer] else { unreachable!("Not executing a Call opcode"); - }; + }; // TODO: add a resolution opcode error for this assert assert!(*id != 0, "Attempting to call main, not allowed"); @@ -458,7 +456,7 @@ impl<'a, B: BlackBoxFunctionSolver> ACVM<'a, B> { let input_value = *witness_to_value(&self.witness_map, *input_witness)?; initial_witness.insert(Witness(i as u32), input_value); } - return Ok(Some(AcirCallWaitInfo { id: *id, initial_witness })) + return Ok(Some(AcirCallWaitInfo { id: *id, initial_witness })); } let result_values = &self.acir_call_results[self.acir_call_counter]; @@ -547,5 +545,5 @@ pub struct AcirCallWaitInfo { /// Index in the list of ACIR function's that should be called pub id: u32, /// Initial witness for the given circuit to be called - pub initial_witness: WitnessMap + pub initial_witness: WitnessMap, } diff --git a/noir/noir-repo/tooling/nargo/src/ops/execute.rs b/noir/noir-repo/tooling/nargo/src/ops/execute.rs index 9aa69f0d2073..484a6a3a538a 100644 --- a/noir/noir-repo/tooling/nargo/src/ops/execute.rs +++ b/noir/noir-repo/tooling/nargo/src/ops/execute.rs @@ -92,10 +92,7 @@ struct ProgramExecutor<'a> { impl<'a> ProgramExecutor<'a> { fn new(functions: &'a [Circuit]) -> Self { - ProgramExecutor { - functions, - witness_stack: WitnessStack::default(), - } + ProgramExecutor { functions, witness_stack: WitnessStack::default() } } fn finalize(self) -> WitnessStack { @@ -111,12 +108,12 @@ impl<'a> ProgramExecutor<'a> { foreign_call_executor: &mut F, ) -> Result { let mut acvm = ACVM::new(blackbox_solver, &circuit.opcodes, initial_witness); - + // This message should be resolved by a nargo foreign call only when we have an unsatisfied assertion. let mut assert_message: Option = None; loop { let solver_status = acvm.solve(); - + match solver_status { ACVMStatus::Solved => break, ACVMStatus::InProgress => { @@ -132,7 +129,7 @@ impl<'a> ProgramExecutor<'a> { } _ => None, }; - + return Err(NargoError::ExecutionError(match call_stack { Some(call_stack) => { // First check whether we have a runtime assertion message that should be resolved on an ACVM failure @@ -140,11 +137,17 @@ impl<'a> ProgramExecutor<'a> { // messages associated with a specific `OpcodeLocation`. // Otherwise return the provided opcode resolution error. if let Some(assert_message) = assert_message { - ExecutionError::AssertionFailed(assert_message.to_owned(), call_stack) + ExecutionError::AssertionFailed( + assert_message.to_owned(), + call_stack, + ) } else if let Some(assert_message) = circuit.get_assert_message( *call_stack.last().expect("Call stacks should not be empty"), ) { - ExecutionError::AssertionFailed(assert_message.to_owned(), call_stack) + ExecutionError::AssertionFailed( + assert_message.to_owned(), + call_stack, + ) } else { ExecutionError::SolvingError(error) } @@ -163,7 +166,7 @@ impl<'a> ProgramExecutor<'a> { unreachable!("Resolving an assert message should happen only once as the VM should have failed"); } assert_message = Some(message); - + acvm.resolve_pending_foreign_call(ForeignCallResult::default()); } } @@ -171,18 +174,27 @@ impl<'a> ProgramExecutor<'a> { ACVMStatus::RequiresAcirCall(acir_call) => { let acir_to_call = &self.functions[acir_call.id as usize]; let initial_witness = acir_call.initial_witness; - let call_solved_witness = self.execute_circuit(acir_to_call, initial_witness, blackbox_solver, foreign_call_executor)?; + let call_solved_witness = self.execute_circuit( + acir_to_call, + initial_witness, + blackbox_solver, + foreign_call_executor, + )?; let mut call_resolved_outputs = Vec::new(); for witness_index in acir_to_call.return_values.indices() { // TODO: turn this into a real execution error - call_resolved_outputs.push(*call_solved_witness.get_index(witness_index).expect("ACVM Error: should have return index")); + call_resolved_outputs.push( + *call_solved_witness + .get_index(witness_index) + .expect("ACVM Error: should have return index"), + ); } acvm.resolve_pending_acir_call(call_resolved_outputs); self.witness_stack.push(acir_call.id, call_solved_witness); } } } - + Ok(acvm.finalize()) } } @@ -197,7 +209,8 @@ pub fn execute_program( let main = &program.functions[0]; let mut executor = ProgramExecutor::new(&program.functions); - let main_witness = executor.execute_circuit(main, initial_witness, blackbox_solver, foreign_call_executor)?; + let main_witness = + executor.execute_circuit(main, initial_witness, blackbox_solver, foreign_call_executor)?; executor.witness_stack.push(0, main_witness); Ok(executor.finalize()) diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/debug_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/debug_cmd.rs index 86e7f0cdfe77..4f3e2886b2e0 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/debug_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/debug_cmd.rs @@ -187,7 +187,11 @@ fn run_async( } if let Some(witness_name) = witness_name { - let witness_path = save_witness_to_dir(WitnessStack::from(solved_witness), witness_name, target_dir)?; + let witness_path = save_witness_to_dir( + WitnessStack::from(solved_witness), + witness_name, + target_dir, + )?; println!("[{}] Witness saved to {}", package.name, witness_path.display()); } diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/execute_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/execute_cmd.rs index 50cd138bac82..4f83a046cccd 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/execute_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/execute_cmd.rs @@ -123,7 +123,8 @@ fn execute_program_and_decode( let witness_stack = execute_program(&program, &inputs_map, foreign_call_resolver_url)?; let public_abi = program.abi.public_abi(); // Get the entry point witness for the ABI - let main_witness = &witness_stack.peek().expect("Should have at least one witness on the stack").witness; + let main_witness = + &witness_stack.peek().expect("Should have at least one witness on the stack").witness; let (_, return_value) = public_abi.decode(main_witness)?; Ok((return_value, witness_stack)) @@ -139,9 +140,9 @@ pub(crate) fn execute_program( let initial_witness = compiled_program.abi.encode(inputs_map, None)?; let solved_witness_stack_err = nargo::ops::execute_program( - &compiled_program.program, - initial_witness, - &blackbox_solver, + &compiled_program.program, + initial_witness, + &blackbox_solver, &mut DefaultForeignCallExecutor::new(true, foreign_call_resolver_url), ); match solved_witness_stack_err { diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/prove_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/prove_cmd.rs index 02ed47f3bd54..b9e4bca9e697 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/prove_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/prove_cmd.rs @@ -122,13 +122,13 @@ pub(crate) fn prove_package( let (inputs_map, _) = read_inputs_from_file(&package.root_dir, prover_name, Format::Toml, &compiled_program.abi)?; - let witness_stack = - execute_program(&compiled_program, &inputs_map, foreign_call_resolver_url)?; + let witness_stack = execute_program(&compiled_program, &inputs_map, foreign_call_resolver_url)?; // Write public inputs into Verifier.toml let public_abi = compiled_program.abi.public_abi(); // Get the entry point witness for the ABI - let main_witness = &witness_stack.peek().expect("Should have at least one witness on the stack").witness; + let main_witness = + &witness_stack.peek().expect("Should have at least one witness on the stack").witness; let (public_inputs, return_value) = public_abi.decode(main_witness)?; write_inputs_to_file( From a512df1df9f832b8664912b33cb388465d7653fc Mon Sep 17 00:00:00 2001 From: vezenovm Date: Thu, 21 Mar 2024 22:28:52 +0000 Subject: [PATCH 114/139] cargo clippy --- noir/noir-repo/tooling/nargo/src/ops/execute.rs | 2 +- noir/noir-repo/tooling/nargo_cli/src/cli/execute_cmd.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/noir/noir-repo/tooling/nargo/src/ops/execute.rs b/noir/noir-repo/tooling/nargo/src/ops/execute.rs index 484a6a3a538a..6b32a81207c6 100644 --- a/noir/noir-repo/tooling/nargo/src/ops/execute.rs +++ b/noir/noir-repo/tooling/nargo/src/ops/execute.rs @@ -75,7 +75,7 @@ pub fn execute_circuit( } } } - ACVMStatus::RequiresAcirCall(acir_call) => { + ACVMStatus::RequiresAcirCall(_) => { unreachable!("hit RequiresAcirCall status, should have used program executor"); } } diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/execute_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/execute_cmd.rs index 4f83a046cccd..697f6d7c1ea6 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/execute_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/execute_cmd.rs @@ -1,4 +1,4 @@ -use acvm::acir::native_types::{WitnessMap, WitnessStack}; +use acvm::acir::native_types::WitnessStack; use bn254_blackbox_solver::Bn254BlackBoxSolver; use clap::Args; From 89452bae68a136dd7fefb8c527ae68230aae2ef8 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Tue, 26 Mar 2024 16:52:58 +0000 Subject: [PATCH 115/139] cargo clippy --- noir/noir-repo/tooling/nargo_cli/src/cli/prove_cmd.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/prove_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/prove_cmd.rs index 1e7b54e0b9bd..b9e4bca9e697 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/prove_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/prove_cmd.rs @@ -1,4 +1,3 @@ -use acvm::acir::native_types::WitnessStack; use clap::Args; use nargo::constants::{PROVER_INPUT_FILE, VERIFIER_INPUT_FILE}; use nargo::ops::{compile_program, report_errors}; From 8ef8408f0dd357532d08ec699ad2868c8f0a62d4 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Tue, 26 Mar 2024 17:14:28 +0000 Subject: [PATCH 116/139] cleanup --- .../acir/src/native_types/witness_stack.rs | 4 + .../acvm-repo/acvm_js/src/execute.rs | 3 + .../fold_fibonacci/Nargo.toml | 7 -- .../fold_fibonacci/Prover.toml | 1 - .../fold_fibonacci/src/main.nr | 13 ---- .../tooling/acvm_cli/src/cli/execute_cmd.rs | 21 +++--- .../tooling/nargo/src/ops/execute.rs | 75 ------------------- noir/noir-repo/tooling/nargo/src/ops/mod.rs | 1 - noir/noir-repo/tooling/nargo/src/ops/test.rs | 14 ++-- 9 files changed, 27 insertions(+), 112 deletions(-) delete mode 100644 noir/noir-repo/test_programs/execution_success/fold_fibonacci/Nargo.toml delete mode 100644 noir/noir-repo/test_programs/execution_success/fold_fibonacci/Prover.toml delete mode 100644 noir/noir-repo/test_programs/execution_success/fold_fibonacci/src/main.nr diff --git a/noir/noir-repo/acvm-repo/acir/src/native_types/witness_stack.rs b/noir/noir-repo/acvm-repo/acir/src/native_types/witness_stack.rs index 3874594b6fd6..a9e8f219b3e7 100644 --- a/noir/noir-repo/acvm-repo/acir/src/native_types/witness_stack.rs +++ b/noir/noir-repo/acvm-repo/acir/src/native_types/witness_stack.rs @@ -40,6 +40,10 @@ impl WitnessStack { pub fn peek(&self) -> Option<&StackItem> { self.stack.last() } + + pub fn length(&self) -> usize { + self.stack.len() + } } impl From for WitnessStack { diff --git a/noir/noir-repo/acvm-repo/acvm_js/src/execute.rs b/noir/noir-repo/acvm-repo/acvm_js/src/execute.rs index ac71a573e64b..60d27a489e20 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/src/execute.rs +++ b/noir/noir-repo/acvm-repo/acvm_js/src/execute.rs @@ -113,6 +113,9 @@ pub async fn execute_circuit_with_black_box_solver( acvm.resolve_pending_foreign_call(result); } + ACVMStatus::RequiresAcirCall(_) => { + todo!("Handle acir calls in acvm JS"); + } } } diff --git a/noir/noir-repo/test_programs/execution_success/fold_fibonacci/Nargo.toml b/noir/noir-repo/test_programs/execution_success/fold_fibonacci/Nargo.toml deleted file mode 100644 index 1c43a7dedd09..000000000000 --- a/noir/noir-repo/test_programs/execution_success/fold_fibonacci/Nargo.toml +++ /dev/null @@ -1,7 +0,0 @@ -[package] -name = "fold_fibonacci" -type = "bin" -authors = [""] -compiler_version = ">=0.25.0" - -[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/execution_success/fold_fibonacci/Prover.toml b/noir/noir-repo/test_programs/execution_success/fold_fibonacci/Prover.toml deleted file mode 100644 index 3a627b9188b9..000000000000 --- a/noir/noir-repo/test_programs/execution_success/fold_fibonacci/Prover.toml +++ /dev/null @@ -1 +0,0 @@ -x = "10" diff --git a/noir/noir-repo/test_programs/execution_success/fold_fibonacci/src/main.nr b/noir/noir-repo/test_programs/execution_success/fold_fibonacci/src/main.nr deleted file mode 100644 index 6abd80cb8c01..000000000000 --- a/noir/noir-repo/test_programs/execution_success/fold_fibonacci/src/main.nr +++ /dev/null @@ -1,13 +0,0 @@ -// fn main(x: u32) { -// assert(fibonacci(x) == 55); -// } - -// TODO: handle recursion -// #[fold] -// fn fibonacci(x: u32) -> u32 { -// if x <= 1 { -// x -// } else { -// fibonacci(x - 1) + fibonacci(x - 2) -// } -// } diff --git a/noir/noir-repo/tooling/acvm_cli/src/cli/execute_cmd.rs b/noir/noir-repo/tooling/acvm_cli/src/cli/execute_cmd.rs index b76d0eccc29c..86e7277451fb 100644 --- a/noir/noir-repo/tooling/acvm_cli/src/cli/execute_cmd.rs +++ b/noir/noir-repo/tooling/acvm_cli/src/cli/execute_cmd.rs @@ -1,14 +1,14 @@ use std::io::{self, Write}; use acir::circuit::Program; -use acir::native_types::WitnessMap; +use acir::native_types::{WitnessMap, WitnessStack}; use bn254_blackbox_solver::Bn254BlackBoxSolver; use clap::Args; use crate::cli::fs::inputs::{read_bytecode_from_file, read_inputs_from_file}; use crate::cli::fs::witness::save_witness_to_dir; use crate::errors::CliError; -use nargo::ops::{execute_circuit, DefaultForeignCallExecutor}; +use nargo::ops::{execute_program, DefaultForeignCallExecutor}; use super::fs::witness::create_output_witness_string; @@ -39,8 +39,11 @@ pub(crate) struct ExecuteCommand { fn run_command(args: ExecuteCommand) -> Result { let bytecode = read_bytecode_from_file(&args.working_directory, &args.bytecode)?; let circuit_inputs = read_inputs_from_file(&args.working_directory, &args.input_witness)?; - let output_witness = execute_program_from_witness(&circuit_inputs, &bytecode, None)?; - let output_witness_string = create_output_witness_string(&output_witness)?; + let output_witness = execute_program_from_witness(circuit_inputs, &bytecode, None)?; + assert_eq!(output_witness.length(), 1, "ACVM CLI only supports a witness stack of size 1"); + let output_witness_string = create_output_witness_string( + &output_witness.peek().expect("Should have a witness stack item").witness, + )?; if args.output_witness.is_some() { save_witness_to_dir( &output_witness_string, @@ -61,16 +64,16 @@ pub(crate) fn run(args: ExecuteCommand) -> Result { } pub(crate) fn execute_program_from_witness( - inputs_map: &WitnessMap, + inputs_map: WitnessMap, bytecode: &[u8], foreign_call_resolver_url: Option<&str>, -) -> Result { +) -> Result { let blackbox_solver = Bn254BlackBoxSolver::new(); let program: Program = Program::deserialize_program(bytecode) .map_err(|_| CliError::CircuitDeserializationError())?; - execute_circuit( - &program.functions[0], - inputs_map.clone(), + execute_program( + &program, + inputs_map, &blackbox_solver, &mut DefaultForeignCallExecutor::new(true, foreign_call_resolver_url), ) diff --git a/noir/noir-repo/tooling/nargo/src/ops/execute.rs b/noir/noir-repo/tooling/nargo/src/ops/execute.rs index 6b32a81207c6..86fb83e9faf9 100644 --- a/noir/noir-repo/tooling/nargo/src/ops/execute.rs +++ b/noir/noir-repo/tooling/nargo/src/ops/execute.rs @@ -9,81 +9,6 @@ use crate::errors::ExecutionError; use crate::NargoError; use super::foreign_calls::{ForeignCallExecutor, NargoForeignCallResult}; - -#[tracing::instrument(level = "trace", skip_all)] -pub fn execute_circuit( - circuit: &Circuit, - initial_witness: WitnessMap, - blackbox_solver: &B, - foreign_call_executor: &mut F, -) -> Result { - let mut acvm = ACVM::new(blackbox_solver, &circuit.opcodes, initial_witness); - - // This message should be resolved by a nargo foreign call only when we have an unsatisfied assertion. - let mut assert_message: Option = None; - loop { - let solver_status = acvm.solve(); - - match solver_status { - ACVMStatus::Solved => break, - ACVMStatus::InProgress => { - unreachable!("Execution should not stop while in `InProgress` state.") - } - ACVMStatus::Failure(error) => { - let call_stack = match &error { - OpcodeResolutionError::UnsatisfiedConstrain { - opcode_location: ErrorLocation::Resolved(opcode_location), - } => Some(vec![*opcode_location]), - OpcodeResolutionError::BrilligFunctionFailed { call_stack, .. } => { - Some(call_stack.clone()) - } - _ => None, - }; - - return Err(NargoError::ExecutionError(match call_stack { - Some(call_stack) => { - // First check whether we have a runtime assertion message that should be resolved on an ACVM failure - // If we do not have a runtime assertion message, we should check whether the circuit has any hardcoded - // messages associated with a specific `OpcodeLocation`. - // Otherwise return the provided opcode resolution error. - if let Some(assert_message) = assert_message { - ExecutionError::AssertionFailed(assert_message.to_owned(), call_stack) - } else if let Some(assert_message) = circuit.get_assert_message( - *call_stack.last().expect("Call stacks should not be empty"), - ) { - ExecutionError::AssertionFailed(assert_message.to_owned(), call_stack) - } else { - ExecutionError::SolvingError(error) - } - } - None => ExecutionError::SolvingError(error), - })); - } - ACVMStatus::RequiresForeignCall(foreign_call) => { - let foreign_call_result = foreign_call_executor.execute(&foreign_call)?; - match foreign_call_result { - NargoForeignCallResult::BrilligOutput(foreign_call_result) => { - acvm.resolve_pending_foreign_call(foreign_call_result); - } - NargoForeignCallResult::ResolvedAssertMessage(message) => { - if assert_message.is_some() { - unreachable!("Resolving an assert message should happen only once as the VM should have failed"); - } - assert_message = Some(message); - - acvm.resolve_pending_foreign_call(ForeignCallResult::default()); - } - } - } - ACVMStatus::RequiresAcirCall(_) => { - unreachable!("hit RequiresAcirCall status, should have used program executor"); - } - } - } - - Ok(acvm.finalize()) -} - struct ProgramExecutor<'a> { functions: &'a [Circuit], // This gets built as we run through the program looking at each function call diff --git a/noir/noir-repo/tooling/nargo/src/ops/mod.rs b/noir/noir-repo/tooling/nargo/src/ops/mod.rs index 924a225b12f7..2f5e6ebb7d43 100644 --- a/noir/noir-repo/tooling/nargo/src/ops/mod.rs +++ b/noir/noir-repo/tooling/nargo/src/ops/mod.rs @@ -2,7 +2,6 @@ pub use self::compile::{ collect_errors, compile_contract, compile_program, compile_program_with_debug_instrumenter, compile_workspace, report_errors, }; -pub use self::execute::execute_circuit; pub use self::execute::execute_program; pub use self::foreign_calls::{ DefaultForeignCallExecutor, ForeignCall, ForeignCallExecutor, NargoForeignCallResult, diff --git a/noir/noir-repo/tooling/nargo/src/ops/test.rs b/noir/noir-repo/tooling/nargo/src/ops/test.rs index 8cf2934da4d8..45b1a88f99c8 100644 --- a/noir/noir-repo/tooling/nargo/src/ops/test.rs +++ b/noir/noir-repo/tooling/nargo/src/ops/test.rs @@ -1,4 +1,7 @@ -use acvm::{acir::native_types::WitnessMap, BlackBoxFunctionSolver}; +use acvm::{ + acir::native_types::{WitnessMap, WitnessStack}, + BlackBoxFunctionSolver, +}; use noirc_driver::{compile_no_check, CompileError, CompileOptions}; use noirc_errors::{debug_info::DebugInfo, FileDiagnostic}; use noirc_evaluator::errors::RuntimeError; @@ -6,7 +9,7 @@ use noirc_frontend::hir::{def_map::TestFunction, Context}; use crate::{errors::try_to_diagnose_runtime_error, NargoError}; -use super::{execute_circuit, DefaultForeignCallExecutor}; +use super::{execute_program, DefaultForeignCallExecutor}; pub enum TestStatus { Pass, @@ -33,9 +36,8 @@ pub fn run_test( Ok(compiled_program) => { // Run the backend to ensure the PWG evaluates functions like std::hash::pedersen, // otherwise constraints involving these expressions will not error. - let circuit_execution = execute_circuit( - // TODO(https://github.com/noir-lang/noir/issues/4428) - &compiled_program.program.functions[0], + let circuit_execution = execute_program( + &compiled_program.program, WitnessMap::new(), blackbox_solver, &mut DefaultForeignCallExecutor::new(show_output, foreign_call_resolver_url), @@ -83,7 +85,7 @@ fn test_status_program_compile_fail(err: CompileError, test_function: &TestFunct fn test_status_program_compile_pass( test_function: &TestFunction, debug: DebugInfo, - circuit_execution: Result, + circuit_execution: Result, ) -> TestStatus { let circuit_execution_err = match circuit_execution { // Circuit execution was successful; ie no errors or unsatisfied constraints From 905f830386d938c0a74de041b5233a72698ada79 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Tue, 26 Mar 2024 20:37:25 +0000 Subject: [PATCH 117/139] test ultra_honk_program and use last witness stack item for existing workflow --- barretenberg/acir_tests/Dockerfile.bb | 2 + .../prove_and_verify_ultra_honk_program.sh | 6 ++ barretenberg/cpp/src/barretenberg/bb/main.cpp | 75 ++++++++++++++++--- .../dsl/acir_format/acir_format.hpp | 2 + .../acir_format/acir_to_constraint_buf.hpp | 64 ++++++++++++++-- 5 files changed, 131 insertions(+), 18 deletions(-) create mode 100755 barretenberg/acir_tests/flows/prove_and_verify_ultra_honk_program.sh diff --git a/barretenberg/acir_tests/Dockerfile.bb b/barretenberg/acir_tests/Dockerfile.bb index 60144b8a707e..cda8d054ca38 100644 --- a/barretenberg/acir_tests/Dockerfile.bb +++ b/barretenberg/acir_tests/Dockerfile.bb @@ -14,6 +14,8 @@ RUN FLOW=prove_then_verify ./run_acir_tests.sh RUN FLOW=prove_and_verify_ultra_honk ./run_acir_tests.sh # Construct and verify a Goblin UltraHonk (GUH) proof for a single arbitrary program RUN FLOW=prove_and_verify_goblin_ultra_honk ./run_acir_tests.sh 6_array +# Construct and verify a UltraHonk proof for all ACIR programs using the new witness stack workflow +RUN FLOW=prove_and_verify_ultra_honk_program ./run_acir_tests.sh # This is a "full" Goblin flow. It constructs and verifies four proofs: GoblinUltraHonk, ECCVM, Translator, and merge RUN FLOW=prove_and_verify_goblin ./run_acir_tests.sh 6_array # Run 1_mul through native bb build, all_cmds flow, to test all cli args. diff --git a/barretenberg/acir_tests/flows/prove_and_verify_ultra_honk_program.sh b/barretenberg/acir_tests/flows/prove_and_verify_ultra_honk_program.sh new file mode 100755 index 000000000000..53c9d08e1a60 --- /dev/null +++ b/barretenberg/acir_tests/flows/prove_and_verify_ultra_honk_program.sh @@ -0,0 +1,6 @@ +#!/bin/sh +set -eu + +VFLAG=${VERBOSE:+-v} + +$BIN prove_and_verify_ultra_honk_program $VFLAG -c $CRS_PATH -b ./target/acir.gz \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/bb/main.cpp b/barretenberg/cpp/src/barretenberg/bb/main.cpp index 34e4ef0fe4ca..9b3b88d52631 100644 --- a/barretenberg/cpp/src/barretenberg/bb/main.cpp +++ b/barretenberg/cpp/src/barretenberg/bb/main.cpp @@ -1,5 +1,6 @@ #include "barretenberg/bb/file_io.hpp" #include "barretenberg/common/serialize.hpp" +#include "barretenberg/dsl/acir_format/acir_format.hpp" #include "barretenberg/dsl/types.hpp" #include "barretenberg/honk/proof_system/types/proof.hpp" #include "barretenberg/plonk/proof_system/proving_key/serialize.hpp" @@ -83,6 +84,18 @@ acir_format::AcirFormat get_constraint_system(std::string const& bytecode_path) return acir_format::circuit_buf_to_acir_format(bytecode); } +acir_format::WitnessVectorStack get_witness_stack(std::string const& witness_path) +{ + auto witness_data = get_bytecode(witness_path); + return acir_format::witness_buf_to_witness_stack(witness_data); +} + +std::vector get_constraint_systems(std::string const& bytecode_path) +{ + auto bytecode = get_bytecode(bytecode_path); + return acir_format::program_buf_to_acir_format(bytecode); +} + /** * @brief Proves and Verifies an ACIR circuit * @@ -127,24 +140,14 @@ bool proveAndVerify(const std::string& bytecodePath, const std::string& witnessP return verified; } -/** - * @brief Constructs and verifies a Honk proof for an acir-generated circuit - * - * @tparam Flavor - * @param bytecodePath Path to serialized acir circuit data - * @param witnessPath Path to serialized acir witness data - */ -template bool proveAndVerifyHonk(const std::string& bytecodePath, const std::string& witnessPath) +template +bool proveAndVerifyHonkAcirFormat(acir_format::AcirFormat constraint_system, acir_format::WitnessVector witness) { using Builder = Flavor::CircuitBuilder; using Prover = UltraProver_; using Verifier = UltraVerifier_; using VerificationKey = Flavor::VerificationKey; - // Populate the acir constraint system and witness from gzipped data - auto constraint_system = get_constraint_system(bytecodePath); - auto witness = get_witness(witnessPath); - // Construct a bberg circuit from the acir representation auto builder = acir_format::create_circuit(constraint_system, 0, witness); @@ -165,6 +168,50 @@ template bool proveAndVerifyHonk(const std::string& bytec return verifier.verify_proof(proof); } +/** + * @brief Constructs and verifies a Honk proof for an acir-generated circuit + * + * @tparam Flavor + * @param bytecodePath Path to serialized acir circuit data + * @param witnessPath Path to serialized acir witness data + */ +template bool proveAndVerifyHonk(const std::string& bytecodePath, const std::string& witnessPath) +{ + // Populate the acir constraint system and witness from gzipped data + auto constraint_system = get_constraint_system(bytecodePath); + auto witness = get_witness(witnessPath); + + return proveAndVerifyHonkAcirFormat(constraint_system, witness); +} + +/** + * @brief Constructs and verifies multiple Honk proofs for an ACIR-generated program. + * + * @tparam Flavor + * @param bytecodePath Path to serialized acir program data. An ACIR program contains a list of circuits. + * @param witnessPath Path to serialized acir witness stack data. This dictates the execution trace the backend should + * follow. + */ +template +bool proveAndVerifyHonkProgram(const std::string& bytecodePath, const std::string& witnessPath) +{ + auto constraint_systems = get_constraint_systems(bytecodePath); + auto witness_stack = get_witness_stack(witnessPath); + + while (!witness_stack.empty()) { + auto witness_stack_item = witness_stack.back(); + // auto witness_stack_item = witness_stack.pop_back(); + auto witness = witness_stack_item.second; + auto constraint_system = constraint_systems[witness_stack_item.first]; + + if (!proveAndVerifyHonkAcirFormat(constraint_system, witness)) { + return false; + } + witness_stack.pop_back(); + } + return true; +} + /** * @brief Proves and Verifies an ACIR circuit * @@ -571,11 +618,15 @@ int main(int argc, char* argv[]) return proveAndVerify(bytecode_path, witness_path) ? 0 : 1; } if (command == "prove_and_verify_ultra_honk") { + // return proveAndVerifyHonkProgram(bytecode_path, witness_path) ? 0 : 1; return proveAndVerifyHonk(bytecode_path, witness_path) ? 0 : 1; } if (command == "prove_and_verify_goblin_ultra_honk") { return proveAndVerifyHonk(bytecode_path, witness_path) ? 0 : 1; } + if (command == "prove_and_verify_ultra_honk_program") { + return proveAndVerifyHonkProgram(bytecode_path, witness_path) ? 0 : 1; + } if (command == "prove_and_verify_goblin") { return proveAndVerifyGoblin(bytecode_path, witness_path) ? 0 : 1; } 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 9a03f96d37a9..c5b64473d80c 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.hpp @@ -17,6 +17,7 @@ #include "recursion_constraint.hpp" #include "schnorr_verify.hpp" #include "sha256_constraint.hpp" +#include namespace acir_format { @@ -93,6 +94,7 @@ struct AcirFormat { }; using WitnessVector = std::vector>; +using WitnessVectorStack = std::vector>; template Builder create_circuit(const AcirFormat& constraint_system, size_t size_hint = 0, WitnessVector const& witness = {}); 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 ddad2310a490..3ea807dc0edd 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 @@ -18,6 +18,7 @@ #include "barretenberg/plonk_honk_shared/arithmetization/gate_data.hpp" #include "serde/index.hpp" #include +#include namespace acir_format { @@ -363,12 +364,8 @@ void handle_memory_op(Program::Opcode::MemoryOp const& mem_op, BlockConstraint& block.trace.push_back(acir_mem_op); } -AcirFormat circuit_buf_to_acir_format(std::vector const& buf) +AcirFormat circuit_serde_to_acir_format(Program::Circuit const& circuit) { - // TODO(maxim): Handle the new `Program` structure once ACVM supports a function call stack. - // For now we expect a single ACIR function - auto circuit = Program::Program::bincodeDeserialize(buf).functions[0]; - AcirFormat af; // `varnum` is the true number of variables, thus we add one to the index which starts at zero af.varnum = circuit.current_witness_index + 1; @@ -406,6 +403,15 @@ AcirFormat circuit_buf_to_acir_format(std::vector const& buf) return af; } +AcirFormat circuit_buf_to_acir_format(std::vector const& buf) +{ + // TODO(maxim): Handle the new `Program` structure once ACVM supports a function call stack. + // For now we expect a single ACIR function + auto circuit = Program::Program::bincodeDeserialize(buf).functions[0]; + + return circuit_serde_to_acir_format(circuit); +} + /** * @brief Converts from the ACIR-native `WitnessMap` format to Barretenberg's internal `WitnessVector` format. * @@ -419,7 +425,8 @@ WitnessVector witness_buf_to_witness_data(std::vector const& buf) // TODO(maxim): Handle the new `WitnessStack` structure once ACVM supports a function call stack // A `StackItem` contains an index to an ACIR circuit and its respective ACIR-native `WitnessMap`. // For now we expect the `WitnessStack` to contain a single witness. - auto w = WitnessStack::WitnessStack::bincodeDeserialize(buf).stack[0].witness; + auto witness_stack = WitnessStack::WitnessStack::bincodeDeserialize(buf); + auto w = witness_stack.stack[witness_stack.stack.size() - 1].witness; WitnessVector wv; size_t index = 0; @@ -437,4 +444,49 @@ WitnessVector witness_buf_to_witness_data(std::vector const& buf) return wv; } +std::vector program_buf_to_acir_format(std::vector const& buf) +{ + auto program = Program::Program::bincodeDeserialize(buf); + + std::vector constraint_systems; + constraint_systems.reserve(program.functions.size()); + for (auto const& function : program.functions) { + constraint_systems.emplace_back(circuit_serde_to_acir_format(function)); + } + + return constraint_systems; +} + +std::pair stack_item_buf_to_stack_item_data(WitnessStack::StackItem const& stack_item) +{ + auto w = stack_item.witness; + + WitnessVector wv; + size_t index = 0; + for (auto& e : w.value) { + // ACIR uses a sparse format for WitnessMap where unused witness indices may be left unassigned. + // To ensure that witnesses sit at the correct indices in the `WitnessVector`, we fill any indices + // which do not exist within the `WitnessMap` with the dummy value of zero. + while (index < e.first.value) { + wv.push_back(bb::fr(0)); + index++; + } + wv.push_back(bb::fr(uint256_t(e.second))); + index++; + } + return std::make_pair(stack_item.index, wv); +} + +WitnessVectorStack witness_buf_to_witness_stack(std::vector const& buf) +{ + auto witness_stack = WitnessStack::WitnessStack::bincodeDeserialize(buf); + WitnessVectorStack witness_vector_stack; + witness_vector_stack.reserve(witness_stack.stack.size()); + for (auto const& stack_item : witness_stack.stack) { + auto serialized_stack_item = stack_item_buf_to_stack_item_data(stack_item); + witness_vector_stack.emplace_back(serialized_stack_item); + } + return witness_vector_stack; +} + } // namespace acir_format From 4cc59d0ceb5d687c31fa3fb5e072525f9893a0f7 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Tue, 26 Mar 2024 20:38:59 +0000 Subject: [PATCH 118/139] delete old comment --- barretenberg/cpp/src/barretenberg/bb/main.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/barretenberg/cpp/src/barretenberg/bb/main.cpp b/barretenberg/cpp/src/barretenberg/bb/main.cpp index 9b3b88d52631..ea98fc7fb598 100644 --- a/barretenberg/cpp/src/barretenberg/bb/main.cpp +++ b/barretenberg/cpp/src/barretenberg/bb/main.cpp @@ -618,7 +618,6 @@ int main(int argc, char* argv[]) return proveAndVerify(bytecode_path, witness_path) ? 0 : 1; } if (command == "prove_and_verify_ultra_honk") { - // return proveAndVerifyHonkProgram(bytecode_path, witness_path) ? 0 : 1; return proveAndVerifyHonk(bytecode_path, witness_path) ? 0 : 1; } if (command == "prove_and_verify_goblin_ultra_honk") { From f04e04abd08a827bd9d86ad20c229e9b2ad12a3f Mon Sep 17 00:00:00 2001 From: vezenovm Date: Tue, 26 Mar 2024 20:52:11 +0000 Subject: [PATCH 119/139] some comments cleanup --- noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs b/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs index 5a288d3ca3c2..79bf8fed6d96 100644 --- a/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs +++ b/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs @@ -266,16 +266,16 @@ impl<'a, B: BlackBoxFunctionSolver> ACVM<'a, B> { self.status(ACVMStatus::RequiresAcirCall(acir_call)) } - /// Resolves a foreign call's [result][acir::brillig_vm::ForeignCallResult] using a result calculated outside of the ACVM. + /// Resolves am ACIR call's result (simply a Vec) using a result calculated by a separate ACVM instance. /// - /// The ACVM can then be restarted to solve the remaining Brillig VM process as well as the remaining ACIR opcodes. + /// The current ACVM instance can then be restarted to solve the remaining ACIR opcodes. pub fn resolve_pending_acir_call(&mut self, call_result: Vec) { if !matches!(self.status, ACVMStatus::RequiresAcirCall(_)) { panic!("ACVM is not expecting an ACIR call response as no call was made"); } if self.acir_call_counter < self.acir_call_results.len() { - panic!("No unresolved foreign calls"); + panic!("No unresolved ACIR calls"); } self.acir_call_results.push(call_result); From 29bd522ab3b394aa130de851cb0224dc265d8a89 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Tue, 26 Mar 2024 23:42:33 +0000 Subject: [PATCH 120/139] cleanup errors in acvm and reuse methods in acir_to_constraint_buf --- barretenberg/cpp/src/barretenberg/bb/main.cpp | 1 - .../acir_format/acir_to_constraint_buf.hpp | 56 +++++++++---------- .../acir/src/native_types/witness_map.rs | 3 - noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs | 26 +++++++-- noir/noir-repo/tooling/nargo/src/errors.rs | 4 +- 5 files changed, 49 insertions(+), 41 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/bb/main.cpp b/barretenberg/cpp/src/barretenberg/bb/main.cpp index ea98fc7fb598..bab9d9dfae1a 100644 --- a/barretenberg/cpp/src/barretenberg/bb/main.cpp +++ b/barretenberg/cpp/src/barretenberg/bb/main.cpp @@ -200,7 +200,6 @@ bool proveAndVerifyHonkProgram(const std::string& bytecodePath, const std::strin while (!witness_stack.empty()) { auto witness_stack_item = witness_stack.back(); - // auto witness_stack_item = witness_stack.pop_back(); auto witness = witness_stack_item.second; auto constraint_system = constraint_systems[witness_stack_item.first]; 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 3ea807dc0edd..0f325e158156 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 @@ -14,6 +14,7 @@ #include "barretenberg/dsl/acir_format/range_constraint.hpp" #include "barretenberg/dsl/acir_format/recursion_constraint.hpp" #include "barretenberg/dsl/acir_format/schnorr_verify.hpp" +#include "barretenberg/dsl/acir_format/serde/witness_stack.hpp" #include "barretenberg/dsl/acir_format/sha256_constraint.hpp" #include "barretenberg/plonk_honk_shared/arithmetization/gate_data.hpp" #include "serde/index.hpp" @@ -415,22 +416,16 @@ AcirFormat circuit_buf_to_acir_format(std::vector const& buf) /** * @brief Converts from the ACIR-native `WitnessMap` format to Barretenberg's internal `WitnessVector` format. * - * @param buf Serialized representation of a `WitnessMap`. + * @param witness_map ACIR-native `WitnessMap` deserialized from a buffer * @return A `WitnessVector` equivalent to the passed `WitnessMap`. * @note This transformation results in all unassigned witnesses within the `WitnessMap` being assigned the value 0. * Converting the `WitnessVector` back to a `WitnessMap` is unlikely to return the exact same `WitnessMap`. */ -WitnessVector witness_buf_to_witness_data(std::vector const& buf) +WitnessVector witness_map_to_witness_vector(WitnessStack::WitnessMap const& witness_map) { - // TODO(maxim): Handle the new `WitnessStack` structure once ACVM supports a function call stack - // A `StackItem` contains an index to an ACIR circuit and its respective ACIR-native `WitnessMap`. - // For now we expect the `WitnessStack` to contain a single witness. - auto witness_stack = WitnessStack::WitnessStack::bincodeDeserialize(buf); - auto w = witness_stack.stack[witness_stack.stack.size() - 1].witness; - WitnessVector wv; size_t index = 0; - for (auto& e : w.value) { + for (auto& e : witness_map.value) { // ACIR uses a sparse format for WitnessMap where unused witness indices may be left unassigned. // To ensure that witnesses sit at the correct indices in the `WitnessVector`, we fill any indices // which do not exist within the `WitnessMap` with the dummy value of zero. @@ -444,6 +439,25 @@ WitnessVector witness_buf_to_witness_data(std::vector const& buf) return wv; } +/** + * @brief Converts from the ACIR-native `WitnessMap` format to Barretenberg's internal `WitnessVector` format. + * + * @param buf Serialized representation of a `WitnessMap`. + * @return A `WitnessVector` equivalent to the passed `WitnessMap`. + * @note This transformation results in all unassigned witnesses within the `WitnessMap` being assigned the value 0. + * Converting the `WitnessVector` back to a `WitnessMap` is unlikely to return the exact same `WitnessMap`. + */ +WitnessVector witness_buf_to_witness_data(std::vector const& buf) +{ + // TODO(maxim): Handle the new `WitnessStack` structure once ACVM supports a function call stack + // A `StackItem` contains an index to an ACIR circuit and its respective ACIR-native `WitnessMap`. + // For now we expect the `WitnessStack` to contain a single witness. + auto witness_stack = WitnessStack::WitnessStack::bincodeDeserialize(buf); + auto w = witness_stack.stack[witness_stack.stack.size() - 1].witness; + + return witness_map_to_witness_vector(w); +} + std::vector program_buf_to_acir_format(std::vector const& buf) { auto program = Program::Program::bincodeDeserialize(buf); @@ -457,34 +471,14 @@ std::vector program_buf_to_acir_format(std::vector const& b return constraint_systems; } -std::pair stack_item_buf_to_stack_item_data(WitnessStack::StackItem const& stack_item) -{ - auto w = stack_item.witness; - - WitnessVector wv; - size_t index = 0; - for (auto& e : w.value) { - // ACIR uses a sparse format for WitnessMap where unused witness indices may be left unassigned. - // To ensure that witnesses sit at the correct indices in the `WitnessVector`, we fill any indices - // which do not exist within the `WitnessMap` with the dummy value of zero. - while (index < e.first.value) { - wv.push_back(bb::fr(0)); - index++; - } - wv.push_back(bb::fr(uint256_t(e.second))); - index++; - } - return std::make_pair(stack_item.index, wv); -} - WitnessVectorStack witness_buf_to_witness_stack(std::vector const& buf) { auto witness_stack = WitnessStack::WitnessStack::bincodeDeserialize(buf); WitnessVectorStack witness_vector_stack; witness_vector_stack.reserve(witness_stack.stack.size()); for (auto const& stack_item : witness_stack.stack) { - auto serialized_stack_item = stack_item_buf_to_stack_item_data(stack_item); - witness_vector_stack.emplace_back(serialized_stack_item); + witness_vector_stack.emplace_back( + std::make_pair(stack_item.index, witness_map_to_witness_vector(stack_item.witness))); } return witness_vector_stack; } diff --git a/noir/noir-repo/acvm-repo/acir/src/native_types/witness_map.rs b/noir/noir-repo/acvm-repo/acir/src/native_types/witness_map.rs index 227c117f6b01..00245d5842ca 100644 --- a/noir/noir-repo/acvm-repo/acir/src/native_types/witness_map.rs +++ b/noir/noir-repo/acvm-repo/acir/src/native_types/witness_map.rs @@ -43,9 +43,6 @@ impl WitnessMap { pub fn insert(&mut self, key: Witness, value: FieldElement) -> Option { self.0.insert(key, value) } - pub fn values(&self) -> Vec { - self.0.values().copied().collect() - } } impl Index<&Witness> for WitnessMap { diff --git a/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs b/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs index 79bf8fed6d96..b9404dd35ee1 100644 --- a/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs +++ b/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs @@ -124,6 +124,10 @@ pub enum OpcodeResolutionError { BlackBoxFunctionFailed(BlackBoxFunc, String), #[error("Failed to solve brillig function, reason: {message}")] BrilligFunctionFailed { message: String, call_stack: Vec }, + #[error("Attempted to call `main` with a `Call` opcode")] + AcirMainCallAttempted { opcode_location: ErrorLocation }, + #[error("{results_size:?} result values were provided for {outputs_size:?} call output witnesses, most likely due to bad ACIR codegen")] + AcirCallOutputsMismatch { opcode_location: ErrorLocation, results_size: u32, outputs_size: u32 }, } impl From for OpcodeResolutionError { @@ -266,7 +270,7 @@ impl<'a, B: BlackBoxFunctionSolver> ACVM<'a, B> { self.status(ACVMStatus::RequiresAcirCall(acir_call)) } - /// Resolves am ACIR call's result (simply a Vec) using a result calculated by a separate ACVM instance. + /// Resolves an ACIR call's result (simply a list of fields) using a result calculated by a separate ACVM instance. /// /// The current ACVM instance can then be restarted to solve the remaining ACIR opcodes. pub fn resolve_pending_acir_call(&mut self, call_result: Vec) { @@ -447,8 +451,13 @@ impl<'a, B: BlackBoxFunctionSolver> ACVM<'a, B> { let Opcode::Call { id, inputs, outputs } = &self.opcodes[self.instruction_pointer] else { unreachable!("Not executing a Call opcode"); }; - // TODO: add a resolution opcode error for this assert - assert!(*id != 0, "Attempting to call main, not allowed"); + if *id == 0 { + return Err(OpcodeResolutionError::AcirMainCallAttempted { + opcode_location: ErrorLocation::Resolved(OpcodeLocation::Acir( + self.instruction_pointer(), + )), + }); + } if self.acir_call_counter >= self.acir_call_results.len() { let mut initial_witness = WitnessMap::default(); @@ -460,8 +469,15 @@ impl<'a, B: BlackBoxFunctionSolver> ACVM<'a, B> { } let result_values = &self.acir_call_results[self.acir_call_counter]; - // TODO: add a resolution opcode error for this assert - assert_eq!(outputs.len(), result_values.len(), "{} result values were provided for ACIR {} call output witnesses, most likely due to codegen", result_values.len(), outputs.len()); + if outputs.len() != result_values.len() { + return Err(OpcodeResolutionError::AcirCallOutputsMismatch { + opcode_location: ErrorLocation::Resolved(OpcodeLocation::Acir( + self.instruction_pointer(), + )), + results_size: result_values.len() as u32, + outputs_size: outputs.len() as u32, + }); + } for (output_witness, result_value) in outputs.iter().zip(result_values) { insert_value(output_witness, *result_value, &mut self.witness_map)?; diff --git a/noir/noir-repo/tooling/nargo/src/errors.rs b/noir/noir-repo/tooling/nargo/src/errors.rs index c743768bee2a..ff238d79a461 100644 --- a/noir/noir-repo/tooling/nargo/src/errors.rs +++ b/noir/noir-repo/tooling/nargo/src/errors.rs @@ -64,7 +64,9 @@ impl NargoError { ExecutionError::SolvingError(error) => match error { OpcodeResolutionError::IndexOutOfBounds { .. } | OpcodeResolutionError::OpcodeNotSolvable(_) - | OpcodeResolutionError::UnsatisfiedConstrain { .. } => None, + | OpcodeResolutionError::UnsatisfiedConstrain { .. } + | OpcodeResolutionError::AcirMainCallAttempted { .. } + | OpcodeResolutionError::AcirCallOutputsMismatch { .. } => None, OpcodeResolutionError::BrilligFunctionFailed { message, .. } => Some(message), OpcodeResolutionError::BlackBoxFunctionFailed(_, reason) => Some(reason), }, From e8d3a9c052204c79c434e5804fbc2a99e7e98f65 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Wed, 27 Mar 2024 00:02:33 +0000 Subject: [PATCH 121/139] remove import from acir_to_constraint_buf and use real error in nargo execution --- .../acir_format/acir_to_constraint_buf.hpp | 1 - .../tooling/nargo/src/ops/execute.rs | 23 +++++++++++-------- 2 files changed, 14 insertions(+), 10 deletions(-) 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 0f325e158156..bb9692ca1266 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 @@ -14,7 +14,6 @@ #include "barretenberg/dsl/acir_format/range_constraint.hpp" #include "barretenberg/dsl/acir_format/recursion_constraint.hpp" #include "barretenberg/dsl/acir_format/schnorr_verify.hpp" -#include "barretenberg/dsl/acir_format/serde/witness_stack.hpp" #include "barretenberg/dsl/acir_format/sha256_constraint.hpp" #include "barretenberg/plonk_honk_shared/arithmetization/gate_data.hpp" #include "serde/index.hpp" diff --git a/noir/noir-repo/tooling/nargo/src/ops/execute.rs b/noir/noir-repo/tooling/nargo/src/ops/execute.rs index 86fb83e9faf9..d271e4b262d5 100644 --- a/noir/noir-repo/tooling/nargo/src/ops/execute.rs +++ b/noir/noir-repo/tooling/nargo/src/ops/execute.rs @@ -1,7 +1,7 @@ use acvm::acir::circuit::Program; use acvm::acir::native_types::WitnessStack; use acvm::brillig_vm::brillig::ForeignCallResult; -use acvm::pwg::{ACVMStatus, ErrorLocation, OpcodeResolutionError, ACVM}; +use acvm::pwg::{ACVMStatus, ErrorLocation, OpcodeNotSolvable, OpcodeResolutionError, ACVM}; use acvm::BlackBoxFunctionSolver; use acvm::{acir::circuit::Circuit, acir::native_types::WitnessMap}; @@ -9,6 +9,7 @@ use crate::errors::ExecutionError; use crate::NargoError; use super::foreign_calls::{ForeignCallExecutor, NargoForeignCallResult}; + struct ProgramExecutor<'a> { functions: &'a [Circuit], // This gets built as we run through the program looking at each function call @@ -106,13 +107,17 @@ impl<'a> ProgramExecutor<'a> { foreign_call_executor, )?; let mut call_resolved_outputs = Vec::new(); - for witness_index in acir_to_call.return_values.indices() { - // TODO: turn this into a real execution error - call_resolved_outputs.push( - *call_solved_witness - .get_index(witness_index) - .expect("ACVM Error: should have return index"), - ); + for return_witness_index in acir_to_call.return_values.indices() { + if let Some(return_value) = + call_solved_witness.get_index(return_witness_index) + { + call_resolved_outputs.push(*return_value); + } else { + return Err(ExecutionError::SolvingError( + OpcodeNotSolvable::MissingAssignment(return_witness_index).into(), + ) + .into()); + } } acvm.resolve_pending_acir_call(call_resolved_outputs); self.witness_stack.push(acir_call.id, call_solved_witness); @@ -137,6 +142,6 @@ pub fn execute_program( let main_witness = executor.execute_circuit(main, initial_witness, blackbox_solver, foreign_call_executor)?; executor.witness_stack.push(0, main_witness); - + dbg!(executor.witness_stack.clone()); Ok(executor.finalize()) } From 0c7113f99cf9c78dab516b5b808e334ee3ba1e3e Mon Sep 17 00:00:00 2001 From: vezenovm Date: Wed, 27 Mar 2024 00:04:29 +0000 Subject: [PATCH 122/139] remove old dbg --- noir/noir-repo/tooling/nargo/src/ops/execute.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noir/noir-repo/tooling/nargo/src/ops/execute.rs b/noir/noir-repo/tooling/nargo/src/ops/execute.rs index d271e4b262d5..4192bbbd81ec 100644 --- a/noir/noir-repo/tooling/nargo/src/ops/execute.rs +++ b/noir/noir-repo/tooling/nargo/src/ops/execute.rs @@ -142,6 +142,6 @@ pub fn execute_program( let main_witness = executor.execute_circuit(main, initial_witness, blackbox_solver, foreign_call_executor)?; executor.witness_stack.push(0, main_witness); - dbg!(executor.witness_stack.clone()); + Ok(executor.finalize()) } From bef3d556ff63b038df88dcd441cbc538093e9aa5 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Wed, 27 Mar 2024 00:06:46 +0000 Subject: [PATCH 123/139] rename acir_call to call_info --- noir/noir-repo/tooling/nargo/src/ops/execute.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/noir/noir-repo/tooling/nargo/src/ops/execute.rs b/noir/noir-repo/tooling/nargo/src/ops/execute.rs index 4192bbbd81ec..1ad751e74a49 100644 --- a/noir/noir-repo/tooling/nargo/src/ops/execute.rs +++ b/noir/noir-repo/tooling/nargo/src/ops/execute.rs @@ -97,9 +97,9 @@ impl<'a> ProgramExecutor<'a> { } } } - ACVMStatus::RequiresAcirCall(acir_call) => { - let acir_to_call = &self.functions[acir_call.id as usize]; - let initial_witness = acir_call.initial_witness; + ACVMStatus::RequiresAcirCall(call_info) => { + let acir_to_call = &self.functions[call_info.id as usize]; + let initial_witness = call_info.initial_witness; let call_solved_witness = self.execute_circuit( acir_to_call, initial_witness, @@ -120,7 +120,7 @@ impl<'a> ProgramExecutor<'a> { } } acvm.resolve_pending_acir_call(call_resolved_outputs); - self.witness_stack.push(acir_call.id, call_solved_witness); + self.witness_stack.push(call_info.id, call_solved_witness); } } } From 60c329401846d45766a514df6b5f961774eaee7a Mon Sep 17 00:00:00 2001 From: Maxim Vezenov Date: Wed, 27 Mar 2024 19:28:40 +0000 Subject: [PATCH 124/139] Update noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs Co-authored-by: Tom French <15848336+TomAFrench@users.noreply.github.com> --- .../noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs index 313d093f957f..bcd62e3b0627 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs @@ -1774,7 +1774,7 @@ impl AcirContext { // Convert `Witness` values which are now constrained to be the output of the // ACIR function call into `AcirVar`s. // Similar to black box functions, we do not apply range information on the output of the function. - // See issue #1439 + // See issue https://github.com/noir-lang/noir/issues/1439 let results = vecmap(&outputs, |witness_index| self.add_data(AcirVarData::Witness(*witness_index))); From ff50bae268489679de81b9bc54cd6d639859209c Mon Sep 17 00:00:00 2001 From: vezenovm Date: Wed, 27 Mar 2024 20:11:11 +0000 Subject: [PATCH 125/139] include foldable in type check --- .../compiler/noirc_evaluator/src/ssa.rs | 1 + .../noirc_evaluator/src/ssa/acir_gen/mod.rs | 13 +++---- .../noirc_evaluator/src/ssa/opt/inlining.rs | 5 +-- .../noirc_evaluator/src/ssa/opt/rc.rs | 20 ++++++++--- .../src/hir/resolution/resolver.rs | 5 +-- .../src/hir/type_check/errors.rs | 2 +- .../noirc_frontend/src/hir/type_check/mod.rs | 36 +++++++++++++++---- .../noirc_frontend/src/lexer/token.rs | 4 +++ 8 files changed, 62 insertions(+), 24 deletions(-) diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs index 57b7343c5c3a..f05a0932f230 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs @@ -126,6 +126,7 @@ pub fn create_program( debug_infos.push(debug_info); warning_infos.extend(warnings); if is_main { + // main_input_witness = circuit.re main_input_witnesses = input_witnesses; main_return_witnesses = return_witnesses; } diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs index 9d062cb806ac..92d0aec0c7c2 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs @@ -184,6 +184,7 @@ impl Ssa { last_array_uses: &HashMap, ) -> Result, RuntimeError> { let mut acirs = Vec::new(); + // TODO: can we parallelise this? for function in self.functions.values() { let context = Context::new(); if let Some(generated_acir) = @@ -664,22 +665,22 @@ impl Context { output_values: Vec, dfg: &DataFlowGraph, ) -> Result<(), RuntimeError> { - for result in result_ids.iter().zip(output_values) { - if let AcirValue::Array(_) = &result.1 { - let array_id = dfg.resolve(*result.0); + for (result_id, output) in result_ids.iter().zip(output_values) { + if let AcirValue::Array(_) = &output { + let array_id = dfg.resolve(*result_id); let block_id = self.block_id(&array_id); let array_typ = dfg.type_of_value(array_id); let len = if matches!(array_typ, Type::Array(_, _)) { array_typ.flattened_size() } else { - Self::flattened_value_size(&result.1) + Self::flattened_value_size(&output) }; - self.initialize_array(block_id, len, Some(result.1.clone()))?; + self.initialize_array(block_id, len, Some(output.clone()))?; } // Do nothing for AcirValue::DynamicArray and AcirValue::Var // A dynamic array returned from a function call should already be initialized // and a single variable does not require any extra initialization. - self.ssa_values.insert(*result.0, result.1); + self.ssa_values.insert(*result_id, output); } Ok(()) } diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/inlining.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/inlining.rs index 42dfa97b2def..f7429f2706fc 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/inlining.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/inlining.rs @@ -94,8 +94,9 @@ struct PerFunctionContext<'function> { } /// The entry point functions are each function we should inline into - and each function that -/// should be left in the final program. This is usually just `main` but also includes any -/// brillig functions used. +/// should be left in the final program. +/// This is usually the `main` function, any Acir functions with a [fold inline type][InlineType::Fold], +/// and any brillig functions used. fn get_entry_point_functions(ssa: &Ssa) -> BTreeSet { let functions = ssa.functions.iter(); let mut entry_points = functions diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/rc.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/rc.rs index 4766bc3e8d28..5e6c2dbb25cb 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/rc.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/rc.rs @@ -166,8 +166,12 @@ mod test { use crate::ssa::{ function_builder::FunctionBuilder, ir::{ - basic_block::BasicBlockId, dfg::DataFlowGraph, function::RuntimeType, - instruction::Instruction, map::Id, types::Type, + basic_block::BasicBlockId, + dfg::DataFlowGraph, + function::{InlineType, RuntimeType}, + instruction::Instruction, + map::Id, + types::Type, }, }; @@ -245,7 +249,11 @@ mod test { // return // } let main_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("mutator".into(), main_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new( + "mutator".into(), + main_id, + RuntimeType::Acir(InlineType::default()), + ); let array_type = Type::Array(Rc::new(vec![Type::field()]), 2); let v0 = builder.add_parameter(array_type.clone()); @@ -294,7 +302,11 @@ mod test { // return // } let main_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("mutator2".into(), main_id, RuntimeType::Acir); + let mut builder = FunctionBuilder::new( + "mutator2".into(), + main_id, + RuntimeType::Acir(InlineType::default()), + ); let array_type = Type::Array(Rc::new(vec![Type::field()]), 2); let reference_type = Type::Reference(Rc::new(array_type.clone())); diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/resolver.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/resolver.rs index 0bf96e6a850f..1fcf0c62ace4 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/resolver.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/resolver.rs @@ -991,10 +991,7 @@ impl<'a> Resolver<'a> { .map(|(name, typevar, _span)| (name.clone(), typevar.clone())) .collect(); - let should_fold = attributes - .function - .as_ref() - .map_or(false, |func_attribute| func_attribute.is_foldable()); + let should_fold = attributes.is_foldable(); FuncMeta { name: name_ident, diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/errors.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/errors.rs index 6beb6929ce14..c881efcfc458 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/errors.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/errors.rs @@ -315,7 +315,7 @@ impl From for Diagnostic { } TypeCheckError::InvalidTypeForEntryPoint { span } => Diagnostic::simple_error( "Only sized types may be used in the entry point to a program".to_string(), - "Slices, references, or any type containing them may not be used in main or a contract function".to_string(), span), + "Slices, references, or any type containing them may not be used in main, contract functions, or foldable functions".to_string(), span), TypeCheckError::MismatchTraitImplNumParameters { expected_num_parameters, actual_num_parameters, diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/mod.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/mod.rs index 39ebb9f02453..be12e5bdcea8 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/mod.rs @@ -160,7 +160,7 @@ fn check_if_type_is_valid_for_program_input( errors: &mut Vec, ) { let meta = type_checker.interner.function_meta(&func_id); - if meta.is_entry_point && !param.1.is_valid_for_program_input() { + if (meta.is_entry_point || meta.should_fold) && !param.1.is_valid_for_program_input() { let span = param.0.span(); errors.push(TypeCheckError::InvalidTypeForEntryPoint { span }); } @@ -566,6 +566,7 @@ mod test { src, expected_num_errors, vec![String::from("main"), String::from("foo")], + 0, ); } #[test] @@ -591,6 +592,19 @@ mod test { type_check_src_code(src, vec![String::from("main")]); } + + #[test] + fn fold_entry_point() { + let src = r#" + #[fold] + fn fold(x: [Field]) -> Field { + x[0] + } + "#; + + type_check_src_code_errors_expected(src, 0, vec![String::from("fold")], 1); + } + // This is the same Stub that is in the resolver, maybe we can pull this out into a test module and re-use? struct TestPathResolver(HashMap); @@ -624,15 +638,16 @@ mod test { } fn type_check_src_code(src: &str, func_namespace: Vec) { - type_check_src_code_errors_expected(src, 0, func_namespace); + type_check_src_code_errors_expected(src, 0, func_namespace, 0); } // This function assumes that there is only one function and this is the // func id that is returned fn type_check_src_code_errors_expected( src: &str, - expected_number_errors: usize, + expected_num_parser_errs: usize, func_namespace: Vec, + expected_num_type_check_errs: usize, ) { let (program, errors) = parse_program(src); let mut interner = NodeInterner::default(); @@ -640,9 +655,9 @@ mod test { assert_eq!( errors.len(), - expected_number_errors, - "expected {} errors, but got {}, errors: {:?}", - expected_number_errors, + expected_num_parser_errs, + "expected {} parser errors, but got {}, errors: {:?}", + expected_num_parser_errs, errors.len(), errors ); @@ -688,6 +703,13 @@ mod test { // Type check section let errors = super::type_check_func(&mut interner, func_ids.first().cloned().unwrap()); - assert_eq!(errors, vec![]); + assert_eq!( + errors.len(), + expected_num_type_check_errs, + "expected {} type check errors, but got {}, errors: {:?}", + expected_num_type_check_errs, + errors.len(), + errors + ); } } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/lexer/token.rs b/noir/noir-repo/compiler/noirc_frontend/src/lexer/token.rs index 7c9580fd908a..f8378cdd84b8 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/lexer/token.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/lexer/token.rs @@ -427,6 +427,10 @@ impl Attributes { } None } + + pub fn is_foldable(&self) -> bool { + self.function.as_ref().map_or(false, |func_attribute| func_attribute.is_foldable()) + } } /// An Attribute can be either a Primary Attribute or a Secondary Attribute From a75a8f651ac6d803728ad45aea5f60d993614e53 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Wed, 27 Mar 2024 20:12:23 +0000 Subject: [PATCH 126/139] use mut ref in test --- .../compiler/noirc_frontend/src/hir/type_check/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/mod.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/mod.rs index be12e5bdcea8..748b1845e2b3 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/mod.rs @@ -597,8 +597,8 @@ mod test { fn fold_entry_point() { let src = r#" #[fold] - fn fold(x: [Field]) -> Field { - x[0] + fn fold(x: &mut Field) -> Field { + *x } "#; From c1d625424cec23e57c04436a391909a92e47f0ca Mon Sep 17 00:00:00 2001 From: vezenovm Date: Wed, 27 Mar 2024 20:53:36 +0000 Subject: [PATCH 127/139] move bb solver and foreign call executor to ProgramExecutor --- noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs | 2 +- .../tooling/nargo/src/ops/execute.rs | 43 +++++++++++-------- 2 files changed, 26 insertions(+), 19 deletions(-) diff --git a/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs b/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs index b9404dd35ee1..3cedcfc03999 100644 --- a/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs +++ b/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs @@ -264,7 +264,7 @@ impl<'a, B: BlackBoxFunctionSolver> ACVM<'a, B> { self.status(ACVMStatus::InProgress); } - /// Sets the status of the VM to `RequriesAcirCall` + /// Sets the status of the VM to `RequiresAcirCall` /// Indicating that the VM is now waiting for an ACIR call to be resolved fn wait_for_acir_call(&mut self, acir_call: AcirCallWaitInfo) -> ACVMStatus { self.status(ACVMStatus::RequiresAcirCall(acir_call)) diff --git a/noir/noir-repo/tooling/nargo/src/ops/execute.rs b/noir/noir-repo/tooling/nargo/src/ops/execute.rs index 1ad751e74a49..6d328d65119b 100644 --- a/noir/noir-repo/tooling/nargo/src/ops/execute.rs +++ b/noir/noir-repo/tooling/nargo/src/ops/execute.rs @@ -10,15 +10,28 @@ use crate::NargoError; use super::foreign_calls::{ForeignCallExecutor, NargoForeignCallResult}; -struct ProgramExecutor<'a> { +struct ProgramExecutor<'a, B: BlackBoxFunctionSolver, F: ForeignCallExecutor> { functions: &'a [Circuit], // This gets built as we run through the program looking at each function call witness_stack: WitnessStack, + + blackbox_solver: &'a B, + + foreign_call_executor: &'a mut F, } -impl<'a> ProgramExecutor<'a> { - fn new(functions: &'a [Circuit]) -> Self { - ProgramExecutor { functions, witness_stack: WitnessStack::default() } +impl<'a, B: BlackBoxFunctionSolver, F: ForeignCallExecutor> ProgramExecutor<'a, B, F> { + fn new( + functions: &'a [Circuit], + blackbox_solver: &'a B, + foreign_call_executor: &'a mut F, + ) -> Self { + ProgramExecutor { + functions, + witness_stack: WitnessStack::default(), + blackbox_solver, + foreign_call_executor, + } } fn finalize(self) -> WitnessStack { @@ -26,14 +39,12 @@ impl<'a> ProgramExecutor<'a> { } #[tracing::instrument(level = "trace", skip_all)] - fn execute_circuit( + fn execute_circuit( &mut self, circuit: &Circuit, initial_witness: WitnessMap, - blackbox_solver: &B, - foreign_call_executor: &mut F, ) -> Result { - let mut acvm = ACVM::new(blackbox_solver, &circuit.opcodes, initial_witness); + let mut acvm = ACVM::new(self.blackbox_solver, &circuit.opcodes, initial_witness); // This message should be resolved by a nargo foreign call only when we have an unsatisfied assertion. let mut assert_message: Option = None; @@ -82,7 +93,7 @@ impl<'a> ProgramExecutor<'a> { })); } ACVMStatus::RequiresForeignCall(foreign_call) => { - let foreign_call_result = foreign_call_executor.execute(&foreign_call)?; + let foreign_call_result = self.foreign_call_executor.execute(&foreign_call)?; match foreign_call_result { NargoForeignCallResult::BrilligOutput(foreign_call_result) => { acvm.resolve_pending_foreign_call(foreign_call_result); @@ -100,12 +111,8 @@ impl<'a> ProgramExecutor<'a> { ACVMStatus::RequiresAcirCall(call_info) => { let acir_to_call = &self.functions[call_info.id as usize]; let initial_witness = call_info.initial_witness; - let call_solved_witness = self.execute_circuit( - acir_to_call, - initial_witness, - blackbox_solver, - foreign_call_executor, - )?; + let call_solved_witness = + self.execute_circuit(acir_to_call, initial_witness)?; let mut call_resolved_outputs = Vec::new(); for return_witness_index in acir_to_call.return_values.indices() { if let Some(return_value) = @@ -138,9 +145,9 @@ pub fn execute_program( ) -> Result { let main = &program.functions[0]; - let mut executor = ProgramExecutor::new(&program.functions); - let main_witness = - executor.execute_circuit(main, initial_witness, blackbox_solver, foreign_call_executor)?; + let mut executor = + ProgramExecutor::new(&program.functions, blackbox_solver, foreign_call_executor); + let main_witness = executor.execute_circuit(main, initial_witness)?; executor.witness_stack.push(0, main_witness); Ok(executor.finalize()) From 9ebb786a5afc8d3f2941ddbd5bcb121b339b321c Mon Sep 17 00:00:00 2001 From: vezenovm Date: Thu, 28 Mar 2024 16:30:00 +0000 Subject: [PATCH 128/139] remove bit shifts on all funcs --- .../compiler/noirc_evaluator/src/ssa/opt/remove_bit_shifts.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/remove_bit_shifts.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/remove_bit_shifts.rs index a71a42d57571..1eb1e20d41d5 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/remove_bit_shifts.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/remove_bit_shifts.rs @@ -20,7 +20,9 @@ impl Ssa { /// See [`constant_folding`][self] module for more information. #[tracing::instrument(level = "trace", skip(self))] pub(crate) fn remove_bit_shifts(mut self) -> Ssa { - remove_bit_shifts(self.main_mut()); + for function in self.functions.values_mut() { + remove_bit_shifts(function); + } self } } From cfed014a41e26ca056dc9573ba0f6e3621928982 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Thu, 28 Mar 2024 16:32:39 +0000 Subject: [PATCH 129/139] flatten more than just main --- .../compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs index 662e6898c6d7..2683d67f7430 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs @@ -167,7 +167,9 @@ impl Ssa { /// For more information, see the module-level comment at the top of this file. #[tracing::instrument(level = "trace", skip(self))] pub(crate) fn flatten_cfg(mut self) -> Ssa { - flatten_function_cfg(self.main_mut()); + for function in self.functions.values_mut() { + flatten_function_cfg(function); + } self } } From 999ef7ab6dbef64f09998a087b263b4629353e2b Mon Sep 17 00:00:00 2001 From: Maxim Vezenov Date: Thu, 28 Mar 2024 19:47:17 +0000 Subject: [PATCH 130/139] Update noir/noir-repo/tooling/debugger/src/context.rs Co-authored-by: jfecher --- noir/noir-repo/tooling/debugger/src/context.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noir/noir-repo/tooling/debugger/src/context.rs b/noir/noir-repo/tooling/debugger/src/context.rs index 2ae7c9c7c202..ba12a20460da 100644 --- a/noir/noir-repo/tooling/debugger/src/context.rs +++ b/noir/noir-repo/tooling/debugger/src/context.rs @@ -382,7 +382,7 @@ impl<'a, B: BlackBoxFunctionSolver> DebugContext<'a, B> { unreachable!("Unexpected pending foreign call resolution"); } ACVMStatus::RequiresAcirCall(_) => { - todo!("Multiple ACIR calls is not supported"); + todo!("Multiple ACIR calls are not supported"); } } } From 5e084e5b9cb911a602aea155c79c9c1f331af994 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Thu, 28 Mar 2024 20:37:08 +0000 Subject: [PATCH 131/139] add links in TODOs --- .../dsl/acir_format/acir_to_constraint_buf.hpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) 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 bb9692ca1266..c3b35c2c88c0 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 @@ -405,8 +405,9 @@ AcirFormat circuit_serde_to_acir_format(Program::Circuit const& circuit) AcirFormat circuit_buf_to_acir_format(std::vector const& buf) { - // TODO(maxim): Handle the new `Program` structure once ACVM supports a function call stack. - // For now we expect a single ACIR function + // TODO(https://github.com/AztecProtocol/barretenberg/issues/927): Move to using just `program_buf_to_acir_format` + // once Honk fully supports all ACIR test flows + // For now the backend still expects to work with a single ACIR function auto circuit = Program::Program::bincodeDeserialize(buf).functions[0]; return circuit_serde_to_acir_format(circuit); @@ -448,9 +449,9 @@ WitnessVector witness_map_to_witness_vector(WitnessStack::WitnessMap const& witn */ WitnessVector witness_buf_to_witness_data(std::vector const& buf) { - // TODO(maxim): Handle the new `WitnessStack` structure once ACVM supports a function call stack - // A `StackItem` contains an index to an ACIR circuit and its respective ACIR-native `WitnessMap`. - // For now we expect the `WitnessStack` to contain a single witness. + // TODO(https://github.com/AztecProtocol/barretenberg/issues/927): Move to using just `witness_buf_to_witness_stack` + // once Honk fully supports all ACIR test flows. + // For now the backend still expects to work with the stop of the `WitnessStack`. auto witness_stack = WitnessStack::WitnessStack::bincodeDeserialize(buf); auto w = witness_stack.stack[witness_stack.stack.size() - 1].witness; From aceb1ca3e58612ed1c8a041dea51d0eac41d3528 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Thu, 28 Mar 2024 21:08:52 +0000 Subject: [PATCH 132/139] update stale comment --- noir/noir-repo/compiler/noirc_driver/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noir/noir-repo/compiler/noirc_driver/src/lib.rs b/noir/noir-repo/compiler/noirc_driver/src/lib.rs index 2cffaa54e38c..e52f702ad7c7 100644 --- a/noir/noir-repo/compiler/noirc_driver/src/lib.rs +++ b/noir/noir-repo/compiler/noirc_driver/src/lib.rs @@ -491,7 +491,7 @@ pub fn compile_no_check( // TODO(https://github.com/noir-lang/noir/issues/4428) program, // TODO(https://github.com/noir-lang/noir/issues/4428) - // Debug info is only relevant for errors at execution time which this PR does not yet support + // Debug info is only relevant for errors at execution time which is not yet supported // The CompileProgram `debug` field is used in multiple places and is better // left to be updated once execution of multiple ACIR functions is enabled debug: debug[0].clone(), From 69ce76cb60c29a4614d1809e436924bac9ffcf14 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Thu, 28 Mar 2024 21:09:50 +0000 Subject: [PATCH 133/139] update stale comment --- noir/noir-repo/compiler/noirc_driver/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noir/noir-repo/compiler/noirc_driver/src/lib.rs b/noir/noir-repo/compiler/noirc_driver/src/lib.rs index 2cffaa54e38c..e52f702ad7c7 100644 --- a/noir/noir-repo/compiler/noirc_driver/src/lib.rs +++ b/noir/noir-repo/compiler/noirc_driver/src/lib.rs @@ -491,7 +491,7 @@ pub fn compile_no_check( // TODO(https://github.com/noir-lang/noir/issues/4428) program, // TODO(https://github.com/noir-lang/noir/issues/4428) - // Debug info is only relevant for errors at execution time which this PR does not yet support + // Debug info is only relevant for errors at execution time which is not yet supported // The CompileProgram `debug` field is used in multiple places and is better // left to be updated once execution of multiple ACIR functions is enabled debug: debug[0].clone(), From 2af705af0ad113d3718b06fa987f7e3936841786 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Thu, 28 Mar 2024 21:11:04 +0000 Subject: [PATCH 134/139] another stale comment --- noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/inlining.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/inlining.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/inlining.rs index f7429f2706fc..9687720a4f5e 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/inlining.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/inlining.rs @@ -95,7 +95,7 @@ struct PerFunctionContext<'function> { /// The entry point functions are each function we should inline into - and each function that /// should be left in the final program. -/// This is usually the `main` function, any Acir functions with a [fold inline type][InlineType::Fold], +/// This is the `main` function, any Acir functions with a [fold inline type][InlineType::Fold], /// and any brillig functions used. fn get_entry_point_functions(ssa: &Ssa) -> BTreeSet { let functions = ssa.functions.iter(); From cce5a786f4a022859e8affc572a0a80bb6c50202 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Thu, 28 Mar 2024 21:34:27 +0000 Subject: [PATCH 135/139] remove runtime arg from FunctionBuilder::new --- .../noirc_evaluator/src/ssa/acir_gen/mod.rs | 9 +++---- .../src/ssa/function_builder/mod.rs | 21 ++++++++------- .../noirc_evaluator/src/ssa/ir/dom.rs | 6 ++--- .../noirc_evaluator/src/ssa/ir/post_order.rs | 3 +-- .../src/ssa/opt/bubble_up_constrains.rs | 3 +-- .../src/ssa/opt/constant_folding.rs | 18 +++++-------- .../src/ssa/opt/defunctionalize.rs | 5 ++-- .../noirc_evaluator/src/ssa/opt/die.rs | 3 +-- .../src/ssa/opt/flatten_cfg.rs | 27 +++++++------------ .../ssa/opt/flatten_cfg/branch_analysis.rs | 6 ++--- .../noirc_evaluator/src/ssa/opt/inlining.rs | 15 +++++------ .../noirc_evaluator/src/ssa/opt/mem2reg.rs | 15 ++++------- .../noirc_evaluator/src/ssa/opt/rc.rs | 15 +++-------- .../src/ssa/opt/simplify_cfg.rs | 6 ++--- .../noirc_evaluator/src/ssa/opt/unrolling.rs | 6 ++--- .../src/ssa/ssa_gen/context.rs | 3 ++- 16 files changed, 60 insertions(+), 101 deletions(-) diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs index 92d0aec0c7c2..96f959612af7 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs @@ -2443,8 +2443,7 @@ mod test { // return v0 // } let foo_id = Id::test_new(0); - let mut builder = - FunctionBuilder::new("main".into(), foo_id, RuntimeType::Acir(InlineType::default())); + let mut builder = FunctionBuilder::new("main".into(), foo_id); let main_v0 = builder.add_parameter(Type::field()); let main_v1 = builder.add_parameter(Type::field()); @@ -2546,8 +2545,7 @@ mod test { // return v0 // } let foo_id = Id::test_new(0); - let mut builder = - FunctionBuilder::new("main".into(), foo_id, RuntimeType::Acir(InlineType::default())); + let mut builder = FunctionBuilder::new("main".into(), foo_id); let main_v0 = builder.add_parameter(Type::field()); let main_v1 = builder.add_parameter(Type::field()); @@ -2623,8 +2621,7 @@ mod test { // return v0 // } let foo_id = Id::test_new(0); - let mut builder = - FunctionBuilder::new("main".into(), foo_id, RuntimeType::Acir(InlineType::default())); + let mut builder = FunctionBuilder::new("main".into(), foo_id); let main_v0 = builder.add_parameter(Type::field()); let main_v1 = builder.add_parameter(Type::field()); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs index b89cf01625fb..e0e60b737ad7 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs @@ -42,13 +42,8 @@ impl FunctionBuilder { /// /// This creates the new function internally so there is no need to call .new_function() /// right after constructing a new FunctionBuilder. - pub(crate) fn new( - function_name: String, - function_id: FunctionId, - runtime: RuntimeType, - ) -> Self { - let mut new_function = Function::new(function_name, function_id); - new_function.set_runtime(runtime); + pub(crate) fn new(function_name: String, function_id: FunctionId) -> Self { + let new_function = Function::new(function_name, function_id); Self { current_block: new_function.entry_block(), @@ -58,6 +53,15 @@ impl FunctionBuilder { } } + /// Set the runtime of the initial function that is created internally after constructing + /// the FunctionBuilder. A function's default runtime type is `RuntimeType::Acir(InlineType::Inline)`. + /// This should only be used immediately following construction of a FunctionBuilder + /// and will panic if there are any already finished functions. + pub(crate) fn set_runtime(&mut self, runtime: RuntimeType) { + assert_eq!(self.finished_functions.len(), 0, "Attempted to set runtime on a FunctionBuilder with finished functions. A FunctionBuilder's runtime should only be set on its initial function"); + self.current_function.set_runtime(runtime); + } + /// Finish the current function and create a new function. /// /// A FunctionBuilder can always only work on one function at a time, so care @@ -511,8 +515,7 @@ mod tests { // let x = 7; // let bits = x.to_le_bits(8); let func_id = Id::test_new(0); - let mut builder = - FunctionBuilder::new("func".into(), func_id, RuntimeType::Acir(InlineType::default())); + let mut builder = FunctionBuilder::new("func".into(), func_id); let one = builder.numeric_constant(FieldElement::one(), Type::bool()); let zero = builder.numeric_constant(FieldElement::zero(), Type::bool()); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/dom.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/dom.rs index 1ce552e6104a..bd1481a74744 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/dom.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/dom.rs @@ -286,8 +286,7 @@ mod tests { // return () // } let func_id = Id::test_new(0); - let mut builder = - FunctionBuilder::new("func".into(), func_id, RuntimeType::Acir(InlineType::default())); + let mut builder = FunctionBuilder::new("func".into(), func_id); let cond = builder.add_parameter(Type::unsigned(1)); let block1_id = builder.insert_block(); @@ -396,8 +395,7 @@ mod tests { // jump block1() // } let func_id = Id::test_new(0); - let mut builder = - FunctionBuilder::new("func".into(), func_id, RuntimeType::Acir(InlineType::default())); + let mut builder = FunctionBuilder::new("func".into(), func_id); let block1_id = builder.insert_block(); let block2_id = builder.insert_block(); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/post_order.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/post_order.rs index 65327be3f589..5d743e953a53 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/post_order.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/post_order.rs @@ -112,8 +112,7 @@ mod tests { // D, F, E, B, A, (C dropped as unreachable) let func_id = Id::test_new(0); - let mut builder = - FunctionBuilder::new("func".into(), func_id, RuntimeType::Acir(InlineType::default())); + let mut builder = FunctionBuilder::new("func".into(), func_id); let block_b_id = builder.insert_block(); let block_c_id = builder.insert_block(); let block_d_id = builder.insert_block(); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/bubble_up_constrains.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/bubble_up_constrains.rs index 8d36a9010c93..6d556e86cb5c 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/bubble_up_constrains.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/bubble_up_constrains.rs @@ -100,8 +100,7 @@ mod test { let main_id = Id::test_new(0); // Compiling main - let mut builder = - FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir(InlineType::default())); + let mut builder = FunctionBuilder::new("main".into(), main_id); let v0 = builder.add_parameter(Type::field()); let one = builder.field_constant(1u128); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/constant_folding.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/constant_folding.rs index b798df16a01b..889483319602 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/constant_folding.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/constant_folding.rs @@ -305,8 +305,7 @@ mod test { let main_id = Id::test_new(0); // Compiling main - let mut builder = - FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir(InlineType::default())); + let mut builder = FunctionBuilder::new("main".into(), main_id); let v0 = builder.add_parameter(Type::field()); let one = builder.field_constant(1u128); @@ -362,8 +361,7 @@ mod test { let main_id = Id::test_new(0); // Compiling main - let mut builder = - FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir(InlineType::default())); + let mut builder = FunctionBuilder::new("main".into(), main_id); let v0 = builder.add_parameter(Type::unsigned(16)); let v1 = builder.add_parameter(Type::unsigned(16)); @@ -417,8 +415,7 @@ mod test { let main_id = Id::test_new(0); // Compiling main - let mut builder = - FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir(InlineType::default())); + let mut builder = FunctionBuilder::new("main".into(), main_id); let v0 = builder.add_parameter(Type::unsigned(16)); let v1 = builder.add_parameter(Type::unsigned(16)); @@ -474,8 +471,7 @@ mod test { let main_id = Id::test_new(0); // Compiling main - let mut builder = - FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir(InlineType::default())); + let mut builder = FunctionBuilder::new("main".into(), main_id); let v0 = builder.add_parameter(Type::field()); let one = builder.field_constant(1u128); let v1 = builder.insert_binary(v0, BinaryOp::Add, one); @@ -522,8 +518,7 @@ mod test { let main_id = Id::test_new(0); // Compiling main - let mut builder = - FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir(InlineType::default())); + let mut builder = FunctionBuilder::new("main".into(), main_id); let v0 = builder.add_parameter(Type::unsigned(16)); let v1 = builder.insert_cast(v0, Type::unsigned(32)); @@ -567,8 +562,7 @@ mod test { let main_id = Id::test_new(0); // Compiling main - let mut builder = - FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir(InlineType::default())); + let mut builder = FunctionBuilder::new("main".into(), main_id); let v0 = builder.add_parameter(Type::bool()); let v1 = builder.add_parameter(Type::bool()); let v2 = builder.add_parameter(Type::bool()); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/defunctionalize.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/defunctionalize.rs index e25d98c9bd0f..ca6527eb0ecc 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/defunctionalize.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/defunctionalize.rs @@ -13,7 +13,7 @@ use crate::ssa::{ function_builder::FunctionBuilder, ir::{ basic_block::BasicBlockId, - function::{Function, FunctionId, InlineType, RuntimeType, Signature}, + function::{Function, FunctionId, Signature}, instruction::{BinaryOp, ConstrainError, Instruction}, types::{NumericType, Type}, value::{Value, ValueId}, @@ -304,8 +304,7 @@ fn create_apply_function( ) -> FunctionId { assert!(!function_ids.is_empty()); ssa.add_fn(|id| { - let mut function_builder = - FunctionBuilder::new("apply".to_string(), id, RuntimeType::Acir(InlineType::default())); + let mut function_builder = FunctionBuilder::new("apply".to_string(), id); let target_id = function_builder.add_parameter(Type::field()); let params_ids = vecmap(signature.params, |typ| function_builder.add_parameter(typ)); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/die.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/die.rs index 7ea435e1233f..df89dcb716d0 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/die.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/die.rs @@ -199,8 +199,7 @@ mod test { let main_id = Id::test_new(0); // Compiling main - let mut builder = - FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir(InlineType::default())); + let mut builder = FunctionBuilder::new("main".into(), main_id); let v0 = builder.add_parameter(Type::field()); let b1 = builder.insert_block(); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs index 2683d67f7430..e731a7952a6b 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs @@ -862,8 +862,7 @@ mod test { // return v1 // } let main_id = Id::test_new(0); - let mut builder = - FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir(InlineType::default())); + let mut builder = FunctionBuilder::new("main".into(), main_id); let b1 = builder.insert_block(); let b2 = builder.insert_block(); @@ -917,8 +916,7 @@ mod test { // return // } let main_id = Id::test_new(0); - let mut builder = - FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir(InlineType::default())); + let mut builder = FunctionBuilder::new("main".into(), main_id); let b1 = builder.insert_block(); let b2 = builder.insert_block(); @@ -967,8 +965,7 @@ mod test { // return // } let main_id = Id::test_new(0); - let mut builder = - FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir(InlineType::default())); + let mut builder = FunctionBuilder::new("main".into(), main_id); let b1 = builder.insert_block(); let b2 = builder.insert_block(); @@ -1029,8 +1026,7 @@ mod test { // return // } let main_id = Id::test_new(0); - let mut builder = - FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir(InlineType::default())); + let mut builder = FunctionBuilder::new("main".into(), main_id); let b1 = builder.insert_block(); let b2 = builder.insert_block(); @@ -1120,8 +1116,7 @@ mod test { // ↘ ↙ // b9 let main_id = Id::test_new(0); - let mut builder = - FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir(InlineType::default())); + let mut builder = FunctionBuilder::new("main".into(), main_id); let b1 = builder.insert_block(); let b2 = builder.insert_block(); @@ -1278,8 +1273,7 @@ mod test { // before the first store to allocate, which loaded an uninitialized value. // In this test we assert the ordering is strictly Allocate then Store then Load. let main_id = Id::test_new(0); - let mut builder = - FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir(InlineType::default())); + let mut builder = FunctionBuilder::new("main".into(), main_id); let b1 = builder.insert_block(); let b2 = builder.insert_block(); @@ -1378,8 +1372,7 @@ mod test { // return // } let main_id = Id::test_new(1); - let mut builder = - FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir(InlineType::default())); + let mut builder = FunctionBuilder::new("main".into(), main_id); builder.insert_block(); // entry @@ -1432,8 +1425,7 @@ mod test { // jmp b3() // } let main_id = Id::test_new(1); - let mut builder = - FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir(InlineType::default())); + let mut builder = FunctionBuilder::new("main".into(), main_id); builder.insert_block(); // b0 let b1 = builder.insert_block(); @@ -1543,8 +1535,7 @@ mod test { // jmp b5() // } let main_id = Id::test_new(0); - let mut builder = - FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir(InlineType::default())); + let mut builder = FunctionBuilder::new("main".into(), main_id); let b1 = builder.insert_block(); let b2 = builder.insert_block(); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg/branch_analysis.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg/branch_analysis.rs index 4db13fdc0ef5..adb6d2871e54 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg/branch_analysis.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg/branch_analysis.rs @@ -139,8 +139,7 @@ mod test { // ↘ ↙ // b9 let main_id = Id::test_new(0); - let mut builder = - FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir(InlineType::default())); + let mut builder = FunctionBuilder::new("main".into(), main_id); let b1 = builder.insert_block(); let b2 = builder.insert_block(); @@ -201,8 +200,7 @@ mod test { // ↘ ↙ // b15 let main_id = Id::test_new(0); - let mut builder = - FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir(InlineType::default())); + let mut builder = FunctionBuilder::new("main".into(), main_id); let b1 = builder.insert_block(); let b2 = builder.insert_block(); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/inlining.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/inlining.rs index 9687720a4f5e..811b15779aee 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/inlining.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/inlining.rs @@ -122,7 +122,8 @@ impl InlineContext { /// that could not be inlined calling it. fn new(ssa: &Ssa, entry_point: FunctionId) -> InlineContext { let source = &ssa.functions[&entry_point]; - let builder = FunctionBuilder::new(source.name().to_owned(), entry_point, source.runtime()); + let mut builder = FunctionBuilder::new(source.name().to_owned(), entry_point); + builder.set_runtime(source.runtime()); Self { builder, recursion_level: 0, entry_point, call_stack: CallStack::new() } } @@ -547,8 +548,7 @@ mod test { // return 72 // } let foo_id = Id::test_new(0); - let mut builder = - FunctionBuilder::new("foo".into(), foo_id, RuntimeType::Acir(InlineType::default())); + let mut builder = FunctionBuilder::new("foo".into(), foo_id); let bar_id = Id::test_new(1); let bar = builder.import_function(bar_id); @@ -597,8 +597,7 @@ mod test { let id2_id = Id::test_new(3); // Compiling main - let mut builder = - FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir(InlineType::default())); + let mut builder = FunctionBuilder::new("main".into(), main_id); let main_v0 = builder.add_parameter(Type::field()); let main_f1 = builder.import_function(square_id); @@ -654,8 +653,7 @@ mod test { // return v4 // } let main_id = Id::test_new(0); - let mut builder = - FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir(InlineType::default())); + let mut builder = FunctionBuilder::new("main".into(), main_id); let factorial_id = Id::test_new(1); let factorial = builder.import_function(factorial_id); @@ -755,8 +753,7 @@ mod test { // jmp b3(Field 2) // } let main_id = Id::test_new(0); - let mut builder = - FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir(InlineType::default())); + let mut builder = FunctionBuilder::new("main".into(), main_id); let main_cond = builder.add_parameter(Type::bool()); let inner1_id = Id::test_new(1); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/mem2reg.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/mem2reg.rs index b47d6594bc5d..f1a38585bd65 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/mem2reg.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/mem2reg.rs @@ -433,8 +433,7 @@ mod tests { // } let func_id = Id::test_new(0); - let mut builder = - FunctionBuilder::new("func".into(), func_id, RuntimeType::Acir(InlineType::default())); + let mut builder = FunctionBuilder::new("func".into(), func_id); let v0 = builder.insert_allocate(Type::Array(Rc::new(vec![Type::field()]), 2)); let one = builder.field_constant(FieldElement::one()); let two = builder.field_constant(FieldElement::one()); @@ -475,8 +474,7 @@ mod tests { // } let func_id = Id::test_new(0); - let mut builder = - FunctionBuilder::new("func".into(), func_id, RuntimeType::Acir(InlineType::default())); + let mut builder = FunctionBuilder::new("func".into(), func_id); let v0 = builder.insert_allocate(Type::field()); let one = builder.field_constant(FieldElement::one()); builder.insert_store(v0, one); @@ -510,8 +508,7 @@ mod tests { // } let func_id = Id::test_new(0); - let mut builder = - FunctionBuilder::new("func".into(), func_id, RuntimeType::Acir(InlineType::default())); + let mut builder = FunctionBuilder::new("func".into(), func_id); let v0 = builder.insert_allocate(Type::field()); let const_one = builder.field_constant(FieldElement::one()); builder.insert_store(v0, const_one); @@ -570,8 +567,7 @@ mod tests { // return v2, v3, v4 // } let main_id = Id::test_new(0); - let mut builder = - FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir(InlineType::default())); + let mut builder = FunctionBuilder::new("main".into(), main_id); let v0 = builder.insert_allocate(Type::field()); @@ -651,8 +647,7 @@ mod tests { // return // } let main_id = Id::test_new(0); - let mut builder = - FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir(InlineType::default())); + let mut builder = FunctionBuilder::new("main".into(), main_id); let v0 = builder.insert_allocate(Type::field()); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/rc.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/rc.rs index 5e6c2dbb25cb..7b5196f20049 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/rc.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/rc.rs @@ -210,7 +210,8 @@ mod test { // return [v0] // } let main_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("foo".into(), main_id, RuntimeType::Brillig); + let mut builder = FunctionBuilder::new("foo".into(), main_id); + builder.set_runtime(RuntimeType::Brillig); let inner_array_type = Type::Array(Rc::new(vec![Type::field()]), 2); let v0 = builder.add_parameter(inner_array_type.clone()); @@ -249,11 +250,7 @@ mod test { // return // } let main_id = Id::test_new(0); - let mut builder = FunctionBuilder::new( - "mutator".into(), - main_id, - RuntimeType::Acir(InlineType::default()), - ); + let mut builder = FunctionBuilder::new("mutator".into(), main_id); let array_type = Type::Array(Rc::new(vec![Type::field()]), 2); let v0 = builder.add_parameter(array_type.clone()); @@ -302,11 +299,7 @@ mod test { // return // } let main_id = Id::test_new(0); - let mut builder = FunctionBuilder::new( - "mutator2".into(), - main_id, - RuntimeType::Acir(InlineType::default()), - ); + let mut builder = FunctionBuilder::new("mutator2".into(), main_id); let array_type = Type::Array(Rc::new(vec![Type::field()]), 2); let reference_type = Type::Reference(Rc::new(array_type.clone())); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/simplify_cfg.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/simplify_cfg.rs index f4b32b6bafad..b9675d99c90c 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/simplify_cfg.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/simplify_cfg.rs @@ -172,8 +172,7 @@ mod test { // return v1 // } let main_id = Id::test_new(0); - let mut builder = - FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir(InlineType::default())); + let mut builder = FunctionBuilder::new("main".into(), main_id); let b1 = builder.insert_block(); let b2 = builder.insert_block(); @@ -229,8 +228,7 @@ mod test { // return Field 2 // } let main_id = Id::test_new(0); - let mut builder = - FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir(InlineType::default())); + let mut builder = FunctionBuilder::new("main".into(), main_id); let v0 = builder.add_parameter(Type::bool()); let b1 = builder.insert_block(); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/unrolling.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/unrolling.rs index 4ebdfd04e45d..92ec1e8f1bb4 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/unrolling.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/unrolling.rs @@ -508,8 +508,7 @@ mod tests { let main_id = Id::test_new(0); // Compiling main - let mut builder = - FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir(InlineType::default())); + let mut builder = FunctionBuilder::new("main".into(), main_id); let b1 = builder.insert_block(); let b2 = builder.insert_block(); @@ -611,8 +610,7 @@ mod tests { // return Field 0 // } let main_id = Id::test_new(0); - let mut builder = - FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir(InlineType::default())); + let mut builder = FunctionBuilder::new("main".into(), main_id); let b1 = builder.insert_block(); let b2 = builder.insert_block(); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs index d13c0dbbdfa7..569e543ce40f 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs @@ -108,7 +108,8 @@ impl<'a> FunctionContext<'a> { .expect("No function in queue for the FunctionContext to compile") .1; - let builder = FunctionBuilder::new(function_name, function_id, runtime); + let mut builder = FunctionBuilder::new(function_name, function_id); + builder.set_runtime(runtime); let definitions = HashMap::default(); let mut this = Self { definitions, builder, shared_context, loops: Vec::new() }; this.add_parameters_to_scope(parameters); From 381cf35decc8b0906371bcd16125da9d2701a330 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Thu, 28 Mar 2024 21:39:07 +0000 Subject: [PATCH 136/139] add is_entry_point on RunTimeType --- .../noirc_evaluator/src/ssa/ir/function.rs | 16 ++++++++++++++++ .../noirc_evaluator/src/ssa/opt/inlining.rs | 8 +------- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/function.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/function.rs index c17738e30d8a..011bee36661b 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/function.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/function.rs @@ -29,6 +29,22 @@ pub(crate) enum InlineType { Fold, } +impl RuntimeType { + /// Returns whether the runtime type represents an entry point. + /// We return `false` for InlineType::Inline on default, which is true + /// in all cases except for main. `main` should be supported with special + /// handling in any places where this function determines logic. + pub(crate) fn is_entry_point(&self) -> bool { + match self { + RuntimeType::Acir(inline_type) => match inline_type { + InlineType::Inline => false, + InlineType::Fold => true, + }, + RuntimeType::Brillig => true, + } + } +} + /// A function holds a list of instructions. /// These instructions are further grouped into Basic blocks /// diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/inlining.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/inlining.rs index 811b15779aee..7c7698d236dd 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/inlining.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/inlining.rs @@ -100,13 +100,7 @@ struct PerFunctionContext<'function> { fn get_entry_point_functions(ssa: &Ssa) -> BTreeSet { let functions = ssa.functions.iter(); let mut entry_points = functions - .filter(|(_, function)| match function.runtime() { - RuntimeType::Acir(inline_type) => match inline_type { - InlineType::Inline => false, - InlineType::Fold => true, - }, - RuntimeType::Brillig => true, - }) + .filter(|(_, function)| function.runtime().is_entry_point()) .map(|(id, _)| *id) .collect::>(); From 67c4a90be6c53e9961ac93b49dc2b3d60544c7c1 Mon Sep 17 00:00:00 2001 From: Maxim Vezenov Date: Thu, 28 Mar 2024 21:40:27 +0000 Subject: [PATCH 137/139] Update noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/mod.rs Co-authored-by: jfecher --- .../noir-repo/compiler/noirc_frontend/src/hir/type_check/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/mod.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/mod.rs index ae4df7858c58..221226e5d21e 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/mod.rs @@ -503,7 +503,7 @@ mod test { trait_constraints: Vec::new(), direct_generics: Vec::new(), is_entry_point: true, - should_fold: true, + should_fold: false, }; interner.push_fn_meta(func_meta, func_id); From 778e8d9eb1a58d1f645de3eadfdc78002c1d6888 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Thu, 28 Mar 2024 21:43:42 +0000 Subject: [PATCH 138/139] remove unnecessary field in type_check tests --- .../noirc_frontend/src/hir/type_check/mod.rs | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/mod.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/mod.rs index ae4df7858c58..3d9d870d0466 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/mod.rs @@ -562,13 +562,7 @@ mod test { "#; - let expected_num_errors = 0; - type_check_src_code_errors_expected( - src, - expected_num_errors, - vec![String::from("main"), String::from("foo")], - 0, - ); + type_check_src_code(src, vec![String::from("main"), String::from("foo")]); } #[test] fn basic_closure() { @@ -603,7 +597,7 @@ mod test { } "#; - type_check_src_code_errors_expected(src, 0, vec![String::from("fold")], 1); + type_check_src_code_errors_expected(src, vec![String::from("fold")], 1); } // This is the same Stub that is in the resolver, maybe we can pull this out into a test module and re-use? @@ -639,14 +633,13 @@ mod test { } fn type_check_src_code(src: &str, func_namespace: Vec) { - type_check_src_code_errors_expected(src, 0, func_namespace, 0); + type_check_src_code_errors_expected(src, func_namespace, 0); } // This function assumes that there is only one function and this is the // func id that is returned fn type_check_src_code_errors_expected( src: &str, - expected_num_parser_errs: usize, func_namespace: Vec, expected_num_type_check_errs: usize, ) { @@ -656,9 +649,8 @@ mod test { assert_eq!( errors.len(), - expected_num_parser_errs, - "expected {} parser errors, but got {}, errors: {:?}", - expected_num_parser_errs, + 0, + "expected 0 parser errors, but got {}, errors: {:?}", errors.len(), errors ); From 5cd9a93bc155734242aad095f7b1b9ee8ec85312 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Fri, 29 Mar 2024 14:25:18 +0000 Subject: [PATCH 139/139] missing set_runtime usage in brillig tests --- .../src/brillig/brillig_gen/brillig_slice_ops.rs | 5 +++-- .../src/brillig/brillig_gen/variable_liveness.rs | 6 ++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_slice_ops.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_slice_ops.rs index e42b2787f73b..b93693d9c797 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_slice_ops.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_slice_ops.rs @@ -373,8 +373,9 @@ mod tests { use crate::ssa::ssa_gen::Ssa; fn create_test_environment() -> (Ssa, FunctionContext, BrilligContext) { - let builder = - FunctionBuilder::new("main".to_string(), Id::test_new(0), RuntimeType::Brillig); + let mut builder = FunctionBuilder::new("main".to_string(), Id::test_new(0)); + builder.set_runtime(RuntimeType::Brillig); + let ssa = builder.finish(); let mut brillig_context = create_context(); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/variable_liveness.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/variable_liveness.rs index 05978c2c6abb..c9f1cd1e247a 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/variable_liveness.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/variable_liveness.rs @@ -323,7 +323,8 @@ mod test { // } let main_id = Id::test_new(1); - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Brillig); + let mut builder = FunctionBuilder::new("main".into(), main_id); + builder.set_runtime(RuntimeType::Brillig); let b1 = builder.insert_block(); let b2 = builder.insert_block(); @@ -425,7 +426,8 @@ mod test { // } let main_id = Id::test_new(1); - let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Brillig); + let mut builder = FunctionBuilder::new("main".into(), main_id); + builder.set_runtime(RuntimeType::Brillig); let b1 = builder.insert_block(); let b2 = builder.insert_block();