From 5c86609723a84605ddef8acd346d5e5d79849d8e Mon Sep 17 00:00:00 2001 From: vezenovm Date: Mon, 8 Jan 2024 17:57:43 +0000 Subject: [PATCH 1/7] remove aggregation objects from RecursionConstraint --- .../acir_format/acir_to_constraint_buf.hpp | 19 ++++++++----------- .../dsl/acir_format/recursion_constraint.hpp | 15 --------------- .../acir_format/recursion_constraint.test.cpp | 3 --- 3 files changed, 8 insertions(+), 29 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 9b6b36d7e065..59df422a7209 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 @@ -203,18 +203,15 @@ void handle_blackbox_func_call(Circuit::Opcode::BlackBoxFuncCall const& arg, aci .proof = map(arg.proof, [](auto& e) { return e.witness.value; }), .public_inputs = map(arg.public_inputs, [](auto& e) { return e.witness.value; }), .key_hash = arg.key_hash.witness.value, - .input_aggregation_object = {}, - .output_aggregation_object = {}, - .nested_aggregation_object = {}, }; - if (arg.input_aggregation_object.has_value()) { - for (size_t i = 0; i < RecursionConstraint::AGGREGATION_OBJECT_SIZE; ++i) { - c.input_aggregation_object[i] = (*arg.input_aggregation_object)[i].witness.value; - } - } - for (size_t i = 0; i < RecursionConstraint::AGGREGATION_OBJECT_SIZE; ++i) { - c.output_aggregation_object[i] = arg.output_aggregation_object[i].value; - } + // if (arg.input_aggregation_object.has_value()) { + // for (size_t i = 0; i < RecursionConstraint::AGGREGATION_OBJECT_SIZE; ++i) { + // c.input_aggregation_object[i] = (*arg.input_aggregation_object)[i].witness.value; + // } + // } + // for (size_t i = 0; i < RecursionConstraint::AGGREGATION_OBJECT_SIZE; ++i) { + // c.output_aggregation_object[i] = arg.output_aggregation_object[i].value; + // } af.recursion_constraints.push_back(c); } }, diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.hpp index 8f6618106d22..d048ce93bdfb 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.hpp @@ -53,15 +53,6 @@ struct RecursionConstraint { std::vector proof; std::vector public_inputs; uint32_t key_hash; - // TODO(maxim):This is now unused, but we keep it here for backwards compatibility - std::array input_aggregation_object; - // TODO(maxim): This is now unused, but we keep it here for backwards compatibility - std::array output_aggregation_object; - // TODO(maxim): This is currently not being used on the Noir level at all, - // TODO(maxim): but we keep it here for backwards compatibility - // TODO(maxim): The object is now currently contained by the `proof` field - // TODO(maxim): and is handled when serializing ACIR to a barretenberg circuit - std::array nested_aggregation_object; friend bool operator==(RecursionConstraint const& lhs, RecursionConstraint const& rhs) = default; }; @@ -100,9 +91,6 @@ template inline void read(B& buf, RecursionConstraint& constraint) read(buf, constraint.proof); read(buf, constraint.public_inputs); read(buf, constraint.key_hash); - read(buf, constraint.input_aggregation_object); - read(buf, constraint.output_aggregation_object); - read(buf, constraint.nested_aggregation_object); } template inline void write(B& buf, RecursionConstraint const& constraint) @@ -112,9 +100,6 @@ template inline void write(B& buf, RecursionConstraint const& const write(buf, constraint.proof); write(buf, constraint.public_inputs); write(buf, constraint.key_hash); - write(buf, constraint.input_aggregation_object); - write(buf, constraint.output_aggregation_object); - write(buf, constraint.nested_aggregation_object); } } // namespace acir_format diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.test.cpp index 63a60cda21ab..5defd40ed197 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.test.cpp @@ -207,9 +207,6 @@ Builder create_outer_circuit(std::vector& inner_circuits) .proof = proof_indices, .public_inputs = inner_public_inputs, .key_hash = key_hash_start_idx, - .input_aggregation_object = input_aggregation_object, - .output_aggregation_object = output_aggregation_object, - .nested_aggregation_object = nested_aggregation_object, }; recursion_constraints.push_back(recursion_constraint); From fe9567c8a422243c62d55ba34243359031da25af Mon Sep 17 00:00:00 2001 From: vezenovm Date: Mon, 8 Jan 2024 17:59:17 +0000 Subject: [PATCH 2/7] remove commented out code --- .../dsl/acir_format/acir_to_constraint_buf.hpp | 8 -------- 1 file changed, 8 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 59df422a7209..02193ef7b71e 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 @@ -204,14 +204,6 @@ void handle_blackbox_func_call(Circuit::Opcode::BlackBoxFuncCall const& arg, aci .public_inputs = map(arg.public_inputs, [](auto& e) { return e.witness.value; }), .key_hash = arg.key_hash.witness.value, }; - // if (arg.input_aggregation_object.has_value()) { - // for (size_t i = 0; i < RecursionConstraint::AGGREGATION_OBJECT_SIZE; ++i) { - // c.input_aggregation_object[i] = (*arg.input_aggregation_object)[i].witness.value; - // } - // } - // for (size_t i = 0; i < RecursionConstraint::AGGREGATION_OBJECT_SIZE; ++i) { - // c.output_aggregation_object[i] = arg.output_aggregation_object[i].value; - // } af.recursion_constraints.push_back(c); } }, From a185a2fc9046772585f10bcd845e2cce77e20f77 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Mon, 8 Jan 2024 18:25:59 +0000 Subject: [PATCH 3/7] Update recursive aggregation opcode to not use agg objects --- .../barretenberg/dsl/acir_format/serde/acir.hpp | 14 -------------- noir/acvm-repo/acir/codegen/acir.cpp | 8 -------- .../circuit/opcodes/black_box_function_call.rs | 17 ++--------------- 3 files changed, 2 insertions(+), 37 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 4aa912073c84..e9a9b17d8648 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/acir.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/acir.hpp @@ -178,8 +178,6 @@ struct BlackBoxFuncCall { std::vector proof; std::vector public_inputs; Circuit::FunctionInput key_hash; - std::optional> input_aggregation_object; - std::vector output_aggregation_object; friend bool operator==(const RecursiveAggregation&, const RecursiveAggregation&); std::vector bincodeSerialize() const; @@ -2659,12 +2657,6 @@ inline bool operator==(const BlackBoxFuncCall::RecursiveAggregation& lhs, if (!(lhs.key_hash == rhs.key_hash)) { return false; } - if (!(lhs.input_aggregation_object == rhs.input_aggregation_object)) { - return false; - } - if (!(lhs.output_aggregation_object == rhs.output_aggregation_object)) { - return false; - } return true; } @@ -2697,8 +2689,6 @@ void serde::Serializable::seria serde::Serializable::serialize(obj.proof, serializer); serde::Serializable::serialize(obj.public_inputs, serializer); serde::Serializable::serialize(obj.key_hash, serializer); - serde::Serializable::serialize(obj.input_aggregation_object, serializer); - serde::Serializable::serialize(obj.output_aggregation_object, serializer); } template <> @@ -2711,10 +2701,6 @@ Circuit::BlackBoxFuncCall::RecursiveAggregation serde::Deserializable< obj.proof = serde::Deserializable::deserialize(deserializer); obj.public_inputs = serde::Deserializable::deserialize(deserializer); obj.key_hash = serde::Deserializable::deserialize(deserializer); - obj.input_aggregation_object = - serde::Deserializable::deserialize(deserializer); - obj.output_aggregation_object = - serde::Deserializable::deserialize(deserializer); return obj; } diff --git a/noir/acvm-repo/acir/codegen/acir.cpp b/noir/acvm-repo/acir/codegen/acir.cpp index 27dc427227f1..0ce57d45bb45 100644 --- a/noir/acvm-repo/acir/codegen/acir.cpp +++ b/noir/acvm-repo/acir/codegen/acir.cpp @@ -178,8 +178,6 @@ namespace Circuit { std::vector proof; std::vector public_inputs; Circuit::FunctionInput key_hash; - std::optional> input_aggregation_object; - std::vector output_aggregation_object; friend bool operator==(const RecursiveAggregation&, const RecursiveAggregation&); std::vector bincodeSerialize() const; @@ -2295,8 +2293,6 @@ namespace Circuit { 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; } - if (!(lhs.input_aggregation_object == rhs.input_aggregation_object)) { return false; } - if (!(lhs.output_aggregation_object == rhs.output_aggregation_object)) { return false; } return true; } @@ -2324,8 +2320,6 @@ void serde::Serializable::seria serde::Serializable::serialize(obj.proof, serializer); serde::Serializable::serialize(obj.public_inputs, serializer); serde::Serializable::serialize(obj.key_hash, serializer); - serde::Serializable::serialize(obj.input_aggregation_object, serializer); - serde::Serializable::serialize(obj.output_aggregation_object, serializer); } template <> @@ -2336,8 +2330,6 @@ Circuit::BlackBoxFuncCall::RecursiveAggregation serde::Deserializable::deserialize(deserializer); obj.public_inputs = serde::Deserializable::deserialize(deserializer); obj.key_hash = serde::Deserializable::deserialize(deserializer); - obj.input_aggregation_object = serde::Deserializable::deserialize(deserializer); - obj.output_aggregation_object = serde::Deserializable::deserialize(deserializer); return obj; } diff --git a/noir/acvm-repo/acir/src/circuit/opcodes/black_box_function_call.rs b/noir/acvm-repo/acir/src/circuit/opcodes/black_box_function_call.rs index fea12f9c08a5..e0dbc81d31b2 100644 --- a/noir/acvm-repo/acir/src/circuit/opcodes/black_box_function_call.rs +++ b/noir/acvm-repo/acir/src/circuit/opcodes/black_box_function_call.rs @@ -107,17 +107,6 @@ pub enum BlackBoxFuncCall { /// The circuit implementing this opcode can use this hash to ensure that the /// key provided to the circuit matches the key produced by the circuit creator key_hash: FunctionInput, - /// An aggregation object is blob of data that the top-level verifier must run some proof system specific - /// algorithm on to complete verification. The size is proof system specific and will be set by the backend integrating this opcode. - /// The input aggregation object is only not `None` when we are verifying a previous recursive aggregation in - /// the current circuit. If this is the first recursive aggregation there is no input aggregation object. - /// It is left to the backend to determine how to handle when there is no input aggregation object. - input_aggregation_object: Option>, - /// This is the result of a recursive aggregation and is what will be fed into the next verifier. - /// The next verifier can either perform a final verification (returning true or false) - /// or perform another recursive aggregation where this output aggregation object - /// will be the input aggregation object of the next recursive aggregation. - output_aggregation_object: Vec, }, } @@ -245,9 +234,7 @@ impl BlackBoxFuncCall { | BlackBoxFuncCall::Blake3 { outputs, .. } | BlackBoxFuncCall::Keccak256 { outputs, .. } | BlackBoxFuncCall::Keccakf1600 { outputs, .. } - | BlackBoxFuncCall::RecursiveAggregation { - output_aggregation_object: outputs, .. - } => outputs.to_vec(), + => outputs.to_vec(), BlackBoxFuncCall::AND { output, .. } | BlackBoxFuncCall::XOR { output, .. } | BlackBoxFuncCall::SchnorrVerify { output, .. } @@ -256,7 +243,7 @@ impl BlackBoxFuncCall { | BlackBoxFuncCall::EcdsaSecp256r1 { output, .. } => vec![*output], BlackBoxFuncCall::FixedBaseScalarMul { outputs, .. } | BlackBoxFuncCall::PedersenCommitment { outputs, .. } => vec![outputs.0, outputs.1], - BlackBoxFuncCall::RANGE { .. } => vec![], + BlackBoxFuncCall::RANGE { .. } | BlackBoxFuncCall::RecursiveAggregation { .. } => vec![], BlackBoxFuncCall::Keccak256VariableLength { outputs, .. } => outputs.to_vec(), } } From 6917893f23b751bcf9bffa9d9be612074cb1679b Mon Sep 17 00:00:00 2001 From: vezenovm Date: Mon, 8 Jan 2024 18:39:02 +0000 Subject: [PATCH 4/7] update ACIR for recursive agg changes --- noir/acvm-repo/acvm/src/compiler/transformers/mod.rs | 6 +----- noir/acvm-repo/acvm/src/pwg/blackbox/mod.rs | 10 ++-------- 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/noir/acvm-repo/acvm/src/compiler/transformers/mod.rs b/noir/acvm-repo/acvm/src/compiler/transformers/mod.rs index 003124f8b63a..586c3d7ddb01 100644 --- a/noir/acvm-repo/acvm/src/compiler/transformers/mod.rs +++ b/noir/acvm-repo/acvm/src/compiler/transformers/mod.rs @@ -105,7 +105,7 @@ pub(super) fn transform_internal( | acir::circuit::opcodes::BlackBoxFuncCall::XOR { output, .. } => { transformer.mark_solvable(*output); } - acir::circuit::opcodes::BlackBoxFuncCall::RANGE { .. } => (), + acir::circuit::opcodes::BlackBoxFuncCall::RANGE { .. } | acir::circuit::opcodes::BlackBoxFuncCall::RecursiveAggregation { .. } => (), acir::circuit::opcodes::BlackBoxFuncCall::SHA256 { outputs, .. } | acir::circuit::opcodes::BlackBoxFuncCall::Keccak256 { outputs, .. } | acir::circuit::opcodes::BlackBoxFuncCall::Keccak256VariableLength { @@ -113,10 +113,6 @@ pub(super) fn transform_internal( .. } | acir::circuit::opcodes::BlackBoxFuncCall::Keccakf1600 { outputs, .. } - | acir::circuit::opcodes::BlackBoxFuncCall::RecursiveAggregation { - output_aggregation_object: outputs, - .. - } | acir::circuit::opcodes::BlackBoxFuncCall::Blake2s { outputs, .. } | acir::circuit::opcodes::BlackBoxFuncCall::Blake3 { outputs, .. } => { for witness in outputs { diff --git a/noir/acvm-repo/acvm/src/pwg/blackbox/mod.rs b/noir/acvm-repo/acvm/src/pwg/blackbox/mod.rs index c36596235a26..3ffc978158d8 100644 --- a/noir/acvm-repo/acvm/src/pwg/blackbox/mod.rs +++ b/noir/acvm-repo/acvm/src/pwg/blackbox/mod.rs @@ -177,13 +177,7 @@ pub(crate) fn solve( BlackBoxFuncCall::FixedBaseScalarMul { low, high, outputs } => { fixed_base_scalar_mul(backend, initial_witness, *low, *high, *outputs) } - BlackBoxFuncCall::RecursiveAggregation { output_aggregation_object, .. } => { - // Solve the output of the recursive aggregation to zero to prevent missing assignment errors - // The correct value will be computed by the backend - for witness in output_aggregation_object { - insert_value(witness, FieldElement::zero(), initial_witness)?; - } - Ok(()) - } + // Recursive aggregation will be entirel handled by the backend and is not solved by the ACVM + BlackBoxFuncCall::RecursiveAggregation { .. } => Ok(()), } } From e7637820c6b73cec54e72b1315c4f4124bad340d Mon Sep 17 00:00:00 2001 From: vezenovm Date: Mon, 8 Jan 2024 18:45:04 +0000 Subject: [PATCH 5/7] update generated_acir --- .../src/ssa/acir_gen/acir_ir/generated_acir.rs | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/noir/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs b/noir/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs index c9f7ee51e977..0eb8cd2bb370 100644 --- a/noir/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs +++ b/noir/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs @@ -227,23 +227,11 @@ impl GeneratedAcir { BlackBoxFuncCall::Keccakf1600 { inputs: inputs[0].clone(), outputs } } BlackBoxFunc::RecursiveAggregation => { - let has_previous_aggregation = self.opcodes.iter().any(|op| { - matches!( - op, - AcirOpcode::BlackBoxFuncCall(BlackBoxFuncCall::RecursiveAggregation { .. }) - ) - }); - - let input_aggregation_object = - if !has_previous_aggregation { None } else { Some(inputs[4].clone()) }; - BlackBoxFuncCall::RecursiveAggregation { verification_key: inputs[0].clone(), proof: inputs[1].clone(), public_inputs: inputs[2].clone(), key_hash: inputs[3][0], - input_aggregation_object, - output_aggregation_object: outputs, } } }; From 04d04d1a9ce2ce98b4c2abe3fdf7b8c7dc1f6d67 Mon Sep 17 00:00:00 2001 From: kevaundray Date: Mon, 8 Jan 2024 19:33:40 +0000 Subject: [PATCH 6/7] Update noir/acvm-repo/acvm/src/pwg/blackbox/mod.rs --- noir/acvm-repo/acvm/src/pwg/blackbox/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noir/acvm-repo/acvm/src/pwg/blackbox/mod.rs b/noir/acvm-repo/acvm/src/pwg/blackbox/mod.rs index 3ffc978158d8..f752924ac186 100644 --- a/noir/acvm-repo/acvm/src/pwg/blackbox/mod.rs +++ b/noir/acvm-repo/acvm/src/pwg/blackbox/mod.rs @@ -177,7 +177,7 @@ pub(crate) fn solve( BlackBoxFuncCall::FixedBaseScalarMul { low, high, outputs } => { fixed_base_scalar_mul(backend, initial_witness, *low, *high, *outputs) } - // Recursive aggregation will be entirel handled by the backend and is not solved by the ACVM + // Recursive aggregation will be entirely handled by the backend and is not solved by the ACVM BlackBoxFuncCall::RecursiveAggregation { .. } => Ok(()), } } From b60a8f16e848515fd8b64d4c68777724ae56bf91 Mon Sep 17 00:00:00 2001 From: vezenovm Date: Mon, 8 Jan 2024 21:07:43 +0000 Subject: [PATCH 7/7] change verify_proof sig --- .../opcodes/black_box_function_call.rs | 4 ---- noir/noir_stdlib/src/lib.nr | 9 ++------- .../double_verify_proof/target/acir.gz | Bin 1186 -> 1166 bytes .../double_verify_proof/target/witness.gz | Bin 8144 -> 8137 bytes .../double_verify_proof/Prover.toml | 6 ------ .../double_verify_proof/src/main.nr | 15 ++++----------- 6 files changed, 6 insertions(+), 28 deletions(-) diff --git a/noir/acvm-repo/acir/src/circuit/opcodes/black_box_function_call.rs b/noir/acvm-repo/acir/src/circuit/opcodes/black_box_function_call.rs index e0dbc81d31b2..2ef9790221c1 100644 --- a/noir/acvm-repo/acir/src/circuit/opcodes/black_box_function_call.rs +++ b/noir/acvm-repo/acir/src/circuit/opcodes/black_box_function_call.rs @@ -212,16 +212,12 @@ impl BlackBoxFuncCall { proof, public_inputs, key_hash, - .. } => { let mut inputs = Vec::new(); inputs.extend(key.iter().copied()); inputs.extend(proof.iter().copied()); inputs.extend(public_inputs.iter().copied()); inputs.push(*key_hash); - // NOTE: we do not return an input aggregation object as it will either be non-existent for the first recursive aggregation - // or the output aggregation object of a previous recursive aggregation. We do not simulate recursive aggregation - // thus the input aggregation object will always be unassigned until proving inputs } } diff --git a/noir/noir_stdlib/src/lib.nr b/noir/noir_stdlib/src/lib.nr index 70b4681b54d1..8c230ab61a3e 100644 --- a/noir/noir_stdlib/src/lib.nr +++ b/noir/noir_stdlib/src/lib.nr @@ -37,13 +37,8 @@ unconstrained pub fn println(input: T) { } #[foreign(recursive_aggregation)] -pub fn verify_proof( - _verification_key: [Field], - _proof: [Field], - _public_inputs: [Field], - _key_hash: Field, - _input_aggregation_object: [Field; N] -) -> [Field; N] {} +pub fn verify_proof(_verification_key: [Field], _proof: [Field], _public_inputs: [Field], _key_hash: Field) {} + // Asserts that the given value is known at compile-time. // Useful for debugging for-loop bounds. #[builtin(assert_constant)] diff --git a/noir/test_programs/acir_artifacts/double_verify_proof/target/acir.gz b/noir/test_programs/acir_artifacts/double_verify_proof/target/acir.gz index 31ff852f775fd90f01e16b25100e391e964dd19d..7f58ae40b89c7e2cd6760f264f957ab3083c213d 100644 GIT binary patch literal 1166 zcmV;91abQxiwFP!00000|LxXebKPkihw;01Q@d$uXYJi?*0$B{+Ui=}uI<{kZQHhO z+r8$#GLz}_1@uAwGiN?IIZrZ~IoI!-oFRmaAwFk+3<+mnbnosj<0WGM7w6GS@qFPLgYY8o>rL?prY8g$^vRY2dYXz;Sm9(-} z(W+Wat7{FdsmXegUaXhsrFxlOu2<-ldX-+S*XXr+onEguXf3@_Q}iaiS#Qx>^)|g- z@6bE-F1=gt(R=kiyD2lXL+SRc_x^)Y>1pU@}uDScX>(P#BJt*y^%9eqJx)R**S zeMMi@*YtILL*LZ5^lg1d-_`f@ef>b|ruln$KJ@)Z`muhZpXz7&xqhKv>R0-;*3)ma zzJ9CU>G%4B{-{6c&-#o0s=w*)`iK6hf9c=)kN&Iw>Hpe58)_qMtWC73Hq++XLR)Gp zZLMvzt+vzl+Ce*NC+)0Vw5xX0?%G3pYA@}reYCIk)BZX@2kIaltV49D4%6W}LPzQ- z9j#+@td7(1IzcDuB%Q2NbgE9%={iGa>MWhD+#jAfzMq@s_vv>k{Z6H5`kjhiXm@I! z@8|0RU8sw6u`bc2x=fer3SFtIbhWP0wYpB%>jvGZn{=~o(XF~ox9bkwsk?Ny?$N!v zPxtEqJ*bEDupZH)dQ6Y&2|cN)uhU8hF@t8*OqyA zPQPh4-KN>}x>kstP6@Hkw3#l`WO_`C=`anZzqFU`(p-8=Yw0YFrLVM=uF_O`N=xY| z4W*y7lWx*X`cpf^PSy#rkF=34(nNYl3+W&Yq<^%J?$JDYN9*VujiYb0jor=WW^c2# z+1YGt_BGp@UCpLuPuB}^N7oN=KeL_L&1`1&GFzFQ%tmG(vyIusY-08>TbLcp24?@V zec8QiUiL0qmz~STW#6)G*|lt1_H3&VcWj#w_bc0#-O6TVud-FysccmCDch7?$|hxx zvPIdUY*6+m+mqeN=45ZOHQAYLO!g()l3mHBWKWI?aYv2`aX+#h*^O*Q_99!6oybOH zAF>VEg=|9hAX|_f$ajkG6Sssr!VTema67mg+zjpow}Lytjo?143h^$i3Gp6q3%CQ^ z0Qyh+=|0V;_q3kQ(|Gz$+vz$@r{}bsj?-}ZO}ptf&8FA1noiT`)IQT?zWnr<7SmxG zOn+%F-KDwome$f)8cSbkD_y0j^puv;Q5s4=X(!#Jne>uY(n%UgA88|9q>1#97Scf) gNdIUb-J^N*j@HpR8b{w!+jYL@46W5`Av6*I0Qf+6RR910 literal 1186 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 literal 8144 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