From 379b5adc259ac69b01e61b852172cdfc87cf9350 Mon Sep 17 00:00:00 2001 From: Innokentii Sennovskii Date: Thu, 7 Dec 2023 00:08:40 +0000 Subject: [PATCH 01/35] feat: Log-derivative based generic permutations for AVM (#3428) Introduces a relation for constructing generic permutations that needs to be templated for PIL for AVM. Renames lookup_library to logderivative_library --- .../src/barretenberg/eccvm/eccvm_prover.cpp | 4 +- .../cpp/src/barretenberg/flavor/toy_avm.hpp | 376 ++++++++++++++++++ ..._library.hpp => logderivative_library.hpp} | 104 ++++- .../eccvm/eccvm_circuit_builder.hpp | 8 +- .../toy_avm/toy_avm_circuit_builder.hpp | 163 ++++++++ .../toy_avm/toy_avm_circuit_builder.test.cpp | 70 ++++ .../relations/databus_lookup_relation.hpp | 20 +- .../relations/ecc_vm/ecc_lookup_relation.cpp | 4 +- .../relations/ecc_vm/ecc_lookup_relation.hpp | 11 +- .../toy_avm/generic_permutation_relation.cpp | 34 ++ .../toy_avm/generic_permutation_relation.hpp | 210 ++++++++++ .../relations/toy_avm/relation_definer.hpp | 213 ++++++++++ .../sumcheck/instance/prover_instance.cpp | 4 +- .../vm/generated/AvmMini_prover.cpp | 2 +- .../barretenberg/vm/generated/Fib_prover.cpp | 2 +- 15 files changed, 1201 insertions(+), 24 deletions(-) create mode 100644 barretenberg/cpp/src/barretenberg/flavor/toy_avm.hpp rename barretenberg/cpp/src/barretenberg/honk/proof_system/{lookup_library.hpp => logderivative_library.hpp} (58%) create mode 100644 barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/toy_avm/toy_avm_circuit_builder.hpp create mode 100644 barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/toy_avm/toy_avm_circuit_builder.test.cpp create mode 100644 barretenberg/cpp/src/barretenberg/relations/toy_avm/generic_permutation_relation.cpp create mode 100644 barretenberg/cpp/src/barretenberg/relations/toy_avm/generic_permutation_relation.hpp create mode 100644 barretenberg/cpp/src/barretenberg/relations/toy_avm/relation_definer.hpp diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp index f9b9fb6ea46..60b5804a47d 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp @@ -2,7 +2,7 @@ #include "barretenberg/commitment_schemes/claim.hpp" #include "barretenberg/commitment_schemes/commitment_key.hpp" #include "barretenberg/common/ref_array.hpp" -#include "barretenberg/honk/proof_system/lookup_library.hpp" +#include "barretenberg/honk/proof_system/logderivative_library.hpp" #include "barretenberg/honk/proof_system/permutation_library.hpp" #include "barretenberg/honk/proof_system/power_polynomial.hpp" #include "barretenberg/polynomials/polynomial.hpp" @@ -183,7 +183,7 @@ template void ECCVMProver_::execute_log_derivative_ gamma * (gamma + beta_sqr) * (gamma + beta_sqr + beta_sqr) * (gamma + beta_sqr + beta_sqr + beta_sqr); relation_parameters.eccvm_set_permutation_delta = relation_parameters.eccvm_set_permutation_delta.invert(); // Compute inverse polynomial for our logarithmic-derivative lookup method - lookup_library::compute_logderivative_inverse( + logderivative_library::compute_logderivative_inverse( prover_polynomials, relation_parameters, key->circuit_size); transcript->send_to_verifier(commitment_labels.lookup_inverses, commitment_key->commit(key->lookup_inverses)); prover_polynomials.lookup_inverses = key->lookup_inverses; diff --git a/barretenberg/cpp/src/barretenberg/flavor/toy_avm.hpp b/barretenberg/cpp/src/barretenberg/flavor/toy_avm.hpp new file mode 100644 index 00000000000..ba0c7c2b465 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/flavor/toy_avm.hpp @@ -0,0 +1,376 @@ +#pragma once +#include "barretenberg/commitment_schemes/commitment_key.hpp" +#include "barretenberg/commitment_schemes/kzg/kzg.hpp" +#include "barretenberg/ecc/curves/bn254/bn254.hpp" +#include "barretenberg/flavor/flavor.hpp" +#include "barretenberg/flavor/flavor_macros.hpp" +#include "barretenberg/polynomials/univariate.hpp" +#include "barretenberg/relations/relation_parameters.hpp" +#include "barretenberg/relations/relation_types.hpp" +#include "barretenberg/relations/toy_avm/generic_permutation_relation.hpp" +#include "barretenberg/relations/toy_avm/relation_definer.hpp" +#include "relation_definitions_fwd.hpp" +#include +#include +#include +#include +#include +#include + +// NOLINTBEGIN(cppcoreguidelines-avoid-const-or-ref-data-members) + +namespace proof_system::honk { +namespace flavor { + +/** + * @brief This class provides an example flavor for using GenericPermutationRelations with various settings to make + * integrating those mechanisms into AVM easier + * + */ +class ToyAVM { + public: + using Curve = curve::BN254; + using FF = Curve::ScalarField; + using GroupElement = Curve::Element; + using Commitment = Curve::AffineElement; + using CommitmentHandle = Curve::AffineElement; + using PCS = pcs::kzg::KZG; + using Polynomial = barretenberg::Polynomial; + using PolynomialHandle = std::span; + using CommitmentKey = pcs::CommitmentKey; + using VerifierCommitmentKey = pcs::VerifierCommitmentKey; + + // The number of wires is 5. The set of tuples (permutation_set_column_1,permutation_set_column_2) should be + // equivalent to (permutation_set_column_3, permutation_set_column_4) and the self_permutation_column contains 2 + // subsets which are permutations of each other + static constexpr size_t NUM_WIRES = 5; + + // The number of multivariate polynomials on which a sumcheck prover sumcheck operates (including shifts). We often + // need containers of this size to hold related data, so we choose a name more agnostic than `NUM_POLYNOMIALS`. + // Note: this number does not include the individual sorted list polynomials. + static constexpr size_t NUM_ALL_ENTITIES = 12; + // The number of polynomials precomputed to describe a circuit and to aid a prover in constructing a satisfying + // assignment of witnesses. We again choose a neutral name. + static constexpr size_t NUM_PRECOMPUTED_ENTITIES = 5; + // The total number of witness entities not including shifts. + static constexpr size_t NUM_WITNESS_ENTITIES = 7; + + // define the tuple of Relations that comprise the Sumcheck relation + using Relations = std::tuple>; + + static constexpr size_t MAX_PARTIAL_RELATION_LENGTH = compute_max_partial_relation_length(); + + // BATCHED_RELATION_PARTIAL_LENGTH = algebraic degree of sumcheck relation *after* multiplying by the `pow_zeta` + // random polynomial e.g. For \sum(x) [A(x) * B(x) + C(x)] * PowZeta(X), relation length = 2 and random relation + // length = 3 + static constexpr size_t BATCHED_RELATION_PARTIAL_LENGTH = MAX_PARTIAL_RELATION_LENGTH + 1; + static constexpr size_t NUM_RELATIONS = std::tuple_size::value; + + // Instantiate the BarycentricData needed to extend each Relation Univariate + + // define the containers for storing the contributions from each relation in Sumcheck + using SumcheckTupleOfTuplesOfUnivariates = decltype(create_sumcheck_tuple_of_tuples_of_univariates()); + using TupleOfArraysOfValues = decltype(create_tuple_of_arrays_of_values()); + + private: + /** + * @brief A base class labelling precomputed entities and (ordered) subsets of interest. + * @details Used to build the proving key and verification key. + */ + template class PrecomputedEntities : public PrecomputedEntitiesBase { + public: + using DataType = DataType_; + DEFINE_FLAVOR_MEMBERS(DataType, + lagrange_first, // column 0 + enable_tuple_set_permutation, // column 1 + enable_single_column_permutation, // column 2 + enable_first_set_permutation, // column 3 + enable_second_set_permutation) // column 4 + + RefVector get_selectors() + { + return { lagrange_first, + enable_tuple_set_permutation, + enable_single_column_permutation, + enable_first_set_permutation, + enable_second_set_permutation }; + }; + RefVector get_sigma_polynomials() { return {}; }; + RefVector get_id_polynomials() { return {}; }; + RefVector get_table_polynomials() { return {}; }; + }; + + /** + * @brief Container for all witness polynomials used/constructed by the prover. + * @details Shifts are not included here since they do not occupy their own memory. + */ + + template class WitnessEntities { + public: + DEFINE_FLAVOR_MEMBERS(DataType, + permutation_set_column_1, // Column 0 + permutation_set_column_2, // Column 1 + permutation_set_column_3, // Column 2 + permutation_set_column_4, // Column 3 + self_permutation_column, // Column 4 + tuple_permutation_inverses, // Column 5 + single_permutation_inverses) // Column 6 + + RefVector get_wires() + { + return { permutation_set_column_1, + permutation_set_column_2, + permutation_set_column_3, + permutation_set_column_4, + self_permutation_column }; + }; + }; + + /** + * @brief A base class labelling all entities (for instance, all of the polynomials used by the prover during + * sumcheck) in this Honk variant along with particular subsets of interest + * @details Used to build containers for: the prover's polynomial during sumcheck; the sumcheck's folded + * polynomials; the univariates consturcted during during sumcheck; the evaluations produced by sumcheck. + * + * Symbolically we have: AllEntities = PrecomputedEntities + WitnessEntities + "ShiftedEntities". It could be + * implemented as such, but we have this now. + */ + + template class AllEntities { + public: + DEFINE_FLAVOR_MEMBERS(DataType, + lagrange_first, // Column 0 + enable_tuple_set_permutation, // Column 1 + enable_single_column_permutation, // Column 2 + enable_first_set_permutation, // Column 3 + enable_second_set_permutation, // Column 4 + permutation_set_column_1, // Column 5 + permutation_set_column_2, // Column 6 + permutation_set_column_3, // Column 7 + permutation_set_column_4, // Column 8 + self_permutation_column, // Column 9 + tuple_permutation_inverses, // Column 10 + single_permutation_inverses) // Column 11 + + RefVector get_wires() + { + return { + permutation_set_column_1, permutation_set_column_2, permutation_set_column_3, permutation_set_column_4 + }; + }; + RefVector get_unshifted() + { + return { lagrange_first, + enable_tuple_set_permutation, + enable_single_column_permutation, + enable_first_set_permutation, + enable_second_set_permutation, + permutation_set_column_1, + permutation_set_column_2, + permutation_set_column_3, + permutation_set_column_4, + self_permutation_column, + tuple_permutation_inverses, + single_permutation_inverses }; + }; + RefVector get_to_be_shifted() { return {}; }; + RefVector get_shifted() { return {}; }; + }; + + public: + /** + * @brief The proving key is responsible for storing the polynomials used by the prover. + * @note TODO(Cody): Maybe multiple inheritance is the right thing here. In that case, nothing should eve inherit + * from ProvingKey. + */ + class ProvingKey : public ProvingKey_, WitnessEntities> { + public: + // Expose constructors on the base class + using Base = ProvingKey_, WitnessEntities>; + using Base::Base; + + // The plookup wires that store plookup read data. + std::array get_table_column_wires() { return {}; }; + }; + + /** + * @brief The verification key is responsible for storing the the commitments to the precomputed (non-witnessk) + * polynomials used by the verifier. + * + * @note Note the discrepancy with what sort of data is stored here vs in the proving key. We may want to resolve + * that, and split out separate PrecomputedPolynomials/Commitments data for clarity but also for portability of our + * circuits. + */ + using VerificationKey = VerificationKey_>; + + /** + * @brief A field element for each entity of the flavor. These entities represent the prover polynomials evaluated + * at one point. + */ + class AllValues : public AllEntities { + public: + using Base = AllEntities; + using Base::Base; + }; + + /** + * @brief An owning container of polynomials. + * @warning When this was introduced it broke some of our design principles. + * - Execution trace builders don't handle "polynomials" because the interpretation of the execution trace + * columns as polynomials is a detail of the proving system, and trace builders are (sometimes in practice, + * always in principle) reusable for different proving protocols (e.g., Plonk and Honk). + * - Polynomial storage is handled by key classes. Polynomials aren't moved, but are accessed elsewhere by + * std::spans. + * + * We will consider revising this data model: TODO(https://github.com/AztecProtocol/barretenberg/issues/743) + */ + class AllPolynomials : public AllEntities { + public: + [[nodiscard]] size_t get_polynomial_size() const { return this->lagrange_first.size(); } + AllValues get_row(const size_t row_idx) const + { + AllValues result; + for (auto [result_field, polynomial] : zip_view(result.get_all(), this->get_all())) { + result_field = polynomial[row_idx]; + } + return result; + } + }; + /** + * @brief A container for polynomials handles; only stores spans. + */ + class ProverPolynomials : public AllEntities { + public: + [[nodiscard]] size_t get_polynomial_size() const { return enable_tuple_set_permutation.size(); } + [[nodiscard]] AllValues get_row(const size_t row_idx) const + { + AllValues result; + for (auto [result_field, polynomial] : zip_view(result.get_all(), get_all())) { + result_field = polynomial[row_idx]; + } + return result; + } + }; + + /** + * @brief A container for storing the partially evaluated multivariates produced by sumcheck. + */ + class PartiallyEvaluatedMultivariates : public AllEntities { + + public: + PartiallyEvaluatedMultivariates() = default; + PartiallyEvaluatedMultivariates(const size_t circuit_size) + { + // Storage is only needed after the first partial evaluation, hence polynomials of size (n / 2) + for (auto& poly : this->get_all()) { + poly = Polynomial(circuit_size / 2); + } + } + }; + /** + * @brief A container for univariates used during Protogalaxy folding and sumcheck. + * @details During folding and sumcheck, the prover evaluates the relations on these univariates. + */ + template using ProverUnivariates = AllEntities>; + + /** + * @brief A container for univariates produced during the hot loop in sumcheck. + */ + using ExtendedEdges = ProverUnivariates; + + /** + * @brief A container for the witness commitments. + */ + + using WitnessCommitments = WitnessEntities; + + /** + * @brief A container for commitment labels. + * @note It's debatable whether this should inherit from AllEntities. since most entries are not strictly needed. It + * has, however, been useful during debugging to have these labels available. + * + */ + class CommitmentLabels : public AllEntities { + private: + using Base = AllEntities; + + public: + CommitmentLabels() + : AllEntities() + { + Base::permutation_set_column_1 = "PERMUTATION_SET_COLUMN_1"; + Base::permutation_set_column_2 = "PERMUTATION_SET_COLUMN_2"; + Base::permutation_set_column_3 = "PERMUTATION_SET_COLUMN_3"; + Base::permutation_set_column_4 = "PERMUTATION_SET_COLUMN_4"; + Base::self_permutation_column = "SELF_PERMUTATION_COLUMN"; + Base::tuple_permutation_inverses = "TUPLE_PERMUTATION_INVERSES"; + Base::single_permutation_inverses = "SINGLE_PERMUTATION_INVERSES"; + // The ones beginning with "__" are only used for debugging + Base::lagrange_first = "__LAGRANGE_FIRST"; + Base::enable_tuple_set_permutation = "__ENABLE_SET_PERMUTATION"; + Base::enable_single_column_permutation = "__ENABLE_SINGLE_COLUMN_PERMUTATION"; + Base::enable_first_set_permutation = "__ENABLE_FIRST_SET_PERMUTATION"; + Base::enable_second_set_permutation = "__ENABLE_SECOND_SET_PERMUTATION"; + }; + }; + + class VerifierCommitments : public AllEntities { + + public: + VerifierCommitments(const std::shared_ptr& verification_key) + { + lagrange_first = verification_key->lagrange_first; + enable_tuple_set_permutation = verification_key->enable_tuple_set_permutation; + enable_single_column_permutation = verification_key->enable_single_column_permutation; + enable_first_set_permutation = verification_key->enable_first_set_permutation; + enable_second_set_permutation = verification_key->enable_second_set_permutation; + } + }; + + /** + * @brief Derived class that defines proof structure for ECCVM proofs, as well as supporting functions. + * + */ + class Transcript : public BaseTranscript { + public: + uint32_t circuit_size; + Commitment column_0_comm; + Commitment column_1_comm; + Commitment permutation_inverses_comm; + std::vector> sumcheck_univariates; + std::array sumcheck_evaluations; + + std::vector zm_cq_comms; + Commitment zm_cq_comm; + Commitment zm_pi_comm; + + Transcript() = default; + + Transcript(const std::vector& proof) + : BaseTranscript(proof) + {} + + void deserialize_full_transcript() + { + // TODO. Codepath is dead for now, because there is no composer + abort(); + // take current proof and put them into the struct + } + + void serialize_full_transcript() + { + // TODO. Codepath is dead for now, because there is no composer + abort(); + } + }; +}; + +// NOLINTEND(cppcoreguidelines-avoid-const-or-ref-data-members) + +} // namespace flavor +namespace sumcheck { + +DECLARE_IMPLEMENTATIONS_FOR_ALL_SETTINGS(GenericPermutationRelationImpl, flavor::ToyAVM) + +} // namespace sumcheck +} // namespace proof_system::honk diff --git a/barretenberg/cpp/src/barretenberg/honk/proof_system/lookup_library.hpp b/barretenberg/cpp/src/barretenberg/honk/proof_system/logderivative_library.hpp similarity index 58% rename from barretenberg/cpp/src/barretenberg/honk/proof_system/lookup_library.hpp rename to barretenberg/cpp/src/barretenberg/honk/proof_system/logderivative_library.hpp index 820bc2907a5..4a86cf74075 100644 --- a/barretenberg/cpp/src/barretenberg/honk/proof_system/lookup_library.hpp +++ b/barretenberg/cpp/src/barretenberg/honk/proof_system/logderivative_library.hpp @@ -1,7 +1,7 @@ #pragma once #include -namespace proof_system::honk::lookup_library { +namespace proof_system::honk::logderivative_library { /** * @brief Compute the inverse polynomial I(X) required for logderivative lookups @@ -29,12 +29,12 @@ void compute_logderivative_inverse(Polynomials& polynomials, auto& relation_para using Accumulator = typename Relation::ValueAccumulator0; constexpr size_t READ_TERMS = Relation::READ_TERMS; constexpr size_t WRITE_TERMS = Relation::WRITE_TERMS; - auto& inverse_polynomial = polynomials.lookup_inverses; auto lookup_relation = Relation(); + auto& inverse_polynomial = lookup_relation.template get_inverse_polynomial(polynomials); for (size_t i = 0; i < circuit_size; ++i) { auto row = polynomials.get_row(i); - bool has_inverse = lookup_relation.lookup_exists_at_row(row); + bool has_inverse = lookup_relation.operation_exists_at_row(row); if (!has_inverse) { continue; } @@ -97,7 +97,7 @@ void accumulate_logderivative_lookup_subrelation_contributions(ContainerOverSubr using Accumulator = typename std::tuple_element_t<0, ContainerOverSubrelations>; using View = typename Accumulator::View; - auto lookup_inverses = View(in.lookup_inverses); + auto lookup_inverses = View(lookup_relation.template get_inverse_polynomial(in)); constexpr size_t NUM_TOTAL_TERMS = READ_TERMS + WRITE_TERMS; std::array lookup_terms; @@ -153,4 +153,98 @@ void accumulate_logderivative_lookup_subrelation_contributions(ContainerOverSubr }); } -} // namespace proof_system::honk::lookup_library \ No newline at end of file +/** + * @brief Compute generic log-derivative set permutation subrelation accumulation + * @details The generic log-derivative lookup relation consistes of two subrelations. The first demonstrates that the + * inverse polynomial I, defined via I = 1/[(read_term) * (write_term)], has been computed correctly. The second + * establishes the correctness of the permutation itself based on the log-derivative argument. Note that the + * latter subrelation is "linearly dependent" in the sense that it establishes that a sum across all rows of the + * execution trace is zero, rather than that some expression holds independently at each row. Accordingly, this + * subrelation is not multiplied by a scaling factor at each accumulation step. The subrelation expressions are + * respectively: + * + * I * (read_term) * (write_term) - q_{permutation_enabler} = 0 + * + * \sum_{i=0}^{n-1} [q_{write_enabler} * I * write_term + q_{read_enabler} * I * read_term] = 0 + * + * The explicit expressions for read_term and write_term are dependent upon the particular structure of the permutation + * being performed and methods for computing them must be defined in the corresponding relation class. The entities + * which are used to determine the use of permutation (is it enabled, is the first "read" set enabled, is the second + * "write" set enabled) must be defined in the relation class. + * + * @tparam FF + * @tparam Relation + * @tparam ContainerOverSubrelations + * @tparam AllEntities + * @tparam Parameters + * @param accumulator + * @param in + * @param params + * @param scaling_factor + */ +template +void accumulate_logderivative_permutation_subrelation_contributions(ContainerOverSubrelations& accumulator, + const AllEntities& in, + const Parameters& params, + const FF& scaling_factor) +{ + constexpr size_t READ_TERMS = Relation::READ_TERMS; + constexpr size_t WRITE_TERMS = Relation::WRITE_TERMS; + + // For now we only do simple permutations over tuples with 1 read and 1 write term + static_assert(READ_TERMS == 1); + static_assert(WRITE_TERMS == 1); + + auto permutation_relation = Relation(); + + using Accumulator = typename std::tuple_element_t<0, ContainerOverSubrelations>; + using View = typename Accumulator::View; + + auto permutation_inverses = View(permutation_relation.template get_inverse_polynomial(in)); + + constexpr size_t NUM_TOTAL_TERMS = 2; + std::array permutation_terms; + std::array denominator_accumulator; + + // The permutation relation = 1 / read_term - 1 / write_term + // To get the inverses (1 / read_term), (1 / write_term), we have a commitment to the product ofinver ses + // i.e. permutation_inverses = (1 / read_term) * (1 / write_term) + // The purpose of this next section is to derive individual inverse terms using `permutation_inverses` + // i.e. (1 / read_term) = permutation_inverses * write_term + // (1 / write_term) = permutation_inverses * read_term + permutation_terms[0] = permutation_relation.template compute_read_term(in, params); + permutation_terms[1] = permutation_relation.template compute_write_term(in, params); + + barretenberg::constexpr_for<0, NUM_TOTAL_TERMS, 1>( + [&]() { denominator_accumulator[i] = permutation_terms[i]; }); + + barretenberg::constexpr_for<0, NUM_TOTAL_TERMS - 1, 1>( + [&]() { denominator_accumulator[i + 1] *= denominator_accumulator[i]; }); + + auto inverse_accumulator = Accumulator(permutation_inverses); // denominator_accumulator[NUM_TOTAL_TERMS - 1]; + + const auto inverse_exists = permutation_relation.template compute_inverse_exists(in); + + // Note: the lookup_inverses are computed so that the value is 0 if !inverse_exists + std::get<0>(accumulator) += + (denominator_accumulator[NUM_TOTAL_TERMS - 1] * permutation_inverses - inverse_exists) * scaling_factor; + + // After this algo, total degree of denominator_accumulator = NUM_TOTAL_TERMS + for (size_t i = 0; i < NUM_TOTAL_TERMS - 1; ++i) { + denominator_accumulator[NUM_TOTAL_TERMS - 1 - i] = + denominator_accumulator[NUM_TOTAL_TERMS - 2 - i] * inverse_accumulator; + inverse_accumulator = inverse_accumulator * permutation_terms[NUM_TOTAL_TERMS - 1 - i]; + } + denominator_accumulator[0] = inverse_accumulator; + + // each predicate is degree-1 + // degree of relation at this point = NUM_TOTAL_TERMS + 1 + std::get<1>(accumulator) += + permutation_relation.template compute_read_term_predicate(in) * denominator_accumulator[0]; + + // each predicate is degree-1 + // degree of relation = NUM_TOTAL_TERMS + 1 + std::get<1>(accumulator) -= + permutation_relation.template compute_write_term_predicate(in) * denominator_accumulator[1]; +} +} // namespace proof_system::honk::logderivative_library \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/eccvm/eccvm_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/eccvm/eccvm_circuit_builder.hpp index 4abbd5bc91f..bdcbd4fa4ad 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/eccvm/eccvm_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/eccvm/eccvm_circuit_builder.hpp @@ -7,7 +7,7 @@ #include "barretenberg/ecc/curves/bn254/fr.hpp" #include "barretenberg/ecc/curves/grumpkin/grumpkin.hpp" #include "barretenberg/flavor/ecc_vm.hpp" -#include "barretenberg/honk/proof_system/lookup_library.hpp" +#include "barretenberg/honk/proof_system/logderivative_library.hpp" #include "barretenberg/honk/proof_system/permutation_library.hpp" #include "barretenberg/proof_system/op_queue/ecc_op_queue.hpp" #include "barretenberg/relations/relation_parameters.hpp" @@ -505,9 +505,9 @@ template class ECCVMCircuitBuilder { auto polynomials = compute_polynomials(); const size_t num_rows = polynomials.get_polynomial_size(); - proof_system::honk::lookup_library::compute_logderivative_inverse>( - polynomials, params, num_rows); + proof_system::honk::logderivative_library:: + compute_logderivative_inverse>( + polynomials, params, num_rows); honk::permutation_library::compute_permutation_grand_product>( num_rows, polynomials, params); diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/toy_avm/toy_avm_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/toy_avm/toy_avm_circuit_builder.hpp new file mode 100644 index 00000000000..659187b4131 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/toy_avm/toy_avm_circuit_builder.hpp @@ -0,0 +1,163 @@ +/** + * @file avm_template_circuit_builder.hpp + * @author Rumata888 + * @brief A circuit builder for the AVM toy version used to showcase permutation and lookup mechanisms for PIL + * + */ +#pragma once + +#include "barretenberg/common/constexpr_utils.hpp" +#include "barretenberg/ecc/curves/bn254/fr.hpp" +#include "barretenberg/flavor/toy_avm.hpp" +#include "barretenberg/honk/proof_system/logderivative_library.hpp" +#include "barretenberg/relations/relation_parameters.hpp" +#include "barretenberg/relations/toy_avm/generic_permutation_relation.hpp" + +namespace proof_system { + +/** + * @brief Circuit builder for the ToyAVM that is used to explain generic permutation settings + * + * @tparam Flavor + */ +template class ToyAVMCircuitBuilder { + public: + using FF = typename Flavor::FF; + using Polynomial = typename Flavor::Polynomial; + + static constexpr size_t NUM_POLYNOMIALS = Flavor::NUM_ALL_ENTITIES; + static constexpr size_t NUM_WIRES = Flavor::NUM_WIRES; + + using AllPolynomials = typename Flavor::AllPolynomials; + size_t num_gates = 0; + std::array, NUM_WIRES> wires; + ToyAVMCircuitBuilder() = default; + + void add_row(const std::array row) + { + for (size_t i = 0; i < NUM_WIRES; i++) { + wires[i].emplace_back(row[i]); + } + num_gates = wires[0].size(); + } + + /** + * @brief Compute the AVM Template flavor polynomial data required to generate a proof + * + * @return AllPolynomials + */ + AllPolynomials compute_polynomials() + { + + const auto num_gates_log2 = static_cast(numeric::get_msb64(num_gates)); + size_t num_gates_pow2 = 1UL << (num_gates_log2 + (1UL << num_gates_log2 == num_gates ? 0 : 1)); + + AllPolynomials polys; + for (auto& poly : polys.get_all()) { + poly = Polynomial(num_gates_pow2); + } + + polys.lagrange_first[0] = 1; + + for (size_t i = 0; i < num_gates; ++i) { + // Fill out the witness polynomials + polys.permutation_set_column_1[i] = wires[0][i]; + polys.permutation_set_column_2[i] = wires[1][i]; + polys.permutation_set_column_3[i] = wires[2][i]; + polys.permutation_set_column_4[i] = wires[3][i]; + polys.self_permutation_column[i] = wires[4][i]; + // By default the permutation is over all rows where we place data + polys.enable_tuple_set_permutation[i] = 1; + // The same column permutation alternates between even and odd values + polys.enable_single_column_permutation[i] = 1; + polys.enable_first_set_permutation[i] = i & 1; + polys.enable_second_set_permutation[i] = 1 - (i & 1); + } + return polys; + } + + /** + * @brief Check that the circuit is correct (proof should work) + * + */ + bool check_circuit() + { + // using FirstPermutationRelation = typename std::tuple_element_t<0, Flavor::Relations>; + // For now only gamma and beta are used + const FF gamma = FF::random_element(); + const FF beta = FF::random_element(); + proof_system::RelationParameters params{ + .eta = 0, + .beta = beta, + .gamma = gamma, + .public_input_delta = 0, + .lookup_grand_product_delta = 0, + .beta_sqr = 0, + .beta_cube = 0, + .eccvm_set_permutation_delta = 0, + }; + + // Compute polynomial values + auto polynomials = compute_polynomials(); + const size_t num_rows = polynomials.get_polynomial_size(); + + // Check the tuple permutation relation + proof_system::honk::logderivative_library::compute_logderivative_inverse< + Flavor, + honk::sumcheck::GenericPermutationRelation>( + polynomials, params, num_rows); + + using PermutationRelation = + honk::sumcheck::GenericPermutationRelation; + typename honk::sumcheck::GenericPermutationRelation::SumcheckArrayOfValuesOverSubrelations + permutation_result; + for (auto& r : permutation_result) { + r = 0; + } + for (size_t i = 0; i < num_rows; ++i) { + PermutationRelation::accumulate(permutation_result, polynomials.get_row(i), params, 1); + } + for (auto r : permutation_result) { + if (r != 0) { + info("Tuple GenericPermutationRelation failed."); + return false; + } + } + // Check the single permutation relation + proof_system::honk::logderivative_library::compute_logderivative_inverse< + Flavor, + honk::sumcheck::GenericPermutationRelation>( + polynomials, params, num_rows); + + using SameWirePermutationRelation = + honk::sumcheck::GenericPermutationRelation; + typename honk::sumcheck::GenericPermutationRelation::SumcheckArrayOfValuesOverSubrelations + second_permutation_result; + for (auto& r : second_permutation_result) { + r = 0; + } + for (size_t i = 0; i < num_rows; ++i) { + SameWirePermutationRelation::accumulate(second_permutation_result, polynomials.get_row(i), params, 1); + } + for (auto r : second_permutation_result) { + if (r != 0) { + info("Same wire GenericPermutationRelation failed."); + return false; + } + } + return true; + } + + [[nodiscard]] size_t get_num_gates() const { return num_gates; } + + [[nodiscard]] size_t get_circuit_subgroup_size(const size_t num_rows) const + { + + const auto num_rows_log2 = static_cast(numeric::get_msb64(num_rows)); + size_t num_rows_pow2 = 1UL << (num_rows_log2 + (1UL << num_rows_log2 == num_rows ? 0 : 1)); + return num_rows_pow2; + } +}; +} // namespace proof_system diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/toy_avm/toy_avm_circuit_builder.test.cpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/toy_avm/toy_avm_circuit_builder.test.cpp new file mode 100644 index 00000000000..62b2e4d83c3 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/toy_avm/toy_avm_circuit_builder.test.cpp @@ -0,0 +1,70 @@ +#include "toy_avm_circuit_builder.hpp" +#include "barretenberg/crypto/generators/generator_data.hpp" +#include + +using namespace barretenberg; + +namespace { +auto& engine = numeric::random::get_debug_engine(); +} + +namespace toy_avm_circuit_builder_tests { + +/** + * @brief A test explaining the work of the permutations in Toy AVM + * + */ +TEST(ToyAVMCircuitBuilder, BaseCase) +{ + + using FF = proof_system::honk::flavor::ToyAVM::FF; + const size_t circuit_size = 16; + proof_system::ToyAVMCircuitBuilder circuit_builder; + + // Sample 2*16 random elements for the tuple permutation example + std::vector column_0; + std::vector column_1; + for (size_t i = 0; i < circuit_size; i++) { + column_0.emplace_back(FF::random_element()); + column_1.emplace_back(FF::random_element()); + } + + // Sample 8 random elements for the single column permutation + std::vector column_2; + for (size_t i = 0; i < circuit_size / 2; i++) { + column_2.emplace_back(FF::random_element()); + } + + for (size_t i = 0; i < circuit_size; i++) { + // We put the same tuple of values in the first 2 wires and in the next 2 to at different rows + // We also put the same value in the self_permutation column in 2 consecutive rows + circuit_builder.add_row({ column_0[i], column_1[i], column_0[15 - i], column_1[15 - i], column_2[i / 2] }); + } + + // Test that permutations with correct values work + bool result = circuit_builder.check_circuit(); + EXPECT_EQ(result, true); + + // Store value temporarily + FF tmp = circuit_builder.wires[0][5]; + + // Replace one of the values in a tuple permutation column with a random one, breaking the permutation + circuit_builder.wires[0][5] = FF::random_element(); + + // Check that it fails + result = circuit_builder.check_circuit(); + EXPECT_EQ(result, false); + + // Restore value + circuit_builder.wires[0][5] = tmp; + + // Check circuit passes + result = circuit_builder.check_circuit(); + EXPECT_EQ(result, true); + + // Break single-column permutation + circuit_builder.wires[circuit_builder.wires.size() - 1][0] = FF::random_element(); + result = circuit_builder.check_circuit(); + EXPECT_EQ(result, false); +} +} // namespace toy_avm_circuit_builder_tests \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/relations/databus_lookup_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/databus_lookup_relation.hpp index da659a321e9..5508a72c292 100644 --- a/barretenberg/cpp/src/barretenberg/relations/databus_lookup_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/databus_lookup_relation.hpp @@ -3,7 +3,7 @@ #include #include "barretenberg/common/constexpr_utils.hpp" -#include "barretenberg/honk/proof_system/lookup_library.hpp" +#include "barretenberg/honk/proof_system/logderivative_library.hpp" #include "barretenberg/polynomials/polynomial.hpp" #include "barretenberg/polynomials/univariate.hpp" #include "barretenberg/relations/relation_types.hpp" @@ -37,11 +37,19 @@ template class DatabusLookupRelationImpl { * @return true * @return false */ - template static bool lookup_exists_at_row(const AllValues& row) + template static bool operation_exists_at_row(const AllValues& row) { return (row.q_busread == 1 || row.calldata_read_counts > 0); } + /** + * @brief Get the lookup inverse polynomial + * + * @tparam AllEntities + * @param in + * @return auto& + */ + template static auto& get_inverse_polynomial(AllEntities& in) { return in.lookup_inverses; } /** * @brief Compute the Accumulator whose values indicate whether the inverse is computed or not * @details This is needed for efficiency since we don't need to compute the inverse unless the log derivative @@ -154,7 +162,7 @@ template class DatabusLookupRelationImpl { /** * @brief Accumulate the contribution from two surelations for the log derivative databus lookup argument - * @details See lookup_library.hpp for details of the generic log-derivative lookup argument + * @details See logderivative_library.hpp for details of the generic log-derivative lookup argument * * @param accumulator transformed to `evals + C(in(X)...)*scaling_factor` * @param in an std::array containing the fully extended Accumulator edges. @@ -167,9 +175,9 @@ template class DatabusLookupRelationImpl { const Parameters& params, const FF& scaling_factor) { - honk::lookup_library::accumulate_logderivative_lookup_subrelation_contributions>( - accumulator, in, params, scaling_factor); + honk::logderivative_library:: + accumulate_logderivative_lookup_subrelation_contributions>( + accumulator, in, params, scaling_factor); } }; diff --git a/barretenberg/cpp/src/barretenberg/relations/ecc_vm/ecc_lookup_relation.cpp b/barretenberg/cpp/src/barretenberg/relations/ecc_vm/ecc_lookup_relation.cpp index 1daf3469bc7..e52e297cfa4 100644 --- a/barretenberg/cpp/src/barretenberg/relations/ecc_vm/ecc_lookup_relation.cpp +++ b/barretenberg/cpp/src/barretenberg/relations/ecc_vm/ecc_lookup_relation.cpp @@ -1,6 +1,6 @@ #include "barretenberg/flavor/ecc_vm.hpp" #include "barretenberg/flavor/relation_definitions_fwd.hpp" -#include "barretenberg/honk/proof_system/lookup_library.hpp" +#include "barretenberg/honk/proof_system/logderivative_library.hpp" #include "ecc_msm_relation.hpp" namespace proof_system::honk::sumcheck { @@ -25,7 +25,7 @@ void ECCVMLookupRelationImpl::accumulate(ContainerOverSubrelations& accumula const Parameters& params, const FF& scaling_factor) { - lookup_library::accumulate_logderivative_lookup_subrelation_contributions>( + logderivative_library::accumulate_logderivative_lookup_subrelation_contributions>( accumulator, in, params, scaling_factor); } diff --git a/barretenberg/cpp/src/barretenberg/relations/ecc_vm/ecc_lookup_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/ecc_vm/ecc_lookup_relation.hpp index 35af59f7490..aa3afffc87f 100644 --- a/barretenberg/cpp/src/barretenberg/relations/ecc_vm/ecc_lookup_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/ecc_vm/ecc_lookup_relation.hpp @@ -24,12 +24,21 @@ template class ECCVMLookupRelationImpl { static constexpr std::array SUBRELATION_LINEARLY_INDEPENDENT = { true, false }; - template static bool lookup_exists_at_row(const AllValues& row) + template static bool operation_exists_at_row(const AllValues& row) { return (row.msm_add == 1) || (row.msm_skew == 1) || (row.precompute_select == 1); } + /** + * @brief Get the inverse lookup polynomial + * + * @tparam AllEntities + * @param in + * @return auto& + */ + template static auto& get_inverse_polynomial(AllEntities& in) { return in.lookup_inverses; } + template static Accumulator compute_inverse_exists(const AllEntities& in) { diff --git a/barretenberg/cpp/src/barretenberg/relations/toy_avm/generic_permutation_relation.cpp b/barretenberg/cpp/src/barretenberg/relations/toy_avm/generic_permutation_relation.cpp new file mode 100644 index 00000000000..1822c388c4e --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/relations/toy_avm/generic_permutation_relation.cpp @@ -0,0 +1,34 @@ +#include "generic_permutation_relation.hpp" +#include "barretenberg/flavor/relation_definitions_fwd.hpp" +#include "barretenberg/flavor/toy_avm.hpp" +#include "barretenberg/honk/proof_system/logderivative_library.hpp" +#include "relation_definer.hpp" + +namespace proof_system::honk::sumcheck { + +/** + * @brief Expression for generic log-derivative-based set permutation. + * @param accumulator transformed to `evals + C(in(X)...)*scaling_factor` + * @param in an std::array containing the fully extended Accumulator edges. + * @param relation_params contains beta, gamma, and public_input_delta, .... + * @param scaling_factor optional term to scale the evaluation before adding to evals. + */ +template +template +void GenericPermutationRelationImpl::accumulate(ContainerOverSubrelations& accumulator, + const AllEntities& in, + const Parameters& params, + const FF& scaling_factor) +{ + logderivative_library::accumulate_logderivative_permutation_subrelation_contributions< + FF, + GenericPermutationRelationImpl>(accumulator, in, params, scaling_factor); +} + +// template class GenericPermutationRelationImpl; +// template +// using GenericPermutationRelationExampleSettingsImpl = GenericPermutationRelationImpl; DEFINE_SUMCHECK_RELATION_CLASS(GenericPermutationRelationExampleSettingsImpl, flavor::AVMTemplate); + +DEFINE_IMPLEMENTATIONS_FOR_ALL_SETTINGS(GenericPermutationRelationImpl, flavor::ToyAVM); +} // namespace proof_system::honk::sumcheck diff --git a/barretenberg/cpp/src/barretenberg/relations/toy_avm/generic_permutation_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/toy_avm/generic_permutation_relation.hpp new file mode 100644 index 00000000000..d4246a423f5 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/relations/toy_avm/generic_permutation_relation.hpp @@ -0,0 +1,210 @@ +/** + * @file generic_permutation_relation.hpp + * @author Rumata888 + * @brief This file contains the template for the generic permutation that can be specialized to enforce various + * permutations (for explanation on how to define them, see "relation_definer.hpp") + * + */ +#pragma once +#include +#include + +#include "barretenberg/common/constexpr_utils.hpp" +#include "barretenberg/polynomials/polynomial.hpp" +#include "barretenberg/polynomials/univariate.hpp" +#include "barretenberg/relations/relation_types.hpp" + +namespace proof_system::honk::sumcheck { +/** + * @brief Specifies positions of elements in the tuple of entities received from methods in the Settings class + * + */ +enum GenericPermutationSettingIndices { + INVERSE_POLYNOMIAL_INDEX, /* The index of the inverse polynomial*/ + ENABLE_INVERSE_CORRECTNESS_CHECK_POLYNOMIAL_INDEX, /* The index of the polynomial enabling first subrelation*/ + FIRST_PERMUTATION_SET_ENABLE_POLYNOMIAL_INDEX, /* The index of the polynomial that adds an element from the first + set to the sum*/ + SECOND_PERMUTATION_SET_ENABLE_POLYNOMIAL_INDEX, /* The index of the polynomial that adds an element from the second + set to the sum*/ + + PERMUTATION_SETS_START_POLYNOMIAL_INDEX, /* The starting index of the polynomials that are used in the permutation + sets*/ +}; + +template class GenericPermutationRelationImpl { + public: + using FF = FF_; + // Read and write terms counts should stay set to 1 unless we want to permute several columns at once as accumulated + // sets (not as tuples). + static constexpr size_t READ_TERMS = 1; + static constexpr size_t WRITE_TERMS = 1; + // 1 + polynomial degree of this relation + static constexpr size_t LENGTH = READ_TERMS + WRITE_TERMS + 3; // 5 + + static constexpr std::array SUBRELATION_PARTIAL_LENGTHS{ + LENGTH, // inverse polynomial correctness sub-relation + LENGTH // log-derived terms subrelation + }; + + /** + * @brief We apply the power polynomial only to the first subrelation + * + *@details The first subrelation establishes correspondence between the inverse polynomial elements and the terms. + *The second relation computes the inverses of individual terms, which are then summed up with sumcheck + * + */ + static constexpr std::array SUBRELATION_LINEARLY_INDEPENDENT = { true, false }; + + /** + * @brief Check if we need to compute the inverse polynomial element value for this row + * @details This proxies to a method in the Settings class + * + * @param row All values at row + */ + template static bool operation_exists_at_row(const AllValues& row) + + { + return Settings::inverse_polynomial_is_computed_at_row(row); + } + + /** + * @brief Get the inverse permutation polynomial (needed to compute its value) + * + */ + template static auto& get_inverse_polynomial(AllEntities& in) + { + // WIRE containing the inverse of the product of terms at this row. Used to reconstruct individual inversed + // terms + return std::get(Settings::get_nonconst_entities(in)); + } + + /** + * @brief Get selector/wire switching on(1) or off(0) inverse computation + * + */ + template + static Accumulator compute_inverse_exists(const AllEntities& in) + { + using View = typename Accumulator::View; + + // WIRE/SELECTOR enabling the permutation used in the sumcheck computation. This affects the first subrelation + return Accumulator( + View(std::get(Settings::get_const_entities(in)))); + } + + /** + * @brief Compute if the value from the first set exists in this row + * + * @tparam read_index Kept for compatibility with lookups, behavior doesn't change + */ + template + static Accumulator compute_read_term_predicate(const AllEntities& in) + + { + static_assert(read_index < WRITE_TERMS); + using View = typename Accumulator::View; + + // The selector/wire value that determines that an element from the first set needs to be included. Can be + // different from the wire used in the write part. + return Accumulator( + View(std::get(Settings::get_const_entities(in)))); + } + + /** + * @brief Compute if the value from the second set exists in this row + * + * @tparam write_index Kept for compatibility with lookups, behavior doesn't change + */ + template + static Accumulator compute_write_term_predicate(const AllEntities& in) + { + static_assert(write_index < WRITE_TERMS); + using View = typename Accumulator::View; + + // The selector/wire value that determines that an element from the second set needs to be included. Can be + // different from the wire used in the read part. + return Accumulator( + View(std::get(Settings::get_const_entities(in)))); + } + + /** + * @brief Compute the value of a single item in the set + * + * @details Computes the polynomial \gamma + \sum_{i=0}^{num_columns}(column_i*\beta^i), so the tuple of columns is + * in the first set + * + * @tparam read_index Kept for compatibility with lookups, behavior doesn't change + * + * @param params Used for beta and gamma + */ + template + static Accumulator compute_read_term(const AllEntities& in, const Parameters& params) + { + using View = typename Accumulator::View; + + static_assert(read_index < READ_TERMS); + + // Retrieve all polynomials used + const auto all_polynomials = Settings::get_const_entities(in); + + auto result = Accumulator(0); + + // Iterate over tuple and sum as a polynomial over beta + barretenberg::constexpr_for( + [&]() { result = result * params.beta + View(std::get(all_polynomials)); }); + + const auto& gamma = params.gamma; + return result + gamma; + } + + /** + * @brief Compute the value of a single item in the set + * + * @details Computes the polynomial \gamma + \sum_{i=0}^{num_columns}(column_i*\beta^i), so the tuple of columns is + * in the second set + * + * @tparam write_index Kept for compatibility with lookups, behavior doesn't change + * + * @param params Used for beta and gamma + */ + template + static Accumulator compute_write_term(const AllEntities& in, const Parameters& params) + { + using View = typename Accumulator::View; + + static_assert(write_index < WRITE_TERMS); + + // Get all used entities + const auto& used_entities = Settings::get_const_entities(in); + + auto result = Accumulator(0); + // Iterate over tuple and sum as a polynomial over beta + barretenberg::constexpr_for( + [&]() { result = result * params.beta + View(std::get(used_entities)); }); + + const auto& gamma = params.gamma; + return result + gamma; + } + + /** + * @brief Expression for generic log-derivative-based set permutation. + * @param accumulator transformed to `evals + C(in(X)...)*scaling_factor` + * @param in an std::array containing the fully extended Accumulator edges. + * @param relation_params contains beta, gamma, and public_input_delta, .... + * @param scaling_factor optional term to scale the evaluation before adding to evals. + */ + template + static void accumulate(ContainerOverSubrelations& accumulator, + const AllEntities& in, + const Parameters& params, + const FF& scaling_factor); +}; + +template +using GenericPermutationRelation = Relation>; + +} // namespace proof_system::honk::sumcheck diff --git a/barretenberg/cpp/src/barretenberg/relations/toy_avm/relation_definer.hpp b/barretenberg/cpp/src/barretenberg/relations/toy_avm/relation_definer.hpp new file mode 100644 index 00000000000..4771c1260b7 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/relations/toy_avm/relation_definer.hpp @@ -0,0 +1,213 @@ +/** + * @file relation_definer.hpp + * @author Rumata888 + * @brief This file contains settings for the General Permutation Relation implementations and (in the future) Lookup + * implementations + * + */ +#pragma once +#include +#include +namespace proof_system::honk::sumcheck { + +/** + * @brief This class contains an example of how to set PermutationSettings classes used by the + * GenericPermutationRelationImpl class to specify a concrete permutation + * + * @details To create your own permutation: + * 1) Create a copy of this class and rename it + * 2) Update all the values with the ones needed for your permutation + * 3) Update "DECLARE_IMPLEMENTATIONS_FOR_ALL_SETTINGS" and "DEFINE_IMPLEMENTATIONS_FOR_ALL_SETTINGS" to include the new + * settings + * 4) Add the relation with the chosen settings to Relations in the flavor (for example,"` + * using Relations = std::tuple>;)` + * + */ +class ExampleTuplePermutationSettings { + public: + // This constant defines how many columns are bundled together to form each set. For example, in this case we are + // bundling tuples of (permutation_set_column_1, permutation_set_column_2) to be a permutation of + // (permutation_set_column_3,permutation_set_column_4). As the tuple has 2 elements, set the value to 2 + constexpr static size_t COLUMNS_PER_SET = 2; + + /** + * @brief If this method returns true on a row of values, then the inverse polynomial at this index. Otherwise the + * value needs to be set to zero. + * + * @details If this is true then permutation takes place in this row + * + */ + template static inline bool inverse_polynomial_is_computed_at_row(const AllEntities& in) + { + return (in.enable_tuple_set_permutation == 1); + } + + /** + * @brief Get all the entities for the permutation when we don't need to update them + * + * @details The entities are returned as a tuple of references in the following order: + * - The entity/polynomial used to store the product of the inverse values + * - The entity/polynomial that switches on the subrelation of the permutation relation that ensures correctness of + * the inverse polynomial + * - The entity/polynomial that enables adding a tuple-generated value from the first set to the logderivative sum + * subrelation + * - The entity/polynomial that enables adding a tuple-generated value from the second set to the logderivative sum + * subrelation + * - A sequence of COLUMNS_PER_SET entities/polynomials that represent the first set (N.B. ORDER IS IMPORTANT!) + * - A sequence of COLUMNS_PER_SET entities/polynomials that represent the second set (N.B. ORDER IS IMPORTANT!) + * + * @return All the entities needed for the permutation + */ + template static inline auto get_const_entities(const AllEntities& in) + { + + return std::forward_as_tuple( + in.tuple_permutation_inverses, /* The polynomial containing the inverse product*/ + in.enable_tuple_set_permutation, /* The polynomial enabling the product check subrelation */ + in.enable_tuple_set_permutation, /* Enables adding first set to the sum */ + in.enable_tuple_set_permutation, /* Enables adding second set to the sum */ + in.permutation_set_column_3, /* The first entry in the first set tuple */ + in.permutation_set_column_4, /* The second entry in the first set tuple */ + in.permutation_set_column_1, /* The first entry in the second set tuple */ + in.permutation_set_column_2); /* The second entry in the second set tuple */ + } + + /** + * @brief Get all the entities for the permutation when need to update them + * + * @details The entities are returned as a tuple of references in the following order: + * - The entity/polynomial used to store the product of the inverse values + * - The entity/polynomial that switches on the subrelation of the permutation relation that ensures correctness of + * the inverse polynomial + * - The entity/polynomial that enables adding a tuple-generated value from the first set to the logderivative sum + * subrelation + * - The entity/polynomial that enables adding a tuple-generated value from the second set to the logderivative sum + * subrelation + * - A sequence of COLUMNS_PER_SET entities/polynomials that represent the first set (N.B. ORDER IS IMPORTANT!) + * - A sequence of COLUMNS_PER_SET entities/polynomials that represent the second set (N.B. ORDER IS IMPORTANT!) + * + * @return All the entities needed for the permutation + */ + template static inline auto get_nonconst_entities(AllEntities& in) + { + return std::forward_as_tuple( + in.tuple_permutation_inverses, /* The polynomial containing the inverse product*/ + in.enable_tuple_set_permutation, /* The polynomial enabling the product check subrelation */ + in.enable_tuple_set_permutation, /* Enables adding first set to the sum */ + in.enable_tuple_set_permutation, /* Enables adding second set to the sum */ + in.permutation_set_column_3, /* The first entry in the first set tuple */ + in.permutation_set_column_4, /* The second entry in the first set tuple */ + in.permutation_set_column_1, /* The first entry in the second set tuple */ + in.permutation_set_column_2); /* The second entry in the second set tuple */ + } +}; + +/** + * @brief This class contains an example of how to set PermutationSettings classes used by the + * GenericPermutationRelationImpl class to specify a concrete permutation + * + * @details To create your own permutation: + * 1) Create a copy of this class and rename it + * 2) Update all the values with the ones needed for your permutation + * 3) Update "DECLARE_IMPLEMENTATIONS_FOR_ALL_SETTINGS" and "DEFINE_IMPLEMENTATIONS_FOR_ALL_SETTINGS" to include the new + * settings + * 4) Add the relation with the chosen settings to Relations in the flavor (for example,"` + * using Relations = std::tuple>;)` + * + */ +class ExampleSameWirePermutationSettings { + public: + // This constant defines how many columns are bundled together to form each set. For example, in this case we are + // permuting entries in the column with itself (self_permutation_column), so we choose just one + constexpr static size_t COLUMNS_PER_SET = 1; + + /** + * @brief If this method returns true on a row of values, then the inverse polynomial at this index. Otherwise the + * value needs to be set to zero. + * + * @details If this is true then permutation takes place in this row + * + */ + template static inline bool inverse_polynomial_is_computed_at_row(const AllEntities& in) + { + return (in.enable_single_column_permutation == 1); + } + + /** + * @brief Get all the entities for the permutation when we don't need to update them + * + * @details The entities are returned as a tuple of references in the following order: + * - The entity/polynomial used to store the product of the inverse values + * - The entity/polynomial that switches on the subrelation of the permutation relation that ensures correctness of + * the inverse polynomial + * - The entity/polynomial that enables adding a tuple-generated value from the first set to the logderivative sum + * subrelation + * - The entity/polynomial that enables adding a tuple-generated value from the second set to the logderivative sum + * subrelation + * - A sequence of COLUMNS_PER_SET entities/polynomials that represent the first set (N.B. ORDER IS IMPORTANT!) + * - A sequence of COLUMNS_PER_SET entities/polynomials that represent the second set (N.B. ORDER IS IMPORTANT!) + * + * @return All the entities needed for the permutation + */ + template static inline auto get_const_entities(const AllEntities& in) + { + + return std::forward_as_tuple( + in.single_permutation_inverses, /* The polynomial containing the inverse product*/ + in.enable_single_column_permutation, /* The polynomial enabling the product check subrelation */ + in.enable_first_set_permutation, /* Enables adding first set to the sum */ + in.enable_second_set_permutation, /* Enables adding second set to the sum */ + in.self_permutation_column, /* The first set column */ + in.self_permutation_column /* The second set column which in this case is the same as the first set column + */ + ); + } + + /** + * @brief Get all the entities for the permutation when need to update them + * + * @details The entities are returned as a tuple of references in the following order: + * - The entity/polynomial used to store the product of the inverse values + * - The entity/polynomial that switches on the subrelation of the permutation relation that ensures correctness of + * the inverse polynomial + * - The entity/polynomial that enables adding a tuple-generated value from the first set to the logderivative sum + * subrelation + * - The entity/polynomial that enables adding a tuple-generated value from the second set to the logderivative sum + * subrelation + * - A sequence of COLUMNS_PER_SET entities/polynomials that represent the first set (N.B. ORDER IS IMPORTANT!) + * - A sequence of COLUMNS_PER_SET entities/polynomials that represent the second set (N.B. ORDER IS IMPORTANT!) + * + * @return All the entities needed for the permutation + */ + template static inline auto get_nonconst_entities(AllEntities& in) + { + return std::forward_as_tuple( + in.single_permutation_inverses, /* The polynomial containing the inverse product*/ + in.enable_single_column_permutation, /* The polynomial enabling the product check subrelation */ + in.enable_first_set_permutation, /* Enables adding first set to the sum */ + in.enable_second_set_permutation, /* Enables adding second set to the sum */ + in.self_permutation_column, /* The first set column */ + in.self_permutation_column /* The second set column which in this case is the same as the first set column + */ + ); + } +}; + +#define DEFINE_IMPLEMENTATIONS_FOR_SETTINGS(RelationImplementation, flavor, Settings) \ + template class RelationImplementation; \ + template using RelationImplementation##Settings = RelationImplementation; \ + DEFINE_SUMCHECK_RELATION_CLASS(RelationImplementation##Settings, flavor); + +#define DEFINE_IMPLEMENTATIONS_FOR_ALL_SETTINGS(RelationImplementation, flavor) \ + DEFINE_IMPLEMENTATIONS_FOR_SETTINGS(RelationImplementation, flavor, ExampleTuplePermutationSettings); \ + DEFINE_IMPLEMENTATIONS_FOR_SETTINGS(RelationImplementation, flavor, ExampleSameWirePermutationSettings); + +#define DECLARE_IMPLEMENTATIONS_FOR_SETTINGS(RelationImplementation, flavor, Settings) \ + extern template class RelationImplementation; \ + template using RelationImplementation##Settings = RelationImplementation; \ + DECLARE_SUMCHECK_RELATION_CLASS(RelationImplementation##Settings, flavor); + +#define DECLARE_IMPLEMENTATIONS_FOR_ALL_SETTINGS(RelationImplementation, flavor) \ + DECLARE_IMPLEMENTATIONS_FOR_SETTINGS(RelationImplementation, flavor, ExampleTuplePermutationSettings); \ + DECLARE_IMPLEMENTATIONS_FOR_SETTINGS(RelationImplementation, flavor, ExampleSameWirePermutationSettings); +} // namespace proof_system::honk::sumcheck \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.cpp b/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.cpp index 3a62affd0ac..8e1a6ede949 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.cpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.cpp @@ -1,5 +1,5 @@ #include "prover_instance.hpp" -#include "barretenberg/honk/proof_system/lookup_library.hpp" +#include "barretenberg/honk/proof_system/logderivative_library.hpp" #include "barretenberg/proof_system/circuit_builder/ultra_circuit_builder.hpp" #include "barretenberg/proof_system/composer/permutation_lib.hpp" #include "barretenberg/proof_system/library/grand_product_delta.hpp" @@ -453,7 +453,7 @@ void ProverInstance_::compute_logderivative_inverse(FF beta, FF gamma) relation_parameters.gamma = gamma; // Compute permutation and lookup grand product polynomials - lookup_library::compute_logderivative_inverse( + logderivative_library::compute_logderivative_inverse( prover_polynomials, relation_parameters, proving_key->circuit_size); } diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/AvmMini_prover.cpp b/barretenberg/cpp/src/barretenberg/vm/generated/AvmMini_prover.cpp index 913dc121988..b7daa36ddb3 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/AvmMini_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/AvmMini_prover.cpp @@ -3,7 +3,7 @@ #include "AvmMini_prover.hpp" #include "barretenberg/commitment_schemes/claim.hpp" #include "barretenberg/commitment_schemes/commitment_key.hpp" -#include "barretenberg/honk/proof_system/lookup_library.hpp" +#include "barretenberg/honk/proof_system/logderivative_library.hpp" #include "barretenberg/honk/proof_system/permutation_library.hpp" #include "barretenberg/honk/proof_system/power_polynomial.hpp" #include "barretenberg/polynomials/polynomial.hpp" diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/Fib_prover.cpp b/barretenberg/cpp/src/barretenberg/vm/generated/Fib_prover.cpp index b8cd3fe8907..a5ade6bdf00 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/Fib_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/Fib_prover.cpp @@ -3,7 +3,7 @@ #include "Fib_prover.hpp" #include "barretenberg/commitment_schemes/claim.hpp" #include "barretenberg/commitment_schemes/commitment_key.hpp" -#include "barretenberg/honk/proof_system/lookup_library.hpp" +#include "barretenberg/honk/proof_system/logderivative_library.hpp" #include "barretenberg/honk/proof_system/permutation_library.hpp" #include "barretenberg/honk/proof_system/power_polynomial.hpp" #include "barretenberg/polynomials/polynomial.hpp" From c9069be32e2d3736b8332db4996f149eae72a8fc Mon Sep 17 00:00:00 2001 From: AztecBot Date: Thu, 7 Dec 2023 02:15:35 +0000 Subject: [PATCH 02/35] git subrepo push --branch=master build-system subrepo: subdir: "build-system" merged: "4e1ea3fc2" upstream: origin: "https://github.com/AztecProtocol/build-system" branch: "master" commit: "4e1ea3fc2" git-subrepo: version: "0.4.6" origin: "???" commit: "???" [skip ci] --- build-system/.gitrepo | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build-system/.gitrepo b/build-system/.gitrepo index a666b09cfe2..b1fdb9bd872 100644 --- a/build-system/.gitrepo +++ b/build-system/.gitrepo @@ -6,7 +6,7 @@ [subrepo] remote = https://github.com/AztecProtocol/build-system branch = master - commit = 36fa99a362d2b86a39a18da6c06eaa8d1fe1f8a9 - parent = eade352a56b2365b5213962733735e45a6d46fb0 + commit = 4e1ea3fc2cdbbfdb97d21b0920eb681ede20c333 + parent = 379b5adc259ac69b01e61b852172cdfc87cf9350 method = merge cmdver = 0.4.6 From 936d62e41a51dce0abbb6490883f606d795ca3c7 Mon Sep 17 00:00:00 2001 From: AztecBot Date: Thu, 7 Dec 2023 02:16:01 +0000 Subject: [PATCH 03/35] git subrepo push --branch=master barretenberg subrepo: subdir: "barretenberg" merged: "4e4634542" upstream: origin: "https://github.com/AztecProtocol/barretenberg" branch: "master" commit: "4e4634542" git-subrepo: version: "0.4.6" origin: "???" commit: "???" [skip ci] --- barretenberg/.gitrepo | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/barretenberg/.gitrepo b/barretenberg/.gitrepo index aab4f229c29..4ba3cac6d74 100644 --- a/barretenberg/.gitrepo +++ b/barretenberg/.gitrepo @@ -6,7 +6,7 @@ [subrepo] remote = https://github.com/AztecProtocol/barretenberg branch = master - commit = b736d1fc1f558f1879ceb5199073a320b8954d94 - parent = eade352a56b2365b5213962733735e45a6d46fb0 + commit = 4e4634542814f15d3703fe560874e08eda57e1fa + parent = 379b5adc259ac69b01e61b852172cdfc87cf9350 method = merge cmdver = 0.4.6 From 242f263472e2c51be96647f1da8a3fe168a5c45d Mon Sep 17 00:00:00 2001 From: AztecBot Date: Thu, 7 Dec 2023 02:16:25 +0000 Subject: [PATCH 04/35] git subrepo push --branch=master yarn-project/aztec-nr subrepo: subdir: "yarn-project/aztec-nr" merged: "4e873ce0d" upstream: origin: "https://github.com/AztecProtocol/aztec-nr" branch: "master" commit: "4e873ce0d" git-subrepo: version: "0.4.6" origin: "???" commit: "???" [skip ci] --- yarn-project/aztec-nr/.gitrepo | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/yarn-project/aztec-nr/.gitrepo b/yarn-project/aztec-nr/.gitrepo index 35123363809..0930abc8a30 100644 --- a/yarn-project/aztec-nr/.gitrepo +++ b/yarn-project/aztec-nr/.gitrepo @@ -6,7 +6,7 @@ [subrepo] remote = https://github.com/AztecProtocol/aztec-nr branch = master - commit = f2038e3bcf602856d07f2faa0ec1d847e8a07bb6 + commit = 4e873ce0d34cad3743be460f5ed703350435a974 method = merge cmdver = 0.4.6 - parent = eade352a56b2365b5213962733735e45a6d46fb0 + parent = 379b5adc259ac69b01e61b852172cdfc87cf9350 From 48e2e3d261a7091cb0b87565ec8bc9ae595b3022 Mon Sep 17 00:00:00 2001 From: Maddiaa <47148561+Maddiaa0@users.noreply.github.com> Date: Thu, 7 Dec 2023 02:55:13 +0000 Subject: [PATCH 05/35] chore: nuke fib (#3607) The avm mini now serves as a good enough example to tests the pil pipeline stability. There is no need for dragging along fib --- barretenberg/cpp/pil/fib/fibonacci.pil | 18 -- barretenberg/cpp/pil/fib/fibonacci_opt.pil | 8 - .../flavor/generated/Fib_flavor.hpp | 296 ------------------ .../generated/Fib_circuit_builder.hpp | 99 ------ .../circuit_builder/generated/Fib_trace.cpp | 62 ---- .../circuit_builder/generated/Fib_trace.hpp | 22 -- .../barretenberg/relations/generated/Fib.hpp | 64 ---- .../vm/generated/Fib_composer.cpp | 85 ----- .../vm/generated/Fib_composer.hpp | 69 ---- .../vm/generated/Fib_composer.test.cpp | 51 --- .../barretenberg/vm/generated/Fib_prover.cpp | 136 -------- .../barretenberg/vm/generated/Fib_prover.hpp | 62 ---- .../vm/generated/Fib_verifier.cpp | 89 ------ .../vm/generated/Fib_verifier.hpp | 33 -- 14 files changed, 1094 deletions(-) delete mode 100644 barretenberg/cpp/pil/fib/fibonacci.pil delete mode 100644 barretenberg/cpp/pil/fib/fibonacci_opt.pil delete mode 100644 barretenberg/cpp/src/barretenberg/flavor/generated/Fib_flavor.hpp delete mode 100644 barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/generated/Fib_circuit_builder.hpp delete mode 100644 barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/generated/Fib_trace.cpp delete mode 100644 barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/generated/Fib_trace.hpp delete mode 100644 barretenberg/cpp/src/barretenberg/relations/generated/Fib.hpp delete mode 100644 barretenberg/cpp/src/barretenberg/vm/generated/Fib_composer.cpp delete mode 100644 barretenberg/cpp/src/barretenberg/vm/generated/Fib_composer.hpp delete mode 100644 barretenberg/cpp/src/barretenberg/vm/generated/Fib_composer.test.cpp delete mode 100644 barretenberg/cpp/src/barretenberg/vm/generated/Fib_prover.cpp delete mode 100644 barretenberg/cpp/src/barretenberg/vm/generated/Fib_prover.hpp delete mode 100644 barretenberg/cpp/src/barretenberg/vm/generated/Fib_verifier.cpp delete mode 100644 barretenberg/cpp/src/barretenberg/vm/generated/Fib_verifier.hpp diff --git a/barretenberg/cpp/pil/fib/fibonacci.pil b/barretenberg/cpp/pil/fib/fibonacci.pil deleted file mode 100644 index 993a675e7d2..00000000000 --- a/barretenberg/cpp/pil/fib/fibonacci.pil +++ /dev/null @@ -1,18 +0,0 @@ -constant %N = 16; - -// This uses the alternative nomenclature as well. - -namespace Fibonacci(%N); - col fixed LAST(i) { match i { - %N - 1 => 1, - _ => 0, - } }; - col fixed FIRST(i) { match i { - 0 => 1, - _ => 0, - } }; - col witness x, y; - - (1-FIRST) * (1-LAST) * (x' - y) = 0; - (1-FIRST) * (1-LAST) * (y' - (x + y)) = 0; - diff --git a/barretenberg/cpp/pil/fib/fibonacci_opt.pil b/barretenberg/cpp/pil/fib/fibonacci_opt.pil deleted file mode 100644 index 2c36cd15327..00000000000 --- a/barretenberg/cpp/pil/fib/fibonacci_opt.pil +++ /dev/null @@ -1,8 +0,0 @@ -constant %N = 16; -namespace Fibonacci(16); - col fixed LAST(i) { match i { (%N - 1) => 1, _ => 0, } }; - col fixed FIRST(i) { match i { 0 => 1, _ => 0, } }; - col witness x; - col witness y; - (((1 - Fibonacci.FIRST) * (1 - Fibonacci.LAST)) * (Fibonacci.x' - Fibonacci.y)) = 0; - (((1 - Fibonacci.FIRST) * (1 - Fibonacci.LAST)) * (Fibonacci.y' - (Fibonacci.x + Fibonacci.y))) = 0; diff --git a/barretenberg/cpp/src/barretenberg/flavor/generated/Fib_flavor.hpp b/barretenberg/cpp/src/barretenberg/flavor/generated/Fib_flavor.hpp deleted file mode 100644 index 9572fedd3ff..00000000000 --- a/barretenberg/cpp/src/barretenberg/flavor/generated/Fib_flavor.hpp +++ /dev/null @@ -1,296 +0,0 @@ - - -#pragma once -#include "../relation_definitions_fwd.hpp" -#include "barretenberg/commitment_schemes/kzg/kzg.hpp" -#include "barretenberg/ecc/curves/bn254/g1.hpp" -#include "barretenberg/polynomials/barycentric.hpp" -#include "barretenberg/polynomials/univariate.hpp" - -#include "barretenberg/flavor/flavor.hpp" -#include "barretenberg/flavor/flavor_macros.hpp" -#include "barretenberg/polynomials/evaluation_domain.hpp" -#include "barretenberg/polynomials/polynomial.hpp" -#include "barretenberg/relations/generated/Fib.hpp" -#include "barretenberg/transcript/transcript.hpp" - -namespace proof_system::honk { -namespace flavor { - -class FibFlavor { - public: - using Curve = curve::BN254; - using G1 = Curve::Group; - using PCS = pcs::kzg::KZG; - - using FF = G1::subgroup_field; - using Polynomial = barretenberg::Polynomial; - using PolynomialHandle = std::span; - using GroupElement = G1::element; - using Commitment = G1::affine_element; - using CommitmentHandle = G1::affine_element; - using CommitmentKey = pcs::CommitmentKey; - using VerifierCommitmentKey = pcs::VerifierCommitmentKey; - - static constexpr size_t NUM_PRECOMPUTED_ENTITIES = 2; - static constexpr size_t NUM_WITNESS_ENTITIES = 2; - static constexpr size_t NUM_WIRES = NUM_WITNESS_ENTITIES + NUM_PRECOMPUTED_ENTITIES; - // We have two copies of the witness entities, so we subtract the number of fixed ones (they have no shift), one for - // the unshifted and one for the shifted - static constexpr size_t NUM_ALL_ENTITIES = 6; - - using Relations = std::tuple>; - - static constexpr size_t MAX_PARTIAL_RELATION_LENGTH = compute_max_partial_relation_length(); - - // BATCHED_RELATION_PARTIAL_LENGTH = algebraic degree of sumcheck relation *after* multiplying by the `pow_zeta` - // random polynomial e.g. For \sum(x) [A(x) * B(x) + C(x)] * PowZeta(X), relation length = 2 and random relation - // length = 3 - static constexpr size_t BATCHED_RELATION_PARTIAL_LENGTH = MAX_PARTIAL_RELATION_LENGTH + 1; - static constexpr size_t NUM_RELATIONS = std::tuple_size::value; - - template - using ProtogalaxyTupleOfTuplesOfUnivariates = - decltype(create_protogalaxy_tuple_of_tuples_of_univariates()); - using SumcheckTupleOfTuplesOfUnivariates = decltype(create_sumcheck_tuple_of_tuples_of_univariates()); - using TupleOfArraysOfValues = decltype(create_tuple_of_arrays_of_values()); - - static constexpr bool has_zero_row = true; - - private: - template class PrecomputedEntities : public PrecomputedEntitiesBase { - public: - using DataType = DataType_; - DEFINE_FLAVOR_MEMBERS(DataType, Fibonacci_LAST, Fibonacci_FIRST) - - RefVector get_selectors() - { - return { - Fibonacci_LAST, - Fibonacci_FIRST, - }; - }; - - RefVector get_sigma_polynomials() { return {}; }; - RefVector get_id_polynomials() { return {}; }; - RefVector get_table_polynomials() { return {}; }; - }; - - template class WitnessEntities { - public: - DEFINE_FLAVOR_MEMBERS(DataType, Fibonacci_x, Fibonacci_y) - - RefVector get_wires() - { - return { - Fibonacci_x, - Fibonacci_y, - - }; - }; - - RefVector get_sorted_polynomials() { return {}; }; - }; - - template class AllEntities { - public: - DEFINE_FLAVOR_MEMBERS( - DataType, Fibonacci_LAST, Fibonacci_FIRST, Fibonacci_x, Fibonacci_y, Fibonacci_x_shift, Fibonacci_y_shift) - - RefVector get_wires() - { - return { - Fibonacci_LAST, Fibonacci_FIRST, Fibonacci_x, Fibonacci_y, Fibonacci_x_shift, Fibonacci_y_shift, - - }; - }; - - RefVector get_unshifted() - { - return { - Fibonacci_LAST, - Fibonacci_FIRST, - Fibonacci_x, - Fibonacci_y, - - }; - }; - - RefVector get_to_be_shifted() - { - return { - Fibonacci_x, - Fibonacci_y, - - }; - }; - - RefVector get_shifted() - { - return { - Fibonacci_x_shift, - Fibonacci_y_shift, - - }; - }; - }; - - public: - class ProvingKey : public ProvingKey_, WitnessEntities> { - public: - // Expose constructors on the base class - using Base = ProvingKey_, WitnessEntities>; - using Base::Base; - - // The plookup wires that store plookup read data. - std::array get_table_column_wires() { return {}; }; - }; - - using VerificationKey = VerificationKey_>; - - using ProverPolynomials = AllEntities; - - using FoldedPolynomials = AllEntities>; - - class AllValues : public AllEntities { - public: - using Base = AllEntities; - using Base::Base; - }; - - class AllPolynomials : public AllEntities { - public: - [[nodiscard]] size_t get_polynomial_size() const { return this->Fibonacci_LAST.size(); } - [[nodiscard]] AllValues get_row(const size_t row_idx) const - { - AllValues result; - for (auto [result_field, polynomial] : zip_view(result.get_all(), get_all())) { - result_field = polynomial[row_idx]; - } - return result; - } - }; - - using RowPolynomials = AllEntities; - - class PartiallyEvaluatedMultivariates : public AllEntities { - public: - PartiallyEvaluatedMultivariates() = default; - PartiallyEvaluatedMultivariates(const size_t circuit_size) - { - // Storage is only needed after the first partial evaluation, hence polynomials of size (n / 2) - for (auto& poly : get_all()) { - poly = Polynomial(circuit_size / 2); - } - } - }; - - /** - * @brief A container for univariates used during Protogalaxy folding and sumcheck. - * @details During folding and sumcheck, the prover evaluates the relations on these univariates. - */ - template using ProverUnivariates = AllEntities>; - - /** - * @brief A container for univariates produced during the hot loop in sumcheck. - */ - using ExtendedEdges = ProverUnivariates; - - class CommitmentLabels : public AllEntities { - private: - using Base = AllEntities; - - public: - CommitmentLabels() - : AllEntities() - { - Base::Fibonacci_LAST = "Fibonacci_LAST"; - Base::Fibonacci_FIRST = "Fibonacci_FIRST"; - Base::Fibonacci_x = "Fibonacci_x"; - Base::Fibonacci_y = "Fibonacci_y"; - }; - }; - - class VerifierCommitments : public AllEntities { - private: - using Base = AllEntities; - - public: - VerifierCommitments(const std::shared_ptr& verification_key) - { - Fibonacci_LAST = verification_key->Fibonacci_LAST; - Fibonacci_FIRST = verification_key->Fibonacci_FIRST; - } - }; - - class Transcript : public BaseTranscript { - public: - uint32_t circuit_size; - - Commitment Fibonacci_x; - Commitment Fibonacci_y; - - std::vector> sumcheck_univariates; - std::array sumcheck_evaluations; - std::vector zm_cq_comms; - Commitment zm_cq_comm; - Commitment zm_pi_comm; - - Transcript() = default; - - Transcript(const std::vector& proof) - : BaseTranscript(proof) - {} - - void deserialize_full_transcript() - { - size_t num_bytes_read = 0; - circuit_size = deserialize_from_buffer(proof_data, num_bytes_read); - size_t log_n = numeric::get_msb(circuit_size); - - Fibonacci_x = deserialize_from_buffer(BaseTranscript::proof_data, num_bytes_read); - Fibonacci_y = deserialize_from_buffer(BaseTranscript::proof_data, num_bytes_read); - - for (size_t i = 0; i < log_n; ++i) { - sumcheck_univariates.emplace_back( - deserialize_from_buffer>( - BaseTranscript::proof_data, num_bytes_read)); - } - sumcheck_evaluations = - deserialize_from_buffer>(BaseTranscript::proof_data, num_bytes_read); - for (size_t i = 0; i < log_n; ++i) { - zm_cq_comms.push_back(deserialize_from_buffer(proof_data, num_bytes_read)); - } - zm_cq_comm = deserialize_from_buffer(proof_data, num_bytes_read); - zm_pi_comm = deserialize_from_buffer(proof_data, num_bytes_read); - } - - void serialize_full_transcript() - { - size_t old_proof_length = proof_data.size(); - BaseTranscript::proof_data.clear(); - size_t log_n = numeric::get_msb(circuit_size); - - serialize_to_buffer(circuit_size, BaseTranscript::proof_data); - - serialize_to_buffer(Fibonacci_x, BaseTranscript::proof_data); - serialize_to_buffer(Fibonacci_y, BaseTranscript::proof_data); - - for (size_t i = 0; i < log_n; ++i) { - serialize_to_buffer(sumcheck_univariates[i], BaseTranscript::proof_data); - } - serialize_to_buffer(sumcheck_evaluations, BaseTranscript::proof_data); - for (size_t i = 0; i < log_n; ++i) { - serialize_to_buffer(zm_cq_comms[i], proof_data); - } - serialize_to_buffer(zm_cq_comm, proof_data); - serialize_to_buffer(zm_pi_comm, proof_data); - - // sanity check to make sure we generate the same length of proof as before. - ASSERT(proof_data.size() == old_proof_length); - } - }; -}; - -} // namespace flavor -} // namespace proof_system::honk diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/generated/Fib_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/generated/Fib_circuit_builder.hpp deleted file mode 100644 index a233692ebf7..00000000000 --- a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/generated/Fib_circuit_builder.hpp +++ /dev/null @@ -1,99 +0,0 @@ - - -// AUTOGENERATED FILE -#pragma once - -#include "barretenberg/common/throw_or_abort.hpp" -#include "barretenberg/ecc/curves/bn254/fr.hpp" -#include "barretenberg/proof_system/circuit_builder/circuit_builder_base.hpp" - -#include "barretenberg/flavor/generated/Fib_flavor.hpp" -#include "barretenberg/relations/generated/Fib.hpp" - -using namespace barretenberg; - -namespace proof_system { - -class FibCircuitBuilder { - public: - using Flavor = proof_system::honk::flavor::FibFlavor; - using FF = Flavor::FF; - using Row = Fib_vm::Row; - - // TODO: template - using Polynomial = Flavor::Polynomial; - using AllPolynomials = Flavor::AllPolynomials; - - static constexpr size_t num_fixed_columns = 6; - static constexpr size_t num_polys = 4; - std::vector rows; - - void set_trace(std::vector&& trace) { rows = std::move(trace); } - - AllPolynomials compute_polynomials() - { - const auto num_rows = get_circuit_subgroup_size(); - AllPolynomials polys; - - // Allocate mem for each column - for (auto& poly : polys.get_all()) { - poly = Polynomial(num_rows); - } - - for (size_t i = 0; i < rows.size(); i++) { - polys.Fibonacci_LAST[i] = rows[i].Fibonacci_LAST; - polys.Fibonacci_FIRST[i] = rows[i].Fibonacci_FIRST; - polys.Fibonacci_x[i] = rows[i].Fibonacci_x; - polys.Fibonacci_y[i] = rows[i].Fibonacci_y; - } - - polys.Fibonacci_x_shift = Polynomial(polys.Fibonacci_x.shifted()); - polys.Fibonacci_y_shift = Polynomial(polys.Fibonacci_y.shifted()); - - return polys; - } - - [[maybe_unused]] bool check_circuit() - { - auto polys = compute_polynomials(); - const size_t num_rows = polys.get_polynomial_size(); - - const auto evaluate_relation = [&](const std::string& relation_name) { - typename Relation::SumcheckArrayOfValuesOverSubrelations result; - for (auto& r : result) { - r = 0; - } - constexpr size_t NUM_SUBRELATIONS = result.size(); - - for (size_t i = 0; i < num_rows; ++i) { - Relation::accumulate(result, polys.get_row(i), {}, 1); - - bool x = true; - for (size_t j = 0; j < NUM_SUBRELATIONS; ++j) { - if (result[j] != 0) { - throw_or_abort( - format("Relation ", relation_name, ", subrelation index ", j, " failed at row ", i)); - x = false; - } - } - if (!x) { - return false; - } - } - return true; - }; - - return evaluate_relation.template operator()>("Fib"); - } - - [[nodiscard]] size_t get_num_gates() const { return rows.size(); } - - [[nodiscard]] size_t get_circuit_subgroup_size() const - { - const size_t num_rows = get_num_gates(); - const auto num_rows_log2 = static_cast(numeric::get_msb64(num_rows)); - size_t num_rows_pow2 = 1UL << (num_rows_log2 + (1UL << num_rows_log2 == num_rows ? 0 : 1)); - return num_rows_pow2; - } -}; -} // namespace proof_system diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/generated/Fib_trace.cpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/generated/Fib_trace.cpp deleted file mode 100644 index d2d86ba4993..00000000000 --- a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/generated/Fib_trace.cpp +++ /dev/null @@ -1,62 +0,0 @@ -#include "barretenberg/ecc/curves/bn254/fr.hpp" -#include "barretenberg/proof_system/arithmetization/arithmetization.hpp" -#include -#include -#include -#include -#include -#include - -#include "./Fib_trace.hpp" - -#include "barretenberg/relations/generated/Fib.hpp" - -using namespace barretenberg; - -namespace proof_system { - -using Row = Fib_vm::Row; - -std::vector FibTraceBuilder::build_trace() -{ - { - std::vector trace; - // Build up the rows - size_t n = 16; - // Build the is_last column - - // Add first row that makes the shifted cols 0 - Row first_row = Row{ .Fibonacci_FIRST = 1 }; - trace.push_back(first_row); - - // The actual first row - Row row = { - .Fibonacci_x = 0, - .Fibonacci_y = 1, - }; - trace.push_back(row); - - for (size_t i = 2; i < n; i++) { - Row prev_row = trace[i - 1]; - - FF x = prev_row.Fibonacci_y; - FF y = prev_row.Fibonacci_x + prev_row.Fibonacci_y; - Row row = { - .Fibonacci_x = x, - .Fibonacci_y = y, - }; - trace.push_back(row); - } - // Build the isLast row - trace[n - 1].Fibonacci_LAST = 1; - - // Build the shifts - for (size_t i = 1; i < n; i++) { - Row& row = trace[i - 1]; - row.Fibonacci_x_shift = trace[(i) % trace.size()].Fibonacci_x; - row.Fibonacci_y_shift = trace[(i) % trace.size()].Fibonacci_y; - } - return trace; - } -} -} // namespace proof_system \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/generated/Fib_trace.hpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/generated/Fib_trace.hpp deleted file mode 100644 index 856400d82b4..00000000000 --- a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/generated/Fib_trace.hpp +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#include "barretenberg/common/throw_or_abort.hpp" -#include "barretenberg/ecc/curves/bn254/fr.hpp" -#include "barretenberg/proof_system/circuit_builder/circuit_builder_base.hpp" - -#include "barretenberg/flavor/generated/Fib_flavor.hpp" -#include "barretenberg/relations/generated/Fib.hpp" - -using namespace barretenberg; - -namespace proof_system { - -class FibTraceBuilder { - public: - using Flavor = proof_system::honk::flavor::FibFlavor; - using FF = Flavor::FF; - using Row = Fib_vm::Row; - - static std::vector build_trace(); -}; -} // namespace proof_system diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/Fib.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/Fib.hpp deleted file mode 100644 index 428c6a1208b..00000000000 --- a/barretenberg/cpp/src/barretenberg/relations/generated/Fib.hpp +++ /dev/null @@ -1,64 +0,0 @@ - -#pragma once -#include "../relation_parameters.hpp" -#include "../relation_types.hpp" - -namespace proof_system::Fib_vm { - -template struct Row { - FF Fibonacci_LAST{}; - FF Fibonacci_FIRST{}; - FF Fibonacci_x{}; - FF Fibonacci_y{}; - FF Fibonacci_x_shift{}; - FF Fibonacci_y_shift{}; -}; - -#define DECLARE_VIEWS(index) \ - using View = typename std::tuple_element::type; \ - [[maybe_unused]] auto Fibonacci_LAST = View(new_term.Fibonacci_LAST); \ - [[maybe_unused]] auto Fibonacci_FIRST = View(new_term.Fibonacci_FIRST); \ - [[maybe_unused]] auto Fibonacci_x = View(new_term.Fibonacci_x); \ - [[maybe_unused]] auto Fibonacci_y = View(new_term.Fibonacci_y); \ - [[maybe_unused]] auto Fibonacci_x_shift = View(new_term.Fibonacci_x_shift); \ - [[maybe_unused]] auto Fibonacci_y_shift = View(new_term.Fibonacci_y_shift); - -template class FibImpl { - public: - using FF = FF_; - - static constexpr std::array SUBRELATION_PARTIAL_LENGTHS{ - 4, - 4, - }; - - template - void static accumulate(ContainerOverSubrelations& evals, - const AllEntities& new_term, - [[maybe_unused]] const RelationParameters&, - [[maybe_unused]] const FF& scaling_factor) - { - - // Contribution 0 - { - DECLARE_VIEWS(0); - - auto tmp = (((-Fibonacci_FIRST + FF(1)) * (-Fibonacci_LAST + FF(1))) * (Fibonacci_x_shift - Fibonacci_y)); - tmp *= scaling_factor; - std::get<0>(evals) += tmp; - } - // Contribution 1 - { - DECLARE_VIEWS(1); - - auto tmp = (((-Fibonacci_FIRST + FF(1)) * (-Fibonacci_LAST + FF(1))) * - (Fibonacci_y_shift - (Fibonacci_x + Fibonacci_y))); - tmp *= scaling_factor; - std::get<1>(evals) += tmp; - } - } -}; - -template using Fib = Relation>; - -} // namespace proof_system::Fib_vm \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/Fib_composer.cpp b/barretenberg/cpp/src/barretenberg/vm/generated/Fib_composer.cpp deleted file mode 100644 index 7a78c264e75..00000000000 --- a/barretenberg/cpp/src/barretenberg/vm/generated/Fib_composer.cpp +++ /dev/null @@ -1,85 +0,0 @@ - - -#include "./Fib_composer.hpp" -#include "barretenberg/proof_system/circuit_builder/generated/Fib_circuit_builder.hpp" -#include "barretenberg/proof_system/composer/composer_lib.hpp" -#include "barretenberg/proof_system/composer/permutation_lib.hpp" -#include "barretenberg/vm/generated/Fib_verifier.hpp" - -namespace proof_system::honk { - -using Flavor = honk::flavor::FibFlavor; -void FibComposer::compute_witness(CircuitConstructor& circuit) -{ - if (computed_witness) { - return; - } - - auto polynomials = circuit.compute_polynomials(); - - proving_key->Fibonacci_LAST = polynomials.Fibonacci_LAST; - proving_key->Fibonacci_FIRST = polynomials.Fibonacci_FIRST; - proving_key->Fibonacci_x = polynomials.Fibonacci_x; - proving_key->Fibonacci_y = polynomials.Fibonacci_y; - - computed_witness = true; -} - -FibProver FibComposer::create_prover(CircuitConstructor& circuit_constructor) -{ - compute_proving_key(circuit_constructor); - compute_witness(circuit_constructor); - compute_commitment_key(circuit_constructor.get_circuit_subgroup_size()); - - FibProver output_state(proving_key, commitment_key); - - return output_state; -} - -FibVerifier FibComposer::create_verifier(CircuitConstructor& circuit_constructor) -{ - auto verification_key = compute_verification_key(circuit_constructor); - - FibVerifier output_state(verification_key); - - auto pcs_verification_key = std::make_unique(verification_key->circuit_size, crs_factory_); - - output_state.pcs_verification_key = std::move(pcs_verification_key); - - return output_state; -} - -std::shared_ptr FibComposer::compute_proving_key(CircuitConstructor& circuit_constructor) -{ - if (proving_key) { - return proving_key; - } - - // Initialize proving_key - { - const size_t subgroup_size = circuit_constructor.get_circuit_subgroup_size(); - proving_key = std::make_shared(subgroup_size, 0); - } - - proving_key->contains_recursive_proof = false; - - return proving_key; -} - -std::shared_ptr FibComposer::compute_verification_key(CircuitConstructor& circuit_constructor) -{ - if (verification_key) { - return verification_key; - } - - if (!proving_key) { - compute_proving_key(circuit_constructor); - } - - verification_key = - std::make_shared(proving_key->circuit_size, proving_key->num_public_inputs); - - return verification_key; -} - -} // namespace proof_system::honk diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/Fib_composer.hpp b/barretenberg/cpp/src/barretenberg/vm/generated/Fib_composer.hpp deleted file mode 100644 index 99c71c1913f..00000000000 --- a/barretenberg/cpp/src/barretenberg/vm/generated/Fib_composer.hpp +++ /dev/null @@ -1,69 +0,0 @@ - - -#pragma once - -#include "barretenberg/proof_system/circuit_builder/generated/Fib_circuit_builder.hpp" -#include "barretenberg/proof_system/composer/composer_lib.hpp" -#include "barretenberg/srs/global_crs.hpp" -#include "barretenberg/vm/generated/Fib_prover.hpp" -#include "barretenberg/vm/generated/Fib_verifier.hpp" - -namespace proof_system::honk { -class FibComposer { - public: - using Flavor = honk::flavor::FibFlavor; - using CircuitConstructor = FibCircuitBuilder; - using ProvingKey = Flavor::ProvingKey; - using VerificationKey = Flavor::VerificationKey; - using PCS = Flavor::PCS; - using CommitmentKey = Flavor::CommitmentKey; - using VerifierCommitmentKey = Flavor::VerifierCommitmentKey; - - // TODO: which of these will we really need - static constexpr std::string_view NAME_STRING = "Fib"; - static constexpr size_t NUM_RESERVED_GATES = 0; - static constexpr size_t NUM_WIRES = Flavor::NUM_WIRES; - - std::shared_ptr proving_key; - std::shared_ptr verification_key; - - // The crs_factory holds the path to the srs and exposes methods to extract the srs elements - std::shared_ptr> crs_factory_; - - // The commitment key is passed to the prover but also used herein to compute the verfication key commitments - std::shared_ptr commitment_key; - - std::vector recursive_proof_public_input_indices; - bool contains_recursive_proof = false; - bool computed_witness = false; - - FibComposer() { crs_factory_ = barretenberg::srs::get_crs_factory(); } - - FibComposer(std::shared_ptr p_key, std::shared_ptr v_key) - : proving_key(std::move(p_key)) - , verification_key(std::move(v_key)) - {} - - FibComposer(FibComposer&& other) noexcept = default; - FibComposer(FibComposer const& other) noexcept = default; - FibComposer& operator=(FibComposer&& other) noexcept = default; - FibComposer& operator=(FibComposer const& other) noexcept = default; - ~FibComposer() = default; - - std::shared_ptr compute_proving_key(CircuitConstructor& circuit_constructor); - std::shared_ptr compute_verification_key(CircuitConstructor& circuit_constructor); - - void compute_witness(CircuitConstructor& circuit_constructor); - - FibProver create_prover(CircuitConstructor& circuit_constructor); - FibVerifier create_verifier(CircuitConstructor& circuit_constructor); - - void add_table_column_selector_poly_to_proving_key(barretenberg::polynomial& small, const std::string& tag); - - void compute_commitment_key(size_t circuit_size) - { - commitment_key = std::make_shared(circuit_size, crs_factory_); - }; -}; - -} // namespace proof_system::honk diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/Fib_composer.test.cpp b/barretenberg/cpp/src/barretenberg/vm/generated/Fib_composer.test.cpp deleted file mode 100644 index 36650f8ce61..00000000000 --- a/barretenberg/cpp/src/barretenberg/vm/generated/Fib_composer.test.cpp +++ /dev/null @@ -1,51 +0,0 @@ -#include "barretenberg/vm/generated/Fib_composer.hpp" -#include "barretenberg/ecc/curves/bn254/fr.hpp" -#include "barretenberg/flavor/generated/Fib_flavor.hpp" -#include "barretenberg/proof_system/circuit_builder/generated/Fib_trace.hpp" -#include "barretenberg/proof_system/plookup_tables/types.hpp" -#include "barretenberg/sumcheck/sumcheck_round.hpp" -#include "barretenberg/vm/generated/Fib_prover.hpp" -#include "barretenberg/vm/generated/Fib_verifier.hpp" -#include -#include -#include -#include -#include - -using namespace proof_system::honk; - -namespace example_relation_honk_composer { - -class FibTests : public ::testing::Test { - protected: - // TODO(640): The Standard Honk on Grumpkin test suite fails unless the SRS is initialised for every test. - void SetUp() override { barretenberg::srs::init_crs_factory("../srs_db/ignition"); }; -}; - -namespace { -auto& engine = numeric::random::get_debug_engine(); -} - -TEST_F(FibTests, powdre2e) -{ - barretenberg::srs::init_crs_factory("../srs_db/ignition"); - - auto circuit_builder = proof_system::FibCircuitBuilder(); - - auto rows = proof_system::FibTraceBuilder::build_trace(); - circuit_builder.set_trace(std::move(rows)); - - auto composer = FibComposer(); - - bool circuit_gud = circuit_builder.check_circuit(); - ASSERT_TRUE(circuit_gud); - - auto prover = composer.create_prover(circuit_builder); - auto proof = prover.construct_proof(); - - auto verifier = composer.create_verifier(circuit_builder); - bool verified = verifier.verify_proof(proof); - ASSERT_TRUE(verified) << proof; -} - -} // namespace example_relation_honk_composer \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/Fib_prover.cpp b/barretenberg/cpp/src/barretenberg/vm/generated/Fib_prover.cpp deleted file mode 100644 index a5ade6bdf00..00000000000 --- a/barretenberg/cpp/src/barretenberg/vm/generated/Fib_prover.cpp +++ /dev/null @@ -1,136 +0,0 @@ - - -#include "Fib_prover.hpp" -#include "barretenberg/commitment_schemes/claim.hpp" -#include "barretenberg/commitment_schemes/commitment_key.hpp" -#include "barretenberg/honk/proof_system/logderivative_library.hpp" -#include "barretenberg/honk/proof_system/permutation_library.hpp" -#include "barretenberg/honk/proof_system/power_polynomial.hpp" -#include "barretenberg/polynomials/polynomial.hpp" -#include "barretenberg/proof_system/library/grand_product_library.hpp" -#include "barretenberg/relations/lookup_relation.hpp" -#include "barretenberg/relations/permutation_relation.hpp" -#include "barretenberg/sumcheck/sumcheck.hpp" - -namespace proof_system::honk { - -using Flavor = honk::flavor::FibFlavor; - -/** - * Create FibProver from proving key, witness and manifest. - * - * @param input_key Proving key. - * @param input_manifest Input manifest - * - * @tparam settings Settings class. - * */ -FibProver::FibProver(std::shared_ptr input_key, std::shared_ptr commitment_key) - : key(input_key) - , commitment_key(commitment_key) -{ - // TODO: take every polynomial and assign it to the key!! - - prover_polynomials.Fibonacci_LAST = key->Fibonacci_LAST; - prover_polynomials.Fibonacci_FIRST = key->Fibonacci_FIRST; - prover_polynomials.Fibonacci_x = key->Fibonacci_x; - prover_polynomials.Fibonacci_y = key->Fibonacci_y; - - prover_polynomials.Fibonacci_x = key->Fibonacci_x; - prover_polynomials.Fibonacci_x_shift = key->Fibonacci_x.shifted(); - - prover_polynomials.Fibonacci_y = key->Fibonacci_y; - prover_polynomials.Fibonacci_y_shift = key->Fibonacci_y.shifted(); - - // prover_polynomials.lookup_inverses = key->lookup_inverses; - // key->z_perm = Polynomial(key->circuit_size); - // prover_polynomials.z_perm = key->z_perm; -} - -/** - * @brief Add circuit size, public input size, and public inputs to transcript - * - */ -void FibProver::execute_preamble_round() -{ - const auto circuit_size = static_cast(key->circuit_size); - - transcript->send_to_verifier("circuit_size", circuit_size); -} - -/** - * @brief Compute commitments to the first three wires - * - */ -void FibProver::execute_wire_commitments_round() -{ - auto wire_polys = key->get_wires(); - auto labels = commitment_labels.get_wires(); - for (size_t idx = 0; idx < wire_polys.size(); ++idx) { - transcript->send_to_verifier(labels[idx], commitment_key->commit(wire_polys[idx])); - } -} - -/** - * @brief Run Sumcheck resulting in u = (u_1,...,u_d) challenges and all evaluations at u being calculated. - * - */ -void FibProver::execute_relation_check_rounds() -{ - using Sumcheck = sumcheck::SumcheckProver; - - auto sumcheck = Sumcheck(key->circuit_size, transcript); - auto alpha = transcript->get_challenge("alpha"); - - sumcheck_output = sumcheck.prove(prover_polynomials, relation_parameters, alpha); -} - -/** - * @brief Execute the ZeroMorph protocol to prove the multilinear evaluations produced by Sumcheck - * @details See https://hackmd.io/dlf9xEwhTQyE3hiGbq4FsA?view for a complete description of the unrolled protocol. - * - * */ -void FibProver::execute_zeromorph_rounds() -{ - ZeroMorph::prove(prover_polynomials.get_unshifted(), - prover_polynomials.get_to_be_shifted(), - sumcheck_output.claimed_evaluations.get_unshifted(), - sumcheck_output.claimed_evaluations.get_shifted(), - sumcheck_output.challenge, - commitment_key, - transcript); -} - -plonk::proof& FibProver::export_proof() -{ - proof.proof_data = transcript->proof_data; - return proof; -} - -plonk::proof& FibProver::construct_proof() -{ - // Add circuit size public input size and public inputs to transcript-> - execute_preamble_round(); - - // Compute wire commitments - execute_wire_commitments_round(); - - // TODO: not implemented for codegen just yet - // Compute sorted list accumulator and commitment - // execute_log_derivative_commitments_round(); - - // Fiat-Shamir: bbeta & gamma - // Compute grand product(s) and commitments. - // execute_grand_product_computation_round(); - - // Fiat-Shamir: alpha - // Run sumcheck subprotocol. - execute_relation_check_rounds(); - - // Fiat-Shamir: rho, y, x, z - // Execute Zeromorph multilinear PCS - execute_zeromorph_rounds(); - - return export_proof(); -} - -} // namespace proof_system::honk diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/Fib_prover.hpp b/barretenberg/cpp/src/barretenberg/vm/generated/Fib_prover.hpp deleted file mode 100644 index 7b9e3cc6862..00000000000 --- a/barretenberg/cpp/src/barretenberg/vm/generated/Fib_prover.hpp +++ /dev/null @@ -1,62 +0,0 @@ - - -#pragma once -#include "barretenberg/commitment_schemes/zeromorph/zeromorph.hpp" -#include "barretenberg/flavor/generated/Fib_flavor.hpp" -#include "barretenberg/plonk/proof_system/types/proof.hpp" -#include "barretenberg/relations/relation_parameters.hpp" -#include "barretenberg/sumcheck/sumcheck_output.hpp" -#include "barretenberg/transcript/transcript.hpp" - -namespace proof_system::honk { - -class FibProver { - - using Flavor = honk::flavor::FibFlavor; - using FF = Flavor::FF; - using PCS = Flavor::PCS; - using PCSCommitmentKey = Flavor::CommitmentKey; - using ProvingKey = Flavor::ProvingKey; - using Polynomial = Flavor::Polynomial; - using ProverPolynomials = Flavor::ProverPolynomials; - using CommitmentLabels = Flavor::CommitmentLabels; - using Curve = Flavor::Curve; - using Transcript = Flavor::Transcript; - - public: - explicit FibProver(std::shared_ptr input_key, std::shared_ptr commitment_key); - - void execute_preamble_round(); - void execute_wire_commitments_round(); - void execute_relation_check_rounds(); - void execute_zeromorph_rounds(); - - plonk::proof& export_proof(); - plonk::proof& construct_proof(); - - std::shared_ptr transcript = std::make_shared(); - - std::vector public_inputs; - - proof_system::RelationParameters relation_parameters; - - std::shared_ptr key; - - // Container for spans of all polynomials required by the prover (i.e. all multivariates evaluated by Sumcheck). - ProverPolynomials prover_polynomials; - - CommitmentLabels commitment_labels; - - Polynomial quotient_W; - - sumcheck::SumcheckOutput sumcheck_output; - - std::shared_ptr commitment_key; - - using ZeroMorph = pcs::zeromorph::ZeroMorphProver_; - - private: - plonk::proof proof; -}; - -} // namespace proof_system::honk diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/Fib_verifier.cpp b/barretenberg/cpp/src/barretenberg/vm/generated/Fib_verifier.cpp deleted file mode 100644 index a47e2c0fdf0..00000000000 --- a/barretenberg/cpp/src/barretenberg/vm/generated/Fib_verifier.cpp +++ /dev/null @@ -1,89 +0,0 @@ - - -#include "./Fib_verifier.hpp" -#include "barretenberg/commitment_schemes/zeromorph/zeromorph.hpp" -#include "barretenberg/honk/proof_system/power_polynomial.hpp" -#include "barretenberg/numeric/bitop/get_msb.hpp" -#include "barretenberg/transcript/transcript.hpp" - -using namespace barretenberg; -using namespace proof_system::honk::sumcheck; - -namespace proof_system::honk { -FibVerifier::FibVerifier(std::shared_ptr verifier_key) - : key(verifier_key) -{} - -FibVerifier::FibVerifier(FibVerifier&& other) noexcept - : key(std::move(other.key)) - , pcs_verification_key(std::move(other.pcs_verification_key)) -{} - -FibVerifier& FibVerifier::operator=(FibVerifier&& other) noexcept -{ - key = other.key; - pcs_verification_key = (std::move(other.pcs_verification_key)); - commitments.clear(); - return *this; -} - -/** - * @brief This function verifies an Fib Honk proof for given program settings. - * - */ -bool FibVerifier::verify_proof(const plonk::proof& proof) -{ - using Flavor = honk::flavor::FibFlavor; - using FF = Flavor::FF; - using Commitment = Flavor::Commitment; - // using Curve = Flavor::Curve; - // using ZeroMorph = pcs::zeromorph::ZeroMorphVerifier_; - using VerifierCommitments = Flavor::VerifierCommitments; - using CommitmentLabels = Flavor::CommitmentLabels; - using Transcript = Flavor::Transcript; - - RelationParameters relation_parameters; - - transcript = std::make_shared(proof.proof_data); - - VerifierCommitments commitments{ key }; - CommitmentLabels commitment_labels; - - const auto circuit_size = transcript->template receive_from_prover("circuit_size"); - - if (circuit_size != key->circuit_size) { - return false; - } - - // Get commitments to VM wires - commitments.Fibonacci_x = transcript->template receive_from_prover(commitment_labels.Fibonacci_x); - commitments.Fibonacci_y = transcript->template receive_from_prover(commitment_labels.Fibonacci_y); - - // Execute Sumcheck Verifier - auto sumcheck = SumcheckVerifier(circuit_size); - - auto alpha = transcript->get_challenge("alpha"); - auto [multivariate_challenge, claimed_evaluations, sumcheck_verified] = - sumcheck.verify(relation_parameters, alpha, transcript); - - // If Sumcheck did not verify, return false - if (sumcheck_verified.has_value() && !sumcheck_verified.value()) { - return false; - } - - // Execute ZeroMorph rounds. See https://hackmd.io/dlf9xEwhTQyE3hiGbq4FsA?view for a complete description of the - // unrolled protocol. - // NOTE: temporarily disabled - facing integration issues - // auto pairing_points = ZeroMorph::verify(commitments.get_unshifted(), - // commitments.get_to_be_shifted(), - // claimed_evaluations.get_unshifted(), - // claimed_evaluations.get_shifted(), - // multivariate_challenge, - // transcript); - - // auto verified = pcs_verification_key->pairing_check(pairing_points[0], pairing_points[1]); - // return sumcheck_verified.value() && verified; - return sumcheck_verified.value(); -} - -} // namespace proof_system::honk diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/Fib_verifier.hpp b/barretenberg/cpp/src/barretenberg/vm/generated/Fib_verifier.hpp deleted file mode 100644 index 303cb4fca70..00000000000 --- a/barretenberg/cpp/src/barretenberg/vm/generated/Fib_verifier.hpp +++ /dev/null @@ -1,33 +0,0 @@ - - -#pragma once -#include "barretenberg/flavor/generated/Fib_flavor.hpp" -#include "barretenberg/plonk/proof_system/types/proof.hpp" -#include "barretenberg/sumcheck/sumcheck.hpp" - -namespace proof_system::honk { -class FibVerifier { - using Flavor = honk::flavor::FibFlavor; - using FF = Flavor::FF; - using Commitment = Flavor::Commitment; - using VerificationKey = Flavor::VerificationKey; - using VerifierCommitmentKey = Flavor::VerifierCommitmentKey; - using Transcript = Flavor::Transcript; - - public: - explicit FibVerifier(std::shared_ptr verifier_key = nullptr); - FibVerifier(FibVerifier&& other) noexcept; - FibVerifier(const FibVerifier& other) = delete; - - FibVerifier& operator=(const FibVerifier& other) = delete; - FibVerifier& operator=(FibVerifier&& other) noexcept; - - bool verify_proof(const plonk::proof& proof); - - std::shared_ptr key; - std::map commitments; - std::shared_ptr pcs_verification_key; - std::shared_ptr transcript; -}; - -} // namespace proof_system::honk From 6a53fbc48624d6ecbcc8dc6fd69564fdb3db342e Mon Sep 17 00:00:00 2001 From: spypsy Date: Thu, 7 Dec 2023 14:58:01 +0000 Subject: [PATCH 06/35] fix(ci): rebuild versioned cli / sandbox images (#3613) Adding `ARG COMMIT_TAG=` to cli & sandbox Dockerfiles so they're picked up by `check_rebuild` on releases. --- yarn-project/aztec-sandbox/Dockerfile | 4 ++++ yarn-project/cli/Dockerfile | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/yarn-project/aztec-sandbox/Dockerfile b/yarn-project/aztec-sandbox/Dockerfile index c61714b06a3..2f9644563e0 100644 --- a/yarn-project/aztec-sandbox/Dockerfile +++ b/yarn-project/aztec-sandbox/Dockerfile @@ -1,4 +1,8 @@ FROM 278380418400.dkr.ecr.eu-west-2.amazonaws.com/yarn-project-prod AS yarn-project-prod +# The version has been updated in yarn-project-prod. +# Adding COMMIT_TAG here to rebuild versioned image. +ARG COMMIT_TAG="" + ENTRYPOINT ["node", "--no-warnings", "/usr/src/yarn-project/aztec-sandbox/dest/bin/index.js"] EXPOSE 8079 8080 diff --git a/yarn-project/cli/Dockerfile b/yarn-project/cli/Dockerfile index 5663b1b079b..dfffe9b1843 100644 --- a/yarn-project/cli/Dockerfile +++ b/yarn-project/cli/Dockerfile @@ -2,6 +2,10 @@ FROM 278380418400.dkr.ecr.eu-west-2.amazonaws.com/yarn-project-prod AS yarn-proj ENTRYPOINT ["node", "--no-warnings", "/usr/src/yarn-project/cli/dest/bin/index.js"] +# The version has been updated in yarn-project-prod. +# Adding COMMIT_TAG here to rebuild versioned image. +ARG COMMIT_TAG="" + # Setup cache volume. ENV XDG_CACHE_HOME /cache RUN mkdir /cache && chmod 777 /cache From fe849e323526ea132c2a3ab41c8351a24f6e9cf4 Mon Sep 17 00:00:00 2001 From: David Banks <47112877+dbanks12@users.noreply.github.com> Date: Thu, 7 Dec 2023 11:55:51 -0500 Subject: [PATCH 07/35] docs(yellowpaper): rewrite section on tagged memory, misc rewording/cleanup (#3523) [See preview here](https://aztec-packages.vercel.app/docs/public-vm/state-model#types-and-tagged-memory) - Reworded and cleaned up tagged memory doc, merged it into state model doc - Moved random short section on VM security into a separate file - Made bit-format images opaque - Did some renaming (in-tag, dst-tag) - Moved image files to simpler paths - Misc other cleanup --- yellow-paper/docs/public-vm/Types.mdx | 0 yellow-paper/docs/public-vm/alu.md | 2 +- yellow-paper/docs/public-vm/control-flow.md | 2 +- .../docs/public-vm/gen/_InstructionSet.mdx | 470 +++++++++--------- .../public-vm/gen/images/bit-formats/ADD.png | Bin 5053 -> 5422 bytes .../gen/images/bit-formats/ADDRESS.png | Bin 3224 -> 3561 bytes .../public-vm/gen/images/bit-formats/AND.png | Bin 5072 -> 5445 bytes .../images/bit-formats/BLOCKL1GASLIMIT.png | Bin 3203 -> 3541 bytes .../images/bit-formats/BLOCKL2GASLIMIT.png | Bin 3216 -> 3564 bytes .../gen/images/bit-formats/BLOCKNUMBER.png | Bin 3172 -> 3517 bytes .../gen/images/bit-formats/BLOCKSROOT.png | Bin 4134 -> 4449 bytes .../public-vm/gen/images/bit-formats/CALL.png | Bin 9061 -> 8813 bytes .../gen/images/bit-formats/CALLDATACOPY.png | Bin 4636 -> 5315 bytes .../gen/images/bit-formats/CALLDEPTH.png | Bin 3213 -> 3552 bytes .../gen/images/bit-formats/CALLER.png | Bin 3204 -> 3546 bytes .../public-vm/gen/images/bit-formats/CAST.png | Bin 4407 -> 4686 bytes .../gen/images/bit-formats/CHAINID.png | Bin 3178 -> 3521 bytes .../public-vm/gen/images/bit-formats/CMOV.png | Bin 5377 -> 5853 bytes .../gen/images/bit-formats/COINBASE.png | Bin 3200 -> 3542 bytes .../gen/images/bit-formats/CONTRACTSROOT.png | Bin 4158 -> 4467 bytes .../public-vm/gen/images/bit-formats/DIV.png | Bin 5061 -> 5438 bytes .../gen/images/bit-formats/EMITNOTEHASH.png | Bin 3318 -> 3653 bytes .../gen/images/bit-formats/EMITNULLIFIER.png | Bin 3274 -> 3593 bytes .../public-vm/gen/images/bit-formats/EQ.png | Bin 5073 -> 5438 bytes .../gen/images/bit-formats/FEEPERL1GAS.png | Bin 3188 -> 3539 bytes .../gen/images/bit-formats/FEEPERL2GAS.png | Bin 3220 -> 3553 bytes .../gen/images/bit-formats/GLOBALSHASH.png | Bin 4129 -> 4450 bytes .../gen/images/bit-formats/GRANDROOT.png | Bin 4143 -> 4453 bytes .../public-vm/gen/images/bit-formats/JUMP.png | Bin 2367 -> 2873 bytes .../gen/images/bit-formats/JUMPI.png | Bin 3916 -> 4232 bytes .../gen/images/bit-formats/L1GAS.png | Bin 3218 -> 3554 bytes .../gen/images/bit-formats/L2GAS.png | Bin 3232 -> 3565 bytes .../public-vm/gen/images/bit-formats/LT.png | Bin 5074 -> 5422 bytes .../public-vm/gen/images/bit-formats/LTE.png | Bin 5071 -> 5441 bytes .../public-vm/gen/images/bit-formats/MOV.png | Bin 3994 -> 4293 bytes .../gen/images/bit-formats/MSGSROOT.png | Bin 4139 -> 4441 bytes .../public-vm/gen/images/bit-formats/NOT.png | Bin 4352 -> 4670 bytes .../gen/images/bit-formats/NOTESROOT.png | Bin 4173 -> 4464 bytes .../gen/images/bit-formats/NULLIFIERSROOT.png | Bin 4158 -> 4462 bytes .../public-vm/gen/images/bit-formats/OR.png | Bin 5057 -> 5424 bytes .../gen/images/bit-formats/ORIGIN.png | Bin 3197 -> 3550 bytes .../gen/images/bit-formats/PORTAL.png | Bin 3204 -> 3547 bytes .../gen/images/bit-formats/PUBLICDATAROOT.png | Bin 4165 -> 4473 bytes .../gen/images/bit-formats/REFUNDEE.png | Bin 3210 -> 3553 bytes .../gen/images/bit-formats/RETURN.png | Bin 3895 -> 4341 bytes .../gen/images/bit-formats/REVERT.png | Bin 3886 -> 4341 bytes .../gen/images/bit-formats/SENDL2TOL1MSG.png | Bin 3267 -> 3591 bytes .../public-vm/gen/images/bit-formats/SET.png | Bin 7004 -> 6614 bytes .../public-vm/gen/images/bit-formats/SHL.png | Bin 5048 -> 5419 bytes .../public-vm/gen/images/bit-formats/SHR.png | Bin 5066 -> 5425 bytes .../gen/images/bit-formats/SLOAD.png | Bin 3969 -> 4292 bytes .../gen/images/bit-formats/SSTORE.png | Bin 4021 -> 4329 bytes .../gen/images/bit-formats/STATICCALL.png | Bin 9056 -> 8813 bytes .../public-vm/gen/images/bit-formats/SUB.png | Bin 5057 -> 5414 bytes .../gen/images/bit-formats/TIMESTAMP.png | Bin 3223 -> 3552 bytes .../public-vm/gen/images/bit-formats/ULOG.png | Bin 3861 -> 4435 bytes .../gen/images/bit-formats/VERSION.png | Bin 3194 -> 3530 bytes .../public-vm/gen/images/bit-formats/XOR.png | Bin 5089 -> 5451 bytes .../{gen/images/alu => images}/alu.png | Bin .../avm-control-flow.png | Bin .../images/state-model => images}/memory.png | Bin yellow-paper/docs/public-vm/security.md | 4 + yellow-paper/docs/public-vm/state-model.md | 147 ++++-- yellow-paper/docs/public-vm/tagged-memory.md | 60 --- .../InstructionSet/InstructionSet.js | 144 +++--- .../InstructionSet/InstructionSize.js | 8 +- .../InstructionSet/genBitFormats.js | 1 + ...uctionSetMarkdownGen.js => genMarkdown.js} | 4 +- yellow-paper/src/preprocess/index.js | 2 +- 69 files changed, 429 insertions(+), 415 deletions(-) delete mode 100644 yellow-paper/docs/public-vm/Types.mdx rename yellow-paper/docs/public-vm/{gen/images/alu => images}/alu.png (100%) rename yellow-paper/docs/public-vm/{gen/images/control-flow => images}/avm-control-flow.png (100%) rename yellow-paper/docs/public-vm/{gen/images/state-model => images}/memory.png (100%) create mode 100644 yellow-paper/docs/public-vm/security.md delete mode 100644 yellow-paper/docs/public-vm/tagged-memory.md rename yellow-paper/src/preprocess/InstructionSet/{InstructionSetMarkdownGen.js => genMarkdown.js} (96%) diff --git a/yellow-paper/docs/public-vm/Types.mdx b/yellow-paper/docs/public-vm/Types.mdx deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/yellow-paper/docs/public-vm/alu.md b/yellow-paper/docs/public-vm/alu.md index bd83dde6a23..d4c0066d936 100644 --- a/yellow-paper/docs/public-vm/alu.md +++ b/yellow-paper/docs/public-vm/alu.md @@ -6,7 +6,7 @@ This component of the VM circuit evaluates both base-2 arithmetic operations and The following block diagram maps out an draft of the internal components of the "ALU" -![](./gen/images/alu/alu.png) +![](./images/alu.png) Notes: diff --git a/yellow-paper/docs/public-vm/control-flow.md b/yellow-paper/docs/public-vm/control-flow.md index 707e78ecf8b..836697fa346 100644 --- a/yellow-paper/docs/public-vm/control-flow.md +++ b/yellow-paper/docs/public-vm/control-flow.md @@ -14,7 +14,7 @@ The intention is for sub-operations to be implementable as independent VM circui # Control flow -![](./gen/images/control-flow/avm-control-flow.png) +![](./images/avm-control-flow.png) > Notation note: whenever the VM "sends a signal" to one or more VM components, this is analogous to defining a boolean column in the execution trace that toggles on/off specific functionality diff --git a/yellow-paper/docs/public-vm/gen/_InstructionSet.mdx b/yellow-paper/docs/public-vm/gen/_InstructionSet.mdx index ba11a18a0e9..4f13ec9bd98 100644 --- a/yellow-paper/docs/public-vm/gen/_InstructionSet.mdx +++ b/yellow-paper/docs/public-vm/gen/_InstructionSet.mdx @@ -1,7 +1,7 @@ [comment]: # (THIS IS A GENERATED FILE! DO NOT EDIT!) [comment]: # (Generated via `yarn preprocess`) -[comment]: # (Generated by InstructionSetMarkdownGen.tsx and InstructionSet.js) +[comment]: # (Generated by genMarkdown.js, InstructionSet.js, InstructionSize.js) import Markdown from 'react-markdown' import CodeBlock from '@theme/CodeBlock' @@ -16,7 +16,7 @@ Click on an instruction name to jump to its section. 0x00 [`ADD`](#isa-section-add) Addition (a + b) - 96 + 128 { `M[dstOffset] = M[aOffset] + M[bOffset] mod 2^k` } @@ -24,7 +24,7 @@ Click on an instruction name to jump to its section. 0x01 [`SUB`](#isa-section-sub) Subtraction (a - b) - 96 + 128 { `M[dstOffset] = M[aOffset] - M[bOffset] mod 2^k` } @@ -32,7 +32,7 @@ Click on an instruction name to jump to its section. 0x02 [`DIV`](#isa-section-div) Unsigned division (a / b) - 96 + 128 { `M[dstOffset] = M[aOffset] / M[bOffset]` } @@ -40,7 +40,7 @@ Click on an instruction name to jump to its section. 0x03 [`EQ`](#isa-section-eq) Equality check (a == b) - 96 + 128 { `M[dstOffset] = M[aOffset] == M[bOffset] ? 1 : 0` } @@ -48,7 +48,7 @@ Click on an instruction name to jump to its section. 0x04 [`LT`](#isa-section-lt) Less-than check (a < b) - 96 + 128 { `M[dstOffset] = M[aOffset] < M[bOffset] ? 1 : 0` } @@ -56,7 +56,7 @@ Click on an instruction name to jump to its section. 0x05 [`LTE`](#isa-section-lte) Less-than-or-equals check (a <= b) - 96 + 128 { `M[dstOffset] = M[aOffset] <= M[bOffset] ? 1 : 0` } @@ -64,7 +64,7 @@ Click on an instruction name to jump to its section. 0x06 [`AND`](#isa-section-and) Bitwise AND (a & b) - 96 + 128 { `M[dstOffset] = M[aOffset] AND M[bOffset]` } @@ -72,7 +72,7 @@ Click on an instruction name to jump to its section. 0x07 [`OR`](#isa-section-or) Bitwise OR (a | b) - 96 + 128 { `M[dstOffset] = M[aOffset] OR M[bOffset]` } @@ -80,7 +80,7 @@ Click on an instruction name to jump to its section. 0x08 [`XOR`](#isa-section-xor) Bitwise XOR (a ^ b) - 96 + 128 { `M[dstOffset] = M[aOffset] XOR M[bOffset]` } @@ -88,7 +88,7 @@ Click on an instruction name to jump to its section. 0x09 [`NOT`](#isa-section-not) Bitwise NOT (inversion) - 72 + 96 { `M[dstOffset] = NOT M[aOffset]` } @@ -96,7 +96,7 @@ Click on an instruction name to jump to its section. 0x0a [`SHL`](#isa-section-shl) Bitwise leftward shift (a << b) - 96 + 128 { `M[dstOffset] = M[aOffset] << M[bOffset]` } @@ -104,7 +104,7 @@ Click on an instruction name to jump to its section. 0x0b [`SHR`](#isa-section-shr) Bitwise rightward shift (a >> b) - 96 + 128 { `M[dstOffset] = M[aOffset] >> M[bOffset]` } @@ -112,15 +112,15 @@ Click on an instruction name to jump to its section. 0x0c [`CAST`](#isa-section-cast) Type cast - 72 + 96 { - `M[dstOffset] = cast(M[aOffset])` + `M[dstOffset] = cast(M[aOffset])` } 0x0d [`SET`](#isa-section-set) Set a memory word from a constant in the bytecode. - 48+N + 64+N { `M[dstOffset] = const` } @@ -128,7 +128,7 @@ Click on an instruction name to jump to its section. 0x0e [`MOV`](#isa-section-mov) Move a word from source memory location to destination`. - 64 + 88 { `M[dstOffset] = M[srcOffset]` } @@ -136,7 +136,7 @@ Click on an instruction name to jump to its section. 0x0f [`CMOV`](#isa-section-cmov) Move a word (conditionally chosen) from one memory location to another (`d = cond > 0 ? a : b`). - 112 + 152 { `M[dstOffset] = M[condOffset] > 0 ? M[aOffset] : M[bOffset]` } @@ -144,15 +144,15 @@ Click on an instruction name to jump to its section. 0x10 [`CALLDATACOPY`](#isa-section-calldatacopy) Copy calldata into memory. - 88 + 120 { - `M[dstOffset:dstOffset+size] = calldata[cdOffset:cdOffset+size]` + `M[dstOffset:dstOffset+copySize] = calldata[cdOffset:cdOffset+copySize]` } 0x11 [`SLOAD`](#isa-section-sload) Load a word from storage. - 64 + 88 { `M[dstOffset] = storage[M[slotOffset]]` } @@ -160,7 +160,7 @@ Click on an instruction name to jump to its section. 0x12 [`SSTORE`](#isa-section-sstore) Write a word to storage. - 64 + 88 { `storage[M[slotOffset]] = M[srcOffset]` } @@ -168,25 +168,25 @@ Click on an instruction name to jump to its section. 0x13 [`EMITNOTEHASH`](#isa-section-emitnotehash) Emit a new note hash to be inserted into the notes tree - 40 + 56 emitNoteHash(M[contentOffset]) 0x14 [`EMITNULLIFIER`](#isa-section-emitnullifier) Emit a new nullifier to be inserted into the nullifier tree - 40 + 56 emitNullifier(M[nullifierOffset]) 0x15 [`SENDL2TOL1MSG`](#isa-section-sendl2tol1msg) Send an L2-to-L1 message - 40 + 56 sendL2ToL1Message(M[contentOffset]) 0x16 [`JUMP`](#isa-section-jump) Jump to a location in the bytecode. - 32 + 48 { `PC = loc` } @@ -194,7 +194,7 @@ Click on an instruction name to jump to its section. 0x17 [`JUMPI`](#isa-section-jumpi) Conditionally jump to a location in the bytecode. - 64 + 88 { `PC = M[condOffset] > 0 ? loc : PC` } @@ -202,26 +202,26 @@ Click on an instruction name to jump to its section. 0x18 [`RETURN`](#isa-section-return) Halt execution with `success`, optionally returning some data. - 64 + 88 { - `return(M[offset:offset+size])` + `return(M[retOffset:retOffset+retSize])` } 0x19 [`REVERT`](#isa-section-revert) Halt execution with `failure`, reverting state changes and optionally returning some data. - 64 + 88 { - `revert(M[offset:offset+size])` + `revert(M[retOffset:retOffset+retSize])` } 0x1a [`CALL`](#isa-section-call) Call into another contract. - 208 + 248 {`M[successOffset] = call( - M[l1GasOffset], M[l2GasOffset], M[addrOffset], + M[gasOffset], M[gasOffset+1], M[addrOffset], M[argsOffset], M[argsSize], M[retOffset], M[retSize])`} @@ -229,10 +229,10 @@ Click on an instruction name to jump to its section. 0x1b [`STATICCALL`](#isa-section-staticcall) Call into another contract, disallowing persistent state modifications. - 208 + 248 {`M[successOffset] = staticcall( - M[l1GasOffset], M[l2GasOffset], M[addrOffset], + M[gasOffset], M[gasOffset+1], M[addrOffset], M[argsOffset], M[argsSize], M[retOffset], M[retSize])`} @@ -240,15 +240,15 @@ Click on an instruction name to jump to its section. 0x1c [`ULOG`](#isa-section-ulog) Emit an unencrypted log with data from the `field` memory page - 64 + 88 { - `ulog(M[offset:offset+size])` + `ulog(M[logOffset:logOffset+logSize])` } 0x1d [`CHAINID`](#isa-section-chainid) Get this rollup's L1 chain ID - 40 + 56 { `M[dstOffset] = Globals.chainId` } @@ -256,7 +256,7 @@ Click on an instruction name to jump to its section. 0x1e [`VERSION`](#isa-section-version) Get this rollup's L2 version ID - 40 + 56 { `M[dstOffset] = Globals.version` } @@ -264,7 +264,7 @@ Click on an instruction name to jump to its section. 0x1f [`BLOCKNUMBER`](#isa-section-blocknumber) Get this block's number - 40 + 56 { `M[dstOffset] = Globals.blocknumber` } @@ -272,7 +272,7 @@ Click on an instruction name to jump to its section. 0x20 [`TIMESTAMP`](#isa-section-timestamp) Get this L2 block's timestamp - 40 + 56 { `M[dstOffset] = Globals.timestamp` } @@ -280,7 +280,7 @@ Click on an instruction name to jump to its section. 0x21 [`COINBASE`](#isa-section-coinbase) Get the block's beneficiary address - 40 + 56 { `M[dstOffset] = Globals.coinbase` } @@ -288,7 +288,7 @@ Click on an instruction name to jump to its section. 0x22 [`BLOCKL1GASLIMIT`](#isa-section-blockl1gaslimit) Total amount of "L1 gas" that a block can consume - 40 + 56 { `M[dstOffset] = Globals.l1GasLimit` } @@ -296,7 +296,7 @@ Click on an instruction name to jump to its section. 0x23 [`BLOCKL2GASLIMIT`](#isa-section-blockl2gaslimit) Total amount of "L2 gas" that a block can consume - 40 + 56 { `M[dstOffset] = Globals.l2GasLimit` } @@ -304,7 +304,7 @@ Click on an instruction name to jump to its section. 0x24 [`NOTESROOT`](#isa-section-notesroot) Get the historical note-hash tree root as of the specified block number. - 64 + 88 { `M[dstOffset] = HistoricalBlockData[M[blockNumOffset]].note_hash_tree_root` } @@ -312,7 +312,7 @@ Click on an instruction name to jump to its section. 0x25 [`NULLIFIERSROOT`](#isa-section-nullroot) Get the historical nullifier tree root as of the specified block number. - 64 + 88 { `M[dstOffset] = HistoricalBlockData[M[blockNumOffset]].nullifier_tree_root` } @@ -320,7 +320,7 @@ Click on an instruction name to jump to its section. 0x26 [`CONTRACTSROOT`](#isa-section-contractsroot) Get the historical contracts tree root as of the specified block number. - 64 + 88 { `M[dstOffset] = HistoricalBlockData[M[blockNumOffset]].contracts_tree_root` } @@ -328,7 +328,7 @@ Click on an instruction name to jump to its section. 0x27 [`MSGSROOT`](#isa-section-msgsroot) Get the historical l1-to-l2 messages tree root as of the specified block number. - 64 + 88 { `M[dstOffset] = HistoricalBlockData[M[blockNumOffset]].l1_to_l2_messages_tree_root` } @@ -336,7 +336,7 @@ Click on an instruction name to jump to its section. 0x28 [`NOTESROOT`](#isa-section-notesroot) Get the historical note-hash tree root as of the specified block number. - 64 + 88 { `M[dstOffset] = HistoricalBlockData[M[blockNumOffset]].note_hash_tree_root` } @@ -344,7 +344,7 @@ Click on an instruction name to jump to its section. 0x29 [`PUBLICDATAROOT`](#isa-section-publicdataroot) Get the historical public data tree root as of the specified block number. - 64 + 88 { `M[dstOffset] = HistoricalBlockData[M[blockNumOffset]].public_data_tree_root` } @@ -352,7 +352,7 @@ Click on an instruction name to jump to its section. 0x2a [`GLOBALSHASH`](#isa-section-globalshash) Get the historical global variables hash as of the specified block number. - 64 + 88 { `M[dstOffset] = HistoricalBlockData[M[blockNumOffset]].global_variables_hash` } @@ -360,7 +360,7 @@ Click on an instruction name to jump to its section. 0x2b [`BLOCKSROOT`](#isa-section-blocksroot) Get the historical blocks tree root as of the specified block number. - 64 + 88 { `M[dstOffset] = HistoricalBlockData[M[blockNumOffset]].archive_root` } @@ -368,7 +368,7 @@ Click on an instruction name to jump to its section. 0x2c [`GRANDROOT`](#isa-section-grandroot) Get the historical grandfather tree root as of the specified block number. - 64 + 88 { `M[dstOffset] = HistoricalBlockData[M[blockNumOffset]].grandfather_tree_root` } @@ -376,7 +376,7 @@ Click on an instruction name to jump to its section. 0x2d [`ORIGIN`](#isa-section-origin) Get the transaction's origination address - 40 + 56 { `M[dstOffset] = TxContext.origin` } @@ -384,7 +384,7 @@ Click on an instruction name to jump to its section. 0x2e [`REFUNDEE`](#isa-section-refundee) The recipient of fee refunds for this transaction - 40 + 56 { `M[dstOffset] = TxContext.refundee` } @@ -392,7 +392,7 @@ Click on an instruction name to jump to its section. 0x2f [`FEEPERL1GAS`](#isa-section-feeperl1gas) The fee to be paid per "L1 gas" - set by the transaction's original caller - 40 + 56 { `M[dstOffset] = TxContext.feePerL1Gas` } @@ -400,7 +400,7 @@ Click on an instruction name to jump to its section. 0x30 [`FEEPERL2GAS`](#isa-section-feeperl2gas) The fee to be paid per "L2 gas" - set by the transaction's original caller - 40 + 56 { `M[dstOffset] = TxContext.feePerL2Gas` } @@ -408,7 +408,7 @@ Click on an instruction name to jump to its section. 0x31 [`CALLER`](#isa-section-caller) Get the address of the sender (the caller's context) - 40 + 56 { `M[dstOffset] = CallContext.sender` } @@ -416,7 +416,7 @@ Click on an instruction name to jump to its section. 0x32 [`ADDRESS`](#isa-section-address) Get the address of the currently executing l2 contract - 40 + 56 { `M[dstOffset] = CallContext.storageContractAddress` } @@ -424,7 +424,7 @@ Click on an instruction name to jump to its section. 0x33 [`PORTAL`](#isa-section-portal) Get the address of the l1 portal contract - 40 + 56 { `M[dstOffset] = CallContext.portalAddress` } @@ -432,7 +432,7 @@ Click on an instruction name to jump to its section. 0x34 [`CALLDEPTH`](#isa-section-calldepth) Get how many calls deep the current call context is - 40 + 56 { `M[dstOffset] = CallContext.calldepth` } @@ -440,7 +440,7 @@ Click on an instruction name to jump to its section. 0x35 [`L1GAS`](#isa-section-l1gas) Remaining "L1 gas" for this call (after this instruction). - 40 + 56 { `M[dstOffset] = LatestContext.l1Gas` } @@ -448,7 +448,7 @@ Click on an instruction name to jump to its section. 0x36 [`L2GAS`](#isa-section-l2gas) Remaining "L2 gas" for this call (after this instruction). - 40 + 56 { `M[dstOffset] = LatestContext.l2Gas` } @@ -466,17 +466,17 @@ Addition (a + b) - **Category**: arithmetic - **Flags**: - **indirect**: Toggles whether each memory-offset argument is an indirect offset. 0th bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. - - **op-type**: The [type/size](./Types) to check inputs against and tag the output with. + - **in-tag**: The [tag/size](./state-model#tags-and-tagged-memory) to check inputs against and tag the destination with. - **Args**: - **aOffset**: memory offset of the operation's left input - **bOffset**: memory offset of the operation's right input - **dstOffset**: memory offset specifying where to store operation's result - **Expression**: `M[dstOffset] = M[aOffset] + M[bOffset] mod 2^k` -- **Tag checks**: `T[aOffset] == T[bOffset] == op-type` -- **Tag updates**: `T[dstOffset] = op-type` -- **Bit-size**: 96 +- **Tag checks**: `T[aOffset] == T[bOffset] == in-tag` +- **Tag updates**: `T[dstOffset] = in-tag` +- **Bit-size**: 128 -![](./images/bit-formats/ADD.png) +[![](./images/bit-formats/ADD.png)](./images/bit-formats/ADD.png) ### `SUB` (0x01) Subtraction (a - b) @@ -486,17 +486,17 @@ Subtraction (a - b) - **Category**: arithmetic - **Flags**: - **indirect**: Toggles whether each memory-offset argument is an indirect offset. 0th bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. - - **op-type**: The [type/size](./Types) to check inputs against and tag the output with. + - **in-tag**: The [tag/size](./state-model#tags-and-tagged-memory) to check inputs against and tag the destination with. - **Args**: - **aOffset**: memory offset of the operation's left input - **bOffset**: memory offset of the operation's right input - **dstOffset**: memory offset specifying where to store operation's result - **Expression**: `M[dstOffset] = M[aOffset] - M[bOffset] mod 2^k` -- **Tag checks**: `T[aOffset] == T[bOffset] == op-type` -- **Tag updates**: `T[dstOffset] = op-type` -- **Bit-size**: 96 +- **Tag checks**: `T[aOffset] == T[bOffset] == in-tag` +- **Tag updates**: `T[dstOffset] = in-tag` +- **Bit-size**: 128 -![](./images/bit-formats/SUB.png) +[![](./images/bit-formats/SUB.png)](./images/bit-formats/SUB.png) ### `DIV` (0x02) Unsigned division (a / b) @@ -506,17 +506,17 @@ Unsigned division (a / b) - **Category**: arithmetic - **Flags**: - **indirect**: Toggles whether each memory-offset argument is an indirect offset. 0th bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. - - **op-type**: The [type/size](./Types) to check inputs against and tag the output with. + - **in-tag**: The [tag/size](./state-model#tags-and-tagged-memory) to check inputs against and tag the destination with. - **Args**: - **aOffset**: memory offset of the operation's left input - **bOffset**: memory offset of the operation's right input - **dstOffset**: memory offset specifying where to store operation's result - **Expression**: `M[dstOffset] = M[aOffset] / M[bOffset]` -- **Tag checks**: `T[aOffset] == T[bOffset] == op-type` -- **Tag updates**: `T[dstOffset] = op-type` -- **Bit-size**: 96 +- **Tag checks**: `T[aOffset] == T[bOffset] == in-tag` +- **Tag updates**: `T[dstOffset] = in-tag` +- **Bit-size**: 128 -![](./images/bit-formats/DIV.png) +[![](./images/bit-formats/DIV.png)](./images/bit-formats/DIV.png) ### `EQ` (0x03) Equality check (a == b) @@ -526,17 +526,17 @@ Equality check (a == b) - **Category**: conditional - **Flags**: - **indirect**: Toggles whether each memory-offset argument is an indirect offset. 0th bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. - - **op-type**: The [type/size](./Types) to check inputs against and tag the output with. + - **in-tag**: The [tag/size](./state-model#tags-and-tagged-memory) to check inputs against and tag the destination with. - **Args**: - **aOffset**: memory offset of the operation's left input - **bOffset**: memory offset of the operation's right input - **dstOffset**: memory offset specifying where to store operation's result - **Expression**: `M[dstOffset] = M[aOffset] == M[bOffset] ? 1 : 0` -- **Tag checks**: `T[aOffset] == T[bOffset] == op-type` -- **Tag updates**: `T[dstOffset] = op-type` -- **Bit-size**: 96 +- **Tag checks**: `T[aOffset] == T[bOffset] == in-tag` +- **Tag updates**: `T[dstOffset] = in-tag` +- **Bit-size**: 128 -![](./images/bit-formats/EQ.png) +[![](./images/bit-formats/EQ.png)](./images/bit-formats/EQ.png) ### `LT` (0x04) Less-than check (a < b) @@ -546,17 +546,17 @@ Less-than check (a < b) - **Category**: conditional - **Flags**: - **indirect**: Toggles whether each memory-offset argument is an indirect offset. 0th bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. - - **op-type**: The [type/size](./Types) to check inputs against and tag the output with. + - **in-tag**: The [tag/size](./state-model#tags-and-tagged-memory) to check inputs against and tag the destination with. - **Args**: - **aOffset**: memory offset of the operation's left input - **bOffset**: memory offset of the operation's right input - **dstOffset**: memory offset specifying where to store operation's result - **Expression**: `M[dstOffset] = M[aOffset] < M[bOffset] ? 1 : 0` -- **Tag checks**: `T[aOffset] == T[bOffset] == op-type` -- **Tag updates**: `T[dstOffset] = op-type` -- **Bit-size**: 96 +- **Tag checks**: `T[aOffset] == T[bOffset] == in-tag` +- **Tag updates**: `T[dstOffset] = in-tag` +- **Bit-size**: 128 -![](./images/bit-formats/LT.png) +[![](./images/bit-formats/LT.png)](./images/bit-formats/LT.png) ### `LTE` (0x05) Less-than-or-equals check (a <= b) @@ -566,17 +566,17 @@ Less-than-or-equals check (a <= b) - **Category**: conditional - **Flags**: - **indirect**: Toggles whether each memory-offset argument is an indirect offset. 0th bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. - - **op-type**: The [type/size](./Types) to check inputs against and tag the output with. + - **in-tag**: The [tag/size](./state-model#tags-and-tagged-memory) to check inputs against and tag the destination with. - **Args**: - **aOffset**: memory offset of the operation's left input - **bOffset**: memory offset of the operation's right input - **dstOffset**: memory offset specifying where to store operation's result - **Expression**: `M[dstOffset] = M[aOffset] <= M[bOffset] ? 1 : 0` -- **Tag checks**: `T[aOffset] == T[bOffset] == op-type` -- **Tag updates**: `T[dstOffset] = op-type` -- **Bit-size**: 96 +- **Tag checks**: `T[aOffset] == T[bOffset] == in-tag` +- **Tag updates**: `T[dstOffset] = in-tag` +- **Bit-size**: 128 -![](./images/bit-formats/LTE.png) +[![](./images/bit-formats/LTE.png)](./images/bit-formats/LTE.png) ### `AND` (0x06) Bitwise AND (a & b) @@ -586,17 +586,17 @@ Bitwise AND (a & b) - **Category**: bitwise - **Flags**: - **indirect**: Toggles whether each memory-offset argument is an indirect offset. 0th bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. - - **op-type**: The [type/size](./Types) to check inputs against and tag the output with. + - **in-tag**: The [tag/size](./state-model#tags-and-tagged-memory) to check inputs against and tag the destination with. - **Args**: - **aOffset**: memory offset of the operation's left input - **bOffset**: memory offset of the operation's right input - **dstOffset**: memory offset specifying where to store operation's result - **Expression**: `M[dstOffset] = M[aOffset] AND M[bOffset]` -- **Tag checks**: `T[aOffset] == T[bOffset] == op-type` -- **Tag updates**: `T[dstOffset] = op-type` -- **Bit-size**: 96 +- **Tag checks**: `T[aOffset] == T[bOffset] == in-tag` +- **Tag updates**: `T[dstOffset] = in-tag` +- **Bit-size**: 128 -![](./images/bit-formats/AND.png) +[![](./images/bit-formats/AND.png)](./images/bit-formats/AND.png) ### `OR` (0x07) Bitwise OR (a | b) @@ -606,17 +606,17 @@ Bitwise OR (a | b) - **Category**: bitwise - **Flags**: - **indirect**: Toggles whether each memory-offset argument is an indirect offset. 0th bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. - - **op-type**: The [type/size](./Types) to check inputs against and tag the output with. + - **in-tag**: The [tag/size](./state-model#tags-and-tagged-memory) to check inputs against and tag the destination with. - **Args**: - **aOffset**: memory offset of the operation's left input - **bOffset**: memory offset of the operation's right input - **dstOffset**: memory offset specifying where to store operation's result - **Expression**: `M[dstOffset] = M[aOffset] OR M[bOffset]` -- **Tag checks**: `T[aOffset] == T[bOffset] == op-type` -- **Tag updates**: `T[dstOffset] = op-type` -- **Bit-size**: 96 +- **Tag checks**: `T[aOffset] == T[bOffset] == in-tag` +- **Tag updates**: `T[dstOffset] = in-tag` +- **Bit-size**: 128 -![](./images/bit-formats/OR.png) +[![](./images/bit-formats/OR.png)](./images/bit-formats/OR.png) ### `XOR` (0x08) Bitwise XOR (a ^ b) @@ -626,17 +626,17 @@ Bitwise XOR (a ^ b) - **Category**: bitwise - **Flags**: - **indirect**: Toggles whether each memory-offset argument is an indirect offset. 0th bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. - - **op-type**: The [type/size](./Types) to check inputs against and tag the output with. + - **in-tag**: The [tag/size](./state-model#tags-and-tagged-memory) to check inputs against and tag the destination with. - **Args**: - **aOffset**: memory offset of the operation's left input - **bOffset**: memory offset of the operation's right input - **dstOffset**: memory offset specifying where to store operation's result - **Expression**: `M[dstOffset] = M[aOffset] XOR M[bOffset]` -- **Tag checks**: `T[aOffset] == T[bOffset] == op-type` -- **Tag updates**: `T[dstOffset] = op-type` -- **Bit-size**: 96 +- **Tag checks**: `T[aOffset] == T[bOffset] == in-tag` +- **Tag updates**: `T[dstOffset] = in-tag` +- **Bit-size**: 128 -![](./images/bit-formats/XOR.png) +[![](./images/bit-formats/XOR.png)](./images/bit-formats/XOR.png) ### `NOT` (0x09) Bitwise NOT (inversion) @@ -646,16 +646,16 @@ Bitwise NOT (inversion) - **Category**: bitwise - **Flags**: - **indirect**: Toggles whether each memory-offset argument is an indirect offset. 0th bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. - - **op-type**: The [type/size](./Types) to check inputs against and tag the output with. + - **in-tag**: The [tag/size](./state-model#tags-and-tagged-memory) to check inputs against and tag the destination with. - **Args**: - **aOffset**: memory offset of the operation's input - **dstOffset**: memory offset specifying where to store operation's result - **Expression**: `M[dstOffset] = NOT M[aOffset]` -- **Tag checks**: `T[aOffset] == op-type` -- **Tag updates**: `T[dstOffset] = op-type` -- **Bit-size**: 72 +- **Tag checks**: `T[aOffset] == in-tag` +- **Tag updates**: `T[dstOffset] = in-tag` +- **Bit-size**: 96 -![](./images/bit-formats/NOT.png) +[![](./images/bit-formats/NOT.png)](./images/bit-formats/NOT.png) ### `SHL` (0x0a) Bitwise leftward shift (a << b) @@ -665,17 +665,17 @@ Bitwise leftward shift (a << b) - **Category**: bitwise - **Flags**: - **indirect**: Toggles whether each memory-offset argument is an indirect offset. 0th bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. - - **op-type**: The [type/size](./Types) to check inputs against and tag the output with. + - **in-tag**: The [tag/size](./state-model#tags-and-tagged-memory) to check inputs against and tag the destination with. - **Args**: - **aOffset**: memory offset of the operation's left input - **bOffset**: memory offset of the operation's right input - **dstOffset**: memory offset specifying where to store operation's result - **Expression**: `M[dstOffset] = M[aOffset] << M[bOffset]` -- **Tag checks**: `T[aOffset] == T[bOffset] == op-type` -- **Tag updates**: `T[dstOffset] = op-type` -- **Bit-size**: 96 +- **Tag checks**: `T[aOffset] == T[bOffset] == in-tag` +- **Tag updates**: `T[dstOffset] = in-tag` +- **Bit-size**: 128 -![](./images/bit-formats/SHL.png) +[![](./images/bit-formats/SHL.png)](./images/bit-formats/SHL.png) ### `SHR` (0x0b) Bitwise rightward shift (a >> b) @@ -685,17 +685,17 @@ Bitwise rightward shift (a >> b) - **Category**: bitwise - **Flags**: - **indirect**: Toggles whether each memory-offset argument is an indirect offset. 0th bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. - - **op-type**: The [type/size](./Types) to check inputs against and tag the output with. + - **in-tag**: The [tag/size](./state-model#tags-and-tagged-memory) to check inputs against and tag the destination with. - **Args**: - **aOffset**: memory offset of the operation's left input - **bOffset**: memory offset of the operation's right input - **dstOffset**: memory offset specifying where to store operation's result - **Expression**: `M[dstOffset] = M[aOffset] >> M[bOffset]` -- **Tag checks**: `T[aOffset] == T[bOffset] == op-type` -- **Tag updates**: `T[dstOffset] = op-type` -- **Bit-size**: 96 +- **Tag checks**: `T[aOffset] == T[bOffset] == in-tag` +- **Tag updates**: `T[dstOffset] = in-tag` +- **Bit-size**: 128 -![](./images/bit-formats/SHR.png) +[![](./images/bit-formats/SHR.png)](./images/bit-formats/SHR.png) ### `CAST` (0x0c) Type cast @@ -705,16 +705,16 @@ Type cast - **Category**: types - **Flags**: - **indirect**: Toggles whether each memory-offset argument is an indirect offset. 0th bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. - - **dest-type**: The [type/size](./Types) to tag the output with when different from `op-type`. + - **dst-tag**: The [tag/size](./state-model#tags-and-tagged-memory) to tag the destination with but not to check inputs against. - **Args**: - **aOffset**: memory offset of word to cast - **dstOffset**: memory offset specifying where to store operation's result -- **Expression**: `M[dstOffset] = cast(M[aOffset])` -- **Details**: Cast a word in memory based on the `dest-type` specified in the bytecode. Truncates when casting to a smaller type, left-zero-pads when casting to a larger type. -- **Tag updates**: `T[dstOffset] = dest-type` -- **Bit-size**: 72 +- **Expression**: `M[dstOffset] = cast(M[aOffset])` +- **Details**: Cast a word in memory based on the `dst-tag` specified in the bytecode. Truncates when casting to a smaller type, left-zero-pads when casting to a larger type. See [here](./state-model#cast-and-tag-conversions) for more details. +- **Tag updates**: `T[dstOffset] = dst-tag` +- **Bit-size**: 96 -![](./images/bit-formats/CAST.png) +[![](./images/bit-formats/CAST.png)](./images/bit-formats/CAST.png) ### `SET` (0x0d) Set a memory word from a constant in the bytecode. @@ -724,16 +724,16 @@ Set a memory word from a constant in the bytecode. - **Category**: memory - **Flags**: - **indirect**: Toggles whether each memory-offset argument is an indirect offset. 0th bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. - - **op-type**: The [type/size](./Types) to check inputs against and tag the output with. `field` type is NOT supported for SET. + - **in-tag**: The [type/size](./state-model#tags-and-tagged-memory) to check inputs against and tag the destination with. `field` type is NOT supported for SET. - **Args**: - **const**: an N-bit constant value from the bytecode to store in memory (any type except `field`) - **dstOffset**: memory offset specifying where to store the constant - **Expression**: `M[dstOffset] = const` -- **Details**: Set memory word at `dstOffset` to `const`'s immediate value. `const`'s bit-size (N) can be 8, 16, 32, 64, or 128 based on `op-type`. It _cannot be 254 (`field` type)_! -- **Tag updates**: `T[dstOffset] = op-type` -- **Bit-size**: 48+N +- **Details**: Set memory word at `dstOffset` to `const`'s immediate value. `const`'s bit-size (N) can be 8, 16, 32, 64, or 128 based on `in-tag`. It _cannot be 254 (`field` type)_! +- **Tag updates**: `T[dstOffset] = in-tag` +- **Bit-size**: 64+N -![](./images/bit-formats/SET.png) +[![](./images/bit-formats/SET.png)](./images/bit-formats/SET.png) ### `MOV` (0x0e) Move a word from source memory location to destination`. @@ -748,9 +748,9 @@ Move a word from source memory location to destination`. - **dstOffset**: memory offset specifying where to store that word - **Expression**: `M[dstOffset] = M[srcOffset]` - **Tag updates**: `T[dstOffset] = T[srcOffset]` -- **Bit-size**: 64 +- **Bit-size**: 88 -![](./images/bit-formats/MOV.png) +[![](./images/bit-formats/MOV.png)](./images/bit-formats/MOV.png) ### `CMOV` (0x0f) Move a word (conditionally chosen) from one memory location to another (`d = cond > 0 ? a : b`). @@ -768,9 +768,9 @@ Move a word (conditionally chosen) from one memory location to another (`d = con - **Expression**: `M[dstOffset] = M[condOffset] > 0 ? M[aOffset] : M[bOffset]` - **Details**: One of two source memory locations is chosen based on the condition. `T[condOffset]` is not checked because the greater-than-zero suboperation is the same regardless of type. - **Tag updates**: `T[dstOffset] = M[condOffset] > 0 ? T[aOffset] : T[bOffset]` -- **Bit-size**: 112 +- **Bit-size**: 152 -![](./images/bit-formats/CMOV.png) +[![](./images/bit-formats/CMOV.png)](./images/bit-formats/CMOV.png) ### `CALLDATACOPY` (0x10) Copy calldata into memory. @@ -782,14 +782,14 @@ Copy calldata into memory. - **indirect**: Toggles whether each memory-offset argument is an indirect offset. 0th bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. - **Args**: - **cdOffset**: offset into calldata to copy from - - **size**: number of words to copy + - **copySize**: number of words to copy - **dstOffset**: memory offset specifying where to copy the first word to -- **Expression**: `M[dstOffset:dstOffset+size] = calldata[cdOffset:cdOffset+size]` +- **Expression**: `M[dstOffset:dstOffset+copySize] = calldata[cdOffset:cdOffset+copySize]` - **Details**: Calldata is read-only and cannot be directly operated on by other instructions. This instruction moves words from calldata into memory so they can be operated on normally. -- **Tag updates**: `T[dstOffset:dstOffset+size] = field` -- **Bit-size**: 88 +- **Tag updates**: `T[dstOffset:dstOffset+copySize] = field` +- **Bit-size**: 120 -![](./images/bit-formats/CALLDATACOPY.png) +[![](./images/bit-formats/CALLDATACOPY.png)](./images/bit-formats/CALLDATACOPY.png) ### `SLOAD` (0x11) Load a word from storage. @@ -805,9 +805,9 @@ Load a word from storage. - **Expression**: `M[dstOffset] = storage[M[slotOffset]]` - **Details**: Load a word from this contract's persistent public storage into memory. - **Tag updates**: `T[dstOffset] = field` -- **Bit-size**: 64 +- **Bit-size**: 88 -![](./images/bit-formats/SLOAD.png) +[![](./images/bit-formats/SLOAD.png)](./images/bit-formats/SLOAD.png) ### `SSTORE` (0x12) Write a word to storage. @@ -822,9 +822,9 @@ Write a word to storage. - **slotOffset**: memory offset containing the storage slot to store to - **Expression**: `storage[M[slotOffset]] = M[srcOffset]` - **Details**: Store a word from memory into this contract's persistent public storage. -- **Bit-size**: 64 +- **Bit-size**: 88 -![](./images/bit-formats/SSTORE.png) +[![](./images/bit-formats/SSTORE.png)](./images/bit-formats/SSTORE.png) ### `EMITNOTEHASH` (0x13) Emit a new note hash to be inserted into the notes tree @@ -837,9 +837,9 @@ Emit a new note hash to be inserted into the notes tree - **Args**: - **noteHashOffset**: memory offset of the note hash - **Expression**: emitNoteHash(M[contentOffset]) -- **Bit-size**: 40 +- **Bit-size**: 56 -![](./images/bit-formats/EMITNOTEHASH.png) +[![](./images/bit-formats/EMITNOTEHASH.png)](./images/bit-formats/EMITNOTEHASH.png) ### `EMITNULLIFIER` (0x14) Emit a new nullifier to be inserted into the nullifier tree @@ -852,9 +852,9 @@ Emit a new nullifier to be inserted into the nullifier tree - **Args**: - **nullifierOffset**: memory offset of nullifier - **Expression**: emitNullifier(M[nullifierOffset]) -- **Bit-size**: 40 +- **Bit-size**: 56 -![](./images/bit-formats/EMITNULLIFIER.png) +[![](./images/bit-formats/EMITNULLIFIER.png)](./images/bit-formats/EMITNULLIFIER.png) ### `SENDL2TOL1MSG` (0x15) Send an L2-to-L1 message @@ -867,9 +867,9 @@ Send an L2-to-L1 message - **Args**: - **contentOffset**: memory offset of the message content - **Expression**: sendL2ToL1Message(M[contentOffset]) -- **Bit-size**: 40 +- **Bit-size**: 56 -![](./images/bit-formats/SENDL2TOL1MSG.png) +[![](./images/bit-formats/SENDL2TOL1MSG.png)](./images/bit-formats/SENDL2TOL1MSG.png) ### `JUMP` (0x16) Jump to a location in the bytecode. @@ -881,9 +881,9 @@ Jump to a location in the bytecode. - **loc**: target location to jump to - **Expression**: `PC = loc` - **Details**: Target location is an immediate value (a constant in the bytecode). -- **Bit-size**: 32 +- **Bit-size**: 48 -![](./images/bit-formats/JUMP.png) +[![](./images/bit-formats/JUMP.png)](./images/bit-formats/JUMP.png) ### `JUMPI` (0x17) Conditionally jump to a location in the bytecode. @@ -898,9 +898,9 @@ Conditionally jump to a location in the bytecode. - **condOffset**: memory offset of the operations 'conditional' input - **Expression**: `PC = M[condOffset] > 0 ? loc : PC` - **Details**: Target location is an immediate value (a constant in the bytecode). `T[condOffset]` is not checked because the greater-than-zero suboperation is the same regardless of type. -- **Bit-size**: 64 +- **Bit-size**: 88 -![](./images/bit-formats/JUMPI.png) +[![](./images/bit-formats/JUMPI.png)](./images/bit-formats/JUMPI.png) ### `RETURN` (0x18) Halt execution with `success`, optionally returning some data. @@ -911,13 +911,13 @@ Halt execution with `success`, optionally returning some data. - **Flags**: - **indirect**: Toggles whether each memory-offset argument is an indirect offset. 0th bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. - **Args**: - - **offset**: memory offset of first word to return - - **size**: number of words to return -- **Expression**: `return(M[offset:offset+size])` + - **retOffset**: memory offset of first word to return + - **retSize**: number of words to return +- **Expression**: `return(M[retOffset:retOffset+retSize])` - **Details**: Return control flow to the calling context/contract. -- **Bit-size**: 64 +- **Bit-size**: 88 -![](./images/bit-formats/RETURN.png) +[![](./images/bit-formats/RETURN.png)](./images/bit-formats/RETURN.png) ### `REVERT` (0x19) Halt execution with `failure`, reverting state changes and optionally returning some data. @@ -928,13 +928,13 @@ Halt execution with `failure`, reverting state changes and optionally returning - **Flags**: - **indirect**: Toggles whether each memory-offset argument is an indirect offset. 0th bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. - **Args**: - - **offset**: memory offset of first word to return - - **size**: number of words to return -- **Expression**: `revert(M[offset:offset+size])` + - **retOffset**: memory offset of first word to return + - **retSize**: number of words to return +- **Expression**: `revert(M[retOffset:retOffset+retSize])` - **Details**: Return control flow to the calling context/contract. -- **Bit-size**: 64 +- **Bit-size**: 88 -![](./images/bit-formats/REVERT.png) +[![](./images/bit-formats/REVERT.png)](./images/bit-formats/REVERT.png) ### `CALL` (0x1a) Call into another contract. @@ -945,8 +945,7 @@ Call into another contract. - **Flags**: - **indirect**: Toggles whether each memory-offset argument is an indirect offset. 0th bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. - **Args**: - - **l1GasOffset**: amount of L1 gas to provide to the callee - - **l2GasOffset**: amount of L2 gas to provide to the callee + - **gasOffset**: offset to two words containing `{l1Gas, l2Gas}`: amount of L1 and L2 gas to provide to the callee - **addrOffset**: address of the contract to call - **argsOffset**: memory offset to args (will become the callee's calldata) - **argsSize**: number of words to pass via callee's calldata @@ -956,22 +955,22 @@ Call into another contract. - **Expression**: {`M[successOffset] = call( - M[l1GasOffset], M[l2GasOffset], M[addrOffset], + M[gasOffset], M[gasOffset+1], M[addrOffset], M[argsOffset], M[argsSize], M[retOffset], M[retSize])`} - **Details**: Creates a new CallContext, triggers execution of the corresponding contract code, and then resumes execution in the current CallContext. A non-existent contract or one with no code will return success. Nested call has an incremented `CallContext.calldepth`. -- **Tag checks**: `T[l1GasOffset] == T[l2GasOffset] == u32` +- **Tag checks**: `T[gasOffset] == T[gasOffset+1] == u32` - **Tag updates**: {`T[successOffset] = u8 T[retOffset:retOffset+retSize] = field`} -- **Bit-size**: 208 +- **Bit-size**: 248 -![](./images/bit-formats/CALL.png) +[![](./images/bit-formats/CALL.png)](./images/bit-formats/CALL.png) ### `STATICCALL` (0x1b) Call into another contract, disallowing persistent state modifications. @@ -982,8 +981,7 @@ Call into another contract, disallowing persistent state modifications. - **Flags**: - **indirect**: Toggles whether each memory-offset argument is an indirect offset. 0th bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. - **Args**: - - **l1GasOffset**: amount of L1 gas to provide to the callee - - **l2GasOffset**: amount of L2 gas to provide to the callee + - **gasOffset**: offset to two words containing `{l1Gas, l2Gas}`: amount of L1 and L2 gas to provide to the callee - **addrOffset**: address of the contract to call - **argsOffset**: memory offset to args (will become the callee's calldata) - **argsSize**: number of words to pass via callee's calldata @@ -993,20 +991,20 @@ Call into another contract, disallowing persistent state modifications. - **Expression**: {`M[successOffset] = staticcall( - M[l1GasOffset], M[l2GasOffset], M[addrOffset], + M[gasOffset], M[gasOffset+1], M[addrOffset], M[argsOffset], M[argsSize], M[retOffset], M[retSize])`} - **Details**: Same as `CALL`, but the callee is cannot modify persistent state. Disallowed instructions are `SSTORE`, `ULOG`, `CALL`. -- **Tag checks**: `T[l1GasOffset] == T[l2GasOffset] == u32` +- **Tag checks**: `T[gasOffset] == T[gasOffset+1] == u32` - **Tag updates**: {`T[successOffset] = u8 T[retOffset:retOffset+retSize] = field`} -- **Bit-size**: 208 +- **Bit-size**: 248 -![](./images/bit-formats/STATICCALL.png) +[![](./images/bit-formats/STATICCALL.png)](./images/bit-formats/STATICCALL.png) ### `ULOG` (0x1c) Emit an unencrypted log with data from the `field` memory page @@ -1017,12 +1015,12 @@ Emit an unencrypted log with data from the `field` memory page - **Flags**: - **indirect**: Toggles whether each memory-offset argument is an indirect offset. 0th bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. - **Args**: - - **offset**: memory offset of the data to log - - **size**: number of words to log -- **Expression**: `ulog(M[offset:offset+size])` -- **Bit-size**: 64 + - **logOffset**: memory offset of the data to log + - **logSize**: number of words to log +- **Expression**: `ulog(M[logOffset:logOffset+logSize])` +- **Bit-size**: 88 -![](./images/bit-formats/ULOG.png) +[![](./images/bit-formats/ULOG.png)](./images/bit-formats/ULOG.png) ### `CHAINID` (0x1d) Get this rollup's L1 chain ID @@ -1036,9 +1034,9 @@ Get this rollup's L1 chain ID - **dstOffset**: memory offset specifying where to store operation's result - **Expression**: `M[dstOffset] = Globals.chainId` - **Tag updates**: `T[dstOffset] = u32` -- **Bit-size**: 40 +- **Bit-size**: 56 -![](./images/bit-formats/CHAINID.png) +[![](./images/bit-formats/CHAINID.png)](./images/bit-formats/CHAINID.png) ### `VERSION` (0x1e) Get this rollup's L2 version ID @@ -1052,9 +1050,9 @@ Get this rollup's L2 version ID - **dstOffset**: memory offset specifying where to store operation's result - **Expression**: `M[dstOffset] = Globals.version` - **Tag updates**: `T[dstOffset] = u32` -- **Bit-size**: 40 +- **Bit-size**: 56 -![](./images/bit-formats/VERSION.png) +[![](./images/bit-formats/VERSION.png)](./images/bit-formats/VERSION.png) ### `BLOCKNUMBER` (0x1f) Get this block's number @@ -1068,9 +1066,9 @@ Get this block's number - **dstOffset**: memory offset specifying where to store operation's result - **Expression**: `M[dstOffset] = Globals.blocknumber` - **Tag updates**: `T[dstOffset] = u32` -- **Bit-size**: 40 +- **Bit-size**: 56 -![](./images/bit-formats/BLOCKNUMBER.png) +[![](./images/bit-formats/BLOCKNUMBER.png)](./images/bit-formats/BLOCKNUMBER.png) ### `TIMESTAMP` (0x20) Get this L2 block's timestamp @@ -1084,9 +1082,9 @@ Get this L2 block's timestamp - **dstOffset**: memory offset specifying where to store operation's result - **Expression**: `M[dstOffset] = Globals.timestamp` - **Tag updates**: `T[dstOffset] = u64` -- **Bit-size**: 40 +- **Bit-size**: 56 -![](./images/bit-formats/TIMESTAMP.png) +[![](./images/bit-formats/TIMESTAMP.png)](./images/bit-formats/TIMESTAMP.png) ### `COINBASE` (0x21) Get the block's beneficiary address @@ -1100,9 +1098,9 @@ Get the block's beneficiary address - **dstOffset**: memory offset specifying where to store operation's result - **Expression**: `M[dstOffset] = Globals.coinbase` - **Tag updates**: `T[dstOffset] = u32` -- **Bit-size**: 40 +- **Bit-size**: 56 -![](./images/bit-formats/COINBASE.png) +[![](./images/bit-formats/COINBASE.png)](./images/bit-formats/COINBASE.png) ### `BLOCKL1GASLIMIT` (0x22) Total amount of "L1 gas" that a block can consume @@ -1116,9 +1114,9 @@ Total amount of "L1 gas" that a block can consume - **dstOffset**: memory offset specifying where to store operation's result - **Expression**: `M[dstOffset] = Globals.l1GasLimit` - **Tag updates**: `T[dstOffset] = u32` -- **Bit-size**: 40 +- **Bit-size**: 56 -![](./images/bit-formats/BLOCKL1GASLIMIT.png) +[![](./images/bit-formats/BLOCKL1GASLIMIT.png)](./images/bit-formats/BLOCKL1GASLIMIT.png) ### `BLOCKL2GASLIMIT` (0x23) Total amount of "L2 gas" that a block can consume @@ -1132,9 +1130,9 @@ Total amount of "L2 gas" that a block can consume - **dstOffset**: memory offset specifying where to store operation's result - **Expression**: `M[dstOffset] = Globals.l2GasLimit` - **Tag updates**: `T[dstOffset] = u32` -- **Bit-size**: 40 +- **Bit-size**: 56 -![](./images/bit-formats/BLOCKL2GASLIMIT.png) +[![](./images/bit-formats/BLOCKL2GASLIMIT.png)](./images/bit-formats/BLOCKL2GASLIMIT.png) ### `NOTESROOT` (0x24) Get the historical note-hash tree root as of the specified block number. @@ -1149,9 +1147,9 @@ Get the historical note-hash tree root as of the specified block number. - **dstOffset**: memory offset specifying where to store operation's result - **Expression**: `M[dstOffset] = HistoricalBlockData[M[blockNumOffset]].note_hash_tree_root` - **Tag updates**: `T[dstOffset] = field` -- **Bit-size**: 64 +- **Bit-size**: 88 -![](./images/bit-formats/NOTESROOT.png) +[![](./images/bit-formats/NOTESROOT.png)](./images/bit-formats/NOTESROOT.png) ### `NULLIFIERSROOT` (0x25) Get the historical nullifier tree root as of the specified block number. @@ -1166,9 +1164,9 @@ Get the historical nullifier tree root as of the specified block number. - **dstOffset**: memory offset specifying where to store operation's result - **Expression**: `M[dstOffset] = HistoricalBlockData[M[blockNumOffset]].nullifier_tree_root` - **Tag updates**: `T[dstOffset] = field` -- **Bit-size**: 64 +- **Bit-size**: 88 -![](./images/bit-formats/NULLIFIERSROOT.png) +[![](./images/bit-formats/NULLIFIERSROOT.png)](./images/bit-formats/NULLIFIERSROOT.png) ### `CONTRACTSROOT` (0x26) Get the historical contracts tree root as of the specified block number. @@ -1183,9 +1181,9 @@ Get the historical contracts tree root as of the specified block number. - **dstOffset**: memory offset specifying where to store operation's result - **Expression**: `M[dstOffset] = HistoricalBlockData[M[blockNumOffset]].contracts_tree_root` - **Tag updates**: `T[dstOffset] = field` -- **Bit-size**: 64 +- **Bit-size**: 88 -![](./images/bit-formats/CONTRACTSROOT.png) +[![](./images/bit-formats/CONTRACTSROOT.png)](./images/bit-formats/CONTRACTSROOT.png) ### `MSGSROOT` (0x27) Get the historical l1-to-l2 messages tree root as of the specified block number. @@ -1200,9 +1198,9 @@ Get the historical l1-to-l2 messages tree root as of the specified block number. - **dstOffset**: memory offset specifying where to store operation's result - **Expression**: `M[dstOffset] = HistoricalBlockData[M[blockNumOffset]].l1_to_l2_messages_tree_root` - **Tag updates**: `T[dstOffset] = field` -- **Bit-size**: 64 +- **Bit-size**: 88 -![](./images/bit-formats/MSGSROOT.png) +[![](./images/bit-formats/MSGSROOT.png)](./images/bit-formats/MSGSROOT.png) ### `NOTESROOT` (0x28) Get the historical note-hash tree root as of the specified block number. @@ -1217,9 +1215,9 @@ Get the historical note-hash tree root as of the specified block number. - **dstOffset**: memory offset specifying where to store operation's result - **Expression**: `M[dstOffset] = HistoricalBlockData[M[blockNumOffset]].note_hash_tree_root` - **Tag updates**: `T[dstOffset] = field` -- **Bit-size**: 64 +- **Bit-size**: 88 -![](./images/bit-formats/NOTESROOT.png) +[![](./images/bit-formats/NOTESROOT.png)](./images/bit-formats/NOTESROOT.png) ### `PUBLICDATAROOT` (0x29) Get the historical public data tree root as of the specified block number. @@ -1234,9 +1232,9 @@ Get the historical public data tree root as of the specified block number. - **dstOffset**: memory offset specifying where to store operation's result - **Expression**: `M[dstOffset] = HistoricalBlockData[M[blockNumOffset]].public_data_tree_root` - **Tag updates**: `T[dstOffset] = field` -- **Bit-size**: 64 +- **Bit-size**: 88 -![](./images/bit-formats/PUBLICDATAROOT.png) +[![](./images/bit-formats/PUBLICDATAROOT.png)](./images/bit-formats/PUBLICDATAROOT.png) ### `GLOBALSHASH` (0x2a) Get the historical global variables hash as of the specified block number. @@ -1251,9 +1249,9 @@ Get the historical global variables hash as of the specified block number. - **dstOffset**: memory offset specifying where to store operation's result - **Expression**: `M[dstOffset] = HistoricalBlockData[M[blockNumOffset]].global_variables_hash` - **Tag updates**: `T[dstOffset] = field` -- **Bit-size**: 64 +- **Bit-size**: 88 -![](./images/bit-formats/GLOBALSHASH.png) +[![](./images/bit-formats/GLOBALSHASH.png)](./images/bit-formats/GLOBALSHASH.png) ### `BLOCKSROOT` (0x2b) Get the historical blocks tree root as of the specified block number. @@ -1268,9 +1266,9 @@ Get the historical blocks tree root as of the specified block number. - **dstOffset**: memory offset specifying where to store operation's result - **Expression**: `M[dstOffset] = HistoricalBlockData[M[blockNumOffset]].archive_root` - **Tag updates**: `T[dstOffset] = field` -- **Bit-size**: 64 +- **Bit-size**: 88 -![](./images/bit-formats/BLOCKSROOT.png) +[![](./images/bit-formats/BLOCKSROOT.png)](./images/bit-formats/BLOCKSROOT.png) ### `GRANDROOT` (0x2c) Get the historical grandfather tree root as of the specified block number. @@ -1285,9 +1283,9 @@ Get the historical grandfather tree root as of the specified block number. - **dstOffset**: memory offset specifying where to store operation's result - **Expression**: `M[dstOffset] = HistoricalBlockData[M[blockNumOffset]].grandfather_tree_root` - **Tag updates**: `T[dstOffset] = field` -- **Bit-size**: 64 +- **Bit-size**: 88 -![](./images/bit-formats/GRANDROOT.png) +[![](./images/bit-formats/GRANDROOT.png)](./images/bit-formats/GRANDROOT.png) ### `ORIGIN` (0x2d) Get the transaction's origination address @@ -1301,9 +1299,9 @@ Get the transaction's origination address - **dstOffset**: memory offset specifying where to store operation's result - **Expression**: `M[dstOffset] = TxContext.origin` - **Tag updates**: `T[dstOffset] = u32` -- **Bit-size**: 40 +- **Bit-size**: 56 -![](./images/bit-formats/ORIGIN.png) +[![](./images/bit-formats/ORIGIN.png)](./images/bit-formats/ORIGIN.png) ### `REFUNDEE` (0x2e) The recipient of fee refunds for this transaction @@ -1317,9 +1315,9 @@ The recipient of fee refunds for this transaction - **dstOffset**: memory offset specifying where to store operation's result - **Expression**: `M[dstOffset] = TxContext.refundee` - **Tag updates**: `T[dstOffset] = u32` -- **Bit-size**: 40 +- **Bit-size**: 56 -![](./images/bit-formats/REFUNDEE.png) +[![](./images/bit-formats/REFUNDEE.png)](./images/bit-formats/REFUNDEE.png) ### `FEEPERL1GAS` (0x2f) The fee to be paid per "L1 gas" - set by the transaction's original caller @@ -1333,9 +1331,9 @@ The fee to be paid per "L1 gas" - set by the transaction's original caller - **dstOffset**: memory offset specifying where to store operation's result - **Expression**: `M[dstOffset] = TxContext.feePerL1Gas` - **Tag updates**: `T[dstOffset] = u32` -- **Bit-size**: 40 +- **Bit-size**: 56 -![](./images/bit-formats/FEEPERL1GAS.png) +[![](./images/bit-formats/FEEPERL1GAS.png)](./images/bit-formats/FEEPERL1GAS.png) ### `FEEPERL2GAS` (0x30) The fee to be paid per "L2 gas" - set by the transaction's original caller @@ -1349,9 +1347,9 @@ The fee to be paid per "L2 gas" - set by the transaction's original caller - **dstOffset**: memory offset specifying where to store operation's result - **Expression**: `M[dstOffset] = TxContext.feePerL2Gas` - **Tag updates**: `T[dstOffset] = u32` -- **Bit-size**: 40 +- **Bit-size**: 56 -![](./images/bit-formats/FEEPERL2GAS.png) +[![](./images/bit-formats/FEEPERL2GAS.png)](./images/bit-formats/FEEPERL2GAS.png) ### `CALLER` (0x31) Get the address of the sender (the caller's context) @@ -1365,9 +1363,9 @@ Get the address of the sender (the caller's context) - **dstOffset**: memory offset specifying where to store operation's result - **Expression**: `M[dstOffset] = CallContext.sender` - **Tag updates**: `T[dstOffset] = u32` -- **Bit-size**: 40 +- **Bit-size**: 56 -![](./images/bit-formats/CALLER.png) +[![](./images/bit-formats/CALLER.png)](./images/bit-formats/CALLER.png) ### `ADDRESS` (0x32) Get the address of the currently executing l2 contract @@ -1381,9 +1379,9 @@ Get the address of the currently executing l2 contract - **dstOffset**: memory offset specifying where to store operation's result - **Expression**: `M[dstOffset] = CallContext.storageContractAddress` - **Tag updates**: `T[dstOffset] = u32` -- **Bit-size**: 40 +- **Bit-size**: 56 -![](./images/bit-formats/ADDRESS.png) +[![](./images/bit-formats/ADDRESS.png)](./images/bit-formats/ADDRESS.png) ### `PORTAL` (0x33) Get the address of the l1 portal contract @@ -1397,9 +1395,9 @@ Get the address of the l1 portal contract - **dstOffset**: memory offset specifying where to store operation's result - **Expression**: `M[dstOffset] = CallContext.portalAddress` - **Tag updates**: `T[dstOffset] = u32` -- **Bit-size**: 40 +- **Bit-size**: 56 -![](./images/bit-formats/PORTAL.png) +[![](./images/bit-formats/PORTAL.png)](./images/bit-formats/PORTAL.png) ### `CALLDEPTH` (0x34) Get how many calls deep the current call context is @@ -1414,9 +1412,9 @@ Get how many calls deep the current call context is - **Expression**: `M[dstOffset] = CallContext.calldepth` - **Details**: Note: security issues with EVM's tx.origin can be resolved by asserting the `calldepth == 0`. - **Tag updates**: `T[dstOffset] = u8` -- **Bit-size**: 40 +- **Bit-size**: 56 -![](./images/bit-formats/CALLDEPTH.png) +[![](./images/bit-formats/CALLDEPTH.png)](./images/bit-formats/CALLDEPTH.png) ### `L1GAS` (0x35) Remaining "L1 gas" for this call (after this instruction). @@ -1430,9 +1428,9 @@ Remaining "L1 gas" for this call (after this instruction). - **dstOffset**: memory offset specifying where to store operation's result - **Expression**: `M[dstOffset] = LatestContext.l1Gas` - **Tag updates**: `T[dstOffset] = u32` -- **Bit-size**: 40 +- **Bit-size**: 56 -![](./images/bit-formats/L1GAS.png) +[![](./images/bit-formats/L1GAS.png)](./images/bit-formats/L1GAS.png) ### `L2GAS` (0x36) Remaining "L2 gas" for this call (after this instruction). @@ -1446,6 +1444,6 @@ Remaining "L2 gas" for this call (after this instruction). - **dstOffset**: memory offset specifying where to store operation's result - **Expression**: `M[dstOffset] = LatestContext.l2Gas` - **Tag updates**: `T[dstOffset] = u32` -- **Bit-size**: 40 +- **Bit-size**: 56 -![](./images/bit-formats/L2GAS.png) +[![](./images/bit-formats/L2GAS.png)](./images/bit-formats/L2GAS.png) diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/ADD.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/ADD.png index 4dd6dcc56b3345928a263804b76cac8f671b62c7..ee1a32d95b71b328c86e10fcddb325013c8d6472 100644 GIT binary patch literal 5422 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 literal 5053 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 diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/ADDRESS.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/ADDRESS.png index 2c128e55cc325bb99186955506048bc935579b3a..4314acef2a15e859191d557429db52a4884c1a74 100644 GIT binary patch literal 3561 zcmdT{dpMNq7XQYe$ZZ$7glV_slEfGp!m!g##n4SIgH5?-+|7iUVY?Jj7!|q9Cg~#A z$+egga*1urC}KuLh#50!Ok+5op3Xkce$IZLy`OXbIp>e}UGKBjde`@TzqQ`qdcVu| zc88@URU`obkhVE;-~<4O(ZF@*MiFpMof01g^_4aUemsTCn;#v?d{AF4W*_D$T+m(s+&rt3$U)p<0kD2Bna1UCY7A!F2ReZdYFkp~5d1c-rR`*te`C^l}i z2WLR!|Jt;+Fcx?19V*_rS1K4yYj5k^_kvm#+lQbZvqt5~ zb*$M})atE zGsR6o$%|ekaZy}+GK>9f_zJmWF<+g7Yl%@T;H}pSl%TmK3hmp=U@Bi#ZM}TuQHUYT z!2rJ69Hg{sm#jvyDM0kEHQQ)%af@f7Jf*+^03ZUZT#S z@07V+UMtspR%kGYBu#uu#{L4zuCW|}yX(!qRytgnyaoKxNOrKCGHu6 z<$5hh3?}WUsVB%u(%UaDTDQmKnPg0Li)zPYjkuDm*vZczm1 z`g=`YL#kWa-R2u2GsH-`$D7M;y_I~GE#;zYs`2tcTB;l83QP$BP1HB!Uh~hwvajr{ ztsYL5oQR0$n!%MF0^c*+)Z1m<=_}H4ZwEFuw@$15K8lz6nw0+v*xxbdSQ62OLsto( zxRZo*4t1ymCj2mMj*iBB>Ay2Q8?|42>F3p0jX!3Bd-CM*6252?WKIQ{mwwfBP<~^EQCjWiyx*& zoH$)yXgBe>`?*_mqgn#vEIs>qC7jl+u_=)6NGD))#E(=bOiKpb&{p`q&E%JxYjX}R zu)5uSKcAh;^2(kTXtE6mC_p z)74@LmZiQFv&|_|TwU0ES(+1o+`wR*m_&;`tZ{$J=5RN$%JQWA+w!Zt~4WM7! zH#@0A37PK^0&)jo^H!uG;dSdW1Zcjqq@dwV0bT#uX8txq{h>L1+r?bJI?(ojt(DNy z%tFr-FKqF_s!>eeSMx<%)n(|Bdl{RVn?O48eI4v?X4w%dq(ffcpKEMOu~_@5c_%IE zW*o;gYhs}HF>y|DF%r75YE-^3?6dzDQk2e?Z)ZCT2l)2)pr#0;VMT> z;R|-_qs0B(>(l@otkvvHUjJsmWbmD-I*?qGFzvKe>v%fW6kc}oY?DNrvuu`hnjmjm zoqpYI)2xHYM8rdcb11nDeV%X8RVV8cgdP1dT%jSTAYcLzBU$-SjX}LMr@%se*YTM* zE4QnP`cl+-73XJ%WP%kD_UitjxU?l)Y)if-49D3aC|iaEx+;K)I9cU;O*!Uo^`rb2@d z*0cq2Fyz%Rfs}77_PlhVb4dn2&l1!CEN_XvVm;J{+i!8iTYJlGoRLmxr*YPOzMWOG zch+`~HF(2Q^d@Trb&xxg9uyDOx^E%XROyL5P z5AvG}zstvRg8{CDqxI#w*>KtETYQ-pA4#QeP8u^DJLnwpwi_xC)ix>e)O?*n{1g8w5Su6%KLPY(VyRdI1^-M zAwp_sYAj2OHWV7~}?>a?X{v8RLXyo#1*r~W0GKnY+s0ZtEp$8L5MwFke_+V=W> zSG=|%Z!)$kss)`+oxNUZLtrcUSru#YDo31N2ATV*o^#7ck$y~4*6yp04CAzkw`5m( zh1m4QxV(q$d-3Eqc5M=irL5QRTfvqOLM?`Zg}k~4JZB4m84+J$6KAban1DO-va|4h zeypoqb5RVwFA&a9VoG^a%$@lraMSp7mZlle$d8i|I(`SEfz&b|Q99JU9+NN0?v0jhaZWsjf}Pp8F5ZP&fhPRHb2Q7`1nxXLv|wB;tK4u0RbRY z_z73Q76Y=!-@kfLg>q92)=FxKwqNP8(PXA8^ aTqXv_UznSjZ(Lr7#^#{if%5$x@&5n_D}9gv literal 3224 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 E3-prxb^rhX diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/AND.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/AND.png index 28699de39598b22723e0c6ba000438fcb547388b..9bfc38479f18a03e6125819b8976ebc8db798134 100644 GIT binary patch literal 5445 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 T^`>TN$I2Ja>uKbxTi*L8V(gm4 literal 5072 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 CHpgfH diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/BLOCKL1GASLIMIT.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/BLOCKL1GASLIMIT.png index f9cbd7a4b408af4d61ab568ea9f9ad6d43b18987..20f5ded93909b6cbb22b4eba0b4fdb333ed70e5c 100644 GIT binary patch literal 3541 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 V1lv(}14ITm^re^E_f`vw32 diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/BLOCKL2GASLIMIT.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/BLOCKL2GASLIMIT.png index 9e1160f7e36751161126004c183948ac20e00945..f952f689f04028de22ba6d466fdd24efb78d99ca 100644 GIT binary patch literal 3564 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 literal 3172 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 E0RtEOGXMYp diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/CALL.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/CALL.png index c4a26fb27ef598274c60545564edbca939093303..a017035166606fa48e490cb10ce37b273e3cbf42 100644 GIT binary patch literal 8813 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 S4l(N1+09N_8et7D#r_Q@T8{Am literal 4636 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 diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/CALLDEPTH.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/CALLDEPTH.png index 382668bfe4a962983bc75eea81ce70ab642585df..1cca7c9e725c8395cd138dfacd054cc2e4c75293 100644 GIT binary patch literal 3552 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 literal 3213 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 literal 3204 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 C1HKag literal 4407 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

|hc+!HZPvYqg?<4Fuz0BN-#yCn_| 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 SkbgA;_J4lBt9-(@<2@jP+r8^4pr6B+4 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 literal 5048 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 literal 5066 zcmeHLc~q0f+Mfg{pa=?=RS+l$1x15Z0Rf4(3L3m@B2Z945s@tjXpuc_zgnya%A&GJ zs0tzw_CO+Gsb#scg&j&DsR+cm9}n=ACDmd4A74 z&&=F)adOzPO=}wfV8@x$C*1&$$3X43a-Tu<14HQ#0H{1XbMl1y?L77*JC#wa4EicR zEGJFzgjE&|m(uJIN84qXr_Jsk3p;yA`tg~<(}RZ#l_1`Y@@{STwbWJzWIhBEvFl}L zrZi%!jVUn1z_vQldtnM&ZM`q#{kGcR#2N61C^-~dV`~8EqTI682H&OsN5x+=)N0V= zw;pb&W?GW-py4h>FgxJdy_j&pMjCLhX)?XG!$Iufw1}owJJ2G>yYh4wqd-4@YJdvY z1IX~YD|^g$g1%B5p~D;c<_6`6Rz;z0-O;oqkcA^7h(}qOBSp_hAX71>i0Y7LG z@}>_~rs9fipMky%oTbAXb%6MsbsQi$t=3|#Pckk%U7*o(Jpc^@Gi5R`U{G^FvTht* zutqZ|hZP3pxUro6aH<7xtaD|d1 zXtPaeS&^L~{dO490SGe- zTf~!qy81RH`x}RQn^oV$Z-*BgTqItU0rruHo9-uJn%L)0NEAHspYW2MrSu10DwpDh zhO7zpYqU@ID1PtCQxO@i$jlB>f5a{}$JBYw=ixgKV$&j&5Qj!VZ2gh;div+!iuG!@ z->#G?%*hV}dEZgufAUjhD9QbO$(MPd?r zR86?l-^ANw65{QS{oBUGtfC+k&br?X^}ha=?v_n4k%NbK_{gzd-jb#I;|9&;4IHyWBx6a{(KnQRV?w=_(~B!%CH){V&tg;_mF ze^I)x1E&+m{hD>n6hy5LPCbAi z8ud22<21-6lhb9qq0#Hc;|audYo(6C(@ot_`kfCPW({s&2YwhRjT&DYTw!<=%( z+D~cP5@h3#Zy48Ert;g&1AqId6P;=45&1E@wTe$0xt)kqAaWQlX`C5#i1v2<7t3?5 ztMU*qyG=2-4!o@P42qe@Gv-1|m-v|It^{4*NspgL;xF%kBx8^`@_tfd zKA`v^GOOlE#L;Y4XVh5iS}|75>31QIO0!Cep0Vk|rYBAgOZMCEIUdV18$*vu53RI_14Q@JQPCdpk?=qOz&t|j=2cdepMv9!F?RsoSTxs&dhCoSaRV1 z1eaeAi8QmJAfIBtCbd~z<4%UV|35ikLPs+g;qyW+x%p*K@R&;eC!t;VlK83hjQ6q% zwKGntKxy&G^||Yb2W=IB24(jMXoC)ElhmDzAw4ww`d2aty_A^W>s6(jPGly&86@cf zx}yoZm+6z1wMQ28<*dj8y)=S+fthNHW$ibvxa=SymycO=kAP#w9+}sNtkPO7LEpgz z@-fIn+*0nbgJ^GKG@R-L*T_vhgyS?3Y!i;tvx`hl-cT*X7RC?40exIhG|kMYZ(H(2 z=cxqryQD~g1Z8okiWnf9QRR#DqAy2C-3XjNFH!rji`&IQ%P~m z72DUBCyp(zE#O2Sg+0T}ms)%Ko?H9R4OsPG*amFQKuA4sn2_Fyl}1#TCFs!x`QVx9 ztNh!C>+PKhji1)spG(_E7)7Xo0$I8)z}V1@Fi#9I3qLlxvxPa2hfyJk6 zYxCh^dPdw@_QFkvBZbew>PJ2&J^@u~>FU|@;Vv%Y>CB?o+c(nmzt~p6i`@~xdEZ^@ z-u**iZ7Wvni?-$5@TgSVC`EHcK=SF$xxeB7%`7}}RPAnD2Ti9V6u%d(YysnNJz0wL z=n(Z1+`Z9D)u+)eQ8V$5A?iMw@BO=8!Eeq~c{5B3-6wd|DhD#Bll80M>>wA59q-7h zZH}fI_a=?9=#4Pa*S$wXsBU3qO~m+GRr;75NPd2`N8+@#?yK47g5q!dK#L&?(+zhmZLt%^nmc)|BIJObcbQs>lB=v9}dOw<#7j0;=(V3qcM=0hGNjpj?4%O&adYYlg*+-Nik=$Jod$YvXys6+<}RX zbmrZzCA>^G09j)k?D(f{h_-l-=-l7}%T{XqHwvmFn)}mX4`Q=C3$GlT_4{JkQ zDEyoBaL?3F<3Qqs063O7<5VnQYmXtLN#df&35Tvt?(;(rhmTx1*DY>X@mzm0cj`BZ5VG5#7Ap)SWl;9S>!Q#grxC$ z9y}Ksf8q?%k^0ebw&xS#gMQmN#>BmqmA@2BVHg^{!n=*few&1YPij$BXWdZD0Y4~ zb#SAPv0J~l%$LdCb@yD=c*lp*rld@qf^z0&`HLBE<8oS?xp9fyAKj*{$yuJJzzaR;fQhr)x&TEY~NYFiV%IReJ-~GP(Z%cjV!vFvP diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/SLOAD.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/SLOAD.png index edb4539d8ca63126db8db003860818a70618fe4d..f9c6540667d42534817b11d9f7c9873120712302 100644 GIT binary patch literal 4292 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 JrQcq@_jg7iNbLXs literal 3969 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 diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/SSTORE.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/SSTORE.png index efc6e0272ecd77fabe436d304087e9a92f9c76f9..5580d4237a774225ed61e8347e0d05d2d8efc1f9 100644 GIT binary patch literal 4329 zcmd^CdpMM9yMG*V2qh7QVv!YJO%y^7GbM*vgGvq|QCW^THfDq|N~NU(C5IWrDu)PT z8Kw|MiA)%W95V-tKIFKZrlA?%4C`Chwf8^!+TZo<>)O}e&mZsgd*1uG-{*er!|#3W zU(Pt#$ZUsf2LQ+*Y)?4?AVJ~dHVI+=6CQ!210Y+0ICa7)Dtngx8U6CL+_tVTYu-kN z$cu<&a_a_X5&0T_ss>cMC2C!bBP^Thdz{K4Ze`~HNKdWn>+mlC43TR>EJ{}vDy zlG_3|faE5KhsTR<0=PO{U;_Z^vg$&cK=%LSXTD#=g7rvGHaodto@l=14c3>!->iC1 zSijUy;l)ki8vhs-+4KM~W*U(F%|G}X{^^^%$7GTGJ({MQQr0C4KM0o_vzAJ(+N)mu zO=Zjf`CTiRw92IlrZ{ec+7hHkx}={V3;5UCxv!QW zPpDH7_!xVEl+jorxb^hJy}yh68EEQS{Tg6FELT6Xxz#o&uknu4{Ak@dAI^V0(7SJ& zW-j}njOY6g?_6@9Kj6J{S=(7>axc93s_R+UQr~18ZbFw#Slz=-95^cSixGh6iE*@C=tB)25q;FXv80btcF@(ha(rE2W#Z zgq&vBns~c=%|MfEb8SJO4Q(_hj%Wcu)a`hnbgo#k2Y>7_vngw8C~M15RFfM|ISlk4HPc<+AfJ(qd-)Z_A#T3`Jd2oGV_ z`x&L2)}7HeHGuMeik6iAzgDMfrw1a3yC0&fp67_aI!C25GWc-stbfr}(}Iy%Y=Dia zKuRV5M^V}C{|$BBwSvX198v9wr1vFm6@^|uN^~h^MM%DDS)5W`Th5VAlj5h-uNwlf znaA{Q??aciD(l}xQ49Rty5h^HdAx2xaR@sd{f^(s<1vb08%N{?yHcbwZ-_1gdJc3H zo+80E`SIdg>HT@;zVA1w(Mby~97UuBSd#)qCU$lp1jHH7uDG=q{5@iG!C&l3kwg2b zlnEKe3~bCCKYMUVWbw1#DlheXU!YAE1#2h%VCppbJ2dwgy39xlz;&#)zZuHV-X;X* zXwvyhD9?-<|2n5I8ZVaIF*KVRlZzd_x}G&GdNC*S&%2` ztDfUyeh0yT84gF(`#Xfx6nAt>r3P0X#w9aQW9_PyE70UBli|2Q?=N$2iAMYO;1ybB z`ji3zc-=KOkNxQch2xs@B80rD>lg}J&O)1CJ!DB8T#odg>Z}`gm$f0AeX9-$-_<4@%GE;Zx^5Q+BiULrofW8G&^ES9_%6GR z(BgVrNR7o#-(q{Jd+vPNNCYOUVBGJ0PMBWy6|9}{(aTD~031GBB7IJvovUoyQAb9h z!yE5@Pt4@6Z?p-;WFe1rz&x1i4Q}BVUNDNzp)2_jLtwNU({2Kgp(i3aSN<^C9&$c67p5QrSTf~hbx-)K`Q#=^_-!7K;Ank#No_?MlrV}+ zOgZfd{Qv~kS=N-xi-OlFp!oVgdS}UM-PC&As`AMLILC(Wdbc=Ea~anM#eo}%0Arg5 z%Ev8>1?OF!N&kMlvsW0q+IFO1mAA4^q4xS8(g~~K<~=e-hJYS8i~=K zApPJFL&D?AO1FslEQY*&rf2=aV@)Bz^4ZKwenn>JSa7a*k-T0JQQ2AKCkp1Yo}Yzt z4FP3La2^7mn?X@Tq7I-03FeT?g85qAZ>Z>5icApz$wmBt`ridp=uaIK6{TqaE+Ta# zK$j?T@V~t9+$>-5b47b%R(=rh0|568_crk@+Qe`HpU8KiZng^83lVj}c7y+K69-W$ zD?7o$u`*(wFW-{Q@fR=ryKh|r6F`{lKqL$X!!liiaRG|e>>cp%cNB~Bkd`G6VL&v5 zD#byHmF2B~7ygE5SH-VMInbfpdJG_ctqnmpKjrB)Y618)z8vAJP9KP z2j<|~0a<){R*}%}Y)H;0kCI-GE5^+-mPR0AW_^W~P#mFQ^;SriSUmZV=N@g1p}c1j zd2+}>dM9;il!d<%&_8PuGeKT7Jo5l*Qa-;fg&Q51+so=eX9PP;0!pfO68O4Ho$g+I zkc6M~9~_$~&r#34^i8$V;A5Lf4j(&6gw)&8XiI1C(F zdLB^9#!s`ehD*;X@edj(t4^m=-F&|6`7}fcVAk{o%ru#C?>-9JU@T3$WVp9LSb30l zz6UKw3e9GsGy#R|R0tAdPD#oezUsl!Ix zpw%{K(%I!TIfOX7A>iYXrTsBetYWS9nYMx3HtFP%Pcs&rrZ8qj&3ygoL`=dlFyg{P zH4;10RGv%i5gd7MJ3R37S{idK`z7m9|Hd=j>(Ban{PoQNUMmb&XHz6D9gfU!IDElb z3}{bB6_cEl%mOqXK9h(N(@!C|hHk&RJb9_`Uc8ptAD%u)+ma&%l6mCcozGcXURbP$ zO-0LsHxHyvDJN;L9`Su!&C5+?uXF5R@0$`7++JYV>7c82$nCMNi9!RXUW9@)ru%(^ z3ekRq2Qmu%K89+UN8hKN(z~u}*8~+}75j#=ueWI>7&T%*lw{GmbfXrliJuzho)=I$ z&89PBmdy@w4={Vtp^{nSrpZsmMyUR?yo4)Gyf2D-9wfBK7+n^D_fpf38wz5gCo*-> z_jKgJWMhI%%)@NW0vp<~*itVT6XFq3s4+&tLrcvJA`Q5WELUO7Eg^9QuiX8x<}ata z()KfB;-Y9XM;ecSunWbGe$izC0fssDM)E&;J<}F8ek+~t;Q`aS?~smV;(Q(Oc+$b5 z&jp@Rl7yw|3Z-ZyzaDysyDMp-T^mlIE@fH`lb zvdJ}i-nUD9W0UknrqC{j>%8Jzw}n}5+gQLDM7A+r&3zh_$PQ(HIOn7H20fxOOV5)5 zG!m-8BH~NnD(>g)B38TL=EC`=1W$ECQWSkg?9C8$E%CWkMBvq$jn_jjSS3``2C*mf zm_^ffJ?Y38Cf8Zi`~4j9fLE41Id+sqj+AAfUWf&Q*9q8y&VkUo9;cV_vkF!q&7iUU zNm`}xNdZwNYA&k*R`4enpnR^nxbYXO{!9Jni2*jZuT?;Vu4-HDEaiOfF1w|Fw!J^Q mz1^|N#Q*R5-v6;?enY%HefrjExsrH+V-Z#kr^-)y-~0zbVL6!q literal 4021 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 b>Qg1~b2w7YOz`eq_2QuehxeE5^E>}H1joP# diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/STATICCALL.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/STATICCALL.png index 4c48dbd0eebcf04a491902535ded0e8318a140c3..e433c5063c3509b0ed94ecfeeb326a364b003ce2 100644 GIT binary patch literal 8813 zcmeHNc{tSD|39{?lr>UhPmH~?g^aS5eJQd<%D(Ti&7@mM$kK?E3KQ84BPxw8V~Ij! z9a*k~>|2=me&$}PTlbIeeZJ4{`+L66b3e~KK4<&9&pGe&I2nZ#-gg*T9!+SSilH$)vPz=XS_wlF1TM3j3KP6^nA{l;4guxzA z{g|kt^^eJKKKaL&-+TeU-vALJpSH-l+b^B;alLB#)b~by4@XXV?x)Bup%u7 znu}A?d1s`>9I1aShf64!v={yDVE)H;K@QO$b3w=pi=Rz{Wdjx3AB!TBSl|5APF_J8 z-yaKtQ>Q7oeo8bl`YV&|>~AJ23znG3#og&u{F&NgF|82hl9(4)+97q zT-}uvVNpD2RDpFmyRLH5?Q*UgJWX|sGN}3SiRhD&u*tU0B4Vw3ZoptYBh7FGN4%@% zj^cw)eRPN|d0Dyd7TKz6J3l2h4@W$Pzy+iYp6&rO5KO3kvHPL;{Wz5992`?OG zw-LV6sx%xSKd1WQ0#*!h$Wa#RgWB$e@wbzbhIOe-$X*VIRBX;7mQzuoN9$b1z_xF&FBV#vI01JrRD?WvNl}C?id+V@fFM4Y@#K z^E?mtDGDwmJxXL&hJztRXC!k{p}N*RJVG8rFH^@DamOm?YIu*qVS(aC;TzP9V1HwJ z)VUa@C}|pPKcQXpLoPC54^%b`G7gBBI5wFCxZ~4d=WfKj?bs#Nj8%1pTHbQKN$$q4 zd+fT>bBZ}Q!y_m^oS>gmjhWxvwRY4lcje`18!J9N=R>32zBQNQz;OsOJfpqKqUVIOotWQBKi4I!)hB$hhz3cNn6nCPp`hZxsmeVLiST{Lw#1};-u+F9)9$k0Kz^Z zt0U9;QRK1Qa&gNV;T_Yn4^9X#=UpIMwxNrfhaYiefF82bQ5cH$0I%tGU$ z#vNf>)J6)&JmfXilhF9~EY*Jab)-rC%0@)cwLY{q{ZMX5pA}K3M=H$3G!r3xXkNGl zUSOGL-sF$gzkvG#2b#a*Kx*TWOZ(&d9?xBmtb_X%ktJ0#$r2W5UVbzt2G8fd56-UJ@v3ipvBhsR(pD)7REau*@l+~%3(O8^^Xm%6*B+w0&M{2uXbZa_3oDMpQvhyt zVhck@B^!T)S4Ghgya%H6d5ldZ32^S?Ce z{ntA8-&wK#(;@gbTbWfbv)*+vyWP)flJC!Ofnt|#S5m*Wo}@UyyCjLkR!W4@!#G&r zolNi_N?M-i_REhj7#j%sAp?pQMf^{w@^+}3w^Y6gH)LW6DFqQqe4%fRNFi@};~yuNz9)efXX< zx^QZ>d;?RF+y6UZKn?P=i*S{?6B?brW2<$uIx}5Vfwu}K`PD^HvLP*1%6;Rm>qC#* zs=Tly$V^|FxcFpS@44HrR0&ux|6vde zHL|{0E2|Y9(&3!>?1R;4M8^?jO;m+!JN(nK5(`bV+dIqi`ej++11`%QkHy_CK4FIi zpXr$H{uJf5j;?$6YReAJjz(@@5}{<#|C{M6gOJa5XbXz?v*zqK$xa~>GL%E#dt(>g zDIYW8JL%7!9JO*eX^41m%=>eul2B*MK6}nBb5CP3uoUmVO76DB?jX?V{LD|)D^ax$ z5rvU)tSq>@%mf#32}swrCp??!aM-0DRVk`CQ;s=P{yTL;mQIb+^}$`Yv4iX*L#oKu z3Db&xp{Tv&>-m-ci|dUBrM@x77vqZOvPx-?vW0@^5!?a|4p8 zOl3}w^=5D8rB4&1lDqkG7Q*flhW3Z4b^B?-ww$b@VESId_Uo|q-=tKSC>yA}(2ak$ z7z*#TUtAlBLm2zB9`E^RYW;o%E2F2;*Zu4Mt!hTu2sTU(U%yuBfS}5KVY%he2Od+o z^Ez^oy9q{v$|WNmrYjj@OKX?M=*HEKn~~aP>j@i1DCN$sN1T1k<{1-{E;$I}?TKaZ z9g6zNDAEgAuXkgd~E;pxhK-q^YJ z$9-Df_ieaRbjR#l3v`WRBjz77W*E}n6TQ>QSWB2`pECUDw%U-DA|x-c-9DJ>fK5@( z_y-=huj3zKpfdhg)(w-Lm%nh8Awb$bT@_2O?kuvYv(eEPyRhuPu`d2{?B>qugWGH& z=d&92_^9$W8t}tVpH)r~RxrT|VAZp>{OcZ)zHFpLT{tUDCz>CYxV>wevi~-M zJ&?n3KGWGGmdnju?xua|(yhAU@0u#ov)r7+y0_8A@C|4e$y+(3gICS=gz)73Hm^RA zw~$DOwF6VK1J8cL$!&daL;GD3);ARg)@6}GQr+7Qp)L73cHEQy7psUBVI{x8AZxO+ zOLeP7-(GkTzn!UneaZw8t0%IP?WSYyq{3XSJ6TE6fM&SV0fky!3 z<9HGP`T`^ha34*sCHwzdf^GBk*M9zuef2~kwEh4jVWQG~QH!v0Tbw*jPvxUe0$`lp zqKW+q!P(z+<`6qXc*?}Z)ZjxRgXHB78I2L922zuENAdn!^$-050R!o>_IZaFmgSPy z@@2;{r)nox@R~kgaq!|ve=iCoXQbreGV`0M%6rSCk%8I(Xd5b*WDRN37rP8aNdttUZ*adeoQ45d}=lK-27CAl2du;YSYeifa^ic$4mtDeKV6= zbY~&8+4D=)${99rE7rma0E`kOoDFOsdki$b1uniZ$CfK?New=%4BkA`zba>p5xr_3 z>IC67S?|L{Bv01~sdgL!xA2=L2SXBRfV~+jC6K?>LJQ>2ZurMR25}wKm}?XHhj;!0 zaLF=)NEl?*(SLl>u&gJIuqsUmlFML9J*44KI_m1yrrPYyarZLg)AB5r!vLqMWBi~d z;N5Dkdf!=w%UqzS=@Apa8C*EraQO~U*;CENSzZZ{v^Os8(sn~7WQoN=M;8ZbQdw{; zG`@OxyFk0T5W)C9mxfwc={%=rRs)9+~(gy29@M3Q-}O_=j5d07(he4HynC zKpQKlN)@s?5uR8l-g43D_Iom})FXGJ>OxVa=>!f1JTH#b(wh(z`^1RDE+yP^&0|rz zSL2lEXn;WmkK^&ZU`QE-k{K4|oEsB>;G`mv{5pvv0h&6`D&ElmDQQc?3DV@4mpecr z@?aD?}G2TV#pm?c#^5cS4YnjF* zy7ZFX@%Hy9j${HG;yDeFH@I~A!ZK_FwkN+IX> ze=a^31Sb0A0~_pmU+Kk8Y1rKf>rcSaMPS*gWRnOMq=~s#@m>X3TKRsXK{iW%vwPg- z1@3vv#^P8n(Q?Sq5-!2gX!S)uWsmF{jyLd9+> zIj?1T%Az-D!Tq7I^5FhYlpxmoJl1olx3#NnVD2SA202(dkHlqgx6dzg=I6sG*jJ!M zI4MK|R2w-*Sc{`+f>`~u-OeZ%&E_g)2sZTka`!G;VMy5yh})QZreR;usN4npW6GNM zb{IZ*n4e>gst}deo8$nu^fsuG6BZ&CsEA_y4bI`JnS{9vd^6#4Xd(>~TTm1pFGybm z(T={)wdSCMRBIcB6ON38`O?llHsT|I42|s_4tzDuP4*r(EFBiZZ6Z=iSPaxwnue{+ z%qf7?D_rcKxdyt*Z#wK+H?e6Fzj_gardDc#=1jIxL5SC>Hch`BmYQokeu)U;T*v!P zSIQ$#U~*lbMt?048=(dazMTP$LShQy15DnO$AG0--|ZN&XmPVwJHY`_D|9F6Xpre^ zsj0I784=w1M>}-&n)ccg!iMhU7{W1(e$5Clq~LEIIZ__zUz*prmqBu@BTYtdh@VWr z<{3{a3l50w7yryk$DRI`CEVFr2UvD=txIFrSR@1EUmwu}Hgb$78))>EW=-ipvfs64 zUsOGc+_cyP1>-N$*(7Gy*OZ{D;1(BGYrX^+Vv2CsrR|~^K}exfK1u^Nj67fPf4&(m zbGPK$s=n`PTNsOr7ET8Cz{iRGB{tqF}7 z-klijClF884|u%bC+@LZ>%rXI6NrY+t850@T4P3K>E`ytl@5qsNDQ2fl;*t`sF6Iz z_sF;bM)3<$6z_d;gih2cexWTih6Xw5a(DI|Ywufbu$mI>phb{L$@-;QHIuGTzprH( zmQH~TRvh_bWjUVNyf-!7iUK65cZm)Ud&HIZE8JhzXLWMY-D%SWfonCc$K~w9(&?%F zni1Bc{6et!niaWy)?>$t1Ye#x%GlY)rx+BO{>p#I*P)xk02UZqZJ3NVgvSd=+>MMo zI`0p7qZ6HJP%?yi7A5!wZV#S39}?4&WDj`nMyvBd)Tx$Yl*rxskq$h4aMXR}DddX& z+S5HXQ=9>rdos$^5{ju1{JvbzVcLDETx`hBlERtu57_QfRaN^>C)oa=Fbnv5`p4U&c%cNa2 z4UTSe#l#?db`C1Eny%`!X0>MR1#jw{8TODQ%+~UK&enQ_JRYo>gJ?YLP!$rB0jX;_ zaUL^PvW76d#cwR)>IidS?H~p?@LDYJ0N$LhoiOaF8DBc-F}8&AF4uOmUr%Zyuee{t z6#Wl1%m~t0yow%COLcRuD4Q#W)}-VtWa}8K>^-$6=otHKQ3_ST1P-yPSm``JVF6$4 ztYGF9zOUt`RoVJc_WgXPah=_L@TLo0XgD5vH+Kr-rg1nlyjji+JgrJJQIFkR%#RVL zqW}^31lTmE%INbs)gUTh^mWuN4_Y{`d(s0>Y^neg1L0H1DQwaD-aC-C2!{l#)Wx9C zPwQb5Em>L7Jyp?aAMg!aFW&Y`?Y55_{35GJ)-Ra1Q<+|8Omn%o*C(zSI}3;>D<3EF ztMo70j?dGA{#Sf$#~NNrb%mU8S&i|Sl^!-wXg2R_Ad^9fPBN=ZI>=nDX|%+qWZ_7>oBeRgQDne zxF-^}rI{hiWa-SSho3@-Zas%1%f(s$3Zp07$_jg4-I>6Vl^Q zcrE0Hqh7!YTB3kl3TG(BLjlC%xA(Uo!kBym#n>7K@zNEEf14rKYZ-u{m z1q=Ut@$)xsggci)2|>HhRu;G%-`-+NlNIyPP5C7uA@1Gm% q@7(k^2IimJ|L^?vKLVmn#{0ar)?*iqp#L8M;Iz7)TER)1@P7fnI99v> literal 9056 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 diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/SUB.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/SUB.png index 1a58fee072da987bdc86889bea128456f3cdbf9c..e6157763289d4a9e2c9647cbbf5c0dbc9a58c9fc 100644 GIT binary patch literal 5414 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 Bd$s@o literal 5057 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 D+#ktI diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/TIMESTAMP.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/TIMESTAMP.png index 2031f2f63068cf8389a08ffa959f5dcc5628574f..8ac215faa811c009b8d3f58fece01e2c0f637a8a 100644 GIT binary patch literal 3552 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 T?e1JS8NlgFH~Xi@e1G^C7pwgj diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/ULOG.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/ULOG.png index c0f17fdb67b387bbcb09bbabc0a4c71a573175e1..1c414f29b5365d5d0f7e5b10b7a4fe42eb076a67 100644 GIT binary patch literal 4435 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 Mj#cTKe2k&>5i2wiq literal 3861 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 literal 3194 zcmdT`YgCfi8vYOlNzJUzn3pN3&S+NH1<}geGhmA0sssPes>|@pxwB_#~%R9Jbk@9k7QP>2UW$_S}ozvGmmHt zo$sbj*r)D{XTzaG*{Hhf$AXQ_qZ1VmDgue9ZJ;YnxX9y!2mpd*SkTfYU`P$7&jAfj55%H~l~ujb9c>kr~(=lYDU72!(!7s~5OT zWxP3JH%qEp3JeRA$UFOZ*z*To$F7>;Co2Ij8<2MF zky=k5ImcrtkP-)up1Uocf2mVU8OFE1Sbg0MkeRmMS|ZQuM?F8ejzj00F0uAJ=ytO) zh@HNF&gFY(iFWF8-sB!?WN1%>)sIta9+m4C4%*Q`e_#>}2^c2VcAaD$weYji@C;!Z z#%eF_vHOZ1Q>#I3`MAiHJ$SaddaR^di*?aC?@8IjT~uX1NKVyw{Hv2 zMzuHOkIr@dp!92*%JZjNLeHEVN~6?W$_U3g#n7<(+uvUKJyei^u^0?ln_+IzA2@hS zv);i014jFK3S`Vs*sW?QMXuKFo}X;Yl~O;Uye|7Ed9eUb0B6zW z{>$xA#+`uaK);V#8Aoi3>)3=*b>Ga;SL*Z%BDiYoPAKd^L)l%cq^){$0I(|fbf-nA z?brla(>{7q^v6X;<$3_vZjQzRi;-(rfSSgAQmMkS!t2Hj)wZxn%=~XfVyy^Z1IM^l3-uScVJGjkk4a=GIFxX(|LZUupxZ=BQcHgya4nIu}ERVkd{cMj-4+I3ny~?<8-3NBQ{elflnYAm<3pjd{D*5%z)fI3>@}$niGXxPok2{l#7k z=pjL10are8dk9glRa8NC3aOXGPGJ9Rs;ODn#k-lKi0Hr5#d*r#Qxg(UjKe)awED2M zo8$ids{;gL(OK>gnwPe|m)`#r|1|5-2DVI^I#al@=axs1qE8``EcQpz6uls+U=&_t zHzEbKCq7G4GaU8a(HU=zO+Le#8CA~Tpg_l5{G@yR_Cjhp%u0s2-D7c#by@O_QTV5? zQ>l047kpmz49arh3W(4!_`Cg5s9yuVggWThN@U{uZtWRsAIyUR&C4h8!$M2k4DqRI zc1)qW$qbDxH%9)7~a7)GP;PfU6H&NWO3b-FR`@NrBO6E`qNObUJmbK zn|zw!4ndTj=1qLn%BLqfI}hp|&@*-bas{|HsQ8I)AS-LZDyuxO zkJ=k(fY1`}iYU9l)bzi4%5-hu)0tfs7~b$wb(APbGZ3R&`PIP6L{h5H)WJ0YL{T{f2Cn&0Hqed1Kdzqd}vPJ1UrsjS* zs7re7BD~p@wDLHaO2l&=hAV7s8IAYR7$Q-YET4q67TpxyiMxI6s_GuSeJg8uLi;y# z_qA_(pNz6Q-*RWQGXBpLk@X>#G>K)v&%R%PuzMx)p~Fn&Fj{j*o<@qcS?Fc z#|_;PZgQxY-7z$8Gw1BbhzA`!WG~>;SbrZQ!eZZ4rmI{yI$-p`USr-6{pLlz>r1Z+gjp48976ZLlQPF=uaVq4lIE%C&k&h7Zp zqS6|9dQ$McQfDCV_`0;4T|+XOaE`I_C+>B6bOaj}L%Y+JooilT0t_#s$MB*TS7};- z?$xyC56c6d13*d$4_lfw@TL{;2h&8+4aA0EfYm{fAa)FLSKia*O!e2rlnojA?a zwvMi$b#?=9RuH#Pw+Uu-yWEWt_+uAb2GKt@8N>o*kF}J@|vqmP~<-E9Rvo&YiIoFK-$ap(Ee7&nUhrICYrc!k{xbInbK`$ro z-jw;CKQ8Xp7N?U7xtg9kKNOBY-$ua^rQA?KW=DSszu|7OV9TOBc5I~U-E^GqurHbG zh?5TSWlfL0GnA9Jq=zy4N~%EV;5@bY66AK)kM)tMDK3LE|`#D9ZMlo*W=IQuue1nkGN8K4@fB+vhagJT{0Ns(!EyB-S=C4}< d|9PFRplKW6Q3zS*;9@A>UA6K1HdwUg}t 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 literal 5089 zcmeG=dpOkF+G}PI7+r|Al-dz;+1ePwaT((_W2*gCyIk6G+;ZD7 zN*R<}Ow4pAcQJ!8GfopD6O#ns>dw^}cJp_jk?j z$B)^mEML1E0H9)jNwnc2?jPw1lZC-PXGT2{ux@Dep8Pi6{X=R(!64ObyYCheWGm&=V2)a1b%0@$Q5u9 zyQ@5`vBw%v6=wo-SMmzh=e_G@0X={UtqIiGtqwZxlj>i&Lch1r*$bkD^Og&9cM|}i z@k7#dtFE^G{PdjiT7Uq^7pHx0Ig8enjLL(Tf40MbZPlI@a<(Eswlx{Cm4&}?;~6l3 zypTl!gcIj`_qK#yN;X$i1c}Y&5bsKo+a{twEQzUiA}L$;{aT?0kj*R+_s7*#fRd(T zlJ)gqguLP325|-oK(G<3_2G~CstL$>rhjmhhH5HDo{7 z#^ct&IJ>L3P99{MYRZAc)<-fqsBn}+QBBz| zYi7^v6UF4@DZa8#qdcrLW3HO13=-ds&PL561i_)2r(`6bkl0d$V0_echY%K9gP9j^ zMZO$9cjZaujK)IIto-O3)|LDzN=%K*$DHacFDuOg*o9aN0m7EyUhH` z2=)|~H#x`tax^ud6)2!iZYDDSLTCAYK^pJ-CV~sL!jw>^E&UBM>ERw$ett{2!We-B zJ07fAfSh%4(7tu4UzM6Jly1wYG2^teJ_YVIolXl$sL2mv`2QN<|c^#xKrDMiw%1cO=R#TEvmu|=Y8uQnXjex#l?pv#4$1i5#^*GiDHB(JhE*| zgN`R!1KJtD4H&Et;2KP1E_q^kUC1^2QlmFEJ%ZrS(fS_?K? zTP9Tdz){_ddBtY9c> z681T~TprFa4}61^nH+11aDA10aWz)1INhg&M7huG7>OLpR& z0e*kdl1O(qyry0XZF*wvmdkf)3zuCfMn zUs;-drw$MWK_rEPchDlPe>2zy;i@#oadnGwC%eK^w>UejFJ7P0X*Xm=L=aud(Nn<` z@%8XrIq2$nmh0~Ad)C%_8=)Q2VVLbVwuRbGBDY;Er^KuIDOOs_vz7_kd z7qoYXdHXRorP~Pt2aFM}+;G2{Ex9`J!DI_YV1xA#GrWUyzhz5Lz2_rUh$TvU8|&s5 zd%!ASA5=h(;_+c+zZ{i_voWgfDZ0~ds7jC7thwANtp7~q{O0%cvl567l%c0tgNs_* z?FtW9ck!pj1d=sPW3@J3h?+2$=4C3C{uZQ@{WOMZdd>3bS8S*C2`ZKlQiL&<> zMgZ7k!9GmQ{q&}%ensaYhvvzSiXWtjt&?gX(N==^GWiL5LuHr!GX9_G>iFwz?BpIxl};^#Dc z`X|Q~;A#;6R(ie@YZcwA4s$Hc=HPBsAh4HIIzpF|Y^m$Gf2*eC7C}*t>iX9R4YH}n z&-Ii$V*9ug3p)x0H}N^SmSKER40ke4a5*f9J@qOAPW7Kq+uOl^-@gNv_ZRi-Ax2|&Yy49Wj!UQhw z*a6VrOyearx(@$pzf^#tJ8L=_Iy$Bh5?;qdF(-I6ESIcEs%`%m+< zRW}pg)(C4XWAQGYx-3Yg()k`%S&^hcV)Z~u_FThN_~^G+IBU8aYvj+Xn)B7KUJ2Cg znlojMV?c?(^iH>EXgNj$sB2s=WBNp%P=|oW6;Bm9oL+K?wP#Z*3nuIaaYCv#*1cyH~WM;lECnwB1a)a+fZ-hz*>j<~kB(=Oo$SnZtg|heHcC()l zq<1=3f{xM}4!=KtxZOUMgH)KM8`7T_KCv|23rDe8`#n!yhopW>CSMLK_qr1TxAjvn zzUSKBIxS%`X(4?r64qp!b#&z&e{J9M+fuaY5rl-Ko$fx(wMKR^!GK^@0-dd2=|nnd z2Aj_S$TNA{4Z>$?F(I@xSDQP?{LkORJWOE$C=aU_?+od>UI zTXo~q11tx3O?!W5Wy5e(2E`)6^1RlTrhZ{>=)T}_&gk^~LZh%#{v*E7<4UotYfgg0`QM%xpsW*Uj*#j&=`@o0r;AKacod4D6sFef);z zS|qZA!Zb8|rqM0#@U`yVJw1*L2|S=p+522`1DdpYMN4&NME9t^S@Y@2zRqJwzXXm) zH;ny$yZrPCH;%`!r#p|CplcLdnNAkP5mVwAcwMr1xBT5dg*GMW9Xp=#5TNj$31Y?_ zdLS0;z{ZdCyp6c0h`CU&G~@*LE*%gP@C#M z+gdGj$VIu=1);lZttd2T2_u-uT&+v?9`2f_ENDe-DD}yQLLkM)=yP=;NM$d?1L{jX z;OrYGo+>|=~12z){jQTHJpoXCioqai1F=+Oi ze_T#IGhi>(I&k|x^+_Q|{VKzEAKl+=9lrNU|4$_tOHjFkoWJ?*P^wHR_J@xhDm&nP F@$ZPS?3e%m diff --git a/yellow-paper/docs/public-vm/gen/images/alu/alu.png b/yellow-paper/docs/public-vm/images/alu.png similarity index 100% rename from yellow-paper/docs/public-vm/gen/images/alu/alu.png rename to yellow-paper/docs/public-vm/images/alu.png diff --git a/yellow-paper/docs/public-vm/gen/images/control-flow/avm-control-flow.png b/yellow-paper/docs/public-vm/images/avm-control-flow.png similarity index 100% rename from yellow-paper/docs/public-vm/gen/images/control-flow/avm-control-flow.png rename to yellow-paper/docs/public-vm/images/avm-control-flow.png diff --git a/yellow-paper/docs/public-vm/gen/images/state-model/memory.png b/yellow-paper/docs/public-vm/images/memory.png similarity index 100% rename from yellow-paper/docs/public-vm/gen/images/state-model/memory.png rename to yellow-paper/docs/public-vm/images/memory.png diff --git a/yellow-paper/docs/public-vm/security.md b/yellow-paper/docs/public-vm/security.md new file mode 100644 index 00000000000..1ebc179d1fd --- /dev/null +++ b/yellow-paper/docs/public-vm/security.md @@ -0,0 +1,4 @@ +# VM threat model, security requirements + +An honest Prover must always be able to construct a satisfiable proof for an AVM program, even if the program throws an error. +This implies constraints produced by the AVM **must** be satisfiable. \ No newline at end of file diff --git a/yellow-paper/docs/public-vm/state-model.md b/yellow-paper/docs/public-vm/state-model.md index 615260cd686..cc92dc820da 100644 --- a/yellow-paper/docs/public-vm/state-model.md +++ b/yellow-paper/docs/public-vm/state-model.md @@ -1,12 +1,12 @@ -# The Aztec VM State Model +# State Model The goal of this note is to describe the VM state model and to specify "internal" VM abstractions that can be mapped to circuit designs. -# A memory-only state model +## A memory-only state model The AVM possesses three distinct data regions, accessed via distinct VM instructions: memory, calldata and returndata -![](./gen/images/state-model/memory.png) +![](./images/memory.png) All data regions are linear blocks of memory where each memory cell stores a finite field element. @@ -45,61 +45,130 @@ Indirect memory addressing is required in order to support read/writes into dyna Memory addresses must be tagged to be a `u32` type. -# Tagged memory +## Types and Tagged Memory -We define a `tag` to refer to the potential maximum value of a cell of main memory. The following tags are supported: +### Terminology/legend +- `M[X]`: main memory cell at offset `X` +- `tag`: a value referring to a memory cell's type (its maximum potential value) +- `T[X]`: the tag associated with memory cell at offset `X` +- `in-tag`: an instruction's tag to check input operands against. Present for many but not all instructions. +- `dst-tag`: the target type of a `CAST` instruction, also used to tag the destination memory cell +- `ADD`: shorthand for an `ADD` instruction with `in-tag = X` +- `ADD aOffset bOffset dstOffset`: an full `ADD` instruction with `in-tag = X`. See [here](./InstructionSet#isa-section-add) for more details. +- `CAST`: a `CAST` instruction with `dst-tag`: `X`. `CAST` is the only instruction with a `dst-tag`. See [here](./InstructionSet#isa-section-cast) for more details. -| tag value | maximum memory cell value | -| --------- | ------------------------- | -| 0 | 0 | -| 1 | $2^8 - 1$ | -| 2 | $2^{16} - 1$ | -| 3 | $2^{32} - 1$ | -| 4 | $2^{64} - 1$ | -| 5 | $2^{128} - 1$ | -| 6 | $p - 1$ | +### Tags and tagged memory -Note: $p$ describes the modulus of the finite field that the AVM circuit is defined over (i.e. number of points on the BN254 curve). +A `tag` refers to the maximum potential value of a cell of main memory. The following tags are supported: -The purpose of a tag is to inform the VM of the maximum possible length of an operand value that has been loaded from memory. +| tag value | maximum memory cell value | shorthand | +| --------- | ------------------------- | ------------- | +| 0 | 0 | uninitialized | +| 1 | $2^8 - 1$ | `u8` | +| 2 | $2^{16} - 1$ | `u16` | +| 3 | $2^{32} - 1$ | `u32` | +| 4 | $2^{64} - 1$ | `u64` | +| 5 | $2^{128} - 1$ | `u128` | +| 6 | $p - 1$ | `field` | +| 7 | reserved | reserved | -Multiple AVM instructions explicitly operate over range-constrained input parameters (e.g. ADD32). The maximum allowable value for an instruction's input parameters is defined via an _instruction tag_. Two potential scenarios result: +> Note: $p$ describes the modulus of the finite field that the AVM circuit is defined over (i.e. number of points on the BN254 curve). +> Note: `u32` is used for offsets into the VM's 32-bit addressable main memory -1. A VM instruction's tag value matches the input parameter tag values -2. A VM instruction's tag value does not match the input parameter tag values +The purpose of a tag is to inform the VM of the maximum possible length of an operand value that has been loaded from memory. -If case 2 is triggered, an error flag is raised. +#### Checking input operand tags ---- +Many AVM instructions explicitly operate over range-constrained input parameters (e.g. `ADD`). The maximum allowable value for an instruction's input parameters is defined via an `in-tag` (instruction/input tag). Two potential scenarios result: -### Writing into memory +1. A VM instruction's tag value matches the input parameter tag values +2. A VM instruction's tag value does _not_ match the input parameter tag values -It is required that all VM instructions that write into main memory explicitly define the tag of the output value and ensure the value is appropriately constrained to be consistent with the assigned tag. +If case 2 is triggered, an error flag is raised and the current call's execution reverts. ---- +#### Writing into memory -### MOV and tag conversions +It is required that all VM instructions that write into main memory explicitly define the tag of the destination value and ensure the value is appropriately constrained to be consistent with the assigned tag. You can see an instruction's "**Tag updates**" in its section of the instruction set document (see [here for `ADD`](./InstructionSet#isa-section-add) and [here for `CAST`](./InstructionSet#isa-section-cast)). -The MOV instruction copies data from between memory cell, perserving tags. +#### Standard tagging example: `ADD` -The only VM instruction that can be used to cast between tags is CAST. There are 2 modes to MOV: +``` +# ADD aOffset bOffset dstOffset +assert T[aOffset] == T[bOffset] == u32 // check inputs against in-tag, revert on mismatch +T[dstOffset] = u32 // tag destination with in-tag +M[dstOffset] = M[aOffset] + M[bOffset] // perform the addition +``` -1. The destination tag describes a maximum value that is _less than_ the source tag -2. The destination tag describes a maximum value that is _greater than or equal to_ the source tag +#### `MOV` and tag preservation -For Case 1, range constraints must be applied to ensure the destination value is consistent with the source value after tag truncations have been applied. - -Case 2 is trivial as no additional consistency checks must be performed between soruce and destination values. +The `MOV` instruction copies data from one memory cell to another, preserving tags. In other words, the destination cell's tag will adopt the value of the source: +``` +# MOV srcOffset dstOffset +T[dstOffset] = T[srcOffset] // preserve tag +M[dstOffset] = M[srcOffset] // perform the move +``` ---- +Note that `MOV` does not have an `in-tag` and therefore does not need to make any assertions regarding the source memory cell's type. -### Calldata/returndata and tag conversions +#### `CAST` and tag conversions -All elements in calldata/returndata are implicitly tagged as field elements (i.e. maximum value is $p - 1$). To perform a tag conversion, calldata/returndata must be copied into main memory, followed by an appropriate MOV instruction. +The only VM instruction that can be used to cast between tags is `CAST`. Two potential scenarios result: -## VM threat model, security requirements +1. The destination tag describes a maximum value that is _less than_ the source tag +2. The destination tag describes a maximum value that is _greater than or equal to_ the source tag -TODO: move this somewhere else, doesn't quite fit. +For Case 1, range constraints must be applied to ensure the destination value is consistent with the source value after tag truncations have been applied. -An honest Prover must always be able to construct a satsisfiable proof for an AVM program, even if the program throws an error. -This implies constraints produced by the AVM **must** be satisfiable. +Case 2 is trivial as no additional consistency checks must be performed between source and destination values. + +``` +# CAST srcOffset dstOffset +T[dstOffset] = u64 // tag destination with dst-tag +M[dstOffset] = cast(M[srcOffset]) // perform cast +``` + +#### Indirect `MOV` and extra tag checks + +A `MOV` instruction may flag its source and/or destination offsets as "indirect". An indirect memory access performs `M[M[offset]]` instead of the standard `M[offset]`. Memory offsets must be `u32`s since main memory is a 32-bit addressable space, and so indirect memory accesses include additional checks. + +Additional checks for a `MOV` with an indirect source offset: +``` +# MOV srcOffset dstOffset // with indirect source +assert T[srcOffset] == u32 // enforce that `M[srcOffset]` is itself a valid memory offset +T[dstOffset] = T[T[srcOffset]] // tag destination to match indirect source tag +M[dstOffset] = M[M[srcOffset]] // perform move from indirect source +``` + +Additional checks for a `MOV` with an indirect destination offset: +``` +# MOV srcOffset dstOffset // with indirect destination +assert T[dstOffset] == u32 // enforce that `M[dstOffset]` is itself a valid memory offset +T[T[dstOffset]] = T[srcOffset] // tag indirect destination to match source tag +M[M[dstOffset]] = M[srcOffset] // perform move to indirect destination +``` + +Additional checks for a `MOV` with both indirect source and destination offsets: +``` +# MOV srcOffset dstOffset // with indirect source and destination +assert T[srcOffset] == T[dstOffset] == u32 // enforce that `M[*Offset]` are valid memory offsets +T[T[dstOffset]] = T[T[srcOffset]] // tag indirect destination to match indirect source tag +M[M[dstOffset]] = M[M[srcOffset]] // perform move to indirect destination +``` + +#### Calldata/returndata and tag conversions + +All elements in calldata/returndata are implicitly tagged as field elements (i.e. maximum value is $p - 1$). To perform a tag conversion, calldata/returndata must be copied into main memory (via [`CALLDATACOPY`](./InstructionSet#isa-section-calldatacopy) or [`RETURN`'s `offset` and `size`](./InstructionSet#isa-section-return)), followed by an appropriate `CAST` instruction. +``` +# Copy calldata to memory and cast a word to u64 +CALLDATACOPY cdOffset size offsetA // copy calldata to memory at offsetA +CAST offsetA dstOffset // cast first copied word to a u64 +``` +This would perform the following: +``` +# CALLDATACOPY cdOffset size offsetA +T[offsetA:offsetA+size] = field // CALLDATACOPY assigns the field tag +M[offsetA:offsetA+size] = calldata[cdOffset:cdOffset+size] // copy calldata to memory +# CAST offsetA dstOffset +T[offsetA] = u64 // CAST assigns a new tag +M[dstOffset] = cast(offsetA) // perform the cast operation +``` \ No newline at end of file diff --git a/yellow-paper/docs/public-vm/tagged-memory.md b/yellow-paper/docs/public-vm/tagged-memory.md deleted file mode 100644 index a72c693da93..00000000000 --- a/yellow-paper/docs/public-vm/tagged-memory.md +++ /dev/null @@ -1,60 +0,0 @@ -# Tagged Memory - An instruction-set centric explanation - -## Explanation of Tagged Memory -Every word in memory will have an associated `type-tag` (unset, u8, u16, u32, u64, u128, field). For memory address `a`, we refer to the corresponding memory word's `type-tag` as `T[a]`. - -Every instruction will be flagged with an `op-type` in bytecode (u8, u16, u32, u64, u128, field). - -If an instruction uses a "source operand" as a memory location (e.g. `z = M[s0] + y`), the VM first retrieves the `type-tag` referenced by the operand (`T[s0]`) and enforces that it matches `op-type`. The VM enforces this for all source operands used for direct memory reads. - -If an instruction uses a "dest operand" as a memory location (e.g. `M[d0] = x + y`), when the VM assigns a word to that memory location, it also assigns the corresponding `type-tag` (`T[d0] = op-type`). The VM performs this tag assignment for all dest operands used for direct memory writes. - -**If an instruction fails any of its operand type-tag-checks, the current call's execution reverts!** - -### `ADD<32>` example -`ADD<32>` is an `ADD` instruction with `op-type` u32. As elaborated on later, an `ADD` performs `M[d0] = M[s0] + M[s1]`. In this case, both `s0` and `s1` are "source operands" used for direct memory reads to retrieve inputs to an addition. So, the VM enforces the `op-type(u32) == T[s0] == T[s1]`. `d0` here is a "dest operand" used for a direct memory write to store the output of the addition. So, the VM tags memory location `d0` with `type-tag` of u32: `T[d0] = op-type(u32)`. - -Here is a summary of what is happening for `ADD<32>`: -``` -assert T[s0] == u32 // enforce that source memory locations' type-tags == op-type -assert T[s1] == u32 -T[d0] = u32 // tag destination memory location as op-type -M[d0] = M[s0] + M[s1] -``` - - -### Type tags and `CASTs` - -`CAST` is different from other instructions in that it will be flagged with an additional `dest-type`. So, a `CAST` will assign `dest-type` (instead of `op-type`) to the memory location specified by its "dest operand" `d0`. `CAST<32, 64>` enforces that `T[s0]` matches u32 (the `op-type`) and assigns `T[d0] = u64` (the `dest-type`). - -Here is a summary of what is happening for a `CAST<32, 64>`: -``` -assert T[s0] == u32 // enforce that source memory location's type-tags == op-type -T[d0] = u64 // tag destination memory location as dest-type -M[d0] = M[s0] -``` - -### Type tags and indirect `MOVs` -A basic `MOV` instruction performs direct memory accesses and operates in the same as a simple `ADD` instruction as outlined above. A simple `MOV<64>` would do: -``` -assert T[s0] == u64 // enforce that source memory location's type-tag == op-type -T[d0] = u64 // tag destination memory location with op-type -M[d0] = M[s0] -``` - -Consider a `MOV<64, s0-indirect>`, which treats s0 as an indirect memory pointer to perform `M[d0] = M[M[s0]]`. Here, the VM first needs to enforce that `M[s0]` is a valid memory address (has type u32), and it then needs to perform the standard check that resulting word has type matching `op-type`: -``` -assert T[s0] == u32 // enforce that the direct source memory location contains a valid address (type-tag == u32) -assert T[M[s0]] == u64 // enforce that the indirect source memory location's type-tag == op-type -T[d0] = u64 // tag destination memory location with op-type -M[d0] = M[M[s0]] -``` - -Similarly, a `MOV<64, d0-indirect>` treats d0 as an indirect memory pointer to perform `M[M[d0]] = M[s0]`, and here the VM first needs to enforce that `M[d0]` is a valid memory address (has type u32) before assigning the destination location its type tag: -``` -assert T[s0] == u64 // enforce that source memory location's type-tag == op-type -assert T[d0] == u32 // enforce that the direct destination memory location contains a valid address (type-tag == u32) -T[M[d0]] = u64 // tag indirect destination memory location with op-type -M[M[d0]] = M[s0] -``` - diff --git a/yellow-paper/src/preprocess/InstructionSet/InstructionSet.js b/yellow-paper/src/preprocess/InstructionSet/InstructionSet.js index 6da9d78749c..844a89c369b 100644 --- a/yellow-paper/src/preprocess/InstructionSet/InstructionSet.js +++ b/yellow-paper/src/preprocess/InstructionSet/InstructionSet.js @@ -7,8 +7,8 @@ const TOPICS_IN_SECTIONS = [ "Name", "Summary", "Category", "Flags", "Args", "Expression", "Details", "Tag checks", "Tag updates", "Bit-size", ]; -const OP_TYPE_DESCRIPTION = "The [type/size](./Types) to check inputs against and tag the output with."; -const DEST_TYPE_DESCRIPTION = "The [type/size](./Types) to tag the output with when different from `op-type`."; +const IN_TAG_DESCRIPTION = "The [tag/size](./state-model#tags-and-tagged-memory) to check inputs against and tag the destination with."; +const DST_TAG_DESCRIPTION = "The [tag/size](./state-model#tags-and-tagged-memory) to tag the destination with but not to check inputs against."; const INDIRECT_FLAG_DESCRIPTION = "Toggles whether each memory-offset argument is an indirect offset. 0th bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`."; const INSTRUCTION_SET_RAW = [ @@ -18,7 +18,7 @@ const INSTRUCTION_SET_RAW = [ "Category": "arithmetic", "Flags": [ {"name": "indirect", "description": INDIRECT_FLAG_DESCRIPTION}, - {"name": "op-type", "description": OP_TYPE_DESCRIPTION}, + {"name": "in-tag", "description": IN_TAG_DESCRIPTION}, ], "#memreads": "2", "#memwrites": "1", @@ -30,8 +30,8 @@ const INSTRUCTION_SET_RAW = [ "Expression": "`M[dstOffset] = M[aOffset] + M[bOffset] mod 2^k`", "Summary": "Addition (a + b)", "Details": "", - "Tag checks": "`T[aOffset] == T[bOffset] == op-type`", - "Tag updates": "`T[dstOffset] = op-type`", + "Tag checks": "`T[aOffset] == T[bOffset] == in-tag`", + "Tag updates": "`T[dstOffset] = in-tag`", }, { "id": "sub", @@ -39,7 +39,7 @@ const INSTRUCTION_SET_RAW = [ "Category": "arithmetic", "Flags": [ {"name": "indirect", "description": INDIRECT_FLAG_DESCRIPTION}, - {"name": "op-type", "description": OP_TYPE_DESCRIPTION}, + {"name": "in-tag", "description": IN_TAG_DESCRIPTION}, ], "#memreads": "2", "#memwrites": "1", @@ -51,8 +51,8 @@ const INSTRUCTION_SET_RAW = [ "Expression": "`M[dstOffset] = M[aOffset] - M[bOffset] mod 2^k`", "Summary": "Subtraction (a - b)", "Details": "", - "Tag checks": "`T[aOffset] == T[bOffset] == op-type`", - "Tag updates": "`T[dstOffset] = op-type`", + "Tag checks": "`T[aOffset] == T[bOffset] == in-tag`", + "Tag updates": "`T[dstOffset] = in-tag`", }, { "id": "div", @@ -60,7 +60,7 @@ const INSTRUCTION_SET_RAW = [ "Category": "arithmetic", "Flags": [ {"name": "indirect", "description": INDIRECT_FLAG_DESCRIPTION}, - {"name": "op-type", "description": OP_TYPE_DESCRIPTION}, + {"name": "in-tag", "description": IN_TAG_DESCRIPTION}, ], "#memreads": "2", "#memwrites": "1", @@ -72,8 +72,8 @@ const INSTRUCTION_SET_RAW = [ "Expression": "`M[dstOffset] = M[aOffset] / M[bOffset]`", "Summary": "Unsigned division (a / b)", "Details": "", - "Tag checks": "`T[aOffset] == T[bOffset] == op-type`", - "Tag updates": "`T[dstOffset] = op-type`", + "Tag checks": "`T[aOffset] == T[bOffset] == in-tag`", + "Tag updates": "`T[dstOffset] = in-tag`", }, { "id": "eq", @@ -81,7 +81,7 @@ const INSTRUCTION_SET_RAW = [ "Category": "conditional", "Flags": [ {"name": "indirect", "description": INDIRECT_FLAG_DESCRIPTION}, - {"name": "op-type", "description": OP_TYPE_DESCRIPTION}, + {"name": "in-tag", "description": IN_TAG_DESCRIPTION}, ], "#memreads": "2", "#memwrites": "1", @@ -93,8 +93,8 @@ const INSTRUCTION_SET_RAW = [ "Expression": "`M[dstOffset] = M[aOffset] == M[bOffset] ? 1 : 0`", "Summary": "Equality check (a == b)", "Details": "", - "Tag checks": "`T[aOffset] == T[bOffset] == op-type`", - "Tag updates": "`T[dstOffset] = op-type`", + "Tag checks": "`T[aOffset] == T[bOffset] == in-tag`", + "Tag updates": "`T[dstOffset] = in-tag`", }, { "id": "lt", @@ -102,7 +102,7 @@ const INSTRUCTION_SET_RAW = [ "Category": "conditional", "Flags": [ {"name": "indirect", "description": INDIRECT_FLAG_DESCRIPTION}, - {"name": "op-type", "description": OP_TYPE_DESCRIPTION}, + {"name": "in-tag", "description": IN_TAG_DESCRIPTION}, ], "#memreads": "2", "#memwrites": "1", @@ -114,8 +114,8 @@ const INSTRUCTION_SET_RAW = [ "Expression": "`M[dstOffset] = M[aOffset] < M[bOffset] ? 1 : 0`", "Summary": "Less-than check (a < b)", "Details": "", - "Tag checks": "`T[aOffset] == T[bOffset] == op-type`", - "Tag updates": "`T[dstOffset] = op-type`", + "Tag checks": "`T[aOffset] == T[bOffset] == in-tag`", + "Tag updates": "`T[dstOffset] = in-tag`", }, { "id": "lte", @@ -123,7 +123,7 @@ const INSTRUCTION_SET_RAW = [ "Category": "conditional", "Flags": [ {"name": "indirect", "description": INDIRECT_FLAG_DESCRIPTION}, - {"name": "op-type", "description": OP_TYPE_DESCRIPTION}, + {"name": "in-tag", "description": IN_TAG_DESCRIPTION}, ], "#memreads": "2", "#memwrites": "1", @@ -135,8 +135,8 @@ const INSTRUCTION_SET_RAW = [ "Expression": "`M[dstOffset] = M[aOffset] <= M[bOffset] ? 1 : 0`", "Summary": "Less-than-or-equals check (a <= b)", "Details": "", - "Tag checks": "`T[aOffset] == T[bOffset] == op-type`", - "Tag updates": "`T[dstOffset] = op-type`", + "Tag checks": "`T[aOffset] == T[bOffset] == in-tag`", + "Tag updates": "`T[dstOffset] = in-tag`", }, { "id": "and", @@ -144,7 +144,7 @@ const INSTRUCTION_SET_RAW = [ "Category": "bitwise", "Flags": [ {"name": "indirect", "description": INDIRECT_FLAG_DESCRIPTION}, - {"name": "op-type", "description": OP_TYPE_DESCRIPTION}, + {"name": "in-tag", "description": IN_TAG_DESCRIPTION}, ], "#memreads": "2", "#memwrites": "1", @@ -156,8 +156,8 @@ const INSTRUCTION_SET_RAW = [ "Expression": "`M[dstOffset] = M[aOffset] AND M[bOffset]`", "Summary": "Bitwise AND (a & b)", "Details": "", - "Tag checks": "`T[aOffset] == T[bOffset] == op-type`", - "Tag updates": "`T[dstOffset] = op-type`", + "Tag checks": "`T[aOffset] == T[bOffset] == in-tag`", + "Tag updates": "`T[dstOffset] = in-tag`", }, { "id": "or", @@ -165,7 +165,7 @@ const INSTRUCTION_SET_RAW = [ "Category": "bitwise", "Flags": [ {"name": "indirect", "description": INDIRECT_FLAG_DESCRIPTION}, - {"name": "op-type", "description": OP_TYPE_DESCRIPTION}, + {"name": "in-tag", "description": IN_TAG_DESCRIPTION}, ], "#memreads": "2", "#memwrites": "1", @@ -177,8 +177,8 @@ const INSTRUCTION_SET_RAW = [ "Expression": "`M[dstOffset] = M[aOffset] OR M[bOffset]`", "Summary": "Bitwise OR (a | b)", "Details": "", - "Tag checks": "`T[aOffset] == T[bOffset] == op-type`", - "Tag updates": "`T[dstOffset] = op-type`", + "Tag checks": "`T[aOffset] == T[bOffset] == in-tag`", + "Tag updates": "`T[dstOffset] = in-tag`", }, { "id": "xor", @@ -186,7 +186,7 @@ const INSTRUCTION_SET_RAW = [ "Category": "bitwise", "Flags": [ {"name": "indirect", "description": INDIRECT_FLAG_DESCRIPTION}, - {"name": "op-type", "description": OP_TYPE_DESCRIPTION}, + {"name": "in-tag", "description": IN_TAG_DESCRIPTION}, ], "#memreads": "2", "#memwrites": "1", @@ -198,8 +198,8 @@ const INSTRUCTION_SET_RAW = [ "Expression": "`M[dstOffset] = M[aOffset] XOR M[bOffset]`", "Summary": "Bitwise XOR (a ^ b)", "Details": "", - "Tag checks": "`T[aOffset] == T[bOffset] == op-type`", - "Tag updates": "`T[dstOffset] = op-type`", + "Tag checks": "`T[aOffset] == T[bOffset] == in-tag`", + "Tag updates": "`T[dstOffset] = in-tag`", }, { "id": "not", @@ -207,7 +207,7 @@ const INSTRUCTION_SET_RAW = [ "Category": "bitwise", "Flags": [ {"name": "indirect", "description": INDIRECT_FLAG_DESCRIPTION}, - {"name": "op-type", "description": OP_TYPE_DESCRIPTION}, + {"name": "in-tag", "description": IN_TAG_DESCRIPTION}, ], "#memreads": "1", "#memwrites": "1", @@ -218,8 +218,8 @@ const INSTRUCTION_SET_RAW = [ "Expression": "`M[dstOffset] = NOT M[aOffset]`", "Summary": "Bitwise NOT (inversion)", "Details": "", - "Tag checks": "`T[aOffset] == op-type`", - "Tag updates": "`T[dstOffset] = op-type`", + "Tag checks": "`T[aOffset] == in-tag`", + "Tag updates": "`T[dstOffset] = in-tag`", }, { "id": "shl", @@ -227,7 +227,7 @@ const INSTRUCTION_SET_RAW = [ "Category": "bitwise", "Flags": [ {"name": "indirect", "description": INDIRECT_FLAG_DESCRIPTION}, - {"name": "op-type", "description": OP_TYPE_DESCRIPTION}, + {"name": "in-tag", "description": IN_TAG_DESCRIPTION}, ], "#memreads": "2", "#memwrites": "1", @@ -239,8 +239,8 @@ const INSTRUCTION_SET_RAW = [ "Expression": "`M[dstOffset] = M[aOffset] << M[bOffset]`", "Summary": "Bitwise leftward shift (a << b)", "Details": "", - "Tag checks": "`T[aOffset] == T[bOffset] == op-type`", - "Tag updates": "`T[dstOffset] = op-type`", + "Tag checks": "`T[aOffset] == T[bOffset] == in-tag`", + "Tag updates": "`T[dstOffset] = in-tag`", }, { "id": "shr", @@ -248,7 +248,7 @@ const INSTRUCTION_SET_RAW = [ "Category": "bitwise", "Flags": [ {"name": "indirect", "description": INDIRECT_FLAG_DESCRIPTION}, - {"name": "op-type", "description": OP_TYPE_DESCRIPTION}, + {"name": "in-tag", "description": IN_TAG_DESCRIPTION}, ], "#memreads": "2", "#memwrites": "1", @@ -260,8 +260,8 @@ const INSTRUCTION_SET_RAW = [ "Expression": "`M[dstOffset] = M[aOffset] >> M[bOffset]`", "Summary": "Bitwise rightward shift (a >> b)", "Details": "", - "Tag checks": "`T[aOffset] == T[bOffset] == op-type`", - "Tag updates": "`T[dstOffset] = op-type`", + "Tag checks": "`T[aOffset] == T[bOffset] == in-tag`", + "Tag updates": "`T[dstOffset] = in-tag`", }, { "id": "cast", @@ -269,7 +269,7 @@ const INSTRUCTION_SET_RAW = [ "Category": "types", "Flags": [ {"name": "indirect", "description": INDIRECT_FLAG_DESCRIPTION}, - {"name": "dest-type", "description": DEST_TYPE_DESCRIPTION}, + {"name": "dst-tag", "description": DST_TAG_DESCRIPTION}, ], "#memreads": "1", "#memwrites": "1", @@ -277,11 +277,11 @@ const INSTRUCTION_SET_RAW = [ {"name": "aOffset", "description": "memory offset of word to cast"}, {"name": "dstOffset", "description": "memory offset specifying where to store operation's result"}, ], - "Expression": "`M[dstOffset] = cast(M[aOffset])`", + "Expression": "`M[dstOffset] = cast(M[aOffset])`", "Summary": "Type cast", - "Details": "Cast a word in memory based on the `dest-type` specified in the bytecode. Truncates when casting to a smaller type, left-zero-pads when casting to a larger type.", + "Details": "Cast a word in memory based on the `dst-tag` specified in the bytecode. Truncates when casting to a smaller type, left-zero-pads when casting to a larger type. See [here](./state-model#cast-and-tag-conversions) for more details.", "Tag checks": "", - "Tag updates": "`T[dstOffset] = dest-type`", + "Tag updates": "`T[dstOffset] = dst-tag`", }, { "id": "set", @@ -289,7 +289,7 @@ const INSTRUCTION_SET_RAW = [ "Category": "memory", "Flags": [ {"name": "indirect", "description": INDIRECT_FLAG_DESCRIPTION}, - {"name": "op-type", "description": "The [type/size](./Types) to check inputs against and tag the output with. `field` type is NOT supported for SET."}, + {"name": "in-tag", "description": "The [type/size](./state-model#tags-and-tagged-memory) to check inputs against and tag the destination with. `field` type is NOT supported for SET."}, ], "#memreads": "0", "#memwrites": "1", @@ -299,9 +299,9 @@ const INSTRUCTION_SET_RAW = [ ], "Expression": "`M[dstOffset] = const`", "Summary": "Set a memory word from a constant in the bytecode.", - "Details": "Set memory word at `dstOffset` to `const`'s immediate value. `const`'s bit-size (N) can be 8, 16, 32, 64, or 128 based on `op-type`. It _cannot be 254 (`field` type)_!", + "Details": "Set memory word at `dstOffset` to `const`'s immediate value. `const`'s bit-size (N) can be 8, 16, 32, 64, or 128 based on `in-tag`. It _cannot be 254 (`field` type)_!", "Tag checks": "", - "Tag updates": "`T[dstOffset] = op-type`", + "Tag updates": "`T[dstOffset] = in-tag`", }, { "id": "mov", @@ -354,14 +354,14 @@ const INSTRUCTION_SET_RAW = [ "#memwrites": "`s1`", "Args": [ {"name": "cdOffset", "description": "offset into calldata to copy from"}, - {"name": "size", "description": "number of words to copy", "mode": "immediate", "type": "u24"}, + {"name": "copySize", "description": "number of words to copy", "mode": "immediate", "type": "u32"}, {"name": "dstOffset", "description": "memory offset specifying where to copy the first word to"}, ], - "Expression": "`M[dstOffset:dstOffset+size] = calldata[cdOffset:cdOffset+size]`", + "Expression": "`M[dstOffset:dstOffset+copySize] = calldata[cdOffset:cdOffset+copySize]`", "Summary": "Copy calldata into memory.", "Details": "Calldata is read-only and cannot be directly operated on by other instructions. This instruction moves words from calldata into memory so they can be operated on normally.", "Tag checks": "", - "Tag updates": "`T[dstOffset:dstOffset+size] = field`", + "Tag updates": "`T[dstOffset:dstOffset+copySize] = field`", }, { "id": "sload", @@ -463,7 +463,7 @@ const INSTRUCTION_SET_RAW = [ "#memreads": "0", "#memwrites": "0", "Args": [ - {"name": "loc", "description": "target location to jump to", "mode": "immediate", "type": "u24"}, + {"name": "loc", "description": "target location to jump to", "mode": "immediate", "type": "u32"}, ], "Expression": "`PC = loc`", "Summary": "Jump to a location in the bytecode.", @@ -481,7 +481,7 @@ const INSTRUCTION_SET_RAW = [ "#memreads": "3", "#memwrites": "0", "Args": [ - {"name": "loc", "description": "target location conditionally jump to", "mode": "immediate", "type": "u24"}, + {"name": "loc", "description": "target location conditionally jump to", "mode": "immediate", "type": "u32"}, {"name": "condOffset", "description": "memory offset of the operations 'conditional' input"}, ], "Expression": "`PC = M[condOffset] > 0 ? loc : PC`", @@ -500,10 +500,10 @@ const INSTRUCTION_SET_RAW = [ "#memreads": "`s1`", "#memwrites": "0", "Args": [ - {"name": "offset", "description": "memory offset of first word to return"}, - {"name": "size", "description": "number of words to return", "mode": "immediate", "type": "u24"}, + {"name": "retOffset", "description": "memory offset of first word to return"}, + {"name": "retSize", "description": "number of words to return", "mode": "immediate", "type": "u32"}, ], - "Expression": "`return(M[offset:offset+size])`", + "Expression": "`return(M[retOffset:retOffset+retSize])`", "Summary": "Halt execution with `success`, optionally returning some data.", "Details": "Return control flow to the calling context/contract.", "Tag checks": "", @@ -519,10 +519,10 @@ const INSTRUCTION_SET_RAW = [ "#memreads": "`s1`", "#memwrites": "0", "Args": [ - {"name": "offset", "description": "memory offset of first word to return"}, - {"name": "size", "description": "number of words to return", "mode": "immediate", "type": "u24"}, + {"name": "retOffset", "description": "memory offset of first word to return"}, + {"name": "retSize", "description": "number of words to return", "mode": "immediate", "type": "u32"}, ], - "Expression": "`revert(M[offset:offset+size])`", + "Expression": "`revert(M[retOffset:retOffset+retSize])`", "Summary": "Halt execution with `failure`, reverting state changes and optionally returning some data.", "Details": "Return control flow to the calling context/contract.", "Tag checks": "", @@ -535,21 +535,20 @@ const INSTRUCTION_SET_RAW = [ "Flags": [ {"name": "indirect", "description": INDIRECT_FLAG_DESCRIPTION}, ], - "#memreads": "5", + "#memreads": "7", "#memwrites": "`1+retSize`", "Args": [ - {"name": "l1GasOffset", "description": "amount of L1 gas to provide to the callee"}, - {"name": "l2GasOffset", "description": "amount of L2 gas to provide to the callee"}, + {"name": "gasOffset", "description": "offset to two words containing `{l1Gas, l2Gas}`: amount of L1 and L2 gas to provide to the callee"}, {"name": "addrOffset", "description": "address of the contract to call"}, {"name": "argsOffset", "description": "memory offset to args (will become the callee's calldata)"}, - {"name": "argsSize", "description": "number of words to pass via callee's calldata", "mode": "immediate", "type": "u24"}, + {"name": "argsSize", "description": "number of words to pass via callee's calldata", "mode": "immediate", "type": "u32"}, {"name": "retOffset", "description": "destination memory offset specifying where to store the data returned from the callee"}, - {"name": "retSize", "description": "number of words to copy from data returned by callee", "mode": "immediate", "type": "u24"}, + {"name": "retSize", "description": "number of words to copy from data returned by callee", "mode": "immediate", "type": "u32"}, {"name": "successOffset", "description": "destination memory offset specifying where to store the call's success (0: failure, 1: success)", "type": "u8"}, ], "Expression":` M[successOffset] = call( - M[l1GasOffset], M[l2GasOffset], M[addrOffset], + M[gasOffset], M[gasOffset+1], M[addrOffset], M[argsOffset], M[argsSize], M[retOffset], M[retSize]) `, @@ -557,7 +556,7 @@ M[successOffset] = call( "Details": `Creates a new CallContext, triggers execution of the corresponding contract code, and then resumes execution in the current CallContext. A non-existent contract or one with no code will return success. Nested call has an incremented \`CallContext.calldepth\`.`, - "Tag checks": "`T[l1GasOffset] == T[l2GasOffset] == u32`", + "Tag checks": "`T[gasOffset] == T[gasOffset+1] == u32`", "Tag updates": ` T[successOffset] = u8 T[retOffset:retOffset+retSize] = field @@ -570,27 +569,26 @@ T[retOffset:retOffset+retSize] = field "Flags": [ {"name": "indirect", "description": INDIRECT_FLAG_DESCRIPTION}, ], - "#memreads": "5", + "#memreads": "7", "#memwrites": "`1+retSize`", "Args": [ - {"name": "l1GasOffset", "description": "amount of L1 gas to provide to the callee"}, - {"name": "l2GasOffset", "description": "amount of L2 gas to provide to the callee"}, + {"name": "gasOffset", "description": "offset to two words containing `{l1Gas, l2Gas}`: amount of L1 and L2 gas to provide to the callee"}, {"name": "addrOffset", "description": "address of the contract to call"}, {"name": "argsOffset", "description": "memory offset to args (will become the callee's calldata)"}, - {"name": "argsSize", "description": "number of words to pass via callee's calldata", "mode": "immediate", "type": "u24"}, + {"name": "argsSize", "description": "number of words to pass via callee's calldata", "mode": "immediate", "type": "u32"}, {"name": "retOffset", "description": "destination memory offset specifying where to store the data returned from the callee"}, - {"name": "retSize", "description": "number of words to copy from data returned by callee", "mode": "immediate", "type": "u24"}, + {"name": "retSize", "description": "number of words to copy from data returned by callee", "mode": "immediate", "type": "u32"}, {"name": "successOffset", "description": "destination memory offset specifying where to store the call's success (0: failure, 1: success)", "type": "u8"}, ], "Expression": ` M[successOffset] = staticcall( - M[l1GasOffset], M[l2GasOffset], M[addrOffset], + M[gasOffset], M[gasOffset+1], M[addrOffset], M[argsOffset], M[argsSize], M[retOffset], M[retSize]) `, "Summary": "Call into another contract, disallowing persistent state modifications.", "Details": "Same as `CALL`, but the callee is cannot modify persistent state. Disallowed instructions are `SSTORE`, `ULOG`, `CALL`.", - "Tag checks": "`T[l1GasOffset] == T[l2GasOffset] == u32`", + "Tag checks": "`T[gasOffset] == T[gasOffset+1] == u32`", "Tag updates": ` T[successOffset] = u8 T[retOffset:retOffset+retSize] = field @@ -606,10 +604,10 @@ T[retOffset:retOffset+retSize] = field "#memreads": "`s1`", "#memwrites": "0", "Args": [ - {"name": "offset", "description": "memory offset of the data to log"}, - {"name": "size", "description": "number of words to log", "mode": "immediate", "type": "u24"}, + {"name": "logOffset", "description": "memory offset of the data to log"}, + {"name": "logSize", "description": "number of words to log", "mode": "immediate", "type": "u32"}, ], - "Expression": "`ulog(M[offset:offset+size])`", + "Expression": "`ulog(M[logOffset:logOffset+logSize])`", "Summary": "Emit an unencrypted log with data from the `field` memory page", "Details": "", "Tag checks": "", diff --git a/yellow-paper/src/preprocess/InstructionSet/InstructionSize.js b/yellow-paper/src/preprocess/InstructionSet/InstructionSize.js index 0cefffcf327..f6cac342791 100644 --- a/yellow-paper/src/preprocess/InstructionSet/InstructionSize.js +++ b/yellow-paper/src/preprocess/InstructionSet/InstructionSize.js @@ -1,7 +1,8 @@ const OPCODE_SIZE = 8; const FLAG_SIZE = 8; +const RESERVED_SIZE = 8; -const DEFAULT_OPERAND_SIZE = 24; // for direct/indirect memory offsets +const DEFAULT_OPERAND_SIZE = 32; // for direct/indirect memory offsets function argSize(arg) { if (arg['mode'] && arg['mode'] == 'immediate') { @@ -31,7 +32,7 @@ function toOpcode(index) { * 1 byte for dest-type */ function instructionSize(instr) { - let size = OPCODE_SIZE; + let size = OPCODE_SIZE + RESERVED_SIZE; let numUntypedImmediates = 0; for (let arg of instr['Args']) { const aSize = argSize(arg); @@ -59,6 +60,9 @@ function instructionBitFormat(instr, index) { 'code': toOpcode(index), 'size': OPCODE_SIZE, }, + 'Reserved': { + 'size': RESERVED_SIZE, + }, 'Args': [], 'Flags': [], }; diff --git a/yellow-paper/src/preprocess/InstructionSet/genBitFormats.js b/yellow-paper/src/preprocess/InstructionSet/genBitFormats.js index 99bdc4c34f8..c406f70a85e 100644 --- a/yellow-paper/src/preprocess/InstructionSet/genBitFormats.js +++ b/yellow-paper/src/preprocess/InstructionSet/genBitFormats.js @@ -10,6 +10,7 @@ function run() { const bitFormat = instructionBitFormat(instr, i); formats.push(bitFormat); } + console.log(`Writing ${formats.length} bit formats to InstructionBitFormats.json`); fs.writeFileSync('./InstructionBitFormats.json', JSON.stringify(formats)); } run(); \ No newline at end of file diff --git a/yellow-paper/src/preprocess/InstructionSet/InstructionSetMarkdownGen.js b/yellow-paper/src/preprocess/InstructionSet/genMarkdown.js similarity index 96% rename from yellow-paper/src/preprocess/InstructionSet/InstructionSetMarkdownGen.js rename to yellow-paper/src/preprocess/InstructionSet/genMarkdown.js index b9a689749cd..e26940ef03f 100644 --- a/yellow-paper/src/preprocess/InstructionSet/InstructionSetMarkdownGen.js +++ b/yellow-paper/src/preprocess/InstructionSet/genMarkdown.js @@ -19,7 +19,7 @@ function stripBraces(str) { function instructionSetPreface() { let preface = "[comment]: # (THIS IS A GENERATED FILE! DO NOT EDIT!)\n"; preface += "[comment]: # (Generated via `yarn preprocess`)\n\n"; - preface += "[comment]: # (Generated by InstructionSetMarkdownGen.tsx and InstructionSet.js)\n\n"; + preface += "[comment]: # (Generated by genMarkdown.js, InstructionSet.js, InstructionSize.js)\n\n"; preface += "import Markdown from 'react-markdown'\n"; preface += "import CodeBlock from '@theme/CodeBlock'\n\n"; return preface; @@ -106,7 +106,7 @@ function markdownInstructionSetSection(pathToGenDir) { } const bitFormatPath = `./images/bit-formats/${name.replace(/`/g, '')}.png`; if (fs.existsSync(`${pathToGenDir}/${bitFormatPath}`)) { - subsection += `\n![](${bitFormatPath})`; + subsection += `\n[![](${bitFormatPath})](${bitFormatPath})`; } markdown += `\n${subsection}\n`; } diff --git a/yellow-paper/src/preprocess/index.js b/yellow-paper/src/preprocess/index.js index 71c4227df06..fe2167bdf09 100644 --- a/yellow-paper/src/preprocess/index.js +++ b/yellow-paper/src/preprocess/index.js @@ -1,4 +1,4 @@ -const {generateInstructionSet} = require('./InstructionSet/InstructionSetMarkdownGen'); +const {generateInstructionSet} = require('./InstructionSet/genMarkdown'); async function run() { await generateInstructionSet(); From cdd92595c313617189a530e0bfda987db211ae6b Mon Sep 17 00:00:00 2001 From: ledwards2225 <98505400+ledwards2225@users.noreply.github.com> Date: Thu, 7 Dec 2023 11:18:33 -0700 Subject: [PATCH 08/35] feat: merge recursive verifier (#3588) This PR includes - Recursive merge verifier implementation and independent test - Incorporation of recursive merge verification into `Goblin::accumulate` (and therefore into the full goblin recursion tests). - Verification of the final ultra and merge proofs in goblin recursion tests - Addition of direct constructors of Ultra and Merge verifiers from minimal inputs - no composer required Closes https://github.com/AztecProtocol/barretenberg/issues/797 --- barretenberg/cpp/src/CMakeLists.txt | 2 +- .../commitment_schemes/kzg/kzg.hpp | 11 +- .../src/barretenberg/goblin/CMakeLists.txt | 2 +- .../goblin/full_goblin_composer.test.cpp | 67 ------------ .../goblin/full_goblin_recursion.test.cpp | 24 +++-- .../cpp/src/barretenberg/goblin/goblin.hpp | 35 +++++- .../src/barretenberg/goblin/mock_circuits.hpp | 9 +- .../verifier/merge_recursive_verifier.cpp | 87 +++++++++++++++ .../verifier/merge_recursive_verifier.hpp | 31 ++++++ .../honk/verifier/merge_verifier.test.cpp | 100 ++++++++++++++++++ .../ultra_honk/goblin_ultra_composer.test.cpp | 2 +- .../ultra_honk/merge_verifier.cpp | 7 +- .../ultra_honk/merge_verifier.hpp | 4 +- .../ultra_honk/ultra_composer.hpp | 10 +- .../ultra_honk/ultra_verifier.cpp | 13 +++ .../ultra_honk/ultra_verifier.hpp | 2 + 16 files changed, 296 insertions(+), 110 deletions(-) delete mode 100644 barretenberg/cpp/src/barretenberg/goblin/full_goblin_composer.test.cpp rename barretenberg/cpp/src/barretenberg/{stdlib/recursion => }/goblin/full_goblin_recursion.test.cpp (84%) create mode 100644 barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/merge_recursive_verifier.cpp create mode 100644 barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/merge_recursive_verifier.hpp create mode 100644 barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/merge_verifier.test.cpp diff --git a/barretenberg/cpp/src/CMakeLists.txt b/barretenberg/cpp/src/CMakeLists.txt index b09a2181ebc..8f3ee4289c5 100644 --- a/barretenberg/cpp/src/CMakeLists.txt +++ b/barretenberg/cpp/src/CMakeLists.txt @@ -58,8 +58,8 @@ add_subdirectory(barretenberg/eccvm) add_subdirectory(barretenberg/env) add_subdirectory(barretenberg/examples) add_subdirectory(barretenberg/flavor) -add_subdirectory(barretenberg/grumpkin_srs_gen) add_subdirectory(barretenberg/goblin) +add_subdirectory(barretenberg/grumpkin_srs_gen) add_subdirectory(barretenberg/honk) add_subdirectory(barretenberg/join_split_example) add_subdirectory(barretenberg/numeric) diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.hpp index e0cfc6e6477..926923d767e 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.hpp @@ -81,16 +81,15 @@ template class KZG { auto quotient_commitment = verifier_transcript->template receive_from_prover("KZG:W"); GroupElement P_0; - // Note: In the recursive setting, we only add the contribution if it is not the point at infinity (i.e. if the - // evaluation is not equal to zero). if constexpr (Curve::is_stdlib_type) { auto builder = verifier_transcript->builder; auto one = Fr(builder, 1); - std::vector commitments = { claim.commitment, quotient_commitment }; - std::vector scalars = { one, claim.opening_pair.challenge }; + std::vector commitments = { claim.commitment, + quotient_commitment, + GroupElement::one(builder) }; + std::vector scalars = { one, claim.opening_pair.challenge, -claim.opening_pair.evaluation }; P_0 = GroupElement::batch_mul(commitments, scalars); - // Note: This implementation assumes the evaluation is zero (as is the case for shplonk). - ASSERT(claim.opening_pair.evaluation.get_value() == 0); + } else { P_0 = claim.commitment; P_0 += quotient_commitment * claim.opening_pair.challenge; diff --git a/barretenberg/cpp/src/barretenberg/goblin/CMakeLists.txt b/barretenberg/cpp/src/barretenberg/goblin/CMakeLists.txt index a6c3c61383a..adaa9814aed 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/CMakeLists.txt +++ b/barretenberg/cpp/src/barretenberg/goblin/CMakeLists.txt @@ -1 +1 @@ -barretenberg_module(goblin ultra_honk eccvm translator_vm transcript) \ No newline at end of file +barretenberg_module(goblin stdlib_recursion ultra_honk eccvm translator_vm) \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/goblin/full_goblin_composer.test.cpp b/barretenberg/cpp/src/barretenberg/goblin/full_goblin_composer.test.cpp deleted file mode 100644 index 7503307881a..00000000000 --- a/barretenberg/cpp/src/barretenberg/goblin/full_goblin_composer.test.cpp +++ /dev/null @@ -1,67 +0,0 @@ -#include "barretenberg/eccvm/eccvm_composer.hpp" -#include "barretenberg/goblin/goblin.hpp" -#include "barretenberg/goblin/mock_circuits.hpp" -#include "barretenberg/goblin/translation_evaluations.hpp" -#include "barretenberg/proof_system/circuit_builder/eccvm/eccvm_circuit_builder.hpp" -#include "barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.hpp" -#include "barretenberg/proof_system/circuit_builder/ultra_circuit_builder.hpp" -#include "barretenberg/translator_vm/goblin_translator_composer.hpp" -#include "barretenberg/ultra_honk/ultra_composer.hpp" - -#include - -using namespace barretenberg; -using namespace proof_system::honk; - -namespace test_full_goblin_composer { - -class FullGoblinComposerTests : public ::testing::Test { - protected: - static void SetUpTestSuite() - { - barretenberg::srs::init_crs_factory("../srs_db/ignition"); - barretenberg::srs::init_grumpkin_crs_factory("../srs_db/grumpkin"); - } - - using Curve = curve::BN254; - using FF = Curve::ScalarField; - using Fbase = Curve::BaseField; - using Point = Curve::AffineElement; - using CommitmentKey = pcs::CommitmentKey; - using OpQueue = proof_system::ECCOpQueue; - using GoblinUltraBuilder = proof_system::GoblinUltraCircuitBuilder; - using ECCVMFlavor = flavor::ECCVM; - using ECCVMBuilder = proof_system::ECCVMCircuitBuilder; - using ECCVMComposer = ECCVMComposer_; - using KernelInput = Goblin::AccumulationOutput; -}; - -/** - * @brief Test proof construction/verification for a circuit with ECC op gates, public inputs, and basic arithmetic - * gates - * @note We simulate op queue interactions with a previous circuit so the actual circuit under test utilizes an op queue - * with non-empty 'previous' data. This avoids complications with zero-commitments etc. - * - */ -TEST_F(FullGoblinComposerTests, SimpleCircuit) -{ - barretenberg::Goblin goblin; - GoblinUltraBuilder initial_circuit{ goblin.op_queue }; - GoblinTestingUtils::construct_simple_initial_circuit(initial_circuit); - KernelInput kernel_input = goblin.accumulate(initial_circuit); - - // Construct a series of simple Goblin circuits; generate and verify their proofs - size_t NUM_CIRCUITS = 2; - for (size_t circuit_idx = 0; circuit_idx < NUM_CIRCUITS; ++circuit_idx) { - GoblinUltraBuilder circuit_builder{ goblin.op_queue }; - GoblinTestingUtils::construct_arithmetic_circuit(circuit_builder); - kernel_input = goblin.accumulate(circuit_builder); - } - - Goblin::Proof proof = goblin.prove(); - bool verified = goblin.verify(proof); - EXPECT_TRUE(verified); -} - -// TODO(https://github.com/AztecProtocol/barretenberg/issues/787) Expand these tests. -} // namespace test_full_goblin_composer diff --git a/barretenberg/cpp/src/barretenberg/stdlib/recursion/goblin/full_goblin_recursion.test.cpp b/barretenberg/cpp/src/barretenberg/goblin/full_goblin_recursion.test.cpp similarity index 84% rename from barretenberg/cpp/src/barretenberg/stdlib/recursion/goblin/full_goblin_recursion.test.cpp rename to barretenberg/cpp/src/barretenberg/goblin/full_goblin_recursion.test.cpp index 51d9f1943cb..2adc5049600 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/recursion/goblin/full_goblin_recursion.test.cpp +++ b/barretenberg/cpp/src/barretenberg/goblin/full_goblin_recursion.test.cpp @@ -24,10 +24,6 @@ class GoblinRecursionTests : public ::testing::Test { using Curve = curve::BN254; using FF = Curve::ScalarField; - using Fbase = Curve::BaseField; - using Point = Curve::AffineElement; - using CommitmentKey = pcs::CommitmentKey; - using OpQueue = proof_system::ECCOpQueue; using GoblinUltraBuilder = proof_system::GoblinUltraCircuitBuilder; using ECCVMFlavor = flavor::ECCVM; using ECCVMBuilder = proof_system::ECCVMCircuitBuilder; @@ -36,11 +32,11 @@ class GoblinRecursionTests : public ::testing::Test { using TranslatorBuilder = proof_system::GoblinTranslatorCircuitBuilder; using TranslatorComposer = GoblinTranslatorComposer; using TranslatorConsistencyData = barretenberg::TranslationEvaluations; - using Proof = proof_system::plonk::proof; - using NativeVerificationKey = flavor::GoblinUltra::VerificationKey; using RecursiveFlavor = flavor::GoblinUltraRecursive_; using RecursiveVerifier = proof_system::plonk::stdlib::recursion::honk::UltraRecursiveVerifier_; + using Goblin = barretenberg::Goblin; using KernelInput = Goblin::AccumulationOutput; + using UltraVerifier = UltraVerifier_; /** * @brief Construct a mock kernel circuit @@ -58,8 +54,11 @@ class GoblinRecursionTests : public ::testing::Test { // Execute recursive aggregation of previous kernel proof RecursiveVerifier verifier{ &builder, kernel_input.verification_key }; // TODO(https://github.com/AztecProtocol/barretenberg/issues/801): Aggregation - auto pairing_points = verifier.verify_proof(kernel_input.proof); // app function proof - pairing_points = verifier.verify_proof(kernel_input.proof); // previous kernel proof + auto pairing_points = verifier.verify_proof(kernel_input.proof); // previous kernel proof + // TODO(https://github.com/AztecProtocol/barretenberg/issues/803): Mock app circuit. In the absence of a mocked + // app circuit proof, we simply perform another recursive verification for the previous kernel proof to + // approximate the work done for the app proof. + pairing_points = verifier.verify_proof(kernel_input.proof); } }; @@ -69,11 +68,12 @@ class GoblinRecursionTests : public ::testing::Test { */ TEST_F(GoblinRecursionTests, Pseudo) { - barretenberg::Goblin goblin; + Goblin goblin; // Construct an initial circuit; its proof will be recursively verified by the first kernel GoblinUltraBuilder initial_circuit{ goblin.op_queue }; GoblinTestingUtils::construct_simple_initial_circuit(initial_circuit); + KernelInput kernel_input = goblin.accumulate(initial_circuit); // Construct a series of simple Goblin circuits; generate and verify their proofs @@ -88,8 +88,12 @@ TEST_F(GoblinRecursionTests, Pseudo) } Goblin::Proof proof = goblin.prove(); + // Verify the final ultra proof + UltraVerifier ultra_verifier{ kernel_input.verification_key }; + bool ultra_verified = ultra_verifier.verify_proof(kernel_input.proof); + // Verify the goblin proof (eccvm, translator, merge) bool verified = goblin.verify(proof); - EXPECT_TRUE(verified); + EXPECT_TRUE(ultra_verified && verified); } // TODO(https://github.com/AztecProtocol/barretenberg/issues/787) Expand these tests. diff --git a/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp b/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp index 315b66657f3..3c2588288df 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp +++ b/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp @@ -4,6 +4,7 @@ #include "barretenberg/proof_system/circuit_builder/eccvm/eccvm_circuit_builder.hpp" #include "barretenberg/proof_system/circuit_builder/goblin_translator_circuit_builder.hpp" #include "barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.hpp" +#include "barretenberg/stdlib/recursion/honk/verifier/merge_recursive_verifier.hpp" #include "barretenberg/translator_vm/goblin_translator_composer.hpp" #include "barretenberg/ultra_honk/ultra_composer.hpp" @@ -24,6 +25,7 @@ class Goblin { }; struct Proof { + HonkProof merge_proof; HonkProof eccvm_proof; HonkProof translator_proof; TranslationEvaluations translation_evaluations; @@ -41,9 +43,17 @@ class Goblin { using ECCVMComposer = proof_system::honk::ECCVMComposer; using TranslatorBuilder = proof_system::GoblinTranslatorCircuitBuilder; using TranslatorComposer = proof_system::honk::GoblinTranslatorComposer; + using RecursiveMergeVerifier = + proof_system::plonk::stdlib::recursion::goblin::MergeRecursiveVerifier_; + using MergeVerifier = proof_system::honk::MergeVerifier_; std::shared_ptr op_queue = std::make_shared(); + HonkProof merge_proof; + + // on the first call to accumulate there is no merge proof to verify + bool merge_proof_exists{ false }; + private: // TODO(https://github.com/AztecProtocol/barretenberg/issues/798) unique_ptr use is a hack std::unique_ptr eccvm_builder; @@ -59,16 +69,25 @@ class Goblin { */ AccumulationOutput accumulate(GoblinUltraCircuitBuilder& circuit_builder) { - // TODO(https://github.com/AztecProtocol/barretenberg/issues/797) Complete the "kernel" logic by recursively - // verifying previous merge proof + // Complete the circuit logic by recursively verifying previous merge proof if it exists + if (merge_proof_exists) { + RecursiveMergeVerifier merge_verifier{ &circuit_builder }; + [[maybe_unused]] auto pairing_points = merge_verifier.verify_proof(merge_proof); + } + // Construct a Honk proof for the main circuit GoblinUltraComposer composer; auto instance = composer.create_instance(circuit_builder); auto prover = composer.create_prover(instance); auto ultra_proof = prover.construct_proof(); + // Construct and store the merge proof to be recursively verified on the next call to accumulate auto merge_prover = composer.create_merge_prover(op_queue); - [[maybe_unused]] auto merge_proof = merge_prover.construct_proof(); + merge_proof = merge_prover.construct_proof(); + + if (!merge_proof_exists) { + merge_proof_exists = true; + } return { ultra_proof, instance->verification_key }; }; @@ -76,6 +95,9 @@ class Goblin { Proof prove() { Proof proof; + + proof.merge_proof = std::move(merge_proof); + eccvm_builder = std::make_unique(op_queue); eccvm_composer = std::make_unique(); auto eccvm_prover = eccvm_composer->create_prover(*eccvm_builder); @@ -87,11 +109,15 @@ class Goblin { translator_composer = std::make_unique(); auto translator_prover = translator_composer->create_prover(*translator_builder, eccvm_prover.transcript); proof.translator_proof = translator_prover.construct_proof(); + return proof; }; bool verify(const Proof& proof) { + MergeVerifier merge_verifier; + bool merge_verified = merge_verifier.verify_proof(proof.merge_proof); + auto eccvm_verifier = eccvm_composer->create_verifier(*eccvm_builder); bool eccvm_verified = eccvm_verifier.verify_proof(proof.eccvm_proof); @@ -100,7 +126,8 @@ class Goblin { // TODO(https://github.com/AztecProtocol/barretenberg/issues/799): // Ensure translation_evaluations are passed correctly bool translation_verified = translator_verifier.verify_translation(proof.translation_evaluations); - return eccvm_verified && accumulator_construction_verified && translation_verified; + + return merge_verified && eccvm_verified && accumulator_construction_verified && translation_verified; }; }; } // namespace barretenberg \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp b/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp index cb12bb08c37..5199a65ab63 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp +++ b/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp @@ -1,12 +1,7 @@ #include "barretenberg/commitment_schemes/commitment_key.hpp" -#include "barretenberg/eccvm/eccvm_composer.hpp" -#include "barretenberg/goblin/goblin.hpp" -#include "barretenberg/goblin/translation_evaluations.hpp" -#include "barretenberg/proof_system/circuit_builder/eccvm/eccvm_circuit_builder.hpp" +#include "barretenberg/flavor/goblin_ultra.hpp" #include "barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.hpp" -#include "barretenberg/proof_system/circuit_builder/ultra_circuit_builder.hpp" -#include "barretenberg/translator_vm/goblin_translator_composer.hpp" -#include "barretenberg/ultra_honk/ultra_composer.hpp" +#include "barretenberg/srs/global_crs.hpp" namespace barretenberg { class GoblinTestingUtils { diff --git a/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/merge_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/merge_recursive_verifier.cpp new file mode 100644 index 00000000000..f04c32c9583 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/merge_recursive_verifier.cpp @@ -0,0 +1,87 @@ +#include "barretenberg/stdlib/recursion/honk/verifier/merge_recursive_verifier.hpp" + +namespace proof_system::plonk::stdlib::recursion::goblin { + +template +MergeRecursiveVerifier_::MergeRecursiveVerifier_(CircuitBuilder* builder) + : builder(builder) +{} + +/** + * @brief Construct recursive verifier for Goblin Merge protocol, up to but not including the pairing + * + * @tparam Flavor + * @param proof + * @return std::array Inputs to final pairing + */ +template +std::array::Element, 2> MergeRecursiveVerifier_::verify_proof( + const plonk::proof& proof) +{ + transcript = std::make_shared(builder, proof.proof_data); + + // Receive commitments [t_i^{shift}], [T_{i-1}], and [T_i] + std::array C_T_prev; + std::array C_t_shift; + std::array C_T_current; + for (size_t idx = 0; idx < NUM_WIRES; ++idx) { + C_T_prev[idx] = transcript->template receive_from_prover("T_PREV_" + std::to_string(idx + 1)); + C_t_shift[idx] = transcript->template receive_from_prover("t_SHIFT_" + std::to_string(idx + 1)); + C_T_current[idx] = transcript->template receive_from_prover("T_CURRENT_" + std::to_string(idx + 1)); + } + + FF kappa = transcript->get_challenge("kappa"); + + // Receive transcript poly evaluations and add corresponding univariate opening claims {(\kappa, p(\kappa), [p(X)]} + std::array T_prev_evals; + std::array t_shift_evals; + std::array T_current_evals; + std::vector opening_claims; + for (size_t idx = 0; idx < NUM_WIRES; ++idx) { + T_prev_evals[idx] = transcript->template receive_from_prover("T_prev_eval_" + std::to_string(idx + 1)); + opening_claims.emplace_back(OpeningClaim{ { kappa, T_prev_evals[idx] }, C_T_prev[idx] }); + } + for (size_t idx = 0; idx < NUM_WIRES; ++idx) { + t_shift_evals[idx] = transcript->template receive_from_prover("t_shift_eval_" + std::to_string(idx + 1)); + opening_claims.emplace_back(OpeningClaim{ { kappa, t_shift_evals[idx] }, C_t_shift[idx] }); + } + for (size_t idx = 0; idx < NUM_WIRES; ++idx) { + T_current_evals[idx] = + transcript->template receive_from_prover("T_current_eval_" + std::to_string(idx + 1)); + opening_claims.emplace_back(OpeningClaim{ { kappa, T_current_evals[idx] }, C_T_current[idx] }); + } + + // Check the identity T_i(\kappa) = T_{i-1}(\kappa) + t_i^{shift}(\kappa) + for (size_t idx = 0; idx < NUM_WIRES; ++idx) { + T_current_evals[idx].assert_equal(T_prev_evals[idx] + t_shift_evals[idx]); + } + + FF alpha = transcript->get_challenge("alpha"); + + // Constuct batched commitment and batched evaluation from constituents using batching challenge \alpha + std::vector scalars; + std::vector commitments; + scalars.emplace_back(FF(builder, 1)); + commitments.emplace_back(opening_claims[0].commitment); + auto batched_eval = opening_claims[0].opening_pair.evaluation; + auto alpha_pow = alpha; + for (size_t idx = 1; idx < opening_claims.size(); ++idx) { + auto& claim = opening_claims[idx]; + scalars.emplace_back(alpha_pow); + commitments.emplace_back(claim.commitment); + batched_eval += alpha_pow * claim.opening_pair.evaluation; + alpha_pow *= alpha; + } + + auto batched_commitment = Commitment::batch_mul(commitments, scalars); + + OpeningClaim batched_claim = { { kappa, batched_eval }, batched_commitment }; + + auto pairing_points = KZG::compute_pairing_points(batched_claim, transcript); + + return pairing_points; +} + +template class MergeRecursiveVerifier_; + +} // namespace proof_system::plonk::stdlib::recursion::goblin diff --git a/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/merge_recursive_verifier.hpp b/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/merge_recursive_verifier.hpp new file mode 100644 index 00000000000..341d91a1bd1 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/merge_recursive_verifier.hpp @@ -0,0 +1,31 @@ +#pragma once +#include "barretenberg/commitment_schemes/kzg/kzg.hpp" +#include "barretenberg/plonk/proof_system/types/proof.hpp" +#include "barretenberg/stdlib/primitives/curves/bn254.hpp" +#include "barretenberg/stdlib/recursion/honk/transcript/transcript.hpp" + +namespace proof_system::plonk::stdlib::recursion::goblin { +template class MergeRecursiveVerifier_ { + public: + using Curve = bn254; + using FF = typename Curve::ScalarField; + using Commitment = typename Curve::Element; + using GroupElement = typename Curve::Element; + using KZG = ::proof_system::honk::pcs::kzg::KZG; + using OpeningClaim = ::proof_system::honk::pcs::OpeningClaim; + using PairingPoints = std::array; + using Transcript = honk::Transcript; + + CircuitBuilder* builder; + std::shared_ptr transcript; + + static constexpr size_t NUM_WIRES = arithmetization::UltraHonk::NUM_WIRES; + + explicit MergeRecursiveVerifier_(CircuitBuilder* builder); + + PairingPoints verify_proof(const plonk::proof& proof); +}; + +extern template class MergeRecursiveVerifier_; + +} // namespace proof_system::plonk::stdlib::recursion::goblin diff --git a/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/merge_verifier.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/merge_verifier.test.cpp new file mode 100644 index 00000000000..39b981c4b6a --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/merge_verifier.test.cpp @@ -0,0 +1,100 @@ +#include "barretenberg/common/test.hpp" +#include "barretenberg/goblin/mock_circuits.hpp" +#include "barretenberg/stdlib/primitives/curves/bn254.hpp" +#include "barretenberg/stdlib/recursion/honk/verifier/merge_recursive_verifier.hpp" +#include "barretenberg/ultra_honk/ultra_composer.hpp" + +namespace proof_system::plonk::stdlib::recursion::goblin { + +/** + * @brief Test suite for recursive verification of Goblin Merge proofs + * @details The recursive verification circuit is arithmetized using Goblin-style Ultra arithmetization + * (GoblinUltraCircuitBuilder). + * + * @tparam Builder + */ +class RecursiveMergeVerifierTest : public testing::Test { + + // Types for recursive verifier circuit + using RecursiveBuilder = GoblinUltraCircuitBuilder; + using RecursiveMergeVerifier = MergeRecursiveVerifier_; + + // Define types relevant for inner circuit + using GoblinUltraFlavor = ::proof_system::honk::flavor::GoblinUltra; + using GoblinUltraComposer = ::proof_system::honk::UltraComposer_; + using InnerFlavor = GoblinUltraFlavor; + using InnerComposer = GoblinUltraComposer; + using InnerBuilder = typename InnerComposer::CircuitBuilder; + + // Define additional types for testing purposes + using Commitment = InnerFlavor::Commitment; + using FF = InnerFlavor::FF; + using VerifierCommitmentKey = ::proof_system::honk::pcs::VerifierCommitmentKey; + + public: + static void SetUpTestSuite() { barretenberg::srs::init_crs_factory("../srs_db/ignition"); } + + /** + * @brief Test recursive merge verification for the ops generated by a sample circuit + * @details We construct and verify an Ultra Honk proof of the recursive merge verifier circuit to check its + * correctness rather than calling check_circuit since this functionality is incomplete for the Goblin + * arithmetization + */ + static void test_recursive_merge_verification() + { + auto op_queue = std::make_shared(); + + InnerBuilder sample_circuit{ op_queue }; + GoblinTestingUtils::construct_simple_initial_circuit(sample_circuit); + + // Generate a proof over the inner circuit + InnerComposer inner_composer; + auto merge_prover = inner_composer.create_merge_prover(op_queue); + auto merge_proof = merge_prover.construct_proof(); + + // Create a recursive merge verification circuit for the merge proof + RecursiveBuilder outer_circuit; + RecursiveMergeVerifier verifier{ &outer_circuit }; + auto pairing_points = verifier.verify_proof(merge_proof); + + // Check for a failure flag in the recursive verifier circuit + EXPECT_EQ(outer_circuit.failed(), false) << outer_circuit.err(); + + // Check 1: Perform native merge verification then perform the pairing on the outputs of the recursive merge + // verifier and check that the result agrees. + auto native_verifier = inner_composer.create_merge_verifier(); + bool verified_native = native_verifier.verify_proof(merge_proof); + VerifierCommitmentKey pcs_verification_key(0, srs::get_crs_factory()); + auto verified_recursive = + pcs_verification_key.pairing_check(pairing_points[0].get_value(), pairing_points[1].get_value()); + EXPECT_EQ(verified_native, verified_recursive); + EXPECT_TRUE(verified_recursive); + + // Check 2: Ensure that the underlying native and recursive merge verification algorithms agree by ensuring + // the manifests produced by each agree. + auto recursive_manifest = verifier.transcript->get_manifest(); + auto native_manifest = native_verifier.transcript->get_manifest(); + for (size_t i = 0; i < recursive_manifest.size(); ++i) { + EXPECT_EQ(recursive_manifest[i], native_manifest[i]); + } + + // Check 3: Construct and verify a (goblin) ultra honk proof of the Merge recursive verifier circuit + { + GoblinUltraComposer composer; + auto instance = composer.create_instance(outer_circuit); + auto prover = composer.create_prover(instance); + auto verifier = composer.create_verifier(instance); + auto proof = prover.construct_proof(); + bool verified = verifier.verify_proof(proof); + + EXPECT_TRUE(verified); + } + } +}; + +TEST_F(RecursiveMergeVerifierTest, SingleRecursiveVerification) +{ + RecursiveMergeVerifierTest::test_recursive_merge_verification(); +}; + +} // namespace proof_system::plonk::stdlib::recursion::goblin \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/goblin_ultra_composer.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/goblin_ultra_composer.test.cpp index a09a822085b..52bc8aa9a03 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/goblin_ultra_composer.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/goblin_ultra_composer.test.cpp @@ -77,7 +77,7 @@ class GoblinUltraHonkComposerTests : public ::testing::Test { bool construct_and_verify_merge_proof(auto& composer, auto& op_queue) { auto merge_prover = composer.create_merge_prover(op_queue); - auto merge_verifier = composer.create_merge_verifier(10); + auto merge_verifier = composer.create_merge_verifier(); auto merge_proof = merge_prover.construct_proof(); bool verified = merge_verifier.verify_proof(merge_proof); diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier.cpp index c93257af7de..ebf18518afa 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier.cpp @@ -3,10 +3,9 @@ namespace proof_system::honk { template -MergeVerifier_::MergeVerifier_(std::unique_ptr verification_key, - const std::shared_ptr& transcript) - : transcript(transcript) - , pcs_verification_key(std::move(verification_key)){}; +MergeVerifier_::MergeVerifier_() + : transcript(std::make_shared()) + , pcs_verification_key(std::make_unique(0, barretenberg::srs::get_crs_factory())){}; /** * @brief Verify proper construction of the aggregate Goblin ECC op queue polynomials T_i^(j), j = 1,2,3,4. diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier.hpp b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier.hpp index d6880476b79..da094df6b7e 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier.hpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier.hpp @@ -5,6 +5,7 @@ #include "barretenberg/flavor/ultra.hpp" #include "barretenberg/plonk/proof_system/types/proof.hpp" #include "barretenberg/proof_system/op_queue/ecc_op_queue.hpp" +#include "barretenberg/srs/global_crs.hpp" #include "barretenberg/transcript/transcript.hpp" namespace proof_system::honk { @@ -31,8 +32,7 @@ template class MergeVerifier_ { std::shared_ptr op_queue; std::shared_ptr pcs_verification_key; - explicit MergeVerifier_(std::unique_ptr verification_key, - const std::shared_ptr& transcript); + explicit MergeVerifier_(); bool verify_proof(const plonk::proof& proof); }; diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_composer.hpp b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_composer.hpp index cdfb202db39..0d4dd752d08 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_composer.hpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_composer.hpp @@ -68,6 +68,8 @@ template class UltraComposer_ { * * @param op_queue * @return MergeProver_ + * TODO(https://github.com/AztecProtocol/barretenberg/issues/804): Goblin should be responsible for constructing + * merge prover/verifier. */ MergeProver_ create_merge_prover( const std::shared_ptr& op_queue, @@ -84,15 +86,9 @@ template class UltraComposer_ { /** * @brief Create Verifier for Goblin ECC op queue merge protocol * - * @param size Size of commitment key required to commit to shifted op queue contribution t_i * @return MergeVerifier_ */ - MergeVerifier_ create_merge_verifier( - size_t srs_size, const std::shared_ptr& transcript = std::make_shared()) - { - auto pcs_verification_key = std::make_unique(srs_size, crs_factory_); - return MergeVerifier_(std::move(pcs_verification_key), transcript); - } + MergeVerifier_ create_merge_verifier() { return MergeVerifier_(); } ProtoGalaxyProver_ create_folding_prover(const std::vector>& instances) { diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_verifier.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_verifier.cpp index df70e5ac12c..2775b586c7e 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_verifier.cpp @@ -15,6 +15,19 @@ UltraVerifier_::UltraVerifier_(const std::shared_ptr& transc , transcript(transcript) {} +/** + * @brief Construct an UltraVerifier directly from a verification key + * + * @tparam Flavor + * @param verifier_key + */ +template +UltraVerifier_::UltraVerifier_(const std::shared_ptr& verifier_key) + : key(verifier_key) + , pcs_verification_key(std::make_unique(0, barretenberg::srs::get_crs_factory())) + , transcript(std::make_shared()) +{} + template UltraVerifier_::UltraVerifier_(UltraVerifier_&& other) : key(std::move(other.key)) diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_verifier.hpp b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_verifier.hpp index 6a023071f02..8197e46a941 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_verifier.hpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_verifier.hpp @@ -2,6 +2,7 @@ #include "barretenberg/flavor/goblin_ultra.hpp" #include "barretenberg/flavor/ultra.hpp" #include "barretenberg/plonk/proof_system/types/proof.hpp" +#include "barretenberg/srs/global_crs.hpp" #include "barretenberg/sumcheck/sumcheck.hpp" namespace proof_system::honk { @@ -15,6 +16,7 @@ template class UltraVerifier_ { public: explicit UltraVerifier_(const std::shared_ptr& transcript, const std::shared_ptr& verifier_key = nullptr); + explicit UltraVerifier_(const std::shared_ptr& verifier_key); UltraVerifier_(UltraVerifier_&& other); UltraVerifier_& operator=(const UltraVerifier_& other) = delete; From 2cede412d25ef27acc7347e31389ae5d780f1b0b Mon Sep 17 00:00:00 2001 From: David Banks <47112877+dbanks12@users.noreply.github.com> Date: Thu, 7 Dec 2023 14:12:48 -0500 Subject: [PATCH 09/35] docs(yellowpaper): update `cast` instruction description with truncation operation (#3621) Simple docs update --- yellow-paper/docs/public-vm/gen/_InstructionSet.mdx | 2 +- yellow-paper/src/preprocess/InstructionSet/InstructionSet.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/yellow-paper/docs/public-vm/gen/_InstructionSet.mdx b/yellow-paper/docs/public-vm/gen/_InstructionSet.mdx index 4f13ec9bd98..2c1cc93dd04 100644 --- a/yellow-paper/docs/public-vm/gen/_InstructionSet.mdx +++ b/yellow-paper/docs/public-vm/gen/_InstructionSet.mdx @@ -710,7 +710,7 @@ Type cast - **aOffset**: memory offset of word to cast - **dstOffset**: memory offset specifying where to store operation's result - **Expression**: `M[dstOffset] = cast(M[aOffset])` -- **Details**: Cast a word in memory based on the `dst-tag` specified in the bytecode. Truncates when casting to a smaller type, left-zero-pads when casting to a larger type. See [here](./state-model#cast-and-tag-conversions) for more details. +- **Details**: Cast a word in memory based on the `dst-tag` specified in the bytecode. Truncates (`M[dstOffset] = M[aOffset] mod 2^dstsize`) when casting to a smaller type, left-zero-pads when casting to a larger type. See [here](./state-model#cast-and-tag-conversions) for more details. - **Tag updates**: `T[dstOffset] = dst-tag` - **Bit-size**: 96 diff --git a/yellow-paper/src/preprocess/InstructionSet/InstructionSet.js b/yellow-paper/src/preprocess/InstructionSet/InstructionSet.js index 844a89c369b..19acb3759ed 100644 --- a/yellow-paper/src/preprocess/InstructionSet/InstructionSet.js +++ b/yellow-paper/src/preprocess/InstructionSet/InstructionSet.js @@ -279,7 +279,7 @@ const INSTRUCTION_SET_RAW = [ ], "Expression": "`M[dstOffset] = cast(M[aOffset])`", "Summary": "Type cast", - "Details": "Cast a word in memory based on the `dst-tag` specified in the bytecode. Truncates when casting to a smaller type, left-zero-pads when casting to a larger type. See [here](./state-model#cast-and-tag-conversions) for more details.", + "Details": "Cast a word in memory based on the `dst-tag` specified in the bytecode. Truncates (`M[dstOffset] = M[aOffset] mod 2^dstsize`) when casting to a smaller type, left-zero-pads when casting to a larger type. See [here](./state-model#cast-and-tag-conversions) for more details.", "Tag checks": "", "Tag updates": "`T[dstOffset] = dst-tag`", }, From 1a6b44d67e077eb5904ab30255454693d6a1edac Mon Sep 17 00:00:00 2001 From: ludamad Date: Thu, 7 Dec 2023 16:38:41 -0500 Subject: [PATCH 10/35] fix: broken uint256_t implicit copy (#3625) Look at the diff, then consider this code ``` #include #include class Uint256_t { public: // Conversion operator (explicit) template explicit operator T() const { std::cout << "Uint256_t conversion operator called\n"; return static_cast(data[0]); } int data[4] = {0,0,0,0}; }; class Field { public: Field() {} // Constructor that takes a Uint256_t Field(int x) { std::cout << "This is silly!!!!" << std::endl; } Field(const Uint256_t& input) { (void)input; std::cout << "Field constructor called\n"; // Additional initialization code here } }; class Toot { public: Toot(Field f) { (void)f; } }; int main() { Uint256_t uint256_value; Field x = uint256_value; Toot t{uint256_value}; return 0; } ``` With std::integral concept on the cast: ``` Field constructor called Field constructor called ``` but without! which was caught in practice passing a uint256 to FieldSponge ``` Field constructor called Uint256_t conversion operator called This is silly!!!! ``` This truncated the field mysteriously! Open-ended implicit conversions are dangerous --------- Co-authored-by: ludamad --- barretenberg/cpp/src/barretenberg/numeric/uint128/uint128.hpp | 3 ++- barretenberg/cpp/src/barretenberg/numeric/uint256/uint256.hpp | 3 ++- .../stdlib/primitives/bigfield/bigfield.fuzzer.hpp | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/numeric/uint128/uint128.hpp b/barretenberg/cpp/src/barretenberg/numeric/uint128/uint128.hpp index 3dc320abe2d..e229f9b7d23 100644 --- a/barretenberg/cpp/src/barretenberg/numeric/uint128/uint128.hpp +++ b/barretenberg/cpp/src/barretenberg/numeric/uint128/uint128.hpp @@ -5,6 +5,7 @@ #ifdef __i386__ #include "barretenberg/common/serialize.hpp" +#include namespace numeric { @@ -37,7 +38,7 @@ class alignas(32) uint128_t { constexpr ~uint128_t() = default; explicit constexpr operator bool() const { return static_cast(data[0]); }; - template explicit constexpr operator T() const { return static_cast(data[0]); }; + template explicit constexpr operator T() const { return static_cast(data[0]); }; [[nodiscard]] constexpr bool get_bit(uint64_t bit_index) const; [[nodiscard]] constexpr uint64_t get_msb() const; diff --git a/barretenberg/cpp/src/barretenberg/numeric/uint256/uint256.hpp b/barretenberg/cpp/src/barretenberg/numeric/uint256/uint256.hpp index d8cd9ef2f18..5ddaa9713ae 100644 --- a/barretenberg/cpp/src/barretenberg/numeric/uint256/uint256.hpp +++ b/barretenberg/cpp/src/barretenberg/numeric/uint256/uint256.hpp @@ -14,6 +14,7 @@ #include "../uint128/uint128.hpp" #include "barretenberg/common/serialize.hpp" #include "barretenberg/common/throw_or_abort.hpp" +#include #include #include #include @@ -91,7 +92,7 @@ class alignas(32) uint256_t { explicit constexpr operator bool() const { return static_cast(data[0]); }; - template explicit constexpr operator T() const { return static_cast(data[0]); }; + template explicit constexpr operator T() const { return static_cast(data[0]); }; [[nodiscard]] constexpr bool get_bit(uint64_t bit_index) const; [[nodiscard]] constexpr uint64_t get_msb() const; diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/bigfield/bigfield.fuzzer.hpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/bigfield/bigfield.fuzzer.hpp index 18e2cbe129e..5111ea71a54 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/bigfield/bigfield.fuzzer.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/bigfield/bigfield.fuzzer.hpp @@ -266,7 +266,7 @@ template class BigFieldBase { mask = (uint256_t(1) << mask_size) - 1; // Choose the bit range // Return instruction - return { .id = instruction_opcode, .arguments.element = Element(temp & mask) }; + return { .id = instruction_opcode, .arguments.element = Element(static_cast(temp & mask)) }; break; case OPCODE::RANDOMSEED: From a2cee4ff1df294b1253f4a495a158794b47bfe66 Mon Sep 17 00:00:00 2001 From: josh crites Date: Thu, 7 Dec 2023 21:59:36 +0000 Subject: [PATCH 11/35] chore(docs): Update implementation references in token contract tutorial (#3626) This PR includes some edits to the token contract tutorial, to keep the text consistent with the referenced source code. # Checklist: Remove the checklist to signal you've completed it. Enable auto-merge if the PR is ready to merge. - [ ] If the pull request requires a cryptography review (e.g. cryptographic algorithm implementations) I have added the 'crypto' tag. - [x] I have reviewed my diff in github, line by line and removed unexpected formatting changes, testing logs, or commented-out code. - [x] Every change is related to the PR description. - [ ] I have [linked](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue) this pull request to relevant issues (if any exist). --- docs/docs/dev_docs/tutorials/writing_token_contract.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/docs/dev_docs/tutorials/writing_token_contract.md b/docs/docs/dev_docs/tutorials/writing_token_contract.md index 18e16c113d6..27cb44bd8f1 100644 --- a/docs/docs/dev_docs/tutorials/writing_token_contract.md +++ b/docs/docs/dev_docs/tutorials/writing_token_contract.md @@ -210,7 +210,7 @@ Just below the contract definition, add the following imports: #include_code imports /yarn-project/noir-contracts/src/contracts/token_contract/src/main.nr rust -We are importing the Option type, items from the `value_note` library to help manage private value storage, note utilities, context (for managing private and public execution contexts), `state_vars` for helping manage state, `types` for data manipulation and `oracle` for help passing data from the private to public execution context. We also import the `auth` [library](https://github.com/AztecProtocol/aztec-packages/blob/#include_aztec_version/yarn-project/aztec-nr/aztec/src/auth.nr) to handle token authorizations from [Account Contracts](../../concepts/foundation/accounts/main). Check out the Account Contract with AuthWitness [here](https://github.com/AztecProtocol/aztec-packages/blob/#include_aztec_version/yarn-project/noir-contracts/src/contracts/schnorr_single_key_account_contract/src/main.nr). +We are importing the Option type, note utilities, context (for managing private and public execution contexts), `state_vars` for helping manage state, `compute_selector` for helping with calling public functions from private functions, and `types` for data manipulation. We also import the `authwit` [library](https://github.com/AztecProtocol/aztec-packages/blob/#include_aztec_version/yarn-project/aztec-nr/aztec/src/auth.nr) to handle token authorizations from [Account Contracts](../../concepts/foundation/accounts/main). Check out the Account Contract with AuthWitness [here](https://github.com/AztecProtocol/aztec-packages/blob/#include_aztec_version/yarn-project/noir-contracts/src/contracts/schnorr_single_key_account_contract/src/main.nr). [SafeU120](https://github.com/AztecProtocol/aztec-packages/blob/#include_aztec_version/yarn-project/aztec-nr/safe-math/src/safe_u120.nr) is a library to do safe math operations on unsigned integers that protects against overflows and underflows. @@ -309,7 +309,7 @@ First, storage is initialized. Then it checks whether the calling contract (`con ##### Authorizing token spends -If the `msg_sender` is **NOT** the same as the account to debit from, the function checks that the account has authorized the `msg_sender` contract to debit tokens on its behalf. This check is done by computing the function selector that needs to be authorized (in this case, the `shield` function), computing the hash of the message that the account contract has approved. This is a hash of the contract that is approved to spend (`context.msg_sender`), the token contract that can be spent from (`context.this_address()`), the `selector`, the account to spend from (`from.address`), the `amount`, the `secret_hash` and a `nonce` to prevent multiple spends. This hash is passed to `assert_valid_public_message_for` to ensure that the Account Contract has approved tokens to be spent on it's behalf. +If the `msg_sender` is **NOT** the same as the account to debit from, the function checks that the account has authorized the `msg_sender` contract to debit tokens on its behalf. This check is done by computing the function selector that needs to be authorized (in this case, the `shield` function), computing the hash of the message that the account contract has approved. This is a hash of the contract that is approved to spend (`context.msg_sender`), the token contract that can be spent from (`context.this_address()`), the `selector`, the account to spend from (`from.address`), the `amount`, the `secret_hash` and a `nonce` to prevent multiple spends. This hash is passed to `assert_current_call_valid_authwit_public` to ensure that the Account Contract has approved tokens to be spent on it's behalf. If the `msg_sender` is the same as the account to debit tokens from, the authorization check is bypassed and the function proceeds to update the account's `public_balance` and adds a new `TransparentNote` to the `pending_shields`. @@ -360,7 +360,7 @@ The function returns `1` to indicate successful execution. This private function enables un-shielding of private `ValueNote`s stored in `balances` to any Aztec account's `public_balance`. -After initializing storage, the function checks that the `msg_sender` is authorized to spend tokens. See [the Authorizing token spends section](#authorizing-token-spends) above for more detail--the only difference being that `assert_valid_message_for` is modified to work specifically in the private context. After the authorization check, the sender's private balance is decreased using the `decrement` helper function for the `value_note` library. Then it stages a public function call on this contract ([`_increase_public_balance`](#_increase_public_balance)) to be executed in the [public execution phase](#execution-contexts) of transaction execution. `_increase_public_balance` is marked as an `internal` function, so can only be called by this token contract. +After initializing storage, the function checks that the `msg_sender` is authorized to spend tokens. See [the Authorizing token spends section](#authorizing-token-spends) above for more detail--the only difference being that `assert_current_call_valid_authwit` is modified to work specifically in the private context. After the authorization check, the sender's private balance is decreased using the `decrement` helper function for the `value_note` library. Then it stages a public function call on this contract ([`_increase_public_balance`](#_increase_public_balance)) to be executed in the [public execution phase](#execution-contexts) of transaction execution. `_increase_public_balance` is marked as an `internal` function, so can only be called by this token contract. The function returns `1` to indicate successful execution. @@ -370,7 +370,7 @@ The function returns `1` to indicate successful execution. This private function enables private token transfers between Aztec accounts. -After initializing storage, the function checks that the `msg_sender` is authorized to spend tokens. See [the Authorizing token spends section](#authorizing-token-spends) above for more detail--the only difference being that `assert_valid_message_for` is modified to work specifically in the private context. After authorization, the function gets the current balances for the sender and recipient and decrements and increments them, respectively, using the `value_note` helper functions. +After initializing storage, the function checks that the `msg_sender` is authorized to spend tokens. See [the Authorizing token spends section](#authorizing-token-spends) above for more detail--the only difference being that `assert_current_call_valid_authwit` is modified to work specifically in the private context. After authorization, the function gets the current balances for the sender and recipient and decrements and increments them, respectively, using the `value_note` helper functions. #include_code transfer /yarn-project/noir-contracts/src/contracts/token_contract/src/main.nr rust From bb86ce9a27e09b8a336af04b787b81d5f1d49ac8 Mon Sep 17 00:00:00 2001 From: maramihali Date: Fri, 8 Dec 2023 11:34:44 +0200 Subject: [PATCH 12/35] feat: complete folding prover and verifier for ultra instances (#3419) Closes https://github.com/AztecProtocol/barretenberg/issues/781 Closes https://github.com/AztecProtocol/barretenberg/issues/689 Closes https://github.com/AztecProtocol/barretenberg/issues/690 Closes https://github.com/AztecProtocol/barretenberg/issues/802 This PR provides the first full version of folding prover and verifiers for Ultra instances and provides the first full folding test. The protogalaxy interfaces have been slightly reworked so the prover now returns a complete new relaxed `Instance` and a folding proof. While the verifier receives the folding proof and returns a boolean dependent on whether the pubic data from the relaxed instance, sent by the prover, is the same as the data computed by the folding verifier. --- .../src/barretenberg/flavor/goblin_ultra.hpp | 79 ++++- .../cpp/src/barretenberg/flavor/ultra.hpp | 94 ++++-- .../src/barretenberg/honk/utils/testing.hpp | 22 +- .../barretenberg/honk/utils/testing.test.cpp | 4 +- .../protogalaxy/combiner.test.cpp | 11 +- .../protogalaxy/combiner_example_gen.py | 1 - .../protogalaxy/folding_result.hpp | 35 +- .../protogalaxy/protogalaxy_prover.cpp | 319 +++++++++++++++--- .../protogalaxy/protogalaxy_prover.hpp | 104 ++++-- .../protogalaxy/protogalaxy_verifier.cpp | 254 +++++++++++--- .../protogalaxy/protogalaxy_verifier.hpp | 50 ++- .../sumcheck/instance/instances.hpp | 30 +- .../sumcheck/instance/prover_instance.cpp | 3 + .../sumcheck/instance/prover_instance.hpp | 12 +- .../sumcheck/instance/verifier_instance.hpp | 8 +- .../ultra_honk/protogalaxy.test.cpp | 93 ++++- .../ultra_honk/ultra_composer.hpp | 16 +- 17 files changed, 893 insertions(+), 242 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/flavor/goblin_ultra.hpp b/barretenberg/cpp/src/barretenberg/flavor/goblin_ultra.hpp index 80d1ca652e9..ce322761ccb 100644 --- a/barretenberg/cpp/src/barretenberg/flavor/goblin_ultra.hpp +++ b/barretenberg/cpp/src/barretenberg/flavor/goblin_ultra.hpp @@ -194,11 +194,6 @@ class GoblinUltra { { return { this->ecc_op_wire_1, this->ecc_op_wire_2, this->ecc_op_wire_3, this->ecc_op_wire_4 }; } - // The sorted concatenations of table and witness data needed for plookup. - RefVector get_sorted_polynomials() - { - return { this->sorted_1, this->sorted_2, this->sorted_3, this->sorted_4 }; - }; }; template class ShiftedEntities { @@ -290,11 +285,60 @@ class GoblinUltra { this->calldata_read_counts, this->lookup_inverses }; }; + + RefVector get_witness() + { + return { this->w_l, + this->w_r, + this->w_o, + this->w_4, + this->sorted_accum, + this->z_perm, + this->z_lookup, + this->ecc_op_wire_1, + this->ecc_op_wire_2, + this->ecc_op_wire_3, + this->ecc_op_wire_4, + this->calldata, + this->calldata_read_counts, + this->lookup_inverses }; + }; RefVector get_to_be_shifted() { return { this->table_1, this->table_2, this->table_3, this->table_4, this->w_l, this->w_r, this->w_o, this->w_4, this->sorted_accum, this->z_perm, this->z_lookup }; }; + RefVector get_precomputed() + { + return { this->q_m, + this->q_c, + this->q_l, + this->q_r, + this->q_o, + this->q_4, + this->q_arith, + this->q_sort, + this->q_elliptic, + this->q_aux, + this->q_lookup, + this->q_busread, + this->sigma_1, + this->sigma_2, + this->sigma_3, + this->sigma_4, + this->id_1, + this->id_2, + this->id_3, + this->id_4, + this->table_1, + this->table_2, + this->table_3, + this->table_4, + this->lagrange_first, + this->lagrange_last, + this->lagrange_ecc_op, + this->databus_id }; + } RefVector get_shifted() { return ShiftedEntities::get_all(); }; }; @@ -381,6 +425,29 @@ class GoblinUltra { } }; + /** + * @brief An owning container of polynomials. + * @warning When this was introduced it broke some of our design principles. + * - Execution trace builders don't handle "polynomials" because the interpretation of the execution trace + * columns as polynomials is a detail of the proving system, and trace builders are (sometimes in practice, + * always in principle) reusable for different proving protocols (e.g., Plonk and Honk). + * - Polynomial storage is handled by key classes. Polynomials aren't moved, but are accessed elsewhere by + * std::spans. + * + * We will consider revising this data model: TODO(https://github.com/AztecProtocol/barretenberg/issues/743) + */ + class AllPolynomials : public AllEntities { + public: + [[nodiscard]] AllValues get_row(const size_t row_idx) const + { + AllValues result; + for (auto [result_field, polynomial] : zip_view(result.get_all(), this->get_all())) { + result_field = polynomial[row_idx]; + } + return result; + } + }; + /** * @brief A container for the witness commitments. */ @@ -488,7 +555,7 @@ class GoblinUltra { using VerifierCommitments = VerifierCommitments_; class FoldingParameters { public: - std::vector gate_separation_challenges; + std::vector gate_challenges; FF target_sum; }; diff --git a/barretenberg/cpp/src/barretenberg/flavor/ultra.hpp b/barretenberg/cpp/src/barretenberg/flavor/ultra.hpp index 065a70aed2f..450571eaaba 100644 --- a/barretenberg/cpp/src/barretenberg/flavor/ultra.hpp +++ b/barretenberg/cpp/src/barretenberg/flavor/ultra.hpp @@ -207,6 +207,18 @@ class Ultra { }; }; + + RefVector get_precomputed() + { + return { q_m, q_c, q_l, q_r, q_o, q_4, q_arith, q_sort, + q_elliptic, q_aux, q_lookup, sigma_1, sigma_2, sigma_3, sigma_4, id_1, + id_2, id_3, id_4, table_1, table_2, table_3, table_4, lagrange_first, + lagrange_last + + }; + } + + RefVector get_witness() { return { w_l, w_r, w_o, w_4, sorted_accum, z_perm, z_lookup }; }; RefVector get_to_be_shifted() { return { table_1, table_2, table_3, table_4, w_l, w_r, w_o, w_4, sorted_accum, z_perm, z_lookup }; @@ -248,8 +260,8 @@ class Ultra { using VerificationKey = VerificationKey_>; /** - * @brief A field element for each entity of the flavor. These entities represent the prover polynomials evaluated - * at one point. + * @brief A field element for each entity of the flavor. These entities represent the prover polynomials + * evaluated at one point. */ class AllValues : public AllEntities { public: @@ -273,6 +285,29 @@ class Ultra { } }; + /** + * @brief An owning container of polynomials. + * @warning When this was introduced it broke some of our design principles. + * - Execution trace builders don't handle "polynomials" because the interpretation of the execution trace + * columns as polynomials is a detail of the proving system, and trace builders are (sometimes in practice, + * always in principle) reusable for different proving protocols (e.g., Plonk and Honk). + * - Polynomial storage is handled by key classes. Polynomials aren't moved, but are accessed elsewhere by + * std::spans. + * + * We will consider revising this data model: TODO(https://github.com/AztecProtocol/barretenberg/issues/743) + */ + class AllPolynomials : public AllEntities { + public: + [[nodiscard]] AllValues get_row(const size_t row_idx) const + { + AllValues result; + for (auto [result_field, polynomial] : zip_view(result.get_all(), this->get_all())) { + result_field = polynomial[row_idx]; + } + return result; + } + }; + /** * @brief A container for storing the partially evaluated multivariates produced by sumcheck. */ @@ -323,32 +358,31 @@ class Ultra { z_lookup = "Z_LOOKUP"; sorted_accum = "SORTED_ACCUM"; - // The ones beginning with "__" are only used for debugging - q_c = "__Q_C"; - q_l = "__Q_L"; - q_r = "__Q_R"; - q_o = "__Q_O"; - q_4 = "__Q_4"; - q_m = "__Q_M"; - q_arith = "__Q_ARITH"; - q_sort = "__Q_SORT"; - q_elliptic = "__Q_ELLIPTIC"; - q_aux = "__Q_AUX"; - q_lookup = "__Q_LOOKUP"; - sigma_1 = "__SIGMA_1"; - sigma_2 = "__SIGMA_2"; - sigma_3 = "__SIGMA_3"; - sigma_4 = "__SIGMA_4"; - id_1 = "__ID_1"; - id_2 = "__ID_2"; - id_3 = "__ID_3"; - id_4 = "__ID_4"; - table_1 = "__TABLE_1"; - table_2 = "__TABLE_2"; - table_3 = "__TABLE_3"; - table_4 = "__TABLE_4"; - lagrange_first = "__LAGRANGE_FIRST"; - lagrange_last = "__LAGRANGE_LAST"; + q_c = "Q_C"; + q_l = "Q_L"; + q_r = "Q_R"; + q_o = "Q_O"; + q_4 = "Q_4"; + q_m = "Q_M"; + q_arith = "Q_ARITH"; + q_sort = "Q_SORT"; + q_elliptic = "Q_ELLIPTIC"; + q_aux = "Q_AUX"; + q_lookup = "Q_LOOKUP"; + sigma_1 = "SIGMA_1"; + sigma_2 = "SIGMA_2"; + sigma_3 = "SIGMA_3"; + sigma_4 = "SIGMA_4"; + id_1 = "ID_1"; + id_2 = "ID_2"; + id_3 = "ID_3"; + id_4 = "ID_4"; + table_1 = "TABLE_1"; + table_2 = "TABLE_2"; + table_3 = "TABLE_3"; + table_4 = "TABLE_4"; + lagrange_first = "LAGRANGE_FIRST"; + lagrange_last = "LAGRANGE_LAST"; }; }; @@ -357,11 +391,11 @@ class Ultra { VerifierCommitments(const std::shared_ptr& verification_key) { q_m = verification_key->q_m; + q_c = verification_key->q_c; q_l = verification_key->q_l; q_r = verification_key->q_r; q_o = verification_key->q_o; q_4 = verification_key->q_4; - q_c = verification_key->q_c; q_arith = verification_key->q_arith; q_sort = verification_key->q_sort; q_elliptic = verification_key->q_elliptic; @@ -386,7 +420,7 @@ class Ultra { class FoldingParameters { public: - std::vector gate_separation_challenges; + std::vector gate_challenges; FF target_sum; }; diff --git a/barretenberg/cpp/src/barretenberg/honk/utils/testing.hpp b/barretenberg/cpp/src/barretenberg/honk/utils/testing.hpp index 37c056609ee..dda23952741 100644 --- a/barretenberg/cpp/src/barretenberg/honk/utils/testing.hpp +++ b/barretenberg/cpp/src/barretenberg/honk/utils/testing.hpp @@ -9,18 +9,17 @@ namespace proof_system::honk { * function returns an array of data pointed to by the ProverPolynomials. */ template -std::pair, Flavor::NUM_ALL_ENTITIES>, - typename Flavor::ProverPolynomials> -get_sequential_prover_polynomials(const size_t log_circuit_size, const size_t starting_value) +std::pair get_sequential_prover_polynomials( + const size_t log_circuit_size, const size_t starting_value) { using FF = typename Flavor::FF; using ProverPolynomials = typename Flavor::ProverPolynomials; using Polynomial = typename Flavor::Polynomial; - std::array, Flavor::NUM_ALL_ENTITIES> storage; + typename Flavor::AllPolynomials storage; size_t circuit_size = 1 << log_circuit_size; size_t value_idx = starting_value; - for (auto& polynomial : storage) { + for (auto& polynomial : storage.get_all()) { polynomial = Polynomial(circuit_size); for (auto& value : polynomial) { value = FF(value_idx++); @@ -28,7 +27,7 @@ get_sequential_prover_polynomials(const size_t log_circuit_size, const size_t st } ProverPolynomials prover_polynomials; - for (auto [prover_poly, storage_poly] : zip_view(prover_polynomials.get_all(), storage)) { + for (auto [prover_poly, storage_poly] : zip_view(prover_polynomials.get_all(), storage.get_all())) { prover_poly = storage_poly; } @@ -36,17 +35,16 @@ get_sequential_prover_polynomials(const size_t log_circuit_size, const size_t st } template -std::pair, Flavor::NUM_ALL_ENTITIES>, - typename Flavor::ProverPolynomials> -get_zero_prover_polynomials(const size_t log_circuit_size) +std::pair get_zero_prover_polynomials( + const size_t log_circuit_size) { using FF = typename Flavor::FF; using ProverPolynomials = typename Flavor::ProverPolynomials; using Polynomial = typename Flavor::Polynomial; - std::array, Flavor::NUM_ALL_ENTITIES> storage; + typename Flavor::AllPolynomials storage; size_t circuit_size = 1 << log_circuit_size; - for (auto& polynomial : storage) { + for (auto& polynomial : storage.get_all()) { polynomial = Polynomial(circuit_size); for (auto& value : polynomial) { value = FF(0); @@ -54,7 +52,7 @@ get_zero_prover_polynomials(const size_t log_circuit_size) } ProverPolynomials prover_polynomials; - for (auto [prover_poly, storage_poly] : zip_view(prover_polynomials.get_all(), storage)) { + for (auto [prover_poly, storage_poly] : zip_view(prover_polynomials.get_all(), storage.get_all())) { prover_poly = storage_poly; } diff --git a/barretenberg/cpp/src/barretenberg/honk/utils/testing.test.cpp b/barretenberg/cpp/src/barretenberg/honk/utils/testing.test.cpp index c4b5fda266c..3e150e4a2d5 100644 --- a/barretenberg/cpp/src/barretenberg/honk/utils/testing.test.cpp +++ b/barretenberg/cpp/src/barretenberg/honk/utils/testing.test.cpp @@ -10,8 +10,8 @@ TEST(HonkTestingUtils, ProverPolynomials) auto [storage, prover_polynomials] = proof_system::honk::get_sequential_prover_polynomials(/*log_circuit_size=*/2, /*starting_value=*/0); auto& first_polynomial = prover_polynomials.get_all()[0]; - EXPECT_EQ(storage[0][0], first_polynomial[0]); - EXPECT_EQ(storage[0][1], first_polynomial[1]); + EXPECT_EQ(storage.get_all()[0][0], first_polynomial[0]); + EXPECT_EQ(storage.get_all()[0][1], first_polynomial[1]); }; } // namespace barretenberg::test_testing_utils diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/combiner.test.cpp b/barretenberg/cpp/src/barretenberg/protogalaxy/combiner.test.cpp index dce50d0220c..68f22195659 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/combiner.test.cpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/combiner.test.cpp @@ -33,9 +33,11 @@ TEST(Protogalaxy, CombinerOn2Instances) }; auto run_test = [&](bool is_random_input) { + // Combiner test on prover polynomisls containing random values, restricted to only the standard arithmetic + // relation. if (is_random_input) { std::vector> instance_data(NUM_INSTANCES); - std::array, NUM_INSTANCES> storage_arrays; + std::array storage_arrays; ProtoGalaxyProver prover; std::vector pow_betas = { FF(1), FF(2) }; @@ -46,6 +48,7 @@ TEST(Protogalaxy, CombinerOn2Instances) restrict_to_standard_arithmetic_relation(prover_polynomials); storage_arrays[idx] = std::move(storage); instance->prover_polynomials = prover_polynomials; + instance->instance_size = 2; instance_data[idx] = instance; } @@ -70,7 +73,7 @@ TEST(Protogalaxy, CombinerOn2Instances) EXPECT_EQ(result, expected_result); } else { std::vector> instance_data(NUM_INSTANCES); - std::array, NUM_INSTANCES> storage_arrays; + std::array storage_arrays; ProtoGalaxyProver prover; std::vector pow_betas = { FF(1), FF(2) }; @@ -81,6 +84,7 @@ TEST(Protogalaxy, CombinerOn2Instances) restrict_to_standard_arithmetic_relation(prover_polynomials); storage_arrays[idx] = std::move(storage); instance->prover_polynomials = prover_polynomials; + instance->instance_size = 2; instance_data[idx] = instance; } @@ -162,7 +166,7 @@ TEST(Protogalaxy, CombinerOn4Instances) auto run_test = [&]() { std::vector> instance_data(NUM_INSTANCES); - std::array, NUM_INSTANCES> storage_arrays; + std::array storage_arrays; ProtoGalaxyProver prover; std::vector pow_betas = { FF(1), FF(2) }; @@ -172,6 +176,7 @@ TEST(Protogalaxy, CombinerOn4Instances) /*log_circuit_size=*/1); storage_arrays[idx] = std::move(storage); instance->prover_polynomials = prover_polynomials; + instance->instance_size = 2; instance_data[idx] = instance; } diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/combiner_example_gen.py b/barretenberg/cpp/src/barretenberg/protogalaxy/combiner_example_gen.py index 906d1948847..ac701d41e95 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/combiner_example_gen.py +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/combiner_example_gen.py @@ -103,7 +103,6 @@ def compute_first_example(): row.q_l, row.q_r, row.q_o, row.q_c) accumulator += zeta_pow * relation_value zeta_pow *= zeta - return accumulator diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/folding_result.hpp b/barretenberg/cpp/src/barretenberg/protogalaxy/folding_result.hpp index 61118b8b6e1..171f9b38a78 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/folding_result.hpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/folding_result.hpp @@ -1,39 +1,18 @@ #pragma once #include "barretenberg/flavor/flavor.hpp" #include "barretenberg/relations/relation_parameters.hpp" +#include "barretenberg/sumcheck/instance/prover_instance.hpp" namespace proof_system::honk { -template struct ProverFoldingResult { - public: - using ProverPolynomials = typename Flavor::ProverPolynomials; - using FoldingParameters = typename Flavor::FoldingParameters; - ProverPolynomials folded_prover_polynomials; - // TODO(https://github.com/AztecProtocol/barretenberg/issues/656): turn folding data into a struct - std::vector folding_data; - FoldingParameters params; -}; - -template struct VerifierFoldingResult { - using FF = typename Flavor::FF; - using VerificationKey = typename Flavor::VerificationKey; - using FoldingParameters = typename Flavor::FoldingParameters; - std::vector folded_public_inputs; - std::shared_ptr folded_verification_key; - FoldingParameters parameters; -}; - /** - * @brief The aggregated result from the prover and verifier after a round of folding, used to create a new Instance. + * @brief The result of running the Protogalaxy prover containing a new accumulator (relaxed instance) as well as the + * proof data to instantiate the verifier transcript. * * @tparam Flavor */ template struct FoldingResult { - using FF = typename Flavor::FF; - using ProverPolynomials = typename Flavor::ProverPolynomials; - using VerificationKey = typename Flavor::VerificationKey; - using FoldingParameters = typename Flavor::FoldingParameters; - ProverPolynomials folded_prover_polynomials; - std::vector folded_public_inputs; - std::shared_ptr verification_key; - FoldingParameters folding_parameters; + public: + std::shared_ptr> accumulator; + // TODO(https://github.com/AztecProtocol/barretenberg/issues/656): turn folding data into a struct + std::vector folding_data; }; } // namespace proof_system::honk \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.cpp b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.cpp index b8543daa64c..4a95f231d52 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.cpp @@ -1,91 +1,306 @@ #include "protogalaxy_prover.hpp" #include "barretenberg/flavor/flavor.hpp" namespace proof_system::honk { +template +void ProtoGalaxyProver_::finalise_and_send_instance(std::shared_ptr instance, + const std::string& domain_separator) +{ + instance->initialize_prover_polynomials(); -template void ProtoGalaxyProver_::prepare_for_folding() + const auto instance_size = static_cast(instance->instance_size); + const auto num_public_inputs = static_cast(instance->public_inputs.size()); + transcript->send_to_verifier(domain_separator + "_instance_size", instance_size); + transcript->send_to_verifier(domain_separator + "_public_input_size", num_public_inputs); + + for (size_t i = 0; i < instance->public_inputs.size(); ++i) { + auto public_input_i = instance->public_inputs[i]; + transcript->send_to_verifier(domain_separator + "_public_input_" + std::to_string(i), public_input_i); + } + transcript->send_to_verifier(domain_separator + "_pub_inputs_offset", + static_cast(instance->pub_inputs_offset)); + + auto& witness_commitments = instance->witness_commitments; + + // Commit to the first three wire polynomials of the instance + // We only commit to the fourth wire polynomial after adding memory recordss + witness_commitments.w_l = commitment_key->commit(instance->proving_key->w_l); + witness_commitments.w_r = commitment_key->commit(instance->proving_key->w_r); + witness_commitments.w_o = commitment_key->commit(instance->proving_key->w_o); + + auto wire_comms = witness_commitments.get_wires(); + auto commitment_labels = instance->commitment_labels; + auto wire_labels = commitment_labels.get_wires(); + for (size_t idx = 0; idx < 3; ++idx) { + transcript->send_to_verifier(domain_separator + "_" + wire_labels[idx], wire_comms[idx]); + } + + auto eta = transcript->get_challenge(domain_separator + "_eta"); + instance->compute_sorted_accumulator_polynomials(eta); + + // Commit to the sorted withness-table accumulator and the finalized (i.e. with memory records) fourth wire + // polynomial + witness_commitments.sorted_accum = commitment_key->commit(instance->prover_polynomials.sorted_accum); + witness_commitments.w_4 = commitment_key->commit(instance->prover_polynomials.w_4); + + transcript->send_to_verifier(domain_separator + "_" + commitment_labels.sorted_accum, + witness_commitments.sorted_accum); + transcript->send_to_verifier(domain_separator + "_" + commitment_labels.w_4, witness_commitments.w_4); + + auto [beta, gamma] = transcript->get_challenges(domain_separator + "_beta", domain_separator + "_gamma"); + instance->compute_grand_product_polynomials(beta, gamma); + + witness_commitments.z_perm = commitment_key->commit(instance->prover_polynomials.z_perm); + witness_commitments.z_lookup = commitment_key->commit(instance->prover_polynomials.z_lookup); + + transcript->send_to_verifier(domain_separator + "_" + commitment_labels.z_perm, + instance->witness_commitments.z_perm); + transcript->send_to_verifier(domain_separator + "_" + commitment_labels.z_lookup, + instance->witness_commitments.z_lookup); + + instance->alpha = transcript->get_challenge(domain_separator + "_alpha"); + + auto vk_view = instance->verification_key->get_all(); + auto labels = instance->commitment_labels.get_precomputed(); + for (size_t idx = 0; idx < labels.size(); idx++) { + transcript->send_to_verifier(domain_separator + "_" + labels[idx], vk_view[idx]); + } +} + +template +void ProtoGalaxyProver_::send_accumulator(std::shared_ptr instance, + const std::string& domain_separator) { - auto idx = 0; - for (auto it = instances.begin(); it != instances.end(); it++, idx++) { - auto instance = *it; - instance->initialize_prover_polynomials(); + const auto instance_size = static_cast(instance->instance_size); + const auto num_public_inputs = static_cast(instance->public_inputs.size()); + transcript->send_to_verifier(domain_separator + "_instance_size", instance_size); + transcript->send_to_verifier(domain_separator + "_public_input_size", num_public_inputs); - auto domain_separator = std::to_string(idx); - const auto circuit_size = static_cast(instance->proving_key->circuit_size); - const auto num_public_inputs = static_cast(instance->proving_key->num_public_inputs); + for (size_t i = 0; i < instance->public_inputs.size(); ++i) { + auto public_input_i = instance->public_inputs[i]; + transcript->send_to_verifier(domain_separator + "_public_input_" + std::to_string(i), public_input_i); + } - transcript->send_to_verifier(domain_separator + "_circuit_size", circuit_size); - transcript->send_to_verifier(domain_separator + "_public_input_size", num_public_inputs); - transcript->send_to_verifier(domain_separator + "_pub_inputs_offset", - static_cast(instance->pub_inputs_offset)); + transcript->send_to_verifier(domain_separator + "_eta", instance->relation_parameters.eta); + transcript->send_to_verifier(domain_separator + "_beta", instance->relation_parameters.beta); + transcript->send_to_verifier(domain_separator + "_gamma", instance->relation_parameters.gamma); + transcript->send_to_verifier(domain_separator + "_public_input_delta", + instance->relation_parameters.public_input_delta); + transcript->send_to_verifier(domain_separator + "_lookup_grand_product_delta", + instance->relation_parameters.lookup_grand_product_delta); - for (size_t i = 0; i < instance->proving_key->num_public_inputs; ++i) { - auto public_input_i = instance->public_inputs[i]; - transcript->send_to_verifier(domain_separator + "_public_input_" + std::to_string(i), public_input_i); - } + transcript->send_to_verifier(domain_separator + "_alpha", instance->alpha); - auto [eta, beta, gamma] = challenges_to_field_elements(transcript->get_challenges( - domain_separator + "_eta", domain_separator + "_beta", domain_separator + "_gamma")); + auto folding_parameters = instance->folding_parameters; + transcript->send_to_verifier(domain_separator + "_target_sum", folding_parameters.target_sum); + for (size_t idx = 0; idx < folding_parameters.gate_challenges.size(); idx++) { + transcript->send_to_verifier(domain_separator + "_gate_challenge_" + std::to_string(idx), + folding_parameters.gate_challenges[idx]); + } - instance->compute_sorted_accumulator_polynomials(eta); - instance->compute_grand_product_polynomials(beta, gamma); - instance->alpha = transcript->get_challenge(domain_separator + "_alpha"); + auto comm_view = instance->witness_commitments.get_all(); + auto witness_labels = instance->commitment_labels.get_witness(); + for (size_t idx = 0; idx < witness_labels.size(); idx++) { + transcript->send_to_verifier(domain_separator + "_" + witness_labels[idx], comm_view[idx]); } - fold_relation_parameters(instances); - fold_alpha(instances); + auto vk_view = instance->verification_key->get_all(); + auto vk_labels = instance->commitment_labels.get_precomputed(); + for (size_t idx = 0; idx < vk_labels.size(); idx++) { + transcript->send_to_verifier(domain_separator + "_" + vk_labels[idx], vk_view[idx]); + } +} + +template void ProtoGalaxyProver_::prepare_for_folding() +{ + auto idx = 0; + auto instance = instances[0]; + auto domain_separator = std::to_string(idx); + transcript->send_to_verifier(domain_separator + "is_accumulator", instance->is_accumulator); + if (instance->is_accumulator) { + send_accumulator(instance, domain_separator); + } else { + finalise_and_send_instance(instance, domain_separator); + } + idx++; + + for (auto it = instances.begin() + 1; it != instances.end(); it++, idx++) { + auto instance = *it; + auto domain_separator = std::to_string(idx); + finalise_and_send_instance(instance, domain_separator); + } } // TODO(#https://github.com/AztecProtocol/barretenberg/issues/689): finalise implementation this function template -ProverFoldingResult ProtoGalaxyProver_::fold_instances() +FoldingResult ProtoGalaxyProver_::fold_instances() { prepare_for_folding(); + // TODO(#https://github.com/AztecProtocol/barretenberg/issues/740): Handle the case where we are folding for the // first time and accumulator is 0 - // TODO(#https://github.com/AztecProtocol/barretenberg/issues/763): Fold alpha FF delta = transcript->get_challenge("delta"); auto accumulator = get_accumulator(); - auto instance_size = accumulator->prover_polynomials.get_polynomial_size(); - const auto log_instance_size = static_cast(numeric::get_msb(instance_size)); - auto deltas = compute_round_challenge_pows(log_instance_size, delta); + auto deltas = compute_round_challenge_pows(accumulator->log_instance_size, delta); auto perturbator = compute_perturbator(accumulator, deltas); - for (size_t idx = 0; idx <= log_instance_size; idx++) { + for (size_t idx = 0; idx <= accumulator->log_instance_size; idx++) { transcript->send_to_verifier("perturbator_" + std::to_string(idx), perturbator[idx]); } + assert(perturbator[0] == accumulator->folding_parameters.target_sum); + auto perturbator_challenge = transcript->get_challenge("perturbator_challenge"); + instances.next_gate_challenges = + update_gate_challenges(perturbator_challenge, accumulator->folding_parameters.gate_challenges, deltas); + const auto pow_betas_star = + compute_pow_polynomial_at_values(instances.next_gate_challenges, accumulator->instance_size); + + combine_relation_parameters(instances); + combine_alpha(instances); + auto combiner = compute_combiner(instances, pow_betas_star); - FF perturbator_challenge = transcript->get_challenge("perturbator_challenge"); auto compressed_perturbator = perturbator.evaluate(perturbator_challenge); - std::vector betas_star(log_instance_size); - betas_star[0] = 1; - auto betas = accumulator->folding_parameters.gate_separation_challenges; - for (size_t idx = 1; idx < log_instance_size; idx++) { - betas_star[idx] = betas[idx] + perturbator_challenge * deltas[idx - 1]; + auto combiner_quotient = compute_combiner_quotient(compressed_perturbator, combiner); + + for (size_t idx = ProverInstances::NUM; idx < ProverInstances::BATCHED_EXTENDED_LENGTH; idx++) { + transcript->send_to_verifier("combiner_quotient_" + std::to_string(idx), combiner_quotient.value_at(idx)); } + auto combiner_challenge = transcript->get_challenge("combiner_quotient_challenge"); - auto pow_betas_star = compute_pow_polynomial_at_values(betas_star, instance_size); + FoldingResult res; + res.accumulator = + compute_next_accumulator(instances, combiner_quotient, combiner_challenge, compressed_perturbator); + res.folding_data = transcript->proof_data; - auto combiner = compute_combiner(instances, pow_betas_star); - auto combiner_quotient = compute_combiner_quotient(compressed_perturbator, combiner); - for (size_t idx = ProverInstances::NUM; idx < combiner.size(); idx++) { - transcript->send_to_verifier("combiner_quotient_" + std::to_string(idx), combiner_quotient.value_at(idx)); + return res; +} +template +std::shared_ptr ProtoGalaxyProver_::compute_next_accumulator( + ProverInstances& instances, + Univariate& combiner_quotient, + const FF& challenge, + const FF& compressed_perturbator) +{ + auto combiner_quotient_at_challenge = combiner_quotient.evaluate(challenge); + + // Given the challenge \gamma, compute Z(\gamma) and {L_0(\gamma),L_1(\gamma)} + // TODO(https://github.com/AztecProtocol/barretenberg/issues/764): Generalize the vanishing polynomial formula + // and the computation of Lagrange basis for k instances + auto vanishing_polynomial_at_challenge = challenge * (challenge - FF(1)); + std::vector lagranges{ FF(1) - challenge, challenge }; + + auto next_accumulator = std::make_shared(); + + // Compute the next target sum and send the next folding parameters to the verifier + auto next_target_sum = + compressed_perturbator * lagranges[0] + vanishing_polynomial_at_challenge * combiner_quotient_at_challenge; + next_accumulator->folding_parameters = { instances.next_gate_challenges, next_target_sum }; + transcript->send_to_verifier("next_target_sum", next_target_sum); + for (size_t idx = 0; idx < instances.next_gate_challenges.size(); idx++) { + transcript->send_to_verifier("next_gate_challenge_" + std::to_string(idx), instances.next_gate_challenges[idx]); } - FF combiner_challenge = transcript->get_challenge("combiner_quotient_challenge"); - auto combiner_quotient_at_challenge = combiner_quotient.evaluate(combiner_challenge); - // TODO(https://github.com/AztecProtocol/barretenberg/issues/764): Generalize these formulas as well as computation - // of Lagrange basis - auto vanishing_polynomial_at_challenge = combiner_challenge * (combiner_challenge - FF(1)); - auto lagrange_0_at_challenge = FF(1) - combiner_challenge; + // Allocate space, initialised to 0, for the prover polynomials of the next accumulator + AllPolynomials storage; + for (auto& polynomial : storage.get_all()) { + polynomial = typename Flavor::Polynomial(instances[0]->instance_size); + for (auto& value : polynomial) { + value = FF(0); + } + } + ProverPolynomials acc_prover_polynomials; + size_t poly_idx = 0; + auto prover_polynomial_pointers = acc_prover_polynomials.get_all(); + for (auto& polynomial : storage.get_all()) { + prover_polynomial_pointers[poly_idx] = polynomial; + poly_idx++; + } - auto new_target_sum = compressed_perturbator * lagrange_0_at_challenge + - vanishing_polynomial_at_challenge * combiner_quotient_at_challenge; + // Fold the prover polynomials + auto acc_poly_views = acc_prover_polynomials.get_all(); + for (size_t inst_idx = 0; inst_idx < ProverInstances::NUM; inst_idx++) { + auto inst_poly_views = instances[inst_idx]->prover_polynomials.get_all(); + for (auto [acc_poly_view, inst_poly_view] : zip_view(acc_poly_views, inst_poly_views)) { + for (size_t poly_idx = 0; poly_idx < inst_poly_view.size(); poly_idx++) { + (acc_poly_view)[poly_idx] += (inst_poly_view)[poly_idx] * lagranges[inst_idx]; + } + } + } + next_accumulator->prover_polynomials = acc_prover_polynomials; - ProverFoldingResult res; - res.params.target_sum = new_target_sum; - res.folding_data = transcript->proof_data; - return res; + // Fold the witness commtiments and send them to the verifier + auto witness_labels = next_accumulator->commitment_labels.get_witness(); + size_t comm_idx = 0; + for (auto& acc_comm : next_accumulator->witness_commitments.get_all()) { + acc_comm = Commitment::infinity(); + size_t inst_idx = 0; + for (auto& instance : instances) { + acc_comm = acc_comm + instance->witness_commitments.get_all()[comm_idx] * lagranges[inst_idx]; + inst_idx++; + } + transcript->send_to_verifier("next_" + witness_labels[comm_idx], acc_comm); + comm_idx++; + } + + // Fold public data ϕ from all instances to produce ϕ* and add it to the transcript. As part of the folding + // verification, the verifier will produce ϕ* as well and check it against what was sent by the prover. + + // Fold the public inputs and send to the verifier + next_accumulator->public_inputs = std::vector(instances[0]->public_inputs.size(), 0); + size_t el_idx = 0; + for (auto& el : next_accumulator->public_inputs) { + size_t inst = 0; + for (auto& instance : instances) { + el += instance->public_inputs[el_idx] * lagranges[inst]; + inst++; + } + transcript->send_to_verifier("next_public_input_" + std::to_string(el_idx), el); + el_idx++; + } + + // Evaluate the combined batching challenge α univariate at challenge to obtain next α and send it to the + // verifier + next_accumulator->alpha = instances.alpha.evaluate(challenge); + transcript->send_to_verifier("next_alpha", next_accumulator->alpha); + + // Evaluate each relation parameter univariate at challenge to obtain the folded relation parameters and send to + // the verifier + auto& combined_relation_parameters = instances.relation_parameters; + auto folded_relation_parameters = proof_system::RelationParameters{ + combined_relation_parameters.eta.evaluate(challenge), + combined_relation_parameters.beta.evaluate(challenge), + combined_relation_parameters.gamma.evaluate(challenge), + combined_relation_parameters.public_input_delta.evaluate(challenge), + combined_relation_parameters.lookup_grand_product_delta.evaluate(challenge), + }; + // TODO(https://github.com/AztecProtocol/barretenberg/issues/805): Add the relation parameters to the transcript + // together. + transcript->send_to_verifier("next_eta", folded_relation_parameters.eta); + transcript->send_to_verifier("next_beta", folded_relation_parameters.beta); + transcript->send_to_verifier("next_gamma", folded_relation_parameters.gamma); + transcript->send_to_verifier("next_public_input_delta", folded_relation_parameters.public_input_delta); + transcript->send_to_verifier("next_lookup_grand_product_delta", + folded_relation_parameters.lookup_grand_product_delta); + next_accumulator->relation_parameters = folded_relation_parameters; + + // Fold the verification key and send it to the verifier as this is part of ϕ as well + auto acc_vk = std::make_shared(instances[0]->prover_polynomials.get_polynomial_size(), + instances[0]->public_inputs.size()); + auto labels = next_accumulator->commitment_labels.get_precomputed(); + size_t vk_idx = 0; + for (auto& vk : acc_vk->get_all()) { + size_t inst = 0; + vk = Commitment::infinity(); + for (auto& instance : instances) { + vk = vk + (instance->verification_key->get_all()[vk_idx]) * lagranges[inst]; + inst++; + } + transcript->send_to_verifier("next_" + labels[vk_idx], vk); + vk_idx++; + } + next_accumulator->verification_key = acc_vk; + + return next_accumulator; } + template class ProtoGalaxyProver_>; template class ProtoGalaxyProver_>; } // namespace proof_system::honk \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.hpp b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.hpp index 5e2b7b32ec6..9c881d82a89 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.hpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.hpp @@ -24,6 +24,11 @@ template class ProtoGalaxyProver_ { using ProverPolynomials = typename Flavor::ProverPolynomials; using Relations = typename Flavor::Relations; using AlphaType = typename ProverInstances::AlphaType; + using VerificationKey = typename Flavor::VerificationKey; + using CommitmentKey = typename Flavor::CommitmentKey; + using WitnessCommitments = typename Flavor::WitnessCommitments; + using Commitment = typename Flavor::Commitment; + using AllPolynomials = typename Flavor::AllPolynomials; using BaseUnivariate = Univariate; // The length of ExtendedUnivariate is the largest length (==max_relation_degree + 1) of a univariate polynomial @@ -44,19 +49,48 @@ template class ProtoGalaxyProver_ { ProverInstances instances; std::shared_ptr transcript = std::make_shared(); + std::shared_ptr commitment_key; + ProtoGalaxyProver_() = default; - ProtoGalaxyProver_(ProverInstances insts) - : instances(insts){}; + ProtoGalaxyProver_(const std::vector>& insts, + const std::shared_ptr& commitment_key) + : instances(ProverInstances(insts)) + , commitment_key(std::move(commitment_key)){}; ~ProtoGalaxyProver_() = default; /** - * @brief Prior to folding we need to add all the public inputs to the transcript, labelled by their corresponding - * instance index, compute all the instance's polynomials and record the relation parameters involved in computing - * these polynomials in the transcript. - * + * @brief Prior to folding, we need to finalize the given instances and add all their public data ϕ to the + * transcript, labelled by their corresponding instance index for domain separation. + * TODO(https://github.com/AztecProtocol/barretenberg/issues/795):The rounds prior to actual proving/folding are + * common between decider and folding verifier and could be somehow shared so we do not duplicate code so much. */ void prepare_for_folding(); + /** + * @brief Send the public data of an accumulator, i.e. a relaxed instance, to the verifier (ϕ in the paper). + * + * @param domain_separator separates the same type of data coming from difference instances by instance + * index + */ + void send_accumulator(std::shared_ptr, const std::string& domain_separator); + + /** + * @brief For each instance produced by a circuit, prior to folding, we need to complete the computation of its + * prover polynomials, commit to witnesses and generate the relation parameters as well as send the public data ϕ of + * an instance to the verifier. + * + * @param domain_separator separates the same type of data coming from difference instances by instance + * index + */ + void finalise_and_send_instance(std::shared_ptr, const std::string& domain_separator); + + /** + * @brief Run the folding prover protocol to produce a new accumulator and a folding proof to be verified by the + * folding verifier. + * + * TODO(https://github.com/AztecProtocol/barretenberg/issues/753): fold goblin polynomials + */ + FoldingResult fold_instances(); /** * @brief Given a vector \vec{\beta} of values, compute the pow polynomial on these values as defined in the paper. */ @@ -89,6 +123,20 @@ template class ProtoGalaxyProver_ { return pows; } + static std::vector update_gate_challenges(const FF perturbator_challenge, + const std::vector& gate_challenges, + const std::vector& round_challenges) + { + auto log_instance_size = gate_challenges.size(); + std::vector next_gate_challenges(log_instance_size); + next_gate_challenges[0] = 1; + + for (size_t idx = 1; idx < log_instance_size; idx++) { + next_gate_challenges[idx] = gate_challenges[idx] + perturbator_challenge * round_challenges[idx - 1]; + } + return next_gate_challenges; + } + // Returns the accumulator, which is the first element in ProverInstances. The accumulator is assumed to have the // FoldingParameters set and be the result of a previous round of folding. // TODO(https://github.com/AztecProtocol/barretenberg/issues/740): handle the case when the accumulator is empty @@ -191,14 +239,12 @@ template class ProtoGalaxyProver_ { { auto full_honk_evaluations = compute_full_honk_evaluations( accumulator->prover_polynomials, accumulator->alpha, accumulator->relation_parameters); - const auto betas = accumulator->folding_parameters.gate_separation_challenges; + const auto betas = accumulator->folding_parameters.gate_challenges; assert(betas.size() == deltas.size()); auto coeffs = construct_perturbator_coefficients(betas, deltas, full_honk_evaluations); return Polynomial(coeffs); } - ProverFoldingResult fold_instances(); - TupleOfTuplesOfUnivariates univariate_accumulators; /** @@ -243,7 +289,7 @@ template class ProtoGalaxyProver_ { ExtendedUnivariateWithRandomization compute_combiner(const ProverInstances& instances, const std::vector& pow_betas_star) { - size_t common_circuit_size = instances[0]->prover_polynomials.get_polynomial_size(); + size_t common_instance_size = instances[0]->instance_size; // Determine number of threads for multithreading. // Note: Multithreading is "on" for every round but we reduce the number of threads from the max available based @@ -251,14 +297,15 @@ template class ProtoGalaxyProver_ { // For now we use a power of 2 number of threads simply to ensure the round size is evenly divided. size_t max_num_threads = get_num_cpus_pow2(); // number of available threads (power of 2) size_t min_iterations_per_thread = 1 << 6; // min number of iterations for which we'll spin up a unique thread - size_t desired_num_threads = common_circuit_size / min_iterations_per_thread; + size_t desired_num_threads = common_instance_size / min_iterations_per_thread; size_t num_threads = std::min(desired_num_threads, max_num_threads); // fewer than max if justified num_threads = num_threads > 0 ? num_threads : 1; // ensure num threads is >= 1 - size_t iterations_per_thread = common_circuit_size / num_threads; // actual iterations per thread + size_t iterations_per_thread = common_instance_size / num_threads; // actual iterations per thread // Construct univariate accumulator containers; one per thread std::vector thread_univariate_accumulators(num_threads); for (auto& accum : thread_univariate_accumulators) { + // just normal relation lengths Utils::zero_univariates(accum); } @@ -341,21 +388,21 @@ template class ProtoGalaxyProver_ { } /** - * @brief Create folded (univariate) relation parameters. + * @brief Combine each relation parameter, in part, from all the instances into univariates, used in the computation + * of combiner. * @details For a given relation parameter type, extract that parameter from each instance, place the values in a * univariate (i.e., sum them against an appropriate univariate Lagrange basis) and then extended as needed during * the constuction of the combiner. */ - static void fold_relation_parameters(ProverInstances& instances) + static void combine_relation_parameters(ProverInstances& instances) { // array of parameters to be computed - auto& folded_parameters = instances.relation_parameters.to_fold; size_t param_idx = 0; - for (auto& folded_parameter : folded_parameters) { + for (auto& folded_parameter : instances.relation_parameters.to_fold) { Univariate tmp(0); size_t instance_idx = 0; for (auto& instance : instances) { - tmp.value_at(instance_idx) = instance->relation_parameters.to_fold[param_idx]; + tmp.value_at(instance_idx) = instance->relation_parameters.to_fold[param_idx].get(); instance_idx++; } folded_parameter.get() = tmp.template extend_to(); @@ -364,14 +411,15 @@ template class ProtoGalaxyProver_ { } /** - * @brief Create folded univariate for the relation batching parameter (alpha). + * @brief Combine the relation batching parameter (named alpha) from each instance into a univariate, used in the + * computation of combiner. * */ // TODO(https://github.com/AztecProtocol/barretenberg/issues/772): At the moment we have a single α per Instance, we // fold them and then we use the unique folded_α for each folded subrelation that is batched in the combiner. This // is obviously insecure. We need to generate α_i for each subrelation_i, fold them and then use folded_α_i when // batching the i-th folded subrelation in the combiner. - static void fold_alpha(ProverInstances& instances) + static void combine_alpha(ProverInstances& instances) { Univariate accumulated_alpha; size_t instance_idx = 0; @@ -381,6 +429,24 @@ template class ProtoGalaxyProver_ { } instances.alpha = accumulated_alpha.template extend_to(); } + + /** + * @brief Compute the next accumulator (ϕ*, ω*\vec{\beta*}, e*), send the public data ϕ* and the folding parameters + * (\vec{\beta*}, e*) to the verifier and return the complete accumulator + * + * @details At this stage, we assume that the instances have the same size and the same number of public parameter.s + * @param instances + * @param combiner_quotient polynomial K in the paper + * @param challenge + * @param compressed_perturbator + * + * TODO(https://github.com/AztecProtocol/barretenberg/issues/796): optimise the construction of the new accumulator + */ + std::shared_ptr compute_next_accumulator( + ProverInstances& instances, + Univariate& combiner_quotient, + const FF& challenge, + const FF& compressed_perturbator); }; extern template class ProtoGalaxyProver_>; diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_verifier.cpp b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_verifier.cpp index 1aa99dea379..7107d991228 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_verifier.cpp @@ -3,57 +3,148 @@ namespace proof_system::honk { template -void ProtoGalaxyVerifier_::prepare_for_folding(std::vector fold_data) +void ProtoGalaxyVerifier_::receive_accumulator(const std::shared_ptr& inst, + const std::string& domain_separator) +{ + inst->instance_size = transcript->template receive_from_prover(domain_separator + "_instance_size"); + inst->log_instance_size = static_cast(numeric::get_msb(inst->instance_size)); + inst->public_input_size = + transcript->template receive_from_prover(domain_separator + "_public_input_size"); + + for (size_t i = 0; i < inst->public_input_size; ++i) { + auto public_input_i = + transcript->template receive_from_prover(domain_separator + "_public_input_" + std::to_string(i)); + inst->public_inputs.emplace_back(public_input_i); + } + + auto eta = transcript->template receive_from_prover(domain_separator + "_eta"); + auto beta = transcript->template receive_from_prover(domain_separator + "_beta"); + auto gamma = transcript->template receive_from_prover(domain_separator + "_gamma"); + auto public_input_delta = transcript->template receive_from_prover(domain_separator + "_public_input_delta"); + auto lookup_grand_product_delta = + transcript->template receive_from_prover(domain_separator + "_lookup_grand_product_delta"); + inst->relation_parameters = + RelationParameters{ eta, beta, gamma, public_input_delta, lookup_grand_product_delta }; + inst->alpha = transcript->template receive_from_prover(domain_separator + "_alpha"); + + inst->folding_parameters.target_sum = + transcript->template receive_from_prover(domain_separator + "_target_sum"); + + inst->folding_parameters.gate_challenges = std::vector(inst->log_instance_size); + for (size_t idx = 0; idx < inst->log_instance_size; idx++) { + inst->folding_parameters.gate_challenges[idx] = + transcript->template receive_from_prover(domain_separator + "_gate_challenge_" + std::to_string(idx)); + } + auto comm_view = inst->witness_commitments.get_all(); + auto witness_labels = inst->commitment_labels.get_witness(); + for (size_t idx = 0; idx < witness_labels.size(); idx++) { + comm_view[idx] = + transcript->template receive_from_prover(domain_separator + "_" + witness_labels[idx]); + } + + inst->verification_key = std::make_shared(inst->instance_size, inst->public_input_size); + auto vk_view = inst->verification_key->get_all(); + auto vk_labels = inst->commitment_labels.get_precomputed(); + for (size_t idx = 0; idx < vk_labels.size(); idx++) { + vk_view[idx] = transcript->template receive_from_prover(domain_separator + "_" + vk_labels[idx]); + } +} + +template +void ProtoGalaxyVerifier_::receive_and_finalise_instance(const std::shared_ptr& inst, + const std::string& domain_separator) +{ + inst->instance_size = transcript->template receive_from_prover(domain_separator + "_instance_size"); + inst->log_instance_size = static_cast(numeric::get_msb(inst->instance_size)); + inst->public_input_size = + transcript->template receive_from_prover(domain_separator + "_public_input_size"); + + for (size_t i = 0; i < inst->public_input_size; ++i) { + auto public_input_i = + transcript->template receive_from_prover(domain_separator + "_public_input_" + std::to_string(i)); + inst->public_inputs.emplace_back(public_input_i); + } + + inst->pub_inputs_offset = + transcript->template receive_from_prover(domain_separator + "_pub_inputs_offset"); + + auto labels = inst->commitment_labels; + auto& witness_commitments = inst->witness_commitments; + witness_commitments.w_l = transcript->template receive_from_prover(domain_separator + "_" + labels.w_l); + witness_commitments.w_r = transcript->template receive_from_prover(domain_separator + "_" + labels.w_r); + witness_commitments.w_o = transcript->template receive_from_prover(domain_separator + "_" + labels.w_o); + + auto eta = transcript->get_challenge(domain_separator + "_eta"); + witness_commitments.sorted_accum = + transcript->template receive_from_prover(domain_separator + "_" + labels.sorted_accum); + witness_commitments.w_4 = transcript->template receive_from_prover(domain_separator + "_" + labels.w_4); + + auto [beta, gamma] = transcript->get_challenges(domain_separator + "_beta", domain_separator + "_gamma"); + witness_commitments.z_perm = + transcript->template receive_from_prover(domain_separator + "_" + labels.z_perm); + witness_commitments.z_lookup = + transcript->template receive_from_prover(domain_separator + "_" + labels.z_lookup); + + const FF public_input_delta = compute_public_input_delta( + inst->public_inputs, beta, gamma, inst->instance_size, inst->pub_inputs_offset); + const FF lookup_grand_product_delta = compute_lookup_grand_product_delta(beta, gamma, inst->instance_size); + inst->relation_parameters = + RelationParameters{ eta, beta, gamma, public_input_delta, lookup_grand_product_delta }; + + inst->alpha = transcript->get_challenge(domain_separator + "_alpha"); + + inst->verification_key = std::make_shared(inst->instance_size, inst->public_input_size); + auto vk_view = inst->verification_key->get_all(); + auto vk_labels = labels.get_precomputed(); + for (size_t idx = 0; idx < vk_labels.size(); idx++) { + vk_view[idx] = transcript->template receive_from_prover(domain_separator + "_" + vk_labels[idx]); + } +} + +// TODO(https://github.com/AztecProtocol/barretenberg/issues/795): The rounds prior to actual verifying are common +// between decider and folding verifier and could be somehow shared so we do not duplicate code so much. +template +void ProtoGalaxyVerifier_::prepare_for_folding(const std::vector& fold_data) { transcript = std::make_shared(fold_data); auto index = 0; - for (auto it = verifier_instances.begin(); it != verifier_instances.end(); it++, index++) { + auto inst = instances[0]; + auto domain_separator = std::to_string(index); + inst->is_accumulator = transcript->template receive_from_prover(domain_separator + "is_accumulator"); + if (inst->is_accumulator) { + receive_accumulator(inst, domain_separator); + } else { + receive_and_finalise_instance(inst, domain_separator); + } + index++; + + for (auto it = instances.begin() + 1; it != instances.end(); it++, index++) { auto inst = *it; auto domain_separator = std::to_string(index); - inst->instance_size = transcript->template receive_from_prover(domain_separator + "_circuit_size"); - inst->public_input_size = - transcript->template receive_from_prover(domain_separator + "_public_input_size"); - inst->pub_inputs_offset = - transcript->template receive_from_prover(domain_separator + "_pub_inputs_offset"); - - for (size_t i = 0; i < inst->public_input_size; ++i) { - auto public_input_i = - transcript->template receive_from_prover(domain_separator + "_public_input_" + std::to_string(i)); - inst->public_inputs.emplace_back(public_input_i); - } - auto [eta, beta, gamma] = challenges_to_field_elements(transcript->get_challenges( - domain_separator + "_eta", domain_separator + "_beta", domain_separator + "_gamma")); - - const FF public_input_delta = compute_public_input_delta( - inst->public_inputs, beta, gamma, inst->instance_size, inst->pub_inputs_offset); - const FF lookup_grand_product_delta = compute_lookup_grand_product_delta(beta, gamma, inst->instance_size); - inst->relation_parameters = - RelationParameters{ eta, beta, gamma, public_input_delta, lookup_grand_product_delta }; - inst->alpha = transcript->get_challenge(domain_separator + "_alpha"); + receive_and_finalise_instance(inst, domain_separator); } } template -VerifierFoldingResult ProtoGalaxyVerifier_< - VerifierInstances>::fold_public_parameters(std::vector fold_data) +bool ProtoGalaxyVerifier_::verify_folding_proof(std::vector fold_data) { - using Flavor = typename VerifierInstances::Flavor; - prepare_for_folding(fold_data); - FF delta = transcript->get_challenge("delta"); + + auto delta = transcript->get_challenge("delta"); auto accumulator = get_accumulator(); - auto log_instance_size = static_cast(numeric::get_msb(accumulator->instance_size)); - auto deltas = compute_round_challenge_pows(log_instance_size, delta); - std::vector perturbator_coeffs(log_instance_size + 1); - for (size_t idx = 0; idx <= log_instance_size; idx++) { + auto deltas = compute_round_challenge_pows(accumulator->log_instance_size, delta); + + std::vector perturbator_coeffs(accumulator->log_instance_size + 1); + for (size_t idx = 0; idx <= accumulator->log_instance_size; idx++) { perturbator_coeffs[idx] = transcript->template receive_from_prover("perturbator_" + std::to_string(idx)); } + ASSERT(perturbator_coeffs[0] == accumulator->folding_parameters.target_sum); auto perturbator = Polynomial(perturbator_coeffs); FF perturbator_challenge = transcript->get_challenge("perturbator_challenge"); auto perturbator_at_challenge = perturbator.evaluate(perturbator_challenge); - // Thed degree of K(X) is dk - k - 1 = k(d - 1) - 1. Hence we need k(d - 1) evaluations to represent it. - std::array combiner_quotient_evals = {}; + // The degree of K(X) is dk - k - 1 = k(d - 1) - 1. Hence we need k(d - 1) evaluations to represent it. + std::array combiner_quotient_evals; for (size_t idx = 0; idx < VerifierInstances::BATCHED_EXTENDED_LENGTH - VerifierInstances::NUM; idx++) { combiner_quotient_evals[idx] = transcript->template receive_from_prover( "combiner_quotient_" + std::to_string(idx + VerifierInstances::NUM)); @@ -64,14 +155,99 @@ VerifierFoldingResult ProtoGalaxyVerifier_< auto combiner_quotient_at_challenge = combiner_quotient.evaluate(combiner_challenge); auto vanishing_polynomial_at_challenge = combiner_challenge * (combiner_challenge - FF(1)); - auto lagrange_0_at_challenge = FF(1) - combiner_challenge; + auto lagranges = std::vector{ FF(1) - combiner_challenge, combiner_challenge }; + + // Compute next folding parameters and verify against the ones received from the prover + auto expected_next_target_sum = + perturbator_at_challenge * lagranges[0] + vanishing_polynomial_at_challenge * combiner_quotient_at_challenge; + auto next_target_sum = transcript->template receive_from_prover("next_target_sum"); + bool verified = (expected_next_target_sum == next_target_sum); + auto expected_betas_star = + update_gate_challenges(perturbator_challenge, accumulator->folding_parameters.gate_challenges, deltas); + for (size_t idx = 0; idx < accumulator->log_instance_size; idx++) { + auto beta_star = transcript->template receive_from_prover("next_gate_challenge_" + std::to_string(idx)); + verified = verified & (expected_betas_star[idx] == beta_star); + } + + // Compute ϕ and verify against the data received from the prover + WitnessCommitments acc_witness_commitments; + auto witness_labels = commitment_labels.get_witness(); + size_t comm_idx = 0; + for (auto& expected_comm : acc_witness_commitments.get_all()) { + expected_comm = Commitment::infinity(); + size_t inst = 0; + for (auto& instance : instances) { + expected_comm = expected_comm + instance->witness_commitments.get_all()[comm_idx] * lagranges[inst]; + inst++; + } + auto comm = transcript->template receive_from_prover("next_" + witness_labels[comm_idx]); + verified = verified & (comm == expected_comm); + comm_idx++; + } - auto new_target_sum = perturbator_at_challenge * lagrange_0_at_challenge + - vanishing_polynomial_at_challenge * combiner_quotient_at_challenge; + std::vector folded_public_inputs(instances[0]->public_inputs.size(), 0); + size_t el_idx = 0; + for (auto& expected_el : folded_public_inputs) { + size_t inst = 0; + for (auto& instance : instances) { + expected_el += instance->public_inputs[el_idx] * lagranges[inst]; + inst++; + } + auto el = transcript->template receive_from_prover("next_public_input" + std::to_string(el_idx)); + verified = verified & (el == expected_el); + el_idx++; + } + + auto expected_alpha = FF(0); + auto expected_parameters = proof_system::RelationParameters{}; + for (size_t inst_idx = 0; inst_idx < VerifierInstances::NUM; inst_idx++) { + auto instance = instances[inst_idx]; + expected_alpha += instance->alpha * lagranges[inst_idx]; + expected_parameters.eta += instance->relation_parameters.eta * lagranges[inst_idx]; + expected_parameters.beta += instance->relation_parameters.beta * lagranges[inst_idx]; + expected_parameters.gamma += instance->relation_parameters.gamma * lagranges[inst_idx]; + expected_parameters.public_input_delta += + instance->relation_parameters.public_input_delta * lagranges[inst_idx]; + expected_parameters.lookup_grand_product_delta += + instance->relation_parameters.lookup_grand_product_delta * lagranges[inst_idx]; + } + + auto next_alpha = transcript->template receive_from_prover("next_alpha"); + verified = verified & (next_alpha == expected_alpha); + info(verified); + auto next_eta = transcript->template receive_from_prover("next_eta"); + verified = verified & (next_eta == expected_parameters.eta); + info(verified); + + auto next_beta = transcript->template receive_from_prover("next_beta"); + verified = verified & (next_beta == expected_parameters.beta); + + auto next_gamma = transcript->template receive_from_prover("next_gamma"); + verified = verified & (next_gamma == expected_parameters.gamma); + + auto next_public_input_delta = transcript->template receive_from_prover("next_public_input_delta"); + verified = verified & (next_public_input_delta == expected_parameters.public_input_delta); + + auto next_lookup_grand_product_delta = + transcript->template receive_from_prover("next_lookup_grand_product_delta"); + verified = verified & (next_lookup_grand_product_delta == expected_parameters.lookup_grand_product_delta); + + auto acc_vk = std::make_shared(instances[0]->instance_size, instances[0]->public_input_size); + auto vk_labels = commitment_labels.get_precomputed(); + size_t vk_idx = 0; + for (auto& expected_vk : acc_vk->get_all()) { + size_t inst = 0; + expected_vk = Commitment::infinity(); + for (auto& instance : instances) { + expected_vk = expected_vk + instance->verification_key->get_all()[vk_idx] * lagranges[inst]; + inst++; + } + auto vk = transcript->template receive_from_prover("next_" + vk_labels[vk_idx]); + verified = verified & (vk == expected_vk); + vk_idx++; + } - VerifierFoldingResult res; - res.parameters.target_sum = new_target_sum; - return res; + return verified; } template class ProtoGalaxyVerifier_>; diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_verifier.hpp b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_verifier.hpp index 3c5a4ed8ef1..c723532a5b9 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_verifier.hpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_verifier.hpp @@ -12,17 +12,23 @@ template class ProtoGalaxyVerifier_ { using Flavor = typename VerifierInstances::Flavor; using Transcript = typename Flavor::Transcript; using FF = typename Flavor::FF; + using Commitment = typename Flavor::Commitment; using Instance = typename VerifierInstances::Instance; using VerificationKey = typename Flavor::VerificationKey; + using WitnessCommitments = typename Flavor::WitnessCommitments; + using CommitmentLabels = typename Flavor::CommitmentLabels; + + VerifierInstances instances; - VerifierInstances verifier_instances; std::shared_ptr transcript = std::make_shared(); + CommitmentLabels commitment_labels; + ProtoGalaxyVerifier_(VerifierInstances insts) - : verifier_instances(insts){}; + : instances(insts){}; ~ProtoGalaxyVerifier_() = default; /** - * @brief For a new round challenge δ at each iteration of the ProtoGalaxy protocol, compute the vector + * @brief Given a new round challenge δ for each iteration of the full ProtoGalaxy protocol, compute the vector * [δ, δ^2,..., δ^t] where t = logn and n is the size of the instance. */ static std::vector compute_round_challenge_pows(size_t log_instance_size, FF round_challenge) @@ -35,21 +41,47 @@ template class ProtoGalaxyVerifier_ { return pows; } - std::shared_ptr get_accumulator() { return verifier_instances[0]; } + static std::vector update_gate_challenges(const FF perturbator_challenge, + const std::vector& gate_challenges, + const std::vector& round_challenges) + { + auto log_instance_size = gate_challenges.size(); + std::vector next_gate_challenges(log_instance_size); + next_gate_challenges[0] = 1; + + for (size_t idx = 1; idx < log_instance_size; idx++) { + next_gate_challenges[idx] = gate_challenges[idx] + perturbator_challenge * round_challenges[idx - 1]; + } + return next_gate_challenges; + } + + std::shared_ptr get_accumulator() { return instances[0]; } /** - * @brief Instatiate the VerifierInstances and the VerifierTranscript. + * @brief Instatiate the instances and the transcript. * * @param fold_data The data transmitted via the transcript by the prover. */ - void prepare_for_folding(std::vector fold_data); + void prepare_for_folding(const std::vector&); + + /** + * @brief Instantiatied the accumulator (i.e. the relaxed instance) from the transcript. + * + */ + void receive_accumulator(const std::shared_ptr&, const std::string&); + + /** + * @brief Process the public data ϕ for the Instances to be folded. + * + */ + void receive_and_finalise_instance(const std::shared_ptr&, const std::string&); /** - * @brief Run the folding protocol on the verifier side. + * @brief Run the folding protocol on the verifier side to establish whether the public data ϕ of the new + * accumulator, received from the prover is the same as that produced by the verifier. * - * TODO(https://github.com/AztecProtocol/barretenberg/issues/690): finalise the implementation of this function */ - VerifierFoldingResult fold_public_parameters(std::vector fold_data); + bool verify_folding_proof(std::vector); }; extern template class ProtoGalaxyVerifier_>; diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/instance/instances.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/instance/instances.hpp index 1fc658eae9c..0fcc8d27614 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/instance/instances.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/instance/instances.hpp @@ -8,6 +8,7 @@ template struct ProverInstances_ { public: static_assert(NUM_ > 0, "Must have at least one prover instance"); using Flavor = Flavor_; + using FoldingParameters = typename Flavor::FoldingParameters; using FF = typename Flavor::FF; static constexpr size_t NUM = NUM_; using Instance = ProverInstance_; @@ -21,6 +22,7 @@ template struct ProverInstances_ { ArrayType _data; RelationParameters relation_parameters; AlphaType alpha; + std::vector next_gate_challenges; std::shared_ptr const& operator[](size_t idx) const { return _data[idx]; } typename ArrayType::iterator begin() { return _data.begin(); }; @@ -54,16 +56,15 @@ template struct ProverInstances_ { */ std::vector> row_to_univariates(size_t row_idx) const { - auto instance_polynomial_views = get_polynomial_views(); + auto insts_prover_polynomials_views = get_polynomials_views(); std::vector> results; - // Initialize to our amount of columns - results.resize(instance_polynomial_views[0].size()); + // Set the size corresponding to the number of rows in the execution trace + results.resize(insts_prover_polynomials_views[0].size()); size_t instance_idx = 0; - // Iterate instances - for (auto& get_all : instance_polynomial_views) { - // Iterate columns + // Iterate over the prover polynomials' views corresponding to each instance + for (auto& get_all : insts_prover_polynomials_views) { + // Iterate over all columns in the trace execution of an instance and extract their value at row_idx. for (auto [result, poly_ptr] : zip_view(results, get_all)) { - // Assign row for each instance result.evaluations[instance_idx] = (poly_ptr)[row_idx]; } instance_idx++; @@ -72,9 +73,10 @@ template struct ProverInstances_ { } private: - auto get_polynomial_views() const + // Returns a vector containing pointer views to the prover polynomials corresponding to each instance. + auto get_polynomials_views() const { - // As a practical measure, get the first instance's pointer view to deduce the vector type + // As a practical measure, get the first instance's view to deduce the vector type std::vector get_alls{ _data[0]->prover_polynomials.get_all() }; // complete the views, starting from the second item for (size_t i = 1; i < NUM; i++) { @@ -97,14 +99,10 @@ template struct VerifierInstances_ { std::shared_ptr const& operator[](size_t idx) const { return _data[idx]; } typename ArrayType::iterator begin() { return _data.begin(); }; typename ArrayType::iterator end() { return _data.end(); }; - VerifierInstances_(std::vector> vks) + + VerifierInstances_() { - ASSERT(vks.size() == NUM); - for (size_t idx = 0; idx < vks.size(); idx++) { - Instance inst; - inst.verification_key = std::move(vks[idx]); - _data[idx] = std::make_unique(inst); - } + std::generate(_data.begin(), _data.end(), []() { return std::make_unique(); }); }; }; } // namespace proof_system::honk diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.cpp b/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.cpp index 8e1a6ede949..4e5a5d66123 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.cpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.cpp @@ -353,6 +353,9 @@ template void ProverInstance_::initialize_prover_polynomi size_t idx = i + pub_inputs_offset; public_inputs.emplace_back(public_wires_source[idx]); } + + instance_size = proving_key->circuit_size; + log_instance_size = static_cast(numeric::get_msb(instance_size)); } template void ProverInstance_::compute_sorted_accumulator_polynomials(FF eta) diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.hpp index 5f12dc0c1dd..ea09aa6fceb 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.hpp @@ -3,7 +3,6 @@ #include "barretenberg/flavor/goblin_ultra.hpp" #include "barretenberg/flavor/ultra.hpp" #include "barretenberg/proof_system/composer/composer_lib.hpp" -#include "barretenberg/protogalaxy/folding_result.hpp" #include "barretenberg/relations/relation_parameters.hpp" #include "barretenberg/srs/factories/file_crs_factory.hpp" @@ -28,6 +27,7 @@ template class ProverInstance_ { using ProverPolynomials = typename Flavor::ProverPolynomials; using Polynomial = typename Flavor::Polynomial; using WitnessCommitments = typename Flavor::WitnessCommitments; + using CommitmentLabels = typename Flavor::CommitmentLabels; public: std::shared_ptr proving_key; @@ -35,6 +35,7 @@ template class ProverInstance_ { ProverPolynomials prover_polynomials; WitnessCommitments witness_commitments; + CommitmentLabels commitment_labels; std::array sorted_polynomials; @@ -50,6 +51,9 @@ template class ProverInstance_ { std::vector recursive_proof_public_input_indices; // non-empty for the accumulated instances FoldingParameters folding_parameters; + bool is_accumulator = false; + size_t instance_size; + size_t log_instance_size; ProverInstance_(Circuit& circuit) { @@ -58,12 +62,6 @@ template class ProverInstance_ { compute_witness(circuit); } - ProverInstance_(FoldingResult result) - : verification_key(std::move(result.verification_key)) - , prover_polynomials(result.folded_prover_polynomials) - , public_inputs(result.folded_public_inputs) - , folding_parameters(result.folding_parameters){}; - ProverInstance_() = default; ~ProverInstance_() = default; diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/instance/verifier_instance.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/instance/verifier_instance.hpp index fb14bd32b8b..06fdc47f264 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/instance/verifier_instance.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/instance/verifier_instance.hpp @@ -8,14 +8,20 @@ template class VerifierInstance_ { using FF = typename Flavor::FF; using VerificationKey = typename Flavor::VerificationKey; using FoldingParameters = typename Flavor::FoldingParameters; + using WitnessCommitments = typename Flavor::WitnessCommitments; + using CommitmentLabels = typename Flavor::CommitmentLabels; std::shared_ptr verification_key; std::vector public_inputs; - size_t pub_inputs_offset; + size_t pub_inputs_offset = 0; size_t public_input_size; size_t instance_size; + size_t log_instance_size; RelationParameters relation_parameters; FF alpha; + bool is_accumulator = false; FoldingParameters folding_parameters; + WitnessCommitments witness_commitments; + CommitmentLabels commitment_labels; }; } // namespace proof_system::honk \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/protogalaxy.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/protogalaxy.test.cpp index fac96d16cc6..caf1285e0b8 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/protogalaxy.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/protogalaxy.test.cpp @@ -6,14 +6,18 @@ using namespace barretenberg; using namespace proof_system::honk; using Flavor = flavor::Ultra; +using VerificationKey = Flavor::VerificationKey; using Instance = ProverInstance_; using Instances = ProverInstances_; using ProtoGalaxyProver = ProtoGalaxyProver_; using FF = Flavor::FF; +using Affine = Flavor::Commitment; +using Projective = Flavor::GroupElement; using Builder = Flavor::CircuitBuilder; using Polynomial = typename Flavor::Polynomial; using ProverPolynomials = Flavor::ProverPolynomials; using RelationParameters = proof_system::RelationParameters; +using WitnessCommitments = typename Flavor::WitnessCommitments; const size_t NUM_POLYNOMIALS = Flavor::NUM_ALL_ENTITIES; namespace protogalaxy_tests { @@ -81,6 +85,26 @@ ProverPolynomials construct_ultra_full_polynomials(auto& input_polynomials) return full_polynomials; } +std::shared_ptr construct_ultra_verification_key(size_t instance_size, size_t num_public_inputs) +{ + auto verification_key = std::make_shared(instance_size, num_public_inputs); + auto vk_view = verification_key->get_all(); + for (auto& view : vk_view) { + view = Affine(Projective::random_element()); + } + return verification_key; +} + +WitnessCommitments construct_witness_commitments() +{ + WitnessCommitments wc; + auto w_view = wc.get_all(); + for (auto& view : w_view) { + view = Affine(Projective::random_element()); + } + return wc; +} + class ProtoGalaxyTests : public ::testing::Test { public: static void SetUpTestSuite() { barretenberg::srs::init_crs_factory("../srs_db/ignition"); } @@ -159,11 +183,9 @@ TEST_F(ProtoGalaxyTests, PerturbatorPolynomial) target_sum += full_honk_evals[i] * pow_beta[i]; } - auto accumulator = std::make_shared( - FoldingResult{ .folded_prover_polynomials = full_polynomials, - .folded_public_inputs = std::vector{}, - .verification_key = std::make_shared(), - .folding_parameters = { betas, target_sum } }); + auto accumulator = std::make_shared(); + accumulator->prover_polynomials = full_polynomials; + accumulator->folding_parameters = { betas, target_sum }; accumulator->relation_parameters = relation_parameters; accumulator->alpha = alpha; @@ -225,7 +247,7 @@ TEST_F(ProtoGalaxyTests, FoldChallenges) instance2->relation_parameters.eta = 3; Instances instances{ { instance1, instance2 } }; - ProtoGalaxyProver::fold_relation_parameters(instances); + ProtoGalaxyProver::combine_relation_parameters(instances); Univariate expected_eta{ { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23 } }; EXPECT_EQ(instances.relation_parameters.eta, expected_eta); @@ -246,10 +268,67 @@ TEST_F(ProtoGalaxyTests, FoldAlpha) instance2->alpha = 4; Instances instances{ { instance1, instance2 } }; - ProtoGalaxyProver::fold_alpha(instances); + ProtoGalaxyProver::combine_alpha(instances); Univariate expected_alpha{ { 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26 } }; EXPECT_EQ(instances.alpha, expected_alpha); } +// TODO(https://github.com/AztecProtocol/barretenberg/issues/807): Have proper full folding testing (both failing and +// passing) and move creating a test accumulator in a separate function. +TEST_F(ProtoGalaxyTests, ComputeNewAccumulator) +{ + const size_t log_instance_size(4); + const size_t instance_size(1 << log_instance_size); + + std::array, NUM_POLYNOMIALS> random_polynomials; + for (auto& poly : random_polynomials) { + poly = get_random_polynomial(instance_size); + } + auto full_polynomials = construct_ultra_full_polynomials(random_polynomials); + auto relation_parameters = proof_system::RelationParameters::get_random(); + auto alpha = FF::random_element(); + + auto full_honk_evals = + ProtoGalaxyProver::compute_full_honk_evaluations(full_polynomials, alpha, relation_parameters); + std::vector betas(log_instance_size); + for (size_t idx = 0; idx < log_instance_size; idx++) { + betas[idx] = FF::random_element(); + } + + // Construct pow(\vec{betas}) as in the paper + auto pow_beta = ProtoGalaxyProver::compute_pow_polynomial_at_values(betas, instance_size); + + // Compute the corresponding target sum and create a dummy accumulator + auto target_sum = FF(0); + for (size_t i = 0; i < instance_size; i++) { + target_sum += full_honk_evals[i] * pow_beta[i]; + } + + auto accumulator = std::make_shared(); + accumulator->witness_commitments = construct_witness_commitments(); + accumulator->instance_size = instance_size; + accumulator->log_instance_size = log_instance_size; + accumulator->prover_polynomials = full_polynomials; + accumulator->folding_parameters = { betas, target_sum }; + accumulator->relation_parameters = relation_parameters; + accumulator->alpha = alpha; + accumulator->is_accumulator = true; + accumulator->public_inputs = std::vector{ FF::random_element() }; + accumulator->verification_key = construct_ultra_verification_key(instance_size, 1); + + auto builder = typename Flavor::CircuitBuilder(); + auto composer = UltraComposer(); + builder.add_public_variable(FF(1)); + + auto instance = composer.create_instance(builder); + auto instances = std::vector>{ accumulator, instance }; + auto folding_prover = composer.create_folding_prover(instances, composer.commitment_key); + auto folding_verifier = composer.create_folding_verifier(); + + auto proof = folding_prover.fold_instances(); + auto res = folding_verifier.verify_folding_proof(proof.folding_data); + EXPECT_EQ(res, true); +} + } // namespace protogalaxy_tests \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_composer.hpp b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_composer.hpp index 0d4dd752d08..7daaab2e1d3 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_composer.hpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_composer.hpp @@ -90,21 +90,17 @@ template class UltraComposer_ { */ MergeVerifier_ create_merge_verifier() { return MergeVerifier_(); } - ProtoGalaxyProver_ create_folding_prover(const std::vector>& instances) + ProtoGalaxyProver_ create_folding_prover(const std::vector>& instances, + const std::shared_ptr& commitment_key) { - ProverInstances insts(instances); - ProtoGalaxyProver_ output_state(insts); + ProtoGalaxyProver_ output_state(instances, commitment_key); return output_state; }; - ProtoGalaxyVerifier_ create_folding_verifier( - const std::vector>& instances) + ProtoGalaxyVerifier_ create_folding_verifier() { - std::vector> vks; - for (const auto& inst : instances) { - vks.emplace_back(inst->verification_key); - } - VerifierInstances insts(vks); + + auto insts = VerifierInstances(); ProtoGalaxyVerifier_ output_state(insts); return output_state; From c7f1878777bf76dbfd451761dbe6dc78903e45e2 Mon Sep 17 00:00:00 2001 From: Charlie Lye Date: Fri, 8 Dec 2023 12:12:25 +0000 Subject: [PATCH 13/35] feat: New install script and container wrappers. (#3617) As title. --- aztec-up/.gitignore | 3 + aztec-up/README.md | 30 ++++ aztec-up/bin/.aztec-run | 99 +++++++++++++ aztec-up/bin/aztec | 4 + aztec-up/bin/aztec-cli | 9 ++ aztec-up/bin/aztec-install | 152 ++++++++++++++++++++ aztec-up/bin/aztec-nargo | 4 + aztec-up/bin/aztec-sandbox | 11 ++ aztec-up/bin/aztec-up | 5 + aztec-up/bin/docker-compose.yml | 34 +++++ aztec-up/deploy.sh | 23 +++ aztec-up/terraform/main.tf | 88 ++++++++++++ yarn-project/aztec-sandbox/src/bin/index.ts | 14 +- yarn-project/cli/src/index.ts | 16 ++- 14 files changed, 489 insertions(+), 3 deletions(-) create mode 100644 aztec-up/.gitignore create mode 100644 aztec-up/README.md create mode 100755 aztec-up/bin/.aztec-run create mode 100755 aztec-up/bin/aztec create mode 100755 aztec-up/bin/aztec-cli create mode 100755 aztec-up/bin/aztec-install create mode 100755 aztec-up/bin/aztec-nargo create mode 100755 aztec-up/bin/aztec-sandbox create mode 100755 aztec-up/bin/aztec-up create mode 100644 aztec-up/bin/docker-compose.yml create mode 100755 aztec-up/deploy.sh create mode 100644 aztec-up/terraform/main.tf diff --git a/aztec-up/.gitignore b/aztec-up/.gitignore new file mode 100644 index 00000000000..5fd438ece3e --- /dev/null +++ b/aztec-up/.gitignore @@ -0,0 +1,3 @@ +.terraform +.terraform* +.DS_Store \ No newline at end of file diff --git a/aztec-up/README.md b/aztec-up/README.md new file mode 100644 index 00000000000..630d0e0fc5c --- /dev/null +++ b/aztec-up/README.md @@ -0,0 +1,30 @@ +# The Aztec Installation Script + +``` +bash -i <(curl -s install.aztec.network) +``` + +That is all. + +This will install into `~/.aztec/bin` a collection of scripts to help running aztec containers, and will update +a users `PATH` variable in their shell startup script so they can be found. + +- `aztec` - The infrastructure container. +- `aztec-cli` - A command line tool for interacting with infrastructure. +- `aztec-nargo` - A build of `nargo` from `noir` that is guaranteed to be version aligned. Provides compiler, lsp and more. +- `aztec-sandbox` - A wrapper around docker-compose that launches services needed for sandbox testing. +- `aztec-up` - A tool to upgrade the aztec toolchain to the latest, or specific versions. + +After installed, you can use `aztec-up` to upgrade or install specific versions. + +``` +VERSION=master aztec-up +``` + +This will install the container built from master branch. + +``` +VERSION=v1.2.3 aztec-up +``` + +This will install tagged release version 1.2.3. diff --git a/aztec-up/bin/.aztec-run b/aztec-up/bin/.aztec-run new file mode 100755 index 00000000000..c338bede2e1 --- /dev/null +++ b/aztec-up/bin/.aztec-run @@ -0,0 +1,99 @@ +#!/usr/bin/env bash +# The script starts a Docker container passing any commands and arguments to the command running inside the container. +# It handles mounting paths into the container. +# It handles networking comms back to the host. +set -euo pipefail + +IMAGE=${1:-} +shift + +VERSION=${VERSION:-"latest"} + +# Any host bindings we might send to the container. +DOCKER_HOST_BINDS="" + +# Volumes to pass to the container. +DOCKER_VOLUME="" + +if ! command -v docker &> /dev/null; then + echo "No docker found." + exit 1 +fi + +# Colors. +yellow="\033[33m" +reset="\033[0m" + +# Set up host.docker.internal alias on Linux, just like it is on mac. +UNAME=$(uname -s) +if [ "$UNAME" == "Linux" ]; then + if docker info 2>/dev/null | grep -q rootless; then + # We're in rootless docker. Probe for the host ip and use that. + ip=$(hostname -I | head | tr -d ' ') + echo -e "${yellow}WARNING: Running within rootless docker. Using $ip as host ip. Ensure listening services are listening on this interface.${reset}" + DOCKER_HOST_BINDS="$DOCKER_HOST_BINDS --add-host host.docker.internal:$ip" + else + DOCKER_HOST_BINDS="$DOCKER_HOST_BINDS --add-host host.docker.internal:host-gateway" + fi +fi + +# Build a list of mount points +function add_mount() { + DIR="${1:-}" + + # Grab its dirname if its a file. + if [ -f "$DIR" ]; then + DIR=$(dirname "$DIR") + fi + + if [ ! -d "$DIR" ]; then + return + fi + + # Check if it's already been added. + REALDIR=$(realpath $DIR) + if [[ "$DOCKER_VOLUME" =~ "$REALDIR:" ]]; then + return + fi + + DOCKER_VOLUME="$DOCKER_VOLUME -v $REALDIR:$REALDIR" +} + +# Always mount the CWD into the container. +add_mount "$PWD" + +# Substitute any references to localhost with our host gateway. +args=("$@") +for i in "${!args[@]}"; do + args[$i]=${args[$i]//localhost/host.docker.internal} +done + +# Check if it's either a filename or a directory that exists outside the CWD. +# If it is then mount inside the container. +# NOTE: This won't work with assignement-style flags, e.g. --outdir=/foo +for i in "${!args[@]}"; do + arg=${args[$i]} + if [[ -f "$arg" || -d "$arg" && $(realpath $arg) != ${PWD}* ]]; then + add_mount "$arg" + fi +done + +DOCKER_ENV="" +for env in ${ENV_VARS_TO_INJECT:-}; do + # First substitute any reference to localhost with our host gateway. + env=${env//localhost/host.docker.internal} + # Inject into container. + DOCKER_ENV+="-e $env:${!env:-} " +done + +DOCKER_VOLUME="$DOCKER_VOLUME -v cache:/cache" + +docker run \ + -ti \ + --rm \ + --user $(id -u):$(id -g) \ + --workdir "$PWD" \ + $DOCKER_HOST_BINDS \ + $DOCKER_ENV \ + $DOCKER_VOLUME \ + $IMAGE:$VERSION ${args[@]:-} diff --git a/aztec-up/bin/aztec b/aztec-up/bin/aztec new file mode 100755 index 00000000000..30ef8a66fab --- /dev/null +++ b/aztec-up/bin/aztec @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +set -euo pipefail + +$(dirname $0)/.aztec-run aztecprotocol/aztec-sandbox $@ \ No newline at end of file diff --git a/aztec-up/bin/aztec-cli b/aztec-up/bin/aztec-cli new file mode 100755 index 00000000000..7d8b75f4146 --- /dev/null +++ b/aztec-up/bin/aztec-cli @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +# TODO: Make compile command always be wasm. Or put nargo in container. Or probe. +# TODO: Make unbox fail if trying to unbox outside of the cwd. +set -euo pipefail + +export ENV_VARS_TO_INJECT="PXE_URL PRIVATE_KEY DEBUG" +export PXE_URL=${PXE_URL:-"http://host.docker.internal:8080"} + +$(dirname $0)/.aztec-run aztecprotocol/cli $@ \ No newline at end of file diff --git a/aztec-up/bin/aztec-install b/aztec-up/bin/aztec-install new file mode 100755 index 00000000000..653e80e9886 --- /dev/null +++ b/aztec-up/bin/aztec-install @@ -0,0 +1,152 @@ +#!/bin/bash +set -euo pipefail + +# Colors +g="\033[32m" # Green +y="\033[33m" # Yellow +b="\033[34m" # Blue +p="\033[35m" # Purple +r="\033[0m" # Reset +bold="\033[1m" + +# Function to replace characters and add color +function print_colored() { + local b=$'\033[34m' # Blue + local y=$'\033[33m' # Yellow + local r=$'\033[0m' # Reset + echo "$1" | sed -E "s/(█+)/${b}\1${y}/g" +} + +function title() { + echo + print_colored " █████╗ ███████╗████████╗███████╗ ██████╗" + print_colored "██╔══██╗╚══███╔╝╚══██╔══╝██╔════╝██╔════╝" + print_colored "███████║ ███╔╝ ██║ █████╗ ██║" + print_colored "██╔══██║ ███╔╝ ██║ ██╔══╝ ██║" + print_colored "██║ ██║███████╗ ██║ ███████╗╚██████╗" + print_colored "╚═╝ ╚═╝╚══════╝ ╚═╝ ╚══════╝ ╚═════╝" + echo -e "${r}" + echo -e "Welcome to the ${bold}${b}Aztec${r} installer! Your journey into blockchain privacy begins... ${bold}${p}now${r}." + echo -e "We presently leverage docker to simplify releases of our complex project." + echo -e "Please ensure it's installed for your platform: https://docs.docker.com/engine/install" + echo + echo -e "This will install the following scripts and update your PATH if necessary:" + echo -e " ${bold}${g}aztec${r} - launches various infrastructure subsystems (sequencer, prover, pxe, etc)." + echo -e " ${bold}${g}aztec-cli${r} - a command line tool for interfacing and experimenting with infrastructure." + echo -e " ${bold}${g}aztec-nargo${r} - aztec's build of nargo, the noir compiler toolchain." + echo -e " ${bold}${g}aztec-sandbox${r} - a wrapper around docker-compose that launches services needed for sandbox testing." + echo -e " ${bold}${g}aztec-up${r} - a tool to upgrade the aztec toolchain to the latest, or specific versions." + echo + read -p "Do you wish to continue? (y/n)" -n 1 -r + echo + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + exit 0 + fi +} + +function info { + echo -e "${g}$1${r}" +} + +function warn { + echo -e "${y}$1${r}" +} + +AZTEC_PATH=$HOME/.aztec +BIN_PATH=$AZTEC_PATH/bin + +# Define version if specified, otherwise set to "latest". +VERSION=${VERSION:-"latest"} +INSTALL_HOST=install.aztec.network.s3-website.eu-west-2.amazonaws.com + +[ -z "${SKIP_TITLE:-}" ] && title + +# Check if Docker is available. +if ! command -v docker &>/dev/null; then + warn "Docker is not installed. Please install Docker and try again." + exit 1 +fi + +# Check if Docker is running. +if ! docker info &>/dev/null; then + warn "Docker is not running. Please start Docker and try again." + exit 1 +fi + +if ! docker compose &>/dev/null && ! command -v docker-compose &>/dev/null; then + warn "WARNING: 'docker compose' not supported and docker-compose not found." + warn "Continuing installation, but aztec-sandbox will not work." +fi + +# Create a "hidden" `$HOME/.aztec` dir, so as not to clutter the user's cwd. +rm -f $BIN_PATH/* && mkdir -p $BIN_PATH + +# Download containers from dockerhub. Tag them as latest. +function pull_container { + docker pull aztecprotocol/$1:$VERSION + + # If not latest, retag to be latest so it runs from scripts. + if [ $VERSION != "latest" ]; then + docker tag aztecprotocol/$1:$VERSION aztecprotocol/$1:latest + fi +} + +info "Pulling aztec version $VERSION..." +pull_container aztec-sandbox +pull_container cli +pull_container noir + +# Download the Docker Compose file. Used by aztec-start. +curl -fsSL http://$INSTALL_HOST/docker-compose.yml -o $BIN_PATH/docker-compose.yml + +function install_bin { + curl -fsSL http://$INSTALL_HOST/$1 -o $BIN_PATH/$1 + chmod +x $BIN_PATH/$1 + echo "Installed: $BIN_PATH/$1" +} + +info "Installing scripts in $BIN_PATH..." +install_bin .aztec-run +install_bin aztec +install_bin aztec-cli +install_bin aztec-sandbox +install_bin aztec-up +install_bin aztec-nargo + +function update_path_env_var { + TARGET_DIR="${1}" + # Check if the target directory is in the user's PATH. + if [[ ":$PATH:" != *":$TARGET_DIR:"* ]]; then + # Determine the user's shell. + SHELL_PROFILE="" + case $SHELL in + */bash) + SHELL_PROFILE="$HOME/.bashrc" + ;; + */zsh) + SHELL_PROFILE="$HOME/.zshrc" + ;; + # Add other shells as needed + *) + echo "Unsupported shell: $SHELL" + return + ;; + esac + # Inform the user about the change and ask for confirmation + warn "The directory $TARGET_DIR is not in your PATH." + read -p "Add it to $SHELL_PROFILE to make the aztec binaries accessible? (y/n)" -n 1 -r + echo + if [[ $REPLY =~ ^[Yy]$ ]]; then + # Add the target directory to the user's PATH in their profile. + echo "export PATH=\$PATH:$TARGET_DIR" >> "$SHELL_PROFILE" + info "Done! Starting fresh shell..." + $SHELL + else + warn "Skipped updating PATH. You might need to add $TARGET_DIR to your PATH manually to use the binary." + fi + fi +} + +update_path_env_var $BIN_PATH + +info "Done!" \ No newline at end of file diff --git a/aztec-up/bin/aztec-nargo b/aztec-up/bin/aztec-nargo new file mode 100755 index 00000000000..5fdee793d7d --- /dev/null +++ b/aztec-up/bin/aztec-nargo @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +set -euo pipefail + +$(dirname $0)/.aztec-run aztecprotocol/noir $@ \ No newline at end of file diff --git a/aztec-up/bin/aztec-sandbox b/aztec-up/bin/aztec-sandbox new file mode 100755 index 00000000000..ccbe9747045 --- /dev/null +++ b/aztec-up/bin/aztec-sandbox @@ -0,0 +1,11 @@ +#!/bin/bash +set -euo pipefail + +# Change working dir, so relative volume mounts are in the right place. +cd ~/.aztec + +# Favour 'docker compose', falling back on docker-compose. +CMD="docker compose" +$CMD &>/dev/null || CMD="docker-compose" + +$CMD -f ~/.aztec/bin/docker-compose.yml up \ No newline at end of file diff --git a/aztec-up/bin/aztec-up b/aztec-up/bin/aztec-up new file mode 100755 index 00000000000..d3b88660090 --- /dev/null +++ b/aztec-up/bin/aztec-up @@ -0,0 +1,5 @@ +#!/bin/bash +set -euo pipefail + +export SKIP_TITLE=1 +bash -i <(curl -s http://install.aztec.network) \ No newline at end of file diff --git a/aztec-up/bin/docker-compose.yml b/aztec-up/bin/docker-compose.yml new file mode 100644 index 00000000000..735466e3904 --- /dev/null +++ b/aztec-up/bin/docker-compose.yml @@ -0,0 +1,34 @@ +version: '3' +services: + ethereum: + image: ghcr.io/foundry-rs/foundry@sha256:29ba6e34379e79c342ec02d437beb7929c9e254261e8032b17e187be71a2609f + entrypoint: > + sh -c ' + if [ -n "$FORK_BLOCK_NUMBER" ] && [ -n "$FORK_URL" ]; then + exec anvil -p 8545 --host 0.0.0.0 --chain-id 31337 --silent --fork-url "$FORK_URL" --fork-block-number "$FORK_BLOCK_NUMBER" + elif [ -n "$FORK_URL" ]; then + exec anvil -p 8545 --host 0.0.0.0 --chain-id 31337 --silent --fork-url "$FORK_URL" + else + exec anvil -p 8545 --host 0.0.0.0 --chain-id 31337 --silent + fi' + ports: + - '${SANDBOX_ANVIL_PORT:-8545}:8545' + + aztec: + image: 'aztecprotocol/aztec-sandbox' + ports: + - '${SANDBOX_AZTEC_NODE_PORT:-8079}:8079' + - '${SANDBOX_PXE_PORT:-8080}:8080' + environment: + DEBUG: # Loaded from the user shell if explicitly set + HOST_WORKDIR: '${PWD}' # Loaded from the user shell to show log files absolute path in host + ETHEREUM_HOST: http://ethereum:8545 + CHAIN_ID: 31337 + ARCHIVER_POLLING_INTERVAL_MS: 50 + P2P_BLOCK_CHECK_INTERVAL_MS: 50 + SEQ_TX_POLLING_INTERVAL_MS: 50 + WS_BLOCK_CHECK_INTERVAL_MS: 50 + PXE_BLOCK_POLLING_INTERVAL_MS: 50 + ARCHIVER_VIEM_POLLING_INTERVAL_MS: 500 + volumes: + - ./log:/usr/src/yarn-project/aztec-sandbox/log:rw diff --git a/aztec-up/deploy.sh b/aztec-up/deploy.sh new file mode 100755 index 00000000000..14f89b8e8db --- /dev/null +++ b/aztec-up/deploy.sh @@ -0,0 +1,23 @@ +set -e + +BRANCH=$1 + +export TF_VAR_BRANCH=$BRANCH + +# Downloads and installs `terraform` if it's not installed. +if [ ! -f /usr/local/bin/terraform ]; then + cd $HOME + TERRAFORM_VERSION=1.5.2 + curl -sSL https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_linux_amd64.zip -o terraform.zip + sudo apt install -y unzip + unzip terraform.zip + sudo mv terraform /usr/local/bin/ + rm terraform.zip + cd - +fi + +echo "Initializing terraform" +terraform init -input=false -backend-config="key=aztec-sandbox-website/$BRANCH" + +echo "Applying terraform config" +terraform apply -input=false -auto-approve \ No newline at end of file diff --git a/aztec-up/terraform/main.tf b/aztec-up/terraform/main.tf new file mode 100644 index 00000000000..2465082e3fa --- /dev/null +++ b/aztec-up/terraform/main.tf @@ -0,0 +1,88 @@ +terraform { + backend "s3" { + bucket = "aztec-terraform" + region = "eu-west-2" + key = "aztec-up" + } + required_providers { + aws = { + source = "hashicorp/aws" + version = "5.29.0" + } + } +} + +# Define provider and region +provider "aws" { + region = "eu-west-2" +} + +data "terraform_remote_state" "aztec2_iac" { + backend = "s3" + config = { + bucket = "aztec-terraform" + key = "aztec2/iac" + region = "eu-west-2" + } +} + +# Create the website S3 bucket +resource "aws_s3_bucket" "install_bucket" { + bucket = "install.aztec.network" +} + +resource "aws_s3_bucket_website_configuration" "website_bucket" { + bucket = aws_s3_bucket.install_bucket.id + + index_document { + suffix = "aztec-install" + } +} + +resource "aws_s3_bucket_public_access_block" "install_bucket_public_access" { + bucket = aws_s3_bucket.install_bucket.id + + block_public_acls = false + ignore_public_acls = false + block_public_policy = false + restrict_public_buckets = false +} + +resource "aws_s3_bucket_policy" "install_bucket_policy" { + bucket = aws_s3_bucket.install_bucket.id + + policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Effect = "Allow" + Principal = "*" + Action = "s3:GetObject" + Resource = "arn:aws:s3:::${aws_s3_bucket.install_bucket.id}/*" + } + ] + }) +} + +# Upload files to s3 bucket if changes were detected +resource "null_resource" "upload_public_directory" { + triggers = { + always_run = "${timestamp()}" + } + + provisioner "local-exec" { + command = "aws s3 sync ../bin s3://${aws_s3_bucket.install_bucket.id}/" + } +} + +resource "aws_route53_record" "subdomain_record" { + zone_id = data.terraform_remote_state.aztec2_iac.outputs.aws_route53_zone_id + name = "install.aztec.network" + type = "A" + + alias { + name = "${aws_s3_bucket_website_configuration.website_bucket.website_domain}" + zone_id = "${aws_s3_bucket.install_bucket.hosted_zone_id}" + evaluate_target_health = true + } +} diff --git a/yarn-project/aztec-sandbox/src/bin/index.ts b/yarn-project/aztec-sandbox/src/bin/index.ts index 71cf982e046..72a9413454d 100644 --- a/yarn-project/aztec-sandbox/src/bin/index.ts +++ b/yarn-project/aztec-sandbox/src/bin/index.ts @@ -10,6 +10,7 @@ import { NoirCommit } from '@aztec/noir-compiler/versions'; import { BootstrapNode, getP2PConfigEnvVars } from '@aztec/p2p'; import { GrumpkinScalar, PXEService, createPXERpcServer } from '@aztec/pxe'; +import { resolve as dnsResolve } from 'dns'; import { readFileSync } from 'fs'; import http from 'http'; import { dirname, resolve } from 'path'; @@ -30,8 +31,19 @@ enum SandboxMode { P2PBootstrap = 'p2p-bootstrap', } +/** + * If we can successfully resolve 'host.docker.internal', then we are running in a container, and we should treat + * localhost as being host.docker.internal. + */ +function getLocalhost() { + return new Promise(resolve => + dnsResolve('host.docker.internal', err => (err ? resolve('localhost') : resolve('host.docker.internal'))), + ); +} + +const LOCALHOST = await getLocalhost(); const { - AZTEC_NODE_URL = 'http://localhost:8079', + AZTEC_NODE_URL = `http://${LOCALHOST}:8079`, AZTEC_NODE_PORT = 8079, PXE_PORT = 8080, MODE = 'sandbox', diff --git a/yarn-project/cli/src/index.ts b/yarn-project/cli/src/index.ts index 6f44a6ca8b3..27a7275880f 100644 --- a/yarn-project/cli/src/index.ts +++ b/yarn-project/cli/src/index.ts @@ -4,6 +4,7 @@ import { fileURLToPath } from '@aztec/foundation/url'; import { addNoirCompilerCommanderActions } from '@aztec/noir-compiler/cli'; import { Command, Option } from 'commander'; +import { resolve as dnsResolve } from 'dns'; import { readFileSync } from 'fs'; import { dirname, resolve } from 'path'; @@ -23,7 +24,18 @@ import { parseTxHash, } from './utils.js'; -const { ETHEREUM_HOST = 'http://localhost:8545', PRIVATE_KEY, API_KEY } = process.env; +/** + * If we can successfully resolve 'host.docker.internal', then we are running in a container, and we should treat + * localhost as being host.docker.internal. + */ +function getLocalhost() { + return new Promise(resolve => + dnsResolve('host.docker.internal', err => (err ? resolve('localhost') : resolve('host.docker.internal'))), + ); +} + +const LOCALHOST = await getLocalhost(); +const { ETHEREUM_HOST = `http://${LOCALHOST}:8545`, PRIVATE_KEY, API_KEY } = process.env; /** * Returns commander program that defines the CLI. @@ -42,7 +54,7 @@ export function getProgram(log: LogFn, debugLogger: DebugLogger): Command { const pxeOption = new Option('-u, --rpc-url ', 'URL of the PXE') .env('PXE_URL') - .default('http://localhost:8080') + .default(`http://${LOCALHOST}:8080`) .makeOptionMandatory(true); const createPrivateKeyOption = (description: string, mandatory: boolean) => From cea862dd7feec714a34eba6a3cf7a2a174a59a1b Mon Sep 17 00:00:00 2001 From: Charlie Lye Date: Sun, 10 Dec 2023 12:10:57 +0000 Subject: [PATCH 14/35] fix: Top level init bb.js, but better scoped imports to not incur cost too early (#3629) Related to this issue: https://github.com/AztecProtocol/aztec-packages/issues/3618 Gets `aztec-cli help` down to 0.01s!!!! --- barretenberg/ts/scripts/cjs_postprocess.sh | 2 + barretenberg/ts/src/barretenberg/index.ts | 14 +- yarn-project/aztec.js/src/api/init.ts | 11 +- yarn-project/aztec.js/src/index.ts | 10 +- .../barretenberg/crypto/aes128/index.test.ts | 5 +- .../crypto/grumpkin/index.test.ts | 4 +- yarn-project/cli/src/cmds/add_note.ts | 2 +- yarn-project/cli/src/index.ts | 5 +- yarn-project/cli/src/parse_args.ts | 248 ++++++++++++++++++ yarn-project/cli/src/test/utils.test.ts | 3 +- yarn-project/cli/src/utils.ts | 234 +---------------- yarn-project/end-to-end/src/shared/browser.ts | 5 +- yarn-project/foundation/src/abi/abi_coder.ts | 2 +- yarn-project/foundation/src/abi/decoder.ts | 4 +- yarn-project/foundation/src/abi/encoder.ts | 4 +- .../foundation/src/abi/function_selector.ts | 8 +- yarn-project/foundation/src/abi/utils.ts | 2 +- .../foundation/src/eth-address/index.ts | 3 +- yarn-project/foundation/src/fields/fields.ts | 2 +- yarn-project/types/src/tx/tx_hash.ts | 5 +- 20 files changed, 300 insertions(+), 273 deletions(-) create mode 100644 yarn-project/cli/src/parse_args.ts diff --git a/barretenberg/ts/scripts/cjs_postprocess.sh b/barretenberg/ts/scripts/cjs_postprocess.sh index ccfcfc2d8a2..8a805bcdd44 100755 --- a/barretenberg/ts/scripts/cjs_postprocess.sh +++ b/barretenberg/ts/scripts/cjs_postprocess.sh @@ -11,4 +11,6 @@ DIR="./dest/node-cjs" for FILE in $(find "$DIR" -name "*.js"); do # Use sed to replace 'import.meta.url' with '""' sed -i.bak 's/import\.meta\.url/""/g' "$FILE" && rm "$FILE.bak" + # Use sed to remove any lines postfixed // POSTPROCESS ESM ONLY + sed -i.bak '/\/\/ POSTPROCESS ESM ONLY$/d' "$FILE" && rm "$FILE.bak" done \ No newline at end of file diff --git a/barretenberg/ts/src/barretenberg/index.ts b/barretenberg/ts/src/barretenberg/index.ts index 6019b24e88f..6b00a9b752a 100644 --- a/barretenberg/ts/src/barretenberg/index.ts +++ b/barretenberg/ts/src/barretenberg/index.ts @@ -65,7 +65,7 @@ export class BarretenbergSync extends BarretenbergApiSync { static getSingleton() { if (!barretenbergSyncSingleton) { - throw new Error('Initialise first via initSingleton().'); + throw new Error('First call BarretenbergSync.initSingleton() on @aztec/bb.js module.'); } return barretenbergSyncSingleton; } @@ -75,10 +75,8 @@ export class BarretenbergSync extends BarretenbergApiSync { } } -// If we're loading this module in a test environment, just init the singleton immediately for convienience. -if (process.env.NODE_ENV === 'test') { - // Need to ignore for cjs build. - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - await BarretenbergSync.initSingleton(); -} +// If we're in ESM environment, use top level await. CJS users need to call it manually. +// Need to ignore for cjs build. +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore +await BarretenbergSync.initSingleton(); // POSTPROCESS ESM ONLY diff --git a/yarn-project/aztec.js/src/api/init.ts b/yarn-project/aztec.js/src/api/init.ts index 2b5203c9d0b..9654b9c8042 100644 --- a/yarn-project/aztec.js/src/api/init.ts +++ b/yarn-project/aztec.js/src/api/init.ts @@ -1 +1,10 @@ -export { init as initAztecJs } from '@aztec/foundation/crypto'; +import { init } from '@aztec/foundation/crypto'; + +/** + * This should only be needed to be called in CJS environments that don't have top level await. + * Initializes any asynchronous subsystems required to use the library. + * At time of writing, this is just our foundation crypto lib. + */ +export async function initAztecJs() { + await init(); +} diff --git a/yarn-project/aztec.js/src/index.ts b/yarn-project/aztec.js/src/index.ts index 38f1bc8970f..353457cd6f5 100644 --- a/yarn-project/aztec.js/src/index.ts +++ b/yarn-project/aztec.js/src/index.ts @@ -16,6 +16,8 @@ * import { AztecAddress } from '@aztec/aztec.js/aztec_address'; * import { EthAddress } from '@aztec/aztec.js/eth_address'; * ``` + * + * TODO: Ultimately reimplement this mega exporter by mega exporting a granular api (then deprecate it). */ export { WaitOpts, @@ -118,7 +120,7 @@ export { // External devs will almost certainly have their own methods of doing these things. // If we want to use them in our own "aztec.js consuming code", import them from foundation as needed. export { ContractArtifact, FunctionArtifact, encodeArguments } from '@aztec/foundation/abi'; -export { sha256, init } from '@aztec/foundation/crypto'; +export { sha256 } from '@aztec/foundation/crypto'; export { DebugLogger, createDebugLogger, onLog } from '@aztec/foundation/log'; export { retry, retryUntil } from '@aztec/foundation/retry'; export { sleep } from '@aztec/foundation/sleep'; @@ -127,6 +129,7 @@ export { fileURLToPath } from '@aztec/foundation/url'; export { to2Fields, toBigInt } from '@aztec/foundation/serialize'; export { toBigIntBE } from '@aztec/foundation/bigint-buffer'; export { makeFetch } from '@aztec/foundation/json-rpc/client'; +export { FieldsOf } from '@aztec/foundation/types'; export { DeployL1Contracts, @@ -135,4 +138,7 @@ export { deployL1Contracts, } from '@aztec/ethereum'; -export { FieldsOf } from '@aztec/foundation/types'; +// Start of section that exports public api via granular api. +// Here you *can* do `export *` as the granular api defacto exports things explicitly. +// This entire index file will be deprecated at some point after we're satisfied. +export * from './api/init.js'; diff --git a/yarn-project/circuits.js/src/barretenberg/crypto/aes128/index.test.ts b/yarn-project/circuits.js/src/barretenberg/crypto/aes128/index.test.ts index df34d06d305..9b8afc328e2 100644 --- a/yarn-project/circuits.js/src/barretenberg/crypto/aes128/index.test.ts +++ b/yarn-project/circuits.js/src/barretenberg/crypto/aes128/index.test.ts @@ -1,5 +1,3 @@ -import { init } from '@aztec/foundation/crypto'; - import { createCipheriv, createDecipheriv, randomBytes } from 'crypto'; import { Aes128 } from './index.js'; @@ -7,8 +5,7 @@ import { Aes128 } from './index.js'; describe('aes128', () => { let aes128!: Aes128; - beforeAll(async () => { - await init(); + beforeAll(() => { aes128 = new Aes128(); }); diff --git a/yarn-project/circuits.js/src/barretenberg/crypto/grumpkin/index.test.ts b/yarn-project/circuits.js/src/barretenberg/crypto/grumpkin/index.test.ts index 671c019291b..154ab39075f 100644 --- a/yarn-project/circuits.js/src/barretenberg/crypto/grumpkin/index.test.ts +++ b/yarn-project/circuits.js/src/barretenberg/crypto/grumpkin/index.test.ts @@ -1,4 +1,3 @@ -import { init } from '@aztec/foundation/crypto'; import { createDebugLogger } from '@aztec/foundation/log'; import { GrumpkinScalar, Point } from '../../../index.js'; @@ -9,8 +8,7 @@ const debug = createDebugLogger('bb:grumpkin_test'); describe('grumpkin', () => { let grumpkin!: Grumpkin; - beforeAll(async () => { - await init(); + beforeAll(() => { grumpkin = new Grumpkin(); }); diff --git a/yarn-project/cli/src/cmds/add_note.ts b/yarn-project/cli/src/cmds/add_note.ts index 64340034370..33ad5a52f80 100644 --- a/yarn-project/cli/src/cmds/add_note.ts +++ b/yarn-project/cli/src/cmds/add_note.ts @@ -3,7 +3,7 @@ import { DebugLogger } from '@aztec/foundation/log'; import { ExtendedNote, Note, TxHash } from '@aztec/types'; import { createCompatibleClient } from '../client.js'; -import { parseFields } from '../utils.js'; +import { parseFields } from '../parse_args.js'; /** * diff --git a/yarn-project/cli/src/index.ts b/yarn-project/cli/src/index.ts index 27a7275880f..08fd0c44b5e 100644 --- a/yarn-project/cli/src/index.ts +++ b/yarn-project/cli/src/index.ts @@ -1,4 +1,3 @@ -import { initAztecJs } from '@aztec/aztec.js/init'; import { DebugLogger, LogFn } from '@aztec/foundation/log'; import { fileURLToPath } from '@aztec/foundation/url'; import { addNoirCompilerCommanderActions } from '@aztec/noir-compiler/cli'; @@ -22,7 +21,7 @@ import { parsePublicKey, parseSaltFromHexString, parseTxHash, -} from './utils.js'; +} from './parse_args.js'; /** * If we can successfully resolve 'host.docker.internal', then we are running in a container, and we should treat @@ -63,8 +62,6 @@ export function getProgram(log: LogFn, debugLogger: DebugLogger): Command { .argParser(parsePrivateKey) .makeOptionMandatory(mandatory); - program.hook('preAction', initAztecJs); - program .command('deploy-l1-contracts') .description('Deploys all necessary Ethereum contracts for Aztec.') diff --git a/yarn-project/cli/src/parse_args.ts b/yarn-project/cli/src/parse_args.ts new file mode 100644 index 00000000000..e2641005cd2 --- /dev/null +++ b/yarn-project/cli/src/parse_args.ts @@ -0,0 +1,248 @@ +import { FunctionSelector } from '@aztec/aztec.js/abi'; +import { AztecAddress } from '@aztec/aztec.js/aztec_address'; +import { EthAddress } from '@aztec/aztec.js/eth_address'; +import { Fr, GrumpkinScalar, Point } from '@aztec/aztec.js/fields'; +import { LogId } from '@aztec/aztec.js/log_id'; +import { TxHash } from '@aztec/aztec.js/tx_hash'; + +import { InvalidArgumentError } from 'commander'; + +/** + * Removes the leading 0x from a hex string. If no leading 0x is found the string is returned unchanged. + * @param hex - A hex string + * @returns A new string with leading 0x removed + */ +const stripLeadingHex = (hex: string) => { + if (hex.length > 2 && hex.startsWith('0x')) { + return hex.substring(2); + } + return hex; +}; + +/** + * Parses a hex encoded string to an Fr integer to be used as salt + * @param str - Hex encoded string + * @returns A integer to be used as salt + */ +export function parseSaltFromHexString(str: string): Fr { + const hex = stripLeadingHex(str); + + // ensure it's a hex string + if (!hex.match(/^[0-9a-f]+$/i)) { + throw new InvalidArgumentError('Invalid hex string'); + } + + // pad it so that we may read it as a buffer. + // Buffer needs _exactly_ two hex characters per byte + const padded = hex.length % 2 === 1 ? '0' + hex : hex; + + // finally, turn it into an integer + return Fr.fromBuffer(Buffer.from(padded, 'hex')); +} + +/** + * Parses an AztecAddress from a string. + * @param address - A serialized Aztec address + * @returns An Aztec address + * @throws InvalidArgumentError if the input string is not valid. + */ +export function parseAztecAddress(address: string): AztecAddress { + try { + return AztecAddress.fromString(address); + } catch { + throw new InvalidArgumentError(`Invalid address: ${address}`); + } +} + +/** + * Parses an Ethereum address from a string. + * @param address - A serialized Ethereum address + * @returns An Ethereum address + * @throws InvalidArgumentError if the input string is not valid. + */ +export function parseEthereumAddress(address: string): EthAddress { + try { + return EthAddress.fromString(address); + } catch { + throw new InvalidArgumentError(`Invalid address: ${address}`); + } +} + +/** + * Parses an AztecAddress from a string. + * @param address - A serialized Aztec address + * @returns An Aztec address + * @throws InvalidArgumentError if the input string is not valid. + */ +export function parseOptionalAztecAddress(address: string): AztecAddress | undefined { + if (!address) { + return undefined; + } + return parseAztecAddress(address); +} + +/** + * Parses an optional log ID string into a LogId object. + * + * @param logId - The log ID string to parse. + * @returns The parsed LogId object, or undefined if the log ID is missing or empty. + */ +export function parseOptionalLogId(logId: string): LogId | undefined { + if (!logId) { + return undefined; + } + return LogId.fromString(logId); +} + +/** + * Parses a selector from a string. + * @param selector - A serialized selector. + * @returns A selector. + * @throws InvalidArgumentError if the input string is not valid. + */ +export function parseOptionalSelector(selector: string): FunctionSelector | undefined { + if (!selector) { + return undefined; + } + try { + return FunctionSelector.fromString(selector); + } catch { + throw new InvalidArgumentError(`Invalid selector: ${selector}`); + } +} + +/** + * Parses a string into an integer or returns undefined if the input is falsy. + * + * @param value - The string to parse into an integer. + * @returns The parsed integer, or undefined if the input string is falsy. + * @throws If the input is not a valid integer. + */ +export function parseOptionalInteger(value: string): number | undefined { + if (!value) { + return undefined; + } + const parsed = Number(value); + if (!Number.isInteger(parsed)) { + throw new InvalidArgumentError('Invalid integer.'); + } + return parsed; +} + +/** + * Parses a TxHash from a string. + * @param txHash - A transaction hash + * @returns A TxHash instance + * @throws InvalidArgumentError if the input string is not valid. + */ +export function parseTxHash(txHash: string): TxHash { + try { + return TxHash.fromString(txHash); + } catch { + throw new InvalidArgumentError(`Invalid transaction hash: ${txHash}`); + } +} + +/** + * Parses an optional TxHash from a string. + * Calls parseTxHash internally. + * @param txHash - A transaction hash + * @returns A TxHash instance, or undefined if the input string is falsy. + * @throws InvalidArgumentError if the input string is not valid. + */ +export function parseOptionalTxHash(txHash: string): TxHash | undefined { + if (!txHash) { + return undefined; + } + return parseTxHash(txHash); +} + +/** + * Parses a public key from a string. + * @param publicKey - A public key + * @returns A Point instance + * @throws InvalidArgumentError if the input string is not valid. + */ +export function parsePublicKey(publicKey: string): Point { + try { + return Point.fromString(publicKey); + } catch (err) { + throw new InvalidArgumentError(`Invalid public key: ${publicKey}`); + } +} + +/** + * Parses a partial address from a string. + * @param address - A partial address + * @returns A Fr instance + * @throws InvalidArgumentError if the input string is not valid. + */ +export function parsePartialAddress(address: string): Fr { + try { + return Fr.fromString(address); + } catch (err) { + throw new InvalidArgumentError(`Invalid partial address: ${address}`); + } +} + +/** + * Parses a private key from a string. + * @param privateKey - A string + * @returns A private key + * @throws InvalidArgumentError if the input string is not valid. + */ +export function parsePrivateKey(privateKey: string): GrumpkinScalar { + try { + const value = GrumpkinScalar.fromString(privateKey); + // most likely a badly formatted key was passed + if (value.isZero()) { + throw new Error('Private key must not be zero'); + } + + return value; + } catch (err) { + throw new InvalidArgumentError(`Invalid private key: ${privateKey}`); + } +} + +/** + * Parses a field from a string. + * @param field - A string representing the field. + * @returns A field. + * @throws InvalidArgumentError if the input string is not valid. + */ +export function parseField(field: string): Fr { + try { + const isHex = field.startsWith('0x') || field.match(new RegExp(`^[0-9a-f]{${Fr.SIZE_IN_BYTES * 2}}$`, 'i')); + if (isHex) { + return Fr.fromString(field); + } + + if (['true', 'false'].includes(field)) { + return new Fr(field === 'true'); + } + + const isNumber = +field || field === '0'; + if (isNumber) { + return new Fr(BigInt(field)); + } + + const isBigInt = field.endsWith('n'); + if (isBigInt) { + return new Fr(BigInt(field.replace(/n$/, ''))); + } + + return new Fr(BigInt(field)); + } catch (err) { + throw new InvalidArgumentError(`Invalid field: ${field}`); + } +} + +/** + * Parses an array of strings to Frs. + * @param fields - An array of strings representing the fields. + * @returns An array of Frs. + */ +export function parseFields(fields: string[]): Fr[] { + return fields.map(parseField); +} diff --git a/yarn-project/cli/src/test/utils.test.ts b/yarn-project/cli/src/test/utils.test.ts index e465138083b..d0c9ff1b7ef 100644 --- a/yarn-project/cli/src/test/utils.test.ts +++ b/yarn-project/cli/src/test/utils.test.ts @@ -5,7 +5,8 @@ import { InvalidArgumentError } from 'commander'; import { MockProxy, mock } from 'jest-mock-extended'; import { encodeArgs } from '../encoding.js'; -import { getTxSender, parseSaltFromHexString, stripLeadingHex } from '../utils.js'; +import { parseSaltFromHexString } from '../parse_args.js'; +import { getTxSender, stripLeadingHex } from '../utils.js'; import { mockContractArtifact } from './mocks.js'; describe('CLI Utils', () => { diff --git a/yarn-project/cli/src/utils.ts b/yarn-project/cli/src/utils.ts index ed8dd3cc017..40867e8fbb0 100644 --- a/yarn-project/cli/src/utils.ts +++ b/yarn-project/cli/src/utils.ts @@ -1,11 +1,7 @@ -import { type ContractArtifact, type FunctionArtifact, FunctionSelector } from '@aztec/aztec.js/abi'; +import { type ContractArtifact, type FunctionArtifact } from '@aztec/aztec.js/abi'; import { AztecAddress } from '@aztec/aztec.js/aztec_address'; -import { EthAddress } from '@aztec/aztec.js/eth_address'; import { type L1ContractArtifactsForDeployment } from '@aztec/aztec.js/ethereum'; -import { Fr, GrumpkinScalar, Point } from '@aztec/aztec.js/fields'; import { type PXE } from '@aztec/aztec.js/interfaces/pxe'; -import { LogId } from '@aztec/aztec.js/log_id'; -import { TxHash } from '@aztec/aztec.js/tx_hash'; import { DebugLogger, LogFn } from '@aztec/foundation/log'; import { CommanderError, InvalidArgumentError } from 'commander'; @@ -182,234 +178,6 @@ export const stripLeadingHex = (hex: string) => { return hex; }; -/** - * Parses a hex encoded string to an Fr integer to be used as salt - * @param str - Hex encoded string - * @returns A integer to be used as salt - */ -export function parseSaltFromHexString(str: string): Fr { - const hex = stripLeadingHex(str); - - // ensure it's a hex string - if (!hex.match(/^[0-9a-f]+$/i)) { - throw new InvalidArgumentError('Invalid hex string'); - } - - // pad it so that we may read it as a buffer. - // Buffer needs _exactly_ two hex characters per byte - const padded = hex.length % 2 === 1 ? '0' + hex : hex; - - // finally, turn it into an integer - return Fr.fromBuffer(Buffer.from(padded, 'hex')); -} - -/** - * Parses an AztecAddress from a string. - * @param address - A serialized Aztec address - * @returns An Aztec address - * @throws InvalidArgumentError if the input string is not valid. - */ -export function parseAztecAddress(address: string): AztecAddress { - try { - return AztecAddress.fromString(address); - } catch { - throw new InvalidArgumentError(`Invalid address: ${address}`); - } -} - -/** - * Parses an Ethereum address from a string. - * @param address - A serialized Ethereum address - * @returns An Ethereum address - * @throws InvalidArgumentError if the input string is not valid. - */ -export function parseEthereumAddress(address: string): EthAddress { - try { - return EthAddress.fromString(address); - } catch { - throw new InvalidArgumentError(`Invalid address: ${address}`); - } -} - -/** - * Parses an AztecAddress from a string. - * @param address - A serialized Aztec address - * @returns An Aztec address - * @throws InvalidArgumentError if the input string is not valid. - */ -export function parseOptionalAztecAddress(address: string): AztecAddress | undefined { - if (!address) { - return undefined; - } - return parseAztecAddress(address); -} - -/** - * Parses an optional log ID string into a LogId object. - * - * @param logId - The log ID string to parse. - * @returns The parsed LogId object, or undefined if the log ID is missing or empty. - */ -export function parseOptionalLogId(logId: string): LogId | undefined { - if (!logId) { - return undefined; - } - return LogId.fromString(logId); -} - -/** - * Parses a selector from a string. - * @param selector - A serialized selector. - * @returns A selector. - * @throws InvalidArgumentError if the input string is not valid. - */ -export function parseOptionalSelector(selector: string): FunctionSelector | undefined { - if (!selector) { - return undefined; - } - try { - return FunctionSelector.fromString(selector); - } catch { - throw new InvalidArgumentError(`Invalid selector: ${selector}`); - } -} - -/** - * Parses a string into an integer or returns undefined if the input is falsy. - * - * @param value - The string to parse into an integer. - * @returns The parsed integer, or undefined if the input string is falsy. - * @throws If the input is not a valid integer. - */ -export function parseOptionalInteger(value: string): number | undefined { - if (!value) { - return undefined; - } - const parsed = Number(value); - if (!Number.isInteger(parsed)) { - throw new InvalidArgumentError('Invalid integer.'); - } - return parsed; -} - -/** - * Parses a TxHash from a string. - * @param txHash - A transaction hash - * @returns A TxHash instance - * @throws InvalidArgumentError if the input string is not valid. - */ -export function parseTxHash(txHash: string): TxHash { - try { - return TxHash.fromString(txHash); - } catch { - throw new InvalidArgumentError(`Invalid transaction hash: ${txHash}`); - } -} - -/** - * Parses an optional TxHash from a string. - * Calls parseTxHash internally. - * @param txHash - A transaction hash - * @returns A TxHash instance, or undefined if the input string is falsy. - * @throws InvalidArgumentError if the input string is not valid. - */ -export function parseOptionalTxHash(txHash: string): TxHash | undefined { - if (!txHash) { - return undefined; - } - return parseTxHash(txHash); -} - -/** - * Parses a public key from a string. - * @param publicKey - A public key - * @returns A Point instance - * @throws InvalidArgumentError if the input string is not valid. - */ -export function parsePublicKey(publicKey: string): Point { - try { - return Point.fromString(publicKey); - } catch (err) { - throw new InvalidArgumentError(`Invalid public key: ${publicKey}`); - } -} - -/** - * Parses a partial address from a string. - * @param address - A partial address - * @returns A Fr instance - * @throws InvalidArgumentError if the input string is not valid. - */ -export function parsePartialAddress(address: string): Fr { - try { - return Fr.fromString(address); - } catch (err) { - throw new InvalidArgumentError(`Invalid partial address: ${address}`); - } -} - -/** - * Parses a private key from a string. - * @param privateKey - A string - * @returns A private key - * @throws InvalidArgumentError if the input string is not valid. - */ -export function parsePrivateKey(privateKey: string): GrumpkinScalar { - try { - const value = GrumpkinScalar.fromString(privateKey); - // most likely a badly formatted key was passed - if (value.isZero()) { - throw new Error('Private key must not be zero'); - } - - return value; - } catch (err) { - throw new InvalidArgumentError(`Invalid private key: ${privateKey}`); - } -} - -/** - * Parses a field from a string. - * @param field - A string representing the field. - * @returns A field. - * @throws InvalidArgumentError if the input string is not valid. - */ -export function parseField(field: string): Fr { - try { - const isHex = field.startsWith('0x') || field.match(new RegExp(`^[0-9a-f]{${Fr.SIZE_IN_BYTES * 2}}$`, 'i')); - if (isHex) { - return Fr.fromString(field); - } - - if (['true', 'false'].includes(field)) { - return new Fr(field === 'true'); - } - - const isNumber = +field || field === '0'; - if (isNumber) { - return new Fr(BigInt(field)); - } - - const isBigInt = field.endsWith('n'); - if (isBigInt) { - return new Fr(BigInt(field.replace(/n$/, ''))); - } - - return new Fr(BigInt(field)); - } catch (err) { - throw new InvalidArgumentError(`Invalid field: ${field}`); - } -} - -/** - * Parses an array of strings to Frs. - * @param fields - An array of strings representing the fields. - * @returns An array of Frs. - */ -export function parseFields(fields: string[]): Fr[] { - return fields.map(parseField); -} - /** * Updates a file in place atomically. * @param filePath - Path to file diff --git a/yarn-project/end-to-end/src/shared/browser.ts b/yarn-project/end-to-end/src/shared/browser.ts index 9c7cfdfc154..72b064bc903 100644 --- a/yarn-project/end-to-end/src/shared/browser.ts +++ b/yarn-project/end-to-end/src/shared/browser.ts @@ -84,9 +84,8 @@ export const browserTestSuite = (setup: () => Server, pageLogger: AztecJs.DebugL }); it('Loads Aztec.js in the browser', async () => { - const generatePublicKeyExists = await page.evaluate(async () => { - const { generatePublicKey, init } = window.AztecJs; - await init(); + const generatePublicKeyExists = await page.evaluate(() => { + const { generatePublicKey } = window.AztecJs; return typeof generatePublicKey === 'function'; }); expect(generatePublicKeyExists).toBe(true); diff --git a/yarn-project/foundation/src/abi/abi_coder.ts b/yarn-project/foundation/src/abi/abi_coder.ts index 6971b423757..a702e65153a 100644 --- a/yarn-project/foundation/src/abi/abi_coder.ts +++ b/yarn-project/foundation/src/abi/abi_coder.ts @@ -1,4 +1,4 @@ -import { ABIType } from '@aztec/foundation/abi'; +import { type ABIType } from './abi.js'; /** * Get the size of an ABI type in field elements. diff --git a/yarn-project/foundation/src/abi/decoder.ts b/yarn-project/foundation/src/abi/decoder.ts index 9ea69388f76..cd37ba361e5 100644 --- a/yarn-project/foundation/src/abi/decoder.ts +++ b/yarn-project/foundation/src/abi/decoder.ts @@ -1,5 +1,5 @@ -import { ABIParameter, ABIType, ABIVariable, FunctionArtifact } from '@aztec/foundation/abi'; -import { Fr } from '@aztec/foundation/fields'; +import { Fr } from '../fields/index.js'; +import { ABIParameter, type ABIType, ABIVariable, FunctionArtifact } from './abi.js'; /** * The type of our decoded ABI. diff --git a/yarn-project/foundation/src/abi/encoder.ts b/yarn-project/foundation/src/abi/encoder.ts index 2e4b1844060..a4db8e24230 100644 --- a/yarn-project/foundation/src/abi/encoder.ts +++ b/yarn-project/foundation/src/abi/encoder.ts @@ -1,6 +1,6 @@ -import { ABIType, FunctionAbi, isAddressStruct } from '@aztec/foundation/abi'; - import { Fr } from '../fields/index.js'; +import { ABIType, FunctionAbi } from './abi.js'; +import { isAddressStruct } from './utils.js'; /** * Encodes arguments for a function call. diff --git a/yarn-project/foundation/src/abi/function_selector.ts b/yarn-project/foundation/src/abi/function_selector.ts index df53ef9a1fb..de0b879cf6b 100644 --- a/yarn-project/foundation/src/abi/function_selector.ts +++ b/yarn-project/foundation/src/abi/function_selector.ts @@ -1,9 +1,11 @@ -import { ABIParameter, decodeFunctionSignature } from '@aztec/foundation/abi'; import { toBigIntBE, toBufferBE } from '@aztec/foundation/bigint-buffer'; -import { keccak } from '@aztec/foundation/crypto'; -import { Fr } from '@aztec/foundation/fields'; import { BufferReader } from '@aztec/foundation/serialize'; +import { keccak } from '../crypto/keccak/index.js'; +import { Fr } from '../fields/index.js'; +import { ABIParameter } from './abi.js'; +import { decodeFunctionSignature } from './decoder.js'; + /** * A function selector is the first 4 bytes of the hash of a function signature. */ diff --git a/yarn-project/foundation/src/abi/utils.ts b/yarn-project/foundation/src/abi/utils.ts index b2ee62d2dd5..d7d15a4d94a 100644 --- a/yarn-project/foundation/src/abi/utils.ts +++ b/yarn-project/foundation/src/abi/utils.ts @@ -1,4 +1,4 @@ -import { ABIType } from './abi.js'; +import { type ABIType } from './abi.js'; /** * Returns whether the ABI type is an Aztec or Ethereum Address defined in Aztec.nr. diff --git a/yarn-project/foundation/src/eth-address/index.ts b/yarn-project/foundation/src/eth-address/index.ts index 2571f09790c..76587ecab26 100644 --- a/yarn-project/foundation/src/eth-address/index.ts +++ b/yarn-project/foundation/src/eth-address/index.ts @@ -1,4 +1,5 @@ -import { keccak256String, randomBytes } from '../crypto/index.js'; +import { keccak256String } from '../crypto/keccak/index.js'; +import { randomBytes } from '../crypto/random/index.js'; import { Fr } from '../fields/index.js'; import { BufferReader } from '../serialize/index.js'; diff --git a/yarn-project/foundation/src/fields/fields.ts b/yarn-project/foundation/src/fields/fields.ts index 591b57f6892..90600643cfe 100644 --- a/yarn-project/foundation/src/fields/fields.ts +++ b/yarn-project/foundation/src/fields/fields.ts @@ -1,5 +1,5 @@ import { toBigIntBE, toBufferBE } from '../bigint-buffer/index.js'; -import { randomBytes } from '../crypto/index.js'; +import { randomBytes } from '../crypto/random/index.js'; import { BufferReader } from '../serialize/buffer_reader.js'; const ZERO_BUFFER = Buffer.alloc(32); diff --git a/yarn-project/types/src/tx/tx_hash.ts b/yarn-project/types/src/tx/tx_hash.ts index 138aa6dbe0f..00003456ee3 100644 --- a/yarn-project/types/src/tx/tx_hash.ts +++ b/yarn-project/types/src/tx/tx_hash.ts @@ -1,4 +1,3 @@ -import { assertMemberLength } from '@aztec/circuits.js'; import { deserializeBigInt, serializeBigInt } from '@aztec/foundation/serialize'; /** @@ -21,7 +20,9 @@ export class TxHash { */ public buffer: Buffer, ) { - assertMemberLength(this, 'buffer', TxHash.SIZE); + if (buffer.length !== TxHash.SIZE) { + throw new Error(`Expected buffer to have length ${TxHash.SIZE} but was ${buffer.length}`); + } } /** From 765a19c3aad3a2793a764b970b7cc8a819094da7 Mon Sep 17 00:00:00 2001 From: Charlie Lye Date: Sun, 10 Dec 2023 16:21:36 +0000 Subject: [PATCH 15/35] fix: aztec sandbox compose fixes (#3634) * Make `aztec-sandbox` properly clean up after itself. * Fix compose file to actually use arguments and not spraff warnings. * Always mount home dir into containers, nothing else. * Fix build system r.e. multiarch success tags. * Fix lying default cli comment. * Convert all bash shebang lines to use bash from PATH rather than /usr/bin. Some scripts need bash 4 or above which requires a brew install on mac. * Convert noir and downstream containers to be ubuntu, from alpine: * Still need to do several others e.g. bb. * Alpine has given us several issue, weird threading slowdowns in bb. * 10x worse performance in nargo. * Slower startup times in node. * Enough is enough! We can now have a unified development and execution environment. Lovely. --- .circleci/config.yml | 8 +-- aztec-up/bin/.aztec-run | 60 +++++++------------ aztec-up/bin/aztec-install | 23 +++++-- aztec-up/bin/aztec-sandbox | 20 +++++-- aztec-up/bin/aztec-up | 2 +- aztec-up/bin/docker-compose.yml | 31 +++++----- .../acir_tests/Dockerfile.noir_acir_tests | 2 +- barretenberg/acir_tests/bash_helpers/catch.sh | 2 +- barretenberg/acir_tests/bench_acir_tests.sh | 2 +- barretenberg/acir_tests/clone_test_vectors.sh | 2 +- .../acir_tests/gen_inner_proof_inputs.sh | 2 +- barretenberg/acir_tests/run_acir_tests.sh | 6 +- .../acir_tests/run_acir_tests_browser.sh | 2 +- barretenberg/bootstrap.sh | 2 +- barretenberg/cpp/bootstrap.sh | 2 +- barretenberg/cpp/format.sh | 2 +- barretenberg/cpp/scripts/bb-tests.sh | 2 +- barretenberg/cpp/scripts/benchmarks.sh | 2 +- .../scripts/collect_coverage_information.sh | 2 +- .../cpp/scripts/collect_heap_information.sh | 2 +- .../scripts/collect_profile_information.sh | 2 +- barretenberg/cpp/scripts/install-wasi-sdk.sh | 2 +- barretenberg/cpp/scripts/run_tests | 2 +- .../benchmark/compare_branch_vs_baseline.sh | 6 +- .../honk_bench/compare_honk_to_plonk_ultra.sh | 12 ++-- barretenberg/scripts/bindgen.sh | 2 +- barretenberg/sol/scripts/init.sh | 2 +- barretenberg/sol/scripts/run_fuzzer.sh | 2 +- barretenberg/ts/bootstrap.sh | 2 +- barretenberg/ts/scripts/run_tests | 2 +- bootstrap.sh | 2 +- bootstrap/bootstrap_test.sh | 2 +- bootstrap_docker.sh | 2 +- .../remote/bootstrap_build_instance.sh | 2 +- build-system/scripts/add_timestamps | 2 +- build-system/scripts/build | 2 +- build-system/scripts/build_local | 2 +- build-system/scripts/calculate_content_hash | 2 +- build-system/scripts/calculate_image_tag | 2 +- build-system/scripts/calculate_image_uri | 2 +- build-system/scripts/calculate_rebuild_files | 2 +- build-system/scripts/check_rebuild | 2 +- build-system/scripts/clean_image_tags | 6 +- build-system/scripts/cond_run_compose | 2 +- build-system/scripts/cond_run_container | 2 +- build-system/scripts/cond_run_script | 2 +- build-system/scripts/cond_spot_run_build | 2 +- build-system/scripts/cond_spot_run_compose | 2 +- build-system/scripts/cond_spot_run_container | 2 +- build-system/scripts/cond_spot_run_script | 9 ++- build-system/scripts/cond_spot_run_test | 2 +- build-system/scripts/create_ecr_manifest | 2 +- build-system/scripts/deploy | 2 +- build-system/scripts/deploy_dockerhub | 2 +- build-system/scripts/deploy_ecr | 2 +- build-system/scripts/deploy_global | 2 +- build-system/scripts/deploy_npm | 2 +- build-system/scripts/deploy_s3 | 2 +- build-system/scripts/deploy_service | 2 +- build-system/scripts/deploy_terraform | 2 +- build-system/scripts/dockerhub_login | 2 +- build-system/scripts/ecr_login | 2 +- build-system/scripts/ensure_repo | 2 +- build-system/scripts/ensure_terraform | 2 +- build-system/scripts/extract_repo | 2 +- build-system/scripts/extract_tag_version | 4 +- build-system/scripts/image_exists | 2 +- build-system/scripts/init_submodules | 2 +- build-system/scripts/query_manifest | 2 +- build-system/scripts/remote_run_script | 2 +- build-system/scripts/remote_runner | 2 +- build-system/scripts/request_spot | 2 +- build-system/scripts/setup_env | 2 +- build-system/scripts/should_deploy | 2 +- build-system/scripts/should_release | 2 +- build-system/scripts/spot_run_script | 2 +- build-system/scripts/tag_remote_image | 4 +- build-system/scripts/untag_remote_image | 2 +- build-system/scripts/upload_logs_to_s3 | 2 +- build-system/start_interactive | 2 +- build_manifest.yml | 2 +- circuits/cpp/bootstrap.sh | 2 +- circuits/cpp/format.sh | 2 +- .../cpp/scripts/build_run_tests_docker_local | 2 +- .../scripts/collect_coverage_information.sh | 4 +- circuits/cpp/scripts/run_tests | 2 +- circuits/cpp/scripts/run_tests_local | 2 +- circuits/cpp/scripts/tidy.sh | 2 +- docs/deploy_netlify.sh | 2 +- docs/scripts/build.sh | 4 +- iac/mainnet-fork/scripts/run_nginx_anvil.sh | 2 +- iac/mainnet-fork/scripts/wait_for_fork | 2 +- l1-contracts/bootstrap.sh | 2 +- l1-contracts/scripts/ci_deploy_contracts.sh | 2 +- l1-contracts/scripts/deploy_contracts.sh | 2 +- .../actions/docs/build-status/script.sh | 2 +- noir/Dockerfile | 13 ++-- noir/bootstrap.sh | 2 +- .../scripts/codegen-verifiers.sh | 2 +- noir/scripts/bootstrap_native.sh | 2 +- noir/scripts/bootstrap_packages.sh | 2 +- noir/scripts/install_wasm-bindgen.sh | 2 +- noir/test_programs/gates_report.sh | 2 +- noir/test_programs/rebuild.sh | 2 +- scripts/ci/assemble_e2e_benchmark.sh | 8 +-- scripts/ci/store_test_benchmark_logs | 6 +- scripts/git-subrepo/note/init-test | 2 +- .../note/recreate-rebase-conflict.sh | 2 +- .../subtree-rebase-fail-example/test.bash | 4 +- scripts/git-subrepo/note/test-subrepo-push.sh | 2 +- scripts/git-subrepo/note/test.sh | 2 +- scripts/git_subrepo.sh | 8 +-- scripts/migrate_barretenberg_branch.sh | 2 +- scripts/tmux-splits | 2 +- yarn-project/Dockerfile | 2 - yarn-project/Dockerfile.prod | 35 +++++++++-- .../terraform/servicediscovery-drain.sh | 2 +- yarn-project/aztec-sandbox/Dockerfile | 7 +-- yarn-project/bootstrap.sh | 2 +- yarn-project/boxes/bootstrap.sh | 8 +-- yarn-project/boxes/run_tests | 2 +- yarn-project/canary/scripts/cond_run_script | 2 +- .../canary/scripts/extract_packages.sh | 2 +- yarn-project/canary/scripts/run_tests | 2 +- .../canary/scripts/update_packages.sh | 2 +- yarn-project/cli/Dockerfile | 15 +---- yarn-project/deploy_npm.sh | 2 +- .../end-to-end/scripts/setup_canary.sh | 2 +- .../scripts/generate-artifacts.sh | 2 +- .../add_noir_compiler_commander_actions.ts | 2 +- yarn-project/noir-contracts/scripts/catch.sh | 2 +- .../noir-contracts/scripts/compile.sh | 2 +- .../noir-contracts/scripts/compile_all.sh | 2 +- .../scripts/get_all_contracts.sh | 2 +- .../scripts/get_all_libraries.sh | 2 +- .../noir-contracts/scripts/install_noir.sh | 2 +- .../noir-contracts/scripts/install_noirup.sh | 2 +- .../noir-contracts/scripts/nargo_check.sh | 2 +- .../noir-contracts/scripts/nargo_test.sh | 2 +- .../noir-contracts/scripts/nargo_test_ci.sh | 2 +- yarn-project/noir-contracts/scripts/types.sh | 2 +- .../noir-contracts/scripts/types_all.sh | 2 +- .../noir-contracts/src/scripts/compile.sh | 2 +- .../terraform/servicediscovery-drain.sh | 2 +- yarn-project/scripts/run_script.sh | 2 +- yarn-project/scripts/version_packages.sh | 2 +- yarn-project/yarn-project-base/Dockerfile | 4 +- 147 files changed, 284 insertions(+), 267 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 794d5a090b7..fb0ea6e4b9a 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -358,15 +358,15 @@ jobs: command: build yarn-project-prod | add_timestamps yarn-project-formatting: - machine: - image: ubuntu-2204:2023.07.2 - resource_class: large + docker: + - image: aztecprotocol/alpine-build-image + resource_class: small steps: - *checkout - *setup_env - run: name: Check Formatting - command: cond_run_container yarn-project formatting | add_timestamps + command: cond_spot_run_container yarn-project 8 formatting | add_timestamps yarn-project-tests: docker: diff --git a/aztec-up/bin/.aztec-run b/aztec-up/bin/.aztec-run index c338bede2e1..82b12deb89a 100755 --- a/aztec-up/bin/.aztec-run +++ b/aztec-up/bin/.aztec-run @@ -13,16 +13,24 @@ VERSION=${VERSION:-"latest"} DOCKER_HOST_BINDS="" # Volumes to pass to the container. -DOCKER_VOLUME="" +DOCKER_VOLUME="-v $HOME:/root" + +# Colors. +y="\033[33m" +r="\033[0m" + +function warn { + echo -e "${y}$1${r}" +} if ! command -v docker &> /dev/null; then - echo "No docker found." + warn "No docker found." exit 1 fi -# Colors. -yellow="\033[33m" -reset="\033[0m" +if [[ $PWD != ${HOME}* ]]; then + warn "Due to how we containerize our applications, we require your working directory to be somewhere within $HOME." +fi # Set up host.docker.internal alias on Linux, just like it is on mac. UNAME=$(uname -s) @@ -30,51 +38,28 @@ if [ "$UNAME" == "Linux" ]; then if docker info 2>/dev/null | grep -q rootless; then # We're in rootless docker. Probe for the host ip and use that. ip=$(hostname -I | head | tr -d ' ') - echo -e "${yellow}WARNING: Running within rootless docker. Using $ip as host ip. Ensure listening services are listening on this interface.${reset}" + warn "WARNING: Running within rootless docker. Using $ip as host ip. Ensure listening services are listening on this interface." DOCKER_HOST_BINDS="$DOCKER_HOST_BINDS --add-host host.docker.internal:$ip" else DOCKER_HOST_BINDS="$DOCKER_HOST_BINDS --add-host host.docker.internal:host-gateway" fi fi -# Build a list of mount points -function add_mount() { - DIR="${1:-}" - - # Grab its dirname if its a file. - if [ -f "$DIR" ]; then - DIR=$(dirname "$DIR") - fi - - if [ ! -d "$DIR" ]; then - return - fi - - # Check if it's already been added. - REALDIR=$(realpath $DIR) - if [[ "$DOCKER_VOLUME" =~ "$REALDIR:" ]]; then - return - fi - - DOCKER_VOLUME="$DOCKER_VOLUME -v $REALDIR:$REALDIR" -} - -# Always mount the CWD into the container. -add_mount "$PWD" - # Substitute any references to localhost with our host gateway. +# TODO: In node, we can hook the resolve override for localhost with host.docker.internal. +# Consider if we should just do that, but that wouldn't help e.g. nargo. args=("$@") for i in "${!args[@]}"; do args[$i]=${args[$i]//localhost/host.docker.internal} done -# Check if it's either a filename or a directory that exists outside the CWD. -# If it is then mount inside the container. -# NOTE: This won't work with assignement-style flags, e.g. --outdir=/foo +# Check if it's either a filename or a directory that exists outside the HOME. +# If so, warn and exit. for i in "${!args[@]}"; do arg=${args[$i]} - if [[ -f "$arg" || -d "$arg" && $(realpath $arg) != ${PWD}* ]]; then - add_mount "$arg" + if [[ -f "$arg" || -d "$arg" && $(realpath $arg) != ${HOME}* ]]; then + warn "Due to how we containerize our applications, paths outside of $HOME cannot be referenced." + exit 1 fi done @@ -91,8 +76,7 @@ DOCKER_VOLUME="$DOCKER_VOLUME -v cache:/cache" docker run \ -ti \ --rm \ - --user $(id -u):$(id -g) \ - --workdir "$PWD" \ + --workdir "${PWD/$HOME/\/root}" \ $DOCKER_HOST_BINDS \ $DOCKER_ENV \ $DOCKER_VOLUME \ diff --git a/aztec-up/bin/aztec-install b/aztec-up/bin/aztec-install index 653e80e9886..e6c7ec5ebf4 100755 --- a/aztec-up/bin/aztec-install +++ b/aztec-up/bin/aztec-install @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -euo pipefail # Colors @@ -29,7 +29,16 @@ function title() { echo -e "Welcome to the ${bold}${b}Aztec${r} installer! Your journey into blockchain privacy begins... ${bold}${p}now${r}." echo -e "We presently leverage docker to simplify releases of our complex project." echo -e "Please ensure it's installed for your platform: https://docs.docker.com/engine/install" - echo + if [ "$(uname -s)" == "Darwin" ]; then + echo + echo -e "${y}WARNING: For best performance we recommend adjusting your default docker settings:" + echo -e " - Under general, enable VirtioFS." + echo -e " - Under resources, set CPUs to ~80-100% your maximum." + echo -e " - Under resources, set Memory to ~80% your maximum." + echo -e "You may receive a warning about your home directory being mounted into a container." + echo -e "This is requested so we can read and write project files, that is all." + echo -e "${r}" + fi echo -e "This will install the following scripts and update your PATH if necessary:" echo -e " ${bold}${g}aztec${r} - launches various infrastructure subsystems (sequencer, prover, pxe, etc)." echo -e " ${bold}${g}aztec-cli${r} - a command line tool for interfacing and experimenting with infrastructure." @@ -91,10 +100,12 @@ function pull_container { fi } -info "Pulling aztec version $VERSION..." -pull_container aztec-sandbox -pull_container cli -pull_container noir +if [ -z "${SKIP_PULL:-}" ]; then + info "Pulling aztec version $VERSION..." + pull_container aztec-sandbox + pull_container cli + pull_container noir +fi # Download the Docker Compose file. Used by aztec-start. curl -fsSL http://$INSTALL_HOST/docker-compose.yml -o $BIN_PATH/docker-compose.yml diff --git a/aztec-up/bin/aztec-sandbox b/aztec-up/bin/aztec-sandbox index ccbe9747045..1558bc49cb2 100755 --- a/aztec-up/bin/aztec-sandbox +++ b/aztec-up/bin/aztec-sandbox @@ -1,11 +1,21 @@ -#!/bin/bash +#!/usr/bin/env bash set -euo pipefail -# Change working dir, so relative volume mounts are in the right place. -cd ~/.aztec - # Favour 'docker compose', falling back on docker-compose. CMD="docker compose" $CMD &>/dev/null || CMD="docker-compose" -$CMD -f ~/.aztec/bin/docker-compose.yml up \ No newline at end of file +ARGS="-f $HOME/.aztec/bin/docker-compose.yml -p sandbox" + +# Function to be executed when SIGINT is received. +cleanup() { + $CMD $ARGS down +} + +# Set trap to catch SIGINT and call the cleanup function. +trap cleanup SIGINT + +# Change working dir, so relative volume mounts are in the right place. +cd ~/.aztec + +$CMD $ARGS up --force-recreate --remove-orphans \ No newline at end of file diff --git a/aztec-up/bin/aztec-up b/aztec-up/bin/aztec-up index d3b88660090..736307e1827 100755 --- a/aztec-up/bin/aztec-up +++ b/aztec-up/bin/aztec-up @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -euo pipefail export SKIP_TITLE=1 diff --git a/aztec-up/bin/docker-compose.yml b/aztec-up/bin/docker-compose.yml index 735466e3904..b861d729d16 100644 --- a/aztec-up/bin/docker-compose.yml +++ b/aztec-up/bin/docker-compose.yml @@ -1,27 +1,28 @@ -version: '3' +version: "3" services: ethereum: image: ghcr.io/foundry-rs/foundry@sha256:29ba6e34379e79c342ec02d437beb7929c9e254261e8032b17e187be71a2609f - entrypoint: > - sh -c ' - if [ -n "$FORK_BLOCK_NUMBER" ] && [ -n "$FORK_URL" ]; then - exec anvil -p 8545 --host 0.0.0.0 --chain-id 31337 --silent --fork-url "$FORK_URL" --fork-block-number "$FORK_BLOCK_NUMBER" - elif [ -n "$FORK_URL" ]; then - exec anvil -p 8545 --host 0.0.0.0 --chain-id 31337 --silent --fork-url "$FORK_URL" - else - exec anvil -p 8545 --host 0.0.0.0 --chain-id 31337 --silent - fi' + command: > + ' + [ -n "$$FORK_URL" ] && ARGS="$$ARGS --fork-url $$FORK_URL"; + [ -n "$$FORK_BLOCK_NUMBER" ] && ARGS="$$ARGS --fork-block-number $$FORK_BLOCK_NUMBER"; + echo anvil -p 8545 --host 0.0.0.0 --chain-id 31337 --silent $$ARGS; + anvil -p 8545 --host 0.0.0.0 --chain-id 31337 --silent $$ARGS + ' ports: - - '${SANDBOX_ANVIL_PORT:-8545}:8545' + - "${SANDBOX_ANVIL_PORT:-8545}:8545" + environment: + FORK_URL: + FORK_BLOCK_NUMBER: aztec: - image: 'aztecprotocol/aztec-sandbox' + image: "aztecprotocol/aztec-sandbox" ports: - - '${SANDBOX_AZTEC_NODE_PORT:-8079}:8079' - - '${SANDBOX_PXE_PORT:-8080}:8080' + - "${SANDBOX_AZTEC_NODE_PORT:-8079}:8079" + - "${SANDBOX_PXE_PORT:-8080}:8080" environment: DEBUG: # Loaded from the user shell if explicitly set - HOST_WORKDIR: '${PWD}' # Loaded from the user shell to show log files absolute path in host + HOST_WORKDIR: "${PWD}" # Loaded from the user shell to show log files absolute path in host ETHEREUM_HOST: http://ethereum:8545 CHAIN_ID: 31337 ARCHIVER_POLLING_INTERVAL_MS: 50 diff --git a/barretenberg/acir_tests/Dockerfile.noir_acir_tests b/barretenberg/acir_tests/Dockerfile.noir_acir_tests index 87fdd8604a4..5131e94e279 100644 --- a/barretenberg/acir_tests/Dockerfile.noir_acir_tests +++ b/barretenberg/acir_tests/Dockerfile.noir_acir_tests @@ -3,7 +3,7 @@ # So, it lives here. # This chains off the nargo build, and creates a container with a compiled set of acir tests. FROM 278380418400.dkr.ecr.eu-west-2.amazonaws.com/noir -RUN apk add bash jq +RUN apt update && apt install -y jq && rm -rf /var/lib/apt/lists/* && apt-get clean ENV PATH="/usr/src/noir/target/release:${PATH}" WORKDIR /usr/src/noir/test_programs COPY . . diff --git a/barretenberg/acir_tests/bash_helpers/catch.sh b/barretenberg/acir_tests/bash_helpers/catch.sh index 888af3cbb44..bc2025d4da5 100644 --- a/barretenberg/acir_tests/bash_helpers/catch.sh +++ b/barretenberg/acir_tests/bash_helpers/catch.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Handler for SIGCHLD, cleanup if child exit with error handle_sigchild() { diff --git a/barretenberg/acir_tests/bench_acir_tests.sh b/barretenberg/acir_tests/bench_acir_tests.sh index b338e82e30b..a41b261d1cc 100755 --- a/barretenberg/acir_tests/bench_acir_tests.sh +++ b/barretenberg/acir_tests/bench_acir_tests.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash TEST_NAMES=("$@") THREADS=(1 4 16 32 64) diff --git a/barretenberg/acir_tests/clone_test_vectors.sh b/barretenberg/acir_tests/clone_test_vectors.sh index c6fd6ef1bf1..b15814ab013 100755 --- a/barretenberg/acir_tests/clone_test_vectors.sh +++ b/barretenberg/acir_tests/clone_test_vectors.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -eu TEST_SRC=${TEST_SRC:-../../noir/test_programs/acir_artifacts} diff --git a/barretenberg/acir_tests/gen_inner_proof_inputs.sh b/barretenberg/acir_tests/gen_inner_proof_inputs.sh index 64b87fe19db..36137bde82e 100755 --- a/barretenberg/acir_tests/gen_inner_proof_inputs.sh +++ b/barretenberg/acir_tests/gen_inner_proof_inputs.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Env var overrides: # BIN: to specify a different binary to test with (e.g. bb.js or bb.js-dev). set -eu diff --git a/barretenberg/acir_tests/run_acir_tests.sh b/barretenberg/acir_tests/run_acir_tests.sh index 84953d01c55..ee28c975113 100755 --- a/barretenberg/acir_tests/run_acir_tests.sh +++ b/barretenberg/acir_tests/run_acir_tests.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Env var overrides: # BIN: to specify a different binary to test with (e.g. bb.js or bb.js-dev). # VERBOSE: to enable logging for each test. @@ -80,8 +80,8 @@ else # If parallel flag is set, run in parallel if [ -n "${PARALLEL:-}" ]; then test $TEST_NAME & - else - test $TEST_NAME + else + test $TEST_NAME fi done fi diff --git a/barretenberg/acir_tests/run_acir_tests_browser.sh b/barretenberg/acir_tests/run_acir_tests_browser.sh index 22830656250..1c1f2ce0e08 100755 --- a/barretenberg/acir_tests/run_acir_tests_browser.sh +++ b/barretenberg/acir_tests/run_acir_tests_browser.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -em cleanup() { diff --git a/barretenberg/bootstrap.sh b/barretenberg/bootstrap.sh index 504f1980982..c16fd294b6c 100755 --- a/barretenberg/bootstrap.sh +++ b/barretenberg/bootstrap.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -eu cd "$(dirname "$0")" diff --git a/barretenberg/cpp/bootstrap.sh b/barretenberg/cpp/bootstrap.sh index 25350c4fcce..0b9295bafbd 100755 --- a/barretenberg/cpp/bootstrap.sh +++ b/barretenberg/cpp/bootstrap.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -eu # Navigate to script folder diff --git a/barretenberg/cpp/format.sh b/barretenberg/cpp/format.sh index 0bf8bca805c..ae314e96a6f 100755 --- a/barretenberg/cpp/format.sh +++ b/barretenberg/cpp/format.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -e if [ "$1" == "staged" ]; then diff --git a/barretenberg/cpp/scripts/bb-tests.sh b/barretenberg/cpp/scripts/bb-tests.sh index 459eb756593..a3f322b2afa 100755 --- a/barretenberg/cpp/scripts/bb-tests.sh +++ b/barretenberg/cpp/scripts/bb-tests.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # This script runs all test suites that have not been broken out into their own jobs for parallelisation. # Might be better to list exclusions here rather than inclusions as risky to maintain. set -eu diff --git a/barretenberg/cpp/scripts/benchmarks.sh b/barretenberg/cpp/scripts/benchmarks.sh index a7ec1dcb1d0..8a547c29aba 100755 --- a/barretenberg/cpp/scripts/benchmarks.sh +++ b/barretenberg/cpp/scripts/benchmarks.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -eu # Move above script dir. diff --git a/barretenberg/cpp/scripts/collect_coverage_information.sh b/barretenberg/cpp/scripts/collect_coverage_information.sh index b018e251483..0a3231a304c 100755 --- a/barretenberg/cpp/scripts/collect_coverage_information.sh +++ b/barretenberg/cpp/scripts/collect_coverage_information.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash if [ $# -ne 2 ]; then echo "Usage: $0 " diff --git a/barretenberg/cpp/scripts/collect_heap_information.sh b/barretenberg/cpp/scripts/collect_heap_information.sh index 1d25c5a791c..a1b6bee078e 100755 --- a/barretenberg/cpp/scripts/collect_heap_information.sh +++ b/barretenberg/cpp/scripts/collect_heap_information.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -eu PRESET=gperftools diff --git a/barretenberg/cpp/scripts/collect_profile_information.sh b/barretenberg/cpp/scripts/collect_profile_information.sh index df932c086bc..ebc0249392e 100755 --- a/barretenberg/cpp/scripts/collect_profile_information.sh +++ b/barretenberg/cpp/scripts/collect_profile_information.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -eu # can also be 'xray-1thread' diff --git a/barretenberg/cpp/scripts/install-wasi-sdk.sh b/barretenberg/cpp/scripts/install-wasi-sdk.sh index 1da258d880b..9d27d012a61 100755 --- a/barretenberg/cpp/scripts/install-wasi-sdk.sh +++ b/barretenberg/cpp/scripts/install-wasi-sdk.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -eu if [[ -d ./src/wasi-sdk-20.0 && -d ./src/wasi-sdk-20.0+threads ]]; then diff --git a/barretenberg/cpp/scripts/run_tests b/barretenberg/cpp/scripts/run_tests index 28d9f8cc4f8..a67f03ee992 100755 --- a/barretenberg/cpp/scripts/run_tests +++ b/barretenberg/cpp/scripts/run_tests @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # This is the default test runner which takes the as arguments: # 1. The number of ignition transcripts to download. # 2. The set of gtest binary names to run. diff --git a/barretenberg/cpp/src/barretenberg/benchmark/compare_branch_vs_baseline.sh b/barretenberg/cpp/src/barretenberg/benchmark/compare_branch_vs_baseline.sh index 0ac6dce1157..34ee2ce171d 100755 --- a/barretenberg/cpp/src/barretenberg/benchmark/compare_branch_vs_baseline.sh +++ b/barretenberg/cpp/src/barretenberg/benchmark/compare_branch_vs_baseline.sh @@ -1,7 +1,7 @@ -#!/bin/bash +#!/usr/bin/env bash # This script is used to compare a suite of benchmarks between baseline (default: master) and -# the branch from which the script is run. Simply check out the branch of interest, ensure +# the branch from which the script is run. Simply check out the branch of interest, ensure # it is up to date with local master, and run the script. # Specify the benchmark suite and the "baseline" branch against which to compare @@ -43,7 +43,7 @@ BASELINE_RESULTS="$BENCH_RESULTS_DIR/results_baseline.json" echo -e "\nRunning $BENCH_TARGET in master.." bin/$BENCH_TARGET --benchmark_format=json > $BASELINE_RESULTS -# Call compare.py on the results (json) to get high level statistics. +# Call compare.py on the results (json) to get high level statistics. # See docs at https://github.com/google/benchmark/blob/main/docs/tools.md for more details. $BENCH_TOOLS_DIR/compare.py benchmarks $BASELINE_RESULTS $BRANCH_RESULTS diff --git a/barretenberg/cpp/src/barretenberg/benchmark/honk_bench/compare_honk_to_plonk_ultra.sh b/barretenberg/cpp/src/barretenberg/benchmark/honk_bench/compare_honk_to_plonk_ultra.sh index 1863327ae4e..f97dbc0eaa7 100755 --- a/barretenberg/cpp/src/barretenberg/benchmark/honk_bench/compare_honk_to_plonk_ultra.sh +++ b/barretenberg/cpp/src/barretenberg/benchmark/honk_bench/compare_honk_to_plonk_ultra.sh @@ -1,7 +1,7 @@ -#!/bin/bash +#!/usr/bin/env bash # This script is used to compare the results of honk_bench between baseline (master) and -# the branch from which the script is run. Simply check out the branch of interest, ensure +# the branch from which the script is run. Simply check out the branch of interest, ensure # it is up to date with local master, and run the script. echo -e '\nComparing Ultra Plonk/Honk benchmarks.' @@ -19,21 +19,21 @@ pip3 install --user -r $BUILD_DIR/_deps/benchmark-src/requirements.txt cd $BASE_DIR mkdir $BENCH_RESULTS_DIR -# +# echo -e '\nBuilding and running Standard benchmarks..' # rm -rf $BUILD_DIR -cmake --preset bench > /dev/null && cmake --build --preset bench --target ultra_plonk_bench +cmake --preset bench > /dev/null && cmake --build --preset bench --target ultra_plonk_bench cd build-bench PLONK_BENCH_RESULTS="$BENCH_RESULTS_DIR/plonk_bench.json" ./bin/ultra_plonk_bench --benchmark_format=json > $PLONK_BENCH_RESULTS cd .. -cmake --preset bench > /dev/null && cmake --build --preset bench --target ultra_honk_bench +cmake --preset bench > /dev/null && cmake --build --preset bench --target ultra_honk_bench cd build-bench HONK_BENCH_RESULTS="$BENCH_RESULTS_DIR/honk_bench.json" ./bin/ultra_honk_bench --benchmark_format=json > $HONK_BENCH_RESULTS -# Call compare.py on the results (json) to get high level statistics. +# Call compare.py on the results (json) to get high level statistics. # See docs at https://github.com/google/benchmark/blob/main/docs/tools.md for more details. $BENCH_TOOLS_DIR/compare.py benchmarks $PLONK_BENCH_RESULTS $HONK_BENCH_RESULTS diff --git a/barretenberg/scripts/bindgen.sh b/barretenberg/scripts/bindgen.sh index 1a2034a213a..e3080a84824 100755 --- a/barretenberg/scripts/bindgen.sh +++ b/barretenberg/scripts/bindgen.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -eu #find ./cpp/src -type f -name "c_bind*.hpp" | ./scripts/decls_json.py > exports.json diff --git a/barretenberg/sol/scripts/init.sh b/barretenberg/sol/scripts/init.sh index 147adc9ae21..70868e37808 100755 --- a/barretenberg/sol/scripts/init.sh +++ b/barretenberg/sol/scripts/init.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash PLONK_FLAVOUR="ultra" diff --git a/barretenberg/sol/scripts/run_fuzzer.sh b/barretenberg/sol/scripts/run_fuzzer.sh index e6e235a85e5..2c76ad1de43 100755 --- a/barretenberg/sol/scripts/run_fuzzer.sh +++ b/barretenberg/sol/scripts/run_fuzzer.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash PLONK_FLAVOUR=${1:-"ultra"} CIRCUIT_FLAVOUR=${2:-"blake"} diff --git a/barretenberg/ts/bootstrap.sh b/barretenberg/ts/bootstrap.sh index 8b2d5b76c66..2f0fa19bb81 100755 --- a/barretenberg/ts/bootstrap.sh +++ b/barretenberg/ts/bootstrap.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -eu cd "$(dirname "$0")" diff --git a/barretenberg/ts/scripts/run_tests b/barretenberg/ts/scripts/run_tests index ed93c9a8091..0f0d2895cec 100755 --- a/barretenberg/ts/scripts/run_tests +++ b/barretenberg/ts/scripts/run_tests @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -xe $(aws ecr get-login --region us-east-2 --no-include-email) 2> /dev/null diff --git a/bootstrap.sh b/bootstrap.sh index 5a953eee6b5..ac402f07baa 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Usage: # Bootstraps the repo. End to end tests should be runnable after a bootstrap: # ./bootstrap.sh diff --git a/bootstrap/bootstrap_test.sh b/bootstrap/bootstrap_test.sh index 805f0d0ef0e..8e05b2650ef 100755 --- a/bootstrap/bootstrap_test.sh +++ b/bootstrap/bootstrap_test.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # This script takes the state of your current repository, and clones it inside of a docker container. # You likely don't have a fresh clone, and it's paramount that to test bootstrapping, we don't have any # intermediate build state in the context. diff --git a/bootstrap_docker.sh b/bootstrap_docker.sh index 6fc48b2b118..6d086d1d331 100755 --- a/bootstrap_docker.sh +++ b/bootstrap_docker.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # This script builds the projects listed in build_manifest.sh, terminating when it reaches PROJECT_NAME. # If run from within a project, it will build only that project, unless env var ONLY_TARGET=false. # diff --git a/build-system/remote/bootstrap_build_instance.sh b/build-system/remote/bootstrap_build_instance.sh index 535bcdd7ce7..c911eb113b3 100644 --- a/build-system/remote/bootstrap_build_instance.sh +++ b/build-system/remote/bootstrap_build_instance.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null sudo apt update diff --git a/build-system/scripts/add_timestamps b/build-system/scripts/add_timestamps index 8b658925ba5..230d51fb626 100755 --- a/build-system/scripts/add_timestamps +++ b/build-system/scripts/add_timestamps @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash while IFS= read -r line; do printf '%(%Y-%m-%d %H:%M:%S)T %s\n' -1 "$line" done diff --git a/build-system/scripts/build b/build-system/scripts/build index 6906a275149..c82e6bde0a6 100755 --- a/build-system/scripts/build +++ b/build-system/scripts/build @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # # Builds a docker image and pushes it to it's repository. Leverages caches where possible. # Cached images include previous successfully built images (including multi-stages) built on this branch. diff --git a/build-system/scripts/build_local b/build-system/scripts/build_local index cdb9f3a60f3..0bc99f17d4a 100755 --- a/build-system/scripts/build_local +++ b/build-system/scripts/build_local @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Builds the PROJECTS in the given order. # Will terminate build at TARGET_PROJECT (if given). # Will only build TARGET_PROJECT if ONLY_TARGET given. diff --git a/build-system/scripts/calculate_content_hash b/build-system/scripts/calculate_content_hash index 28ae8ff2e62..7b7b68ade71 100755 --- a/build-system/scripts/calculate_content_hash +++ b/build-system/scripts/calculate_content_hash @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash [ -n "${BUILD_SYSTEM_DEBUG:-}" ] && set -x # conditionally trace set -euo pipefail diff --git a/build-system/scripts/calculate_image_tag b/build-system/scripts/calculate_image_tag index c273648287c..f2a3cea871f 100755 --- a/build-system/scripts/calculate_image_tag +++ b/build-system/scripts/calculate_image_tag @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Return a repositories build cache image tag based on content hash. # If the second argument is set: # It's used to suffix the tag with the given unique arch descriptor. diff --git a/build-system/scripts/calculate_image_uri b/build-system/scripts/calculate_image_uri index 8efd7ab4cdc..c107647434c 100755 --- a/build-system/scripts/calculate_image_uri +++ b/build-system/scripts/calculate_image_uri @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash [ -n "${BUILD_SYSTEM_DEBUG:-}" ] && set -x # conditionally trace set -eu diff --git a/build-system/scripts/calculate_rebuild_files b/build-system/scripts/calculate_rebuild_files index 9be1afd4912..49e07634955 100755 --- a/build-system/scripts/calculate_rebuild_files +++ b/build-system/scripts/calculate_rebuild_files @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash [ -n "${BUILD_SYSTEM_DEBUG:-}" ] && set -x # conditionally trace set -eu diff --git a/build-system/scripts/check_rebuild b/build-system/scripts/check_rebuild index 76f99c6540e..df2291065e4 100755 --- a/build-system/scripts/check_rebuild +++ b/build-system/scripts/check_rebuild @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # If this script fails (nonzero exit), then the caller should rebuild. [ -n "${BUILD_SYSTEM_DEBUG:-}" ] && set -x # conditionally trace set -euo pipefail diff --git a/build-system/scripts/clean_image_tags b/build-system/scripts/clean_image_tags index 832fdf4cda6..9c4557e68c6 100755 --- a/build-system/scripts/clean_image_tags +++ b/build-system/scripts/clean_image_tags @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash [ -n "${BUILD_SYSTEM_DEBUG:-}" ] && set -x # conditionally trace set -e @@ -20,7 +20,7 @@ fi # Collect all the commits ids in the repository and remove the remote for faster lookups # See warning in https://github.blog/2020-12-21-get-up-to-speed-with-partial-clone-and-shallow-clone/ -git config fetch.recurseSubmodules false +git config fetch.recurseSubmodules false git fetch --filter=tree:0 origin ORIGIN_URL=$(git remote get-url origin) git remote remove origin @@ -29,7 +29,7 @@ git remote remove origin # This happens for all commits tagged for PRs that then get squashed and merged IFS=$'\n' for TAG in $IMAGE_TAGS; do - if [[ $TAG =~ ^cache-[0-9a-fA-F]+-builder$ ]]; then + if [[ $TAG =~ ^cache-[0-9a-fA-F]+-builder$ ]]; then TAG_COMMIT=$(echo "$TAG" | cut -d '-' -f 2) if git cat-file -e $TAG_COMMIT; then echo "Commit for $TAG found" diff --git a/build-system/scripts/cond_run_compose b/build-system/scripts/cond_run_compose index ee412325a6a..d1d14c6baca 100755 --- a/build-system/scripts/cond_run_compose +++ b/build-system/scripts/cond_run_compose @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash [ -n "${BUILD_SYSTEM_DEBUG:-}" ] && set -x # conditionally trace set -eu diff --git a/build-system/scripts/cond_run_container b/build-system/scripts/cond_run_container index ca8d67fc0bd..12badea45af 100755 --- a/build-system/scripts/cond_run_container +++ b/build-system/scripts/cond_run_container @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Conditionally runs a script if the REPOSITORY content hash has changed and we haven't had a successful run. # # Arguments are: diff --git a/build-system/scripts/cond_run_script b/build-system/scripts/cond_run_script index c1ada5f8cf2..1eb6b3695d9 100755 --- a/build-system/scripts/cond_run_script +++ b/build-system/scripts/cond_run_script @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Conditionally runs a script if the REPOSITORY content hash has changed and we haven't had a successful run. # # Arguments are: diff --git a/build-system/scripts/cond_spot_run_build b/build-system/scripts/cond_spot_run_build index 3333e5dec7c..a2e2663de89 100755 --- a/build-system/scripts/cond_spot_run_build +++ b/build-system/scripts/cond_spot_run_build @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash [ -n "${BUILD_SYSTEM_DEBUG:-}" ] && set -x # conditionally trace set -euo pipefail diff --git a/build-system/scripts/cond_spot_run_compose b/build-system/scripts/cond_spot_run_compose index 51a4529471a..56da3e3da4e 100755 --- a/build-system/scripts/cond_spot_run_compose +++ b/build-system/scripts/cond_spot_run_compose @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash [ -n "${BUILD_SYSTEM_DEBUG:-}" ] && set -x # conditionally trace set -euo pipefail diff --git a/build-system/scripts/cond_spot_run_container b/build-system/scripts/cond_spot_run_container index 48876a65f3b..5b2ebc71f32 100755 --- a/build-system/scripts/cond_spot_run_container +++ b/build-system/scripts/cond_spot_run_container @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash [ -n "${BUILD_SYSTEM_DEBUG:-}" ] && set -x # conditionally trace set -eu diff --git a/build-system/scripts/cond_spot_run_script b/build-system/scripts/cond_spot_run_script index 4b1832127ac..23a678fcd32 100755 --- a/build-system/scripts/cond_spot_run_script +++ b/build-system/scripts/cond_spot_run_script @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Conditionally runs a script on a remote spot instance if the REPOSITORY content hash has changed and we haven't had a # successful run. # The TAG_POSTFIX is used by cond_spot_run_test whereby we use an image tag postfixed with JOB_NAME to identifify if @@ -19,7 +19,12 @@ CPUS=$2 ARCH=$3 shift 3 -BASE_TAG=$(calculate_image_tag $REPOSITORY) +MULTIARCH=$(query_manifest multiarch $REPOSITORY) +if [ "$MULTIARCH" == "host" ]; then + BASE_TAG=$(calculate_image_tag $REPOSITORY $ARCH) +else + BASE_TAG=$(calculate_image_tag $REPOSITORY) +fi SUCCESS_TAG=$BASE_TAG if [ -n "${TAG_POSTFIX:-}" ]; then diff --git a/build-system/scripts/cond_spot_run_test b/build-system/scripts/cond_spot_run_test index e8b8f71358d..cc48ffc742e 100755 --- a/build-system/scripts/cond_spot_run_test +++ b/build-system/scripts/cond_spot_run_test @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash [ -n "${BUILD_SYSTEM_DEBUG:-}" ] && set -x # conditionally trace set -euo pipefail diff --git a/build-system/scripts/create_ecr_manifest b/build-system/scripts/create_ecr_manifest index 5bda420039d..fcc96d7651e 100755 --- a/build-system/scripts/create_ecr_manifest +++ b/build-system/scripts/create_ecr_manifest @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # This script: # 1. Logs into ECR and ensures we have the given repository # 2. Computes the image uri of the cached images for the given repository given the list of architectures diff --git a/build-system/scripts/deploy b/build-system/scripts/deploy index ca43d5b9cfb..a158175c414 100755 --- a/build-system/scripts/deploy +++ b/build-system/scripts/deploy @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash [ -n "${BUILD_SYSTEM_DEBUG:-}" ] && set -x # conditionally trace set -eu diff --git a/build-system/scripts/deploy_dockerhub b/build-system/scripts/deploy_dockerhub index 606e0952b5d..b8d925b0711 100755 --- a/build-system/scripts/deploy_dockerhub +++ b/build-system/scripts/deploy_dockerhub @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash [ -n "${BUILD_SYSTEM_DEBUG:-}" ] && set -x # conditionally trace set -eu diff --git a/build-system/scripts/deploy_ecr b/build-system/scripts/deploy_ecr index 3be534694c7..c156f99e71e 100755 --- a/build-system/scripts/deploy_ecr +++ b/build-system/scripts/deploy_ecr @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash [ -n "${BUILD_SYSTEM_DEBUG:-}" ] && set -x # conditionally trace set -eu diff --git a/build-system/scripts/deploy_global b/build-system/scripts/deploy_global index 28b70a28619..2267474706f 100755 --- a/build-system/scripts/deploy_global +++ b/build-system/scripts/deploy_global @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Deployment script for global service (e.g. company website and metrics). [ -n "${BUILD_SYSTEM_DEBUG:-}" ] && set -x # conditionally trace set -eu diff --git a/build-system/scripts/deploy_npm b/build-system/scripts/deploy_npm index a35d68c4650..16df5a156d0 100755 --- a/build-system/scripts/deploy_npm +++ b/build-system/scripts/deploy_npm @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash [ -n "${BUILD_SYSTEM_DEBUG:-}" ] && set -x # conditionally trace set -eu diff --git a/build-system/scripts/deploy_s3 b/build-system/scripts/deploy_s3 index caaa4d00bd9..87acbf004d9 100755 --- a/build-system/scripts/deploy_s3 +++ b/build-system/scripts/deploy_s3 @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash [ -n "${BUILD_SYSTEM_DEBUG:-}" ] && set -x # conditionally trace set -eu diff --git a/build-system/scripts/deploy_service b/build-system/scripts/deploy_service index b014ca0d823..83c45128141 100755 --- a/build-system/scripts/deploy_service +++ b/build-system/scripts/deploy_service @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash [ -n "${BUILD_SYSTEM_DEBUG:-}" ] && set -x # conditionally trace set -eu diff --git a/build-system/scripts/deploy_terraform b/build-system/scripts/deploy_terraform index ce2231853aa..b81c4d3f4b2 100755 --- a/build-system/scripts/deploy_terraform +++ b/build-system/scripts/deploy_terraform @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash [ -n "${BUILD_SYSTEM_DEBUG:-}" ] && set -x # conditionally trace set -eu diff --git a/build-system/scripts/dockerhub_login b/build-system/scripts/dockerhub_login index dae523fb43b..50a2068377b 100755 --- a/build-system/scripts/dockerhub_login +++ b/build-system/scripts/dockerhub_login @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -eu # Retries up to 3 times with 10 second intervals for i in $(seq 1 3); do diff --git a/build-system/scripts/ecr_login b/build-system/scripts/ecr_login index 54a8e6d36da..331b49d4024 100755 --- a/build-system/scripts/ecr_login +++ b/build-system/scripts/ecr_login @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -eu REGION=${1:-$ECR_REGION} # Retries up to 3 times with 10 second intervals diff --git a/build-system/scripts/ensure_repo b/build-system/scripts/ensure_repo index b767976354f..b71c0fabb2f 100755 --- a/build-system/scripts/ensure_repo +++ b/build-system/scripts/ensure_repo @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Logs the shell into the ECR instance at the given region, establishes if the given repository exists, creates it if it # doesn't, and re-applies thie lifecycle policy (determines when images should be automatically deleted) if it does. [ -n "${BUILD_SYSTEM_DEBUG:-}" ] && set -x # conditionally trace diff --git a/build-system/scripts/ensure_terraform b/build-system/scripts/ensure_terraform index d7444aa4e4c..ce53dba1b31 100755 --- a/build-system/scripts/ensure_terraform +++ b/build-system/scripts/ensure_terraform @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Downloads and installs `terraform` if it's not installed. [ -n "${BUILD_SYSTEM_DEBUG:-}" ] && set -x # conditionally trace set -eu diff --git a/build-system/scripts/extract_repo b/build-system/scripts/extract_repo index c2579b5a46f..6bdae1027f9 100755 --- a/build-system/scripts/extract_repo +++ b/build-system/scripts/extract_repo @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Given a repository, extracts the builds entire /usr/src dir to the given path. [ -n "${BUILD_SYSTEM_DEBUG:-}" ] && set -x # conditionally trace set -eu diff --git a/build-system/scripts/extract_tag_version b/build-system/scripts/extract_tag_version index d142458104d..c0f7c3fd165 100755 --- a/build-system/scripts/extract_tag_version +++ b/build-system/scripts/extract_tag_version @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # This script takes a repository name as variable, # then checks if the commit tag variable (if any) # is a valid semver & echoes that valid semver. @@ -28,7 +28,7 @@ if [[ "$COMMIT_TAG" == *"/"* ]]; then COMMIT_TAG_VERSION="${COMMIT_TAG#*/}" echo "Tag was made for: $REPO_NAME" >&2 echo "Version: $COMMIT_TAG_VERSION" >&2 - + # Check if REPO_NAME is equal to REPOSITORY if [[ "$REPO_NAME" != "$REPOSITORY" ]]; then echo "REPO_NAME ($REPO_NAME) does not match REPOSITORY ($REPOSITORY). Exiting..." >&2 diff --git a/build-system/scripts/image_exists b/build-system/scripts/image_exists index 0a4bee54d7a..0ad9d90ae69 100755 --- a/build-system/scripts/image_exists +++ b/build-system/scripts/image_exists @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -eu # Returns true if the given image exists in the current ECR. aws ecr describe-images --region=$ECR_REGION --repository-name=$1 --image-ids=imageTag=$2 > /dev/null 2>&1 diff --git a/build-system/scripts/init_submodules b/build-system/scripts/init_submodules index a4a9cd62db6..0b89b089866 100755 --- a/build-system/scripts/init_submodules +++ b/build-system/scripts/init_submodules @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # For a given repository, init any required submodules. [ -n "${BUILD_SYSTEM_DEBUG:-}" ] && set -x # conditionally trace set -euo pipefail diff --git a/build-system/scripts/query_manifest b/build-system/scripts/query_manifest index 1fee0ee5759..a6e84650331 100755 --- a/build-system/scripts/query_manifest +++ b/build-system/scripts/query_manifest @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash [ -n "${BUILD_SYSTEM_DEBUG:-}" ] && set -x # conditionally trace set -eu CMD=$1 diff --git a/build-system/scripts/remote_run_script b/build-system/scripts/remote_run_script index e9ef84d723d..8e1d8adf38c 100755 --- a/build-system/scripts/remote_run_script +++ b/build-system/scripts/remote_run_script @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copies the runner script to the remote instance, runs it giving it script and args to run. # The runner script checks out the repository first and runs setup-env. # diff --git a/build-system/scripts/remote_runner b/build-system/scripts/remote_runner index ce1a567a198..6283050283c 100755 --- a/build-system/scripts/remote_runner +++ b/build-system/scripts/remote_runner @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash [ -n "${BUILD_SYSTEM_DEBUG:-}" ] && set -x # conditionally trace set -eu diff --git a/build-system/scripts/request_spot b/build-system/scripts/request_spot index 35c4d650bac..3d669fed1df 100755 --- a/build-system/scripts/request_spot +++ b/build-system/scripts/request_spot @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash [ -n "${BUILD_SYSTEM_DEBUG:-}" ] && set -x # conditionally trace set -eu diff --git a/build-system/scripts/setup_env b/build-system/scripts/setup_env index 8e4058a1c53..3486e5f8653 100755 --- a/build-system/scripts/setup_env +++ b/build-system/scripts/setup_env @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # This script sets up the global build environment. This should be called before any other build scripts, # as the other build scripts assume these global variables are set. The global variables are written to # the file in $BASH_ENV, which means that any new bash shells launched within the lifetime of the machine diff --git a/build-system/scripts/should_deploy b/build-system/scripts/should_deploy index 53f295b191f..283191f51f3 100755 --- a/build-system/scripts/should_deploy +++ b/build-system/scripts/should_deploy @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Returns success if we are expected to do a deployment. # Right now, that's only if we're master. set -eu diff --git a/build-system/scripts/should_release b/build-system/scripts/should_release index 5473fc6da76..701b8a375db 100755 --- a/build-system/scripts/should_release +++ b/build-system/scripts/should_release @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Returns true if we are expected to proceed with a release job. # Specifically if we have a commit tag, are master, or are being forced to release. # This script should be used at the start of all release steps to early out PR runs. diff --git a/build-system/scripts/spot_run_script b/build-system/scripts/spot_run_script index 7a2377973d5..d5e77e35712 100755 --- a/build-system/scripts/spot_run_script +++ b/build-system/scripts/spot_run_script @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Runs a test script on a remote spot instance. Arguments are: # 1. NAME: Used to identify spot jobs. # 2. CPUS: Number of cpus on spot request. diff --git a/build-system/scripts/tag_remote_image b/build-system/scripts/tag_remote_image index bc7675b237c..0bb9e2a390f 100755 --- a/build-system/scripts/tag_remote_image +++ b/build-system/scripts/tag_remote_image @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash [ -n "${BUILD_SYSTEM_DEBUG:-}" ] && set -x # conditionally trace set -eu @@ -34,7 +34,7 @@ if [ "$EXISTING_TAG_MANIFEST" != "$NEW_TAG_MANIFEST" ]; then --image-tag $NEW_TAG \ --image-manifest "$EXISTING_TAG_MANIFEST" 2>&1) TAG_EXIT_CODE=$? - + # If we failed to tag due to too many tags on this image, then clean some of them up and try again if [ $TAG_EXIT_CODE -ne 0 ] && $(echo $TAG_RESULT | grep -q LimitExceededException); then echo "Failed to tag due to limit exceeded. Starting tag cleanup." diff --git a/build-system/scripts/untag_remote_image b/build-system/scripts/untag_remote_image index f79fee729bc..aa913c1200b 100755 --- a/build-system/scripts/untag_remote_image +++ b/build-system/scripts/untag_remote_image @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash REPOSITORY=$1 TAG=$2 aws ecr batch-delete-image --region=$ECR_REGION --repository-name $REPOSITORY --image-ids imageTag=$2 > /dev/null \ No newline at end of file diff --git a/build-system/scripts/upload_logs_to_s3 b/build-system/scripts/upload_logs_to_s3 index ede934edae5..25c7fe2e50a 100755 --- a/build-system/scripts/upload_logs_to_s3 +++ b/build-system/scripts/upload_logs_to_s3 @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Uploads to S3 the contents of the log file mounted on the end-to-end container, # which contains log entries with an associated event and metrics for it. diff --git a/build-system/start_interactive b/build-system/start_interactive index 2ed1f2df13a..64e24499782 100755 --- a/build-system/start_interactive +++ b/build-system/start_interactive @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Starts an interactive shell with the build system initialised. # Good for playing around with build system on development machines. diff --git a/build_manifest.yml b/build_manifest.yml index 588c3c70a93..43bce1a4071 100644 --- a/build_manifest.yml +++ b/build_manifest.yml @@ -216,4 +216,4 @@ docs: yellow-paper: buildDir: yellow-paper rebuildPatterns: - - ^yellow-paper/ \ No newline at end of file + - ^yellow-paper/ diff --git a/circuits/cpp/bootstrap.sh b/circuits/cpp/bootstrap.sh index 6a64d541b7b..440bf1e44c6 100755 --- a/circuits/cpp/bootstrap.sh +++ b/circuits/cpp/bootstrap.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -eu cd "$(dirname "$0")" diff --git a/circuits/cpp/format.sh b/circuits/cpp/format.sh index e12e84ab27a..54047bd6def 100755 --- a/circuits/cpp/format.sh +++ b/circuits/cpp/format.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -eu if [ "${1:-}" == "staged" ]; then diff --git a/circuits/cpp/scripts/build_run_tests_docker_local b/circuits/cpp/scripts/build_run_tests_docker_local index 19eb1784f71..f861fecbfa8 100755 --- a/circuits/cpp/scripts/build_run_tests_docker_local +++ b/circuits/cpp/scripts/build_run_tests_docker_local @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash [ -n "${BUILD_SYSTEM_DEBUG:-}" ] && set -x # conditionally trace set -eu diff --git a/circuits/cpp/scripts/collect_coverage_information.sh b/circuits/cpp/scripts/collect_coverage_information.sh index cac9393a9b6..45ad2764a22 100755 --- a/circuits/cpp/scripts/collect_coverage_information.sh +++ b/circuits/cpp/scripts/collect_coverage_information.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Check that the correct number of args have been provided if [ $# -ne 2 ]; then @@ -67,7 +67,7 @@ if [ ${#non_empty_profiles[@]} -gt 1 ]; then additional_objects+="-object $WORKING_DIRECTORY/bin/${non_empty_profile_base}_tests " done object_string=${additional_objects#"-object"} - + # Output the coverage report into `all_tests_coverage_report` folder rm -rf "$WORKING_DIRECTORY/all_tests_coverage_report" mkdir "$WORKING_DIRECTORY/all_tests_coverage_report" diff --git a/circuits/cpp/scripts/run_tests b/circuits/cpp/scripts/run_tests index dd7d7e21388..62fbd90153b 100755 --- a/circuits/cpp/scripts/run_tests +++ b/circuits/cpp/scripts/run_tests @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash [ -n "${BUILD_SYSTEM_DEBUG:-}" ] && set -x # conditionally trace set -eu diff --git a/circuits/cpp/scripts/run_tests_local b/circuits/cpp/scripts/run_tests_local index d65ff5f358f..4c12807414e 100755 --- a/circuits/cpp/scripts/run_tests_local +++ b/circuits/cpp/scripts/run_tests_local @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash [ -n "${BUILD_SYSTEM_DEBUG:-}" ] && set -x # conditionally trace set -eu diff --git a/circuits/cpp/scripts/tidy.sh b/circuits/cpp/scripts/tidy.sh index 3283fb89b62..7faab2658c6 100755 --- a/circuits/cpp/scripts/tidy.sh +++ b/circuits/cpp/scripts/tidy.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -eu # Run clang-tidy on all C++ source files diff --git a/docs/deploy_netlify.sh b/docs/deploy_netlify.sh index 82b447119f6..24c7c1f3845 100755 --- a/docs/deploy_netlify.sh +++ b/docs/deploy_netlify.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash [ -n "${BUILD_SYSTEM_DEBUG:-}" ] && set -x # conditionally trace set -eu diff --git a/docs/scripts/build.sh b/docs/scripts/build.sh index e06ae5f2aa9..eb63a05887d 100755 --- a/docs/scripts/build.sh +++ b/docs/scripts/build.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -eo pipefail # Helper function for building packages in yarn project @@ -10,7 +10,7 @@ build_package() { (cd "yarn-project/$package_name" && $build_command) } -# Build script. If run on Netlify, first it needs to compile all yarn-projects +# Build script. If run on Netlify, first it needs to compile all yarn-projects # that are involved in typedoc in order to generate their type information. if [ -n "$NETLIFY" ]; then # Move to project root diff --git a/iac/mainnet-fork/scripts/run_nginx_anvil.sh b/iac/mainnet-fork/scripts/run_nginx_anvil.sh index 4b701f13256..38788424ed7 100755 --- a/iac/mainnet-fork/scripts/run_nginx_anvil.sh +++ b/iac/mainnet-fork/scripts/run_nginx_anvil.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -eum pipefail diff --git a/iac/mainnet-fork/scripts/wait_for_fork b/iac/mainnet-fork/scripts/wait_for_fork index 326582c25af..831e06723e2 100755 --- a/iac/mainnet-fork/scripts/wait_for_fork +++ b/iac/mainnet-fork/scripts/wait_for_fork @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -e # When destroying and applying mainnet fork terraform, it may not be diff --git a/l1-contracts/bootstrap.sh b/l1-contracts/bootstrap.sh index db2a71b8c75..f776b6072dc 100755 --- a/l1-contracts/bootstrap.sh +++ b/l1-contracts/bootstrap.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -eu cd "$(dirname "$0")" diff --git a/l1-contracts/scripts/ci_deploy_contracts.sh b/l1-contracts/scripts/ci_deploy_contracts.sh index 128a1702f31..aaedb6f2f7d 100755 --- a/l1-contracts/scripts/ci_deploy_contracts.sh +++ b/l1-contracts/scripts/ci_deploy_contracts.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash export ETHEREUM_HOST=https://$DEPLOY_TAG-mainnet-fork.aztec.network:8545/$FORK_API_KEY diff --git a/l1-contracts/scripts/deploy_contracts.sh b/l1-contracts/scripts/deploy_contracts.sh index 6223a0719a9..0bd743e1567 100755 --- a/l1-contracts/scripts/deploy_contracts.sh +++ b/l1-contracts/scripts/deploy_contracts.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -eu # Sets up defaults then runs the E2E Setup script to perform contract deployments diff --git a/noir/.github/actions/docs/build-status/script.sh b/noir/.github/actions/docs/build-status/script.sh index 0b282557cf2..2e86de6c173 100755 --- a/noir/.github/actions/docs/build-status/script.sh +++ b/noir/.github/actions/docs/build-status/script.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash BRANCH_NAME=$(echo "$BRANCH_NAME" | sed -e "s#refs/[^/]*/##") DEPLOY_STATUS=$(curl -X GET "https://api.netlify.com/api/v1/sites/$SITE_ID/deploys?branch=$BRANCH_NAME" | jq -r '.[] | select(.created_at != null) | .state' | head -1) diff --git a/noir/Dockerfile b/noir/Dockerfile index ac818cb8bd2..de63983db3e 100644 --- a/noir/Dockerfile +++ b/noir/Dockerfile @@ -1,15 +1,10 @@ -FROM rust:alpine3.17 -RUN apk update \ - && apk upgrade \ - && apk add --no-cache \ - build-base \ - bash +FROM rust:bookworm WORKDIR /usr/src/noir COPY . . RUN ./scripts/bootstrap_native.sh -# When running the container, mount the current working directory to /project. -FROM alpine:3.17 +# When running the container, mount the users home directory to /root +FROM ubuntu:lunar COPY --from=0 /usr/src/noir/target/release/nargo /usr/src/noir/target/release/nargo -WORKDIR /project +WORKDIR /root ENTRYPOINT ["/usr/src/noir/target/release/nargo"] \ No newline at end of file diff --git a/noir/bootstrap.sh b/noir/bootstrap.sh index bf672ac0ad2..5ebe7ade090 100755 --- a/noir/bootstrap.sh +++ b/noir/bootstrap.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -eu cd $(dirname "$0") diff --git a/noir/compiler/integration-tests/scripts/codegen-verifiers.sh b/noir/compiler/integration-tests/scripts/codegen-verifiers.sh index 13667038728..4518141fc13 100644 --- a/noir/compiler/integration-tests/scripts/codegen-verifiers.sh +++ b/noir/compiler/integration-tests/scripts/codegen-verifiers.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash self_path=$(dirname "$(readlink -f "$0")") diff --git a/noir/scripts/bootstrap_native.sh b/noir/scripts/bootstrap_native.sh index 693a9d9678e..b5e004106ff 100755 --- a/noir/scripts/bootstrap_native.sh +++ b/noir/scripts/bootstrap_native.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -eu cd $(dirname "$0")/.. diff --git a/noir/scripts/bootstrap_packages.sh b/noir/scripts/bootstrap_packages.sh index 5fce2675037..1363acf51a6 100755 --- a/noir/scripts/bootstrap_packages.sh +++ b/noir/scripts/bootstrap_packages.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -eu cd $(dirname "$0")/.. diff --git a/noir/scripts/install_wasm-bindgen.sh b/noir/scripts/install_wasm-bindgen.sh index 5e9f9127506..c6e85bac50b 100755 --- a/noir/scripts/install_wasm-bindgen.sh +++ b/noir/scripts/install_wasm-bindgen.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -eu cd $(dirname "$0")/.. diff --git a/noir/test_programs/gates_report.sh b/noir/test_programs/gates_report.sh index e06e6812e9d..4192c581376 100755 --- a/noir/test_programs/gates_report.sh +++ b/noir/test_programs/gates_report.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -e # These tests are incompatible with gas reporting diff --git a/noir/test_programs/rebuild.sh b/noir/test_programs/rebuild.sh index dfc3dc5c967..fd3e4478d62 100755 --- a/noir/test_programs/rebuild.sh +++ b/noir/test_programs/rebuild.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -e process_dir() { diff --git a/scripts/ci/assemble_e2e_benchmark.sh b/scripts/ci/assemble_e2e_benchmark.sh index 7456d4e1cbc..4a7b1bbe015 100755 --- a/scripts/ci/assemble_e2e_benchmark.sh +++ b/scripts/ci/assemble_e2e_benchmark.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Grabs the log files uploaded in yarn-project/end-to-end/scripts/upload_logs_to_s3.sh # that contain representative benchmarks, extracts whatever metrics are interesting, # and assembles a single file that shows the current state of the repository. @@ -70,7 +70,7 @@ if [ -n "${BENCHMARK_LATEST_FILE:-}" ]; then aws s3 cp $BENCHMARK_FILE_JSON "s3://${BUCKET_NAME}/${BENCHMARK_LATEST_FILE}" fi -# If on a pull request, get the data from the most recent commit on master where it's available, +# If on a pull request, get the data from the most recent commit on master where it's available, # generate a markdown comment, and post it on the pull request if [ -n "${CIRCLE_PULL_REQUEST:-}" ]; then MASTER_COMMIT_HASH=$(curl -s "https://api.github.com/repos/AztecProtocol/aztec-packages/pulls/${CIRCLE_PULL_REQUEST##*/}" | jq -r '.base.sha') @@ -88,11 +88,9 @@ if [ -n "${CIRCLE_PULL_REQUEST:-}" ]; then done set -e - if [ -z "${BASE_COMMIT_HASH:-}" ]; then + if [ -z "${BASE_COMMIT_HASH:-}" ]; then echo "No base commit data found" fi (yarn-project/scripts/run_script.sh workspace @aztec/scripts bench-comment && echo "commented on pr $CIRCLE_PULL_REQUEST") || echo "failed commenting on pr" fi - - diff --git a/scripts/ci/store_test_benchmark_logs b/scripts/ci/store_test_benchmark_logs index 3554aa746d2..c9ae07fc96a 100755 --- a/scripts/ci/store_test_benchmark_logs +++ b/scripts/ci/store_test_benchmark_logs @@ -1,5 +1,5 @@ -#!/bin/bash -# Script for storing barretenberg benchmark results. +#!/usr/bin/env bash +# Script for storing barretenberg benchmark results. # Uploads results to the AztecProtocol/benchmark-archive repository. [ -n "${BUILD_SYSTEM_DEBUG:-}" ] && set -x # conditionally trace @@ -36,7 +36,7 @@ cat /tmp/csv/new.csv \ # If there actually were any logs, update the information in the benchmark repository if [ -s /tmp/csv/trimmed.csv ]; then cd /tmp - + git clone --depth 1 https://$AZTEC_GITHUB_TOKEN:@github.com/AztecProtocol/benchmark-archive cd benchmark-archive diff --git a/scripts/git-subrepo/note/init-test b/scripts/git-subrepo/note/init-test index a20854de88a..810dae14a4d 100755 --- a/scripts/git-subrepo/note/init-test +++ b/scripts/git-subrepo/note/init-test @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -ex cat $0 # Show this script in the output diff --git a/scripts/git-subrepo/note/recreate-rebase-conflict.sh b/scripts/git-subrepo/note/recreate-rebase-conflict.sh index 8e1103e575d..6dc0a51e300 100644 --- a/scripts/git-subrepo/note/recreate-rebase-conflict.sh +++ b/scripts/git-subrepo/note/recreate-rebase-conflict.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -eu set -x diff --git a/scripts/git-subrepo/note/subtree-rebase-fail-example/test.bash b/scripts/git-subrepo/note/subtree-rebase-fail-example/test.bash index df8b818cee6..9118236848a 100755 --- a/scripts/git-subrepo/note/subtree-rebase-fail-example/test.bash +++ b/scripts/git-subrepo/note/subtree-rebase-fail-example/test.bash @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -ex @@ -24,6 +24,6 @@ git clone repo1 repo3 git subrepo clone ../repo2 subrepo bash git rebase -i HEAD^ - git log -p + git log -p ls ) diff --git a/scripts/git-subrepo/note/test-subrepo-push.sh b/scripts/git-subrepo/note/test-subrepo-push.sh index afceb5efa92..13b76e47fc8 100644 --- a/scripts/git-subrepo/note/test-subrepo-push.sh +++ b/scripts/git-subrepo/note/test-subrepo-push.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -ex diff --git a/scripts/git-subrepo/note/test.sh b/scripts/git-subrepo/note/test.sh index fae278795d1..d27548f0937 100755 --- a/scripts/git-subrepo/note/test.sh +++ b/scripts/git-subrepo/note/test.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -x diff --git a/scripts/git_subrepo.sh b/scripts/git_subrepo.sh index df9743a2bd5..969789cdcc8 100755 --- a/scripts/git_subrepo.sh +++ b/scripts/git_subrepo.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -eu SCRIPT_DIR=$(dirname "$(realpath "$0")") @@ -11,10 +11,10 @@ fi # git subrepo is quite nice, but has one flaw in our workflow: # We frequently squash commits in PRs, and we might update the .gitrepo file -# with a parent commit that later does not exist. +# with a parent commit that later does not exist. # A backup heuristic is used to later find the squashed commit's parent -# using the .gitrepo file's git history. This might be brittle -# in the face of e.g. a .gitrepo whitespace change, but it's a fallback, +# using the .gitrepo file's git history. This might be brittle +# in the face of e.g. a .gitrepo whitespace change, but it's a fallback, # we only have this issue in master, and the file should only be edited # generally by subrepo commands. SUBREPO_PATH="${2:-}" diff --git a/scripts/migrate_barretenberg_branch.sh b/scripts/migrate_barretenberg_branch.sh index 8cf396867c3..36c128a6232 100755 --- a/scripts/migrate_barretenberg_branch.sh +++ b/scripts/migrate_barretenberg_branch.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -eu # Usage: ./this.sh diff --git a/scripts/tmux-splits b/scripts/tmux-splits index 296cdb36632..6b1e28f8559 100755 --- a/scripts/tmux-splits +++ b/scripts/tmux-splits @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Launches tmux with 1 window that has 2 panes running, from top to bottom: # - aztec.js # - a shell in end-to-end. If a test is given as an argument, the test will be run here automatically. diff --git a/yarn-project/Dockerfile b/yarn-project/Dockerfile index 257d93af911..696c60fbe1c 100644 --- a/yarn-project/Dockerfile +++ b/yarn-project/Dockerfile @@ -6,8 +6,6 @@ # Any subsequent build steps needed to support downstream containers should be done in those containers build files. FROM 278380418400.dkr.ecr.eu-west-2.amazonaws.com/yarn-project-base as builder -RUN apk add bash perl - # Copy in the entire workspace. COPY . . diff --git a/yarn-project/Dockerfile.prod b/yarn-project/Dockerfile.prod index 95e4479137b..16f65db4740 100644 --- a/yarn-project/Dockerfile.prod +++ b/yarn-project/Dockerfile.prod @@ -3,8 +3,8 @@ FROM 278380418400.dkr.ecr.eu-west-2.amazonaws.com/yarn-project AS yarn-project # Need new arch specific image. -FROM node:18.19.0-alpine AS builder -RUN apk add bash jq --no-cache +FROM node:18.19.0 AS builder +RUN apt update && apt install -y jq && rm -rf /var/lib/apt/lists/* && apt-get clean COPY --from=yarn-project /usr/src /usr/src WORKDIR /usr/src/yarn-project ARG COMMIT_TAG="" @@ -18,5 +18,32 @@ RUN yarn workspaces focus @aztec/cli @aztec/aztec-sandbox @aztec/aztec-faucet -- RUN rm -rf /usr/src/noir/target # Create fresh minimal size image. -FROM node:18.19.0-alpine -COPY --from=builder /usr/src /usr/src \ No newline at end of file +# Installs our specific version of node, stripping out the unnecessary. +# We could probably just apt install nodejs, but it's both a different version, and seemingly a bit slower. +# We could also use distroless, to get us about 20mb off, but meh. It's actually useful to shell into containers. +#FROM gcr.io/distroless/nodejs18-debian12 +FROM ubuntu:lunar +# RUN apt update && apt install -y nodejs && rm -rf /var/lib/apt/lists/* && apt-get clean +RUN apt update && apt install -y curl && rm -rf /var/lib/apt/lists/* && apt-get clean +ENV NODE_VERSION=18.19.0 +RUN ARCH= && \ + dpkgArch="$(dpkg --print-architecture)" && \ + case "${dpkgArch##*-}" in \ + amd64) ARCH='x64';; \ + arm64) ARCH='arm64';; \ + *) echo "unsupported architecture"; exit 1 ;; \ + esac && \ + curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-$ARCH.tar.gz" && \ + tar zxf "node-v$NODE_VERSION-linux-$ARCH.tar.gz" -C /usr --strip-components=1 --no-same-owner \ + --exclude "*/share/*" \ + --exclude "*/bin/corepack" \ + --exclude "*/bin/npx" \ + --exclude "*/bin/npm" \ + --exclude "*/corepack/*" \ + --exclude "*/npm/man/*" \ + --exclude "*/npm/docs/*" \ + --exclude "*/include/*" && \ + rm "node-v$NODE_VERSION-linux-$ARCH.tar.gz" && \ + node --version +COPY --from=builder /usr/src /usr/src +ENTRYPOINT ["/usr/bin/node"] \ No newline at end of file diff --git a/yarn-project/aztec-node/terraform/servicediscovery-drain.sh b/yarn-project/aztec-node/terraform/servicediscovery-drain.sh index 1fa02e92d91..b8d6c301519 100755 --- a/yarn-project/aztec-node/terraform/servicediscovery-drain.sh +++ b/yarn-project/aztec-node/terraform/servicediscovery-drain.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash [ $# -ne 1 ] && echo "Usage: $0 " && exit 1 diff --git a/yarn-project/aztec-sandbox/Dockerfile b/yarn-project/aztec-sandbox/Dockerfile index 2f9644563e0..93378a67503 100644 --- a/yarn-project/aztec-sandbox/Dockerfile +++ b/yarn-project/aztec-sandbox/Dockerfile @@ -1,8 +1,7 @@ FROM 278380418400.dkr.ecr.eu-west-2.amazonaws.com/yarn-project-prod AS yarn-project-prod +CMD ["--no-warnings", "/usr/src/yarn-project/aztec-sandbox/dest/bin/index.js"] +EXPOSE 8079 8080 # The version has been updated in yarn-project-prod. # Adding COMMIT_TAG here to rebuild versioned image. -ARG COMMIT_TAG="" - -ENTRYPOINT ["node", "--no-warnings", "/usr/src/yarn-project/aztec-sandbox/dest/bin/index.js"] -EXPOSE 8079 8080 +ARG COMMIT_TAG="" \ No newline at end of file diff --git a/yarn-project/bootstrap.sh b/yarn-project/bootstrap.sh index 6f9acecd7db..ff01dcb5e80 100755 --- a/yarn-project/bootstrap.sh +++ b/yarn-project/bootstrap.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -eu cd "$(dirname "$0")" diff --git a/yarn-project/boxes/bootstrap.sh b/yarn-project/boxes/bootstrap.sh index 340bc0e8972..9d1b562be36 100755 --- a/yarn-project/boxes/bootstrap.sh +++ b/yarn-project/boxes/bootstrap.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # should be run from yarn-project/boxes original_path=$(pwd) @@ -7,16 +7,16 @@ original_path=$(pwd) for dir in *; do # Check if it's a directory if [ -d "${dir}" ]; then - + cd "${dir}" # Run the compile command echo "Running compile command inside ${dir}..." # Runs ts-node command from "../cli" to use latest "compile" code. this uses the yarn command to use the subpackage ts-node dep yarn compile:local - + # Change back to the original directory cd "${original_path}" - + fi done diff --git a/yarn-project/boxes/run_tests b/yarn-project/boxes/run_tests index 24a089b203c..c358a9366ee 100755 --- a/yarn-project/boxes/run_tests +++ b/yarn-project/boxes/run_tests @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # This script is used to run an e2e type test in CI (see .circleci/config.yml). # It pulls images and runs docker-compose, which has the test as the entrypoint. [ -n "${BUILD_SYSTEM_DEBUG:-}" ] && set -x # conditionally trace diff --git a/yarn-project/canary/scripts/cond_run_script b/yarn-project/canary/scripts/cond_run_script index 32834cef2f1..84c03bd4574 100755 --- a/yarn-project/canary/scripts/cond_run_script +++ b/yarn-project/canary/scripts/cond_run_script @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Conditionally runs a script if any dependent code has changed between # the last successful run and the present commit. # diff --git a/yarn-project/canary/scripts/extract_packages.sh b/yarn-project/canary/scripts/extract_packages.sh index 24499e23375..78255e01b24 100755 --- a/yarn-project/canary/scripts/extract_packages.sh +++ b/yarn-project/canary/scripts/extract_packages.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash FILE=$1 diff --git a/yarn-project/canary/scripts/run_tests b/yarn-project/canary/scripts/run_tests index 21894dbedb0..6bde0b451a4 100755 --- a/yarn-project/canary/scripts/run_tests +++ b/yarn-project/canary/scripts/run_tests @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # This script is used to run an e2e test in CI (see config.yml and cond_spot_run_tests). # It sets a few environment variables used inside the docker-compose.yml, pulls images, and runs docker-compose. [ -n "${BUILD_SYSTEM_DEBUG:-}" ] && set -x # conditionally trace diff --git a/yarn-project/canary/scripts/update_packages.sh b/yarn-project/canary/scripts/update_packages.sh index c8fe7740bb7..085dfd217bd 100755 --- a/yarn-project/canary/scripts/update_packages.sh +++ b/yarn-project/canary/scripts/update_packages.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -eu DIST_TAG=$1 diff --git a/yarn-project/cli/Dockerfile b/yarn-project/cli/Dockerfile index dfffe9b1843..96cc8fd045d 100644 --- a/yarn-project/cli/Dockerfile +++ b/yarn-project/cli/Dockerfile @@ -1,17 +1,6 @@ FROM 278380418400.dkr.ecr.eu-west-2.amazonaws.com/yarn-project-prod AS yarn-project-prod - -ENTRYPOINT ["node", "--no-warnings", "/usr/src/yarn-project/cli/dest/bin/index.js"] +CMD ["--no-warnings", "/usr/src/yarn-project/cli/dest/bin/index.js"] # The version has been updated in yarn-project-prod. # Adding COMMIT_TAG here to rebuild versioned image. -ARG COMMIT_TAG="" - -# Setup cache volume. -ENV XDG_CACHE_HOME /cache -RUN mkdir /cache && chmod 777 /cache -VOLUME [ "/cache" ] - -# Run as non-root user. -RUN corepack enable -RUN addgroup -S aztec && adduser -S aztec -G aztec -USER aztec +ARG COMMIT_TAG="" \ No newline at end of file diff --git a/yarn-project/deploy_npm.sh b/yarn-project/deploy_npm.sh index 04f6ab46841..f092e6fe106 100755 --- a/yarn-project/deploy_npm.sh +++ b/yarn-project/deploy_npm.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash [ -n "${BUILD_SYSTEM_DEBUG:-}" ] && set -x # conditionally trace set -eu diff --git a/yarn-project/end-to-end/scripts/setup_canary.sh b/yarn-project/end-to-end/scripts/setup_canary.sh index 2d4cd7fa2ef..14d7e176652 100755 --- a/yarn-project/end-to-end/scripts/setup_canary.sh +++ b/yarn-project/end-to-end/scripts/setup_canary.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -eu TARGET_PKGS_FILE=$1 diff --git a/yarn-project/l1-artifacts/scripts/generate-artifacts.sh b/yarn-project/l1-artifacts/scripts/generate-artifacts.sh index 1c4bd5e2ba9..37a07c35e17 100755 --- a/yarn-project/l1-artifacts/scripts/generate-artifacts.sh +++ b/yarn-project/l1-artifacts/scripts/generate-artifacts.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -euo pipefail; target_dir=./generated diff --git a/yarn-project/noir-compiler/src/cli/add_noir_compiler_commander_actions.ts b/yarn-project/noir-compiler/src/cli/add_noir_compiler_commander_actions.ts index f651eecd996..7dff5ecb7b1 100644 --- a/yarn-project/noir-compiler/src/cli/add_noir_compiler_commander_actions.ts +++ b/yarn-project/noir-compiler/src/cli/add_noir_compiler_commander_actions.ts @@ -26,7 +26,7 @@ export function addNoirCompilerCommanderActions(program: Command, log: LogFn = ( .option('-o, --outdir ', 'Output folder for the binary artifacts, relative to the project path', 'target') .option('-ts, --typescript ', 'Optional output folder for generating typescript wrappers', undefined) .option('-i, --interface ', 'Optional output folder for generating an Aztec.nr contract interface', undefined) - .option('-c --compiler ', 'Which compiler to use. Either nargo or wasm. Defaults to nargo', 'wasm') + .option('-c --compiler ', 'Which compiler to use. Either nargo or wasm.', 'wasm') .description('Compiles the Noir Source in the target project') .action(async (projectPath: string, options: Options) => { diff --git a/yarn-project/noir-contracts/scripts/catch.sh b/yarn-project/noir-contracts/scripts/catch.sh index 8a0a894b93f..87b485eb3f3 100644 --- a/yarn-project/noir-contracts/scripts/catch.sh +++ b/yarn-project/noir-contracts/scripts/catch.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Handler for SIGCHLD, cleanup if child exit with error, used by nargo_test.sh and compile.sh handle_sigchld() { diff --git a/yarn-project/noir-contracts/scripts/compile.sh b/yarn-project/noir-contracts/scripts/compile.sh index bc217a6156b..055485220e0 100755 --- a/yarn-project/noir-contracts/scripts/compile.sh +++ b/yarn-project/noir-contracts/scripts/compile.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -euo pipefail; diff --git a/yarn-project/noir-contracts/scripts/compile_all.sh b/yarn-project/noir-contracts/scripts/compile_all.sh index 32de820a630..7445dbbc854 100755 --- a/yarn-project/noir-contracts/scripts/compile_all.sh +++ b/yarn-project/noir-contracts/scripts/compile_all.sh @@ -1,3 +1,3 @@ -#!/bin/bash +#!/usr/bin/env bash echo "Compiling all contracts" ./scripts/compile.sh $(./scripts/get_all_contracts.sh) diff --git a/yarn-project/noir-contracts/scripts/get_all_contracts.sh b/yarn-project/noir-contracts/scripts/get_all_contracts.sh index caaf81c1a13..1311a4862a4 100755 --- a/yarn-project/noir-contracts/scripts/get_all_contracts.sh +++ b/yarn-project/noir-contracts/scripts/get_all_contracts.sh @@ -1,3 +1,3 @@ -#!/bin/bash +#!/usr/bin/env bash # Utility to get the names of all contracts echo $(ls -d src/contracts/*_contract/Nargo.toml | sed -r "s/src\\/contracts\\/(.+)_contract\\/Nargo.toml/\\1/") \ No newline at end of file diff --git a/yarn-project/noir-contracts/scripts/get_all_libraries.sh b/yarn-project/noir-contracts/scripts/get_all_libraries.sh index f1913a46caf..8fbe7bb1b19 100755 --- a/yarn-project/noir-contracts/scripts/get_all_libraries.sh +++ b/yarn-project/noir-contracts/scripts/get_all_libraries.sh @@ -1,3 +1,3 @@ -#!/bin/bash +#!/usr/bin/env bash # Utility to get the names of all noir libraries located in ../aztec-nr echo $(ls -d ../aztec-nr/*/Nargo.toml | sed -r "s/..\\/aztec-nr\\/(.+)\\/Nargo.toml/\\1/") \ No newline at end of file diff --git a/yarn-project/noir-contracts/scripts/install_noir.sh b/yarn-project/noir-contracts/scripts/install_noir.sh index 325e9a56620..b1105d6ad46 100755 --- a/yarn-project/noir-contracts/scripts/install_noir.sh +++ b/yarn-project/noir-contracts/scripts/install_noir.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Script to install noirup and the latest aztec nargo set -eu diff --git a/yarn-project/noir-contracts/scripts/install_noirup.sh b/yarn-project/noir-contracts/scripts/install_noirup.sh index 11ba9b15d31..025237333cd 100755 --- a/yarn-project/noir-contracts/scripts/install_noirup.sh +++ b/yarn-project/noir-contracts/scripts/install_noirup.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Script to install noirup and the latest nargo set -eu diff --git a/yarn-project/noir-contracts/scripts/nargo_check.sh b/yarn-project/noir-contracts/scripts/nargo_check.sh index 10d9d14c2c1..45209d4ee43 100644 --- a/yarn-project/noir-contracts/scripts/nargo_check.sh +++ b/yarn-project/noir-contracts/scripts/nargo_check.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Check nargo version matches the expected one nargo_check() { diff --git a/yarn-project/noir-contracts/scripts/nargo_test.sh b/yarn-project/noir-contracts/scripts/nargo_test.sh index 8468c19f492..0666714388d 100755 --- a/yarn-project/noir-contracts/scripts/nargo_test.sh +++ b/yarn-project/noir-contracts/scripts/nargo_test.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Tests noir contracts, if multiple are provided, then they are testing in parallel, bubbling any testing errors # diff --git a/yarn-project/noir-contracts/scripts/nargo_test_ci.sh b/yarn-project/noir-contracts/scripts/nargo_test_ci.sh index 5a4458d4da5..d835f972324 100755 --- a/yarn-project/noir-contracts/scripts/nargo_test_ci.sh +++ b/yarn-project/noir-contracts/scripts/nargo_test_ci.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Runs tests scripts for all contracts, then for all libraries. ./scripts/nargo_test.sh CONTRACT $(./scripts/get_all_contracts.sh) diff --git a/yarn-project/noir-contracts/scripts/types.sh b/yarn-project/noir-contracts/scripts/types.sh index ebbc24bdc5f..3e2410e4004 100755 --- a/yarn-project/noir-contracts/scripts/types.sh +++ b/yarn-project/noir-contracts/scripts/types.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Example: # - this script will automatically be run when running `yarn noir:build` diff --git a/yarn-project/noir-contracts/scripts/types_all.sh b/yarn-project/noir-contracts/scripts/types_all.sh index 5cbb3ce9d91..38081dc6efe 100755 --- a/yarn-project/noir-contracts/scripts/types_all.sh +++ b/yarn-project/noir-contracts/scripts/types_all.sh @@ -1,3 +1,3 @@ -#!/bin/bash +#!/usr/bin/env bash # Run the types script for all files ./scripts/types.sh $(./scripts/get_all_contracts.sh) diff --git a/yarn-project/noir-contracts/src/scripts/compile.sh b/yarn-project/noir-contracts/src/scripts/compile.sh index 551f7a74869..adedfaeba4f 100755 --- a/yarn-project/noir-contracts/src/scripts/compile.sh +++ b/yarn-project/noir-contracts/src/scripts/compile.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Example: diff --git a/yarn-project/p2p-bootstrap/terraform/servicediscovery-drain.sh b/yarn-project/p2p-bootstrap/terraform/servicediscovery-drain.sh index 1fa02e92d91..b8d6c301519 100755 --- a/yarn-project/p2p-bootstrap/terraform/servicediscovery-drain.sh +++ b/yarn-project/p2p-bootstrap/terraform/servicediscovery-drain.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash [ $# -ne 1 ] && echo "Usage: $0 " && exit 1 diff --git a/yarn-project/scripts/run_script.sh b/yarn-project/scripts/run_script.sh index a3347411e85..a06cf4eb42e 100755 --- a/yarn-project/scripts/run_script.sh +++ b/yarn-project/scripts/run_script.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Downloads the image that contains the built scripts package and executes the given command in it. [ -n "${BUILD_SYSTEM_DEBUG:-}" ] && set -x # conditionally trace set -eu diff --git a/yarn-project/scripts/version_packages.sh b/yarn-project/scripts/version_packages.sh index a708cb7a4ed..bf631bd8ac1 100755 --- a/yarn-project/scripts/version_packages.sh +++ b/yarn-project/scripts/version_packages.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -eu if [ -n "$COMMIT_TAG" ]; then diff --git a/yarn-project/yarn-project-base/Dockerfile b/yarn-project/yarn-project-base/Dockerfile index ee9c4f4f6b7..96be5e824c3 100644 --- a/yarn-project/yarn-project-base/Dockerfile +++ b/yarn-project/yarn-project-base/Dockerfile @@ -47,8 +47,8 @@ FROM 278380418400.dkr.ecr.eu-west-2.amazonaws.com/bb.js as bb.js FROM 278380418400.dkr.ecr.eu-west-2.amazonaws.com/noir as noir FROM 278380418400.dkr.ecr.eu-west-2.amazonaws.com/noir-packages as noir-packages -FROM node:18.19.0-alpine -RUN apk update && apk add --no-cache bash jq curl +FROM node:18.19.0 +RUN apt update && apt install -y jq curl perl && rm -rf /var/lib/apt/lists/* && apt-get clean # Copy L1 contracts. COPY --from=contracts /usr/src/l1-contracts /usr/src/l1-contracts From 9c5443651faaed3dcb9fae36727337a34ce5922b Mon Sep 17 00:00:00 2001 From: Charlie Lye Date: Sun, 10 Dec 2023 18:13:07 +0000 Subject: [PATCH 16/35] Fixes. Yolo. --- aztec-up/bin/.aztec-run | 1 + aztec-up/bin/aztec-install | 2 +- yarn-project/aztec-sandbox/Dockerfile | 2 +- yarn-project/cli/Dockerfile | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/aztec-up/bin/.aztec-run b/aztec-up/bin/.aztec-run index 82b12deb89a..a02a3bafbd9 100755 --- a/aztec-up/bin/.aztec-run +++ b/aztec-up/bin/.aztec-run @@ -30,6 +30,7 @@ fi if [[ $PWD != ${HOME}* ]]; then warn "Due to how we containerize our applications, we require your working directory to be somewhere within $HOME." + exit 1 fi # Set up host.docker.internal alias on Linux, just like it is on mac. diff --git a/aztec-up/bin/aztec-install b/aztec-up/bin/aztec-install index e6c7ec5ebf4..11eaada215d 100755 --- a/aztec-up/bin/aztec-install +++ b/aztec-up/bin/aztec-install @@ -29,8 +29,8 @@ function title() { echo -e "Welcome to the ${bold}${b}Aztec${r} installer! Your journey into blockchain privacy begins... ${bold}${p}now${r}." echo -e "We presently leverage docker to simplify releases of our complex project." echo -e "Please ensure it's installed for your platform: https://docs.docker.com/engine/install" + echo if [ "$(uname -s)" == "Darwin" ]; then - echo echo -e "${y}WARNING: For best performance we recommend adjusting your default docker settings:" echo -e " - Under general, enable VirtioFS." echo -e " - Under resources, set CPUs to ~80-100% your maximum." diff --git a/yarn-project/aztec-sandbox/Dockerfile b/yarn-project/aztec-sandbox/Dockerfile index 93378a67503..afdfb2094e1 100644 --- a/yarn-project/aztec-sandbox/Dockerfile +++ b/yarn-project/aztec-sandbox/Dockerfile @@ -1,5 +1,5 @@ FROM 278380418400.dkr.ecr.eu-west-2.amazonaws.com/yarn-project-prod AS yarn-project-prod -CMD ["--no-warnings", "/usr/src/yarn-project/aztec-sandbox/dest/bin/index.js"] +ENTRYPOINT ["node", "--no-warnings", "/usr/src/yarn-project/aztec-sandbox/dest/bin/index.js"] EXPOSE 8079 8080 # The version has been updated in yarn-project-prod. diff --git a/yarn-project/cli/Dockerfile b/yarn-project/cli/Dockerfile index 96cc8fd045d..dc70ce119ca 100644 --- a/yarn-project/cli/Dockerfile +++ b/yarn-project/cli/Dockerfile @@ -1,5 +1,5 @@ FROM 278380418400.dkr.ecr.eu-west-2.amazonaws.com/yarn-project-prod AS yarn-project-prod -CMD ["--no-warnings", "/usr/src/yarn-project/cli/dest/bin/index.js"] +ENTRYPOINT ["node", "--no-warnings", "/usr/src/yarn-project/cli/dest/bin/index.js"] # The version has been updated in yarn-project-prod. # Adding COMMIT_TAG here to rebuild versioned image. From f2dca6403d56c2477eb74aa9ee348d7a812c476e Mon Sep 17 00:00:00 2001 From: AztecBot Date: Mon, 11 Dec 2023 02:15:53 +0000 Subject: [PATCH 17/35] git subrepo push --branch=master build-system subrepo: subdir: "build-system" merged: "1f7b38d90" upstream: origin: "https://github.com/AztecProtocol/build-system" branch: "master" commit: "1f7b38d90" git-subrepo: version: "0.4.6" origin: "???" commit: "???" [skip ci] --- build-system/.gitrepo | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build-system/.gitrepo b/build-system/.gitrepo index b1fdb9bd872..5b99662494d 100644 --- a/build-system/.gitrepo +++ b/build-system/.gitrepo @@ -6,7 +6,7 @@ [subrepo] remote = https://github.com/AztecProtocol/build-system branch = master - commit = 4e1ea3fc2cdbbfdb97d21b0920eb681ede20c333 - parent = 379b5adc259ac69b01e61b852172cdfc87cf9350 + commit = 1f7b38d90be36c46b46ac52c5d63ce7a0d627ecf + parent = 9c5443651faaed3dcb9fae36727337a34ce5922b method = merge cmdver = 0.4.6 From 6d4580a10cdc096278d60eb8c92a69bc781d8259 Mon Sep 17 00:00:00 2001 From: AztecBot Date: Mon, 11 Dec 2023 02:16:21 +0000 Subject: [PATCH 18/35] git subrepo push --branch=master barretenberg subrepo: subdir: "barretenberg" merged: "86e6d6f1e" upstream: origin: "https://github.com/AztecProtocol/barretenberg" branch: "master" commit: "86e6d6f1e" git-subrepo: version: "0.4.6" origin: "???" commit: "???" [skip ci] --- barretenberg/.gitrepo | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/barretenberg/.gitrepo b/barretenberg/.gitrepo index 4ba3cac6d74..ea339226546 100644 --- a/barretenberg/.gitrepo +++ b/barretenberg/.gitrepo @@ -6,7 +6,7 @@ [subrepo] remote = https://github.com/AztecProtocol/barretenberg branch = master - commit = 4e4634542814f15d3703fe560874e08eda57e1fa - parent = 379b5adc259ac69b01e61b852172cdfc87cf9350 + commit = 86e6d6f1e48a0609de3f8e8f99007d45b4dbbdf4 + parent = 9c5443651faaed3dcb9fae36727337a34ce5922b method = merge cmdver = 0.4.6 From 1696a8fdafd359c58229d27943a05ec3177d3348 Mon Sep 17 00:00:00 2001 From: AztecBot Date: Mon, 11 Dec 2023 02:16:44 +0000 Subject: [PATCH 19/35] git subrepo push --branch=master yarn-project/aztec-nr subrepo: subdir: "yarn-project/aztec-nr" merged: "a3aa6bd5d" upstream: origin: "https://github.com/AztecProtocol/aztec-nr" branch: "master" commit: "a3aa6bd5d" git-subrepo: version: "0.4.6" origin: "???" commit: "???" [skip ci] --- yarn-project/aztec-nr/.gitrepo | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/yarn-project/aztec-nr/.gitrepo b/yarn-project/aztec-nr/.gitrepo index 0930abc8a30..6fc3eca0c44 100644 --- a/yarn-project/aztec-nr/.gitrepo +++ b/yarn-project/aztec-nr/.gitrepo @@ -6,7 +6,7 @@ [subrepo] remote = https://github.com/AztecProtocol/aztec-nr branch = master - commit = 4e873ce0d34cad3743be460f5ed703350435a974 + commit = a3aa6bd5d8f2ad9d44e3d9340550203fbe38c4d6 method = merge cmdver = 0.4.6 - parent = 379b5adc259ac69b01e61b852172cdfc87cf9350 + parent = 9c5443651faaed3dcb9fae36727337a34ce5922b From 12249bf91d5934f798856a75cdd9de8a5822604b Mon Sep 17 00:00:00 2001 From: Rahul Kothari Date: Tue, 12 Dec 2023 16:13:31 +0400 Subject: [PATCH 20/35] fix(noir-compiler): compile time error if ctor is missing (#3649) Fix a part of the problem highlighted by #3630 Also created * https://github.com/noir-lang/noir/issues/3768 * [Discussion to see why we prioritise Aztec-nr issues over noir syntax issues. E.g. if we have storage and a syntax error in a method, instead of showinf the syntax error, we say "no compute_note_hash_and_nullifier() found"](https://aztecprotocol.slack.com/archives/C03P17YHVK8/p1702312023384759) --- yarn-project/noir-compiler/src/contract-interface-gen/abi.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/yarn-project/noir-compiler/src/contract-interface-gen/abi.ts b/yarn-project/noir-compiler/src/contract-interface-gen/abi.ts index df819ae6578..d97f66f1a43 100644 --- a/yarn-project/noir-compiler/src/contract-interface-gen/abi.ts +++ b/yarn-project/noir-compiler/src/contract-interface-gen/abi.ts @@ -89,6 +89,10 @@ export function generateContractArtifact( { contract, debug }: NoirContractCompilationArtifacts, aztecNrVersion?: string, ): ContractArtifact { + const constructorArtifact = contract.functions.find(({ name }) => name === 'constructor'); + if (constructorArtifact === undefined) { + throw new Error('Contract must have a constructor function'); + } if (contract.functions.length > 2 ** FUNCTION_TREE_HEIGHT) { throw new Error(`Contract can only have a maximum of ${2 ** FUNCTION_TREE_HEIGHT} functions`); } From 7c85750089e022240376751086d515d993409d98 Mon Sep 17 00:00:00 2001 From: Alex Gherghisan Date: Tue, 12 Dec 2023 13:00:43 +0000 Subject: [PATCH 21/35] feat: update command handles Dockerized sandbox (#3656) This PR cherry-picks some of the changes from #3567 1. It no longer fails if it doesn't detect package.json. So it can now be used to update contracts on their own aztec-cli update --contract path/to/some/folder 2. Instead of looking for the latest @aztec/aztec-sandbox, it now looks for the latest @aztec/aztec.js. 3. Prints a reminder to the user to update Docker containers and links to update instructions. --- yarn-project/cli/src/index.ts | 5 +- yarn-project/cli/src/update/npm.ts | 20 +++++ yarn-project/cli/src/update/update.ts | 111 +++++++------------------- 3 files changed, 52 insertions(+), 84 deletions(-) diff --git a/yarn-project/cli/src/index.ts b/yarn-project/cli/src/index.ts index 08fd0c44b5e..83d5ebd3f96 100644 --- a/yarn-project/cli/src/index.ts +++ b/yarn-project/cli/src/index.ts @@ -483,11 +483,12 @@ export function getProgram(log: LogFn, debugLogger: DebugLogger): Command { .description('Updates Nodejs and Noir dependencies') .argument('[projectPath]', 'Path to the project directory', process.cwd()) .option('--contract [paths...]', 'Paths to contracts to update dependencies', []) - .option('--sandbox-version ', 'The sandbox version to update to. Defaults to latest', 'latest') + .option('--aztec-version ', 'The version to update Aztec packages to. Defaults to latest', 'latest') .addOption(pxeOption) .action(async (projectPath: string, options) => { const { update } = await import('./update/update.js'); - await update(projectPath, options.contract, options.rpcUrl, options.sandboxVersion, log, debugLogger); + const { contract, aztecVersion, rpcUrl } = options; + await update(projectPath, contract, rpcUrl, aztecVersion, log); }); addNoirCompilerCommanderActions(program, log); diff --git a/yarn-project/cli/src/update/npm.ts b/yarn-project/cli/src/update/npm.ts index 6d73c1ca7d6..703dc29219f 100644 --- a/yarn-project/cli/src/update/npm.ts +++ b/yarn-project/cli/src/update/npm.ts @@ -9,6 +9,15 @@ import { SemVer, parse } from 'semver'; import { atomicUpdateFile } from '../utils.js'; import { DependencyChanges } from './common.js'; +const deprecatedNpmPackages = new Set([]); +const npmDeprecationMessage = ` +The following packages have been deprecated and will no longer be updated on the npm registry: +${Array.from(deprecatedNpmPackages) + .map(pkg => ` - ${pkg}`) + .join('\n')} +Remove them from package.json +`; + /** * Looks up a package.json file and returns its contents * @param projectPath - Path to Nodejs project @@ -68,6 +77,8 @@ export async function updateAztecDeps( log(`Updating @aztec packages to ${aztecVersion} in ${relative(process.cwd(), changes.file)}`); const version = aztecVersion.version; + let detectedDeprecatedPackages = false; + for (const depType of ['dependencies', 'devDependencies'] as const) { const dependencies = pkg[depType]; if (!dependencies) { @@ -84,6 +95,11 @@ export async function updateAztecDeps( continue; } + if (deprecatedNpmPackages.has(name)) { + detectedDeprecatedPackages = true; + continue; + } + if (dependencies[name] !== version) { changes.dependencies.push({ name, @@ -96,6 +112,10 @@ export async function updateAztecDeps( } } + if (detectedDeprecatedPackages) { + log(npmDeprecationMessage); + } + if (changes.dependencies.length > 0) { const contents = JSON.stringify(pkg, null, 2) + '\n'; await atomicUpdateFile(resolve(join(projectPath, 'package.json')), contents); diff --git a/yarn-project/cli/src/update/update.ts b/yarn-project/cli/src/update/update.ts index 977cb699c4e..9f78d0caab2 100644 --- a/yarn-project/cli/src/update/update.ts +++ b/yarn-project/cli/src/update/update.ts @@ -1,84 +1,68 @@ /* eslint-disable jsdoc/require-jsdoc */ -import { DebugLogger, LogFn } from '@aztec/foundation/log'; +import { LogFn } from '@aztec/foundation/log'; import { relative, resolve } from 'path'; -import { SemVer, coerce, gt, lt, parse } from 'semver'; +import { parse } from 'semver'; -import { createCompatibleClient } from '../client.js'; import { GITHUB_TAG_PREFIX } from '../github.js'; import { DependencyChanges } from './common.js'; import { updateAztecNr } from './noir.js'; -import { getNewestVersion as getLatestVersion, readPackageJson, updateAztecDeps, updateLockfile } from './npm.js'; +import { getNewestVersion, updateAztecDeps, updateLockfile } from './npm.js'; -const SANDBOX_PACKAGE = '@aztec/aztec-sandbox'; +const AZTECJS_PACKAGE = '@aztec/aztec.js'; +const UPDATE_DOCS_URL = 'https://docs.aztec.network/dev_docs/updating'; export async function update( projectPath: string, contracts: string[], pxeUrl: string, - sandboxVersion: string, + aztecVersion: string, log: LogFn, - debugLog: DebugLogger, ): Promise { - const targetSandboxVersion = - sandboxVersion === 'latest' ? await getLatestVersion(SANDBOX_PACKAGE, 'latest') : parse(sandboxVersion); + const targetAztecVersion = + aztecVersion === 'latest' ? await getNewestVersion(AZTECJS_PACKAGE, 'latest') : parse(aztecVersion); - if (!targetSandboxVersion) { - throw new Error(`Invalid aztec version ${sandboxVersion}`); + if (!targetAztecVersion) { + throw new Error(`Invalid aztec version ${aztecVersion}`); } - let currentSandboxVersion = await getNpmSandboxVersion(projectPath, log); - - if (!currentSandboxVersion) { - currentSandboxVersion = await getRemoteSandboxVersion(pxeUrl, log, debugLog); - - if (currentSandboxVersion && lt(currentSandboxVersion, targetSandboxVersion)) { - log(` -Sandbox is older than version ${targetSandboxVersion}. If running via docker-compose, follow update instructions: -https://docs.aztec.network/dev_docs/cli/updating - -Once the sandbox is updated, run the \`aztec-cli update\` command again`); - return; + const projectDependencyChanges: DependencyChanges[] = []; + try { + const npmChanges = await updateAztecDeps(resolve(process.cwd(), projectPath), targetAztecVersion, log); + if (npmChanges.dependencies.length > 0) { + updateLockfile(projectPath, log); } - } - - if (!currentSandboxVersion) { - throw new Error('Sandbox version could not be detected'); - } - - // sanity check - if (gt(currentSandboxVersion, targetSandboxVersion)) { - throw new Error('Local sandbox version is newer than latest version.'); - } - const npmChanges = await updateAztecDeps(projectPath, targetSandboxVersion, log); - if (npmChanges.dependencies.length > 0) { - updateLockfile(projectPath, log); + projectDependencyChanges.push(npmChanges); + } catch (err) { + if (err instanceof Error && 'code' in err && err.code === 'ENOENT') { + log(`No package.json found in ${projectPath}. Skipping npm update...`); + } else { + throw err; + } } - const contractChanges: DependencyChanges[] = []; for (const contract of contracts) { try { - contractChanges.push( + projectDependencyChanges.push( await updateAztecNr( - resolve(projectPath, contract), - `${GITHUB_TAG_PREFIX}-v${targetSandboxVersion.version}`, + resolve(process.cwd(), projectPath, contract), + `${GITHUB_TAG_PREFIX}-v${targetAztecVersion.version}`, log, ), ); } catch (err) { if (err instanceof Error && 'code' in err && err.code === 'ENOENT') { log(`No Nargo.toml found in ${relative(process.cwd(), contract)}. Skipping...`); - process.exit(1); + } else { + throw err; } - - throw err; } } - printChanges(npmChanges, log); + log(`To update Docker containers follow instructions at ${UPDATE_DOCS_URL}`); - contractChanges.forEach(changes => { + projectDependencyChanges.forEach(changes => { printChanges(changes, log); }); } @@ -93,40 +77,3 @@ function printChanges(changes: DependencyChanges, log: LogFn): void { }); } } - -async function getNpmSandboxVersion(projectPath: string, log: LogFn): Promise { - try { - const pkg = await readPackageJson(projectPath); - // use coerce instead of parse because it eliminates semver operators like ~ and ^ - if (pkg.dependencies?.[SANDBOX_PACKAGE]) { - return coerce(pkg.dependencies[SANDBOX_PACKAGE]); - } else if (pkg.devDependencies?.[SANDBOX_PACKAGE]) { - return coerce(pkg.devDependencies[SANDBOX_PACKAGE]); - } else { - return null; - } - } catch (err) { - if (err instanceof Error && 'code' in err && err.code === 'ENOENT') { - log(`No package.json found in ${projectPath}`); - process.exit(1); - } - - throw err; - } -} - -async function getRemoteSandboxVersion(pxeUrl: string, log: LogFn, debugLog: DebugLogger): Promise { - try { - const client = await createCompatibleClient(pxeUrl, debugLog); - const nodeInfo = await client.getNodeInfo(); - - return parse(nodeInfo.sandboxVersion); - } catch (err) { - if (err instanceof Error && err.message === 'fetch failed') { - log(`Could not connect to Sandbox running on ${pxeUrl}`); - process.exit(1); - } - - throw err; - } -} From ac1edc1d30352cc3e3dcbfce4e69fe38777cc0df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Bene=C5=A1?= Date: Tue, 12 Dec 2023 15:08:59 +0100 Subject: [PATCH 22/35] feat: block header block number oracle (#3648) --- .../acir-simulator/src/acvm/oracle/oracle.ts | 11 +++++ .../src/acvm/oracle/typed_oracle.ts | 5 +++ .../acir-simulator/src/client/db_oracle.ts | 6 +++ .../src/client/view_data_oracle.ts | 33 ++++++++++++++- yarn-project/aztec-nr/aztec/src/context.nr | 2 +- .../aztec/src/oracle/get_block_header.nr | 42 ++++++++++++------- .../src/oracle/get_membership_witness.nr | 4 +- .../get_nullifier_membership_witness.nr | 8 ++-- .../aztec/src/oracle/get_sibling_path.nr | 4 +- .../src/e2e_inclusion_proofs_contract.test.ts | 35 ++++++++++++---- .../inclusion_proofs_contract/src/main.nr | 28 ++----------- .../pxe/src/simulator_oracle/index.ts | 8 ++++ .../types/src/interfaces/aztec-node.ts | 6 --- .../src/interfaces/state_info_provider.ts | 6 +++ .../merkle_tree_snapshot_operations_facade.ts | 2 +- 15 files changed, 134 insertions(+), 66 deletions(-) diff --git a/yarn-project/acir-simulator/src/acvm/oracle/oracle.ts b/yarn-project/acir-simulator/src/acvm/oracle/oracle.ts index 87a32f072c0..5b93133e406 100644 --- a/yarn-project/acir-simulator/src/acvm/oracle/oracle.ts +++ b/yarn-project/acir-simulator/src/acvm/oracle/oracle.ts @@ -119,6 +119,17 @@ export class Oracle { return blockHeader.toArray().map(toACVMField); } + // TODO(#3564) - Nuke this oracle and inject the number directly to context + async getNullifierRootBlockNumber([nullifierTreeRoot]: ACVMField[]): Promise { + const parsedRoot = fromACVMField(nullifierTreeRoot); + + const blockNumber = await this.typedOracle.getNullifierRootBlockNumber(parsedRoot); + if (!blockNumber) { + throw new Error(`Block header not found for block ${parsedRoot}.`); + } + return toACVMField(blockNumber); + } + async getAuthWitness([messageHash]: ACVMField[]): Promise { const messageHashField = fromACVMField(messageHash); const witness = await this.typedOracle.getAuthWitness(messageHashField); diff --git a/yarn-project/acir-simulator/src/acvm/oracle/typed_oracle.ts b/yarn-project/acir-simulator/src/acvm/oracle/typed_oracle.ts index 7013689a8ca..556da1bebf8 100644 --- a/yarn-project/acir-simulator/src/acvm/oracle/typed_oracle.ts +++ b/yarn-project/acir-simulator/src/acvm/oracle/typed_oracle.ts @@ -106,6 +106,11 @@ export abstract class TypedOracle { throw new Error('Not available.'); } + // TODO(#3564) - Nuke this oracle and inject the number directly to context + getNullifierRootBlockNumber(_nullifierTreeRoot: Fr): Promise { + throw new Error('Not available.'); + } + getCompleteAddress(_address: AztecAddress): Promise { throw new Error('Not available.'); } diff --git a/yarn-project/acir-simulator/src/client/db_oracle.ts b/yarn-project/acir-simulator/src/client/db_oracle.ts index 6ed7a6a8e6a..5d866dac224 100644 --- a/yarn-project/acir-simulator/src/client/db_oracle.ts +++ b/yarn-project/acir-simulator/src/client/db_oracle.ts @@ -159,4 +159,10 @@ export interface DBOracle extends CommitmentsDB { * @returns - The block corresponding to the given block number. Undefined if it does not exist. */ getBlock(blockNumber: number): Promise; + + /** + * Fetches the current block number. + * @returns The block number. + */ + getBlockNumber(): Promise; } diff --git a/yarn-project/acir-simulator/src/client/view_data_oracle.ts b/yarn-project/acir-simulator/src/client/view_data_oracle.ts index 8a1c2258737..1edcfe3998b 100644 --- a/yarn-project/acir-simulator/src/client/view_data_oracle.ts +++ b/yarn-project/acir-simulator/src/client/view_data_oracle.ts @@ -3,7 +3,14 @@ import { computeGlobalsHash, siloNullifier } from '@aztec/circuits.js/abis'; import { AztecAddress } from '@aztec/foundation/aztec-address'; import { Fr } from '@aztec/foundation/fields'; import { createDebugLogger } from '@aztec/foundation/log'; -import { AuthWitness, AztecNode, CompleteAddress, MerkleTreeId, NullifierMembershipWitness } from '@aztec/types'; +import { + AuthWitness, + AztecNode, + CompleteAddress, + INITIAL_L2_BLOCK_NUM, + MerkleTreeId, + NullifierMembershipWitness, +} from '@aztec/types'; import { NoteData, TypedOracle } from '../acvm/index.js'; import { DBOracle } from './db_oracle.js'; @@ -113,6 +120,30 @@ export class ViewDataOracle extends TypedOracle { ); } + /** + * Gets number of a block in which a given nullifier tree root was included. + * @param nullifierTreeRoot - The nullifier tree root to get the block number for. + * @returns The block number. + * + * TODO(#3564) - Nuke this oracle and inject the number directly to context + */ + public async getNullifierRootBlockNumber(nullifierTreeRoot: Fr): Promise { + const currentBlockNumber = await this.db.getBlockNumber(); + for (let i = currentBlockNumber; i >= INITIAL_L2_BLOCK_NUM; i -= 2) { + const block = await this.db.getBlock(i); + if (!block) { + throw new Error(`Block ${i} not found`); + } + if (block.endNullifierTreeSnapshot.root.equals(nullifierTreeRoot)) { + return i; + } + if (block.startNullifierTreeSnapshot.root.equals(nullifierTreeRoot)) { + return i - 1; + } + } + throw new Error(`Failed to find block containing nullifier tree root ${nullifierTreeRoot}`); + } + /** * Retrieve the complete address associated to a given address. * @param address - Address to fetch the complete address for. diff --git a/yarn-project/aztec-nr/aztec/src/context.nr b/yarn-project/aztec-nr/aztec/src/context.nr index c7609942d4c..020a9410ce5 100644 --- a/yarn-project/aztec-nr/aztec/src/context.nr +++ b/yarn-project/aztec-nr/aztec/src/context.nr @@ -129,7 +129,7 @@ impl PrivateContext { self.inputs.call_context.function_selector } - pub fn get_block_header(self, block_number: Field) -> BlockHeader { + pub fn get_block_header(self, block_number: u32) -> BlockHeader { get_block_header(block_number, self) } diff --git a/yarn-project/aztec-nr/aztec/src/oracle/get_block_header.nr b/yarn-project/aztec-nr/aztec/src/oracle/get_block_header.nr index 9d15d693393..7d10a895646 100644 --- a/yarn-project/aztec-nr/aztec/src/oracle/get_block_header.nr +++ b/yarn-project/aztec-nr/aztec/src/oracle/get_block_header.nr @@ -13,34 +13,44 @@ use crate::{ }, }; +// TODO(#3564) - Nuke this oracle and Inject the number directly to context +#[oracle(getNullifierRootBlockNumber)] +fn get_nullifier_root_block_number_oracle(_nullifier_tree_root: Field) -> Field {} + +unconstrained pub fn get_nullifier_root_block_number(nullifier_tree_root: Field) -> u32 { + get_nullifier_root_block_number_oracle(nullifier_tree_root) as u32 +} + #[oracle(getBlockHeader)] -fn get_block_header_oracle(_block_number: Field) -> [Field; BLOCK_HEADER_LENGTH] {} +fn get_block_header_oracle(_block_number: u32) -> [Field; BLOCK_HEADER_LENGTH] {} -unconstrained pub fn get_block_header_internal(block_number: Field) -> BlockHeader { +unconstrained pub fn get_block_header_internal(block_number: u32) -> BlockHeader { let block_header = get_block_header_oracle(block_number); BlockHeader::deserialize(block_header) } -pub fn get_block_header(block_number: Field, context: PrivateContext) -> BlockHeader { - // 1) Get block header of a given block from oracle +pub fn get_block_header(block_number: u32, context: PrivateContext) -> BlockHeader { + // 1) Get block number corresponding to block header inside context + // Using nullifier tree root to get the block header block number because that changes in every block (every tx emits a nullifier). + let block_header_block_number = get_nullifier_root_block_number(context.block_header.nullifier_tree_root); + + // 2) Check that the block header block number is more than or equal to the block number we want to prove against + // We could not perform the proof otherwise because the archive root from the header would not "contain" the block we want to prove against + assert(block_header_block_number >= block_number, "Block header block number is smaller than the block number we want to prove against"); + + // 3) Get block header of a given block from oracle let block_header = get_block_header_internal(block_number); - // 2) Compute the block hash from the block header + // 4) Compute the block hash from the block header let block_hash = block_header.block_hash(); - // 3) Get the membership witness of the block in the archive + // 5) Get the membership witness of the block in the archive let archive_id = 5; // TODO(#3443) - - // Using `block_number` here for path is incorrect and it will break if we pass in an incorrect block number on input. - // Instead here should be the block number corresponding to `context.block_header.blocks_tree_root` - // This is not currently available in private context. See issue #3564 - let path_block_number = block_number; - - let witness: MembershipWitness = get_membership_witness(path_block_number, archive_id, block_hash); - - // 4) Check that the block is in the archive (i.e. the witness is valid) + let witness: MembershipWitness = get_membership_witness(block_header_block_number, archive_id, block_hash); + + // 6) Check that the block is in the archive (i.e. the witness is valid) assert(context.block_header.archive_root == compute_merkle_root(block_hash, witness.index, witness.path), "Proving membership of a block in archive failed"); - // 5) Return the block header + // 7) Return the block header block_header } diff --git a/yarn-project/aztec-nr/aztec/src/oracle/get_membership_witness.nr b/yarn-project/aztec-nr/aztec/src/oracle/get_membership_witness.nr index 1f43ae52f57..320b57cedc3 100644 --- a/yarn-project/aztec-nr/aztec/src/oracle/get_membership_witness.nr +++ b/yarn-project/aztec-nr/aztec/src/oracle/get_membership_witness.nr @@ -14,9 +14,9 @@ struct MembershipWitness { } #[oracle(getMembershipWitness)] -fn get_membership_witness_oracle(_block_number: Field, _tree_id: Field, _leaf_value: Field) -> [Field; M] {} +fn get_membership_witness_oracle(_block_number: u32, _tree_id: Field, _leaf_value: Field) -> [Field; M] {} -unconstrained pub fn get_membership_witness(block_number: Field, tree_id: Field, leaf_value: Field) -> MembershipWitness { +unconstrained pub fn get_membership_witness(block_number: u32, tree_id: Field, leaf_value: Field) -> MembershipWitness { let fields: [Field; M] = get_membership_witness_oracle(block_number, tree_id, leaf_value); MembershipWitness { index: fields[0], path: arr_copy_slice(fields, [0; N], 1) } } diff --git a/yarn-project/aztec-nr/aztec/src/oracle/get_nullifier_membership_witness.nr b/yarn-project/aztec-nr/aztec/src/oracle/get_nullifier_membership_witness.nr index 2cc493d7966..204bde2b1c1 100644 --- a/yarn-project/aztec-nr/aztec/src/oracle/get_nullifier_membership_witness.nr +++ b/yarn-project/aztec-nr/aztec/src/oracle/get_nullifier_membership_witness.nr @@ -32,11 +32,11 @@ struct NullifierMembershipWitness { } #[oracle(getLowNullifierMembershipWitness)] -fn get_low_nullifier_membership_witness_oracle(_block_number: Field, _nullifier: Field) -> [Field; NULLIFIER_MEMBERSHIP_WITNESS] {} +fn get_low_nullifier_membership_witness_oracle(_block_number: u32, _nullifier: Field) -> [Field; NULLIFIER_MEMBERSHIP_WITNESS] {} // Nullifier here refers to the nullifier we are looking to get non-inclusion proof for (by proving that a lower // nullifier's next_value is bigger than the nullifier) -unconstrained pub fn get_low_nullifier_membership_witness(block_number: Field, nullifier: Field) -> NullifierMembershipWitness { +unconstrained pub fn get_low_nullifier_membership_witness(block_number: u32, nullifier: Field) -> NullifierMembershipWitness { let fields = get_low_nullifier_membership_witness_oracle(block_number, nullifier); NullifierMembershipWitness { index: fields[0], @@ -46,11 +46,11 @@ unconstrained pub fn get_low_nullifier_membership_witness(block_number: Field, n } #[oracle(getNullifierMembershipWitness)] -fn get_nullifier_membership_witness_oracle(_block_number: Field, _nullifier: Field) -> [Field; NULLIFIER_MEMBERSHIP_WITNESS] {} +fn get_nullifier_membership_witness_oracle(_block_number: u32, _nullifier: Field) -> [Field; NULLIFIER_MEMBERSHIP_WITNESS] {} // Nullifier here refers to the nullifier we are looking to get non-inclusion proof for (by proving that a lower // nullifier's next_value is bigger than the nullifier) -unconstrained pub fn get_nullifier_membership_witness(block_number: Field, nullifier: Field) -> NullifierMembershipWitness { +unconstrained pub fn get_nullifier_membership_witness(block_number: u32, nullifier: Field) -> NullifierMembershipWitness { let fields = get_nullifier_membership_witness_oracle(block_number, nullifier); NullifierMembershipWitness { index: fields[0], diff --git a/yarn-project/aztec-nr/aztec/src/oracle/get_sibling_path.nr b/yarn-project/aztec-nr/aztec/src/oracle/get_sibling_path.nr index 7fbe0936997..2109767a211 100644 --- a/yarn-project/aztec-nr/aztec/src/oracle/get_sibling_path.nr +++ b/yarn-project/aztec-nr/aztec/src/oracle/get_sibling_path.nr @@ -2,9 +2,9 @@ use dep::protocol_types::constants::NOTE_HASH_TREE_HEIGHT; use crate::utils::arr_copy_slice; #[oracle(getSiblingPath)] -fn get_sibling_path_oracle(_block_number: Field, _tree_id: Field, _leaf_index: Field) -> [Field; N] {} +fn get_sibling_path_oracle(_block_number: u32, _tree_id: Field, _leaf_index: Field) -> [Field; N] {} -unconstrained pub fn get_sibling_path(block_number: Field, tree_id: Field, leaf_index: Field) -> [Field; N] { +unconstrained pub fn get_sibling_path(block_number: u32, tree_id: Field, leaf_index: Field) -> [Field; N] { let value: [Field; N] = get_sibling_path_oracle(block_number, tree_id, leaf_index); value } diff --git a/yarn-project/end-to-end/src/e2e_inclusion_proofs_contract.test.ts b/yarn-project/end-to-end/src/e2e_inclusion_proofs_contract.test.ts index 56807979809..4240a863566 100644 --- a/yarn-project/end-to-end/src/e2e_inclusion_proofs_contract.test.ts +++ b/yarn-project/end-to-end/src/e2e_inclusion_proofs_contract.test.ts @@ -19,12 +19,15 @@ describe('e2e_inclusion_proofs_contract', () => { let accounts: CompleteAddress[]; let contract: InclusionProofsContract; + let deploymentBlockNumber: number; const publicValue = 236n; beforeAll(async () => { ({ pxe, teardown, wallets, accounts } = await setup(1)); - contract = await InclusionProofsContract.deploy(wallets[0], publicValue).send().deployed(); + const receipt = await InclusionProofsContract.deploy(wallets[0], publicValue).send().wait(); + contract = receipt.contract; + deploymentBlockNumber = receipt.blockNumber!; }, 100_000); afterAll(() => teardown()); @@ -32,11 +35,15 @@ describe('e2e_inclusion_proofs_contract', () => { it('proves note existence and its nullifier non-existence and nullifier non-existence failure case', async () => { // Owner of a note const owner = accounts[0].address; + let noteCreationBlockNumber: number; { // Create a note const value = 100n; const receipt = await contract.methods.create_note(owner, value).send().wait({ debug: true }); + + noteCreationBlockNumber = receipt.blockNumber!; const { newCommitments, visibleNotes } = receipt.debugInfo!; + expect(newCommitments.length).toBe(1); expect(visibleNotes.length).toBe(1); const [receivedValue, receivedOwner, _randomness] = visibleNotes[0].note.items; @@ -46,17 +53,14 @@ describe('e2e_inclusion_proofs_contract', () => { { // Prove note inclusion in a given block. - // TODO: Use here note block number from the creation note tx to test archival node. This is currently not - // possible because of issue #3564 - const blockNumber = await pxe.getBlockNumber(); const ignoredCommitment = 0; // Not ignored only when the note doesn't exist - await contract.methods.proveNoteInclusion(owner, blockNumber, ignoredCommitment).send().wait(); + await contract.methods.proveNoteInclusion(owner, noteCreationBlockNumber, ignoredCommitment).send().wait(); } { // Prove that the note has not been nullified - // TODO: Use here note block number from the creation note tx to test archival node. This is currently not - // possible because of issue #3564 + // TODO(#3535): Prove the nullifier non-inclusion at older block to test archival node. This is currently not + // possible because of issue https://github.com/AztecProtocol/aztec-packages/issues/3535 const blockNumber = await pxe.getBlockNumber(); const ignoredNullifier = 0; // Not ignored only when the note doesn't exist await contract.methods.proveNullifierNonInclusion(owner, blockNumber, ignoredNullifier).send().wait(); @@ -93,12 +97,16 @@ describe('e2e_inclusion_proofs_contract', () => { }); it('proves an existence of a public value in private context', async () => { - const blockNumber = await pxe.getBlockNumber(); + // Chose random block number between deployment and current block number to test archival node + const blockNumber = await getRandomBlockNumberSinceDeployment(); + await contract.methods.provePublicValueInclusion(publicValue, blockNumber).send().wait(); }); it('public value existence failure case', async () => { - const blockNumber = await pxe.getBlockNumber(); + // Chose random block number between deployment and current block number to test archival node + const blockNumber = await getRandomBlockNumberSinceDeployment(); + const randomPublicValue = Fr.random(); await expect( contract.methods.provePublicValueInclusion(randomPublicValue, blockNumber).send().wait(), @@ -106,6 +114,8 @@ describe('e2e_inclusion_proofs_contract', () => { }); it('proves existence of a nullifier in private context', async () => { + // TODO(#3535): Test this at "random" block to test archival node. This is currently not possible because of + // issue https://github.com/AztecProtocol/aztec-packages/issues/3535 const blockNumber = await pxe.getBlockNumber(); const block = await pxe.getBlock(blockNumber); const nullifier = block?.newNullifiers[0]; @@ -114,6 +124,8 @@ describe('e2e_inclusion_proofs_contract', () => { }); it('nullifier existence failure case', async () => { + // TODO(#3535): Test this at "random" block to test archival node. This is currently not possible because of + // issue https://github.com/AztecProtocol/aztec-packages/issues/3535 const blockNumber = await pxe.getBlockNumber(); const randomNullifier = Fr.random(); @@ -121,4 +133,9 @@ describe('e2e_inclusion_proofs_contract', () => { /Low nullifier witness not found for nullifier 0x[0-9a-fA-F]+ at block/, ); }); + + const getRandomBlockNumberSinceDeployment = async () => { + const currentBlockNumber = await pxe.getBlockNumber(); + return deploymentBlockNumber + Math.floor(Math.random() * (currentBlockNumber - deploymentBlockNumber)); + }; }); diff --git a/yarn-project/noir-contracts/src/contracts/inclusion_proofs_contract/src/main.nr b/yarn-project/noir-contracts/src/contracts/inclusion_proofs_contract/src/main.nr index d9235ccd6ee..a06c832cd50 100644 --- a/yarn-project/noir-contracts/src/contracts/inclusion_proofs_contract/src/main.nr +++ b/yarn-project/noir-contracts/src/contracts/inclusion_proofs_contract/src/main.nr @@ -98,14 +98,9 @@ contract InclusionProofs { #[aztec(private)] fn proveNoteInclusion( owner: AztecAddress, - block_number: Field, // The block at which we'll prove that the note exists + block_number: u32, // The block at which we'll prove that the note exists spare_commitment: Field, // This is only used when the note is not found --> used to test the failure case ) { - // TODO: assert that block number is less than the block number of context.block_header - // --> This will either require a new oracle method that returns block_header.global_variables_hash preimage - // or modifying the private context so that we somehow expose it. - // Blocked by #3564 - // 1) Get block header from oracle and ensure that the block hash is included in the current blocks tree // root. let block_header = context.get_block_header(block_number); @@ -142,14 +137,9 @@ contract InclusionProofs { #[aztec(private)] fn proveNullifierNonInclusion( owner: AztecAddress, - block_number: Field, // The block at which we'll prove that the nullifier does not exists + block_number: u32, // The block at which we'll prove that the nullifier does not exists spare_nullifier: Field, // This is only used when the note is not found --> used to test the failure case ) { - // TODO: assert that block number is less than the block number of context.block_header - // --> This will either require a new oracle method that returns block_header.global_variables_hash preimage - // or modifying the private context so that we somehow expose it. - // Blocked by #3564 - // 1) Get block header from oracle and ensure that the block hash is included in the current blocks tree // root. let block_header = context.get_block_header(block_number); @@ -215,13 +205,8 @@ contract InclusionProofs { #[aztec(private)] fn proveNullifierInclusion( nullifier: Field, - block_number: Field, // The block at which we'll prove that the nullifier not exists in the tree + block_number: u32, // The block at which we'll prove that the nullifier not exists in the tree ) { - // TODO: assert that block number is less than the block number of context.block_header - // --> This will either require a new oracle method that returns block_header.global_variables_hash preimage - // or modifying the private context so that we somehow expose it. - // Blocked by #3564 - // 1) Get block header from oracle and ensure that the block hash is included in the current blocks tree // root. let block_header = context.get_block_header(block_number); @@ -248,13 +233,8 @@ contract InclusionProofs { #[aztec(private)] fn provePublicValueInclusion( public_value: Field, - block_number: Field, // The block at which we'll prove that the public value exists + block_number: u32, // The block at which we'll prove that the public value exists ) { - // TODO: assert that block number is less than the block number of context.block_header - // --> This will either require a new oracle method that returns block_header.global_variables_hash preimage - // or modifying the private context so that we somehow expose it. - // Blocked by #3564 - // 1) Get block header from oracle and ensure that the block hash is included in the current blocks tree // root. let block_header = context.get_block_header(block_number); diff --git a/yarn-project/pxe/src/simulator_oracle/index.ts b/yarn-project/pxe/src/simulator_oracle/index.ts index 7e495c173ea..2eb485fd287 100644 --- a/yarn-project/pxe/src/simulator_oracle/index.ts +++ b/yarn-project/pxe/src/simulator_oracle/index.ts @@ -183,4 +183,12 @@ export class SimulatorOracle implements DBOracle { getBlockHeader(): Promise { return Promise.resolve(this.db.getBlockHeader()); } + + /** + * Fetches the current block number. + * @returns The block number. + */ + public async getBlockNumber(): Promise { + return await this.stateInfoProvider.getBlockNumber(); + } } diff --git a/yarn-project/types/src/interfaces/aztec-node.ts b/yarn-project/types/src/interfaces/aztec-node.ts index 92463e96b0f..ac57cd2f3a5 100644 --- a/yarn-project/types/src/interfaces/aztec-node.ts +++ b/yarn-project/types/src/interfaces/aztec-node.ts @@ -38,12 +38,6 @@ export interface AztecNode extends StateInfoProvider { */ getBlocks(from: number, limit: number): Promise; - /** - * Fetches the current block number. - * @returns The block number. - */ - getBlockNumber(): Promise; - /** * Method to fetch the version of the rollup the node is connected to. * @returns The rollup version. diff --git a/yarn-project/types/src/interfaces/state_info_provider.ts b/yarn-project/types/src/interfaces/state_info_provider.ts index 7818f984dab..97616711fb9 100644 --- a/yarn-project/types/src/interfaces/state_info_provider.ts +++ b/yarn-project/types/src/interfaces/state_info_provider.ts @@ -138,4 +138,10 @@ export interface StateInfoProvider { * @returns The requested block. */ getBlock(number: number): Promise; + + /** + * Fetches the current block number. + * @returns The block number. + */ + getBlockNumber(): Promise; } diff --git a/yarn-project/world-state/src/merkle-tree/merkle_tree_snapshot_operations_facade.ts b/yarn-project/world-state/src/merkle-tree/merkle_tree_snapshot_operations_facade.ts index 1fd883b98b5..450b6c5bca8 100644 --- a/yarn-project/world-state/src/merkle-tree/merkle_tree_snapshot_operations_facade.ts +++ b/yarn-project/world-state/src/merkle-tree/merkle_tree_snapshot_operations_facade.ts @@ -65,7 +65,7 @@ export class MerkleTreeSnapshotOperationsFacade implements MerkleTreeOperations } | undefined > { - return Promise.reject(new Error('not implemented')); + return Promise.reject(new Error('Snapshots not implemented for nullifier tree')); } async getSiblingPath(treeId: MerkleTreeId, index: bigint): Promise> { From 383e1231c1df23e1365e94642fe0d4d670d84c8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Rodr=C3=ADguez?= Date: Tue, 12 Dec 2023 15:08:53 +0000 Subject: [PATCH 23/35] chore: Run the protocol circuits noir tests in CI (#3660) Resolves #3205 --- yarn-project/noir-protocol-circuits/package.json | 6 ++---- .../src/crates/types/src/tests/fixtures/contract_tree.nr | 6 +++--- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/yarn-project/noir-protocol-circuits/package.json b/yarn-project/noir-protocol-circuits/package.json index f5eccb835a5..26096a5ecaa 100644 --- a/yarn-project/noir-protocol-circuits/package.json +++ b/yarn-project/noir-protocol-circuits/package.json @@ -15,11 +15,9 @@ "noir:build": "cd src && ../../../noir/target/release/nargo compile --silence-warnings && rm -rf ./target/debug_*", "noir:types": "yarn ts-node --esm src/scripts/generate_ts_from_abi.ts && yarn formatting:fix", "noir:test": "cd src && ../../../noir/target/release/nargo test", - "test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules $(yarn bin jest) --passWithNoTests" + "test": "yarn test:js && yarn noir:test", + "test:js": "NODE_NO_WARNINGS=1 node --experimental-vm-modules $(yarn bin jest) --passWithNoTests" }, - "inherits": [ - "../package.common.json" - ], "jest": { "preset": "ts-jest/presets/default-esm", "moduleNameMapper": { diff --git a/yarn-project/noir-protocol-circuits/src/crates/types/src/tests/fixtures/contract_tree.nr b/yarn-project/noir-protocol-circuits/src/crates/types/src/tests/fixtures/contract_tree.nr index 81626d401d8..867f28adbe1 100644 --- a/yarn-project/noir-protocol-circuits/src/crates/types/src/tests/fixtures/contract_tree.nr +++ b/yarn-project/noir-protocol-circuits/src/crates/types/src/tests/fixtures/contract_tree.nr @@ -1,8 +1,8 @@ // Constants taken from __snapshots__/noir_test_gen.test.ts.snap -global ROOT = 0x08ccb752b9e4f898ad6b87fb9ca1ed1f2b5e0b6cd67bf083e466ca6a31e21fae; +global ROOT = 0x2d541f5813387a5f4b32d1b3b103447ae142927457a60d00c779a5eeaead471d; global SIBLING_PATHS = [ [ - 0x141929db05c4a4803aebc2a4aea0fb2f09a15ae9862c4da49f245b7726f4088e, + 0x0c58a1ae52142f3369f9c46e6717bbef5aa55f9fc0e901a7d8cc860d9467021e, 0x27b1d0839a5b23baf12a8d195b18ac288fcf401afb2f70b8a4b529ede5fa9fed, 0x21dbfd1d029bf447152fcf89e355c334610d1632436ba170f738107266a71550, 0x0bcd1f91cf7bdd471d0a30c58c4706f3fdab3807a954b8f5b5e3bfec87d001bb, @@ -20,7 +20,7 @@ global SIBLING_PATHS = [ 0x177b9a10bbee32f77c719c6f8d071a18476cbeb021e155c642bbf93c716ce943, ], [ - 0x0b5dfb998fbdce8e5804992d471c1fc8050642b7aba107e854052eb562944a01, + 0x1ec6c50dc972349d72602ec6887f7accd3174d912ea58629447937865cb88a4d, 0x27b1d0839a5b23baf12a8d195b18ac288fcf401afb2f70b8a4b529ede5fa9fed, 0x21dbfd1d029bf447152fcf89e355c334610d1632436ba170f738107266a71550, 0x0bcd1f91cf7bdd471d0a30c58c4706f3fdab3807a954b8f5b5e3bfec87d001bb, From fd6eefe310e291e9625184dee9177a9b219e82f2 Mon Sep 17 00:00:00 2001 From: spypsy Date: Tue, 12 Dec 2023 15:12:44 +0000 Subject: [PATCH 24/35] fix: sandbox node mode api prefix (#3662) Please provide a paragraph or two giving a summary of the change, including relevant motivation and context. # Checklist: Remove the checklist to signal you've completed it. Enable auto-merge if the PR is ready to merge. - [ ] If the pull request requires a cryptography review (e.g. cryptographic algorithm implementations) I have added the 'crypto' tag. - [ ] I have reviewed my diff in github, line by line and removed unexpected formatting changes, testing logs, or commented-out code. - [ ] Every change is related to the PR description. - [ ] I have [linked](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue) this pull request to relevant issues (if any exist). Co-authored-by: PhilWindle <60546371+PhilWindle@users.noreply.github.com> --- yarn-project/aztec-sandbox/src/bin/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/aztec-sandbox/src/bin/index.ts b/yarn-project/aztec-sandbox/src/bin/index.ts index 72a9413454d..95ce182ff8a 100644 --- a/yarn-project/aztec-sandbox/src/bin/index.ts +++ b/yarn-project/aztec-sandbox/src/bin/index.ts @@ -160,7 +160,7 @@ async function main() { const port = process.env.AZTEC_NODE_PORT || 8080; // Use standard 8080 when no PXE is running const nodeRpcServer = createAztecNodeRpcServer(node); - const app = nodeRpcServer.getApp(); + const app = nodeRpcServer.getApp(API_PREFIX); // Add a /status endpoint const statusRouter = createStatusRouter(API_PREFIX); From b82b0c579c4a315c9b4eaf3e9726275633603b5a Mon Sep 17 00:00:00 2001 From: ledwards2225 <98505400+ledwards2225@users.noreply.github.com> Date: Tue, 12 Dec 2023 12:57:03 -0700 Subject: [PATCH 25/35] feat: copy constructors for builders (#3635) This work removes all reference data members from the circuit builders so that they can be default copy constructed. --- .../plonk/composer/ultra_composer.cpp | 8 +- .../arithmetization/arithmetization.hpp | 33 + .../goblin_ultra_circuit_builder.cpp | 220 +-- .../goblin_ultra_circuit_builder.hpp | 21 +- .../goblin_ultra_circuit_builder.test.cpp | 63 +- .../standard_circuit_builder.cpp | 164 +-- .../standard_circuit_builder.hpp | 34 +- .../circuit_builder/ultra_circuit_builder.cpp | 1230 ++++++++--------- .../circuit_builder/ultra_circuit_builder.hpp | 151 +- .../ultra_circuit_builder.test.cpp | 34 + .../composer/composer_lib.test.cpp | 10 +- .../stdlib/primitives/field/field.test.cpp | 4 +- 12 files changed, 1058 insertions(+), 914 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/plonk/composer/ultra_composer.cpp b/barretenberg/cpp/src/barretenberg/plonk/composer/ultra_composer.cpp index e34787f26d3..d83c9706eff 100644 --- a/barretenberg/cpp/src/barretenberg/plonk/composer/ultra_composer.cpp +++ b/barretenberg/cpp/src/barretenberg/plonk/composer/ultra_composer.cpp @@ -43,10 +43,10 @@ void UltraComposer::compute_witness(CircuitBuilder& circuit_constructor) // Note: the remaining NUM_RESERVED_GATES indices are padded with zeros within `compute_witness_base` (called // next). for (size_t i = filled_gates; i < total_num_gates; ++i) { - circuit_constructor.w_l.emplace_back(circuit_constructor.zero_idx); - circuit_constructor.w_r.emplace_back(circuit_constructor.zero_idx); - circuit_constructor.w_o.emplace_back(circuit_constructor.zero_idx); - circuit_constructor.w_4.emplace_back(circuit_constructor.zero_idx); + circuit_constructor.w_l().emplace_back(circuit_constructor.zero_idx); + circuit_constructor.w_r().emplace_back(circuit_constructor.zero_idx); + circuit_constructor.w_o().emplace_back(circuit_constructor.zero_idx); + circuit_constructor.w_4().emplace_back(circuit_constructor.zero_idx); } auto wire_polynomial_evaluations = construct_wire_polynomials_base(circuit_constructor, subgroup_size); diff --git a/barretenberg/cpp/src/barretenberg/proof_system/arithmetization/arithmetization.hpp b/barretenberg/cpp/src/barretenberg/proof_system/arithmetization/arithmetization.hpp index 05121c857f4..df0cd534a5f 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/arithmetization/arithmetization.hpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/arithmetization/arithmetization.hpp @@ -47,6 +47,12 @@ template class Standard { SelectorType& q_3() { return selectors[3]; }; SelectorType& q_c() { return selectors[4]; }; + const SelectorType& q_m() const { return selectors[0]; }; + const SelectorType& q_1() const { return selectors[1]; }; + const SelectorType& q_2() const { return selectors[2]; }; + const SelectorType& q_3() const { return selectors[3]; }; + const SelectorType& q_c() const { return selectors[4]; }; + Standard() : selectors(NUM_SELECTORS) {} @@ -87,6 +93,18 @@ template class Ultra { SelectorType& q_aux() { return selectors[9]; }; SelectorType& q_lookup_type() { return selectors[10]; }; + const SelectorType& q_m() const { return selectors[0]; }; + const SelectorType& q_c() const { return selectors[1]; }; + const SelectorType& q_1() const { return selectors[2]; }; + const SelectorType& q_2() const { return selectors[3]; }; + const SelectorType& q_3() const { return selectors[4]; }; + const SelectorType& q_4() const { return selectors[5]; }; + const SelectorType& q_arith() const { return selectors[6]; }; + const SelectorType& q_sort() const { return selectors[7]; }; + const SelectorType& q_elliptic() const { return selectors[8]; }; + const SelectorType& q_aux() const { return selectors[9]; }; + const SelectorType& q_lookup_type() const { return selectors[10]; }; + const auto& get() const { return selectors; }; void reserve(size_t size_hint) @@ -141,6 +159,21 @@ template class UltraHonk { SelectorType& q_poseidon2_external() { return this->selectors[12]; }; SelectorType& q_poseidon2_internal() { return this->selectors[13]; }; + const SelectorType& q_m() const { return selectors[0]; }; + const SelectorType& q_c() const { return selectors[1]; }; + const SelectorType& q_1() const { return selectors[2]; }; + const SelectorType& q_2() const { return selectors[3]; }; + const SelectorType& q_3() const { return selectors[4]; }; + const SelectorType& q_4() const { return selectors[5]; }; + const SelectorType& q_arith() const { return selectors[6]; }; + const SelectorType& q_sort() const { return selectors[7]; }; + const SelectorType& q_elliptic() const { return selectors[8]; }; + const SelectorType& q_aux() const { return selectors[9]; }; + const SelectorType& q_lookup_type() const { return selectors[10]; }; + const SelectorType& q_busread() const { return selectors[11]; }; + const SelectorType& q_poseidon2_external() const { return this->selectors[12]; }; + const SelectorType& q_poseidon2_internal() const { return this->selectors[13]; }; + const auto& get() const { return selectors; }; void reserve(size_t size_hint) diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.cpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.cpp index 0ce5b9fdfa1..8b30c606781 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.cpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.cpp @@ -43,72 +43,72 @@ template void GoblinUltraCircuitBuilder_::add_gates_to_ensure_ } // Construct gate corresponding to a single calldata read - size_t read_idx = 1; // index into calldata array at which we want to read - this->w_l.emplace_back(public_calldata[read_idx]); // populate with value of calldata at read index - this->w_r.emplace_back(this->add_variable(FF(read_idx))); // populate with read index as witness - calldata_read_counts[read_idx]++; // increment read count at read index - q_busread().emplace_back(1); // read selector on + size_t read_idx = 1; // index into calldata array at which we want to read + this->w_l().emplace_back(public_calldata[read_idx]); // populate with value of calldata at read index + this->w_r().emplace_back(this->add_variable(FF(read_idx))); // populate with read index as witness + calldata_read_counts[read_idx]++; // increment read count at read index + q_busread().emplace_back(1); // read selector on // populate all other components with zero - this->w_o.emplace_back(this->zero_idx); - this->w_4.emplace_back(this->zero_idx); - this->q_m.emplace_back(0); - this->q_1.emplace_back(0); - this->q_2.emplace_back(0); - this->q_3.emplace_back(0); - this->q_c.emplace_back(0); - this->q_sort.emplace_back(0); - this->q_arith.emplace_back(0); - this->q_4.emplace_back(0); - this->q_lookup_type.emplace_back(0); - this->q_elliptic.emplace_back(0); - this->q_aux.emplace_back(0); - this->q_poseidon2_external.emplace_back(0); - this->q_poseidon2_internal.emplace_back(0); + this->w_o().emplace_back(this->zero_idx); + this->w_4().emplace_back(this->zero_idx); + this->q_m().emplace_back(0); + this->q_1().emplace_back(0); + this->q_2().emplace_back(0); + this->q_3().emplace_back(0); + this->q_c().emplace_back(0); + this->q_sort().emplace_back(0); + this->q_arith().emplace_back(0); + this->q_4().emplace_back(0); + this->q_lookup_type().emplace_back(0); + this->q_elliptic().emplace_back(0); + this->q_aux().emplace_back(0); + this->q_poseidon2_external().emplace_back(0); + this->q_poseidon2_internal().emplace_back(0); ++this->num_gates; // mock gates that use poseidon selectors, with all zeros as input - this->w_l.emplace_back(this->zero_idx); - this->w_r.emplace_back(this->zero_idx); - this->w_o.emplace_back(this->zero_idx); - this->w_4.emplace_back(this->zero_idx); - this->q_m.emplace_back(0); - this->q_1.emplace_back(0); - this->q_2.emplace_back(0); - this->q_3.emplace_back(0); - this->q_c.emplace_back(0); - this->q_arith.emplace_back(0); - this->q_4.emplace_back(0); - this->q_sort.emplace_back(0); - this->q_lookup_type.emplace_back(0); - this->q_elliptic.emplace_back(0); - this->q_aux.emplace_back(0); + this->w_l().emplace_back(this->zero_idx); + this->w_r().emplace_back(this->zero_idx); + this->w_o().emplace_back(this->zero_idx); + this->w_4().emplace_back(this->zero_idx); + this->q_m().emplace_back(0); + this->q_1().emplace_back(0); + this->q_2().emplace_back(0); + this->q_3().emplace_back(0); + this->q_c().emplace_back(0); + this->q_arith().emplace_back(0); + this->q_4().emplace_back(0); + this->q_sort().emplace_back(0); + this->q_lookup_type().emplace_back(0); + this->q_elliptic().emplace_back(0); + this->q_aux().emplace_back(0); this->q_busread().emplace_back(0); - this->q_poseidon2_external.emplace_back(1); - this->q_poseidon2_internal.emplace_back(1); + this->q_poseidon2_external().emplace_back(1); + this->q_poseidon2_internal().emplace_back(1); ++this->num_gates; // second gate that stores the output of all zeros of the poseidon gates - this->w_l.emplace_back(this->zero_idx); - this->w_r.emplace_back(this->zero_idx); - this->w_o.emplace_back(this->zero_idx); - this->w_4.emplace_back(this->zero_idx); - this->q_m.emplace_back(0); - this->q_1.emplace_back(0); - this->q_2.emplace_back(0); - this->q_3.emplace_back(0); - this->q_c.emplace_back(0); - this->q_arith.emplace_back(0); - this->q_4.emplace_back(0); - this->q_sort.emplace_back(0); - this->q_lookup_type.emplace_back(0); - this->q_elliptic.emplace_back(0); - this->q_aux.emplace_back(0); + this->w_l().emplace_back(this->zero_idx); + this->w_r().emplace_back(this->zero_idx); + this->w_o().emplace_back(this->zero_idx); + this->w_4().emplace_back(this->zero_idx); + this->q_m().emplace_back(0); + this->q_1().emplace_back(0); + this->q_2().emplace_back(0); + this->q_3().emplace_back(0); + this->q_c().emplace_back(0); + this->q_arith().emplace_back(0); + this->q_4().emplace_back(0); + this->q_sort().emplace_back(0); + this->q_lookup_type().emplace_back(0); + this->q_elliptic().emplace_back(0); + this->q_aux().emplace_back(0); this->q_busread().emplace_back(0); - this->q_poseidon2_external.emplace_back(0); - this->q_poseidon2_internal.emplace_back(0); + this->q_poseidon2_external().emplace_back(0); + this->q_poseidon2_internal().emplace_back(0); ++this->num_gates; } @@ -233,15 +233,15 @@ ecc_op_tuple GoblinUltraCircuitBuilder_::decompose_ecc_operands(uint32_t op_ */ template void GoblinUltraCircuitBuilder_::populate_ecc_op_wires(const ecc_op_tuple& in) { - ecc_op_wire_1.emplace_back(in.op); - ecc_op_wire_2.emplace_back(in.x_lo); - ecc_op_wire_3.emplace_back(in.x_hi); - ecc_op_wire_4.emplace_back(in.y_lo); + ecc_op_wire_1().emplace_back(in.op); + ecc_op_wire_2().emplace_back(in.x_lo); + ecc_op_wire_3().emplace_back(in.x_hi); + ecc_op_wire_4().emplace_back(in.y_lo); - ecc_op_wire_1.emplace_back(this->zero_idx); - ecc_op_wire_2.emplace_back(in.y_hi); - ecc_op_wire_3.emplace_back(in.z_1); - ecc_op_wire_4.emplace_back(in.z_2); + ecc_op_wire_1().emplace_back(this->zero_idx); + ecc_op_wire_2().emplace_back(in.y_hi); + ecc_op_wire_3().emplace_back(in.z_1); + ecc_op_wire_4().emplace_back(in.z_2); num_ecc_op_gates += 2; }; @@ -249,48 +249,48 @@ template void GoblinUltraCircuitBuilder_::populate_ecc_op_wire template void GoblinUltraCircuitBuilder_::create_poseidon2_external_gate(const poseidon2_external_gate_& in) { - this->w_l.emplace_back(in.a); - this->w_r.emplace_back(in.b); - this->w_o.emplace_back(in.c); - this->w_4.emplace_back(in.d); - this->q_m.emplace_back(0); - this->q_1.emplace_back(Poseidon2Bn254ScalarFieldParams::round_constants[in.round_idx][0]); - this->q_2.emplace_back(Poseidon2Bn254ScalarFieldParams::round_constants[in.round_idx][1]); - this->q_3.emplace_back(Poseidon2Bn254ScalarFieldParams::round_constants[in.round_idx][2]); - this->q_c.emplace_back(0); - this->q_arith.emplace_back(0); - this->q_4.emplace_back(Poseidon2Bn254ScalarFieldParams::round_constants[in.round_idx][3]); - this->q_sort.emplace_back(0); - this->q_lookup_type.emplace_back(0); - this->q_elliptic.emplace_back(0); - this->q_aux.emplace_back(0); + this->w_l().emplace_back(in.a); + this->w_r().emplace_back(in.b); + this->w_o().emplace_back(in.c); + this->w_4().emplace_back(in.d); + this->q_m().emplace_back(0); + this->q_1().emplace_back(Poseidon2Bn254ScalarFieldParams::round_constants[in.round_idx][0]); + this->q_2().emplace_back(Poseidon2Bn254ScalarFieldParams::round_constants[in.round_idx][1]); + this->q_3().emplace_back(Poseidon2Bn254ScalarFieldParams::round_constants[in.round_idx][2]); + this->q_c().emplace_back(0); + this->q_arith().emplace_back(0); + this->q_4().emplace_back(Poseidon2Bn254ScalarFieldParams::round_constants[in.round_idx][3]); + this->q_sort().emplace_back(0); + this->q_lookup_type().emplace_back(0); + this->q_elliptic().emplace_back(0); + this->q_aux().emplace_back(0); this->q_busread().emplace_back(0); - this->q_poseidon2_external.emplace_back(1); - this->q_poseidon2_internal.emplace_back(0); + this->q_poseidon2_external().emplace_back(1); + this->q_poseidon2_internal().emplace_back(0); ++this->num_gates; } template void GoblinUltraCircuitBuilder_::create_poseidon2_internal_gate(const poseidon2_internal_gate_& in) { - this->w_l.emplace_back(in.a); - this->w_r.emplace_back(in.b); - this->w_o.emplace_back(in.c); - this->w_4.emplace_back(in.d); - this->q_m.emplace_back(0); - this->q_1.emplace_back(Poseidon2Bn254ScalarFieldParams::round_constants[in.round_idx][0]); - this->q_2.emplace_back(0); - this->q_3.emplace_back(0); - this->q_c.emplace_back(0); - this->q_arith.emplace_back(0); - this->q_4.emplace_back(0); - this->q_sort.emplace_back(0); - this->q_lookup_type.emplace_back(0); - this->q_elliptic.emplace_back(0); - this->q_aux.emplace_back(0); + this->w_l().emplace_back(in.a); + this->w_r().emplace_back(in.b); + this->w_o().emplace_back(in.c); + this->w_4().emplace_back(in.d); + this->q_m().emplace_back(0); + this->q_1().emplace_back(Poseidon2Bn254ScalarFieldParams::round_constants[in.round_idx][0]); + this->q_2().emplace_back(0); + this->q_3().emplace_back(0); + this->q_c().emplace_back(0); + this->q_arith().emplace_back(0); + this->q_4().emplace_back(0); + this->q_sort().emplace_back(0); + this->q_lookup_type().emplace_back(0); + this->q_elliptic().emplace_back(0); + this->q_aux().emplace_back(0); this->q_busread().emplace_back(0); - this->q_poseidon2_external.emplace_back(0); - this->q_poseidon2_internal.emplace_back(1); + this->q_poseidon2_external().emplace_back(0); + this->q_poseidon2_internal().emplace_back(1); ++this->num_gates; } @@ -420,25 +420,25 @@ template bool GoblinUltraCircuitBuilder_::check_circuit() FF w_3_value; FF w_4_value; // Get the values of selectors and wires and update tag products along the way - q_poseidon2_external_value = this->q_poseidon2_external[i]; - q_poseidon2_internal_value = this->q_poseidon2_internal[i]; - q_1_value = this->q_1[i]; - q_2_value = this->q_2[i]; - q_3_value = this->q_3[i]; - q_4_value = this->q_4[i]; - w_1_value = this->get_variable(this->w_l[i]); - w_2_value = this->get_variable(this->w_r[i]); - w_3_value = this->get_variable(this->w_o[i]); - w_4_value = this->get_variable(this->w_4[i]); + q_poseidon2_external_value = this->q_poseidon2_external()[i]; + q_poseidon2_internal_value = this->q_poseidon2_internal()[i]; + q_1_value = this->q_1()[i]; + q_2_value = this->q_2()[i]; + q_3_value = this->q_3()[i]; + q_4_value = this->q_4()[i]; + w_1_value = this->get_variable(this->w_l()[i]); + w_2_value = this->get_variable(this->w_r()[i]); + w_3_value = this->get_variable(this->w_o()[i]); + w_4_value = this->get_variable(this->w_4()[i]); FF w_1_shifted_value; FF w_2_shifted_value; FF w_3_shifted_value; FF w_4_shifted_value; if (i < (this->num_gates - 1)) { - w_1_shifted_value = this->get_variable(this->w_l[i + 1]); - w_2_shifted_value = this->get_variable(this->w_r[i + 1]); - w_3_shifted_value = this->get_variable(this->w_o[i + 1]); - w_4_shifted_value = this->get_variable(this->w_4[i + 1]); + w_1_shifted_value = this->get_variable(this->w_l()[i + 1]); + w_2_shifted_value = this->get_variable(this->w_r()[i + 1]); + w_3_shifted_value = this->get_variable(this->w_o()[i + 1]); + w_4_shifted_value = this->get_variable(this->w_4()[i + 1]); } else { w_1_shifted_value = FF::zero(); w_2_shifted_value = FF::zero(); diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.hpp index e037fe2571d..8e5c6b14018 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.hpp @@ -37,14 +37,23 @@ template class GoblinUltraCircuitBuilder_ : public UltraCircuitBui // Wires storing ecc op queue data; values are indices into the variables array std::array::NUM_WIRES> ecc_op_wires; - WireVector& ecc_op_wire_1 = std::get<0>(ecc_op_wires); - WireVector& ecc_op_wire_2 = std::get<1>(ecc_op_wires); - WireVector& ecc_op_wire_3 = std::get<2>(ecc_op_wires); - WireVector& ecc_op_wire_4 = std::get<3>(ecc_op_wires); + WireVector& ecc_op_wire_1() { return std::get<0>(ecc_op_wires); }; + WireVector& ecc_op_wire_2() { return std::get<1>(ecc_op_wires); }; + WireVector& ecc_op_wire_3() { return std::get<2>(ecc_op_wires); }; + WireVector& ecc_op_wire_4() { return std::get<3>(ecc_op_wires); }; + + const WireVector& ecc_op_wire_1() const { return std::get<0>(ecc_op_wires); }; + const WireVector& ecc_op_wire_2() const { return std::get<1>(ecc_op_wires); }; + const WireVector& ecc_op_wire_3() const { return std::get<2>(ecc_op_wires); }; + const WireVector& ecc_op_wire_4() const { return std::get<3>(ecc_op_wires); }; SelectorVector& q_busread() { return this->selectors.q_busread(); }; - SelectorVector& q_poseidon2_external = this->selectors.q_poseidon2_external(); - SelectorVector& q_poseidon2_internal = this->selectors.q_poseidon2_internal(); + SelectorVector& q_poseidon2_external() { return this->selectors.q_poseidon2_external(); }; + SelectorVector& q_poseidon2_internal() { return this->selectors.q_poseidon2_internal(); }; + + const SelectorVector& q_busread() const { return this->selectors.q_busread(); }; + const SelectorVector& q_poseidon2_external() const { return this->selectors.q_poseidon2_external(); }; + const SelectorVector& q_poseidon2_internal() const { return this->selectors.q_poseidon2_internal(); }; // DataBus call/return data arrays std::vector public_calldata; diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.test.cpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.test.cpp index 7a3424626ae..87529305ecf 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.test.cpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.test.cpp @@ -8,6 +8,47 @@ auto& engine = numeric::random::get_debug_engine(); } namespace proof_system { +TEST(GoblinUltraCircuitBuilder, CopyConstructor) +{ + GoblinUltraCircuitBuilder circuit_constructor = GoblinUltraCircuitBuilder(); + fr a = fr::one(); + circuit_constructor.add_public_variable(a); + + for (size_t i = 0; i < 16; ++i) { + for (size_t j = 0; j < 16; ++j) { + uint64_t left = static_cast(j); + uint64_t right = static_cast(i); + uint32_t left_idx = circuit_constructor.add_variable(fr(left)); + uint32_t right_idx = circuit_constructor.add_variable(fr(right)); + uint32_t result_idx = circuit_constructor.add_variable(fr(left ^ right)); + + uint32_t add_idx = + circuit_constructor.add_variable(fr(left) + fr(right) + circuit_constructor.get_variable(result_idx)); + circuit_constructor.create_big_add_gate( + { left_idx, right_idx, result_idx, add_idx, fr(1), fr(1), fr(1), fr(-1), fr(0) }); + } + } + + // Compute a simple point accumulation natively + auto P1 = g1::affine_element::random_element(); + auto P2 = g1::affine_element::random_element(); + auto z = fr::random_element(); + + // Add gates corresponding to the above operations + circuit_constructor.queue_ecc_add_accum(P1); + circuit_constructor.queue_ecc_mul_accum(P2, z); + circuit_constructor.queue_ecc_eq(); + + bool result = circuit_constructor.check_circuit(); + EXPECT_EQ(result, true); + + GoblinUltraCircuitBuilder duplicate_circuit_constructor{ circuit_constructor }; + + EXPECT_EQ(duplicate_circuit_constructor.get_num_gates(), circuit_constructor.get_num_gates()); + EXPECT_EQ(duplicate_circuit_constructor.selectors.get(), circuit_constructor.selectors.get()); + EXPECT_TRUE(duplicate_circuit_constructor.check_circuit()); +} + TEST(GoblinUltraCircuitBuilder, BaseCase) { GoblinUltraCircuitBuilder circuit_constructor = GoblinUltraCircuitBuilder(); @@ -61,27 +102,27 @@ TEST(GoblinUltraCircuitBuilder, GoblinSimple) EXPECT_EQ(builder.num_ecc_op_gates, 6); // Check that the expected op codes have been correctly recorded in the 1st op wire - EXPECT_EQ(builder.ecc_op_wire_1[0], EccOpCode::ADD_ACCUM); - EXPECT_EQ(builder.ecc_op_wire_1[2], EccOpCode::MUL_ACCUM); - EXPECT_EQ(builder.ecc_op_wire_1[4], EccOpCode::EQUALITY); + EXPECT_EQ(builder.ecc_op_wire_1()[0], EccOpCode::ADD_ACCUM); + EXPECT_EQ(builder.ecc_op_wire_1()[2], EccOpCode::MUL_ACCUM); + EXPECT_EQ(builder.ecc_op_wire_1()[4], EccOpCode::EQUALITY); // Check that we can reconstruct the coordinates of P1 from the op_wires - auto P1_x_lo = uint256_t(builder.variables[builder.ecc_op_wire_2[0]]); - auto P1_x_hi = uint256_t(builder.variables[builder.ecc_op_wire_3[0]]); + auto P1_x_lo = uint256_t(builder.variables[builder.ecc_op_wire_2()[0]]); + auto P1_x_hi = uint256_t(builder.variables[builder.ecc_op_wire_3()[0]]); auto P1_x = P1_x_lo + (P1_x_hi << CHUNK_SIZE); EXPECT_EQ(P1_x, uint256_t(P1.x)); - auto P1_y_lo = uint256_t(builder.variables[builder.ecc_op_wire_4[0]]); - auto P1_y_hi = uint256_t(builder.variables[builder.ecc_op_wire_2[1]]); + auto P1_y_lo = uint256_t(builder.variables[builder.ecc_op_wire_4()[0]]); + auto P1_y_hi = uint256_t(builder.variables[builder.ecc_op_wire_2()[1]]); auto P1_y = P1_y_lo + (P1_y_hi << CHUNK_SIZE); EXPECT_EQ(P1_y, uint256_t(P1.y)); // Check that we can reconstruct the coordinates of P2 from the op_wires - auto P2_x_lo = uint256_t(builder.variables[builder.ecc_op_wire_2[2]]); - auto P2_x_hi = uint256_t(builder.variables[builder.ecc_op_wire_3[2]]); + auto P2_x_lo = uint256_t(builder.variables[builder.ecc_op_wire_2()[2]]); + auto P2_x_hi = uint256_t(builder.variables[builder.ecc_op_wire_3()[2]]); auto P2_x = P2_x_lo + (P2_x_hi << CHUNK_SIZE); EXPECT_EQ(P2_x, uint256_t(P2.x)); - auto P2_y_lo = uint256_t(builder.variables[builder.ecc_op_wire_4[2]]); - auto P2_y_hi = uint256_t(builder.variables[builder.ecc_op_wire_2[3]]); + auto P2_y_lo = uint256_t(builder.variables[builder.ecc_op_wire_4()[2]]); + auto P2_y_hi = uint256_t(builder.variables[builder.ecc_op_wire_2()[3]]); auto P2_y = P2_y_lo + (P2_y_hi << CHUNK_SIZE); EXPECT_EQ(P2_y, uint256_t(P2.y)); } diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/standard_circuit_builder.cpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/standard_circuit_builder.cpp index c9bcaa65b8f..3f930ec331e 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/standard_circuit_builder.cpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/standard_circuit_builder.cpp @@ -15,20 +15,20 @@ namespace proof_system { * Create an addition gate. * * @param in An add_triple containing the indexes of variables to be placed into the - * wires w_l, w_r, w_o and addition coefficients to be placed into q_1, q_2, q_3, q_c. + * wires w_l, w_r, w_o and addition coefficients to be placed into q_1, q_2, q_3, q_c(). */ template void StandardCircuitBuilder_::create_add_gate(const add_triple_& in) { this->assert_valid_variables({ in.a, in.b, in.c }); - w_l.emplace_back(in.a); - w_r.emplace_back(in.b); - w_o.emplace_back(in.c); - q_m.emplace_back(FF::zero()); - q_1.emplace_back(in.a_scaling); - q_2.emplace_back(in.b_scaling); - q_3.emplace_back(in.c_scaling); - q_c.emplace_back(in.const_scaling); + w_l().emplace_back(in.a); + w_r().emplace_back(in.b); + w_o().emplace_back(in.c); + q_m().emplace_back(FF::zero()); + q_1().emplace_back(in.a_scaling); + q_2().emplace_back(in.b_scaling); + q_3().emplace_back(in.c_scaling); + q_c().emplace_back(in.const_scaling); ++this->num_gates; } @@ -72,25 +72,25 @@ template void StandardCircuitBuilder_::create_balanced_add_gat FF temp = t0 + t1; uint32_t temp_idx = this->add_variable(temp); - w_l.emplace_back(in.a); - w_r.emplace_back(in.b); - w_o.emplace_back(temp_idx); - q_m.emplace_back(FF::zero()); - q_1.emplace_back(in.a_scaling); - q_2.emplace_back(in.b_scaling); - q_3.emplace_back(FF::neg_one()); - q_c.emplace_back(FF::zero()); + w_l().emplace_back(in.a); + w_r().emplace_back(in.b); + w_o().emplace_back(temp_idx); + q_m().emplace_back(FF::zero()); + q_1().emplace_back(in.a_scaling); + q_2().emplace_back(in.b_scaling); + q_3().emplace_back(FF::neg_one()); + q_c().emplace_back(FF::zero()); ++this->num_gates; - w_l.emplace_back(temp_idx); - w_r.emplace_back(in.c); - w_o.emplace_back(in.d); - q_m.emplace_back(FF::zero()); - q_1.emplace_back(FF::one()); - q_2.emplace_back(in.c_scaling); - q_3.emplace_back(in.d_scaling); - q_c.emplace_back(in.const_scaling); + w_l().emplace_back(temp_idx); + w_r().emplace_back(in.c); + w_o().emplace_back(in.d); + q_m().emplace_back(FF::zero()); + q_1().emplace_back(FF::one()); + q_2().emplace_back(in.c_scaling); + q_3().emplace_back(in.d_scaling); + q_c().emplace_back(in.const_scaling); ++this->num_gates; @@ -98,26 +98,26 @@ template void StandardCircuitBuilder_::create_balanced_add_gat // i.e. in.d * (in.d - 1) * (in.d - 2) = 0 FF temp_2 = this->get_variable(in.d).sqr() - this->get_variable(in.d); uint32_t temp_2_idx = this->add_variable(temp_2); - w_l.emplace_back(in.d); - w_r.emplace_back(in.d); - w_o.emplace_back(temp_2_idx); - q_m.emplace_back(FF::one()); - q_1.emplace_back(FF::neg_one()); - q_2.emplace_back(FF::zero()); - q_3.emplace_back(FF::neg_one()); - q_c.emplace_back(FF::zero()); + w_l().emplace_back(in.d); + w_r().emplace_back(in.d); + w_o().emplace_back(temp_2_idx); + q_m().emplace_back(FF::one()); + q_1().emplace_back(FF::neg_one()); + q_2().emplace_back(FF::zero()); + q_3().emplace_back(FF::neg_one()); + q_c().emplace_back(FF::zero()); ++this->num_gates; constexpr FF neg_two = -FF(2); - w_l.emplace_back(temp_2_idx); - w_r.emplace_back(in.d); - w_o.emplace_back(this->zero_idx); - q_m.emplace_back(FF::one()); - q_1.emplace_back(neg_two); - q_2.emplace_back(FF::zero()); - q_3.emplace_back(FF::zero()); - q_c.emplace_back(FF::zero()); + w_l().emplace_back(temp_2_idx); + w_r().emplace_back(in.d); + w_o().emplace_back(this->zero_idx); + q_m().emplace_back(FF::one()); + q_1().emplace_back(neg_two); + q_2().emplace_back(FF::zero()); + q_3().emplace_back(FF::zero()); + q_c().emplace_back(FF::zero()); ++this->num_gates; } @@ -181,20 +181,20 @@ template void StandardCircuitBuilder_::create_big_mul_gate(con * Create a multiplication gate. * * @param in A mul_tripple containing the indexes of variables to be placed into the - * wires w_l, w_r, w_o and scaling coefficients to be placed into q_m, q_3, q_c. + * wires w_l, w_r, w_o and scaling coefficients to be placed into q_m, q_3, q_c(). */ template void StandardCircuitBuilder_::create_mul_gate(const mul_triple_& in) { this->assert_valid_variables({ in.a, in.b, in.c }); - w_l.emplace_back(in.a); - w_r.emplace_back(in.b); - w_o.emplace_back(in.c); - q_m.emplace_back(in.mul_scaling); - q_1.emplace_back(FF::zero()); - q_2.emplace_back(FF::zero()); - q_3.emplace_back(in.c_scaling); - q_c.emplace_back(in.const_scaling); + w_l().emplace_back(in.a); + w_r().emplace_back(in.b); + w_o().emplace_back(in.c); + q_m().emplace_back(in.mul_scaling); + q_1().emplace_back(FF::zero()); + q_2().emplace_back(FF::zero()); + q_3().emplace_back(in.c_scaling); + q_c().emplace_back(in.const_scaling); ++this->num_gates; } @@ -209,15 +209,15 @@ template void StandardCircuitBuilder_::create_bool_gate(const { this->assert_valid_variables({ variable_index }); - w_l.emplace_back(variable_index); - w_r.emplace_back(variable_index); - w_o.emplace_back(variable_index); + w_l().emplace_back(variable_index); + w_r().emplace_back(variable_index); + w_o().emplace_back(variable_index); - q_m.emplace_back(FF::one()); - q_1.emplace_back(FF::zero()); - q_2.emplace_back(FF::zero()); - q_3.emplace_back(FF::neg_one()); - q_c.emplace_back(FF::zero()); + q_m().emplace_back(FF::one()); + q_1().emplace_back(FF::zero()); + q_2().emplace_back(FF::zero()); + q_3().emplace_back(FF::neg_one()); + q_c().emplace_back(FF::zero()); ++this->num_gates; } @@ -231,14 +231,14 @@ template void StandardCircuitBuilder_::create_poly_gate(const { this->assert_valid_variables({ in.a, in.b, in.c }); - w_l.emplace_back(in.a); - w_r.emplace_back(in.b); - w_o.emplace_back(in.c); - q_m.emplace_back(in.q_m); - q_1.emplace_back(in.q_l); - q_2.emplace_back(in.q_r); - q_3.emplace_back(in.q_o); - q_c.emplace_back(in.q_c); + w_l().emplace_back(in.a); + w_r().emplace_back(in.b); + w_o().emplace_back(in.c); + q_m().emplace_back(in.q_m); + q_1().emplace_back(in.q_l); + q_2().emplace_back(in.q_r); + q_3().emplace_back(in.q_o); + q_c().emplace_back(in.q_c); ++this->num_gates; } @@ -435,14 +435,14 @@ void StandardCircuitBuilder_::fix_witness(const uint32_t witness_index, cons { this->assert_valid_variables({ witness_index }); - w_l.emplace_back(witness_index); - w_r.emplace_back(this->zero_idx); - w_o.emplace_back(this->zero_idx); - q_m.emplace_back(FF::zero()); - q_1.emplace_back(FF::one()); - q_2.emplace_back(FF::zero()); - q_3.emplace_back(FF::zero()); - q_c.emplace_back(-witness_value); + w_l().emplace_back(witness_index); + w_r().emplace_back(this->zero_idx); + w_o().emplace_back(this->zero_idx); + q_m().emplace_back(FF::zero()); + q_1().emplace_back(FF::one()); + q_2().emplace_back(FF::zero()); + q_3().emplace_back(FF::zero()); + q_c().emplace_back(-witness_value); ++this->num_gates; } @@ -499,10 +499,10 @@ template bool StandardCircuitBuilder_::check_circuit() for (size_t i = 0; i < this->num_gates; i++) { gate_sum = FF::zero(); - left = this->get_variable(w_l[i]); - right = this->get_variable(w_r[i]); - output = this->get_variable(w_o[i]); - gate_sum = q_m[i] * left * right + q_1[i] * left + q_2[i] * right + q_3[i] * output + q_c[i]; + left = this->get_variable(w_l()[i]); + right = this->get_variable(w_r()[i]); + output = this->get_variable(w_o()[i]); + gate_sum = q_m()[i] * left * right + q_1()[i] * left + q_2()[i] * right + q_3()[i] * output + q_c()[i]; if (!gate_sum.is_zero()) { info("gate number", i); return false; @@ -543,11 +543,11 @@ template msgpack::sbuffer StandardCircuitBuilder_::export_circ } for (size_t i = 0; i < this->num_gates; i++) { - std::vector tmp_sel = { q_m[i], q_1[i], q_2[i], q_3[i], q_c[i] }; + std::vector tmp_sel = { q_m()[i], q_1()[i], q_2()[i], q_3()[i], q_c()[i] }; std::vector tmp_w = { - this->real_variable_index[w_l[i]], - this->real_variable_index[w_r[i]], - this->real_variable_index[w_o[i]], + this->real_variable_index[w_l()[i]], + this->real_variable_index[w_r()[i]], + this->real_variable_index[w_o()[i]], }; cir.selectors.push_back(tmp_sel); cir.wires.push_back(tmp_w); diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/standard_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/standard_circuit_builder.hpp index 819bc5a3c51..4c379ae9acd 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/standard_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/standard_circuit_builder.hpp @@ -29,15 +29,25 @@ template class StandardCircuitBuilder_ : public CircuitBuilderBase using WireVector = std::vector>; using SelectorVector = std::vector>; - WireVector& w_l = std::get<0>(wires); - WireVector& w_r = std::get<1>(wires); - WireVector& w_o = std::get<2>(wires); - - SelectorVector& q_m = this->selectors.q_m(); - SelectorVector& q_1 = this->selectors.q_1(); - SelectorVector& q_2 = this->selectors.q_2(); - SelectorVector& q_3 = this->selectors.q_3(); - SelectorVector& q_c = this->selectors.q_c(); + WireVector& w_l() { return std::get<0>(wires); }; + WireVector& w_r() { return std::get<1>(wires); }; + WireVector& w_o() { return std::get<2>(wires); }; + + const WireVector& w_l() const { return std::get<0>(wires); }; + const WireVector& w_r() const { return std::get<1>(wires); }; + const WireVector& w_o() const { return std::get<2>(wires); }; + + SelectorVector& q_m() { return this->selectors.q_m(); }; + SelectorVector& q_1() { return this->selectors.q_1(); }; + SelectorVector& q_2() { return this->selectors.q_2(); }; + SelectorVector& q_3() { return this->selectors.q_3(); }; + SelectorVector& q_c() { return this->selectors.q_c(); }; + + const SelectorVector& q_m() const { return this->selectors.q_m(); }; + const SelectorVector& q_1() const { return this->selectors.q_1(); }; + const SelectorVector& q_2() const { return this->selectors.q_2(); }; + const SelectorVector& q_3() const { return this->selectors.q_3(); }; + const SelectorVector& q_c() const { return this->selectors.q_c(); }; static constexpr size_t UINT_LOG2_BASE = 2; @@ -50,9 +60,9 @@ template class StandardCircuitBuilder_ : public CircuitBuilderBase : CircuitBuilderBase(size_hint) { selectors.reserve(size_hint); - w_l.reserve(size_hint); - w_r.reserve(size_hint); - w_o.reserve(size_hint); + w_l().reserve(size_hint); + w_r().reserve(size_hint); + w_o().reserve(size_hint); // To effieciently constrain wires to zero, we set the first value of w_1 to be 0, and use copy constraints for // all future zero values. // (#216)(Adrian): This should be done in a constant way, maybe by initializing the constant_variable_indices diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/ultra_circuit_builder.cpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/ultra_circuit_builder.cpp index 39443c58c7f..d3d9767bb74 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/ultra_circuit_builder.cpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/ultra_circuit_builder.cpp @@ -63,22 +63,22 @@ void UltraCircuitBuilder_::add_gates_to_ensure_all_polys_are_no { // First add a gate to simultaneously ensure first entries of all wires is zero and to add a non // zero value to all selectors aside from q_c and q_lookup - w_l.emplace_back(this->zero_idx); - w_r.emplace_back(this->zero_idx); - w_o.emplace_back(this->zero_idx); - w_4.emplace_back(this->zero_idx); - q_m.emplace_back(1); - q_1.emplace_back(1); - q_2.emplace_back(1); - q_3.emplace_back(1); - q_c.emplace_back(0); - q_sort.emplace_back(1); - - q_arith.emplace_back(1); - q_4.emplace_back(1); - q_lookup_type.emplace_back(0); - q_elliptic.emplace_back(1); - q_aux.emplace_back(1); + w_l().emplace_back(this->zero_idx); + w_r().emplace_back(this->zero_idx); + w_o().emplace_back(this->zero_idx); + w_4().emplace_back(this->zero_idx); + q_m().emplace_back(1); + q_1().emplace_back(1); + q_2().emplace_back(1); + q_3().emplace_back(1); + q_c().emplace_back(0); + q_sort().emplace_back(1); + + q_arith().emplace_back(1); + q_4().emplace_back(1); + q_lookup_type().emplace_back(0); + q_elliptic().emplace_back(1); + q_aux().emplace_back(1); selectors.pad_additional(); check_selector_length_consistency(); ++this->num_gates; @@ -125,21 +125,21 @@ void UltraCircuitBuilder_::create_add_gate(const add_triple_assert_valid_variables({ in.a, in.b, in.c }); - w_l.emplace_back(in.a); - w_r.emplace_back(in.b); - w_o.emplace_back(in.c); - w_4.emplace_back(this->zero_idx); - q_m.emplace_back(0); - q_1.emplace_back(in.a_scaling); - q_2.emplace_back(in.b_scaling); - q_3.emplace_back(in.c_scaling); - q_c.emplace_back(in.const_scaling); - q_arith.emplace_back(1); - q_4.emplace_back(0); - q_sort.emplace_back(0); - q_lookup_type.emplace_back(0); - q_elliptic.emplace_back(0); - q_aux.emplace_back(0); + w_l().emplace_back(in.a); + w_r().emplace_back(in.b); + w_o().emplace_back(in.c); + w_4().emplace_back(this->zero_idx); + q_m().emplace_back(0); + q_1().emplace_back(in.a_scaling); + q_2().emplace_back(in.b_scaling); + q_3().emplace_back(in.c_scaling); + q_c().emplace_back(in.const_scaling); + q_arith().emplace_back(1); + q_4().emplace_back(0); + q_sort().emplace_back(0); + q_lookup_type().emplace_back(0); + q_elliptic().emplace_back(0); + q_aux().emplace_back(0); selectors.pad_additional(); check_selector_length_consistency(); ++this->num_gates; @@ -158,21 +158,21 @@ void UltraCircuitBuilder_::create_big_add_gate(const add_quad_< const bool include_next_gate_w_4) { this->assert_valid_variables({ in.a, in.b, in.c, in.d }); - w_l.emplace_back(in.a); - w_r.emplace_back(in.b); - w_o.emplace_back(in.c); - w_4.emplace_back(in.d); - q_m.emplace_back(0); - q_1.emplace_back(in.a_scaling); - q_2.emplace_back(in.b_scaling); - q_3.emplace_back(in.c_scaling); - q_c.emplace_back(in.const_scaling); - q_arith.emplace_back(include_next_gate_w_4 ? 2 : 1); - q_4.emplace_back(in.d_scaling); - q_sort.emplace_back(0); - q_lookup_type.emplace_back(0); - q_elliptic.emplace_back(0); - q_aux.emplace_back(0); + w_l().emplace_back(in.a); + w_r().emplace_back(in.b); + w_o().emplace_back(in.c); + w_4().emplace_back(in.d); + q_m().emplace_back(0); + q_1().emplace_back(in.a_scaling); + q_2().emplace_back(in.b_scaling); + q_3().emplace_back(in.c_scaling); + q_c().emplace_back(in.const_scaling); + q_arith().emplace_back(include_next_gate_w_4 ? 2 : 1); + q_4().emplace_back(in.d_scaling); + q_sort().emplace_back(0); + q_lookup_type().emplace_back(0); + q_elliptic().emplace_back(0); + q_aux().emplace_back(0); selectors.pad_additional(); check_selector_length_consistency(); ++this->num_gates; @@ -253,21 +253,21 @@ void UltraCircuitBuilder_::create_big_mul_gate(const mul_quad_< { this->assert_valid_variables({ in.a, in.b, in.c, in.d }); - w_l.emplace_back(in.a); - w_r.emplace_back(in.b); - w_o.emplace_back(in.c); - w_4.emplace_back(in.d); - q_m.emplace_back(in.mul_scaling); - q_1.emplace_back(in.a_scaling); - q_2.emplace_back(in.b_scaling); - q_3.emplace_back(in.c_scaling); - q_c.emplace_back(in.const_scaling); - q_arith.emplace_back(1); - q_4.emplace_back(in.d_scaling); - q_sort.emplace_back(0); - q_lookup_type.emplace_back(0); - q_elliptic.emplace_back(0); - q_aux.emplace_back(0); + w_l().emplace_back(in.a); + w_r().emplace_back(in.b); + w_o().emplace_back(in.c); + w_4().emplace_back(in.d); + q_m().emplace_back(in.mul_scaling); + q_1().emplace_back(in.a_scaling); + q_2().emplace_back(in.b_scaling); + q_3().emplace_back(in.c_scaling); + q_c().emplace_back(in.const_scaling); + q_arith().emplace_back(1); + q_4().emplace_back(in.d_scaling); + q_sort().emplace_back(0); + q_lookup_type().emplace_back(0); + q_elliptic().emplace_back(0); + q_aux().emplace_back(0); selectors.pad_additional(); check_selector_length_consistency(); ++this->num_gates; @@ -280,21 +280,21 @@ void UltraCircuitBuilder_::create_balanced_add_gate(const add_q { this->assert_valid_variables({ in.a, in.b, in.c, in.d }); - w_l.emplace_back(in.a); - w_r.emplace_back(in.b); - w_o.emplace_back(in.c); - w_4.emplace_back(in.d); - q_m.emplace_back(0); - q_1.emplace_back(in.a_scaling); - q_2.emplace_back(in.b_scaling); - q_3.emplace_back(in.c_scaling); - q_c.emplace_back(in.const_scaling); - q_arith.emplace_back(1); - q_4.emplace_back(in.d_scaling); - q_sort.emplace_back(0); - q_lookup_type.emplace_back(0); - q_elliptic.emplace_back(0); - q_aux.emplace_back(0); + w_l().emplace_back(in.a); + w_r().emplace_back(in.b); + w_o().emplace_back(in.c); + w_4().emplace_back(in.d); + q_m().emplace_back(0); + q_1().emplace_back(in.a_scaling); + q_2().emplace_back(in.b_scaling); + q_3().emplace_back(in.c_scaling); + q_c().emplace_back(in.const_scaling); + q_arith().emplace_back(1); + q_4().emplace_back(in.d_scaling); + q_sort().emplace_back(0); + q_lookup_type().emplace_back(0); + q_elliptic().emplace_back(0); + q_aux().emplace_back(0); selectors.pad_additional(); check_selector_length_consistency(); ++this->num_gates; @@ -323,21 +323,21 @@ void UltraCircuitBuilder_::create_mul_gate(const mul_triple_assert_valid_variables({ in.a, in.b, in.c }); - w_l.emplace_back(in.a); - w_r.emplace_back(in.b); - w_o.emplace_back(in.c); - w_4.emplace_back(this->zero_idx); - q_m.emplace_back(in.mul_scaling); - q_1.emplace_back(0); - q_2.emplace_back(0); - q_3.emplace_back(in.c_scaling); - q_c.emplace_back(in.const_scaling); - q_arith.emplace_back(1); - q_4.emplace_back(0); - q_sort.emplace_back(0); - q_lookup_type.emplace_back(0); - q_elliptic.emplace_back(0); - q_aux.emplace_back(0); + w_l().emplace_back(in.a); + w_r().emplace_back(in.b); + w_o().emplace_back(in.c); + w_4().emplace_back(this->zero_idx); + q_m().emplace_back(in.mul_scaling); + q_1().emplace_back(0); + q_2().emplace_back(0); + q_3().emplace_back(in.c_scaling); + q_c().emplace_back(in.const_scaling); + q_arith().emplace_back(1); + q_4().emplace_back(0); + q_sort().emplace_back(0); + q_lookup_type().emplace_back(0); + q_elliptic().emplace_back(0); + q_aux().emplace_back(0); selectors.pad_additional(); check_selector_length_consistency(); ++this->num_gates; @@ -352,22 +352,22 @@ void UltraCircuitBuilder_::create_bool_gate(const uint32_t vari { this->assert_valid_variables({ variable_index }); - w_l.emplace_back(variable_index); - w_r.emplace_back(variable_index); - w_o.emplace_back(this->zero_idx); - w_4.emplace_back(this->zero_idx); - q_m.emplace_back(1); - q_1.emplace_back(-1); - q_2.emplace_back(0); - q_3.emplace_back(0); - q_c.emplace_back(0); - q_sort.emplace_back(0); - - q_arith.emplace_back(1); - q_4.emplace_back(0); - q_lookup_type.emplace_back(0); - q_elliptic.emplace_back(0); - q_aux.emplace_back(0); + w_l().emplace_back(variable_index); + w_r().emplace_back(variable_index); + w_o().emplace_back(this->zero_idx); + w_4().emplace_back(this->zero_idx); + q_m().emplace_back(1); + q_1().emplace_back(-1); + q_2().emplace_back(0); + q_3().emplace_back(0); + q_c().emplace_back(0); + q_sort().emplace_back(0); + + q_arith().emplace_back(1); + q_4().emplace_back(0); + q_lookup_type().emplace_back(0); + q_elliptic().emplace_back(0); + q_aux().emplace_back(0); selectors.pad_additional(); check_selector_length_consistency(); ++this->num_gates; @@ -384,22 +384,22 @@ void UltraCircuitBuilder_::create_poly_gate(const poly_triple_< { this->assert_valid_variables({ in.a, in.b, in.c }); - w_l.emplace_back(in.a); - w_r.emplace_back(in.b); - w_o.emplace_back(in.c); - w_4.emplace_back(this->zero_idx); - q_m.emplace_back(in.q_m); - q_1.emplace_back(in.q_l); - q_2.emplace_back(in.q_r); - q_3.emplace_back(in.q_o); - q_c.emplace_back(in.q_c); - q_sort.emplace_back(0); - - q_arith.emplace_back(1); - q_4.emplace_back(0); - q_lookup_type.emplace_back(0); - q_elliptic.emplace_back(0); - q_aux.emplace_back(0); + w_l().emplace_back(in.a); + w_r().emplace_back(in.b); + w_o().emplace_back(in.c); + w_4().emplace_back(this->zero_idx); + q_m().emplace_back(in.q_m); + q_1().emplace_back(in.q_l); + q_2().emplace_back(in.q_r); + q_3().emplace_back(in.q_o); + q_c().emplace_back(in.q_c); + q_sort().emplace_back(0); + + q_arith().emplace_back(1); + q_4().emplace_back(0); + q_lookup_type().emplace_back(0); + q_elliptic().emplace_back(0); + q_aux().emplace_back(0); selectors.pad_additional(); check_selector_length_consistency(); ++this->num_gates; @@ -427,53 +427,53 @@ void UltraCircuitBuilder_::create_ecc_add_gate(const ecc_add_ga this->assert_valid_variables({ in.x1, in.x2, in.x3, in.y1, in.y2, in.y3 }); bool can_fuse_into_previous_gate = true; - can_fuse_into_previous_gate = can_fuse_into_previous_gate && (w_r[this->num_gates - 1] == in.x1); - can_fuse_into_previous_gate = can_fuse_into_previous_gate && (w_o[this->num_gates - 1] == in.y1); - can_fuse_into_previous_gate = can_fuse_into_previous_gate && (q_3[this->num_gates - 1] == 0); - can_fuse_into_previous_gate = can_fuse_into_previous_gate && (q_4[this->num_gates - 1] == 0); - can_fuse_into_previous_gate = can_fuse_into_previous_gate && (q_1[this->num_gates - 1] == 0); - can_fuse_into_previous_gate = can_fuse_into_previous_gate && (q_arith[this->num_gates - 1] == 0); - can_fuse_into_previous_gate = can_fuse_into_previous_gate && (q_m[this->num_gates - 1] == 0); + can_fuse_into_previous_gate = can_fuse_into_previous_gate && (w_r()[this->num_gates - 1] == in.x1); + can_fuse_into_previous_gate = can_fuse_into_previous_gate && (w_o()[this->num_gates - 1] == in.y1); + can_fuse_into_previous_gate = can_fuse_into_previous_gate && (q_3()[this->num_gates - 1] == 0); + can_fuse_into_previous_gate = can_fuse_into_previous_gate && (q_4()[this->num_gates - 1] == 0); + can_fuse_into_previous_gate = can_fuse_into_previous_gate && (q_1()[this->num_gates - 1] == 0); + can_fuse_into_previous_gate = can_fuse_into_previous_gate && (q_arith()[this->num_gates - 1] == 0); + can_fuse_into_previous_gate = can_fuse_into_previous_gate && (q_m()[this->num_gates - 1] == 0); if (can_fuse_into_previous_gate) { - q_1[this->num_gates - 1] = in.sign_coefficient; - q_elliptic[this->num_gates - 1] = 1; + q_1()[this->num_gates - 1] = in.sign_coefficient; + q_elliptic()[this->num_gates - 1] = 1; } else { - w_l.emplace_back(this->zero_idx); - w_r.emplace_back(in.x1); - w_o.emplace_back(in.y1); - w_4.emplace_back(this->zero_idx); - q_3.emplace_back(0); - q_4.emplace_back(0); - q_1.emplace_back(in.sign_coefficient); - - q_arith.emplace_back(0); - q_2.emplace_back(0); - q_m.emplace_back(0); - q_c.emplace_back(0); - q_sort.emplace_back(0); - q_lookup_type.emplace_back(0); - q_elliptic.emplace_back(1); - q_aux.emplace_back(0); + w_l().emplace_back(this->zero_idx); + w_r().emplace_back(in.x1); + w_o().emplace_back(in.y1); + w_4().emplace_back(this->zero_idx); + q_3().emplace_back(0); + q_4().emplace_back(0); + q_1().emplace_back(in.sign_coefficient); + + q_arith().emplace_back(0); + q_2().emplace_back(0); + q_m().emplace_back(0); + q_c().emplace_back(0); + q_sort().emplace_back(0); + q_lookup_type().emplace_back(0); + q_elliptic().emplace_back(1); + q_aux().emplace_back(0); selectors.pad_additional(); check_selector_length_consistency(); ++this->num_gates; } - w_l.emplace_back(in.x2); - w_4.emplace_back(in.y2); - w_r.emplace_back(in.x3); - w_o.emplace_back(in.y3); - q_m.emplace_back(0); - q_1.emplace_back(0); - q_2.emplace_back(0); - q_3.emplace_back(0); - q_c.emplace_back(0); - q_arith.emplace_back(0); - q_4.emplace_back(0); - q_sort.emplace_back(0); - q_lookup_type.emplace_back(0); - q_elliptic.emplace_back(0); - q_aux.emplace_back(0); + w_l().emplace_back(in.x2); + w_4().emplace_back(in.y2); + w_r().emplace_back(in.x3); + w_o().emplace_back(in.y3); + q_m().emplace_back(0); + q_1().emplace_back(0); + q_2().emplace_back(0); + q_3().emplace_back(0); + q_c().emplace_back(0); + q_arith().emplace_back(0); + q_4().emplace_back(0); + q_sort().emplace_back(0); + q_lookup_type().emplace_back(0); + q_elliptic().emplace_back(0); + q_aux().emplace_back(0); selectors.pad_additional(); check_selector_length_consistency(); ++this->num_gates; @@ -496,51 +496,51 @@ void UltraCircuitBuilder_::create_ecc_dbl_gate(const ecc_dbl_ga * can also chain double gates together **/ bool can_fuse_into_previous_gate = true; - can_fuse_into_previous_gate = can_fuse_into_previous_gate && (w_r[this->num_gates - 1] == in.x1); - can_fuse_into_previous_gate = can_fuse_into_previous_gate && (w_o[this->num_gates - 1] == in.y1); - can_fuse_into_previous_gate = can_fuse_into_previous_gate && (q_arith[this->num_gates - 1] == 0); - can_fuse_into_previous_gate = can_fuse_into_previous_gate && (q_lookup_type[this->num_gates - 1] == 0); - can_fuse_into_previous_gate = can_fuse_into_previous_gate && (q_aux[this->num_gates - 1] == 0); + can_fuse_into_previous_gate = can_fuse_into_previous_gate && (w_r()[this->num_gates - 1] == in.x1); + can_fuse_into_previous_gate = can_fuse_into_previous_gate && (w_o()[this->num_gates - 1] == in.y1); + can_fuse_into_previous_gate = can_fuse_into_previous_gate && (q_arith()[this->num_gates - 1] == 0); + can_fuse_into_previous_gate = can_fuse_into_previous_gate && (q_lookup_type()[this->num_gates - 1] == 0); + can_fuse_into_previous_gate = can_fuse_into_previous_gate && (q_aux()[this->num_gates - 1] == 0); if (can_fuse_into_previous_gate) { - q_elliptic[this->num_gates - 1] = 1; - q_m[this->num_gates - 1] = 1; + q_elliptic()[this->num_gates - 1] = 1; + q_m()[this->num_gates - 1] = 1; } else { - w_r.emplace_back(in.x1); - w_o.emplace_back(in.y1); - w_l.emplace_back(this->zero_idx); - w_4.emplace_back(this->zero_idx); - q_elliptic.emplace_back(1); - q_m.emplace_back(1); - q_1.emplace_back(0); - q_2.emplace_back(0); - q_3.emplace_back(0); - q_c.emplace_back(0); - q_arith.emplace_back(0); - q_4.emplace_back(0); - q_sort.emplace_back(0); - q_lookup_type.emplace_back(0); - q_aux.emplace_back(0); + w_r().emplace_back(in.x1); + w_o().emplace_back(in.y1); + w_l().emplace_back(this->zero_idx); + w_4().emplace_back(this->zero_idx); + q_elliptic().emplace_back(1); + q_m().emplace_back(1); + q_1().emplace_back(0); + q_2().emplace_back(0); + q_3().emplace_back(0); + q_c().emplace_back(0); + q_arith().emplace_back(0); + q_4().emplace_back(0); + q_sort().emplace_back(0); + q_lookup_type().emplace_back(0); + q_aux().emplace_back(0); selectors.pad_additional(); check_selector_length_consistency(); ++this->num_gates; } - w_r.emplace_back(in.x3); - w_o.emplace_back(in.y3); - w_l.emplace_back(this->zero_idx); - w_4.emplace_back(this->zero_idx); - q_m.emplace_back(0); - q_1.emplace_back(0); - q_2.emplace_back(0); - q_3.emplace_back(0); - q_c.emplace_back(0); - q_arith.emplace_back(0); - q_4.emplace_back(0); - q_sort.emplace_back(0); - q_lookup_type.emplace_back(0); - q_elliptic.emplace_back(0); - q_aux.emplace_back(0); + w_r().emplace_back(in.x3); + w_o().emplace_back(in.y3); + w_l().emplace_back(this->zero_idx); + w_4().emplace_back(this->zero_idx); + q_m().emplace_back(0); + q_1().emplace_back(0); + q_2().emplace_back(0); + q_3().emplace_back(0); + q_c().emplace_back(0); + q_arith().emplace_back(0); + q_4().emplace_back(0); + q_sort().emplace_back(0); + q_lookup_type().emplace_back(0); + q_elliptic().emplace_back(0); + q_aux().emplace_back(0); selectors.pad_additional(); check_selector_length_consistency(); ++this->num_gates; @@ -557,21 +557,21 @@ void UltraCircuitBuilder_::fix_witness(const uint32_t witness_i { this->assert_valid_variables({ witness_index }); - w_l.emplace_back(witness_index); - w_r.emplace_back(this->zero_idx); - w_o.emplace_back(this->zero_idx); - w_4.emplace_back(this->zero_idx); - q_m.emplace_back(0); - q_1.emplace_back(1); - q_2.emplace_back(0); - q_3.emplace_back(0); - q_c.emplace_back(-witness_value); - q_arith.emplace_back(1); - q_4.emplace_back(0); - q_sort.emplace_back(0); - q_lookup_type.emplace_back(0); - q_elliptic.emplace_back(0); - q_aux.emplace_back(0); + w_l().emplace_back(witness_index); + w_r().emplace_back(this->zero_idx); + w_o().emplace_back(this->zero_idx); + w_4().emplace_back(this->zero_idx); + q_m().emplace_back(0); + q_1().emplace_back(1); + q_2().emplace_back(0); + q_3().emplace_back(0); + q_c().emplace_back(-witness_value); + q_arith().emplace_back(1); + q_4().emplace_back(0); + q_sort().emplace_back(0); + q_lookup_type().emplace_back(0); + q_elliptic().emplace_back(0); + q_aux().emplace_back(0); selectors.pad_additional(); check_selector_length_consistency(); ++this->num_gates; @@ -633,21 +633,21 @@ plookup::ReadData UltraCircuitBuilder_::create_gates_ read_data[plookup::ColumnIdx::C3].push_back(third_idx); this->assert_valid_variables({ first_idx, second_idx, third_idx }); - q_lookup_type.emplace_back(FF(1)); - q_3.emplace_back(FF(table.table_index)); - w_l.emplace_back(first_idx); - w_r.emplace_back(second_idx); - w_o.emplace_back(third_idx); - w_4.emplace_back(this->zero_idx); - q_1.emplace_back(0); - q_2.emplace_back((i == (num_lookups - 1) ? 0 : -multi_table.column_1_step_sizes[i + 1])); - q_m.emplace_back((i == (num_lookups - 1) ? 0 : -multi_table.column_2_step_sizes[i + 1])); - q_c.emplace_back((i == (num_lookups - 1) ? 0 : -multi_table.column_3_step_sizes[i + 1])); - q_arith.emplace_back(0); - q_4.emplace_back(0); - q_sort.emplace_back(0); - q_elliptic.emplace_back(0); - q_aux.emplace_back(0); + q_lookup_type().emplace_back(FF(1)); + q_3().emplace_back(FF(table.table_index)); + w_l().emplace_back(first_idx); + w_r().emplace_back(second_idx); + w_o().emplace_back(third_idx); + w_4().emplace_back(this->zero_idx); + q_1().emplace_back(0); + q_2().emplace_back((i == (num_lookups - 1) ? 0 : -multi_table.column_1_step_sizes[i + 1])); + q_m().emplace_back((i == (num_lookups - 1) ? 0 : -multi_table.column_2_step_sizes[i + 1])); + q_c().emplace_back((i == (num_lookups - 1) ? 0 : -multi_table.column_3_step_sizes[i + 1])); + q_arith().emplace_back(0); + q_4().emplace_back(0); + q_sort().emplace_back(0); + q_elliptic().emplace_back(0); + q_aux().emplace_back(0); selectors.pad_additional(); check_selector_length_consistency(); ++this->num_gates; @@ -942,42 +942,42 @@ void UltraCircuitBuilder_::create_sort_constraint(const std::ve for (size_t i = 0; i < variable_index.size(); i += gate_width) { - w_l.emplace_back(variable_index[i]); - w_r.emplace_back(variable_index[i + 1]); - w_o.emplace_back(variable_index[i + 2]); - w_4.emplace_back(variable_index[i + 3]); + w_l().emplace_back(variable_index[i]); + w_r().emplace_back(variable_index[i + 1]); + w_o().emplace_back(variable_index[i + 2]); + w_4().emplace_back(variable_index[i + 3]); ++this->num_gates; - q_m.emplace_back(0); - q_1.emplace_back(0); - q_2.emplace_back(0); - q_3.emplace_back(0); - q_c.emplace_back(0); - q_arith.emplace_back(0); - q_4.emplace_back(0); - q_sort.emplace_back(1); - q_elliptic.emplace_back(0); - q_lookup_type.emplace_back(0); - q_aux.emplace_back(0); + q_m().emplace_back(0); + q_1().emplace_back(0); + q_2().emplace_back(0); + q_3().emplace_back(0); + q_c().emplace_back(0); + q_arith().emplace_back(0); + q_4().emplace_back(0); + q_sort().emplace_back(1); + q_elliptic().emplace_back(0); + q_lookup_type().emplace_back(0); + q_aux().emplace_back(0); selectors.pad_additional(); check_selector_length_consistency(); } // dummy gate needed because of sort widget's check of next row - w_l.emplace_back(variable_index[variable_index.size() - 1]); - w_r.emplace_back(this->zero_idx); - w_o.emplace_back(this->zero_idx); - w_4.emplace_back(this->zero_idx); + w_l().emplace_back(variable_index[variable_index.size() - 1]); + w_r().emplace_back(this->zero_idx); + w_o().emplace_back(this->zero_idx); + w_4().emplace_back(this->zero_idx); ++this->num_gates; - q_m.emplace_back(0); - q_1.emplace_back(0); - q_2.emplace_back(0); - q_3.emplace_back(0); - q_c.emplace_back(0); - q_arith.emplace_back(0); - q_4.emplace_back(0); - q_sort.emplace_back(0); - q_elliptic.emplace_back(0); - q_lookup_type.emplace_back(0); - q_aux.emplace_back(0); + q_m().emplace_back(0); + q_1().emplace_back(0); + q_2().emplace_back(0); + q_3().emplace_back(0); + q_c().emplace_back(0); + q_arith().emplace_back(0); + q_4().emplace_back(0); + q_sort().emplace_back(0); + q_elliptic().emplace_back(0); + q_lookup_type().emplace_back(0); + q_aux().emplace_back(0); selectors.pad_additional(); check_selector_length_consistency(); } @@ -997,22 +997,22 @@ void UltraCircuitBuilder_::create_dummy_constraints(const std:: this->assert_valid_variables(padded_list); for (size_t i = 0; i < padded_list.size(); i += gate_width) { - w_l.emplace_back(padded_list[i]); - w_r.emplace_back(padded_list[i + 1]); - w_o.emplace_back(padded_list[i + 2]); - w_4.emplace_back(padded_list[i + 3]); + w_l().emplace_back(padded_list[i]); + w_r().emplace_back(padded_list[i + 1]); + w_o().emplace_back(padded_list[i + 2]); + w_4().emplace_back(padded_list[i + 3]); ++this->num_gates; - q_m.emplace_back(0); - q_1.emplace_back(0); - q_2.emplace_back(0); - q_3.emplace_back(0); - q_c.emplace_back(0); - q_arith.emplace_back(0); - q_4.emplace_back(0); - q_sort.emplace_back(0); - q_elliptic.emplace_back(0); - q_lookup_type.emplace_back(0); - q_aux.emplace_back(0); + q_m().emplace_back(0); + q_1().emplace_back(0); + q_2().emplace_back(0); + q_3().emplace_back(0); + q_c().emplace_back(0); + q_arith().emplace_back(0); + q_4().emplace_back(0); + q_sort().emplace_back(0); + q_elliptic().emplace_back(0); + q_lookup_type().emplace_back(0); + q_aux().emplace_back(0); selectors.pad_additional(); check_selector_length_consistency(); } @@ -1029,86 +1029,86 @@ void UltraCircuitBuilder_::create_sort_constraint_with_edges( this->assert_valid_variables(variable_index); // enforce range checks of first row and starting at start - w_l.emplace_back(variable_index[0]); - w_r.emplace_back(variable_index[1]); - w_o.emplace_back(variable_index[2]); - w_4.emplace_back(variable_index[3]); + w_l().emplace_back(variable_index[0]); + w_r().emplace_back(variable_index[1]); + w_o().emplace_back(variable_index[2]); + w_4().emplace_back(variable_index[3]); ++this->num_gates; - q_m.emplace_back(0); - q_1.emplace_back(1); - q_2.emplace_back(0); - q_3.emplace_back(0); - q_c.emplace_back(-start); - q_arith.emplace_back(1); - q_4.emplace_back(0); - q_sort.emplace_back(1); - q_elliptic.emplace_back(0); - q_lookup_type.emplace_back(0); - q_aux.emplace_back(0); + q_m().emplace_back(0); + q_1().emplace_back(1); + q_2().emplace_back(0); + q_3().emplace_back(0); + q_c().emplace_back(-start); + q_arith().emplace_back(1); + q_4().emplace_back(0); + q_sort().emplace_back(1); + q_elliptic().emplace_back(0); + q_lookup_type().emplace_back(0); + q_aux().emplace_back(0); selectors.pad_additional(); check_selector_length_consistency(); // enforce range check for middle rows for (size_t i = gate_width; i < variable_index.size() - gate_width; i += gate_width) { - w_l.emplace_back(variable_index[i]); - w_r.emplace_back(variable_index[i + 1]); - w_o.emplace_back(variable_index[i + 2]); - w_4.emplace_back(variable_index[i + 3]); + w_l().emplace_back(variable_index[i]); + w_r().emplace_back(variable_index[i + 1]); + w_o().emplace_back(variable_index[i + 2]); + w_4().emplace_back(variable_index[i + 3]); ++this->num_gates; - q_m.emplace_back(0); - q_1.emplace_back(0); - q_2.emplace_back(0); - q_3.emplace_back(0); - q_c.emplace_back(0); - q_arith.emplace_back(0); - q_4.emplace_back(0); - q_sort.emplace_back(1); - q_elliptic.emplace_back(0); - q_lookup_type.emplace_back(0); - q_aux.emplace_back(0); + q_m().emplace_back(0); + q_1().emplace_back(0); + q_2().emplace_back(0); + q_3().emplace_back(0); + q_c().emplace_back(0); + q_arith().emplace_back(0); + q_4().emplace_back(0); + q_sort().emplace_back(1); + q_elliptic().emplace_back(0); + q_lookup_type().emplace_back(0); + q_aux().emplace_back(0); selectors.pad_additional(); check_selector_length_consistency(); } // enforce range checks of last row and ending at end if (variable_index.size() > gate_width) { - w_l.emplace_back(variable_index[variable_index.size() - 4]); - w_r.emplace_back(variable_index[variable_index.size() - 3]); - w_o.emplace_back(variable_index[variable_index.size() - 2]); - w_4.emplace_back(variable_index[variable_index.size() - 1]); + w_l().emplace_back(variable_index[variable_index.size() - 4]); + w_r().emplace_back(variable_index[variable_index.size() - 3]); + w_o().emplace_back(variable_index[variable_index.size() - 2]); + w_4().emplace_back(variable_index[variable_index.size() - 1]); ++this->num_gates; - q_m.emplace_back(0); - q_1.emplace_back(0); - q_2.emplace_back(0); - q_3.emplace_back(0); - q_c.emplace_back(0); - q_arith.emplace_back(0); - q_4.emplace_back(0); - q_sort.emplace_back(1); - q_elliptic.emplace_back(0); - q_lookup_type.emplace_back(0); - q_aux.emplace_back(0); + q_m().emplace_back(0); + q_1().emplace_back(0); + q_2().emplace_back(0); + q_3().emplace_back(0); + q_c().emplace_back(0); + q_arith().emplace_back(0); + q_4().emplace_back(0); + q_sort().emplace_back(1); + q_elliptic().emplace_back(0); + q_lookup_type().emplace_back(0); + q_aux().emplace_back(0); selectors.pad_additional(); check_selector_length_consistency(); } // dummy gate needed because of sort widget's check of next row // use this gate to check end condition - w_l.emplace_back(variable_index[variable_index.size() - 1]); - w_r.emplace_back(this->zero_idx); - w_o.emplace_back(this->zero_idx); - w_4.emplace_back(this->zero_idx); + w_l().emplace_back(variable_index[variable_index.size() - 1]); + w_r().emplace_back(this->zero_idx); + w_o().emplace_back(this->zero_idx); + w_4().emplace_back(this->zero_idx); ++this->num_gates; - q_m.emplace_back(0); - q_1.emplace_back(1); - q_2.emplace_back(0); - q_3.emplace_back(0); - q_c.emplace_back(-end); - q_arith.emplace_back(1); - q_4.emplace_back(0); - q_sort.emplace_back(0); - q_elliptic.emplace_back(0); - q_lookup_type.emplace_back(0); - q_aux.emplace_back(0); + q_m().emplace_back(0); + q_1().emplace_back(1); + q_2().emplace_back(0); + q_3().emplace_back(0); + q_c().emplace_back(-end); + q_arith().emplace_back(1); + q_4().emplace_back(0); + q_sort().emplace_back(0); + q_elliptic().emplace_back(0); + q_lookup_type().emplace_back(0); + q_aux().emplace_back(0); selectors.pad_additional(); check_selector_length_consistency(); } @@ -1213,67 +1213,67 @@ std::vector UltraCircuitBuilder_::decompose_into_defa template void UltraCircuitBuilder_::apply_aux_selectors(const AUX_SELECTORS type) { - q_aux.emplace_back(type == AUX_SELECTORS::NONE ? 0 : 1); - q_sort.emplace_back(0); - q_lookup_type.emplace_back(0); - q_elliptic.emplace_back(0); + q_aux().emplace_back(type == AUX_SELECTORS::NONE ? 0 : 1); + q_sort().emplace_back(0); + q_lookup_type().emplace_back(0); + q_elliptic().emplace_back(0); switch (type) { case AUX_SELECTORS::LIMB_ACCUMULATE_1: { - q_1.emplace_back(0); - q_2.emplace_back(0); - q_3.emplace_back(1); - q_4.emplace_back(1); - q_m.emplace_back(0); - q_c.emplace_back(0); - q_arith.emplace_back(0); + q_1().emplace_back(0); + q_2().emplace_back(0); + q_3().emplace_back(1); + q_4().emplace_back(1); + q_m().emplace_back(0); + q_c().emplace_back(0); + q_arith().emplace_back(0); selectors.pad_additional(); check_selector_length_consistency(); break; } case AUX_SELECTORS::LIMB_ACCUMULATE_2: { - q_1.emplace_back(0); - q_2.emplace_back(0); - q_3.emplace_back(1); - q_4.emplace_back(0); - q_m.emplace_back(1); - q_c.emplace_back(0); - q_arith.emplace_back(0); + q_1().emplace_back(0); + q_2().emplace_back(0); + q_3().emplace_back(1); + q_4().emplace_back(0); + q_m().emplace_back(1); + q_c().emplace_back(0); + q_arith().emplace_back(0); selectors.pad_additional(); check_selector_length_consistency(); break; } case AUX_SELECTORS::NON_NATIVE_FIELD_1: { - q_1.emplace_back(0); - q_2.emplace_back(1); - q_3.emplace_back(1); - q_4.emplace_back(0); - q_m.emplace_back(0); - q_c.emplace_back(0); - q_arith.emplace_back(0); + q_1().emplace_back(0); + q_2().emplace_back(1); + q_3().emplace_back(1); + q_4().emplace_back(0); + q_m().emplace_back(0); + q_c().emplace_back(0); + q_arith().emplace_back(0); selectors.pad_additional(); check_selector_length_consistency(); break; } case AUX_SELECTORS::NON_NATIVE_FIELD_2: { - q_1.emplace_back(0); - q_2.emplace_back(1); - q_3.emplace_back(0); - q_4.emplace_back(1); - q_m.emplace_back(0); - q_c.emplace_back(0); - q_arith.emplace_back(0); + q_1().emplace_back(0); + q_2().emplace_back(1); + q_3().emplace_back(0); + q_4().emplace_back(1); + q_m().emplace_back(0); + q_c().emplace_back(0); + q_arith().emplace_back(0); selectors.pad_additional(); check_selector_length_consistency(); break; } case AUX_SELECTORS::NON_NATIVE_FIELD_3: { - q_1.emplace_back(0); - q_2.emplace_back(1); - q_3.emplace_back(0); - q_4.emplace_back(0); - q_m.emplace_back(1); - q_c.emplace_back(0); - q_arith.emplace_back(0); + q_1().emplace_back(0); + q_2().emplace_back(1); + q_3().emplace_back(0); + q_4().emplace_back(0); + q_m().emplace_back(1); + q_c().emplace_back(0); + q_arith().emplace_back(0); selectors.pad_additional(); check_selector_length_consistency(); break; @@ -1283,13 +1283,13 @@ void UltraCircuitBuilder_::apply_aux_selectors(const AUX_SELECT // Apply sorted memory read checks with the following additional check: // 1. Assert that if index field across two gates does not change, the value field does not change. // Used for ROM reads and RAM reads across write/read boundaries - q_1.emplace_back(1); - q_2.emplace_back(1); - q_3.emplace_back(0); - q_4.emplace_back(0); - q_m.emplace_back(0); - q_c.emplace_back(0); - q_arith.emplace_back(0); + q_1().emplace_back(1); + q_2().emplace_back(1); + q_3().emplace_back(0); + q_4().emplace_back(0); + q_m().emplace_back(0); + q_c().emplace_back(0); + q_arith().emplace_back(0); selectors.pad_additional(); check_selector_length_consistency(); break; @@ -1300,13 +1300,13 @@ void UltraCircuitBuilder_::apply_aux_selectors(const AUX_SELECT // 2. Validate record computation (r = read_write_flag + index * \eta + \timestamp * \eta^2 + value * \eta^3) // 3. If adjacent index values across 2 gates does not change, and the next gate's read_write_flag is set to // 'read', validate adjacent values do not change Used for ROM reads and RAM reads across read/write boundaries - q_1.emplace_back(0); - q_2.emplace_back(0); - q_3.emplace_back(0); - q_4.emplace_back(0); - q_m.emplace_back(0); - q_c.emplace_back(0); - q_arith.emplace_back(1); + q_1().emplace_back(0); + q_2().emplace_back(0); + q_3().emplace_back(0); + q_4().emplace_back(0); + q_m().emplace_back(0); + q_c().emplace_back(0); + q_arith().emplace_back(1); selectors.pad_additional(); check_selector_length_consistency(); break; @@ -1314,13 +1314,13 @@ void UltraCircuitBuilder_::apply_aux_selectors(const AUX_SELECT case AUX_SELECTORS::RAM_TIMESTAMP_CHECK: { // For two adjacent RAM entries that share the same index, validate the timestamp value is monotonically // increasing - q_1.emplace_back(1); - q_2.emplace_back(0); - q_3.emplace_back(0); - q_4.emplace_back(1); - q_m.emplace_back(0); - q_c.emplace_back(0); - q_arith.emplace_back(0); + q_1().emplace_back(1); + q_2().emplace_back(0); + q_3().emplace_back(0); + q_4().emplace_back(1); + q_m().emplace_back(0); + q_c().emplace_back(0); + q_arith().emplace_back(0); selectors.pad_additional(); check_selector_length_consistency(); break; @@ -1329,13 +1329,13 @@ void UltraCircuitBuilder_::apply_aux_selectors(const AUX_SELECT // Memory read gate for reading memory cells. // Validates record witness computation (r = read_write_flag + index * \eta + timestamp * \eta^2 + value * // \eta^3) - q_1.emplace_back(1); - q_2.emplace_back(0); - q_3.emplace_back(0); - q_4.emplace_back(0); - q_m.emplace_back(1); // validate record witness is correctly computed - q_c.emplace_back(0); // read/write flag stored in q_c - q_arith.emplace_back(0); + q_1().emplace_back(1); + q_2().emplace_back(0); + q_3().emplace_back(0); + q_4().emplace_back(0); + q_m().emplace_back(1); // validate record witness is correctly computed + q_c().emplace_back(0); // read/write flag stored in q_c + q_arith().emplace_back(0); selectors.pad_additional(); check_selector_length_consistency(); break; @@ -1344,13 +1344,13 @@ void UltraCircuitBuilder_::apply_aux_selectors(const AUX_SELECT // Memory read gate for reading memory cells. // Validates record witness computation (r = read_write_flag + index * \eta + timestamp * \eta^2 + value * // \eta^3) - q_1.emplace_back(1); - q_2.emplace_back(0); - q_3.emplace_back(0); - q_4.emplace_back(0); - q_m.emplace_back(1); // validate record witness is correctly computed - q_c.emplace_back(0); // read/write flag stored in q_c - q_arith.emplace_back(0); + q_1().emplace_back(1); + q_2().emplace_back(0); + q_3().emplace_back(0); + q_4().emplace_back(0); + q_m().emplace_back(1); // validate record witness is correctly computed + q_c().emplace_back(0); // read/write flag stored in q_c + q_arith().emplace_back(0); selectors.pad_additional(); check_selector_length_consistency(); break; @@ -1359,25 +1359,25 @@ void UltraCircuitBuilder_::apply_aux_selectors(const AUX_SELECT // Memory read gate for writing memory cells. // Validates record witness computation (r = read_write_flag + index * \eta + timestamp * \eta^2 + value * // \eta^3) - q_1.emplace_back(1); - q_2.emplace_back(0); - q_3.emplace_back(0); - q_4.emplace_back(0); - q_m.emplace_back(1); // validate record witness is correctly computed - q_c.emplace_back(1); // read/write flag stored in q_c - q_arith.emplace_back(0); + q_1().emplace_back(1); + q_2().emplace_back(0); + q_3().emplace_back(0); + q_4().emplace_back(0); + q_m().emplace_back(1); // validate record witness is correctly computed + q_c().emplace_back(1); // read/write flag stored in q_c + q_arith().emplace_back(0); selectors.pad_additional(); check_selector_length_consistency(); break; } default: { - q_1.emplace_back(0); - q_2.emplace_back(0); - q_3.emplace_back(0); - q_4.emplace_back(0); - q_m.emplace_back(0); - q_c.emplace_back(0); - q_arith.emplace_back(0); + q_1().emplace_back(0); + q_2().emplace_back(0); + q_3().emplace_back(0); + q_4().emplace_back(0); + q_m().emplace_back(0); + q_c().emplace_back(0); + q_arith().emplace_back(0); selectors.pad_additional(); check_selector_length_consistency(); break; @@ -1445,20 +1445,20 @@ void UltraCircuitBuilder_::range_constrain_two_limbs(const uint const std::array lo_sublimbs = get_sublimbs(lo_idx, lo_masks); const std::array hi_sublimbs = get_sublimbs(hi_idx, hi_masks); - w_l.emplace_back(lo_sublimbs[0]); - w_r.emplace_back(lo_sublimbs[1]); - w_o.emplace_back(lo_sublimbs[2]); - w_4.emplace_back(lo_idx); + w_l().emplace_back(lo_sublimbs[0]); + w_r().emplace_back(lo_sublimbs[1]); + w_o().emplace_back(lo_sublimbs[2]); + w_4().emplace_back(lo_idx); - w_l.emplace_back(lo_sublimbs[3]); - w_r.emplace_back(lo_sublimbs[4]); - w_o.emplace_back(hi_sublimbs[0]); - w_4.emplace_back(hi_sublimbs[1]); + w_l().emplace_back(lo_sublimbs[3]); + w_r().emplace_back(lo_sublimbs[4]); + w_o().emplace_back(hi_sublimbs[0]); + w_4().emplace_back(hi_sublimbs[1]); - w_l.emplace_back(hi_sublimbs[2]); - w_r.emplace_back(hi_sublimbs[3]); - w_o.emplace_back(hi_sublimbs[4]); - w_4.emplace_back(hi_idx); + w_l().emplace_back(hi_sublimbs[2]); + w_r().emplace_back(hi_sublimbs[3]); + w_o().emplace_back(hi_sublimbs[4]); + w_4().emplace_back(hi_idx); apply_aux_selectors(AUX_SELECTORS::LIMB_ACCUMULATE_1); apply_aux_selectors(AUX_SELECTORS::LIMB_ACCUMULATE_2); @@ -1618,28 +1618,28 @@ std::array UltraCircuitBuilder_::evaluate_non_nati 0 }, true); - w_l.emplace_back(input.a[1]); - w_r.emplace_back(input.b[1]); - w_o.emplace_back(input.r[0]); - w_4.emplace_back(lo_0_idx); + w_l().emplace_back(input.a[1]); + w_r().emplace_back(input.b[1]); + w_o().emplace_back(input.r[0]); + w_4().emplace_back(lo_0_idx); apply_aux_selectors(AUX_SELECTORS::NON_NATIVE_FIELD_1); ++this->num_gates; - w_l.emplace_back(input.a[0]); - w_r.emplace_back(input.b[0]); - w_o.emplace_back(input.a[3]); - w_4.emplace_back(input.b[3]); + w_l().emplace_back(input.a[0]); + w_r().emplace_back(input.b[0]); + w_o().emplace_back(input.a[3]); + w_4().emplace_back(input.b[3]); apply_aux_selectors(AUX_SELECTORS::NON_NATIVE_FIELD_2); ++this->num_gates; - w_l.emplace_back(input.a[2]); - w_r.emplace_back(input.b[2]); - w_o.emplace_back(input.r[3]); - w_4.emplace_back(hi_0_idx); + w_l().emplace_back(input.a[2]); + w_r().emplace_back(input.b[2]); + w_o().emplace_back(input.r[3]); + w_4().emplace_back(hi_0_idx); apply_aux_selectors(AUX_SELECTORS::NON_NATIVE_FIELD_3); ++this->num_gates; - w_l.emplace_back(input.a[1]); - w_r.emplace_back(input.b[1]); - w_o.emplace_back(input.r[2]); - w_4.emplace_back(hi_1_idx); + w_l().emplace_back(input.a[1]); + w_r().emplace_back(input.b[1]); + w_o().emplace_back(input.r[2]); + w_4().emplace_back(hi_1_idx); apply_aux_selectors(AUX_SELECTORS::NONE); ++this->num_gates; @@ -1703,28 +1703,28 @@ void UltraCircuitBuilder_::process_non_native_field_multiplicat // iterate over the cached items and create constraints for (const auto& input : cached_partial_non_native_field_multiplications) { - w_l.emplace_back(input.a[1]); - w_r.emplace_back(input.b[1]); - w_o.emplace_back(this->zero_idx); - w_4.emplace_back(input.lo_0); + w_l().emplace_back(input.a[1]); + w_r().emplace_back(input.b[1]); + w_o().emplace_back(this->zero_idx); + w_4().emplace_back(input.lo_0); apply_aux_selectors(AUX_SELECTORS::NON_NATIVE_FIELD_1); ++this->num_gates; - w_l.emplace_back(input.a[0]); - w_r.emplace_back(input.b[0]); - w_o.emplace_back(input.a[3]); - w_4.emplace_back(input.b[3]); + w_l().emplace_back(input.a[0]); + w_r().emplace_back(input.b[0]); + w_o().emplace_back(input.a[3]); + w_4().emplace_back(input.b[3]); apply_aux_selectors(AUX_SELECTORS::NON_NATIVE_FIELD_2); ++this->num_gates; - w_l.emplace_back(input.a[2]); - w_r.emplace_back(input.b[2]); - w_o.emplace_back(this->zero_idx); - w_4.emplace_back(input.hi_0); + w_l().emplace_back(input.a[2]); + w_r().emplace_back(input.b[2]); + w_o().emplace_back(this->zero_idx); + w_4().emplace_back(input.hi_0); apply_aux_selectors(AUX_SELECTORS::NON_NATIVE_FIELD_3); ++this->num_gates; - w_l.emplace_back(input.a[1]); - w_r.emplace_back(input.b[1]); - w_o.emplace_back(this->zero_idx); - w_4.emplace_back(input.hi_1); + w_l().emplace_back(input.a[1]); + w_r().emplace_back(input.b[1]); + w_o().emplace_back(this->zero_idx); + w_4().emplace_back(input.hi_1); apply_aux_selectors(AUX_SELECTORS::NONE); ++this->num_gates; } @@ -1845,61 +1845,61 @@ std::array UltraCircuitBuilder_::evaluate_non_nati * By setting `q_arith` to `3`, we can validate `x_p + y_p + q_m = z_p` **/ // GATE 1 - w_l.emplace_back(y_p); - w_r.emplace_back(x_0); - w_o.emplace_back(y_0); - w_4.emplace_back(x_p); - w_l.emplace_back(z_p); - w_r.emplace_back(x_1); - w_o.emplace_back(y_1); // | 1 | 2 | 3 | 4 | - w_4.emplace_back(z_0); // |-----|-----|-----|-----| - w_l.emplace_back(x_2); // | y.p | x.0 | y.0 | z.p | (b.p + b.p - c.p = 0) AND (a.0 + b.0 - c.0 = 0) - w_r.emplace_back(y_2); // | x.p | x.1 | y.1 | z.0 | (a.1 + b.1 - c.1 = 0) - w_o.emplace_back(z_2); // | x.2 | y.2 | z.2 | z.1 | (a.2 + b.2 - c.2 = 0) - w_4.emplace_back(z_1); // | x.3 | y.3 | z.3 | --- | (a.3 + b.3 - c.3 = 0) - w_l.emplace_back(x_3); - w_r.emplace_back(y_3); - w_o.emplace_back(z_3); - w_4.emplace_back(this->zero_idx); - - q_m.emplace_back(addconstp); - q_1.emplace_back(0); - q_2.emplace_back(-x_mulconst0 * - 2); // scale constants by 2. If q_arith = 3 then w_4_omega value (z0) gets scaled by 2x - q_3.emplace_back(-y_mulconst0 * 2); // z_0 - (x_0 * -xmulconst0) - (y_0 * ymulconst0) = 0 => z_0 = x_0 + y_0 - q_4.emplace_back(0); - q_c.emplace_back(-addconst0 * 2); - q_arith.emplace_back(3); - - q_m.emplace_back(0); - q_1.emplace_back(0); - q_2.emplace_back(-x_mulconst1); - q_3.emplace_back(-y_mulconst1); - q_4.emplace_back(0); - q_c.emplace_back(-addconst1); - q_arith.emplace_back(2); - - q_m.emplace_back(0); - q_1.emplace_back(-x_mulconst2); - q_2.emplace_back(-y_mulconst2); - q_3.emplace_back(1); - q_4.emplace_back(0); - q_c.emplace_back(-addconst2); - q_arith.emplace_back(1); - - q_m.emplace_back(0); - q_1.emplace_back(-x_mulconst3); - q_2.emplace_back(-y_mulconst3); - q_3.emplace_back(1); - q_4.emplace_back(0); - q_c.emplace_back(-addconst3); - q_arith.emplace_back(1); + w_l().emplace_back(y_p); + w_r().emplace_back(x_0); + w_o().emplace_back(y_0); + w_4().emplace_back(x_p); + w_l().emplace_back(z_p); + w_r().emplace_back(x_1); + w_o().emplace_back(y_1); // | 1 | 2 | 3 | 4 | + w_4().emplace_back(z_0); // |-----|-----|-----|-----| + w_l().emplace_back(x_2); // | y.p | x.0 | y.0 | z.p | (b.p + b.p - c.p = 0) AND (a.0 + b.0 - c.0 = 0) + w_r().emplace_back(y_2); // | x.p | x.1 | y.1 | z.0 | (a.1 + b.1 - c.1 = 0) + w_o().emplace_back(z_2); // | x.2 | y.2 | z.2 | z.1 | (a.2 + b.2 - c.2 = 0) + w_4().emplace_back(z_1); // | x.3 | y.3 | z.3 | --- | (a.3 + b.3 - c.3 = 0) + w_l().emplace_back(x_3); + w_r().emplace_back(y_3); + w_o().emplace_back(z_3); + w_4().emplace_back(this->zero_idx); + + q_m().emplace_back(addconstp); + q_1().emplace_back(0); + q_2().emplace_back(-x_mulconst0 * + 2); // scale constants by 2. If q_arith = 3 then w_4_omega value (z0) gets scaled by 2x + q_3().emplace_back(-y_mulconst0 * 2); // z_0 - (x_0 * -xmulconst0) - (y_0 * ymulconst0) = 0 => z_0 = x_0 + y_0 + q_4().emplace_back(0); + q_c().emplace_back(-addconst0 * 2); + q_arith().emplace_back(3); + + q_m().emplace_back(0); + q_1().emplace_back(0); + q_2().emplace_back(-x_mulconst1); + q_3().emplace_back(-y_mulconst1); + q_4().emplace_back(0); + q_c().emplace_back(-addconst1); + q_arith().emplace_back(2); + + q_m().emplace_back(0); + q_1().emplace_back(-x_mulconst2); + q_2().emplace_back(-y_mulconst2); + q_3().emplace_back(1); + q_4().emplace_back(0); + q_c().emplace_back(-addconst2); + q_arith().emplace_back(1); + + q_m().emplace_back(0); + q_1().emplace_back(-x_mulconst3); + q_2().emplace_back(-y_mulconst3); + q_3().emplace_back(1); + q_4().emplace_back(0); + q_c().emplace_back(-addconst3); + q_arith().emplace_back(1); for (size_t i = 0; i < 4; ++i) { - q_sort.emplace_back(0); - q_lookup_type.emplace_back(0); - q_elliptic.emplace_back(0); - q_aux.emplace_back(0); + q_sort().emplace_back(0); + q_lookup_type().emplace_back(0); + q_elliptic().emplace_back(0); + q_aux().emplace_back(0); selectors.pad_additional(); } check_selector_length_consistency(); @@ -1969,60 +1969,60 @@ std::array UltraCircuitBuilder_::evaluate_non_nati * **/ // GATE 1 - w_l.emplace_back(y_p); - w_r.emplace_back(x_0); - w_o.emplace_back(y_0); - w_4.emplace_back(z_p); - w_l.emplace_back(x_p); - w_r.emplace_back(x_1); - w_o.emplace_back(y_1); // | 1 | 2 | 3 | 4 | - w_4.emplace_back(z_0); // |-----|-----|-----|-----| - w_l.emplace_back(x_2); // | y.p | x.0 | y.0 | z.p | (b.p + c.p - a.p = 0) AND (a.0 - b.0 - c.0 = 0) - w_r.emplace_back(y_2); // | x.p | x.1 | y.1 | z.0 | (a.1 - b.1 - c.1 = 0) - w_o.emplace_back(z_2); // | x.2 | y.2 | z.2 | z.1 | (a.2 - b.2 - c.2 = 0) - w_4.emplace_back(z_1); // | x.3 | y.3 | z.3 | --- | (a.3 - b.3 - c.3 = 0) - w_l.emplace_back(x_3); - w_r.emplace_back(y_3); - w_o.emplace_back(z_3); - w_4.emplace_back(this->zero_idx); - - q_m.emplace_back(-addconstp); - q_1.emplace_back(0); - q_2.emplace_back(-x_mulconst0 * 2); - q_3.emplace_back(y_mulconst0 * 2); // z_0 + (x_0 * -xmulconst0) + (y_0 * ymulconst0) = 0 => z_0 = x_0 - y_0 - q_4.emplace_back(0); - q_c.emplace_back(-addconst0 * 2); - q_arith.emplace_back(3); - - q_m.emplace_back(0); - q_1.emplace_back(0); - q_2.emplace_back(-x_mulconst1); - q_3.emplace_back(y_mulconst1); - q_4.emplace_back(0); - q_c.emplace_back(-addconst1); - q_arith.emplace_back(2); - - q_m.emplace_back(0); - q_1.emplace_back(-x_mulconst2); - q_2.emplace_back(y_mulconst2); - q_3.emplace_back(1); - q_4.emplace_back(0); - q_c.emplace_back(-addconst2); - q_arith.emplace_back(1); - - q_m.emplace_back(0); - q_1.emplace_back(-x_mulconst3); - q_2.emplace_back(y_mulconst3); - q_3.emplace_back(1); - q_4.emplace_back(0); - q_c.emplace_back(-addconst3); - q_arith.emplace_back(1); + w_l().emplace_back(y_p); + w_r().emplace_back(x_0); + w_o().emplace_back(y_0); + w_4().emplace_back(z_p); + w_l().emplace_back(x_p); + w_r().emplace_back(x_1); + w_o().emplace_back(y_1); // | 1 | 2 | 3 | 4 | + w_4().emplace_back(z_0); // |-----|-----|-----|-----| + w_l().emplace_back(x_2); // | y.p | x.0 | y.0 | z.p | (b.p + c.p - a.p = 0) AND (a.0 - b.0 - c.0 = 0) + w_r().emplace_back(y_2); // | x.p | x.1 | y.1 | z.0 | (a.1 - b.1 - c.1 = 0) + w_o().emplace_back(z_2); // | x.2 | y.2 | z.2 | z.1 | (a.2 - b.2 - c.2 = 0) + w_4().emplace_back(z_1); // | x.3 | y.3 | z.3 | --- | (a.3 - b.3 - c.3 = 0) + w_l().emplace_back(x_3); + w_r().emplace_back(y_3); + w_o().emplace_back(z_3); + w_4().emplace_back(this->zero_idx); + + q_m().emplace_back(-addconstp); + q_1().emplace_back(0); + q_2().emplace_back(-x_mulconst0 * 2); + q_3().emplace_back(y_mulconst0 * 2); // z_0 + (x_0 * -xmulconst0) + (y_0 * ymulconst0) = 0 => z_0 = x_0 - y_0 + q_4().emplace_back(0); + q_c().emplace_back(-addconst0 * 2); + q_arith().emplace_back(3); + + q_m().emplace_back(0); + q_1().emplace_back(0); + q_2().emplace_back(-x_mulconst1); + q_3().emplace_back(y_mulconst1); + q_4().emplace_back(0); + q_c().emplace_back(-addconst1); + q_arith().emplace_back(2); + + q_m().emplace_back(0); + q_1().emplace_back(-x_mulconst2); + q_2().emplace_back(y_mulconst2); + q_3().emplace_back(1); + q_4().emplace_back(0); + q_c().emplace_back(-addconst2); + q_arith().emplace_back(1); + + q_m().emplace_back(0); + q_1().emplace_back(-x_mulconst3); + q_2().emplace_back(y_mulconst3); + q_3().emplace_back(1); + q_4().emplace_back(0); + q_c().emplace_back(-addconst3); + q_arith().emplace_back(1); for (size_t i = 0; i < 4; ++i) { - q_sort.emplace_back(0); - q_lookup_type.emplace_back(0); - q_elliptic.emplace_back(0); - q_aux.emplace_back(0); + q_sort().emplace_back(0); + q_lookup_type().emplace_back(0); + q_elliptic().emplace_back(0); + q_aux().emplace_back(0); selectors.pad_additional(); } check_selector_length_consistency(); @@ -2045,10 +2045,10 @@ template void UltraCircuitBuilder_:: // Record wire value can't yet be computed record.record_witness = this->add_variable(0); apply_aux_selectors(AUX_SELECTORS::ROM_READ); - w_l.emplace_back(record.index_witness); - w_r.emplace_back(record.value_column1_witness); - w_o.emplace_back(record.value_column2_witness); - w_4.emplace_back(record.record_witness); + w_l().emplace_back(record.index_witness); + w_r().emplace_back(record.value_column1_witness); + w_o().emplace_back(record.value_column2_witness); + w_4().emplace_back(record.record_witness); record.gate_index = this->num_gates; ++this->num_gates; } @@ -2065,10 +2065,10 @@ void UltraCircuitBuilder_::create_sorted_ROM_gate(RomRecord& re { record.record_witness = this->add_variable(0); apply_aux_selectors(AUX_SELECTORS::ROM_CONSISTENCY_CHECK); - w_l.emplace_back(record.index_witness); - w_r.emplace_back(record.value_column1_witness); - w_o.emplace_back(record.value_column2_witness); - w_4.emplace_back(record.record_witness); + w_l().emplace_back(record.index_witness); + w_r().emplace_back(record.value_column1_witness); + w_o().emplace_back(record.value_column2_witness); + w_4().emplace_back(record.record_witness); record.gate_index = this->num_gates; ++this->num_gates; } @@ -2111,10 +2111,10 @@ template void UltraCircuitBuilder_:: record.record_witness = this->add_variable(0); apply_aux_selectors(record.access_type == RamRecord::AccessType::READ ? AUX_SELECTORS::RAM_READ : AUX_SELECTORS::RAM_WRITE); - w_l.emplace_back(record.index_witness); - w_r.emplace_back(record.timestamp_witness); - w_o.emplace_back(record.value_witness); - w_4.emplace_back(record.record_witness); + w_l().emplace_back(record.index_witness); + w_r().emplace_back(record.timestamp_witness); + w_o().emplace_back(record.value_witness); + w_4().emplace_back(record.record_witness); record.gate_index = this->num_gates; ++this->num_gates; } @@ -2132,10 +2132,10 @@ void UltraCircuitBuilder_::create_sorted_RAM_gate(RamRecord& re { record.record_witness = this->add_variable(0); apply_aux_selectors(AUX_SELECTORS::RAM_CONSISTENCY_CHECK); - w_l.emplace_back(record.index_witness); - w_r.emplace_back(record.timestamp_witness); - w_o.emplace_back(record.value_witness); - w_4.emplace_back(record.record_witness); + w_l().emplace_back(record.index_witness); + w_r().emplace_back(record.timestamp_witness); + w_o().emplace_back(record.value_witness); + w_4().emplace_back(record.record_witness); record.gate_index = this->num_gates; ++this->num_gates; } @@ -2627,10 +2627,10 @@ template void UltraCircuitBuilder_:: uint32_t timestamp_delta_witness = this->add_variable(timestamp_delta); apply_aux_selectors(AUX_SELECTORS::RAM_TIMESTAMP_CHECK); - w_l.emplace_back(current.index_witness); - w_r.emplace_back(current.timestamp_witness); - w_o.emplace_back(timestamp_delta_witness); - w_4.emplace_back(this->zero_idx); + w_l().emplace_back(current.index_witness); + w_r().emplace_back(current.timestamp_witness); + w_o().emplace_back(timestamp_delta_witness); + w_4().emplace_back(this->zero_idx); ++this->num_gates; // store timestamp offsets for later. Need to apply range checks to them, but calling @@ -3329,26 +3329,26 @@ template bool UltraCircuitBuilder_:: FF w_4_value; FF w_4_index; // Get the values of selectors and wires and update tag products along the way - q_arith_value = q_arith[i]; - q_aux_value = q_aux[i]; - q_elliptic_value = q_elliptic[i]; - q_sort_value = q_sort[i]; - q_lookup_type_value = q_lookup_type[i]; - q_1_value = q_1[i]; - q_2_value = q_2[i]; - q_3_value = q_3[i]; - q_4_value = q_4[i]; - q_m_value = q_m[i]; - q_c_value = q_c[i]; - w_1_value = this->get_variable(w_l[i]); - update_tag_check_information(w_l[i], w_1_value); - w_2_value = this->get_variable(w_r[i]); - update_tag_check_information(w_r[i], w_2_value); - w_3_value = this->get_variable(w_o[i]); - update_tag_check_information(w_o[i], w_3_value); - w_4_value = this->get_variable(w_4[i]); + q_arith_value = q_arith()[i]; + q_aux_value = q_aux()[i]; + q_elliptic_value = q_elliptic()[i]; + q_sort_value = q_sort()[i]; + q_lookup_type_value = q_lookup_type()[i]; + q_1_value = q_1()[i]; + q_2_value = q_2()[i]; + q_3_value = q_3()[i]; + q_4_value = q_4()[i]; + q_m_value = q_m()[i]; + q_c_value = q_c()[i]; + w_1_value = this->get_variable(w_l()[i]); + update_tag_check_information(w_l()[i], w_1_value); + w_2_value = this->get_variable(w_r()[i]); + update_tag_check_information(w_r()[i], w_2_value); + w_3_value = this->get_variable(w_o()[i]); + update_tag_check_information(w_o()[i], w_3_value); + w_4_value = this->get_variable(w_4()[i]); // We need to wait before updating tag product for w_4 - w_4_index = w_4[i]; + w_4_index = w_4()[i]; // If we are touching a gate with memory access, we need to update the value of the 4th witness if (memory_read_record_gates.contains(i)) { @@ -3364,10 +3364,10 @@ template bool UltraCircuitBuilder_:: FF w_3_shifted_value; FF w_4_shifted_value; if (i < (this->num_gates - 1)) { - w_1_shifted_value = this->get_variable(w_l[i + 1]); - w_2_shifted_value = this->get_variable(w_r[i + 1]); - w_3_shifted_value = this->get_variable(w_o[i + 1]); - w_4_shifted_value = this->get_variable(w_4[i + 1]); + w_1_shifted_value = this->get_variable(w_l()[i + 1]); + w_2_shifted_value = this->get_variable(w_r()[i + 1]); + w_3_shifted_value = this->get_variable(w_o()[i + 1]); + w_4_shifted_value = this->get_variable(w_4()[i + 1]); } else { w_1_shifted_value = FF::zero(); w_2_shifted_value = FF::zero(); diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/ultra_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/ultra_circuit_builder.hpp index 9767781e72d..14c7f9cc2b9 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/ultra_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/ultra_circuit_builder.hpp @@ -344,21 +344,21 @@ class UltraCircuitBuilder_ : public CircuitBuilderBasecircuit_finalized = circuit_finalized; builder->num_gates = num_gates; builder->cached_partial_non_native_field_multiplications = cached_partial_non_native_field_multiplications; - builder->w_l.resize(num_gates); - builder->w_r.resize(num_gates); - builder->w_o.resize(num_gates); - builder->w_4.resize(num_gates); - builder->q_m.resize(num_gates); - builder->q_c.resize(num_gates); - builder->q_1.resize(num_gates); - builder->q_2.resize(num_gates); - builder->q_3.resize(num_gates); - builder->q_4.resize(num_gates); - builder->q_arith.resize(num_gates); - builder->q_sort.resize(num_gates); - builder->q_elliptic.resize(num_gates); - builder->q_aux.resize(num_gates); - builder->q_lookup_type.resize(num_gates); + builder->w_l().resize(num_gates); + builder->w_r().resize(num_gates); + builder->w_o().resize(num_gates); + builder->w_4().resize(num_gates); + builder->q_m().resize(num_gates); + builder->q_c().resize(num_gates); + builder->q_1().resize(num_gates); + builder->q_2().resize(num_gates); + builder->q_3().resize(num_gates); + builder->q_4().resize(num_gates); + builder->q_arith().resize(num_gates); + builder->q_sort().resize(num_gates); + builder->q_elliptic().resize(num_gates); + builder->q_aux().resize(num_gates); + builder->q_lookup_type().resize(num_gates); } /** * @brief Checks that the circuit state is the same as the stored circuit's one @@ -489,49 +489,49 @@ class UltraCircuitBuilder_ : public CircuitBuilderBase>; using SelectorVector = std::vector>; - WireVector& w_l = std::get<0>(wires); - WireVector& w_r = std::get<1>(wires); - WireVector& w_o = std::get<2>(wires); - WireVector& w_4 = std::get<3>(wires); - - SelectorVector& q_m = selectors.q_m(); - SelectorVector& q_c = selectors.q_c(); - SelectorVector& q_1 = selectors.q_1(); - SelectorVector& q_2 = selectors.q_2(); - SelectorVector& q_3 = selectors.q_3(); - SelectorVector& q_4 = selectors.q_4(); - SelectorVector& q_arith = selectors.q_arith(); - SelectorVector& q_sort = selectors.q_sort(); - SelectorVector& q_elliptic = selectors.q_elliptic(); - SelectorVector& q_aux = selectors.q_aux(); - SelectorVector& q_lookup_type = selectors.q_lookup_type(); + WireVector& w_l() { return std::get<0>(wires); }; + WireVector& w_r() { return std::get<1>(wires); }; + WireVector& w_o() { return std::get<2>(wires); }; + WireVector& w_4() { return std::get<3>(wires); }; + + const WireVector& w_l() const { return std::get<0>(wires); }; + const WireVector& w_r() const { return std::get<1>(wires); }; + const WireVector& w_o() const { return std::get<2>(wires); }; + const WireVector& w_4() const { return std::get<3>(wires); }; + + SelectorVector& q_m() { return selectors.q_m(); }; + SelectorVector& q_c() { return selectors.q_c(); }; + SelectorVector& q_1() { return selectors.q_1(); }; + SelectorVector& q_2() { return selectors.q_2(); }; + SelectorVector& q_3() { return selectors.q_3(); }; + SelectorVector& q_4() { return selectors.q_4(); }; + SelectorVector& q_arith() { return selectors.q_arith(); }; + SelectorVector& q_sort() { return selectors.q_sort(); }; + SelectorVector& q_elliptic() { return selectors.q_elliptic(); }; + SelectorVector& q_aux() { return selectors.q_aux(); }; + SelectorVector& q_lookup_type() { return selectors.q_lookup_type(); }; + + const SelectorVector& q_c() const { return selectors.q_c(); }; + const SelectorVector& q_1() const { return selectors.q_1(); }; + const SelectorVector& q_2() const { return selectors.q_2(); }; + const SelectorVector& q_3() const { return selectors.q_3(); }; + const SelectorVector& q_4() const { return selectors.q_4(); }; + const SelectorVector& q_arith() const { return selectors.q_arith(); }; + const SelectorVector& q_sort() const { return selectors.q_sort(); }; + const SelectorVector& q_elliptic() const { return selectors.q_elliptic(); }; + const SelectorVector& q_aux() const { return selectors.q_aux(); }; + const SelectorVector& q_lookup_type() const { return selectors.q_lookup_type(); }; + const SelectorVector& q_m() const { return selectors.q_m(); }; // These are variables that we have used a gate on, to enforce that they are // equal to a defined value. @@ -632,14 +649,14 @@ class UltraCircuitBuilder_ : public CircuitBuilderBase(size_hint) { selectors.reserve(size_hint); - w_l.reserve(size_hint); - w_r.reserve(size_hint); - w_o.reserve(size_hint); - w_4.reserve(size_hint); + w_l().reserve(size_hint); + w_r().reserve(size_hint); + w_o().reserve(size_hint); + w_4().reserve(size_hint); this->zero_idx = put_constant_variable(FF::zero()); this->tau.insert({ DUMMY_TAG, DUMMY_TAG }); // TODO(luke): explain this }; - UltraCircuitBuilder_(const UltraCircuitBuilder_& other) = delete; + UltraCircuitBuilder_(const UltraCircuitBuilder_& other) = default; UltraCircuitBuilder_(UltraCircuitBuilder_&& other) : CircuitBuilderBase(std::move(other)) { @@ -657,7 +674,7 @@ class UltraCircuitBuilder_ : public CircuitBuilderBase::operator=(std::move(other)); diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/ultra_circuit_builder.test.cpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/ultra_circuit_builder.test.cpp index 608727c812a..6af8c8ad259 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/ultra_circuit_builder.test.cpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/ultra_circuit_builder.test.cpp @@ -11,6 +11,34 @@ namespace proof_system { using plookup::ColumnIdx; using plookup::MultiTableId; +TEST(ultra_circuit_constructor, copy_constructor) +{ + UltraCircuitBuilder circuit_constructor = UltraCircuitBuilder(); + + for (size_t i = 0; i < 16; ++i) { + for (size_t j = 0; j < 16; ++j) { + uint64_t left = static_cast(j); + uint64_t right = static_cast(i); + uint32_t left_idx = circuit_constructor.add_variable(fr(left)); + uint32_t right_idx = circuit_constructor.add_variable(fr(right)); + uint32_t result_idx = circuit_constructor.add_variable(fr(left ^ right)); + + uint32_t add_idx = + circuit_constructor.add_variable(fr(left) + fr(right) + circuit_constructor.get_variable(result_idx)); + circuit_constructor.create_big_add_gate( + { left_idx, right_idx, result_idx, add_idx, fr(1), fr(1), fr(1), fr(-1), fr(0) }); + } + } + + bool result = circuit_constructor.check_circuit(); + EXPECT_EQ(result, true); + + UltraCircuitBuilder duplicate_circuit_constructor{ circuit_constructor }; + + EXPECT_EQ(duplicate_circuit_constructor.get_num_gates(), circuit_constructor.get_num_gates()); + EXPECT_TRUE(duplicate_circuit_constructor.check_circuit()); +} + TEST(ultra_circuit_constructor, create_gates_from_plookup_accumulators) { @@ -742,6 +770,12 @@ TEST(ultra_circuit_constructor, ram) EXPECT_EQ(result, true); EXPECT_TRUE(saved_state.is_same_state(circuit_constructor)); + + // Test the builder copy constructor for a circuit with RAM gates + UltraCircuitBuilder duplicate_circuit_constructor{ circuit_constructor }; + + EXPECT_EQ(duplicate_circuit_constructor.get_num_gates(), circuit_constructor.get_num_gates()); + EXPECT_TRUE(duplicate_circuit_constructor.check_circuit()); } TEST(ultra_circuit_constructor, range_checks_on_duplicates) diff --git a/barretenberg/cpp/src/barretenberg/proof_system/composer/composer_lib.test.cpp b/barretenberg/cpp/src/barretenberg/proof_system/composer/composer_lib.test.cpp index 8546d793f28..0b5788b8ff7 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/composer/composer_lib.test.cpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/composer/composer_lib.test.cpp @@ -22,11 +22,11 @@ class ComposerLibTests : public ::testing::Test { TEST_F(ComposerLibTests, ConstructSelectors) { - circuit_constructor.q_m = { 1, 2, 3, 4 }; - circuit_constructor.q_1 = { 5, 6, 7, 8 }; - circuit_constructor.q_2 = { 9, 10, 11, 12 }; - circuit_constructor.q_3 = { 13, 14, 15, 16 }; - circuit_constructor.q_c = { 17, 18, 19, 20 }; + circuit_constructor.q_m() = { 1, 2, 3, 4 }; + circuit_constructor.q_1() = { 5, 6, 7, 8 }; + circuit_constructor.q_2() = { 9, 10, 11, 12 }; + circuit_constructor.q_3() = { 13, 14, 15, 16 }; + circuit_constructor.q_c() = { 17, 18, 19, 20 }; construct_selector_polynomials(circuit_constructor, &proving_key); size_t offset = 0; diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/field/field.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/field/field.test.cpp index 9ed50192778..f7670c9c7da 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/field/field.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/field/field.test.cpp @@ -183,7 +183,7 @@ template class stdlib_field : public testing::Test { auto gates_before = builder.get_num_gates(); uint64_t expected = fidget(builder); auto gates_after = builder.get_num_gates(); - EXPECT_EQ(builder.get_variable(builder.w_o[gates_after - 1]), fr(expected)); + EXPECT_EQ(builder.get_variable(builder.w_o()[gates_after - 1]), fr(expected)); info("Number of gates added", gates_after - gates_before); bool result = builder.check_circuit(); EXPECT_EQ(result, true); @@ -257,7 +257,7 @@ template class stdlib_field : public testing::Test { auto gates_before = builder.get_num_gates(); fibbonaci(builder); auto gates_after = builder.get_num_gates(); - EXPECT_EQ(builder.get_variable(builder.w_l[builder.get_num_gates() - 1]), fr(4181)); + EXPECT_EQ(builder.get_variable(builder.w_l()[builder.get_num_gates() - 1]), fr(4181)); EXPECT_EQ(gates_after - gates_before, 18UL); bool result = builder.check_circuit(); From 53eb54fb3416711dbc411e6037bc2da18d523cc3 Mon Sep 17 00:00:00 2001 From: Charlie Lye Date: Tue, 12 Dec 2023 21:56:58 +0000 Subject: [PATCH 26/35] fix: Make lsp work in docker, plus some other install tweaks. (#3661) * LSP couldn't work in docker due to `ClientProcessMonitor` thing which needs to be able to see the pid of vscode, in order to exit when vscode is not there. Not quite sure why it's needed as vscode launches the process, so the process terminates on vscode exit anyway. * Mount HOME at HOME rather than /root. * Fix conditional. * Disable annoying CLI hints on windows docker. * Wrap nargo launcher in `tini` as it doesn't handle signals as expected. * Allow for debug builds of noir via script using env var. --- aztec-up/bin/.aztec-run | 8 +++--- aztec-up/bin/aztec-install | 6 ++-- noir/Cargo.lock | 35 ++++++++++++++--------- noir/Dockerfile | 5 ++-- noir/scripts/bootstrap_native.sh | 6 +++- noir/tooling/nargo_cli/src/cli/lsp_cmd.rs | 5 ++-- 6 files changed, 41 insertions(+), 24 deletions(-) diff --git a/aztec-up/bin/.aztec-run b/aztec-up/bin/.aztec-run index a02a3bafbd9..2a6d50397b4 100755 --- a/aztec-up/bin/.aztec-run +++ b/aztec-up/bin/.aztec-run @@ -13,7 +13,7 @@ VERSION=${VERSION:-"latest"} DOCKER_HOST_BINDS="" # Volumes to pass to the container. -DOCKER_VOLUME="-v $HOME:/root" +DOCKER_VOLUME="-v $HOME:$HOME" # Colors. y="\033[33m" @@ -35,7 +35,7 @@ fi # Set up host.docker.internal alias on Linux, just like it is on mac. UNAME=$(uname -s) -if [ "$UNAME" == "Linux" ]; then +if [[ -z "${SKIP_NET:-}" && "$UNAME" == "Linux" ]]; then if docker info 2>/dev/null | grep -q rootless; then # We're in rootless docker. Probe for the host ip and use that. ip=$(hostname -I | head | tr -d ' ') @@ -58,7 +58,7 @@ done # If so, warn and exit. for i in "${!args[@]}"; do arg=${args[$i]} - if [[ -f "$arg" || -d "$arg" && $(realpath $arg) != ${HOME}* ]]; then + if [[ -f "$arg" || -d "$arg" ]] && [[ $(realpath $arg) != ${HOME}* ]]; then warn "Due to how we containerize our applications, paths outside of $HOME cannot be referenced." exit 1 fi @@ -77,7 +77,7 @@ DOCKER_VOLUME="$DOCKER_VOLUME -v cache:/cache" docker run \ -ti \ --rm \ - --workdir "${PWD/$HOME/\/root}" \ + --workdir "$PWD" \ $DOCKER_HOST_BINDS \ $DOCKER_ENV \ $DOCKER_VOLUME \ diff --git a/aztec-up/bin/aztec-install b/aztec-up/bin/aztec-install index 11eaada215d..e8d2b211e2b 100755 --- a/aztec-up/bin/aztec-install +++ b/aztec-up/bin/aztec-install @@ -33,7 +33,7 @@ function title() { if [ "$(uname -s)" == "Darwin" ]; then echo -e "${y}WARNING: For best performance we recommend adjusting your default docker settings:" echo -e " - Under general, enable VirtioFS." - echo -e " - Under resources, set CPUs to ~80-100% your maximum." + echo -e " - Under resources, set CPUs to ~80% your maximum." echo -e " - Under resources, set Memory to ~80% your maximum." echo -e "You may receive a warning about your home directory being mounted into a container." echo -e "This is requested so we can read and write project files, that is all." @@ -100,6 +100,8 @@ function pull_container { fi } +export DOCKER_CLI_HINTS=false + if [ -z "${SKIP_PULL:-}" ]; then info "Pulling aztec version $VERSION..." pull_container aztec-sandbox @@ -149,7 +151,7 @@ function update_path_env_var { echo if [[ $REPLY =~ ^[Yy]$ ]]; then # Add the target directory to the user's PATH in their profile. - echo "export PATH=\$PATH:$TARGET_DIR" >> "$SHELL_PROFILE" + echo "export PATH=\"\$PATH:$TARGET_DIR\"" >> "$SHELL_PROFILE" info "Done! Starting fresh shell..." $SHELL else diff --git a/noir/Cargo.lock b/noir/Cargo.lock index 43958d2f1cb..3bab28cd1c5 100644 --- a/noir/Cargo.lock +++ b/noir/Cargo.lock @@ -1979,7 +1979,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2", + "socket2 0.4.9", "tokio", "tower-service", "tracing", @@ -2227,9 +2227,9 @@ checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" [[package]] name = "libc" -version = "0.2.147" +version = "0.2.151" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" +checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" [[package]] name = "libm" @@ -2371,9 +2371,9 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.8" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" +checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" dependencies = [ "libc", "wasi", @@ -2867,9 +2867,9 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.10" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c40d25201921e5ff0c862a505c6557ea88568a4e3ace775ab55e93f2f4f9d57" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" [[package]] name = "pin-utils" @@ -3960,6 +3960,16 @@ dependencies = [ "winapi", ] +[[package]] +name = "socket2" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" +dependencies = [ + "libc", + "windows-sys 0.48.0", +] + [[package]] name = "spin" version = "0.5.2" @@ -4257,27 +4267,26 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.29.1" +version = "1.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da" +checksum = "841d45b238a16291a4e1584e61820b8ae57d696cc5015c459c229ccc6990cc1c" dependencies = [ - "autocfg", "backtrace", "bytes", "libc", "mio", "num_cpus", "pin-project-lite", - "socket2", + "socket2 0.5.5", "tokio-macros", "windows-sys 0.48.0", ] [[package]] name = "tokio-macros" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", diff --git a/noir/Dockerfile b/noir/Dockerfile index de63983db3e..7ba47b04e31 100644 --- a/noir/Dockerfile +++ b/noir/Dockerfile @@ -5,6 +5,7 @@ RUN ./scripts/bootstrap_native.sh # When running the container, mount the users home directory to /root FROM ubuntu:lunar +# Install Tini as nargo doesn't handle signals properly. +RUN apt-get update && apt-get install -y tini && rm -rf /var/lib/apt/lists/* && apt-get clean COPY --from=0 /usr/src/noir/target/release/nargo /usr/src/noir/target/release/nargo -WORKDIR /root -ENTRYPOINT ["/usr/src/noir/target/release/nargo"] \ No newline at end of file +ENTRYPOINT ["/usr/bin/tini", "--", "/usr/src/noir/target/release/nargo"] \ No newline at end of file diff --git a/noir/scripts/bootstrap_native.sh b/noir/scripts/bootstrap_native.sh index b5e004106ff..fb361c96f57 100755 --- a/noir/scripts/bootstrap_native.sh +++ b/noir/scripts/bootstrap_native.sh @@ -13,4 +13,8 @@ else fi # Build native. -cargo build --features="noirc_driver/aztec" --release +if [ -n "${DEBUG:-}" ]; then + cargo build --features="noirc_driver/aztec" +else + cargo build --features="noirc_driver/aztec" --release +fi diff --git a/noir/tooling/nargo_cli/src/cli/lsp_cmd.rs b/noir/tooling/nargo_cli/src/cli/lsp_cmd.rs index a41bb877991..e1f0a9dd8b9 100644 --- a/noir/tooling/nargo_cli/src/cli/lsp_cmd.rs +++ b/noir/tooling/nargo_cli/src/cli/lsp_cmd.rs @@ -1,5 +1,5 @@ use async_lsp::{ - client_monitor::ClientProcessMonitorLayer, concurrency::ConcurrencyLayer, + concurrency::ConcurrencyLayer, panic::CatchUnwindLayer, server::LifecycleLayer, tracing::TracingLayer, }; use clap::Args; @@ -39,10 +39,11 @@ pub(crate) fn run( .layer(LifecycleLayer::default()) .layer(CatchUnwindLayer::default()) .layer(ConcurrencyLayer::default()) - .layer(ClientProcessMonitorLayer::new(client)) .service(router) }); + eprintln!("LSP starting..."); + // Prefer truly asynchronous piped stdin/stdout without blocking tasks. #[cfg(unix)] let (stdin, stdout) = ( From 6877ca1c906743afbf488ac0f7e662bf4486f6a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Bene=C5=A1?= Date: Wed, 13 Dec 2023 08:33:40 +0100 Subject: [PATCH 27/35] feat: libraryfying historic access (#3658) --- yarn-project/aztec-nr/aztec/src/history.nr | 5 + .../aztec/src/history/note_inclusion.nr | 48 +++++ .../aztec/src/history/note_validity.nr | 19 ++ .../aztec/src/history/nullifier_inclusion.nr | 33 ++++ .../src/history/nullifier_non_inclusion.nr | 63 +++++++ .../src/history/public_value_inclusion.nr | 44 +++++ yarn-project/aztec-nr/aztec/src/lib.nr | 1 + yarn-project/aztec-nr/aztec/src/utils.nr | 12 ++ .../src/e2e_inclusion_proofs_contract.test.ts | 47 +++-- .../inclusion_proofs_contract/src/main.nr | 176 +++++------------- .../inclusion_proofs_contract/src/utils.nr | 11 -- 11 files changed, 306 insertions(+), 153 deletions(-) create mode 100644 yarn-project/aztec-nr/aztec/src/history.nr create mode 100644 yarn-project/aztec-nr/aztec/src/history/note_inclusion.nr create mode 100644 yarn-project/aztec-nr/aztec/src/history/note_validity.nr create mode 100644 yarn-project/aztec-nr/aztec/src/history/nullifier_inclusion.nr create mode 100644 yarn-project/aztec-nr/aztec/src/history/nullifier_non_inclusion.nr create mode 100644 yarn-project/aztec-nr/aztec/src/history/public_value_inclusion.nr delete mode 100644 yarn-project/noir-contracts/src/contracts/inclusion_proofs_contract/src/utils.nr diff --git a/yarn-project/aztec-nr/aztec/src/history.nr b/yarn-project/aztec-nr/aztec/src/history.nr new file mode 100644 index 00000000000..c36332d365a --- /dev/null +++ b/yarn-project/aztec-nr/aztec/src/history.nr @@ -0,0 +1,5 @@ +mod note_inclusion; +mod note_validity; +mod nullifier_inclusion; +mod nullifier_non_inclusion; +mod public_value_inclusion; \ No newline at end of file diff --git a/yarn-project/aztec-nr/aztec/src/history/note_inclusion.nr b/yarn-project/aztec-nr/aztec/src/history/note_inclusion.nr new file mode 100644 index 00000000000..df05ce24529 --- /dev/null +++ b/yarn-project/aztec-nr/aztec/src/history/note_inclusion.nr @@ -0,0 +1,48 @@ +use dep::protocol_types::constants::NOTE_HASH_TREE_HEIGHT; +use dep::std::merkle::compute_merkle_root; + +use crate::{ + context::PrivateContext, + note::{ + utils::compute_unique_siloed_note_hash, + note_header::NoteHeader, + note_interface::NoteInterface, + }, + oracle::get_membership_witness::{ + get_membership_witness, + MembershipWitness, + }, +}; + +pub fn prove_note_commitment_inclusion( + note_commitment: Field, + block_number: u32, // The block at which we'll prove that the note exists + context: PrivateContext +) { + // 1) Get block header from oracle and ensure that the block is included in the archive. + let block_header = context.get_block_header(block_number); + + // 2) Get the membership witness of the note in the note hash tree + let note_hash_tree_id = 2; // TODO(#3443) + let witness: MembershipWitness = + get_membership_witness(block_number, note_hash_tree_id, note_commitment); + + // 3) Prove that the commitment is in the note hash tree + assert( + block_header.note_hash_tree_root == compute_merkle_root(note_commitment, witness.index, witness.path), + "Proving note inclusion failed" + ); + + // --> Now we have traversed the trees all the way up to archive root. +} + +pub fn prove_note_inclusion( + note_interface: NoteInterface, + note_with_header: Note, + block_number: u32, // The block at which we'll prove that the note exists + context: PrivateContext +) { + let note_commitment = compute_unique_siloed_note_hash(note_interface, note_with_header); + + prove_note_commitment_inclusion(note_commitment, block_number, context); +} \ No newline at end of file diff --git a/yarn-project/aztec-nr/aztec/src/history/note_validity.nr b/yarn-project/aztec-nr/aztec/src/history/note_validity.nr new file mode 100644 index 00000000000..47a45547e40 --- /dev/null +++ b/yarn-project/aztec-nr/aztec/src/history/note_validity.nr @@ -0,0 +1,19 @@ +use crate::{ + context::PrivateContext, + history::{ + note_inclusion::prove_note_inclusion, + nullifier_non_inclusion::prove_note_not_nullified, + }, + note::note_interface::NoteInterface, +}; + +// A helper function that proves that a note is valid at the given block number +pub fn prove_note_validity( + note_interface: NoteInterface, + note_with_header: Note, + block_number: u32, // The block at which we'll prove that the note exists + context: PrivateContext +) { + prove_note_inclusion(note_interface, note_with_header, block_number, context); + prove_note_not_nullified(note_interface, note_with_header, block_number, context); +} \ No newline at end of file diff --git a/yarn-project/aztec-nr/aztec/src/history/nullifier_inclusion.nr b/yarn-project/aztec-nr/aztec/src/history/nullifier_inclusion.nr new file mode 100644 index 00000000000..f6f5185cace --- /dev/null +++ b/yarn-project/aztec-nr/aztec/src/history/nullifier_inclusion.nr @@ -0,0 +1,33 @@ +use dep::std::merkle::compute_merkle_root; + +use crate::{ + context::PrivateContext, + oracle::get_nullifier_membership_witness::get_nullifier_membership_witness, +}; + +pub fn prove_nullifier_inclusion( + nullifier: Field, + block_number: u32, // The block at which we'll prove that the note exists + context: PrivateContext +) { + // 1) Get block header from oracle and ensure that the block hash is included in the archive. + let block_header = context.get_block_header(block_number); + + // 2) Get the membership witness of the nullifier + let witness = get_nullifier_membership_witness(block_number, nullifier); + + // 3) Check that the witness we obtained matches the nullifier + assert(witness.leaf_data.value == nullifier, "Nullifier does not match value in witness"); + + // 4) Compute the nullifier tree leaf + let nullifier_leaf = witness.leaf_data.hash(); + + // 5) Prove that the nullifier is in the nullifier tree + assert( + block_header.nullifier_tree_root == compute_merkle_root(nullifier_leaf, witness.index, witness.path), + "Proving nullifier inclusion failed" + ); + + // --> Now we have traversed the trees all the way up to archive root and verified that the nullifier + // was not yet included in the nullifier tree. +} \ No newline at end of file diff --git a/yarn-project/aztec-nr/aztec/src/history/nullifier_non_inclusion.nr b/yarn-project/aztec-nr/aztec/src/history/nullifier_non_inclusion.nr new file mode 100644 index 00000000000..f491e55a2c1 --- /dev/null +++ b/yarn-project/aztec-nr/aztec/src/history/nullifier_non_inclusion.nr @@ -0,0 +1,63 @@ +use dep::std::merkle::compute_merkle_root; + +use crate::{ + context::PrivateContext, + note::{ + utils::compute_siloed_nullifier, + note_header::NoteHeader, + note_interface::NoteInterface, + }, + oracle::get_nullifier_membership_witness::get_low_nullifier_membership_witness, + utils::{ + full_field_less_than, + full_field_greater_than, + }, +}; + +pub fn prove_nullifier_non_inclusion( + nullifier: Field, + block_number: u32, // The block at which we'll prove that the nullifier does not exists + context: PrivateContext +) { + // 1) Get block header from oracle and ensure that the block is included in the archive. + let block_header = context.get_block_header(block_number); + + // 2) Get the membership witness of a low nullifier of the nullifier + let witness = get_low_nullifier_membership_witness(block_number, nullifier); + + // 3) Prove that the nullifier is not included in the nullifier tree + + // 3.a) Compute the low nullifier leaf and prove that it is in the nullifier tree + let low_nullifier_leaf = witness.leaf_data.hash(); + assert( + block_header.nullifier_tree_root == compute_merkle_root(low_nullifier_leaf, witness.index, witness.path), + "Proving nullifier non-inclusion failed: Could not prove low nullifier inclusion" + ); + + // 3.b) Prove that the low nullifier is smaller than the nullifier + assert( + full_field_less_than(witness.leaf_data.value, nullifier), + "Proving nullifier non-inclusion failed: low_nullifier.value < nullifier.value check failed" + ); + + // 3.c) Prove that the low nullifier is pointing "over" the nullifier to prove that the nullifier is not + // included in the nullifier tree (or to 0 if the to-be-inserted nullifier is the largest of all) + assert( + full_field_greater_than(witness.leaf_data.next_value, nullifier) | (witness.leaf_data.next_index == 0), + "Proving nullifier non-inclusion failed: low_nullifier.next_value > nullifier.value check failed" + ); + + // --> Now we have traversed the trees all the way up to archive root and verified that the nullifier + // was not yet included in the nullifier tree. +} + +pub fn prove_note_not_nullified( + note_interface: NoteInterface, + note_with_header: Note, + block_number: u32, // The block at which we'll prove that the note was not nullified + context: PrivateContext +) { + let nullifier = compute_siloed_nullifier(note_interface, note_with_header); + + prove_nullifier_non_inclusion(nullifier, block_number, context); +} \ No newline at end of file diff --git a/yarn-project/aztec-nr/aztec/src/history/public_value_inclusion.nr b/yarn-project/aztec-nr/aztec/src/history/public_value_inclusion.nr new file mode 100644 index 00000000000..ec666cb69cb --- /dev/null +++ b/yarn-project/aztec-nr/aztec/src/history/public_value_inclusion.nr @@ -0,0 +1,44 @@ +use dep::protocol_types::constants::{ + PUBLIC_DATA_TREE_HEIGHT, + GENERATOR_INDEX__PUBLIC_LEAF_INDEX, +}; +use dep::std::merkle::compute_merkle_root; + +use crate::{ + context::PrivateContext, + hash::pedersen_hash, + oracle::get_sibling_path::get_sibling_path, +}; + +pub fn prove_public_value_inclusion( + value: Field, // The value that we want to prove is in the public data tree + storage_slot: Field, // The storage slot in which the value is stored + block_number: u32, // The block at which we'll prove that the note exists + context: PrivateContext +) { + // 1) Get block header from oracle and ensure that the block hash is included in the archive. + let block_header = context.get_block_header(block_number); + + // 2) Compute the public value leaf index. + // We have to compute the leaf index here because unlike in the case of note commitments, public values are + // not siloed with contract address so an oracle could cheat and give us a membership witness for arbitrary + // value in the public data tree. + let value_leaf_index = pedersen_hash( + [context.this_address(), storage_slot], + GENERATOR_INDEX__PUBLIC_LEAF_INDEX + ); + + // 3) Get the sibling path of the value leaf index in the public data tree at block `block_number`. + let public_data_tree_id = 3; // TODO(#3443) + let path: [Field; PUBLIC_DATA_TREE_HEIGHT] = + get_sibling_path(block_number, public_data_tree_id, value_leaf_index); + + // 4) Prove that the value provided on input is in the public data tree at the given storage slot. + assert( + block_header.public_data_tree_root == compute_merkle_root(value, value_leaf_index, path), + "Proving public value inclusion failed" + ); + + // --> Now we have traversed the trees all the way up to archive root and that way verified that a specific + // `value` was really set in a given contract storage slot at block `block_number` in public data tree. +} \ No newline at end of file diff --git a/yarn-project/aztec-nr/aztec/src/lib.nr b/yarn-project/aztec-nr/aztec/src/lib.nr index 99c087b0075..badfa9c0f05 100644 --- a/yarn-project/aztec-nr/aztec/src/lib.nr +++ b/yarn-project/aztec-nr/aztec/src/lib.nr @@ -2,6 +2,7 @@ mod abi; mod address; mod context; mod hash; +mod history; mod log; mod messaging; mod note; diff --git a/yarn-project/aztec-nr/aztec/src/utils.nr b/yarn-project/aztec-nr/aztec/src/utils.nr index 205b19fd49a..a9a766c6b7a 100644 --- a/yarn-project/aztec-nr/aztec/src/utils.nr +++ b/yarn-project/aztec-nr/aztec/src/utils.nr @@ -20,3 +20,15 @@ pub fn field_from_bytes(bytes: [u8; N], big_endian: bool) -> Field { as_field } + +// TODO(#3470): Copied over from https://github.com/AztecProtocol/aztec-packages/blob/a07c4bd47313be6aa604a63f37857eb0136b41ba/yarn-project/noir-protocol-circuits/src/crates/rollup-lib/src/base/base_rollup_inputs.nr#L599 +// move to a shared place? + +// TODO to radix returns u8, so we cannot use bigger radixes. It'd be ideal to use a radix of the maximum range-constrained integer noir supports +pub fn full_field_less_than(lhs: Field, rhs: Field) -> bool { + dep::std::eddsa::lt_bytes32(lhs, rhs) +} + +pub fn full_field_greater_than(lhs: Field, rhs: Field) -> bool { + dep::std::eddsa::lt_bytes32(rhs, lhs) +} \ No newline at end of file diff --git a/yarn-project/end-to-end/src/e2e_inclusion_proofs_contract.test.ts b/yarn-project/end-to-end/src/e2e_inclusion_proofs_contract.test.ts index 4240a863566..298ff392724 100644 --- a/yarn-project/end-to-end/src/e2e_inclusion_proofs_contract.test.ts +++ b/yarn-project/end-to-end/src/e2e_inclusion_proofs_contract.test.ts @@ -54,7 +54,7 @@ describe('e2e_inclusion_proofs_contract', () => { { // Prove note inclusion in a given block. const ignoredCommitment = 0; // Not ignored only when the note doesn't exist - await contract.methods.proveNoteInclusion(owner, noteCreationBlockNumber, ignoredCommitment).send().wait(); + await contract.methods.test_note_inclusion_proof(owner, noteCreationBlockNumber, ignoredCommitment).send().wait(); } { @@ -63,12 +63,12 @@ describe('e2e_inclusion_proofs_contract', () => { // possible because of issue https://github.com/AztecProtocol/aztec-packages/issues/3535 const blockNumber = await pxe.getBlockNumber(); const ignoredNullifier = 0; // Not ignored only when the note doesn't exist - await contract.methods.proveNullifierNonInclusion(owner, blockNumber, ignoredNullifier).send().wait(); + await contract.methods.test_nullifier_non_inclusion_proof(owner, blockNumber, ignoredNullifier).send().wait(); } { // We test the failure case now --> The proof should fail when the nullifier already exists - const receipt = await contract.methods.nullifyNote(owner).send().wait({ debug: true }); + const receipt = await contract.methods.nullify_note(owner).send().wait({ debug: true }); const { newNullifiers } = receipt.debugInfo!; expect(newNullifiers.length).toBe(2); @@ -78,13 +78,38 @@ describe('e2e_inclusion_proofs_contract', () => { // the low nullifier when the nullifier already exists in the tree and for this reason the execution fails // on low_nullifier.value < nullifier.value check. await expect( - contract.methods.proveNullifierNonInclusion(owner, blockNumber, nullifier).send().wait(), + contract.methods.test_nullifier_non_inclusion_proof(owner, blockNumber, nullifier).send().wait(), ).rejects.toThrowError( /Proving nullifier non-inclusion failed: low_nullifier.value < nullifier.value check failed/, ); } }); + it('proves note validity (note commitment inclusion and nullifier non-inclusion)', async () => { + // Owner of a note + const owner = accounts[0].address; + let noteCreationBlockNumber: number; + { + // Create a note + const value = 100n; + const receipt = await contract.methods.create_note(owner, value).send().wait({ debug: true }); + + noteCreationBlockNumber = receipt.blockNumber!; + const { newCommitments, visibleNotes } = receipt.debugInfo!; + + expect(newCommitments.length).toBe(1); + expect(visibleNotes.length).toBe(1); + const [receivedValue, receivedOwner, _randomness] = visibleNotes[0].note.items; + expect(receivedValue.toBigInt()).toBe(value); + expect(receivedOwner).toEqual(owner.toField()); + } + + { + // Prove note validity + await contract.methods.test_note_validity_proof(owner, noteCreationBlockNumber).send().wait(); + } + }); + it('note existence failure case', async () => { // Owner of a note const owner = AztecAddress.random(); @@ -92,7 +117,7 @@ describe('e2e_inclusion_proofs_contract', () => { const blockNumber = await pxe.getBlockNumber(); const randomNoteCommitment = Fr.random(); await expect( - contract.methods.proveNoteInclusion(owner, blockNumber, randomNoteCommitment).send().wait(), + contract.methods.test_note_inclusion_proof(owner, blockNumber, randomNoteCommitment).send().wait(), ).rejects.toThrow(/Leaf value: 0x[0-9a-fA-F]+ not found in NOTE_HASH_TREE/); }); @@ -100,7 +125,7 @@ describe('e2e_inclusion_proofs_contract', () => { // Chose random block number between deployment and current block number to test archival node const blockNumber = await getRandomBlockNumberSinceDeployment(); - await contract.methods.provePublicValueInclusion(publicValue, blockNumber).send().wait(); + await contract.methods.test_public_value_inclusion_proof(publicValue, blockNumber).send().wait(); }); it('public value existence failure case', async () => { @@ -109,7 +134,7 @@ describe('e2e_inclusion_proofs_contract', () => { const randomPublicValue = Fr.random(); await expect( - contract.methods.provePublicValueInclusion(randomPublicValue, blockNumber).send().wait(), + contract.methods.test_public_value_inclusion_proof(randomPublicValue, blockNumber).send().wait(), ).rejects.toThrow(/Proving public value inclusion failed/); }); @@ -120,7 +145,7 @@ describe('e2e_inclusion_proofs_contract', () => { const block = await pxe.getBlock(blockNumber); const nullifier = block?.newNullifiers[0]; - await contract.methods.proveNullifierInclusion(nullifier!, blockNumber).send().wait(); + await contract.methods.test_nullifier_inclusion_proof(nullifier!, blockNumber).send().wait(); }); it('nullifier existence failure case', async () => { @@ -129,9 +154,9 @@ describe('e2e_inclusion_proofs_contract', () => { const blockNumber = await pxe.getBlockNumber(); const randomNullifier = Fr.random(); - await expect(contract.methods.proveNullifierInclusion(randomNullifier, blockNumber).send().wait()).rejects.toThrow( - /Low nullifier witness not found for nullifier 0x[0-9a-fA-F]+ at block/, - ); + await expect( + contract.methods.test_nullifier_inclusion_proof(randomNullifier, blockNumber).send().wait(), + ).rejects.toThrow(/Low nullifier witness not found for nullifier 0x[0-9a-fA-F]+ at block/); }); const getRandomBlockNumberSinceDeployment = async () => { diff --git a/yarn-project/noir-contracts/src/contracts/inclusion_proofs_contract/src/main.nr b/yarn-project/noir-contracts/src/contracts/inclusion_proofs_contract/src/main.nr index a06c832cd50..3509134e7cf 100644 --- a/yarn-project/noir-contracts/src/contracts/inclusion_proofs_contract/src/main.nr +++ b/yarn-project/noir-contracts/src/contracts/inclusion_proofs_contract/src/main.nr @@ -1,13 +1,5 @@ -mod utils; - // A demonstration of inclusion and non-inclusion proofs. contract InclusionProofs { - use dep::protocol_types::constants::{ - NOTE_HASH_TREE_HEIGHT, - PUBLIC_DATA_TREE_HEIGHT, - GENERATOR_INDEX__PUBLIC_LEAF_INDEX, - }; - use dep::std::merkle::compute_merkle_root; use dep::aztec::{ state_vars::{ map::Map, @@ -26,27 +18,28 @@ contract InclusionProofs { utils as note_utils, }, - oracle::{ - get_membership_witness::{ - get_membership_witness, - MembershipWitness, + history::{ + note_inclusion::{ + prove_note_commitment_inclusion, + prove_note_inclusion, + }, + note_validity::{ + prove_note_validity, + }, + nullifier_inclusion::{ + prove_nullifier_inclusion, + }, + nullifier_non_inclusion::{ + prove_nullifier_non_inclusion, + prove_note_not_nullified, }, - get_sibling_path::get_sibling_path, - get_nullifier_membership_witness::{ - get_low_nullifier_membership_witness, - get_nullifier_membership_witness, - NullifierMembershipWitness, + public_value_inclusion::{ + prove_public_value_inclusion, }, }, - hash::pedersen_hash, }; use dep::value_note::value_note::{ValueNote, ValueNoteMethods, VALUE_NOTE_LEN}; - use crate::utils::{ - full_field_less_than, - full_field_greater_than, - }; - struct Storage { private_values: Map>, public_value: PublicState, @@ -96,54 +89,33 @@ contract InclusionProofs { // Proves that the owner owned a ValueNote at block `block_number`. #[aztec(private)] - fn proveNoteInclusion( + fn test_note_inclusion_proof( owner: AztecAddress, block_number: u32, // The block at which we'll prove that the note exists spare_commitment: Field, // This is only used when the note is not found --> used to test the failure case ) { - // 1) Get block header from oracle and ensure that the block hash is included in the current blocks tree - // root. - let block_header = context.get_block_header(block_number); - - // 2) Get the note from PXE. + // 1) Get the note from PXE. let private_values = storage.private_values.at(owner.address); let options = NoteGetterOptions::new().select(1, owner.address).set_limit(1); let notes = private_values.get_notes(options); let maybe_note = notes[0]; - // 3) Compute the commitment from the note - let note_commitment = if maybe_note.is_some() { - note_utils::compute_unique_siloed_note_hash(ValueNoteMethods, maybe_note.unwrap_unchecked()) + // 2) Prove the note inclusion + if maybe_note.is_some() { + prove_note_inclusion(ValueNoteMethods, maybe_note.unwrap_unchecked(), block_number, context); } else { - // Note was not found so we will use the spare commitment - spare_commitment + // Note was not found so we will prove inclusion of the spare commitment + prove_note_commitment_inclusion(spare_commitment, block_number, context); }; - - // 4) Get the membership witness of the note in the note hash tree - let note_hash_tree_id = 2; // TODO(#3443) - let witness: MembershipWitness = - get_membership_witness(block_number, note_hash_tree_id, note_commitment); - - // 5) Prove that the commitment is in the note hash tree - assert( - block_header.note_hash_tree_root == compute_merkle_root(note_commitment, witness.index, witness.path), - "Proving note inclusion failed" - ); - - // --> Now we have traversed the trees all the way up to blocks tree root. } // Proves that the note was not yet nullified at block `block_number`. #[aztec(private)] - fn proveNullifierNonInclusion( + fn test_nullifier_non_inclusion_proof( owner: AztecAddress, block_number: u32, // The block at which we'll prove that the nullifier does not exists spare_nullifier: Field, // This is only used when the note is not found --> used to test the failure case ) { - // 1) Get block header from oracle and ensure that the block hash is included in the current blocks tree - // root. - let block_header = context.get_block_header(block_number); - // 2) Get the note from PXE let private_values = storage.private_values.at(owner.address); let options = NoteGetterOptions::new().select(1, owner.address).set_limit(1); @@ -151,44 +123,31 @@ contract InclusionProofs { let maybe_note = notes[0]; // 3) Compute the nullifier from the note - let nullifier = if maybe_note.is_some() { - note_utils::compute_siloed_nullifier(ValueNoteMethods, maybe_note.unwrap_unchecked()) + if maybe_note.is_some() { + prove_note_not_nullified(ValueNoteMethods, maybe_note.unwrap_unchecked(), block_number, context); } else { // Note was not found so we will use the spare nullifier - spare_nullifier + prove_nullifier_non_inclusion(spare_nullifier, block_number, context); }; + } - // 4) Get the membership witness of a low nullifier of the nullifier - let witness = get_low_nullifier_membership_witness(block_number, nullifier); - - // 5) Prove that the nullifier is not included in the nullifier tree - - // 5.a) Compute the low nullifier leaf and prove that it is in the nullifier tree - let low_nullifier_leaf = witness.leaf_data.hash(); - assert( - block_header.nullifier_tree_root == compute_merkle_root(low_nullifier_leaf, witness.index, witness.path), - "Proving nullifier non-inclusion failed: Could not prove low nullifier inclusion" - ); - - // 5.b) Prove that the low nullifier is smaller than the nullifier - assert( - full_field_less_than(witness.leaf_data.value, nullifier), - "Proving nullifier non-inclusion failed: low_nullifier.value < nullifier.value check failed" - ); - - // 5.c) Prove that the low nullifier is pointing "over" the nullifier to prove that the nullifier is not - // included in the nullifier tree (or to 0 if the to-be-inserted nullifier is the largest of all) - assert( - full_field_greater_than(witness.leaf_data.next_value, nullifier) | (witness.leaf_data.next_index == 0), - "Proving nullifier non-inclusion failed: low_nullifier.next_value > nullifier.value check failed" - ); + #[aztec(private)] + fn test_note_validity_proof( + owner: AztecAddress, + block_number: u32, // The block at which we'll prove that the note exists and is not nullified + ) { + // 1) Get the note from PXE. + let private_values = storage.private_values.at(owner.address); + let options = NoteGetterOptions::new().select(1, owner.address).set_limit(1); + let notes = private_values.get_notes(options); + let note = notes[0].unwrap(); - // --> Now we have traversed the trees all the way up to blocks tree root and verified that the nullifier - // was not yet included in the nullifier tree. + // 2) Prove the note validity + prove_note_validity(ValueNoteMethods, note, block_number, context); } #[aztec(private)] - fn nullifyNote( + fn nullify_note( owner: AztecAddress, ) { let private_values = storage.private_values.at(owner.address); @@ -203,64 +162,19 @@ contract InclusionProofs { // Note: I am not getting a nullifier of the note that was created in this contract in this function because it is // currently not possible to obtain a nullified note from PXE. #[aztec(private)] - fn proveNullifierInclusion( + fn test_nullifier_inclusion_proof( nullifier: Field, block_number: u32, // The block at which we'll prove that the nullifier not exists in the tree ) { - // 1) Get block header from oracle and ensure that the block hash is included in the current blocks tree - // root. - let block_header = context.get_block_header(block_number); - - // 2) Get the membership witness of the nullifier - let witness = get_nullifier_membership_witness(block_number, nullifier); - - // 3) Check that the witness we obtained matches the nullifier - assert(witness.leaf_data.value == nullifier, "Nullifier does not match value in witness"); - - // 4) Compute the nullifier tree leaf - let nullifier_leaf = witness.leaf_data.hash(); - - // 5) Prove that the nullifier is in the nullifier tree - assert( - block_header.nullifier_tree_root == compute_merkle_root(nullifier_leaf, witness.index, witness.path), - "Proving nullifier inclusion failed" - ); - - // --> Now we have traversed the trees all the way up to blocks tree root and verified that the nullifier - // was not yet included in the nullifier tree. + prove_nullifier_inclusion(nullifier, block_number, context); } #[aztec(private)] - fn provePublicValueInclusion( + fn test_public_value_inclusion_proof( public_value: Field, block_number: u32, // The block at which we'll prove that the public value exists ) { - // 1) Get block header from oracle and ensure that the block hash is included in the current blocks tree - // root. - let block_header = context.get_block_header(block_number); - - // 2) Compute the public value leaf index. - // We have to compute the leaf index here because unlike in the case of note commitments, public values are - // not siloed with contract address so an oracle could cheat and give us a membership witness for arbitrary - // value in the public data tree. - let public_value_leaf_index = pedersen_hash( - [context.this_address(), storage.public_value.storage_slot], - GENERATOR_INDEX__PUBLIC_LEAF_INDEX - ); - - // 3) Get the sibling path of the public value leaf index in the public data tree at block `block_number`. - let public_data_tree_id = 3; // TODO(#3443) - let path: [Field; PUBLIC_DATA_TREE_HEIGHT] = - get_sibling_path(block_number, public_data_tree_id, public_value_leaf_index); - - // 4) Prove that the public value provided on input is in the public data tree - assert( - block_header.public_data_tree_root == compute_merkle_root(public_value, public_value_leaf_index, path), - "Proving public value inclusion failed" - ); - - // --> Now we have traversed the trees all the way up to blocks tree root and that way verified that - // a specific `public_value` was really set in a given contract storage slot at block `block_number`. + prove_public_value_inclusion(public_value, storage.public_value.storage_slot, block_number, context); } // Computes note hash and nullifier. diff --git a/yarn-project/noir-contracts/src/contracts/inclusion_proofs_contract/src/utils.nr b/yarn-project/noir-contracts/src/contracts/inclusion_proofs_contract/src/utils.nr deleted file mode 100644 index e67cf2fd776..00000000000 --- a/yarn-project/noir-contracts/src/contracts/inclusion_proofs_contract/src/utils.nr +++ /dev/null @@ -1,11 +0,0 @@ -// TODO(#3470): Copied over from https://github.com/AztecProtocol/aztec-packages/blob/a07c4bd47313be6aa604a63f37857eb0136b41ba/yarn-project/noir-protocol-circuits/src/crates/rollup-lib/src/base/base_rollup_inputs.nr#L599 -// move to a shared place? - -// TODO to radix returns u8, so we cannot use bigger radixes. It'd be ideal to use a radix of the maximum range-constrained integer noir supports -pub fn full_field_less_than(lhs: Field, rhs: Field) -> bool { - dep::std::eddsa::lt_bytes32(lhs, rhs) -} - -pub fn full_field_greater_than(lhs: Field, rhs: Field) -> bool { - dep::std::eddsa::lt_bytes32(rhs, lhs) -} \ No newline at end of file From 55136246ffa457c73426190438c254743c841675 Mon Sep 17 00:00:00 2001 From: PhilWindle <60546371+PhilWindle@users.noreply.github.com> Date: Wed, 13 Dec 2023 09:20:52 +0000 Subject: [PATCH 28/35] docs: Updated yellow paper for fees (#3659) This PR contains an updated fees spec in the yellow paper. # Checklist: Remove the checklist to signal you've completed it. Enable auto-merge if the PR is ready to merge. - [ ] If the pull request requires a cryptography review (e.g. cryptographic algorithm implementations) I have added the 'crypto' tag. - [ ] I have reviewed my diff in github, line by line and removed unexpected formatting changes, testing logs, or commented-out code. - [ ] Every change is related to the PR description. - [ ] I have [linked](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue) this pull request to relevant issues (if any exist). --- .../docs/gas-and-fees/gas-and-fees.md | 120 +++++++++--------- 1 file changed, 59 insertions(+), 61 deletions(-) diff --git a/yellow-paper/docs/gas-and-fees/gas-and-fees.md b/yellow-paper/docs/gas-and-fees/gas-and-fees.md index f4d63b6b4bf..21ee12c5abb 100644 --- a/yellow-paper/docs/gas-and-fees/gas-and-fees.md +++ b/yellow-paper/docs/gas-and-fees/gas-and-fees.md @@ -33,9 +33,9 @@ We can define a number of requirements that serve to provide a transparent and f ## High Level Concepts and Design -1. We will use concepts of L1 and L2 gas to universally define units of resource for the Ethereum and Aztec networks respectively. L1 gas directly mirrors the actual gas specification as defined by Ethereum, L2 gas covers all resource expended on the L2 network. -2. We will deterministically quantify all resource consumption of a transaction into 4 values. These being the amortized and transaction specific quantities of each of L1 and L2 gas. -3. The transaction sender will provide a single fee for the transaction. This will be split into 2 components to cover each of the L1 and L2 gas costs. The sender will specify `feePerGas` and `gasLimit` for each component. Doing so provides protection to the sender that the amount of fee applicable to L1 costs has an upper bound and L2 a lower bound. +1. We will use concepts of L1, L2 and DA gas to universally define units of resource for the Ethereum and Aztec networks respectively. L1 gas directly mirrors the actual gas specification as defined by Ethereum, L2 gas covers all resource expended on the L2 network. Finally, DA gas accounts for the data stored on the network's Data Availability solution. +2. We will deterministically quantify all resource consumption of a transaction into 7 values. We will define these value later but essentially they represent the amortized and transaction specific quantities of each of L1, L2 and DA gas. +3. The transaction sender will provide a single fee for the transaction. This will be split into 3 components to cover each of the L1, L2 and DA gas costs. The sender will specify `feePerGas` and `gasLimit` for each component. Doing so provides protection to the sender that the amount of fee applicable to any component is constrained. 4. We will constrain the sequencer to apply the correct amortized and transaction specific fees ensuring the sender can not be charged arbitrarily. 5. We will define a method by which fees can be paid in any asset, either publicly or privately, on Ethereum or Aztec but where the sequencer retains agency as to what assets and fee payment methods they are willing to accept. 6. Upon accepting a transaction, we will constrain the sequencer to receive payment and provide any refund owing via the methods specified by the sender. @@ -63,33 +63,34 @@ Some operations are specific to a transaction, such as public function execution All of the operations listed in the transaction specific table can provide us with deterministic gas values for a transaction. The transaction can be simulated and appropriate gas figures can be calculated before the transaction is sent to the network. The transaction will also need to provide a fee to cover it's portion of the amortized cost. This can be done by deciding on a value of `N`, the number of transactions in a rollup. Of course, the transaction sender can't know in advance how many other transactions will be included in the same rollup but the sender will be able to see how many transactions were included in prior rollups and decide on a value that will give them some certainty of inclusion without overpaying for insufficient amortization. As with all costs, any additional amortization will be refunded to the sender. -For example, if the previous 10 rollups consist of an average of 5000 transactions, the sender could decide on a value of 1000 for `N` in it's amortization. If the transaction is included in a rollup with > `N` transactions, the fee saved by the additional amortization will be refunded to the sender. +For example, if the previous 10 rollups consist of an average of 5000 transactions, the sender could decide on a value of 1000 for `N` in it's amortization. If the transaction is included in a rollup with > `N` transactions, the fee saved by the additional amortization will be refunded to the sender. If the sequencer chooses to include the transaction in a rollup with < `N` transactions, the sequencer will effectively subsidize that reduced amortization. -The transaction will be provided with 6 gas values: +The transaction will be provided with 7 gas values: | Value | Description | | -------- | -------- | -| `l1BaseGasLimit` | The maximum quantity of gas permitted for use in amortized L1 operations | -| `l1TxGasLimit` | The maximum quantity of gas permitted for use in transaction specific L1 operations | -| `l2BaseGasLimit` | The maximum quantity of gas permitted for use in amortized L2 operations | -| `l2TxGasLimit` | The maximum quantity of gas permitted for use in transaction specific operations | -| `l1FeeDistributionGas` | The quantity of L1 gas the sequencer can charge for executing the fee distribution function | -| `l2FeeDistributionGas` | The quantity of L2 gas the sequencer can charge for executing the fee distribution function | +| `L1BaseGasLimit` | The maximum quantity of gas permitted for use in amortized L1 operations | +| `L1TxGasLimit` | The maximum quantity of gas permitted for use in transaction specific L1 operations | +| `L2BaseGasLimit` | The maximum quantity of gas permitted for use in amortized L2 operations | +| `L2TxGasLimit` | The maximum quantity of gas permitted for use in transaction specific L2 operations | +| `L2FeeDistributionGas` | The quantity of L2 gas the sequencer can charge for executing the fee distribution function | +| `DAFeeDistributionGas` | The quantity of DA gas the sequencer can charge for storing state updates produced as part of fee distribution | +| `DATxGasLimit` | The maximum quantity of DA gas permitted for use in transaction specific Data Availability functions | By constraining each of the above values individually, the transaction sender is protected from a dishonest sequencer allocating an unfairly high amount of gas to one category and leaving insufficient gas for other categories causing a transaction to erroneously be deemed 'out of gas' and a fee taken for improper execution. ### Gas Measurement By A Sequencer -When a transaction is received by a sequencer, it will want to determine if the transaction has been endowed with sufficient fee to be considered for inclusion in a rollup. Although the transaction contains information as to the gas limits and fees it provides, these may not be accurate either because the sender is dishonest or because the simulation of any public functions was performed on a system state that differs to that at the point of inclusion. Unlike transactions on Ethereum it is not simply a case of linearly executing the transactions opcodes until completion of the transaction exceeds the provided gas. Rollup inclusion and public function execution and proving require significant resource investment on the part of the sequencer even for the most trivial of transaction. +When a transaction is received by a sequencer, it will want to determine if the transaction has been endowed with sufficient fee to be considered for inclusion in a rollup. Although the transaction contains information as to the gas limits and fees it provides, these may not be accurate either because the sender is dishonest or because the simulation of any public functions was performed on a system state that differs to that at the point of inclusion. Unlike transactions on Ethereum, it is not simply a case of linearly executing the transactions opcodes until completion of the transaction exceeds the provided gas. Rollup inclusion and public function execution and proving require significant resource investment on the part of the sequencer even for the most trivial transaction. There are a series of steps the sequencer would wish to perform such that it incrementally increases it's commitment to processing the transaction as it becomes more confident of a successful outcome: -1. Determine how much fee has been provided and verify that this is sufficient to cover the L1 and L2 gas limits specified in the transaction. Later on we will look at how this is done but it may involve simulation of a public function. The sequencer will have visibility over which function on which contract has been specified for this step and has agency to disregard the transaction if it is not willing to execute this step. -2. Once the fee is known, verify that enough fee exists to cover the transaction's requirements at this stage. This would include publishing the results of the private stage of the transaction and the amortized cost of rollup construction and publishing. +1. Determine how much fee has been provided and verify that this is sufficient to cover the L1, L2 and DA gas limits specified in the transaction. Later on we will look at how this is done but it may involve simulation of a public function. The sequencer will have visibility over which function on which contract has been specified for this step and has agency to disregard the transaction if it is not willing to execute this step. +2. Once the fee is known, verify that enough fee exists to cover the transaction's requirements at this stage. This would include publishing the results of the private stage of the transaction and the amortized cost of rollup construction and verification. 3. If at least one public function is enqueued, verify that enough fee exists to cover at least 1 iteration of the public VM, 1 iteration of the public kernel circuit and a non-zero amount left for public function simulation. The sequencer here will seek to determine if it is worth proceeding with the transaction. Proceeding requires an investment at least covering the cost of the minimum public VM execution and an iteration of the public kernel circuit. The minimum cost could be described as the cost to simulate, execute and prove a function which reverts as soon as it enters the function. -Each of the above steps should be relatively trivial for the sequencer to perform and they have agency to disregard the transaction after each one. Having decided that a transaction is worth proceeding with, the sequencer will simulate any public portion of the transaction until completion or simulation exceeds the provided L1 or L2 gas limits. As simulation takes place, it should be noted that further L1 state updates will be made and any nested public calls will incur additional public VM and public kernel iteration costs. +Each of the above steps should be relatively trivial for the sequencer to perform and they have agency to disregard the transaction after each one. Having decided that a transaction is worth proceeding with, the sequencer will simulate any public portion of the transaction until completion or simulation exceeds the provided gas limits. As simulation takes place, it should be noted that further DA state updates will be made and any nested public calls will incur additional public VM and public kernel iteration costs. After simulation, the sequencer will have complete visibility over the gas profile of the transaction and can determine how much witness generation and proving is required for transaction inclusion. @@ -99,9 +100,9 @@ Now that we have a method for defining and measuring the gas consumption of a tr To achieve the above requirements we will break the transaction into 3 components: -1. The fee preparation component can have both private and/or public functions. -2. The transaction payload component can have both private and/or public functions. -3. The fee distribution component only has a public function. +1. The fee preparation component can contain both private and/or public functions. +2. The transaction payload component can contain both private and/or public functions. +3. The fee distribution component only contains a public function. All of these components occur **within the same transaction**, ultimately they result in 2 sets of public inputs being emitted from the private kernel circuits. Those related to the fee payment and those related to the transaction payload. State changes requested by the transaction payload are reverted if any component fails. State changes in the fee preparation and distribution components are only reverted if either of those components fail. @@ -109,17 +110,17 @@ All of these components occur **within the same transaction**, ultimately they r ### Fee Preparation -This component can consist of both private and/or public execution, the result of which must be that an easily identifiable fee be made available to the sequencer. This could be implemented in a variety of ways but typically, we would expect a call to a 'fee payment', escrowing the funds to later be released by the fee distribution component. Any public execution should be minimal to reduce unnecessary work for the sequencer during the period of evaluating whether a transaction is to be included. If public execution is required as part of fee preparation, the sequencer will have complete visibility over what they are being expected to execute. We expect that sequencers will select only those transactions that provide identifiable fees using whitelisted contract addresses and functions. Ultimately, whilst a sequencer's goal is to include as many transactions as possible within a rollup, it will have agency over how much risk it is willing to take that a transaction does not successfully provide a sufficient fee. +This component can consist of both private and/or public execution, the result of which must be that an easily identifiable fee be made available to the sequencer. This could be implemented in a variety of ways but typically, we would expect a call to a 'fee payment' contract, escrowing the funds to later be released by the fee distribution component. Any public execution should be minimal to reduce unnecessary work for the sequencer during the period of evaluating whether a transaction is to be included. If public execution is required as part of fee preparation, the sequencer will have complete visibility over what they are being expected to execute. We expect that sequencers will select only those transactions that provide identifiable fees using whitelisted contract addresses and functions. Ultimately, whilst a sequencer's goal is to include as many transactions as possible within a rollup, it will have agency over how much risk it is willing to take that a transaction does not successfully provide a sufficient fee. ### Transaction Payload -This is the main component of the transaction, the part containing the execution the transaction sender wishes to make. This may revert or run out of gas, causing it's state changes to be reverted, but the sequencer will still be able to claim payment for the work performed. +This is the main component of the transaction, the part containing the execution the transaction sender wishes to perform. This may revert or run out of gas, causing it's state changes to be reverted, but the sequencer will still be able to claim payment for the work performed. ### Fee Distribution Fee distribution consists of a single call to a contract function specified by the client. The function will require the sequencer to provide accurate information about the gas consumed throughout the execution of the transaction payload and perform the necessary steps to finalize the payment to the sequencer and any refund owed to the client. -Like the fee payment component, this must have a very low probability of failure and the sequencer is free to only consider transactions with fee distribution components that they deem acceptable. Reverting here reverts the entire transaction as no fee is distributed to the sequencer. However, it should be straight forward to create fee distribution functions that will not fail given valid inputs that have been verified by the sequencer. +Like the fee payment component, this must have a very low probability of failure and the sequencer is free to only consider transactions with fee distribution components that they deem acceptable. Reverting here reverts the entire transaction as no fee is distributed to the sequencer. However, it should be straight forward to create fee distribution functions that will not fail given valid inputs that have been verified by the sequencer. Payment for execution of this function is provided by the fixed values of `L2FeeDistributionGas` and `DAFeeDistributionGas` so fee distribution functions with highly deterministic gas profiles will be favoured by sequencers. ### Sequencer Validation and DOS Protection @@ -129,13 +130,13 @@ It is of course possible that the fee payment contract and asset is supported by ### Fee Collection -We will define a new block scoped global value ‘coinbase’ that will be used to identify the address of the sequencer for the current block. The sequencer will provide this address to public VM, public kernel and rollup circuits. The rollup circuits will constrain that the same value is used for all circuits in the proving tree. +We will define a block scoped global value ‘coinbase’ that will be used to identify the address of the sequencer for the current block. The sequencer will provide this address to public VM, public kernel and rollup circuits. The rollup circuits will constrain that the same value is used for all circuits in the proving tree. -With this new value defined, a typical fee payment flow might look as follows: +With this value defined, a typical fee payment flow might look as follows: 1. Sequencer executes the public portion of the fee preparation component, escrowing some funds by transferring them to a public balance within a ‘fee payment’ contract. 2. Sequencer executes the transaction payload, in doing so computes the actual cost of the transaction. -3. Sequencer executes the fee distribution function, transferring the actual cost to the ‘coinbase’ address and any refund back to the transaction sender. +3. Sequencer executes the fee distribution function, transferring the final cost to the ‘coinbase’ address and any refund back to the transaction sender. The final cost here will be the sum of the transaction specific cost, the amortised cost and the fee provided for executing the fee distribution function. ## Transaction and Fee Lifecycle @@ -145,16 +146,18 @@ We will attempt to walk through the process by which a transaction is created wi Transactions begin on a user's device where a user opts to interact privately with a contract. This execution results in the generation of new notes and nullifiers and potentially some enqueued public function calls. Additionally, at some point during this execution, a fee will need to be generated. The state updates related to this fee will be added to a separate collection of notes, nullifiers and public calls where these state updates only revert on failure of the fee preparation or distribution logic. -This would appear to introduce a circular dependency whereby an appropriate fee can't be produced without knowing the gas profile (the required quantities of L1 and L2 gas) but the gas profile can depend on the fee required. When simulating the transaction, we will introduce new values to the global context: +This would appear to introduce a circular dependency whereby an appropriate fee can't be produced without knowing the gas profile (the required quantities of L1, L2 and DA gas), but the gas profile can depend on the fee required. When simulating the transaction, we will introduce values to the global context: - **feePerL1Gas** - The fee provided per unit of L1 gas - **feePerL2Gas** - The fee provided per unit of L2 gas -- **l1BaseGasLimit** - The upper bound of L1 amortized gas the transaction is willing to pay for -- **l2BaseGasLimit** - The upper bound of L2 amortized gas the transaction is willing to pay for -- **l1TxGasLimit** - The upper bound of L1 transaction specific gas the transaction is willing to pay for -- **l2TxGasLimit** - The upper bound of L2 transaction specific gas the transaction is willing to pay for -- **l1FeeDistributionGas** - The amount of L1 gas the transaction is willing to pay for execution of the fee distribution function -- **l2FeeDistributionGas** - The amount of L1 gas the transaction is willing to pay for execution of the fee distribution function +- **feePerDAGas** - The fee provided per unit of DA gas +- **L1BaseGasLimit** - The upper bound of L1 amortized gas the transaction is willing to pay for +- **L2BaseGasLimit** - The upper bound of L2 amortized gas the transaction is willing to pay for +- **L1TxGasLimit** - The upper bound of L1 transaction specific gas the transaction is willing to pay for +- **L2TxGasLimit** - The upper bound of L2 transaction specific gas the transaction is willing to pay for +- **DATxGasLimit** - The upper bound of DA transaction specific gas the transaction is willing to pay for +- **L1FeeDistributionGas** - The amount of L1 gas the transaction is willing to pay for execution of the fee distribution function +- **DAFeeDistributionGas** - The amount of DA gas the transaction is willing to pay for execution of the fee distribution function Simulation of the transaction will provide feedback as to it's gas consumption, this can be repeated to converge on the optimum values of fee and gas limits for the transaction. The private portion of the transaction will be proven via the private kernel circuit resulting in a number of fee related public inputs: @@ -167,12 +170,14 @@ Simulation of the transaction will provide feedback as to it's gas consumption, - **feeUnencryptedLogsHash** - The hash of unencrypted logs generated by the fee payment - **feePerL1Gas** - The fee provided per unit of L1 gas - **feePerL2Gas** - The fee provided per unit of L2 gas -- **l1BaseGasLimit** - The upper bound of L1 amortized gas the transaction is willing to pay for -- **l2BaseGasLimit** - The upper bound of L2 amortized gas the transaction is willing to pay for -- **l1TxGasLimit** - The upper bound of L1 transaction specific gas the transaction is willing to pay for -- **l2TxGasLimit** - The upper bound of L2 transaction specific gas the transaction is willing to pay for -- **l1FeeDistributionGas** - The amount of L1 gas the transaction is willing to pay for execution of the fee distribution function -- **l2FeeDistributionGas** - The amount of L2 gas the transaction is willing to pay for execution of the fee distribution function +- **feePerDAGas** - The fee provided per unit of DA gas +- **L1BaseGasLimit** - The upper bound of L1 amortized gas the transaction is willing to pay for +- **L2BaseGasLimit** - The upper bound of L2 amortized gas the transaction is willing to pay for +- **L1TxGasLimit** - The upper bound of L1 transaction specific gas the transaction is willing to pay for +- **L2TxGasLimit** - The upper bound of L2 transaction specific gas the transaction is willing to pay for +- **DATxGasLimit** - The upper bound of DA transaction specific gas the transaction is willing to pay for +- **L2FeeDistributionGas** - The amount of L2 gas the transaction is willing to pay for execution of the fee distribution function +- **DAFeeDistributionGas** - The amount of DA gas the transaction is willing to pay for execution of the fee distribution function ### Transaction Selection and Execution @@ -188,27 +193,30 @@ struct TxContext { l2BaseGasLimit; // provided by the client l1TxGasLimit; // provided by the client l2TxGasLimit; // provided by the client - l1FeeDistributionGas: // provided by the client + dATxGasLimit; // provided by the client + dAFeeDistributionGas: // provided by the client l2FeeDistributionGas: // provided by the client feePerL1Gas; // provided by the client feePerL2Gas; // provided by the client + feePerDAGas; // provided by the client l1GasUsed; // accumulated through circuits l2GasUsed; // accumulated through circuits + dAGasUsed; // accumulated through circuits refundRecipient; // used in the case of public payments/refunds txId; // identifier used for private refunds rollupSize; // set by the sequencer for the rollup } ``` -The sequencer will need to specify the intended size of the rollup (determined as part of the sequencer selection commitment phase) and use this value to calculate gas amortization. These values of amortized L1 and L2 gas will be added to the `l1GasUsed` and `l2GasUsed` accumulators. These accumulators will need to accurately reflect the gas consumption of the transaction prior to public function execution including state updates produced as part of private execution. +The sequencer will need to specify the intended size of the rollup (determined as part of the sequencer selection commitment phase) and use this value to calculate gas amortization. These values of amortized L1 and L2 gas will be added to the `l1GasUsed` and `l2GasUsed` accumulators. These accumulators, along with `dAGasUsed` will need to accurately reflect the gas consumption of the transaction prior to public function execution including state updates produced as part of private execution. -Any enqueued public function calls can be simulated by the sequencer to obtain an accurate gas profile of their execution. This simulation will enable the sequencer to compute the number of additional state updates to be made, the number of public function calls and the L2 gas consumption of each of those calls. If either the L1 or L2 gas limits are breached, simulation will identify where in the execution trace this takes place and so the sequencer will only need to perform iterations of the public VM and public kernel circuits for the calls that either partially or completely succeeded. This ensures that the sequencer is not forced to execute and prove circuits for which they will not be compensated. +Any enqueued public function calls can be simulated by the sequencer to obtain an accurate gas profile of their execution. This simulation will enable the sequencer to compute the number of additional state updates to be made, the number of public function calls and the L2 gas consumption of each of those calls. If any of the gas limits are breached, simulation will identify where in the execution trace this takes place and so the sequencer will only need to perform iterations of the public VM and public kernel circuits for the calls that either partially or completely succeeded. This ensures that the sequencer is not forced to execute and prove circuits for which they will not be compensated. -The public VM circuit can now be executed and proven until completion or until the gas limit is reached. Each invocation of the circuit will constrain it's reported usage of both L1 and L2 gas. +The public VM circuit can now be executed and proven until completion or until a gas limit is reached. Each invocation of the circuit will constrain it's reported usage of all types of gas. Public kernel circuit iterations will be executed for each public function call that actually took place. The combination of VM and kernel circuit executions will constrain the sequencer to correctly maintain the `TxContext` object such that: -1. The gas consumption claimed by the sequencer is correct for both L1 and L2 gas. +1. The gas consumption claimed by the sequencer is correct for all types of gas. 2. Any reverts claimed by the sequencer did indeed occur. 3. After such reverts no unnecessary gas consumption took place. @@ -216,14 +224,15 @@ Once transaction execution is complete, the sequencer will execute the fee distr ### Fee Distribution -Once public function execution has completed (or hit the gas limit), the fee distribution component is executed. This is a public function and will also need to be proven via the VM and public kernel circuits. The sequencer will have agency over which functions they are willing to accept and this will be part of the earlier transaction acceptance. Execution of this function is paid for using a fixed fee, specified by the gas values `l1FeeDistributionGas` and `l2FeeDistributionGas`. The sequencer will be able to verify that these are sufficient to cover the likely cost of calling this function. +Once public function execution has completed (or hit a gas limit), the fee distribution component is executed. This is a public function and will also need to be proven via the VM and public kernel circuits. The sequencer will have agency over which functions they are willing to accept and this will be part of the earlier transaction acceptance. Execution of this function is paid for using a fixed fee, specified by the gas values `l2FeeDistributionGas` and `dAFeeDistributionGas`. The sequencer will be able to verify that these are sufficient to cover the likely cost of calling this function. -The total fee taken by the sequencer is calculated from the values of consumed L1 and L2 gas and the `feeDistributionGas` and `feePerGas` values provided with the transaction. Any balance remaining must be refunded. +The total fee taken by the sequencer is calculated from the values of consumed L1, L2 and DA gas and the `feeDistributionGas` and `feePerGas` values provided with the transaction. Any balance remaining must be refunded. ``` -let actual_l1_cost = (tx_context.l1GasUsed + l1FeeDistributionGas) * tx_context.feePerL1Gas; +let actual_l1_cost = (tx_context.l1GasUsed) * tx_context.feePerL1Gas; let actual_l2_cost = (tx_context.l2GasUsed + l2FeeDistributionGas) * tx_context.feePerL2Gas; -let total_tx_cost = actual_l1_cost + actual_l2_cost; +let actual_da_cost = (tx_context.dAGasUsed + dAFeeDistributionGas) * tx_context.feePerDAGas; +let total_tx_cost = actual_l1_cost + actual_l2_cost + actual_da_cost; let refund = tx_context.totalFee - total_tx_cost; ``` @@ -232,12 +241,12 @@ let refund = tx_context.totalFee - total_tx_cost; To ensure clients are fairly charged for complete execution of their transactions, the public kernel circuit will verify: 1. The values of `base` gas applied to the transaction correctly corresponds to the size of rollup selected by the sequencer -2. The values of l1 and l2 gas accumulated within the `TxContext` object were accurate -3. The l1 and l2 gas limits specified in the transaction were respected -4. The correct values of `feePerL1Gas` and `feePerL2Gas` were used +2. The values of L1, L2 and DA gas accumulated within the `TxContext` object were accurate +3. All gas limits specified in the transaction were respected +4. The correct values of `feePerL1Gas`, `feePerL2Gas` and `feePerDAGas` were used 5. The correct public functions were called as part of the fee preparation and fee distribution components -Additionally, the merge and root rollup circuits will constrain that the value of `base` gas was consistent with the actual rollup size +Additionally, the merge and root rollup circuits will constrain that the value of `base` gas was consistent with the actual rollup size. ## Payment Methods @@ -257,14 +266,3 @@ This next example differs in that the refund is performed privately using partia In both of these examples the fee is effectively escrowed as part of the private portion of fee preparation. The enqueued public function is simply an instruction to increase the balance of the payment asset held by the fee payment contract. The sequencer should be able to inspect the public call instruction, consisting of contract address, function selector and arguments and be confident that this function will not fail. Provided the logic of the fee payment contract is defined correctly, once escrowed, the fee can't be modified by the user's transaction payload. This gives the sequencer the guarantee that they will be paid for the work they perform. Finally, the fee distribution function in either of these examples can be written such that the sequencer can be confident of success. This function simply needs to take the securely escrowed fee, compute the actual fee and subsequent refund before increasing the balance of the 2 parties within the payment asset. - - -### Paying Via L1 - -As a further option, it would be possible to facilitate payments directly from L1. Here, a mechanism similar to L1 -> L2 messaging would be used to transmit the payment to the sequencer. - -1. The user deposits the fee to the rollup contract and sends an L1 -> L2 message along the lines of 'L1 fee of $100 for transaction X'. -2. The user creates the transaction and executes the fee payment circuit with the message 'L1 fee of $100 for transaction X'. -3. The sequencer accepts the transaction and the L1 -> L2 message confirming that the funds have been made available on L1. -4. The sequencer executes the transaction and the fee distribution function taking their fee and distributing a refund on L2. -5. The L1 -> L2 message is consumed by the rollup transaction on L1. From b47d49def5b8ae9db3cab9afd1367c68b15cb766 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Bene=C5=A1?= Date: Wed, 13 Dec 2023 10:40:01 +0100 Subject: [PATCH 29/35] feat: enabling nullifier tree snapshot (#3670) In this PR I enable nullifier tree snapshot and I use that in the inclusion proofs test. --- .../src/e2e_inclusion_proofs_contract.test.ts | 29 +++++++++++-------- .../merkle_tree_snapshot_operations_facade.ts | 9 +++--- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/yarn-project/end-to-end/src/e2e_inclusion_proofs_contract.test.ts b/yarn-project/end-to-end/src/e2e_inclusion_proofs_contract.test.ts index 298ff392724..1feedd2864c 100644 --- a/yarn-project/end-to-end/src/e2e_inclusion_proofs_contract.test.ts +++ b/yarn-project/end-to-end/src/e2e_inclusion_proofs_contract.test.ts @@ -1,4 +1,4 @@ -import { AccountWallet, AztecAddress, CompleteAddress, Fr, PXE } from '@aztec/aztec.js'; +import { AccountWallet, AztecAddress, CompleteAddress, Fr, INITIAL_L2_BLOCK_NUM, PXE } from '@aztec/aztec.js'; import { InclusionProofsContract } from '@aztec/noir-contracts/types'; import { jest } from '@jest/globals'; @@ -111,10 +111,12 @@ describe('e2e_inclusion_proofs_contract', () => { }); it('note existence failure case', async () => { - // Owner of a note + // Owner of a note - ignored in the contract since the note won't be found and the spare random note commitment + // will be used instead const owner = AztecAddress.random(); - const blockNumber = await pxe.getBlockNumber(); + // Choose random block number between deployment and current block number to test archival node + const blockNumber = await getRandomBlockNumberSinceDeployment(); const randomNoteCommitment = Fr.random(); await expect( contract.methods.test_note_inclusion_proof(owner, blockNumber, randomNoteCommitment).send().wait(), @@ -122,15 +124,15 @@ describe('e2e_inclusion_proofs_contract', () => { }); it('proves an existence of a public value in private context', async () => { - // Chose random block number between deployment and current block number to test archival node + // Choose random block number between deployment and current block number to test archival node const blockNumber = await getRandomBlockNumberSinceDeployment(); await contract.methods.test_public_value_inclusion_proof(publicValue, blockNumber).send().wait(); }); it('public value existence failure case', async () => { - // Chose random block number between deployment and current block number to test archival node - const blockNumber = await getRandomBlockNumberSinceDeployment(); + // Choose random block number between first block and current block number to test archival node + const blockNumber = await getRandomBlockNumber(); const randomPublicValue = Fr.random(); await expect( @@ -139,9 +141,8 @@ describe('e2e_inclusion_proofs_contract', () => { }); it('proves existence of a nullifier in private context', async () => { - // TODO(#3535): Test this at "random" block to test archival node. This is currently not possible because of - // issue https://github.com/AztecProtocol/aztec-packages/issues/3535 - const blockNumber = await pxe.getBlockNumber(); + // Choose random block number between deployment and current block number to test archival node + const blockNumber = await getRandomBlockNumberSinceDeployment(); const block = await pxe.getBlock(blockNumber); const nullifier = block?.newNullifiers[0]; @@ -149,9 +150,8 @@ describe('e2e_inclusion_proofs_contract', () => { }); it('nullifier existence failure case', async () => { - // TODO(#3535): Test this at "random" block to test archival node. This is currently not possible because of - // issue https://github.com/AztecProtocol/aztec-packages/issues/3535 - const blockNumber = await pxe.getBlockNumber(); + // Choose random block number between first block and current block number to test archival node + const blockNumber = await getRandomBlockNumber(); const randomNullifier = Fr.random(); await expect( @@ -163,4 +163,9 @@ describe('e2e_inclusion_proofs_contract', () => { const currentBlockNumber = await pxe.getBlockNumber(); return deploymentBlockNumber + Math.floor(Math.random() * (currentBlockNumber - deploymentBlockNumber)); }; + + const getRandomBlockNumber = async () => { + const currentBlockNumber = await pxe.getBlockNumber(); + return deploymentBlockNumber + Math.floor(Math.random() * (currentBlockNumber - INITIAL_L2_BLOCK_NUM)); + }; }); diff --git a/yarn-project/world-state/src/merkle-tree/merkle_tree_snapshot_operations_facade.ts b/yarn-project/world-state/src/merkle-tree/merkle_tree_snapshot_operations_facade.ts index 450b6c5bca8..54308855517 100644 --- a/yarn-project/world-state/src/merkle-tree/merkle_tree_snapshot_operations_facade.ts +++ b/yarn-project/world-state/src/merkle-tree/merkle_tree_snapshot_operations_facade.ts @@ -49,9 +49,9 @@ export class MerkleTreeSnapshotOperationsFacade implements MerkleTreeOperations return snapshot.getLeafValue(BigInt(index)); } - getPreviousValueIndex( - _treeId: MerkleTreeId.NULLIFIER_TREE, - _value: bigint, + async getPreviousValueIndex( + treeId: MerkleTreeId.NULLIFIER_TREE, + value: bigint, ): Promise< | { /** @@ -65,7 +65,8 @@ export class MerkleTreeSnapshotOperationsFacade implements MerkleTreeOperations } | undefined > { - return Promise.reject(new Error('Snapshots not implemented for nullifier tree')); + const snapshot = (await this.#getTreeSnapshot(treeId)) as IndexedTreeSnapshot; + return snapshot.findIndexOfPreviousKey(value); } async getSiblingPath(treeId: MerkleTreeId, index: bigint): Promise> { From e749daa7f1e9e34cad93d64e76e04d2525c6f458 Mon Sep 17 00:00:00 2001 From: PhilWindle <60546371+PhilWindle@users.noreply.github.com> Date: Wed, 13 Dec 2023 09:55:17 +0000 Subject: [PATCH 30/35] chore: Reduced spam logging in archiver (#3671) This PR reduces the redundant logging in the archiver. # Checklist: Remove the checklist to signal you've completed it. Enable auto-merge if the PR is ready to merge. - [ ] If the pull request requires a cryptography review (e.g. cryptographic algorithm implementations) I have added the 'crypto' tag. - [ ] I have reviewed my diff in github, line by line and removed unexpected formatting changes, testing logs, or commented-out code. - [ ] Every change is related to the PR description. - [ ] I have [linked](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue) this pull request to relevant issues (if any exist). --- .../archiver/src/archiver/archiver.ts | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/yarn-project/archiver/src/archiver/archiver.ts b/yarn-project/archiver/src/archiver/archiver.ts index 5f3c855d224..e8860ceac92 100644 --- a/yarn-project/archiver/src/archiver/archiver.ts +++ b/yarn-project/archiver/src/archiver/archiver.ts @@ -197,20 +197,25 @@ export class Archiver implements L2BlockSource, L2LogsSource, ContractDataSource // TODO (#717): optimize this - there could be messages in confirmed that are also in pending. // Or messages in pending that are also cancelled in the same block. No need to modify storage for them. - // Store l1 to l2 messages - this.log('Adding pending l1 to l2 messages to store'); - await this.store.addPendingL1ToL2Messages(retrievedPendingL1ToL2Messages.retrievedData); - // remove cancelled messages from the pending message store: - this.log('Removing pending l1 to l2 messages from store where messages were cancelled'); - await this.store.cancelPendingL1ToL2Messages(retrievedCancelledL1ToL2Messages.retrievedData); + + if (retrievedPendingL1ToL2Messages.retrievedData.length) { + // Store l1 to l2 messages + this.log(`Adding ${retrievedPendingL1ToL2Messages.retrievedData.length} pending l1 to l2 messages to store`); + await this.store.addPendingL1ToL2Messages(retrievedPendingL1ToL2Messages.retrievedData); + } + + if (retrievedCancelledL1ToL2Messages.retrievedData.length) { + // remove cancelled messages from the pending message store: + this.log( + `Removing ${retrievedCancelledL1ToL2Messages.retrievedData.length} pending l1 to l2 messages from store where messages were cancelled`, + ); + await this.store.cancelPendingL1ToL2Messages(retrievedCancelledL1ToL2Messages.retrievedData); + } // ********** Events that are processed per block ********** // Read all data from chain and then write to our stores at the end const nextExpectedL2BlockNum = BigInt((await this.store.getBlockNumber()) + 1); - this.log( - `Retrieving chain state from L1 block: ${this.nextL2BlockFromL1Block}, next expected l2 block number: ${nextExpectedL2BlockNum}`, - ); const retrievedBlocks = await retrieveBlocks( this.publicClient, this.rollupAddress, From 0888c05098c94151462e30528a32322ae793d9ac Mon Sep 17 00:00:00 2001 From: spypsy Date: Wed, 13 Dec 2023 13:06:18 +0000 Subject: [PATCH 31/35] chore(ci): combine deploy / release jobs + canary update (#3610) - Combine all release / deploy jobs into 1 to simplify CI - Add canary flow that tests NPM releases are working before tagging them as `latest` - remove old canary code - add `DRY_DEPLOY` functionality to terraform script (`terraform plan`) Closes #3563 Closes #3579 --- .circleci/config.yml | 82 +++++-------------- build-system/scripts/deploy_npm | 28 +++++-- build-system/scripts/deploy_terraform | 6 +- build_manifest.yml | 13 --- .../token_portal/typescript_glue_code.md | 4 +- .../tutorials/uniswap/typescript_glue_code.md | 2 +- yarn-project/canary/.eslintrc.cjs | 1 - yarn-project/canary/.gitignore | 1 - yarn-project/canary/Dockerfile | 37 --------- yarn-project/canary/Dockerfile.build | 9 -- yarn-project/canary/README.md | 15 ---- .../canary/jest.integration.config.json | 13 --- yarn-project/canary/package.json | 50 ----------- .../canary/scripts/docker-compose-browser.yml | 9 -- .../canary/scripts/docker-compose.yml | 9 -- .../canary/scripts/extract_packages.sh | 11 --- yarn-project/canary/scripts/run_tests | 27 ------ .../canary/scripts/update_packages.sh | 24 ------ .../canary/src/aztec_js_browser.test.ts | 25 ------ yarn-project/canary/src/cli.test.ts | 14 ---- .../src/uniswap_trade_on_l1_from_l2.test.ts | 36 -------- yarn-project/canary/src/web/index.html | 10 --- yarn-project/canary/tsconfig.json | 42 ---------- yarn-project/deploy_npm.sh | 12 ++- .../end-to-end/scripts/setup_canary.sh | 62 -------------- .../src/uniswap_trade_on_l1_from_l2.test.ts | 2 + yarn-project/package.json | 3 +- yarn-project/tsconfig.json | 1 - yarn-project/yarn.lock | 43 +--------- 29 files changed, 63 insertions(+), 528 deletions(-) delete mode 100644 yarn-project/canary/.eslintrc.cjs delete mode 100644 yarn-project/canary/.gitignore delete mode 100644 yarn-project/canary/Dockerfile delete mode 100644 yarn-project/canary/Dockerfile.build delete mode 100644 yarn-project/canary/README.md delete mode 100644 yarn-project/canary/jest.integration.config.json delete mode 100644 yarn-project/canary/package.json delete mode 100644 yarn-project/canary/scripts/docker-compose-browser.yml delete mode 100644 yarn-project/canary/scripts/docker-compose.yml delete mode 100755 yarn-project/canary/scripts/extract_packages.sh delete mode 100755 yarn-project/canary/scripts/run_tests delete mode 100755 yarn-project/canary/scripts/update_packages.sh delete mode 100644 yarn-project/canary/src/aztec_js_browser.test.ts delete mode 100644 yarn-project/canary/src/cli.test.ts delete mode 100644 yarn-project/canary/src/uniswap_trade_on_l1_from_l2.test.ts delete mode 100644 yarn-project/canary/src/web/index.html delete mode 100644 yarn-project/canary/tsconfig.json delete mode 100755 yarn-project/end-to-end/scripts/setup_canary.sh diff --git a/.circleci/config.yml b/.circleci/config.yml index fb0ea6e4b9a..6580d59be53 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -904,8 +904,8 @@ jobs: name: "Assemble benchmark summary from uploaded logs" command: ./scripts/ci/assemble_e2e_benchmark.sh - # Release jobs. - release-npm: + # Deploy & release jobs. + deploy-and-release: machine: image: ubuntu-2204:2023.07.2 resource_class: medium @@ -913,68 +913,45 @@ jobs: - *checkout - *setup_env - run: - name: "yarn-project" + name: "Release to dockerhub" + command: | + should_release || exit 0 + deploy_dockerhub noir + deploy_dockerhub aztec-sandbox + deploy_dockerhub cli + deploy_dockerhub aztec-faucet + deploy_dockerhub mainnet-fork + - run: + name: "Release canary to NPM: yarn-project" + command: | + should_release || exit 0 + yarn-project/deploy_npm.sh canary + - run: + name: "Release latest to NPM: yarn-project" command: | should_release || exit 0 yarn-project/deploy_npm.sh latest - run: - name: "l1-contracts" + name: "Release canary to NPM: l1-contracts" command: | should_release || exit 0 - deploy_npm l1-contracts - - release-dockerhub: - machine: - image: ubuntu-2204:2023.07.2 - resource_class: medium - steps: - - *checkout - - *setup_env + deploy_npm l1-contracts canary - run: - name: "Release to dockerhub" + name: "Release latest to NPM: l1-contracts" command: | should_release || exit 0 - deploy_dockerhub noir - deploy_dockerhub aztec-sandbox - deploy_dockerhub cli - deploy_dockerhub aztec-faucet - deploy_dockerhub mainnet-fork - - # Deploy jobs. - deploy-mainnet-fork: - machine: - image: ubuntu-2204:2023.07.2 - resource_class: medium - steps: - - *checkout - - *setup_env + deploy_npm l1-contracts latest - run: name: "Deploy mainnet fork" command: | should_deploy || exit 0 deploy mainnet-fork - - deploy-contracts: - machine: - image: ubuntu-2204:2023.07.2 - resource_class: medium - steps: - - *checkout - - *setup_env - run: name: "Deploy L1 contracts to mainnet fork" working_directory: l1-contracts command: | should_deploy || exit 0 ./scripts/ci_deploy_contracts.sh - - deploy-devnet: - machine: - image: ubuntu-2204:2023.07.2 - resource_class: medium - steps: - - *checkout - - *setup_env - run: name: "Deploy devnet to AWS" command: | @@ -1213,19 +1190,4 @@ workflows: <<: *defaults # Production releases. - - release-dockerhub: *defaults_deploy - - release-npm: *defaults_deploy - - # Production deployment. - - deploy-mainnet-fork: - requires: - - release-dockerhub - <<: *defaults_deploy - - deploy-contracts: - requires: - - deploy-mainnet-fork - <<: *defaults_deploy - - deploy-devnet: - requires: - - deploy-contracts - <<: *defaults_deploy + - deploy-and-release: *defaults_deploy \ No newline at end of file diff --git a/build-system/scripts/deploy_npm b/build-system/scripts/deploy_npm index 16df5a156d0..22b5a63d9a7 100755 --- a/build-system/scripts/deploy_npm +++ b/build-system/scripts/deploy_npm @@ -3,7 +3,8 @@ set -eu readonly REPOSITORY=$1 -readonly STANDALONE=${2:-} +readonly DIST_TAG=${2:-"latest"} +readonly STANDALONE=${3:-} # Only publish tagged commits to npm. [ -n "${COMMIT_TAG:-}" ] || { echo "Will only publish tagged commits to npm. Skipping." && exit 0; } @@ -12,7 +13,7 @@ extract_repo $REPOSITORY /usr/src project cd project/src/$(query_manifest relativeProjectDir $REPOSITORY) -echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" > .npmrc +echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >.npmrc VERSION=$(extract_tag_version $REPOSITORY true) @@ -21,14 +22,17 @@ TAG=$(echo "$VERSION" | grep -oP ".*-\K(.*)(?=\.\d+)" || true) TAG_ARG="" if [ -n "$TAG" ]; then TAG_ARG="--tag $TAG" +else + TAG_ARG="--tag $DIST_TAG" + TAG=$DIST_TAG fi -readonly PUBLISHED_VERSION=$(npm show . version ${TAG_ARG:-} 2> /dev/null) +readonly PUBLISHED_VERSION=$(npm show . version ${TAG_ARG:-} 2>/dev/null) readonly HIGHER_VERSION=$(npx semver ${VERSION} ${PUBLISHED_VERSION} | tail -1) # If there is already a published package equal to given version, assume this is a re-run of a deploy, and early out. if [ "$VERSION" == "$PUBLISHED_VERSION" ]; then - echo "Tagged version $VERSION is equal to published version $PUBLISHED_VERSION. Skipping publish." + echo "Tagged ${DIST_TAG:+ $DIST_TAG}version $VERSION is equal to published ${DIST_TAG:+ $DIST_TAG}version $PUBLISHED_VERSION. Skipping publish." exit 0 fi @@ -40,18 +44,26 @@ fi # Update the package version in package.json. TMP=$(mktemp) -jq --arg v $VERSION '.version = $v' package.json > $TMP && mv $TMP package.json +jq --arg v $VERSION '.version = $v' package.json >$TMP && mv $TMP package.json if [ -z "$STANDALONE" ]; then # Update each dependent @aztec package version in package.json. for PKG in $(jq --raw-output ".dependencies | keys[] | select(contains(\"@aztec/\"))" package.json); do - jq --arg v $VERSION ".dependencies[\"$PKG\"] = \$v" package.json > $TMP && mv $TMP package.json + jq --arg v $VERSION ".dependencies[\"$PKG\"] = \$v" package.json >$TMP && mv $TMP package.json done fi # Publish if we have a commit tag -if [ "$DRY_DEPLOY" -eq 1 ] ; then +if [ "$DRY_DEPLOY" -eq 1 ]; then npm publish --dry-run $TAG_ARG --access public else - npm publish $TAG_ARG --access public + # npm publish $TAG_ARG --access public + # Check if version exists + if npm view "$PACKAGE_NAME@$VERSION" version >/dev/null 2>&1; then + # Tag the existing version + npm dist-tag add $PACKAGE_NAME@$VERSION $TAG + else + # Publish new version + npm publish $TAG_ARG --access public + fi fi diff --git a/build-system/scripts/deploy_terraform b/build-system/scripts/deploy_terraform index b81c4d3f4b2..f5ff4dc810b 100755 --- a/build-system/scripts/deploy_terraform +++ b/build-system/scripts/deploy_terraform @@ -43,4 +43,8 @@ for RESOURCE in $TO_TAINT; do terraform taint $RESOURCE || true done -terraform apply -input=false -auto-approve +if [ "$DRY_DEPLOY" -eq 1 ]; then + terraform plan -input=false -auto-approve +else + terraform apply -input=false -auto-approve +fi diff --git a/build_manifest.yml b/build_manifest.yml index 43bce1a4071..00309fad698 100644 --- a/build_manifest.yml +++ b/build_manifest.yml @@ -174,19 +174,6 @@ boxes-token: dependencies: - aztec-sandbox -canary-build: - buildDir: yarn-project - projectDir: yarn-project/canary - dockerfile: Dockerfile.build - dependencies: - - yarn-project - -canary: - buildDir: yarn-project - projectDir: yarn-project/canary - dependencies: - - yarn-project - end-to-end: buildDir: yarn-project projectDir: yarn-project/end-to-end diff --git a/docs/docs/dev_docs/tutorials/token_portal/typescript_glue_code.md b/docs/docs/dev_docs/tutorials/token_portal/typescript_glue_code.md index 8775c14955a..1bd59d9a331 100644 --- a/docs/docs/dev_docs/tutorials/token_portal/typescript_glue_code.md +++ b/docs/docs/dev_docs/tutorials/token_portal/typescript_glue_code.md @@ -116,7 +116,7 @@ describe('e2e_cross_chain_messaging', () => { let outbox: any; beforeEach(async () => { - logger = createDebugLogger('aztec:canary_uniswap'); + logger = createDebugLogger('aztec:e2e_uniswap'); const pxe = createPXEClient(PXE_URL); await waitForSandbox(pxe); const wallets = await getSandboxAccountsWallets(pxe); @@ -165,7 +165,7 @@ This fetches the wallets from the sandbox and deploys our cross chain harness on ```bash cd packages/src -DEBUG='aztec:canary_uniswap' yarn test +DEBUG='aztec:e2e_uniswap' yarn test ``` ### Error handling diff --git a/docs/docs/dev_docs/tutorials/uniswap/typescript_glue_code.md b/docs/docs/dev_docs/tutorials/uniswap/typescript_glue_code.md index ff965fa77d7..9ac161a01eb 100644 --- a/docs/docs/dev_docs/tutorials/uniswap/typescript_glue_code.md +++ b/docs/docs/dev_docs/tutorials/uniswap/typescript_glue_code.md @@ -115,7 +115,7 @@ const hdAccount = mnemonicToAccount(MNEMONIC); const expectedForkBlockNumber = 17514288; #include_code uniswap_l1_l2_test_setup_const yarn-project/end-to-end/src/shared/uniswap_l1_l2.ts raw -#include_code uniswap_setup yarn-project/canary/src/uniswap_trade_on_l1_from_l2.test.ts raw +#include_code uniswap_setup yarn-project/end-to-end/src/uniswap_trade_on_l1_from_l2.test.ts raw #include_code uniswap_l1_l2_test_beforeAll yarn-project/end-to-end/src/shared/uniswap_l1_l2.ts raw ``` diff --git a/yarn-project/canary/.eslintrc.cjs b/yarn-project/canary/.eslintrc.cjs deleted file mode 100644 index e659927475c..00000000000 --- a/yarn-project/canary/.eslintrc.cjs +++ /dev/null @@ -1 +0,0 @@ -module.exports = require('@aztec/foundation/eslint'); diff --git a/yarn-project/canary/.gitignore b/yarn-project/canary/.gitignore deleted file mode 100644 index 9dea6a91bc6..00000000000 --- a/yarn-project/canary/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tsconfig.tsbuildinfo \ No newline at end of file diff --git a/yarn-project/canary/Dockerfile b/yarn-project/canary/Dockerfile deleted file mode 100644 index 3856f455c9f..00000000000 --- a/yarn-project/canary/Dockerfile +++ /dev/null @@ -1,37 +0,0 @@ -FROM node:18.19.0-alpine AS builder - -RUN apk update && apk add --no-cache bash jq curl - -COPY ./end-to-end /usr/src/end-to-end -COPY ./canary /usr/src/canary - -# Setup & Build end-to-end package -WORKDIR /usr/src/end-to-end -# Extract canary @aztec dependencies -RUN ../canary/scripts/extract_packages.sh ../canary/package.json > ./target_pkgs.txt -# Update end-to-end dependencies with target version -RUN ./scripts/setup_canary.sh ./target_pkgs.txt package.json -RUN rm ./target_pkgs.txt -# yarn install & build to apply changes (canary packages) -RUN yarn && yarn build - -# Install & build canary packages -WORKDIR /usr/src/canary -RUN ./scripts/update_packages.sh canary ../end-to-end/ -RUN yarn && yarn build - -FROM node:18.19.0-alpine -RUN apk update && apk add --no-cache udev ttf-freefont chromium bash -ENV CHROME_BIN="/usr/bin/chromium-browser" PUPPETEER_SKIP_CHROMIUM_DOWNLOAD="true" - -COPY --from=builder /usr/src/end-to-end /usr/src/end-to-end -COPY --from=builder /usr/src/canary /usr/src/canary - -WORKDIR /usr/src/canary -# Copy browser script -RUN cp ../end-to-end/scripts/start_e2e_ci_browser.sh ./scripts/start_e2e_ci_browser.sh -RUN chmod +x scripts/start_e2e_ci_browser.sh - -RUN cp ./node_modules/@aztec/aztec.js/dest/main.js src/web/ - -ENTRYPOINT ["yarn", "test"] diff --git a/yarn-project/canary/Dockerfile.build b/yarn-project/canary/Dockerfile.build deleted file mode 100644 index fadd8daaa8b..00000000000 --- a/yarn-project/canary/Dockerfile.build +++ /dev/null @@ -1,9 +0,0 @@ -FROM 278380418400.dkr.ecr.eu-west-2.amazonaws.com/yarn-project AS builder -WORKDIR /usr/src/yarn-project/canary -# Productionify. See comment in yarn-project-base/Dockerfile. -RUN yarn cache clean && yarn workspaces focus --production - -FROM node:18.19.0-alpine -COPY --from=builder /usr/src /usr/src -WORKDIR /usr/src/yarn-project/canary -ENTRYPOINT ["yarn", "test"] \ No newline at end of file diff --git a/yarn-project/canary/README.md b/yarn-project/canary/README.md deleted file mode 100644 index 3ff4851a9ec..00000000000 --- a/yarn-project/canary/README.md +++ /dev/null @@ -1,15 +0,0 @@ -# Canary - -This package is designed for running a comprehensive end to end test of the system using deployed artifacts. It is built and executed after the deployment of artifacts to npm and dockerhub. - -## Development - -If you have an instance of the aztec-sandbox running, then you can simply run `yarn test uniswap` to execute the test. - -To build and execute the test: - -`export FORK_BLOCK_NUMBER=17514288` -`export FORK_URL='https://mainnet.infura.io/v3/9928b52099854248b3a096be07a6b23c'` -`docker build --build-arg COMMIT_TAG= .` -`cd ./scripts` -`docker-compose up` diff --git a/yarn-project/canary/jest.integration.config.json b/yarn-project/canary/jest.integration.config.json deleted file mode 100644 index d9dc9cf2dbb..00000000000 --- a/yarn-project/canary/jest.integration.config.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "preset": "ts-jest/presets/default-esm", - "globals": { - "ts-jest": { - "useESM": true - } - }, - "moduleNameMapper": { - "^(\\.{1,2}/.*)\\.js$": "$1" - }, - "testRegex": "./src/.*\\.test\\.ts$", - "rootDir": "./src" -} diff --git a/yarn-project/canary/package.json b/yarn-project/canary/package.json deleted file mode 100644 index dc95e326550..00000000000 --- a/yarn-project/canary/package.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "name": "@aztec/canary", - "version": "0.0.0", - "type": "module", - "exports": "./dest/index.js", - "license": "Apache-2.0", - "scripts": { - "build": "yarn clean && tsc -b", - "build:dev": "tsc -b --watch", - "clean": "rm -rf ./dest .tsbuildinfo", - "formatting": "run -T prettier --check ./src && run -T eslint ./src", - "formatting:fix": "run -T prettier -w ./src", - "test": "DEBUG='aztec:*' NODE_NO_WARNINGS=1 node --experimental-vm-modules $(yarn bin jest) --runInBand --passWithNoTests --testTimeout=15000" - }, - "jest": { - "preset": "ts-jest/presets/default-esm", - "moduleNameMapper": { - "^(\\.{1,2}/.*)\\.js$": "$1" - }, - "testRegex": "./src/.*\\.test\\.ts$", - "rootDir": "./src" - }, - "dependencies": { - "@aztec/aztec.js": "workspace:^", - "@aztec/cli": "workspace:^", - "@aztec/end-to-end": "workspace:^", - "@aztec/ethereum": "workspace:^", - "@aztec/l1-artifacts": "workspace:^", - "@aztec/noir-contracts": "workspace:^", - "@jest/globals": "^29.5.0", - "@types/jest": "^29.5.0", - "@types/koa-static": "^4.0.2", - "@types/node": "^18.7.23", - "abitype": "^0.9.8", - "jest": "^29.5.0", - "koa": "^2.14.2", - "koa-static": "^5.0.0", - "ts-jest": "^29.1.0", - "ts-node": "^10.9.1", - "tslib": "^2.4.0", - "typescript": "^5.0.4", - "viem": "^1.2.5" - }, - "files": [ - "dest", - "src", - "!*.test.*" - ], - "types": "./dest/index.d.ts" -} diff --git a/yarn-project/canary/scripts/docker-compose-browser.yml b/yarn-project/canary/scripts/docker-compose-browser.yml deleted file mode 100644 index 98d8a7d9625..00000000000 --- a/yarn-project/canary/scripts/docker-compose-browser.yml +++ /dev/null @@ -1,9 +0,0 @@ -version: '3' -services: - canary: - image: aztecprotocol/canary:latest - environment: - ETHEREUM_HOST: http://ethereum:8545 - CHAIN_ID: 31337 - PXE_URL: http://aztec:8080 - command: ['./scripts/start_e2e_ci_browser.sh', './src/aztec_js_browser.test.ts'] diff --git a/yarn-project/canary/scripts/docker-compose.yml b/yarn-project/canary/scripts/docker-compose.yml deleted file mode 100644 index 74a28452a07..00000000000 --- a/yarn-project/canary/scripts/docker-compose.yml +++ /dev/null @@ -1,9 +0,0 @@ -version: '3' -services: - canary: - image: aztecprotocol/canary:latest - environment: - ETHEREUM_HOST: http://ethereum:8545 - CHAIN_ID: 31337 - PXE_URL: http://aztec:8080 - command: ${TEST:-./src/cli.test.ts} diff --git a/yarn-project/canary/scripts/extract_packages.sh b/yarn-project/canary/scripts/extract_packages.sh deleted file mode 100755 index 78255e01b24..00000000000 --- a/yarn-project/canary/scripts/extract_packages.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env bash - -FILE=$1 - -# Capture the output of the jq command in a Bash array -mapfile -t TARGET_PKGS < <(jq -r '.dependencies | keys[] | select(startswith("@aztec/") and . != "@aztec/end-to-end")' $FILE) - -# Loop through the array and print each element on a new line -for pkg in "${TARGET_PKGS[@]}"; do - echo "$pkg" -done \ No newline at end of file diff --git a/yarn-project/canary/scripts/run_tests b/yarn-project/canary/scripts/run_tests deleted file mode 100755 index 6bde0b451a4..00000000000 --- a/yarn-project/canary/scripts/run_tests +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env bash -# This script is used to run an e2e test in CI (see config.yml and cond_spot_run_tests). -# It sets a few environment variables used inside the docker-compose.yml, pulls images, and runs docker-compose. -[ -n "${BUILD_SYSTEM_DEBUG:-}" ] && set -x # conditionally trace -set -eu - -export TEST=$1 -export IMAGE=${2:-canary} -export COMPOSE_FILE=${3:-./scripts/docker-compose.yml} -: -# if test name ends with uniswap_trade_on_l1_from_l2.test.ts, use the forked mainnet -if [[ "$TEST" == *"uniswap_trade_on_l1_from_l2"* ]]; then - export FORK_URL=https://mainnet.infura.io/v3/9928b52099854248b3a096be07a6b23c - export FORK_BLOCK_NUMBER=17514288 -fi - -# Login to ECR. -ecr_login - -export PATH="$PATH:$(git rev-parse --show-toplevel)/build-system/scripts" -IMAGE_URI=$(calculate_image_uri $IMAGE) -retry docker pull $IMAGE_URI -retry docker tag $IMAGE_URI aztecprotocol/canary:latest - -export SANDBOX_VERSION=canary -docker-compose -f ../aztec-sandbox/docker-compose.yml -f $COMPOSE_FILE rm -f -docker-compose -f ../aztec-sandbox/docker-compose.yml -f $COMPOSE_FILE up --exit-code-from canary diff --git a/yarn-project/canary/scripts/update_packages.sh b/yarn-project/canary/scripts/update_packages.sh deleted file mode 100755 index 085dfd217bd..00000000000 --- a/yarn-project/canary/scripts/update_packages.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env bash -set -eu - -DIST_TAG=$1 -E2E_DIR=$2 - -if [ -z "$DIST_TAG" ]; then - echo "No dist tag provided." - exit 0 -fi - -echo "Updating Aztec dependencies to tag $DIST_TAG" - -TMP=$(mktemp) -# Update NPM dependencies to dist tag -for PKG in $(jq --raw-output ".dependencies | keys[] | select(contains(\"@aztec/\") and (. != \"@aztec/end-to-end\"))" package.json); do - jq --arg v $DIST_TAG ".dependencies[\"$PKG\"] = \$v" package.json >$TMP && mv $TMP package.json -done - -# Update end-to-end to local dependency -TMP=$(mktemp) -jq --arg dir "file:$E2E_DIR" '.dependencies["@aztec/end-to-end"] = $dir' package.json >$TMP && mv $TMP package.json - -jq ".references = []" tsconfig.json >$TMP && mv $TMP tsconfig.json diff --git a/yarn-project/canary/src/aztec_js_browser.test.ts b/yarn-project/canary/src/aztec_js_browser.test.ts deleted file mode 100644 index 3db3febdb67..00000000000 --- a/yarn-project/canary/src/aztec_js_browser.test.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { createDebugLogger, fileURLToPath } from '@aztec/aztec.js'; -import { browserTestSuite } from '@aztec/end-to-end'; - -import Koa from 'koa'; -import serve from 'koa-static'; -import path, { dirname } from 'path'; - -const __filename = fileURLToPath(import.meta.url); -const __dirname = dirname(__filename); -const PORT = 3000; - -const logger = createDebugLogger('aztec:canary_aztec.js:web'); -const pageLogger = createDebugLogger('aztec:canary_aztec.js:web:page'); - -const setupApp = () => { - const app = new Koa(); - app.use(serve(path.resolve(__dirname, './web'))); - const server = app.listen(PORT, () => { - logger(`Server started at http://localhost:${PORT}`); - }); - - return server; -}; - -browserTestSuite(setupApp, pageLogger); diff --git a/yarn-project/canary/src/cli.test.ts b/yarn-project/canary/src/cli.test.ts deleted file mode 100644 index ef5e9184789..00000000000 --- a/yarn-project/canary/src/cli.test.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { createDebugLogger, createPXEClient, makeFetch, waitForSandbox } from '@aztec/aztec.js'; -import { cliTestSuite } from '@aztec/end-to-end'; - -const { PXE_URL = 'http://localhost:8080' } = process.env; - -const debug = createDebugLogger('aztec:canary_cli'); - -const setupRPC = async () => { - const pxe = createPXEClient(PXE_URL, makeFetch([1, 2, 3, 4, 5], true)); - await waitForSandbox(pxe); - return pxe; -}; - -cliTestSuite('CLI Canary', setupRPC, () => Promise.resolve(), debug, PXE_URL); diff --git a/yarn-project/canary/src/uniswap_trade_on_l1_from_l2.test.ts b/yarn-project/canary/src/uniswap_trade_on_l1_from_l2.test.ts deleted file mode 100644 index ff00b4f92f9..00000000000 --- a/yarn-project/canary/src/uniswap_trade_on_l1_from_l2.test.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { createDebugLogger, createPXEClient, getSandboxAccountsWallets, waitForSandbox } from '@aztec/aztec.js'; -import { UniswapSetupContext, uniswapL1L2TestSuite } from '@aztec/end-to-end'; - -import { createPublicClient, createWalletClient, http } from 'viem'; -import { mnemonicToAccount } from 'viem/accounts'; -import { foundry } from 'viem/chains'; - -const { PXE_URL = 'http://localhost:8080', ETHEREUM_HOST = 'http://localhost:8545' } = process.env; -export const MNEMONIC = 'test test test test test test test test test test test junk'; -const hdAccount = mnemonicToAccount(MNEMONIC); -// This tests works on forked mainnet, configured on the CI. -const EXPECTED_FORKED_BLOCK = 17514288; - -// docs:start:uniswap_setup -const setup = async (): Promise => { - const logger = createDebugLogger('aztec:canary_uniswap'); - const pxe = createPXEClient(PXE_URL); - await waitForSandbox(pxe); - - const walletClient = createWalletClient({ - account: hdAccount, - chain: foundry, - transport: http(ETHEREUM_HOST), - }); - const publicClient = createPublicClient({ - chain: foundry, - transport: http(ETHEREUM_HOST), - }); - - const [ownerWallet, sponsorWallet] = await getSandboxAccountsWallets(pxe); - - return { pxe, logger, publicClient, walletClient, ownerWallet, sponsorWallet }; -}; -// docs:end:uniswap_setup - -uniswapL1L2TestSuite(setup, () => Promise.resolve(), EXPECTED_FORKED_BLOCK); diff --git a/yarn-project/canary/src/web/index.html b/yarn-project/canary/src/web/index.html deleted file mode 100644 index 97e7d022731..00000000000 --- a/yarn-project/canary/src/web/index.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - diff --git a/yarn-project/canary/tsconfig.json b/yarn-project/canary/tsconfig.json deleted file mode 100644 index a80b4f11c64..00000000000 --- a/yarn-project/canary/tsconfig.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "compilerOptions": { - "outDir": "dest", - "rootDir": "src", - "target": "es2020", - "lib": ["dom", "esnext", "es2017.object"], - "module": "NodeNext", - "moduleResolution": "NodeNext", - "strict": true, - "declaration": true, - "allowSyntheticDefaultImports": true, - "esModuleInterop": true, - "downlevelIteration": true, - "inlineSourceMap": true, - "declarationMap": true, - "importHelpers": true, - "resolveJsonModule": true, - "composite": true, - "skipLibCheck": true - }, - "references": [ - { - "path": "../aztec.js" - }, - { - "path": "../cli" - }, - { - "path": "../end-to-end" - }, - { - "path": "../ethereum" - }, - { - "path": "../l1-artifacts" - }, - { - "path": "../noir-contracts" - } - ], - "include": ["src"] -} diff --git a/yarn-project/deploy_npm.sh b/yarn-project/deploy_npm.sh index f092e6fe106..19c58b80d6c 100755 --- a/yarn-project/deploy_npm.sh +++ b/yarn-project/deploy_npm.sh @@ -23,8 +23,14 @@ function deploy_package() { VERSION=$(extract_tag_version $REPOSITORY false) echo "Deploying $REPOSITORY $VERSION $DIST_TAG" - if [ -n "$DIST_TAG" ]; then + # If the commit tag itself has a dist-tag (e.g. v2.1.0-testnet.123), extract the dist-tag. + TAG=$(echo "$VERSION" | grep -oP ".*-\K(.*)(?=\.\d+)" || true) + TAG_ARG="" + if [ -n "$TAG" ]; then + TAG_ARG="--tag $TAG" + else TAG_ARG="--tag $DIST_TAG" + TAG=$DIST_TAG fi PUBLISHED_VERSION=$(npm show . version ${TAG_ARG:-} 2>/dev/null) || true @@ -32,7 +38,7 @@ function deploy_package() { # Check if there is already a published package equal to given version, assume this is a re-run of a deploy if [ "$VERSION" == "$PUBLISHED_VERSION" ]; then - echo "Tagged ${DIST_TAG:+ $DIST_TAG}version $VERSION is equal to published ${DIST_TAG:+ $DIST_TAG}version $PUBLISHED_VERSION." + echo "Tagged $TAG version $VERSION is equal to published $TAG version $PUBLISHED_VERSION." echo "Skipping publish." exit 0 fi @@ -61,7 +67,7 @@ function deploy_package() { # Check if version exists if npm view "$PACKAGE_NAME@$VERSION" version >/dev/null 2>&1; then # Tag the existing version - npm dist-tag add $PACKAGE_NAME@$VERSION $DIST_TAG + npm dist-tag add $PACKAGE_NAME@$VERSION $TAG else # Publish new version npm publish $TAG_ARG --access public diff --git a/yarn-project/end-to-end/scripts/setup_canary.sh b/yarn-project/end-to-end/scripts/setup_canary.sh deleted file mode 100755 index 14d7e176652..00000000000 --- a/yarn-project/end-to-end/scripts/setup_canary.sh +++ /dev/null @@ -1,62 +0,0 @@ -#!/usr/bin/env bash -set -eu - -TARGET_PKGS_FILE=$1 - -DIST_TAG=canary - -# Check if file exists and read it into an array -if [ -f "$TARGET_PKGS_FILE" ]; then - mapfile -t TARGET_PKGS < <(cat "$TARGET_PKGS_FILE") - echo "Loaded package array:" - for i in "${TARGET_PKGS[@]}"; do - echo "$i" - done -else - echo "File $TARGET_PKGS_FILE does not exist." -fi - -if [ -z "$DIST_TAG" ]; then - echo "No dist tag provided." - exit 0 -fi - -echo "Removing all files & folders that aren't needed for canary tests" -TARGET_DIR="./src" -cd "$TARGET_DIR" - -# Loop through all files and folders in the directory -for item in $(ls -A); do - if [[ "$item" != "index.ts" && "$item" != "shared" ]]; then - # Remove the item (either file or folder) - rm -rf "$item" - fi -done -cd .. - -echo "Updating external Aztec dependencies to tag '$DIST_TAG'" -JSON_TARGET_PKGS=$(printf '%s\n' "${TARGET_PKGS[@]}" | jq -R -s -c 'split("\n") | map(select(. != ""))') - -TMP=$(mktemp) -jq --arg v $DIST_TAG --argjson target_pkgs "$JSON_TARGET_PKGS" ' -.dependencies |= with_entries( - select( - (.key | startswith("@aztec")) as $isAztec | - if $isAztec then - .key as $k | any($target_pkgs[]; . == $k) - else - true - end - ) | - if .key as $k | any($target_pkgs[]; . == $k) then - .value = $v - else - . - end -)' package.json >$TMP && mv $TMP package.json - -echo "Updating end-to-end tsconfig.json" -TMP=$(mktemp) -# Copy canary's tsconfig.json -cp ../canary/tsconfig.json tsconfig.json -jq 'del(.references)' tsconfig.json >$TMP && mv $TMP tsconfig.json diff --git a/yarn-project/end-to-end/src/uniswap_trade_on_l1_from_l2.test.ts b/yarn-project/end-to-end/src/uniswap_trade_on_l1_from_l2.test.ts index 9bc5db2f362..5e20be7f9f5 100644 --- a/yarn-project/end-to-end/src/uniswap_trade_on_l1_from_l2.test.ts +++ b/yarn-project/end-to-end/src/uniswap_trade_on_l1_from_l2.test.ts @@ -9,6 +9,7 @@ const EXPECTED_FORKED_BLOCK = 0; //17514288; let teardown: () => Promise; +// docs:start:uniswap_setup const testSetup = async (): Promise => { const { teardown: teardown_, @@ -28,6 +29,7 @@ const testSetup = async (): Promise => { return { pxe, logger, publicClient, walletClient, ownerWallet, sponsorWallet }; }; +// docs:end:uniswap_setup const testCleanup = async () => { await teardown(); diff --git a/yarn-project/package.json b/yarn-project/package.json index 089ce942376..34945e2ad55 100644 --- a/yarn-project/package.json +++ b/yarn-project/package.json @@ -10,7 +10,7 @@ "formatting:fix": "FORCE_COLOR=true yarn workspaces foreach -p -v run formatting:fix", "lint": "yarn eslint --cache --ignore-pattern l1-artifacts .", "format": "yarn prettier --cache -w .", - "test": "FORCE_COLOR=true yarn workspaces foreach --exclude @aztec/aztec3-packages --exclude @aztec/end-to-end --exclude @aztec/canary --exclude private-token -p -j unlimited -v run test", + "test": "FORCE_COLOR=true yarn workspaces foreach --exclude @aztec/aztec3-packages --exclude @aztec/end-to-end --exclude private-token -p -j unlimited -v run test", "build": "yarn workspace @aztec/l1-artifacts build && tsc -b tsconfig.json", "build:dev": "yarn workspace @aztec/l1-artifacts build && tsc -b tsconfig.json --watch", "clean": "yarn workspaces foreach -p -v run clean" @@ -26,7 +26,6 @@ "boxes/blank", "boxes/blank-react", "boxes/token", - "canary", "circuits.js", "cli", "docs", diff --git a/yarn-project/tsconfig.json b/yarn-project/tsconfig.json index 9910d1379ca..7ca6f4322c1 100644 --- a/yarn-project/tsconfig.json +++ b/yarn-project/tsconfig.json @@ -25,7 +25,6 @@ { "path": "aztec-node/tsconfig.json" }, { "path": "pxe/tsconfig.json" }, { "path": "aztec-sandbox/tsconfig.json" }, - { "path": "canary/tsconfig.json" }, { "path": "circuits.js/tsconfig.json" }, { "path": "cli/tsconfig.json" }, { "path": "end-to-end/tsconfig.json" }, diff --git a/yarn-project/yarn.lock b/yarn-project/yarn.lock index 935cf87829a..06a076f1cfe 100644 --- a/yarn-project/yarn.lock +++ b/yarn-project/yarn.lock @@ -290,32 +290,6 @@ __metadata: languageName: node linkType: soft -"@aztec/canary@workspace:canary": - version: 0.0.0-use.local - resolution: "@aztec/canary@workspace:canary" - dependencies: - "@aztec/aztec.js": "workspace:^" - "@aztec/cli": "workspace:^" - "@aztec/end-to-end": "workspace:^" - "@aztec/ethereum": "workspace:^" - "@aztec/l1-artifacts": "workspace:^" - "@aztec/noir-contracts": "workspace:^" - "@jest/globals": ^29.5.0 - "@types/jest": ^29.5.0 - "@types/koa-static": ^4.0.2 - "@types/node": ^18.7.23 - abitype: ^0.9.8 - jest: ^29.5.0 - koa: ^2.14.2 - koa-static: ^5.0.0 - ts-jest: ^29.1.0 - ts-node: ^10.9.1 - tslib: ^2.4.0 - typescript: ^5.0.4 - viem: ^1.2.5 - languageName: unknown - linkType: soft - "@aztec/circuits.js@workspace:^, @aztec/circuits.js@workspace:circuits.js": version: 0.0.0-use.local resolution: "@aztec/circuits.js@workspace:circuits.js" @@ -382,7 +356,7 @@ __metadata: languageName: unknown linkType: soft -"@aztec/end-to-end@workspace:^, @aztec/end-to-end@workspace:end-to-end": +"@aztec/end-to-end@workspace:end-to-end": version: 0.0.0-use.local resolution: "@aztec/end-to-end@workspace:end-to-end" dependencies: @@ -6470,21 +6444,6 @@ __metadata: languageName: node linkType: hard -"abitype@npm:^0.9.8": - version: 0.9.8 - resolution: "abitype@npm:0.9.8" - peerDependencies: - typescript: ">=5.0.4" - zod: ^3 >=3.19.1 - peerDependenciesMeta: - typescript: - optional: true - zod: - optional: true - checksum: d7d887f29d6821e3f7a400de9620511b80ead3f85c5c87308aaec97965d3493e6687ed816e88722b4f512249bd66dee9e69231b49af0e1db8f69400a62c87cf6 - languageName: node - linkType: hard - "abortable-iterator@npm:^5.0.1": version: 5.0.1 resolution: "abortable-iterator@npm:5.0.1" From 9ccbbd96e50f22646f0527c7d15944cecabca662 Mon Sep 17 00:00:00 2001 From: Alex Gherghisan Date: Wed, 13 Dec 2023 13:30:16 +0000 Subject: [PATCH 32/35] feat: persist pxe state (#3628) This PR adds a persistent database to PXE. I've created a new package in the monorepo called `@aztec/kv-store` which exports a set of general data structures that can be used by components to store state in consistent manner. The only implementation right now is with LMDB (both persisted on disk and in-memory/temporary file). This higher level abstraction allowed me to easily add storage to ~PXE's note processors, its synchronizer and~ the key store too. Fix #3364 Changes to the synchronizer and note processors have been taken out and will be merged in a separate PR (as part of #3570) because it will require some changes to the benchmarking code. Synch changes here #3673 --- .../end-to-end/src/e2e_p2p_network.test.ts | 2 +- yarn-project/end-to-end/src/fixtures/utils.ts | 2 +- .../foundation/src/serialize/buffer_reader.ts | 12 +- yarn-project/key-store/package.json | 1 + yarn-project/key-store/src/test_key_store.ts | 38 ++- yarn-project/key-store/tsconfig.json | 3 + yarn-project/kv-store/.eslintrc.cjs | 1 + yarn-project/kv-store/README.md | 10 + yarn-project/kv-store/package.json | 50 +++ yarn-project/kv-store/src/index.ts | 5 + yarn-project/kv-store/src/interfaces/array.ts | 54 ++++ yarn-project/kv-store/src/interfaces/map.ts | 70 +++++ .../kv-store/src/interfaces/singleton.ts | 20 ++ yarn-project/kv-store/src/interfaces/store.ts | 40 +++ yarn-project/kv-store/src/lmdb/array.test.ts | 91 ++++++ yarn-project/kv-store/src/lmdb/array.ts | 109 +++++++ yarn-project/kv-store/src/lmdb/map.test.ts | 72 +++++ yarn-project/kv-store/src/lmdb/map.ts | 88 ++++++ .../kv-store/src/lmdb/singleton.test.ts | 25 ++ yarn-project/kv-store/src/lmdb/singleton.ts | 31 ++ yarn-project/kv-store/src/lmdb/store.ts | 131 ++++++++ yarn-project/kv-store/tsconfig.json | 14 + yarn-project/package.json | 3 +- yarn-project/pxe/package.json | 4 +- yarn-project/pxe/src/config/index.ts | 6 +- yarn-project/pxe/src/contract_tree/index.ts | 7 +- yarn-project/pxe/src/database/index.ts | 2 +- .../pxe/src/database/kv_pxe_database.test.ts | 15 + .../pxe/src/database/kv_pxe_database.ts | 288 ++++++++++++++++++ .../pxe/src/database/memory_db.test.ts | 3 + yarn-project/pxe/src/database/memory_db.ts | 21 +- .../database/{database.ts => pxe_database.ts} | 15 +- .../src/database/pxe_database_test_suite.ts | 220 +++++++++++++ .../src/note_processor/note_processor.test.ts | 12 +- .../pxe/src/note_processor/note_processor.ts | 4 +- .../pxe/src/pxe_service/create_pxe_service.ts | 34 +-- .../pxe/src/pxe_service/pxe_service.ts | 9 +- .../src/pxe_service/test/pxe_service.test.ts | 20 +- yarn-project/pxe/src/simulator/index.ts | 4 +- .../pxe/src/simulator_oracle/index.ts | 4 +- .../pxe/src/synchronizer/synchronizer.test.ts | 16 +- .../pxe/src/synchronizer/synchronizer.ts | 4 +- yarn-project/pxe/tsconfig.json | 3 + yarn-project/types/src/contract_dao.test.ts | 54 ++++ yarn-project/types/src/contract_dao.ts | 94 +++--- yarn-project/types/src/keys/key_store.ts | 2 +- yarn-project/yarn.lock | 19 ++ 47 files changed, 1583 insertions(+), 149 deletions(-) create mode 100644 yarn-project/kv-store/.eslintrc.cjs create mode 100644 yarn-project/kv-store/README.md create mode 100644 yarn-project/kv-store/package.json create mode 100644 yarn-project/kv-store/src/index.ts create mode 100644 yarn-project/kv-store/src/interfaces/array.ts create mode 100644 yarn-project/kv-store/src/interfaces/map.ts create mode 100644 yarn-project/kv-store/src/interfaces/singleton.ts create mode 100644 yarn-project/kv-store/src/interfaces/store.ts create mode 100644 yarn-project/kv-store/src/lmdb/array.test.ts create mode 100644 yarn-project/kv-store/src/lmdb/array.ts create mode 100644 yarn-project/kv-store/src/lmdb/map.test.ts create mode 100644 yarn-project/kv-store/src/lmdb/map.ts create mode 100644 yarn-project/kv-store/src/lmdb/singleton.test.ts create mode 100644 yarn-project/kv-store/src/lmdb/singleton.ts create mode 100644 yarn-project/kv-store/src/lmdb/store.ts create mode 100644 yarn-project/kv-store/tsconfig.json create mode 100644 yarn-project/pxe/src/database/kv_pxe_database.test.ts create mode 100644 yarn-project/pxe/src/database/kv_pxe_database.ts rename yarn-project/pxe/src/database/{database.ts => pxe_database.ts} (88%) create mode 100644 yarn-project/pxe/src/database/pxe_database_test_suite.ts create mode 100644 yarn-project/types/src/contract_dao.test.ts diff --git a/yarn-project/end-to-end/src/e2e_p2p_network.test.ts b/yarn-project/end-to-end/src/e2e_p2p_network.test.ts index 7c782e6edf9..cf414d6df7f 100644 --- a/yarn-project/end-to-end/src/e2e_p2p_network.test.ts +++ b/yarn-project/end-to-end/src/e2e_p2p_network.test.ts @@ -150,7 +150,7 @@ describe('e2e_p2p_network', () => { numTxs: number, ): Promise => { const rpcConfig = getRpcConfig(); - const pxeService = await createPXEService(node, rpcConfig, {}, true); + const pxeService = await createPXEService(node, rpcConfig, true); const keyPair = ConstantKeyPair.random(new Grumpkin()); const completeAddress = CompleteAddress.fromPrivateKeyAndPartialAddress(keyPair.getPrivateKey(), Fr.random()); diff --git a/yarn-project/end-to-end/src/fixtures/utils.ts b/yarn-project/end-to-end/src/fixtures/utils.ts index 978147ab5e0..3ac20b8339f 100644 --- a/yarn-project/end-to-end/src/fixtures/utils.ts +++ b/yarn-project/end-to-end/src/fixtures/utils.ts @@ -151,7 +151,7 @@ export async function setupPXEService( logger: DebugLogger; }> { const pxeServiceConfig = getPXEServiceConfig(); - const pxe = await createPXEService(aztecNode, pxeServiceConfig, {}, useLogSuffix); + const pxe = await createPXEService(aztecNode, pxeServiceConfig, useLogSuffix); const wallets = await createAccounts(pxe, numberOfAccounts); diff --git a/yarn-project/foundation/src/serialize/buffer_reader.ts b/yarn-project/foundation/src/serialize/buffer_reader.ts index 1b8749d6358..b54a2d1b52b 100644 --- a/yarn-project/foundation/src/serialize/buffer_reader.ts +++ b/yarn-project/foundation/src/serialize/buffer_reader.ts @@ -31,8 +31,16 @@ export class BufferReader { * @param bufferOrReader - A Buffer or BufferReader to initialize the BufferReader. * @returns An instance of BufferReader. */ - public static asReader(bufferOrReader: Buffer | BufferReader) { - return Buffer.isBuffer(bufferOrReader) ? new BufferReader(bufferOrReader) : bufferOrReader; + public static asReader(bufferOrReader: Uint8Array | Buffer | BufferReader): BufferReader { + if (bufferOrReader instanceof BufferReader) { + return bufferOrReader; + } + + const buf = Buffer.isBuffer(bufferOrReader) + ? bufferOrReader + : Buffer.from(bufferOrReader.buffer, bufferOrReader.byteOffset, bufferOrReader.byteLength); + + return new BufferReader(buf); } /** diff --git a/yarn-project/key-store/package.json b/yarn-project/key-store/package.json index bbcdabc0de8..a19af464fd2 100644 --- a/yarn-project/key-store/package.json +++ b/yarn-project/key-store/package.json @@ -32,6 +32,7 @@ "dependencies": { "@aztec/circuits.js": "workspace:^", "@aztec/foundation": "workspace:^", + "@aztec/kv-store": "workspace:^", "@aztec/types": "workspace:^", "tslib": "^2.4.0" }, diff --git a/yarn-project/key-store/src/test_key_store.ts b/yarn-project/key-store/src/test_key_store.ts index 865fb9d75ee..65d64fd0231 100644 --- a/yarn-project/key-store/src/test_key_store.ts +++ b/yarn-project/key-store/src/test_key_store.ts @@ -1,5 +1,6 @@ -import { GrumpkinPrivateKey } from '@aztec/circuits.js'; +import { GrumpkinPrivateKey, GrumpkinScalar, Point } from '@aztec/circuits.js'; import { Grumpkin } from '@aztec/circuits.js/barretenberg'; +import { AztecKVStore, AztecMap } from '@aztec/kv-store'; import { KeyPair, KeyStore, PublicKey } from '@aztec/types'; import { ConstantKeyPair } from './key_pair.js'; @@ -9,30 +10,27 @@ import { ConstantKeyPair } from './key_pair.js'; * It should be utilized in testing scenarios where secure key management is not required, and ease-of-use is prioritized. */ export class TestKeyStore implements KeyStore { - private accounts: KeyPair[] = []; - constructor(private curve: Grumpkin) {} + #keys: AztecMap; - public addAccount(privKey: GrumpkinPrivateKey): PublicKey { - const keyPair = ConstantKeyPair.fromPrivateKey(this.curve, privKey); - - // check if private key has already been used - const account = this.accounts.find(a => a.getPublicKey().equals(keyPair.getPublicKey())); - if (account) { - return account.getPublicKey(); - } + constructor(private curve: Grumpkin, database: AztecKVStore) { + this.#keys = database.createMap('key_store'); + } - this.accounts.push(keyPair); + public async addAccount(privKey: GrumpkinPrivateKey): Promise { + const keyPair = ConstantKeyPair.fromPrivateKey(this.curve, privKey); + await this.#keys.setIfNotExists(keyPair.getPublicKey().toString(), keyPair.getPrivateKey().toBuffer()); return keyPair.getPublicKey(); } - public createAccount(): Promise { + public async createAccount(): Promise { const keyPair = ConstantKeyPair.random(this.curve); - this.accounts.push(keyPair); - return Promise.resolve(keyPair.getPublicKey()); + await this.#keys.set(keyPair.getPublicKey().toString(), keyPair.getPrivateKey().toBuffer()); + return keyPair.getPublicKey(); } public getAccounts(): Promise { - return Promise.resolve(this.accounts.map(a => a.getPublicKey())); + const range = Array.from(this.#keys.keys()); + return Promise.resolve(range.map(key => Point.fromString(key))); } public getAccountPrivateKey(pubKey: PublicKey): Promise { @@ -48,13 +46,13 @@ export class TestKeyStore implements KeyStore { * @param pubKey - The public key of the account to retrieve. * @returns The KeyPair object associated with the provided key. */ - private getAccount(pubKey: PublicKey) { - const account = this.accounts.find(a => a.getPublicKey().equals(pubKey)); - if (!account) { + private getAccount(pubKey: PublicKey): KeyPair { + const privKey = this.#keys.get(pubKey.toString()); + if (!privKey) { throw new Error( 'Unknown account.\nSee docs for context: https://docs.aztec.network/dev_docs/contracts/common_errors#unknown-contract-error', ); } - return account; + return ConstantKeyPair.fromPrivateKey(this.curve, GrumpkinScalar.fromBuffer(privKey)); } } diff --git a/yarn-project/key-store/tsconfig.json b/yarn-project/key-store/tsconfig.json index 1820488d409..76107a492b5 100644 --- a/yarn-project/key-store/tsconfig.json +++ b/yarn-project/key-store/tsconfig.json @@ -6,6 +6,9 @@ "tsBuildInfoFile": ".tsbuildinfo" }, "references": [ + { + "path": "../kv-store" + }, { "path": "../circuits.js" }, diff --git a/yarn-project/kv-store/.eslintrc.cjs b/yarn-project/kv-store/.eslintrc.cjs new file mode 100644 index 00000000000..e659927475c --- /dev/null +++ b/yarn-project/kv-store/.eslintrc.cjs @@ -0,0 +1 @@ +module.exports = require('@aztec/foundation/eslint'); diff --git a/yarn-project/kv-store/README.md b/yarn-project/kv-store/README.md new file mode 100644 index 00000000000..37c15c72f12 --- /dev/null +++ b/yarn-project/kv-store/README.md @@ -0,0 +1,10 @@ +# KV Store + +The Aztec KV store is an implementation of a durable key-value database with a pluggable backend. THe only supported backend right now is LMDB by using the [`lmdb-js` package](https://github.com/kriszyp/lmdb-js). + +This package exports a number of primitive data structures that can be used to build domain-specific databases in each node component (e.g. a PXE database or an Archiver database). The data structures supported: + +- singleton - holds a single value. Great for when a value needs to be stored but it's not a collection (e.g. the latest block header or the length of an array) +- array - works like a normal in-memory JS array. It can't contain holes and it can be used as a stack (push-pop mechanics). +- map - a hashmap where keys can be numbers or strings +- multi-map - just like a map but each key holds multiple values. Can be used for indexing into other data structures diff --git a/yarn-project/kv-store/package.json b/yarn-project/kv-store/package.json new file mode 100644 index 00000000000..8aea043378d --- /dev/null +++ b/yarn-project/kv-store/package.json @@ -0,0 +1,50 @@ +{ + "name": "@aztec/kv-store", + "version": "0.1.0", + "type": "module", + "exports": "./dest/index.js", + "scripts": { + "build": "yarn clean && tsc -b", + "build:dev": "tsc -b --watch", + "clean": "rm -rf ./dest .tsbuildinfo", + "formatting": "run -T prettier --check ./src && run -T eslint ./src", + "formatting:fix": "run -T eslint --fix ./src && run -T prettier -w ./src", + "test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules $(yarn bin jest) --passWithNoTests", + "start": "DEBUG='aztec:*' && node ./dest/bin/index.js" + }, + "inherits": [ + "../package.common.json" + ], + "jest": { + "preset": "ts-jest/presets/default-esm", + "moduleNameMapper": { + "^(\\.{1,2}/.*)\\.[cm]?js$": "$1" + }, + "testRegex": "./src/.*\\.test\\.(js|mjs|ts)$", + "rootDir": "./src", + "workerThreads": true + }, + "dependencies": { + "@aztec/foundation": "workspace:^", + "lmdb": "^2.9.1" + }, + "devDependencies": { + "@jest/globals": "^29.5.0", + "@types/jest": "^29.5.0", + "@types/node": "^18.7.23", + "jest": "^29.5.0", + "jest-mock-extended": "^3.0.3", + "ts-jest": "^29.1.0", + "ts-node": "^10.9.1", + "typescript": "^5.0.4" + }, + "files": [ + "dest", + "src", + "!*.test.*" + ], + "types": "./dest/index.d.ts", + "engines": { + "node": ">=18" + } +} diff --git a/yarn-project/kv-store/src/index.ts b/yarn-project/kv-store/src/index.ts new file mode 100644 index 00000000000..2a71333f9e6 --- /dev/null +++ b/yarn-project/kv-store/src/index.ts @@ -0,0 +1,5 @@ +export * from './interfaces/array.js'; +export * from './interfaces/map.js'; +export * from './interfaces/singleton.js'; +export * from './interfaces/store.js'; +export * from './lmdb/store.js'; diff --git a/yarn-project/kv-store/src/interfaces/array.ts b/yarn-project/kv-store/src/interfaces/array.ts new file mode 100644 index 00000000000..e2492204212 --- /dev/null +++ b/yarn-project/kv-store/src/interfaces/array.ts @@ -0,0 +1,54 @@ +/** + * An array backed by a persistent store. Can not have any holes in it. + */ +export interface AztecArray { + /** + * The size of the array + */ + length: number; + + /** + * Pushes values to the end of the array + * @param vals - The values to push to the end of the array + * @returns The new length of the array + */ + push(...vals: T[]): Promise; + + /** + * Pops a value from the end of the array. + * @returns The value that was popped, or undefined if the array was empty + */ + pop(): Promise; + + /** + * Gets the value at the given index. Index can be in the range [-length, length - 1). + * If the index is negative, it will be treated as an offset from the end of the array. + * + * @param index - The index to get the value from + * @returns The value at the given index or undefined if the index is out of bounds + */ + at(index: number): T | undefined; + + /** + * Updates the value at the given index. Index can be in the range [-length, length - 1). + * @param index - The index to set the value at + * @param val - The value to set + * @returns Whether the value was set + */ + setAt(index: number, val: T): Promise; + + /** + * Iterates over the array with indexes. + */ + entries(): IterableIterator<[number, T]>; + + /** + * Iterates over the array. + */ + values(): IterableIterator; + + /** + * Iterates over the array. + */ + [Symbol.iterator](): IterableIterator; +} diff --git a/yarn-project/kv-store/src/interfaces/map.ts b/yarn-project/kv-store/src/interfaces/map.ts new file mode 100644 index 00000000000..8de773837b7 --- /dev/null +++ b/yarn-project/kv-store/src/interfaces/map.ts @@ -0,0 +1,70 @@ +/** + * A map backed by a persistent store. + */ +export interface AztecMap { + /** + * Gets the value at the given key. + * @param key - The key to get the value from + */ + get(key: K): V | undefined; + + /** + * Checks if a key exists in the map. + * @param key - The key to check + * @returns True if the key exists, false otherwise + */ + has(key: K): boolean; + + /** + * Sets the value at the given key. + * @param key - The key to set the value at + * @param val - The value to set + */ + set(key: K, val: V): Promise; + + /** + * Sets the value at the given key if it does not already exist. + * @param key - The key to set the value at + * @param val - The value to set + */ + setIfNotExists(key: K, val: V): Promise; + + /** + * Deletes the value at the given key. + * @param key - The key to delete the value at + */ + delete(key: K): Promise; + + /** + * Iterates over the map's key-value entries + */ + entries(): IterableIterator<[K, V]>; + + /** + * Iterates over the map's values + */ + values(): IterableIterator; + + /** + * Iterates over the map's keys + */ + keys(): IterableIterator; +} + +/** + * A map backed by a persistent store that can have multiple values for a single key. + */ +export interface AztecMultiMap extends AztecMap { + /** + * Gets all the values at the given key. + * @param key - The key to get the values from + */ + getValues(key: K): IterableIterator; + + /** + * Deletes a specific value at the given key. + * @param key - The key to delete the value at + * @param val - The value to delete + */ + deleteValue(key: K, val: V): Promise; +} diff --git a/yarn-project/kv-store/src/interfaces/singleton.ts b/yarn-project/kv-store/src/interfaces/singleton.ts new file mode 100644 index 00000000000..43b34aa0ad8 --- /dev/null +++ b/yarn-project/kv-store/src/interfaces/singleton.ts @@ -0,0 +1,20 @@ +/** + * Represents a singleton value in the database. + */ +export interface AztecSingleton { + /** + * Gets the value. + */ + get(): T | undefined; + + /** + * Sets the value. + * @param val - The new value + */ + set(val: T): Promise; + + /** + * Deletes the value. + */ + delete(): Promise; +} diff --git a/yarn-project/kv-store/src/interfaces/store.ts b/yarn-project/kv-store/src/interfaces/store.ts new file mode 100644 index 00000000000..d7ccfa3cd29 --- /dev/null +++ b/yarn-project/kv-store/src/interfaces/store.ts @@ -0,0 +1,40 @@ +import { AztecArray } from './array.js'; +import { AztecMap, AztecMultiMap } from './map.js'; +import { AztecSingleton } from './singleton.js'; + +/** A key-value store */ +export interface AztecKVStore { + /** + * Creates a new map. + * @param name - The name of the map + * @returns The map + */ + createMap(name: string): AztecMap; + + /** + * Creates a new multi-map. + * @param name - The name of the multi-map + * @returns The multi-map + */ + createMultiMap(name: string): AztecMultiMap; + + /** + * Creates a new array. + * @param name - The name of the array + * @returns The array + */ + createArray(name: string): AztecArray; + + /** + * Creates a new singleton. + * @param name - The name of the singleton + * @returns The singleton + */ + createSingleton(name: string): AztecSingleton; + + /** + * Starts a transaction. All calls to read/write data while in a transaction are queued and executed atomically. + * @param callback - The callback to execute in a transaction + */ + transaction>>(callback: () => T): Promise; +} diff --git a/yarn-project/kv-store/src/lmdb/array.test.ts b/yarn-project/kv-store/src/lmdb/array.test.ts new file mode 100644 index 00000000000..3058302e87f --- /dev/null +++ b/yarn-project/kv-store/src/lmdb/array.test.ts @@ -0,0 +1,91 @@ +import { Database, open } from 'lmdb'; + +import { LmdbAztecArray } from './array.js'; + +describe('LmdbAztecArray', () => { + let db: Database; + let arr: LmdbAztecArray; + + beforeEach(() => { + db = open({} as any); + arr = new LmdbAztecArray(db, 'test'); + }); + + it('should be able to push and pop values', async () => { + await arr.push(1); + await arr.push(2); + await arr.push(3); + + expect(arr.length).toEqual(3); + expect(await arr.pop()).toEqual(3); + expect(await arr.pop()).toEqual(2); + expect(await arr.pop()).toEqual(1); + expect(await arr.pop()).toEqual(undefined); + }); + + it('should be able to get values by index', async () => { + await arr.push(1); + await arr.push(2); + await arr.push(3); + + expect(arr.at(0)).toEqual(1); + expect(arr.at(1)).toEqual(2); + expect(arr.at(2)).toEqual(3); + expect(arr.at(3)).toEqual(undefined); + expect(arr.at(-1)).toEqual(3); + expect(arr.at(-2)).toEqual(2); + expect(arr.at(-3)).toEqual(1); + expect(arr.at(-4)).toEqual(undefined); + }); + + it('should be able to set values by index', async () => { + await arr.push(1); + await arr.push(2); + await arr.push(3); + + expect(await arr.setAt(0, 4)).toEqual(true); + expect(await arr.setAt(1, 5)).toEqual(true); + expect(await arr.setAt(2, 6)).toEqual(true); + + expect(await arr.setAt(3, 7)).toEqual(false); + + expect(arr.at(0)).toEqual(4); + expect(arr.at(1)).toEqual(5); + expect(arr.at(2)).toEqual(6); + expect(arr.at(3)).toEqual(undefined); + + expect(await arr.setAt(-1, 8)).toEqual(true); + expect(await arr.setAt(-2, 9)).toEqual(true); + expect(await arr.setAt(-3, 10)).toEqual(true); + + expect(await arr.setAt(-4, 11)).toEqual(false); + + expect(arr.at(-1)).toEqual(8); + expect(arr.at(-2)).toEqual(9); + expect(arr.at(-3)).toEqual(10); + expect(arr.at(-4)).toEqual(undefined); + }); + + it('should be able to iterate over values', async () => { + await arr.push(1); + await arr.push(2); + await arr.push(3); + + expect([...arr.values()]).toEqual([1, 2, 3]); + expect([...arr.entries()]).toEqual([ + [0, 1], + [1, 2], + [2, 3], + ]); + }); + + it('should be able to restore state', async () => { + await arr.push(1); + await arr.push(2); + await arr.push(3); + + const arr2 = new LmdbAztecArray(db, 'test'); + expect(arr2.length).toEqual(3); + expect([...arr2.values()]).toEqual([...arr.values()]); + }); +}); diff --git a/yarn-project/kv-store/src/lmdb/array.ts b/yarn-project/kv-store/src/lmdb/array.ts new file mode 100644 index 00000000000..1da3676aac0 --- /dev/null +++ b/yarn-project/kv-store/src/lmdb/array.ts @@ -0,0 +1,109 @@ +import { Database, Key } from 'lmdb'; + +import { AztecArray } from '../interfaces/array.js'; +import { LmdbAztecSingleton } from './singleton.js'; + +/** The shape of a key that stores a value in an array */ +type ArrayIndexSlot = ['array', string, 'slot', number]; + +/** + * An persistent array backed by LMDB. + */ +export class LmdbAztecArray implements AztecArray { + #db: Database; + #name: string; + #length: LmdbAztecSingleton; + + constructor(db: Database, arrName: string) { + this.#name = arrName; + this.#length = new LmdbAztecSingleton(db, `${arrName}:meta:length`); + this.#db = db as Database; + } + + get length(): number { + return this.#length.get() ?? 0; + } + + push(...vals: T[]): Promise { + return this.#db.childTransaction(() => { + let length = this.length; + for (const val of vals) { + void this.#db.put(this.#slot(length), val); + length += 1; + } + + void this.#length.set(length); + + return length; + }); + } + + pop(): Promise { + return this.#db.childTransaction(() => { + const length = this.length; + if (length === 0) { + return undefined; + } + + const slot = this.#slot(length - 1); + const val = this.#db.get(slot) as T; + + void this.#db.remove(slot); + void this.#length.set(length - 1); + + return val; + }); + } + + at(index: number): T | undefined { + if (index < 0) { + index = this.length + index; + } + + // the Array API only accepts indexes in the range [-this.length, this.length) + // so if after normalizing the index is still out of range, return undefined + if (index < 0 || index >= this.length) { + return undefined; + } + + return this.#db.get(this.#slot(index)); + } + + setAt(index: number, val: T): Promise { + if (index < 0) { + index = this.length + index; + } + + if (index < 0 || index >= this.length) { + return Promise.resolve(false); + } + + return this.#db.put(this.#slot(index), val); + } + + *entries(): IterableIterator<[number, T]> { + const values = this.#db.getRange({ + start: this.#slot(0), + limit: this.length, + }); + + for (const { key, value } of values) { + const index = key[3]; + yield [index, value]; + } + } + + *values(): IterableIterator { + for (const [_, value] of this.entries()) { + yield value; + } + } + + [Symbol.iterator](): IterableIterator { + return this.values(); + } + + #slot(index: number): ArrayIndexSlot { + return ['array', this.#name, 'slot', index]; + } +} diff --git a/yarn-project/kv-store/src/lmdb/map.test.ts b/yarn-project/kv-store/src/lmdb/map.test.ts new file mode 100644 index 00000000000..5319e0a26c3 --- /dev/null +++ b/yarn-project/kv-store/src/lmdb/map.test.ts @@ -0,0 +1,72 @@ +import { Database, open } from 'lmdb'; + +import { LmdbAztecMap } from './map.js'; + +describe('LmdbAztecMap', () => { + let db: Database; + let map: LmdbAztecMap; + + beforeEach(() => { + db = open({ dupSort: true } as any); + map = new LmdbAztecMap(db, 'test'); + }); + + it('should be able to set and get values', async () => { + await map.set('foo', 'bar'); + await map.set('baz', 'qux'); + + expect(map.get('foo')).toEqual('bar'); + expect(map.get('baz')).toEqual('qux'); + expect(map.get('quux')).toEqual(undefined); + }); + + it('should be able to set values if they do not exist', async () => { + expect(await map.setIfNotExists('foo', 'bar')).toEqual(true); + expect(await map.setIfNotExists('foo', 'baz')).toEqual(false); + + expect(map.get('foo')).toEqual('bar'); + }); + + it('should be able to delete values', async () => { + await map.set('foo', 'bar'); + await map.set('baz', 'qux'); + + expect(await map.delete('foo')).toEqual(true); + + expect(map.get('foo')).toEqual(undefined); + expect(map.get('baz')).toEqual('qux'); + }); + + it('should be able to iterate over entries', async () => { + await map.set('foo', 'bar'); + await map.set('baz', 'qux'); + + expect([...map.entries()]).toEqual( + expect.arrayContaining([ + ['foo', 'bar'], + ['baz', 'qux'], + ]), + ); + }); + + it('should be able to iterate over values', async () => { + await map.set('foo', 'bar'); + await map.set('baz', 'qux'); + + expect([...map.values()]).toEqual(expect.arrayContaining(['bar', 'qux'])); + }); + + it('should be able to iterate over keys', async () => { + await map.set('foo', 'bar'); + await map.set('baz', 'qux'); + + expect([...map.keys()]).toEqual(expect.arrayContaining(['foo', 'baz'])); + }); + + it('should be able to get multiple values for a single key', async () => { + await map.set('foo', 'bar'); + await map.set('foo', 'baz'); + + expect([...map.getValues('foo')]).toEqual(['bar', 'baz']); + }); +}); diff --git a/yarn-project/kv-store/src/lmdb/map.ts b/yarn-project/kv-store/src/lmdb/map.ts new file mode 100644 index 00000000000..b883b809738 --- /dev/null +++ b/yarn-project/kv-store/src/lmdb/map.ts @@ -0,0 +1,88 @@ +import { Database, Key } from 'lmdb'; + +import { AztecMultiMap } from '../interfaces/map.js'; + +/** The slot where a key-value entry would be stored */ +type MapKeyValueSlot = ['map', string, 'slot', K]; + +/** + * A map backed by LMDB. + */ +export class LmdbAztecMap implements AztecMultiMap { + protected db: Database>; + protected name: string; + + constructor(rootDb: Database, mapName: string) { + this.name = mapName; + this.db = rootDb as Database>; + } + + close(): Promise { + return this.db.close(); + } + + get(key: K): V | undefined { + return this.db.get(this.#slot(key)) as V | undefined; + } + + *getValues(key: K): IterableIterator { + const values = this.db.getValues(this.#slot(key)); + for (const value of values) { + yield value; + } + } + + has(key: K): boolean { + return this.db.doesExist(this.#slot(key)); + } + + set(key: K, val: V): Promise { + return this.db.put(this.#slot(key), val); + } + + setIfNotExists(key: K, val: V): Promise { + const slot = this.#slot(key); + return this.db.ifNoExists(slot, () => { + void this.db.put(slot, val); + }); + } + + delete(key: K): Promise { + return this.db.remove(this.#slot(key)); + } + + async deleteValue(key: K, val: V): Promise { + await this.db.remove(this.#slot(key), val); + } + + *entries(): IterableIterator<[K, V]> { + const iterator = this.db.getRange({ + start: ['map', this.name, 'slot'], + }); + + for (const { key, value } of iterator) { + if (key[0] !== 'map' || key[1] !== this.name) { + break; + } + + const originalKey = key[3]; + yield [originalKey, value]; + } + } + + *values(): IterableIterator { + for (const [_, value] of this.entries()) { + yield value; + } + } + + *keys(): IterableIterator { + for (const [key, _] of this.entries()) { + yield key; + } + } + + #slot(key: K): MapKeyValueSlot { + return ['map', this.name, 'slot', key]; + } +} diff --git a/yarn-project/kv-store/src/lmdb/singleton.test.ts b/yarn-project/kv-store/src/lmdb/singleton.test.ts new file mode 100644 index 00000000000..de1eefae462 --- /dev/null +++ b/yarn-project/kv-store/src/lmdb/singleton.test.ts @@ -0,0 +1,25 @@ +import { open } from 'lmdb'; + +import { LmdbAztecSingleton } from './singleton.js'; + +describe('LmdbAztecSingleton', () => { + let singleton: LmdbAztecSingleton; + beforeEach(() => { + singleton = new LmdbAztecSingleton(open({} as any), 'test'); + }); + + it('returns undefined if the value is not set', () => { + expect(singleton.get()).toEqual(undefined); + }); + + it('should be able to set and get values', async () => { + expect(await singleton.set('foo')).toEqual(true); + expect(singleton.get()).toEqual('foo'); + }); + + it('overwrites the value if it is set again', async () => { + expect(await singleton.set('foo')).toEqual(true); + expect(await singleton.set('bar')).toEqual(true); + expect(singleton.get()).toEqual('bar'); + }); +}); diff --git a/yarn-project/kv-store/src/lmdb/singleton.ts b/yarn-project/kv-store/src/lmdb/singleton.ts new file mode 100644 index 00000000000..0fa4ffe69e4 --- /dev/null +++ b/yarn-project/kv-store/src/lmdb/singleton.ts @@ -0,0 +1,31 @@ +import { Database, Key } from 'lmdb'; + +import { AztecSingleton } from '../interfaces/singleton.js'; + +/** The slot where this singleton will store its value */ +type ValueSlot = ['singleton', string, 'value']; + +/** + * Stores a single value in LMDB. + */ +export class LmdbAztecSingleton implements AztecSingleton { + #db: Database; + #slot: ValueSlot; + + constructor(db: Database, name: string) { + this.#db = db as Database; + this.#slot = ['singleton', name, 'value']; + } + + get(): T | undefined { + return this.#db.get(this.#slot); + } + + set(val: T): Promise { + return this.#db.put(this.#slot, val); + } + + delete(): Promise { + return this.#db.remove(this.#slot); + } +} diff --git a/yarn-project/kv-store/src/lmdb/store.ts b/yarn-project/kv-store/src/lmdb/store.ts new file mode 100644 index 00000000000..9ede111a875 --- /dev/null +++ b/yarn-project/kv-store/src/lmdb/store.ts @@ -0,0 +1,131 @@ +import { EthAddress } from '@aztec/foundation/eth-address'; +import { Logger, createDebugLogger } from '@aztec/foundation/log'; + +import { Database, Key, RootDatabase, open } from 'lmdb'; + +import { AztecArray } from '../interfaces/array.js'; +import { AztecMap, AztecMultiMap } from '../interfaces/map.js'; +import { AztecSingleton } from '../interfaces/singleton.js'; +import { AztecKVStore } from '../interfaces/store.js'; +import { LmdbAztecArray } from './array.js'; +import { LmdbAztecMap } from './map.js'; +import { LmdbAztecSingleton } from './singleton.js'; + +/** + * A key-value store backed by LMDB. + */ +export class AztecLmdbStore implements AztecKVStore { + #rootDb: RootDatabase; + #data: Database; + #multiMapData: Database; + #rollupAddress: AztecSingleton; + #log: Logger; + + constructor(rootDb: RootDatabase, log: Logger) { + this.#rootDb = rootDb; + this.#log = log; + + // big bucket to store all the data + this.#data = rootDb.openDB('data', { + encoding: 'msgpack', + keyEncoding: 'ordered-binary', + }); + + this.#multiMapData = rootDb.openDB('data_dup_sort', { + encoding: 'msgpack', + keyEncoding: 'ordered-binary', + dupSort: true, + }); + + this.#rollupAddress = this.createSingleton('rollupAddress'); + } + + /** + * Creates a new AztecKVStore backed by LMDB. The path to the database is optional. If not provided, + * the database will be stored in a temporary location and be deleted when the process exists. + * + * The `rollupAddress` passed is checked against what is stored in the database. If they do not match, + * the database is cleared before returning the store. This way data is not accidentally shared between + * different rollup instances. + * + * @param rollupAddress - The ETH address of the rollup contract + * @param path - A path on the disk to store the database. Optional + * @param log - A logger to use. Optional + * @returns The store + */ + static async create( + rollupAddress: EthAddress, + path?: string, + log = createDebugLogger('aztec:kv-store:lmdb'), + ): Promise { + log.info(`Opening LMDB database at ${path || 'temporary location'}`); + + const rootDb = open({ + path, + }); + + const db = new AztecLmdbStore(rootDb, log); + await db.#init(rollupAddress); + + return db; + } + + /** + * Creates a new AztecMap in the store. + * @param name - Name of the map + * @returns A new AztecMap + */ + createMap(name: string): AztecMap { + return new LmdbAztecMap(this.#data, name); + } + + /** + * Creates a new AztecMultiMap in the store. A multi-map stores multiple values for a single key automatically. + * @param name - Name of the map + * @returns A new AztecMultiMap + */ + createMultiMap(name: string): AztecMultiMap { + return new LmdbAztecMap(this.#multiMapData, name); + } + + /** + * Creates a new AztecArray in the store. + * @param name - Name of the array + * @returns A new AztecArray + */ + createArray(name: string): AztecArray { + return new LmdbAztecArray(this.#data, name); + } + + /** + * Creates a new AztecSingleton in the store. + * @param name - Name of the singleton + * @returns A new AztecSingleton + */ + createSingleton(name: string): AztecSingleton { + return new LmdbAztecSingleton(this.#data, name); + } + + /** + * Runs a callback in a transaction. + * @param callback - Function to execute in a transaction + * @returns A promise that resolves to the return value of the callback + */ + transaction(callback: () => T): Promise { + return this.#rootDb.transaction(callback); + } + + async #init(rollupAddress: EthAddress): Promise { + const storedRollupAddress = this.#rollupAddress.get(); + const rollupAddressString = rollupAddress.toString(); + + if (typeof storedRollupAddress === 'string' && rollupAddressString !== storedRollupAddress) { + this.#log.warn( + `Rollup address mismatch: expected ${rollupAddress}, found ${storedRollupAddress}. Clearing entire database...`, + ); + await this.#rootDb.clearAsync(); + } + + await this.#rollupAddress.set(rollupAddressString); + } +} diff --git a/yarn-project/kv-store/tsconfig.json b/yarn-project/kv-store/tsconfig.json new file mode 100644 index 00000000000..63f8ab3e9f7 --- /dev/null +++ b/yarn-project/kv-store/tsconfig.json @@ -0,0 +1,14 @@ +{ + "extends": "..", + "compilerOptions": { + "outDir": "dest", + "rootDir": "src", + "tsBuildInfoFile": ".tsbuildinfo" + }, + "references": [ + { + "path": "../foundation" + } + ], + "include": ["src"] +} diff --git a/yarn-project/package.json b/yarn-project/package.json index 34945e2ad55..542e94b28e4 100644 --- a/yarn-project/package.json +++ b/yarn-project/package.json @@ -46,7 +46,8 @@ "scripts", "types", "world-state", - "yarn-project-base" + "yarn-project-base", + "kv-store" ], "prettier": "@aztec/foundation/prettier", "devDependencies": { diff --git a/yarn-project/pxe/package.json b/yarn-project/pxe/package.json index b426db2c3ed..b1892b3b1f3 100644 --- a/yarn-project/pxe/package.json +++ b/yarn-project/pxe/package.json @@ -29,7 +29,8 @@ "^(\\.{1,2}/.*)\\.[cm]?js$": "$1" }, "testRegex": "./src/.*\\.test\\.(js|mjs|ts)$", - "rootDir": "./src" + "rootDir": "./src", + "workerThreads": true }, "dependencies": { "@aztec/acir-simulator": "workspace:^", @@ -37,6 +38,7 @@ "@aztec/ethereum": "workspace:^", "@aztec/foundation": "workspace:^", "@aztec/key-store": "workspace:^", + "@aztec/kv-store": "workspace:^", "@aztec/noir-compiler": "workspace:^", "@aztec/noir-protocol-circuits": "workspace:^", "@aztec/types": "workspace:^", diff --git a/yarn-project/pxe/src/config/index.ts b/yarn-project/pxe/src/config/index.ts index 8c511ce4fa0..e96a5e64519 100644 --- a/yarn-project/pxe/src/config/index.ts +++ b/yarn-project/pxe/src/config/index.ts @@ -12,17 +12,21 @@ export interface PXEServiceConfig { l2BlockPollingIntervalMS: number; /** L2 block to start scanning from */ l2StartingBlock: number; + + /** Where to store PXE data. If not set will store in memory */ + dataDirectory?: string; } /** * Creates an instance of PXEServiceConfig out of environment variables using sensible defaults for integration testing if not set. */ export function getPXEServiceConfig(): PXEServiceConfig { - const { PXE_BLOCK_POLLING_INTERVAL_MS, PXE_L2_STARTING_BLOCK } = process.env; + const { PXE_BLOCK_POLLING_INTERVAL_MS, PXE_L2_STARTING_BLOCK, DATA_DIRECTORY } = process.env; return { l2BlockPollingIntervalMS: PXE_BLOCK_POLLING_INTERVAL_MS ? +PXE_BLOCK_POLLING_INTERVAL_MS : 1000, l2StartingBlock: PXE_L2_STARTING_BLOCK ? +PXE_L2_STARTING_BLOCK : INITIAL_L2_BLOCK_NUM, + dataDirectory: DATA_DIRECTORY, }; } diff --git a/yarn-project/pxe/src/contract_tree/index.ts b/yarn-project/pxe/src/contract_tree/index.ts index 2c3f9de54dc..8078e310f3d 100644 --- a/yarn-project/pxe/src/contract_tree/index.ts +++ b/yarn-project/pxe/src/contract_tree/index.ts @@ -93,12 +93,7 @@ export class ContractTree { const completeAddress = computeCompleteAddress(from, contractAddressSalt, root, constructorHash); - const contractDao: ContractDao = { - ...artifact, - completeAddress, - functions, - portalContract, - }; + const contractDao = new ContractDao(artifact, completeAddress, portalContract); const NewContractConstructor = { functionData, vkHash, diff --git a/yarn-project/pxe/src/database/index.ts b/yarn-project/pxe/src/database/index.ts index d1306dbafe0..35d4e000a20 100644 --- a/yarn-project/pxe/src/database/index.ts +++ b/yarn-project/pxe/src/database/index.ts @@ -1,2 +1,2 @@ -export * from './database.js'; +export * from './pxe_database.js'; export * from './memory_db.js'; diff --git a/yarn-project/pxe/src/database/kv_pxe_database.test.ts b/yarn-project/pxe/src/database/kv_pxe_database.test.ts new file mode 100644 index 00000000000..a9054af0719 --- /dev/null +++ b/yarn-project/pxe/src/database/kv_pxe_database.test.ts @@ -0,0 +1,15 @@ +import { EthAddress } from '@aztec/circuits.js'; +import { AztecLmdbStore } from '@aztec/kv-store'; + +import { KVPxeDatabase } from './kv_pxe_database.js'; +import { describePxeDatabase } from './pxe_database_test_suite.js'; + +describe('KVPxeDatabase', () => { + let database: KVPxeDatabase; + + beforeEach(async () => { + database = new KVPxeDatabase(await AztecLmdbStore.create(EthAddress.random())); + }); + + describePxeDatabase(() => database); +}); diff --git a/yarn-project/pxe/src/database/kv_pxe_database.ts b/yarn-project/pxe/src/database/kv_pxe_database.ts new file mode 100644 index 00000000000..8e5e27c2b8b --- /dev/null +++ b/yarn-project/pxe/src/database/kv_pxe_database.ts @@ -0,0 +1,288 @@ +import { AztecAddress, BlockHeader, CompleteAddress } from '@aztec/circuits.js'; +import { Fr } from '@aztec/foundation/fields'; +import { AztecArray, AztecKVStore, AztecMap, AztecMultiMap, AztecSingleton } from '@aztec/kv-store'; +import { ContractDao, MerkleTreeId, NoteFilter, PublicKey } from '@aztec/types'; + +import { NoteDao } from './note_dao.js'; +import { PxeDatabase } from './pxe_database.js'; + +/** Serialized structure of a block header */ +type SerializedBlockHeader = { + /** The tree roots when the block was created */ + roots: Record; + /** The hash of the global variables */ + globalVariablesHash: string; +}; + +/** + * A PXE database backed by LMDB. + */ +export class KVPxeDatabase implements PxeDatabase { + #blockHeader: AztecSingleton; + #addresses: AztecArray; + #addressIndex: AztecMap; + #authWitnesses: AztecMap; + #capsules: AztecArray; + #contracts: AztecMap; + #notes: AztecArray; + #nullifiedNotes: AztecMap; + #notesByContract: AztecMultiMap; + #notesByStorageSlot: AztecMultiMap; + #notesByTxHash: AztecMultiMap; + #notesByOwner: AztecMultiMap; + #db: AztecKVStore; + + constructor(db: AztecKVStore) { + this.#db = db; + + this.#addresses = db.createArray('addresses'); + this.#addressIndex = db.createMap('address_index'); + + this.#authWitnesses = db.createMap('auth_witnesses'); + this.#capsules = db.createArray('capsules'); + this.#blockHeader = db.createSingleton('block_header'); + this.#contracts = db.createMap('contracts'); + + this.#notes = db.createArray('notes'); + this.#nullifiedNotes = db.createMap('nullified_notes'); + + this.#notesByContract = db.createMultiMap('notes_by_contract'); + this.#notesByStorageSlot = db.createMultiMap('notes_by_storage_slot'); + this.#notesByTxHash = db.createMultiMap('notes_by_tx_hash'); + this.#notesByOwner = db.createMultiMap('notes_by_owner'); + } + + async addAuthWitness(messageHash: Fr, witness: Fr[]): Promise { + await this.#authWitnesses.set( + messageHash.toString(), + witness.map(w => w.toBuffer()), + ); + } + + getAuthWitness(messageHash: Fr): Promise { + const witness = this.#authWitnesses.get(messageHash.toString()); + return Promise.resolve(witness?.map(w => Fr.fromBuffer(w))); + } + + async addCapsule(capsule: Fr[]): Promise { + await this.#capsules.push(capsule.map(c => c.toBuffer())); + } + + async popCapsule(): Promise { + const val = await this.#capsules.pop(); + return val?.map(b => Fr.fromBuffer(b)); + } + + async addNote(note: NoteDao): Promise { + await this.addNotes([note]); + } + + async addNotes(notes: NoteDao[]): Promise { + const newLength = await this.#notes.push(...notes.map(note => note.toBuffer())); + for (const [index, note] of notes.entries()) { + const noteId = newLength - notes.length + index; + await Promise.all([ + this.#notesByContract.set(note.contractAddress.toString(), noteId), + this.#notesByStorageSlot.set(note.storageSlot.toString(), noteId), + this.#notesByTxHash.set(note.txHash.toString(), noteId), + this.#notesByOwner.set(note.publicKey.toString(), noteId), + ]); + } + } + + *#getAllNonNullifiedNotes(): IterableIterator { + for (const [index, serialized] of this.#notes.entries()) { + if (this.#nullifiedNotes.has(index)) { + continue; + } + + yield NoteDao.fromBuffer(serialized); + } + } + + async getNotes(filter: NoteFilter): Promise { + const publicKey: PublicKey | undefined = filter.owner + ? (await this.getCompleteAddress(filter.owner))?.publicKey + : undefined; + + const initialNoteIds = publicKey + ? this.#notesByOwner.getValues(publicKey.toString()) + : filter.txHash + ? this.#notesByTxHash.getValues(filter.txHash.toString()) + : filter.contractAddress + ? this.#notesByContract.getValues(filter.contractAddress.toString()) + : filter.storageSlot + ? this.#notesByStorageSlot.getValues(filter.storageSlot.toString()) + : undefined; + + if (!initialNoteIds) { + return Array.from(this.#getAllNonNullifiedNotes()); + } + + const result: NoteDao[] = []; + for (const noteId of initialNoteIds) { + const serializedNote = this.#notes.at(noteId); + if (!serializedNote) { + continue; + } + + const note = NoteDao.fromBuffer(serializedNote); + if (filter.contractAddress && !note.contractAddress.equals(filter.contractAddress)) { + continue; + } + + if (filter.txHash && !note.txHash.equals(filter.txHash)) { + continue; + } + + if (filter.storageSlot && !note.storageSlot.equals(filter.storageSlot!)) { + continue; + } + + if (publicKey && !note.publicKey.equals(publicKey)) { + continue; + } + + result.push(note); + } + + return result; + } + + removeNullifiedNotes(nullifiers: Fr[], account: PublicKey): Promise { + const nullifierSet = new Set(nullifiers.map(n => n.toString())); + return this.#db.transaction(() => { + const notesIds = this.#notesByOwner.getValues(account.toString()); + const nullifiedNotes: NoteDao[] = []; + + for (const noteId of notesIds) { + const note = NoteDao.fromBuffer(this.#notes.at(noteId)!); + if (nullifierSet.has(note.siloedNullifier.toString())) { + nullifiedNotes.push(note); + + void this.#nullifiedNotes.set(noteId, true); + void this.#notesByOwner.deleteValue(account.toString(), noteId); + void this.#notesByTxHash.deleteValue(note.txHash.toString(), noteId); + void this.#notesByContract.deleteValue(note.contractAddress.toString(), noteId); + void this.#notesByStorageSlot.deleteValue(note.storageSlot.toString(), noteId); + } + } + + return nullifiedNotes; + }); + } + + getTreeRoots(): Record { + const roots = this.#blockHeader.get()?.roots; + if (!roots) { + throw new Error(`Tree roots not set`); + } + + return { + [MerkleTreeId.ARCHIVE]: Fr.fromString(roots[MerkleTreeId.ARCHIVE]), + [MerkleTreeId.CONTRACT_TREE]: Fr.fromString(roots[MerkleTreeId.CONTRACT_TREE].toString()), + [MerkleTreeId.L1_TO_L2_MESSAGES_TREE]: Fr.fromString(roots[MerkleTreeId.L1_TO_L2_MESSAGES_TREE].toString()), + [MerkleTreeId.NOTE_HASH_TREE]: Fr.fromString(roots[MerkleTreeId.NOTE_HASH_TREE].toString()), + [MerkleTreeId.PUBLIC_DATA_TREE]: Fr.fromString(roots[MerkleTreeId.PUBLIC_DATA_TREE].toString()), + [MerkleTreeId.NULLIFIER_TREE]: Fr.fromString(roots[MerkleTreeId.NULLIFIER_TREE].toString()), + }; + } + + async setBlockHeader(blockHeader: BlockHeader): Promise { + await this.#blockHeader.set({ + globalVariablesHash: blockHeader.globalVariablesHash.toString(), + roots: { + [MerkleTreeId.NOTE_HASH_TREE]: blockHeader.noteHashTreeRoot.toString(), + [MerkleTreeId.NULLIFIER_TREE]: blockHeader.nullifierTreeRoot.toString(), + [MerkleTreeId.CONTRACT_TREE]: blockHeader.contractTreeRoot.toString(), + [MerkleTreeId.L1_TO_L2_MESSAGES_TREE]: blockHeader.l1ToL2MessagesTreeRoot.toString(), + [MerkleTreeId.ARCHIVE]: blockHeader.archiveRoot.toString(), + [MerkleTreeId.PUBLIC_DATA_TREE]: blockHeader.publicDataTreeRoot.toString(), + }, + }); + } + + getBlockHeader(): BlockHeader { + const value = this.#blockHeader.get(); + if (!value) { + throw new Error(`Block header not set`); + } + + const blockHeader = new BlockHeader( + Fr.fromString(value.roots[MerkleTreeId.NOTE_HASH_TREE]), + Fr.fromString(value.roots[MerkleTreeId.NULLIFIER_TREE]), + Fr.fromString(value.roots[MerkleTreeId.CONTRACT_TREE]), + Fr.fromString(value.roots[MerkleTreeId.L1_TO_L2_MESSAGES_TREE]), + Fr.fromString(value.roots[MerkleTreeId.ARCHIVE]), + Fr.ZERO, // todo: private kernel vk tree root + Fr.fromString(value.roots[MerkleTreeId.PUBLIC_DATA_TREE]), + Fr.fromString(value.globalVariablesHash), + ); + + return blockHeader; + } + + addCompleteAddress(completeAddress: CompleteAddress): Promise { + return this.#db.transaction(() => { + const addressString = completeAddress.address.toString(); + const buffer = completeAddress.toBuffer(); + const existing = this.#addressIndex.get(addressString); + if (typeof existing === 'undefined') { + const index = this.#addresses.length; + void this.#addresses.push(buffer); + void this.#addressIndex.set(addressString, index); + + return true; + } else { + const existingBuffer = this.#addresses.at(existing); + + if (existingBuffer?.equals(buffer)) { + return false; + } + + throw new Error( + `Complete address with aztec address ${addressString} but different public key or partial key already exists in memory database`, + ); + } + }); + } + + getCompleteAddress(address: AztecAddress): Promise { + const index = this.#addressIndex.get(address.toString()); + if (typeof index === 'undefined') { + return Promise.resolve(undefined); + } + + const value = this.#addresses.at(index); + return Promise.resolve(value ? CompleteAddress.fromBuffer(value) : undefined); + } + + getCompleteAddresses(): Promise { + return Promise.resolve(Array.from(this.#addresses).map(v => CompleteAddress.fromBuffer(v))); + } + + estimateSize(): number { + const notesSize = Array.from(this.#getAllNonNullifiedNotes()).reduce((sum, note) => sum + note.getSize(), 0); + const authWitsSize = Array.from(this.#authWitnesses.values()).reduce( + (sum, value) => sum + value.length * Fr.SIZE_IN_BYTES, + 0, + ); + const addressesSize = this.#addresses.length * CompleteAddress.SIZE_IN_BYTES; + const treeRootsSize = Object.keys(MerkleTreeId).length * Fr.SIZE_IN_BYTES; + + return notesSize + treeRootsSize + authWitsSize + addressesSize; + } + + async addContract(contract: ContractDao): Promise { + await this.#contracts.set(contract.completeAddress.address.toString(), contract.toBuffer()); + } + + getContract(address: AztecAddress): Promise { + const contract = this.#contracts.get(address.toString()); + return Promise.resolve(contract ? ContractDao.fromBuffer(contract) : undefined); + } + + getContracts(): Promise { + return Promise.resolve(Array.from(this.#contracts.values()).map(c => ContractDao.fromBuffer(c))); + } +} diff --git a/yarn-project/pxe/src/database/memory_db.test.ts b/yarn-project/pxe/src/database/memory_db.test.ts index 077f705167a..f505efa4a79 100644 --- a/yarn-project/pxe/src/database/memory_db.test.ts +++ b/yarn-project/pxe/src/database/memory_db.test.ts @@ -2,6 +2,7 @@ import { AztecAddress, Fr } from '@aztec/circuits.js'; import { MemoryDB } from './memory_db.js'; import { randomNoteDao } from './note_dao.test.js'; +import { describePxeDatabase } from './pxe_database_test_suite.js'; describe('Memory DB', () => { let db: MemoryDB; @@ -10,6 +11,8 @@ describe('Memory DB', () => { db = new MemoryDB(); }); + describePxeDatabase(() => db); + describe('NoteDao', () => { const contractAddress = AztecAddress.random(); const storageSlot = Fr.random(); diff --git a/yarn-project/pxe/src/database/memory_db.ts b/yarn-project/pxe/src/database/memory_db.ts index 4f2849b42e5..641603b0210 100644 --- a/yarn-project/pxe/src/database/memory_db.ts +++ b/yarn-project/pxe/src/database/memory_db.ts @@ -5,8 +5,8 @@ import { createDebugLogger } from '@aztec/foundation/log'; import { MerkleTreeId, NoteFilter } from '@aztec/types'; import { MemoryContractDatabase } from '../contract_database/index.js'; -import { Database } from './database.js'; import { NoteDao } from './note_dao.js'; +import { PxeDatabase } from './pxe_database.js'; /** * The MemoryDB class provides an in-memory implementation of a database to manage transactions and auxiliary data. @@ -14,7 +14,7 @@ import { NoteDao } from './note_dao.js'; * The class offers methods to add, fetch, and remove transaction records and auxiliary data based on various filters such as transaction hash, address, and storage slot. * As an in-memory database, the stored data will not persist beyond the life of the application instance. */ -export class MemoryDB extends MemoryContractDatabase implements Database { +export class MemoryDB extends MemoryContractDatabase implements PxeDatabase { private notesTable: NoteDao[] = []; private treeRoots: Record | undefined; private globalVariablesHash: Fr | undefined; @@ -43,7 +43,7 @@ export class MemoryDB extends MemoryContractDatabase implements Database { * @param messageHash - The message hash. * @returns A Promise that resolves to an array of field elements representing the auth witness. */ - public getAuthWitness(messageHash: Fr): Promise { + public getAuthWitness(messageHash: Fr): Promise { return Promise.resolve(this.authWitnesses[messageHash.toString()]); } @@ -113,9 +113,8 @@ export class MemoryDB extends MemoryContractDatabase implements Database { return roots; } - public setTreeRoots(roots: Record) { + private setTreeRoots(roots: Record) { this.treeRoots = roots; - return Promise.resolve(); } public getBlockHeader(): BlockHeader { @@ -135,9 +134,9 @@ export class MemoryDB extends MemoryContractDatabase implements Database { ); } - public async setBlockHeader(blockHeader: BlockHeader): Promise { + public setBlockHeader(blockHeader: BlockHeader): Promise { this.globalVariablesHash = blockHeader.globalVariablesHash; - await this.setTreeRoots({ + this.setTreeRoots({ [MerkleTreeId.NOTE_HASH_TREE]: blockHeader.noteHashTreeRoot, [MerkleTreeId.NULLIFIER_TREE]: blockHeader.nullifierTreeRoot, [MerkleTreeId.CONTRACT_TREE]: blockHeader.contractTreeRoot, @@ -145,6 +144,8 @@ export class MemoryDB extends MemoryContractDatabase implements Database { [MerkleTreeId.ARCHIVE]: blockHeader.archiveRoot, [MerkleTreeId.PUBLIC_DATA_TREE]: blockHeader.publicDataTreeRoot, }); + + return Promise.resolve(); } public addCompleteAddress(completeAddress: CompleteAddress): Promise { @@ -154,8 +155,10 @@ export class MemoryDB extends MemoryContractDatabase implements Database { return Promise.resolve(false); } - throw new Error( - `Complete address with aztec address ${completeAddress.address.toString()} but different public key or partial key already exists in memory database`, + return Promise.reject( + new Error( + `Complete address with aztec address ${completeAddress.address.toString()} but different public key or partial key already exists in memory database`, + ), ); } this.addresses.push(completeAddress); diff --git a/yarn-project/pxe/src/database/database.ts b/yarn-project/pxe/src/database/pxe_database.ts similarity index 88% rename from yarn-project/pxe/src/database/database.ts rename to yarn-project/pxe/src/database/pxe_database.ts index 72f50a1c576..0c7f1551770 100644 --- a/yarn-project/pxe/src/database/database.ts +++ b/yarn-project/pxe/src/database/pxe_database.ts @@ -9,7 +9,7 @@ import { NoteDao } from './note_dao.js'; * A database interface that provides methods for retrieving, adding, and removing transactional data related to Aztec * addresses, storage slots, and nullifiers. */ -export interface Database extends ContractDatabase { +export interface PxeDatabase extends ContractDatabase { /** * Add a auth witness to the database. * @param messageHash - The message hash. @@ -22,7 +22,7 @@ export interface Database extends ContractDatabase { * @param messageHash - The message hash. * @returns A Promise that resolves to an array of field elements representing the auth witness. */ - getAuthWitness(messageHash: Fr): Promise; + getAuthWitness(messageHash: Fr): Promise; /** * Adding a capsule to the capsule dispenser. @@ -79,17 +79,6 @@ export interface Database extends ContractDatabase { */ getTreeRoots(): Record; - /** - * Set the tree roots for the Merkle trees in the database. - * This function updates the 'treeRoots' property of the instance - * with the provided 'roots' object containing MerkleTreeId and Fr pairs. - * Note that this will overwrite any existing tree roots in the database. - * - * @param roots - A Record object mapping MerkleTreeIds to their corresponding Fr root values. - * @returns A Promise that resolves when the tree roots have been successfully updated in the database. - */ - setTreeRoots(roots: Record): Promise; - /** * Retrieve the stored Block Header from the database. * The function returns a Promise that resolves to the Block Header. diff --git a/yarn-project/pxe/src/database/pxe_database_test_suite.ts b/yarn-project/pxe/src/database/pxe_database_test_suite.ts new file mode 100644 index 00000000000..69eaff032b9 --- /dev/null +++ b/yarn-project/pxe/src/database/pxe_database_test_suite.ts @@ -0,0 +1,220 @@ +import { AztecAddress, BlockHeader, CompleteAddress } from '@aztec/circuits.js'; +import { Fr, Point } from '@aztec/foundation/fields'; +import { MerkleTreeId, NoteFilter, randomTxHash } from '@aztec/types'; + +import { NoteDao } from './note_dao.js'; +import { randomNoteDao } from './note_dao.test.js'; +import { PxeDatabase } from './pxe_database.js'; + +/** + * A common test suite for a PXE database. + * @param getDatabase - A function that returns a database instance. + */ +export function describePxeDatabase(getDatabase: () => PxeDatabase) { + let database: PxeDatabase; + + beforeEach(() => { + database = getDatabase(); + }); + + describe('Database', () => { + describe('auth witnesses', () => { + it('stores and retrieves auth witnesses', async () => { + const messageHash = Fr.random(); + const witness = [Fr.random(), Fr.random()]; + + await database.addAuthWitness(messageHash, witness); + await expect(database.getAuthWitness(messageHash)).resolves.toEqual(witness); + }); + + it("returns undefined if it doesn't have auth witnesses for the message", async () => { + const messageHash = Fr.random(); + await expect(database.getAuthWitness(messageHash)).resolves.toBeUndefined(); + }); + + it.skip('refuses to overwrite auth witnesses for the same message', async () => { + const messageHash = Fr.random(); + const witness = [Fr.random(), Fr.random()]; + + await database.addAuthWitness(messageHash, witness); + await expect(database.addAuthWitness(messageHash, witness)).rejects.toThrow(); + }); + }); + + describe('capsules', () => { + it('stores and retrieves capsules', async () => { + const capsule = [Fr.random(), Fr.random()]; + + await database.addCapsule(capsule); + await expect(database.popCapsule()).resolves.toEqual(capsule); + }); + + it("returns undefined if it doesn't have capsules", async () => { + await expect(database.popCapsule()).resolves.toBeUndefined(); + }); + + it('behaves like a stack when storing capsules', async () => { + const capsule1 = [Fr.random(), Fr.random()]; + const capsule2 = [Fr.random(), Fr.random()]; + + await database.addCapsule(capsule1); + await database.addCapsule(capsule2); + await expect(database.popCapsule()).resolves.toEqual(capsule2); + await expect(database.popCapsule()).resolves.toEqual(capsule1); + }); + }); + + describe('notes', () => { + let owners: CompleteAddress[]; + let contractAddresses: AztecAddress[]; + let storageSlots: Fr[]; + let notes: NoteDao[]; + + const filteringTests: [() => NoteFilter, () => NoteDao[]][] = [ + [() => ({}), () => notes], + + [ + () => ({ contractAddress: contractAddresses[0] }), + () => notes.filter(note => note.contractAddress.equals(contractAddresses[0])), + ], + [() => ({ contractAddress: AztecAddress.random() }), () => []], + + [ + () => ({ storageSlot: storageSlots[0] }), + () => notes.filter(note => note.storageSlot.equals(storageSlots[0])), + ], + [() => ({ storageSlot: Fr.random() }), () => []], + + [() => ({ txHash: notes[0].txHash }), () => [notes[0]]], + [() => ({ txHash: randomTxHash() }), () => []], + + [() => ({ owner: owners[0].address }), () => notes.filter(note => note.publicKey.equals(owners[0].publicKey))], + + [ + () => ({ contractAddress: contractAddresses[0], storageSlot: storageSlots[0] }), + () => + notes.filter( + note => note.contractAddress.equals(contractAddresses[0]) && note.storageSlot.equals(storageSlots[0]), + ), + ], + [() => ({ contractAddress: contractAddresses[0], storageSlot: storageSlots[1] }), () => []], + ]; + + beforeEach(() => { + owners = Array.from({ length: 2 }).map(() => CompleteAddress.random()); + contractAddresses = Array.from({ length: 2 }).map(() => AztecAddress.random()); + storageSlots = Array.from({ length: 2 }).map(() => Fr.random()); + + notes = Array.from({ length: 10 }).map((_, i) => + randomNoteDao({ + contractAddress: contractAddresses[i % contractAddresses.length], + storageSlot: storageSlots[i % storageSlots.length], + publicKey: owners[i % owners.length].publicKey, + }), + ); + }); + + beforeEach(async () => { + for (const owner of owners) { + await database.addCompleteAddress(owner); + } + }); + + it.each(filteringTests)('stores notes in bulk and retrieves notes', async (getFilter, getExpected) => { + await database.addNotes(notes); + await expect(database.getNotes(getFilter())).resolves.toEqual(getExpected()); + }); + + it.each(filteringTests)('stores notes one by one and retrieves notes', async (getFilter, getExpected) => { + for (const note of notes) { + await database.addNote(note); + } + await expect(database.getNotes(getFilter())).resolves.toEqual(getExpected()); + }); + + it('removes nullified notes', async () => { + const notesToNullify = notes.filter(note => note.publicKey.equals(owners[0].publicKey)); + const nullifiers = notesToNullify.map(note => note.siloedNullifier); + + await database.addNotes(notes); + + await expect(database.removeNullifiedNotes(nullifiers, notesToNullify[0].publicKey)).resolves.toEqual( + notesToNullify, + ); + await expect( + database.getNotes({ + owner: owners[0].address, + }), + ).resolves.toEqual([]); + await expect(database.getNotes({})).resolves.toEqual(notes.filter(note => !notesToNullify.includes(note))); + }); + }); + + describe('block header', () => { + it('stores and retrieves the block header', async () => { + const blockHeader = BlockHeader.random(); + blockHeader.privateKernelVkTreeRoot = Fr.zero(); + + await database.setBlockHeader(blockHeader); + expect(database.getBlockHeader()).toEqual(blockHeader); + }); + + it('retrieves the merkle tree roots from the block', async () => { + const blockHeader = BlockHeader.random(); + await database.setBlockHeader(blockHeader); + expect(database.getTreeRoots()).toEqual({ + [MerkleTreeId.NOTE_HASH_TREE]: blockHeader.noteHashTreeRoot, + [MerkleTreeId.NULLIFIER_TREE]: blockHeader.nullifierTreeRoot, + [MerkleTreeId.CONTRACT_TREE]: blockHeader.contractTreeRoot, + [MerkleTreeId.L1_TO_L2_MESSAGES_TREE]: blockHeader.l1ToL2MessagesTreeRoot, + [MerkleTreeId.ARCHIVE]: blockHeader.archiveRoot, + [MerkleTreeId.PUBLIC_DATA_TREE]: blockHeader.publicDataTreeRoot, + }); + }); + + it('rejects getting merkle tree roots if no block set', () => { + expect(() => database.getTreeRoots()).toThrow(); + }); + }); + + describe('addresses', () => { + it('stores and retrieves addresses', async () => { + const address = CompleteAddress.random(); + await expect(database.addCompleteAddress(address)).resolves.toBe(true); + await expect(database.getCompleteAddress(address.address)).resolves.toEqual(address); + }); + + it('silently ignores an address it already knows about', async () => { + const address = CompleteAddress.random(); + await expect(database.addCompleteAddress(address)).resolves.toBe(true); + await expect(database.addCompleteAddress(address)).resolves.toBe(false); + }); + + it.skip('refuses to overwrite an address with a different public key', async () => { + const address = CompleteAddress.random(); + const otherAddress = new CompleteAddress(address.address, Point.random(), address.partialAddress); + + await database.addCompleteAddress(address); + await expect(database.addCompleteAddress(otherAddress)).rejects.toThrow(); + }); + + it('returns all addresses', async () => { + const addresses = Array.from({ length: 10 }).map(() => CompleteAddress.random()); + for (const address of addresses) { + await database.addCompleteAddress(address); + } + + const result = await database.getCompleteAddresses(); + expect(result).toEqual(expect.arrayContaining(addresses)); + }); + + it("returns an empty array if it doesn't have addresses", async () => { + expect(await database.getCompleteAddresses()).toEqual([]); + }); + + it("returns undefined if it doesn't have an address", async () => { + expect(await database.getCompleteAddress(CompleteAddress.random().address)).toBeUndefined(); + }); + }); + }); +} diff --git a/yarn-project/pxe/src/note_processor/note_processor.test.ts b/yarn-project/pxe/src/note_processor/note_processor.test.ts index d766a04c336..a317c24cddd 100644 --- a/yarn-project/pxe/src/note_processor/note_processor.test.ts +++ b/yarn-project/pxe/src/note_processor/note_processor.test.ts @@ -1,9 +1,10 @@ import { AcirSimulator } from '@aztec/acir-simulator'; -import { Fr, MAX_NEW_COMMITMENTS_PER_TX } from '@aztec/circuits.js'; +import { EthAddress, Fr, MAX_NEW_COMMITMENTS_PER_TX } from '@aztec/circuits.js'; import { Grumpkin } from '@aztec/circuits.js/barretenberg'; import { pedersenHash } from '@aztec/foundation/crypto'; import { Point } from '@aztec/foundation/fields'; import { ConstantKeyPair } from '@aztec/key-store'; +import { AztecLmdbStore } from '@aztec/kv-store'; import { AztecNode, FunctionL2Logs, @@ -21,7 +22,8 @@ import { import { jest } from '@jest/globals'; import { MockProxy, mock } from 'jest-mock-extended'; -import { Database, MemoryDB } from '../database/index.js'; +import { PxeDatabase } from '../database/index.js'; +import { KVPxeDatabase } from '../database/kv_pxe_database.js'; import { NoteDao } from '../database/note_dao.js'; import { NoteProcessor } from './note_processor.js'; @@ -29,7 +31,7 @@ const TXS_PER_BLOCK = 4; describe('Note Processor', () => { let grumpkin: Grumpkin; - let database: Database; + let database: PxeDatabase; let aztecNode: ReturnType>; let addNotesSpy: any; let noteProcessor: NoteProcessor; @@ -114,8 +116,8 @@ describe('Note Processor', () => { owner = ConstantKeyPair.random(grumpkin); }); - beforeEach(() => { - database = new MemoryDB(); + beforeEach(async () => { + database = new KVPxeDatabase(await AztecLmdbStore.create(EthAddress.random())); addNotesSpy = jest.spyOn(database, 'addNotes'); aztecNode = mock(); diff --git a/yarn-project/pxe/src/note_processor/note_processor.ts b/yarn-project/pxe/src/note_processor/note_processor.ts index 0f07830436f..436085df589 100644 --- a/yarn-project/pxe/src/note_processor/note_processor.ts +++ b/yarn-project/pxe/src/note_processor/note_processor.ts @@ -7,7 +7,7 @@ import { Timer } from '@aztec/foundation/timer'; import { AztecNode, KeyStore, L1NotePayload, L2BlockContext, L2BlockL2Logs } from '@aztec/types'; import { NoteProcessorStats } from '@aztec/types/stats'; -import { Database } from '../database/index.js'; +import { PxeDatabase } from '../database/index.js'; import { NoteDao } from '../database/note_dao.js'; import { getAcirSimulator } from '../simulator/index.js'; @@ -45,7 +45,7 @@ export class NoteProcessor { */ public readonly publicKey: PublicKey, private keyStore: KeyStore, - private db: Database, + private db: PxeDatabase, private node: AztecNode, private startingBlock: number, private simulator = getAcirSimulator(db, node, keyStore), diff --git a/yarn-project/pxe/src/pxe_service/create_pxe_service.ts b/yarn-project/pxe/src/pxe_service/create_pxe_service.ts index 04eddd7db48..f2942d8a800 100644 --- a/yarn-project/pxe/src/pxe_service/create_pxe_service.ts +++ b/yarn-project/pxe/src/pxe_service/create_pxe_service.ts @@ -1,25 +1,14 @@ import { Grumpkin } from '@aztec/circuits.js/barretenberg'; import { TestKeyStore } from '@aztec/key-store'; -import { AztecNode, KeyStore } from '@aztec/types'; +import { AztecLmdbStore } from '@aztec/kv-store'; +import { AztecNode } from '@aztec/types'; + +import { join } from 'path'; import { PXEServiceConfig } from '../config/index.js'; -import { Database, MemoryDB } from '../database/index.js'; +import { KVPxeDatabase } from '../database/kv_pxe_database.js'; import { PXEService } from './pxe_service.js'; -/** - * Optional information for creating an PXEService. - */ -interface CreatePXEServiceOptions { - /** - * A secure storage for cryptographic keys. - */ - keyStore?: KeyStore; - /** - * Storage for the PXE. - */ - db?: Database; -} - /** * Create and start an PXEService instance with the given AztecNode. * If no keyStore or database is provided, it will use TestKeyStore and MemoryDB as default values. @@ -33,7 +22,6 @@ interface CreatePXEServiceOptions { export async function createPXEService( aztecNode: AztecNode, config: PXEServiceConfig, - { keyStore, db }: CreatePXEServiceOptions = {}, useLogSuffix: string | boolean | undefined = undefined, ) { const logSuffix = @@ -43,10 +31,18 @@ export async function createPXEService( : undefined : useLogSuffix; - keyStore = keyStore || new TestKeyStore(new Grumpkin()); - db = db || new MemoryDB(logSuffix); + const pxeDbPath = config.dataDirectory ? join(config.dataDirectory, 'pxe_data') : undefined; + const keyStorePath = config.dataDirectory ? join(config.dataDirectory, 'pxe_key_store') : undefined; + const l1Contracts = await aztecNode.getL1ContractAddresses(); + + const keyStore = new TestKeyStore( + new Grumpkin(), + await AztecLmdbStore.create(l1Contracts.rollupAddress, keyStorePath), + ); + const db = new KVPxeDatabase(await AztecLmdbStore.create(l1Contracts.rollupAddress, pxeDbPath)); const server = new PXEService(keyStore, aztecNode, db, config, logSuffix); + await server.start(); return server; } diff --git a/yarn-project/pxe/src/pxe_service/pxe_service.ts b/yarn-project/pxe/src/pxe_service/pxe_service.ts index 37f4eb7dcb3..f4cf6eb29d9 100644 --- a/yarn-project/pxe/src/pxe_service/pxe_service.ts +++ b/yarn-project/pxe/src/pxe_service/pxe_service.ts @@ -50,12 +50,11 @@ import { TxStatus, getNewContractPublicFunctions, isNoirCallStackUnresolved, - toContractDao, } from '@aztec/types'; import { PXEServiceConfig, getPackageInfo } from '../config/index.js'; import { ContractDataOracle } from '../contract_data_oracle/index.js'; -import { Database } from '../database/index.js'; +import { PxeDatabase } from '../database/index.js'; import { NoteDao } from '../database/note_dao.js'; import { KernelOracle } from '../kernel_oracle/index.js'; import { KernelProver } from '../kernel_prover/kernel_prover.js'; @@ -75,7 +74,7 @@ export class PXEService implements PXE { constructor( private keyStore: KeyStore, private node: AztecNode, - private db: Database, + private db: PxeDatabase, private config: PXEServiceConfig, logSuffix?: string, ) { @@ -128,7 +127,7 @@ export class PXEService implements PXE { const completeAddress = CompleteAddress.fromPrivateKeyAndPartialAddress(privKey, partialAddress); const wasAdded = await this.db.addCompleteAddress(completeAddress); if (wasAdded) { - const pubKey = this.keyStore.addAccount(privKey); + const pubKey = await this.keyStore.addAccount(privKey); this.synchronizer.addAccount(pubKey, this.keyStore, this.config.l2StartingBlock); this.log.info(`Registered account ${completeAddress.address.toString()}`); this.log.debug(`Registered account\n ${completeAddress.toReadableString()}`); @@ -178,7 +177,7 @@ export class PXEService implements PXE { } public async addContracts(contracts: DeployedContract[]) { - const contractDaos = contracts.map(c => toContractDao(c.artifact, c.completeAddress, c.portalContract)); + const contractDaos = contracts.map(c => new ContractDao(c.artifact, c.completeAddress, c.portalContract)); await Promise.all(contractDaos.map(c => this.db.addContract(c))); for (const contract of contractDaos) { const portalInfo = diff --git a/yarn-project/pxe/src/pxe_service/test/pxe_service.test.ts b/yarn-project/pxe/src/pxe_service/test/pxe_service.test.ts index e265d99a898..e55560280a0 100644 --- a/yarn-project/pxe/src/pxe_service/test/pxe_service.test.ts +++ b/yarn-project/pxe/src/pxe_service/test/pxe_service.test.ts @@ -2,19 +2,22 @@ import { Grumpkin } from '@aztec/circuits.js/barretenberg'; import { L1ContractAddresses } from '@aztec/ethereum'; import { EthAddress } from '@aztec/foundation/eth-address'; import { TestKeyStore } from '@aztec/key-store'; +import { AztecLmdbStore } from '@aztec/kv-store'; import { AztecNode, INITIAL_L2_BLOCK_NUM, L2Tx, PXE, mockTx } from '@aztec/types'; import { MockProxy, mock } from 'jest-mock-extended'; -import { MemoryDB } from '../../database/memory_db.js'; +import { KVPxeDatabase } from '../../database/kv_pxe_database.js'; +import { PxeDatabase } from '../../database/pxe_database.js'; import { PXEServiceConfig } from '../../index.js'; import { PXEService } from '../pxe_service.js'; import { pxeTestSuite } from './pxe_test_suite.js'; -function createPXEService(): Promise { - const keyStore = new TestKeyStore(new Grumpkin()); +async function createPXEService(): Promise { + const kvStore = await AztecLmdbStore.create(EthAddress.random()); + const keyStore = new TestKeyStore(new Grumpkin(), kvStore); const node = mock(); - const db = new MemoryDB(); + const db = new KVPxeDatabase(kvStore); const config: PXEServiceConfig = { l2BlockPollingIntervalMS: 100, l2StartingBlock: INITIAL_L2_BLOCK_NUM }; // Setup the relevant mocks @@ -39,13 +42,14 @@ pxeTestSuite('PXEService', createPXEService); describe('PXEService', () => { let keyStore: TestKeyStore; let node: MockProxy; - let db: MemoryDB; + let db: PxeDatabase; let config: PXEServiceConfig; - beforeEach(() => { - keyStore = new TestKeyStore(new Grumpkin()); + beforeEach(async () => { + const kvStore = await AztecLmdbStore.create(EthAddress.random()); + keyStore = new TestKeyStore(new Grumpkin(), kvStore); node = mock(); - db = new MemoryDB(); + db = new KVPxeDatabase(kvStore); config = { l2BlockPollingIntervalMS: 100, l2StartingBlock: INITIAL_L2_BLOCK_NUM }; }); diff --git a/yarn-project/pxe/src/simulator/index.ts b/yarn-project/pxe/src/simulator/index.ts index 0ffc34a35ef..64abb774d20 100644 --- a/yarn-project/pxe/src/simulator/index.ts +++ b/yarn-project/pxe/src/simulator/index.ts @@ -2,14 +2,14 @@ import { AcirSimulator } from '@aztec/acir-simulator'; import { KeyStore, StateInfoProvider } from '@aztec/types'; import { ContractDataOracle } from '../contract_data_oracle/index.js'; -import { Database } from '../database/database.js'; +import { PxeDatabase } from '../database/pxe_database.js'; import { SimulatorOracle } from '../simulator_oracle/index.js'; /** * Helper method to create an instance of the acir simulator. */ export function getAcirSimulator( - db: Database, + db: PxeDatabase, stateInfoProvider: StateInfoProvider, keyStore: KeyStore, contractDataOracle?: ContractDataOracle, diff --git a/yarn-project/pxe/src/simulator_oracle/index.ts b/yarn-project/pxe/src/simulator_oracle/index.ts index 2eb485fd287..4b3e21aee64 100644 --- a/yarn-project/pxe/src/simulator_oracle/index.ts +++ b/yarn-project/pxe/src/simulator_oracle/index.ts @@ -13,7 +13,7 @@ import { createDebugLogger } from '@aztec/foundation/log'; import { KeyStore, L2Block, MerkleTreeId, NullifierMembershipWitness, StateInfoProvider } from '@aztec/types'; import { ContractDataOracle } from '../contract_data_oracle/index.js'; -import { Database } from '../database/index.js'; +import { PxeDatabase } from '../database/index.js'; /** * A data oracle that provides information needed for simulating a transaction. @@ -21,7 +21,7 @@ import { Database } from '../database/index.js'; export class SimulatorOracle implements DBOracle { constructor( private contractDataOracle: ContractDataOracle, - private db: Database, + private db: PxeDatabase, private keyStore: KeyStore, private stateInfoProvider: StateInfoProvider, private log = createDebugLogger('aztec:pxe:simulator_oracle'), diff --git a/yarn-project/pxe/src/synchronizer/synchronizer.test.ts b/yarn-project/pxe/src/synchronizer/synchronizer.test.ts index 95893f10810..5270b0d7d1e 100644 --- a/yarn-project/pxe/src/synchronizer/synchronizer.test.ts +++ b/yarn-project/pxe/src/synchronizer/synchronizer.test.ts @@ -1,22 +1,24 @@ -import { BlockHeader, CompleteAddress, Fr, GrumpkinScalar } from '@aztec/circuits.js'; +import { BlockHeader, CompleteAddress, EthAddress, Fr, GrumpkinScalar } from '@aztec/circuits.js'; import { Grumpkin } from '@aztec/circuits.js/barretenberg'; import { TestKeyStore } from '@aztec/key-store'; +import { AztecLmdbStore } from '@aztec/kv-store'; import { AztecNode, INITIAL_L2_BLOCK_NUM, L2Block, MerkleTreeId } from '@aztec/types'; import { MockProxy, mock } from 'jest-mock-extended'; import omit from 'lodash.omit'; -import { Database, MemoryDB } from '../database/index.js'; +import { PxeDatabase } from '../database/index.js'; +import { KVPxeDatabase } from '../database/kv_pxe_database.js'; import { Synchronizer } from './synchronizer.js'; describe('Synchronizer', () => { let aztecNode: MockProxy; - let database: Database; + let database: PxeDatabase; let synchronizer: TestSynchronizer; let roots: Record; let blockHeader: BlockHeader; - beforeEach(() => { + beforeEach(async () => { blockHeader = BlockHeader.random(); roots = { [MerkleTreeId.CONTRACT_TREE]: blockHeader.contractTreeRoot, @@ -28,7 +30,7 @@ describe('Synchronizer', () => { }; aztecNode = mock(); - database = new MemoryDB(); + database = new KVPxeDatabase(await AztecLmdbStore.create(EthAddress.random())); synchronizer = new TestSynchronizer(aztecNode, database); }); @@ -102,9 +104,9 @@ describe('Synchronizer', () => { aztecNode.getBlockNumber.mockResolvedValueOnce(1); // Manually adding account to database so that we can call synchronizer.isAccountStateSynchronized - const keyStore = new TestKeyStore(new Grumpkin()); + const keyStore = new TestKeyStore(new Grumpkin(), await AztecLmdbStore.create(EthAddress.random())); const privateKey = GrumpkinScalar.random(); - keyStore.addAccount(privateKey); + await keyStore.addAccount(privateKey); const completeAddress = CompleteAddress.fromPrivateKeyAndPartialAddress(privateKey, Fr.random()); await database.addCompleteAddress(completeAddress); diff --git a/yarn-project/pxe/src/synchronizer/synchronizer.ts b/yarn-project/pxe/src/synchronizer/synchronizer.ts index 1c557386c18..2346ae7d613 100644 --- a/yarn-project/pxe/src/synchronizer/synchronizer.ts +++ b/yarn-project/pxe/src/synchronizer/synchronizer.ts @@ -5,7 +5,7 @@ import { InterruptibleSleep } from '@aztec/foundation/sleep'; import { AztecNode, INITIAL_L2_BLOCK_NUM, KeyStore, L2BlockContext, L2BlockL2Logs, LogType } from '@aztec/types'; import { NoteProcessorCaughtUpStats } from '@aztec/types/stats'; -import { Database } from '../database/index.js'; +import { PxeDatabase } from '../database/index.js'; import { NoteProcessor } from '../note_processor/index.js'; /** @@ -25,7 +25,7 @@ export class Synchronizer { private log: DebugLogger; private noteProcessorsToCatchUp: NoteProcessor[] = []; - constructor(private node: AztecNode, private db: Database, logSuffix = '') { + constructor(private node: AztecNode, private db: PxeDatabase, logSuffix = '') { this.log = createDebugLogger(logSuffix ? `aztec:pxe_synchronizer_${logSuffix}` : 'aztec:pxe_synchronizer'); } diff --git a/yarn-project/pxe/tsconfig.json b/yarn-project/pxe/tsconfig.json index 3106fcd762f..c282504efe6 100644 --- a/yarn-project/pxe/tsconfig.json +++ b/yarn-project/pxe/tsconfig.json @@ -9,6 +9,9 @@ { "path": "../acir-simulator" }, + { + "path": "../kv-store" + }, { "path": "../circuits.js" }, diff --git a/yarn-project/types/src/contract_dao.test.ts b/yarn-project/types/src/contract_dao.test.ts new file mode 100644 index 00000000000..5cfa8ea7e92 --- /dev/null +++ b/yarn-project/types/src/contract_dao.test.ts @@ -0,0 +1,54 @@ +import { CompleteAddress, EthAddress } from '@aztec/circuits.js'; +import { ABIParameterVisibility, ContractArtifact, FunctionSelector, FunctionType } from '@aztec/foundation/abi'; + +import { ContractDao } from './contract_dao.js'; +import { randomContractArtifact } from './mocks.js'; + +describe('ContractDao', () => { + it('serializes / deserializes correctly', () => { + const artifact = randomContractArtifact(); + const dao = new ContractDao(artifact, CompleteAddress.random(), EthAddress.random()); + + expect(ContractDao.fromBuffer(dao.toBuffer())).toEqual(dao); + }); + + it('extracts function data', () => { + const artifact: ContractArtifact = { + name: 'test', + functions: [ + { + name: 'bar', + functionType: FunctionType.SECRET, + isInternal: false, + parameters: [ + { + name: 'value', + type: { + kind: 'field', + }, + visibility: ABIParameterVisibility.PUBLIC, + }, + { + name: 'value', + type: { + kind: 'field', + }, + visibility: ABIParameterVisibility.SECRET, + }, + ], + returnTypes: [], + bytecode: '0af', + }, + ], + events: [], + }; + + const dao = new ContractDao(artifact, CompleteAddress.random(), EthAddress.random()); + + expect(dao.functions[0]).toEqual({ + ...artifact.functions[0], + // number representing bar((Field),Field) + selector: new FunctionSelector(4138634513), + }); + }); +}); diff --git a/yarn-project/types/src/contract_dao.ts b/yarn-project/types/src/contract_dao.ts index d07e2d66a58..10cb955d743 100644 --- a/yarn-project/types/src/contract_dao.ts +++ b/yarn-project/types/src/contract_dao.ts @@ -1,53 +1,67 @@ import { CompleteAddress, ContractFunctionDao } from '@aztec/circuits.js'; -import { ContractArtifact, FunctionSelector, FunctionType } from '@aztec/foundation/abi'; +import { ContractArtifact, DebugMetadata, EventAbi, FunctionSelector, FunctionType } from '@aztec/foundation/abi'; import { EthAddress } from '@aztec/foundation/eth-address'; +import { prefixBufferWithLength } from '@aztec/foundation/serialize'; -import { EncodedContractFunction } from './contract_data.js'; +import { BufferReader, EncodedContractFunction } from './contract_data.js'; /** * A contract Data Access Object (DAO). * Contains the contract's address, portal contract address, and an array of ContractFunctionDao objects. * Each ContractFunctionDao object includes FunctionAbi data and the function selector buffer. */ -export interface ContractDao extends ContractArtifact { - /** - * The complete address representing the contract on L2. - */ - completeAddress: CompleteAddress; - /** - * The Ethereum address of the L1 contract serving as a bridge for cross-layer interactions. - */ - portalContract: EthAddress; - /** - * An array of contract functions with additional selector property. - */ - functions: ContractFunctionDao[]; -} +export class ContractDao implements ContractArtifact { + /** An array of contract functions with additional selector property. */ + public readonly functions: ContractFunctionDao[]; + constructor( + private contractArtifact: ContractArtifact, + /** The complete address representing the contract on L2. */ + public readonly completeAddress: CompleteAddress, + /** The Ethereum address of the L1 contract serving as a bridge for cross-layer interactions. */ + public readonly portalContract: EthAddress, + ) { + this.functions = contractArtifact.functions.map(f => ({ + ...f, + selector: FunctionSelector.fromNameAndParameters(f.name, f.parameters), + })); + } -/** - * Converts the given contract artifact into a ContractDao object that includes additional properties - * such as the address, portal contract, and function selectors. - * - * @param artifact - The contract artifact. - * @param completeAddress - The AztecAddress representing the contract's address. - * @param portalContract - The EthAddress representing the address of the associated portal contract. - * @returns A ContractDao object containing the provided information along with generated function selectors. - */ -export function toContractDao( - artifact: ContractArtifact, - completeAddress: CompleteAddress, - portalContract: EthAddress, -): ContractDao { - const functions = artifact.functions.map(f => ({ - ...f, - selector: FunctionSelector.fromNameAndParameters(f.name, f.parameters), - })); - return { - ...artifact, - completeAddress, - functions, - portalContract, - }; + get aztecNrVersion() { + return this.contractArtifact.aztecNrVersion; + } + + get name(): string { + return this.contractArtifact.name; + } + + get events(): EventAbi[] { + return this.contractArtifact.events; + } + + get debug(): DebugMetadata | undefined { + return this.contractArtifact.debug; + } + + toBuffer(): Buffer { + // the contract artifact was originally emitted to a JSON file by Noir + // should be safe to JSON.stringify it (i.e. it doesn't contain BigInts) + const contractArtifactJson = JSON.stringify(this.contractArtifact); + const buf = Buffer.concat([ + this.completeAddress.toBuffer(), + this.portalContract.toBuffer20(), + prefixBufferWithLength(Buffer.from(contractArtifactJson, 'utf-8')), + ]); + + return buf; + } + + static fromBuffer(buf: Uint8Array | BufferReader) { + const reader = BufferReader.asReader(buf); + const completeAddress = CompleteAddress.fromBuffer(reader); + const portalContract = new EthAddress(reader.readBytes(EthAddress.SIZE_IN_BYTES)); + const contractArtifact = JSON.parse(reader.readString()); + return new ContractDao(contractArtifact, completeAddress, portalContract); + } } /** diff --git a/yarn-project/types/src/keys/key_store.ts b/yarn-project/types/src/keys/key_store.ts index bce41ab0163..682aa89862e 100644 --- a/yarn-project/types/src/keys/key_store.ts +++ b/yarn-project/types/src/keys/key_store.ts @@ -18,7 +18,7 @@ export interface KeyStore { * @param privKey - The private key of the account. * @returns - The account's public key. */ - addAccount(privKey: GrumpkinPrivateKey): PublicKey; + addAccount(privKey: GrumpkinPrivateKey): Promise; /** * Retrieves the public keys of all accounts stored. diff --git a/yarn-project/yarn.lock b/yarn-project/yarn.lock index 06a076f1cfe..8be9c238210 100644 --- a/yarn-project/yarn.lock +++ b/yarn-project/yarn.lock @@ -496,6 +496,7 @@ __metadata: dependencies: "@aztec/circuits.js": "workspace:^" "@aztec/foundation": "workspace:^" + "@aztec/kv-store": "workspace:^" "@aztec/types": "workspace:^" "@jest/globals": ^29.5.0 "@types/jest": ^29.5.0 @@ -508,6 +509,23 @@ __metadata: languageName: unknown linkType: soft +"@aztec/kv-store@workspace:^, @aztec/kv-store@workspace:kv-store": + version: 0.0.0-use.local + resolution: "@aztec/kv-store@workspace:kv-store" + dependencies: + "@aztec/foundation": "workspace:^" + "@jest/globals": ^29.5.0 + "@types/jest": ^29.5.0 + "@types/node": ^18.7.23 + jest: ^29.5.0 + jest-mock-extended: ^3.0.3 + lmdb: ^2.9.1 + ts-jest: ^29.1.0 + ts-node: ^10.9.1 + typescript: ^5.0.4 + languageName: unknown + linkType: soft + "@aztec/l1-artifacts@workspace:^, @aztec/l1-artifacts@workspace:l1-artifacts": version: 0.0.0-use.local resolution: "@aztec/l1-artifacts@workspace:l1-artifacts" @@ -715,6 +733,7 @@ __metadata: "@aztec/ethereum": "workspace:^" "@aztec/foundation": "workspace:^" "@aztec/key-store": "workspace:^" + "@aztec/kv-store": "workspace:^" "@aztec/noir-compiler": "workspace:^" "@aztec/noir-protocol-circuits": "workspace:^" "@aztec/types": "workspace:^" From 10376ef55f8d697127902913afc19d9df791be7f Mon Sep 17 00:00:00 2001 From: Aztec Bot <49558828+AztecBot@users.noreply.github.com> Date: Wed, 13 Dec 2023 08:59:00 -0500 Subject: [PATCH 33/35] chore(master): Release 0.16.8 (#3609) :robot: I have created a release *beep* *boop* ---

aztec-packages: 0.16.8 ## [0.16.8](https://github.com/AztecProtocol/aztec-packages/compare/aztec-packages-v0.16.7...aztec-packages-v0.16.8) (2023-12-13) ### Features * Block header block number oracle ([#3648](https://github.com/AztecProtocol/aztec-packages/issues/3648)) ([ac1edc1](https://github.com/AztecProtocol/aztec-packages/commit/ac1edc1d30352cc3e3dcbfce4e69fe38777cc0df)) * Complete folding prover and verifier for ultra instances ([#3419](https://github.com/AztecProtocol/aztec-packages/issues/3419)) ([bb86ce9](https://github.com/AztecProtocol/aztec-packages/commit/bb86ce9a27e09b8a336af04b787b81d5f1d49ac8)) * Copy constructors for builders ([#3635](https://github.com/AztecProtocol/aztec-packages/issues/3635)) ([b82b0c5](https://github.com/AztecProtocol/aztec-packages/commit/b82b0c579c4a315c9b4eaf3e9726275633603b5a)) * Enabling nullifier tree snapshot ([#3670](https://github.com/AztecProtocol/aztec-packages/issues/3670)) ([b47d49d](https://github.com/AztecProtocol/aztec-packages/commit/b47d49def5b8ae9db3cab9afd1367c68b15cb766)) * Libraryfying historic access ([#3658](https://github.com/AztecProtocol/aztec-packages/issues/3658)) ([6877ca1](https://github.com/AztecProtocol/aztec-packages/commit/6877ca1c906743afbf488ac0f7e662bf4486f6a6)) * Log-derivative based generic permutations for AVM ([#3428](https://github.com/AztecProtocol/aztec-packages/issues/3428)) ([379b5ad](https://github.com/AztecProtocol/aztec-packages/commit/379b5adc259ac69b01e61b852172cdfc87cf9350)) * Merge recursive verifier ([#3588](https://github.com/AztecProtocol/aztec-packages/issues/3588)) ([cdd9259](https://github.com/AztecProtocol/aztec-packages/commit/cdd92595c313617189a530e0bfda987db211ae6b)) * New install script and container wrappers. ([#3617](https://github.com/AztecProtocol/aztec-packages/issues/3617)) ([c7f1878](https://github.com/AztecProtocol/aztec-packages/commit/c7f1878777bf76dbfd451761dbe6dc78903e45e2)) * Persist pxe state ([#3628](https://github.com/AztecProtocol/aztec-packages/issues/3628)) ([9ccbbd9](https://github.com/AztecProtocol/aztec-packages/commit/9ccbbd96e50f22646f0527c7d15944cecabca662)) * Update command handles Dockerized sandbox ([#3656](https://github.com/AztecProtocol/aztec-packages/issues/3656)) ([7c85750](https://github.com/AztecProtocol/aztec-packages/commit/7c85750089e022240376751086d515d993409d98)) ### Bug Fixes * Aztec sandbox compose fixes ([#3634](https://github.com/AztecProtocol/aztec-packages/issues/3634)) ([765a19c](https://github.com/AztecProtocol/aztec-packages/commit/765a19c3aad3a2793a764b970b7cc8a819094da7)) * Broken uint256_t implicit copy ([#3625](https://github.com/AztecProtocol/aztec-packages/issues/3625)) ([1a6b44d](https://github.com/AztecProtocol/aztec-packages/commit/1a6b44d67e077eb5904ab30255454693d6a1edac)) * **ci:** Rebuild versioned cli / sandbox images ([#3613](https://github.com/AztecProtocol/aztec-packages/issues/3613)) ([6a53fbc](https://github.com/AztecProtocol/aztec-packages/commit/6a53fbc48624d6ecbcc8dc6fd69564fdb3db342e)) * Make lsp work in docker, plus some other install tweaks. ([#3661](https://github.com/AztecProtocol/aztec-packages/issues/3661)) ([53eb54f](https://github.com/AztecProtocol/aztec-packages/commit/53eb54fb3416711dbc411e6037bc2da18d523cc3)) * **noir-compiler:** Compile time error if ctor is missing ([#3649](https://github.com/AztecProtocol/aztec-packages/issues/3649)) ([12249bf](https://github.com/AztecProtocol/aztec-packages/commit/12249bf91d5934f798856a75cdd9de8a5822604b)) * Sandbox node mode api prefix ([#3662](https://github.com/AztecProtocol/aztec-packages/issues/3662)) ([fd6eefe](https://github.com/AztecProtocol/aztec-packages/commit/fd6eefe310e291e9625184dee9177a9b219e82f2)) * Top level init bb.js, but better scoped imports to not incur cost too early ([#3629](https://github.com/AztecProtocol/aztec-packages/issues/3629)) ([cea862d](https://github.com/AztecProtocol/aztec-packages/commit/cea862dd7feec714a34eba6a3cf7a2a174a59a1b)) ### Miscellaneous * **ci:** Combine deploy / release jobs + canary update ([#3610](https://github.com/AztecProtocol/aztec-packages/issues/3610)) ([0888c05](https://github.com/AztecProtocol/aztec-packages/commit/0888c05098c94151462e30528a32322ae793d9ac)), closes [#3579](https://github.com/AztecProtocol/aztec-packages/issues/3579) * **docs:** Update implementation references in token contract tutorial ([#3626](https://github.com/AztecProtocol/aztec-packages/issues/3626)) ([a2cee4f](https://github.com/AztecProtocol/aztec-packages/commit/a2cee4ff1df294b1253f4a495a158794b47bfe66)) * Nuke fib ([#3607](https://github.com/AztecProtocol/aztec-packages/issues/3607)) ([48e2e3d](https://github.com/AztecProtocol/aztec-packages/commit/48e2e3d261a7091cb0b87565ec8bc9ae595b3022)) * Reduced spam logging in archiver ([#3671](https://github.com/AztecProtocol/aztec-packages/issues/3671)) ([e749daa](https://github.com/AztecProtocol/aztec-packages/commit/e749daa7f1e9e34cad93d64e76e04d2525c6f458)) * Run the protocol circuits noir tests in CI ([#3660](https://github.com/AztecProtocol/aztec-packages/issues/3660)) ([383e123](https://github.com/AztecProtocol/aztec-packages/commit/383e1231c1df23e1365e94642fe0d4d670d84c8f)), closes [#3205](https://github.com/AztecProtocol/aztec-packages/issues/3205) ### Documentation * Updated yellow paper for fees ([#3659](https://github.com/AztecProtocol/aztec-packages/issues/3659)) ([5513624](https://github.com/AztecProtocol/aztec-packages/commit/55136246ffa457c73426190438c254743c841675)) * **yellowpaper:** Rewrite section on tagged memory, misc rewording/cleanup ([#3523](https://github.com/AztecProtocol/aztec-packages/issues/3523)) ([fe849e3](https://github.com/AztecProtocol/aztec-packages/commit/fe849e323526ea132c2a3ab41c8351a24f6e9cf4)) * **yellowpaper:** Update `cast` instruction description with truncation operation ([#3621](https://github.com/AztecProtocol/aztec-packages/issues/3621)) ([2cede41](https://github.com/AztecProtocol/aztec-packages/commit/2cede412d25ef27acc7347e31389ae5d780f1b0b))
barretenberg.js: 0.16.8 ## [0.16.8](https://github.com/AztecProtocol/aztec-packages/compare/barretenberg.js-v0.16.7...barretenberg.js-v0.16.8) (2023-12-13) ### Bug Fixes * Aztec sandbox compose fixes ([#3634](https://github.com/AztecProtocol/aztec-packages/issues/3634)) ([765a19c](https://github.com/AztecProtocol/aztec-packages/commit/765a19c3aad3a2793a764b970b7cc8a819094da7)) * Top level init bb.js, but better scoped imports to not incur cost too early ([#3629](https://github.com/AztecProtocol/aztec-packages/issues/3629)) ([cea862d](https://github.com/AztecProtocol/aztec-packages/commit/cea862dd7feec714a34eba6a3cf7a2a174a59a1b))
barretenberg: 0.16.8 ## [0.16.8](https://github.com/AztecProtocol/aztec-packages/compare/barretenberg-v0.16.7...barretenberg-v0.16.8) (2023-12-13) ### Features * Complete folding prover and verifier for ultra instances ([#3419](https://github.com/AztecProtocol/aztec-packages/issues/3419)) ([bb86ce9](https://github.com/AztecProtocol/aztec-packages/commit/bb86ce9a27e09b8a336af04b787b81d5f1d49ac8)) * Copy constructors for builders ([#3635](https://github.com/AztecProtocol/aztec-packages/issues/3635)) ([b82b0c5](https://github.com/AztecProtocol/aztec-packages/commit/b82b0c579c4a315c9b4eaf3e9726275633603b5a)) * Log-derivative based generic permutations for AVM ([#3428](https://github.com/AztecProtocol/aztec-packages/issues/3428)) ([379b5ad](https://github.com/AztecProtocol/aztec-packages/commit/379b5adc259ac69b01e61b852172cdfc87cf9350)) * Merge recursive verifier ([#3588](https://github.com/AztecProtocol/aztec-packages/issues/3588)) ([cdd9259](https://github.com/AztecProtocol/aztec-packages/commit/cdd92595c313617189a530e0bfda987db211ae6b)) ### Bug Fixes * Aztec sandbox compose fixes ([#3634](https://github.com/AztecProtocol/aztec-packages/issues/3634)) ([765a19c](https://github.com/AztecProtocol/aztec-packages/commit/765a19c3aad3a2793a764b970b7cc8a819094da7)) * Broken uint256_t implicit copy ([#3625](https://github.com/AztecProtocol/aztec-packages/issues/3625)) ([1a6b44d](https://github.com/AztecProtocol/aztec-packages/commit/1a6b44d67e077eb5904ab30255454693d6a1edac)) ### Miscellaneous * Nuke fib ([#3607](https://github.com/AztecProtocol/aztec-packages/issues/3607)) ([48e2e3d](https://github.com/AztecProtocol/aztec-packages/commit/48e2e3d261a7091cb0b87565ec8bc9ae595b3022))
--- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- .release-please-manifest.json | 6 ++--- CHANGELOG.md | 43 +++++++++++++++++++++++++++++++++ barretenberg/CHANGELOG.md | 21 ++++++++++++++++ barretenberg/cpp/CMakeLists.txt | 2 +- barretenberg/ts/CHANGELOG.md | 8 ++++++ barretenberg/ts/package.json | 2 +- 6 files changed, 77 insertions(+), 5 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index a655b1913f8..067e66e27f2 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,5 +1,5 @@ { - ".": "0.16.7", - "barretenberg": "0.16.7", - "barretenberg/ts": "0.16.7" + ".": "0.16.8", + "barretenberg": "0.16.8", + "barretenberg/ts": "0.16.8" } diff --git a/CHANGELOG.md b/CHANGELOG.md index 956258bb1b1..4cb9d45e6a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,48 @@ # Changelog +## [0.16.8](https://github.com/AztecProtocol/aztec-packages/compare/aztec-packages-v0.16.7...aztec-packages-v0.16.8) (2023-12-13) + + +### Features + +* Block header block number oracle ([#3648](https://github.com/AztecProtocol/aztec-packages/issues/3648)) ([ac1edc1](https://github.com/AztecProtocol/aztec-packages/commit/ac1edc1d30352cc3e3dcbfce4e69fe38777cc0df)) +* Complete folding prover and verifier for ultra instances ([#3419](https://github.com/AztecProtocol/aztec-packages/issues/3419)) ([bb86ce9](https://github.com/AztecProtocol/aztec-packages/commit/bb86ce9a27e09b8a336af04b787b81d5f1d49ac8)) +* Copy constructors for builders ([#3635](https://github.com/AztecProtocol/aztec-packages/issues/3635)) ([b82b0c5](https://github.com/AztecProtocol/aztec-packages/commit/b82b0c579c4a315c9b4eaf3e9726275633603b5a)) +* Enabling nullifier tree snapshot ([#3670](https://github.com/AztecProtocol/aztec-packages/issues/3670)) ([b47d49d](https://github.com/AztecProtocol/aztec-packages/commit/b47d49def5b8ae9db3cab9afd1367c68b15cb766)) +* Libraryfying historic access ([#3658](https://github.com/AztecProtocol/aztec-packages/issues/3658)) ([6877ca1](https://github.com/AztecProtocol/aztec-packages/commit/6877ca1c906743afbf488ac0f7e662bf4486f6a6)) +* Log-derivative based generic permutations for AVM ([#3428](https://github.com/AztecProtocol/aztec-packages/issues/3428)) ([379b5ad](https://github.com/AztecProtocol/aztec-packages/commit/379b5adc259ac69b01e61b852172cdfc87cf9350)) +* Merge recursive verifier ([#3588](https://github.com/AztecProtocol/aztec-packages/issues/3588)) ([cdd9259](https://github.com/AztecProtocol/aztec-packages/commit/cdd92595c313617189a530e0bfda987db211ae6b)) +* New install script and container wrappers. ([#3617](https://github.com/AztecProtocol/aztec-packages/issues/3617)) ([c7f1878](https://github.com/AztecProtocol/aztec-packages/commit/c7f1878777bf76dbfd451761dbe6dc78903e45e2)) +* Persist pxe state ([#3628](https://github.com/AztecProtocol/aztec-packages/issues/3628)) ([9ccbbd9](https://github.com/AztecProtocol/aztec-packages/commit/9ccbbd96e50f22646f0527c7d15944cecabca662)) +* Update command handles Dockerized sandbox ([#3656](https://github.com/AztecProtocol/aztec-packages/issues/3656)) ([7c85750](https://github.com/AztecProtocol/aztec-packages/commit/7c85750089e022240376751086d515d993409d98)) + + +### Bug Fixes + +* Aztec sandbox compose fixes ([#3634](https://github.com/AztecProtocol/aztec-packages/issues/3634)) ([765a19c](https://github.com/AztecProtocol/aztec-packages/commit/765a19c3aad3a2793a764b970b7cc8a819094da7)) +* Broken uint256_t implicit copy ([#3625](https://github.com/AztecProtocol/aztec-packages/issues/3625)) ([1a6b44d](https://github.com/AztecProtocol/aztec-packages/commit/1a6b44d67e077eb5904ab30255454693d6a1edac)) +* **ci:** Rebuild versioned cli / sandbox images ([#3613](https://github.com/AztecProtocol/aztec-packages/issues/3613)) ([6a53fbc](https://github.com/AztecProtocol/aztec-packages/commit/6a53fbc48624d6ecbcc8dc6fd69564fdb3db342e)) +* Make lsp work in docker, plus some other install tweaks. ([#3661](https://github.com/AztecProtocol/aztec-packages/issues/3661)) ([53eb54f](https://github.com/AztecProtocol/aztec-packages/commit/53eb54fb3416711dbc411e6037bc2da18d523cc3)) +* **noir-compiler:** Compile time error if ctor is missing ([#3649](https://github.com/AztecProtocol/aztec-packages/issues/3649)) ([12249bf](https://github.com/AztecProtocol/aztec-packages/commit/12249bf91d5934f798856a75cdd9de8a5822604b)) +* Sandbox node mode api prefix ([#3662](https://github.com/AztecProtocol/aztec-packages/issues/3662)) ([fd6eefe](https://github.com/AztecProtocol/aztec-packages/commit/fd6eefe310e291e9625184dee9177a9b219e82f2)) +* Top level init bb.js, but better scoped imports to not incur cost too early ([#3629](https://github.com/AztecProtocol/aztec-packages/issues/3629)) ([cea862d](https://github.com/AztecProtocol/aztec-packages/commit/cea862dd7feec714a34eba6a3cf7a2a174a59a1b)) + + +### Miscellaneous + +* **ci:** Combine deploy / release jobs + canary update ([#3610](https://github.com/AztecProtocol/aztec-packages/issues/3610)) ([0888c05](https://github.com/AztecProtocol/aztec-packages/commit/0888c05098c94151462e30528a32322ae793d9ac)), closes [#3579](https://github.com/AztecProtocol/aztec-packages/issues/3579) +* **docs:** Update implementation references in token contract tutorial ([#3626](https://github.com/AztecProtocol/aztec-packages/issues/3626)) ([a2cee4f](https://github.com/AztecProtocol/aztec-packages/commit/a2cee4ff1df294b1253f4a495a158794b47bfe66)) +* Nuke fib ([#3607](https://github.com/AztecProtocol/aztec-packages/issues/3607)) ([48e2e3d](https://github.com/AztecProtocol/aztec-packages/commit/48e2e3d261a7091cb0b87565ec8bc9ae595b3022)) +* Reduced spam logging in archiver ([#3671](https://github.com/AztecProtocol/aztec-packages/issues/3671)) ([e749daa](https://github.com/AztecProtocol/aztec-packages/commit/e749daa7f1e9e34cad93d64e76e04d2525c6f458)) +* Run the protocol circuits noir tests in CI ([#3660](https://github.com/AztecProtocol/aztec-packages/issues/3660)) ([383e123](https://github.com/AztecProtocol/aztec-packages/commit/383e1231c1df23e1365e94642fe0d4d670d84c8f)), closes [#3205](https://github.com/AztecProtocol/aztec-packages/issues/3205) + + +### Documentation + +* Updated yellow paper for fees ([#3659](https://github.com/AztecProtocol/aztec-packages/issues/3659)) ([5513624](https://github.com/AztecProtocol/aztec-packages/commit/55136246ffa457c73426190438c254743c841675)) +* **yellowpaper:** Rewrite section on tagged memory, misc rewording/cleanup ([#3523](https://github.com/AztecProtocol/aztec-packages/issues/3523)) ([fe849e3](https://github.com/AztecProtocol/aztec-packages/commit/fe849e323526ea132c2a3ab41c8351a24f6e9cf4)) +* **yellowpaper:** Update `cast` instruction description with truncation operation ([#3621](https://github.com/AztecProtocol/aztec-packages/issues/3621)) ([2cede41](https://github.com/AztecProtocol/aztec-packages/commit/2cede412d25ef27acc7347e31389ae5d780f1b0b)) + ## [0.16.7](https://github.com/AztecProtocol/aztec-packages/compare/aztec-packages-v0.16.6...aztec-packages-v0.16.7) (2023-12-06) diff --git a/barretenberg/CHANGELOG.md b/barretenberg/CHANGELOG.md index 65412da7cf3..4e3132d30c1 100644 --- a/barretenberg/CHANGELOG.md +++ b/barretenberg/CHANGELOG.md @@ -1,5 +1,26 @@ # Changelog +## [0.16.8](https://github.com/AztecProtocol/aztec-packages/compare/barretenberg-v0.16.7...barretenberg-v0.16.8) (2023-12-13) + + +### Features + +* Complete folding prover and verifier for ultra instances ([#3419](https://github.com/AztecProtocol/aztec-packages/issues/3419)) ([bb86ce9](https://github.com/AztecProtocol/aztec-packages/commit/bb86ce9a27e09b8a336af04b787b81d5f1d49ac8)) +* Copy constructors for builders ([#3635](https://github.com/AztecProtocol/aztec-packages/issues/3635)) ([b82b0c5](https://github.com/AztecProtocol/aztec-packages/commit/b82b0c579c4a315c9b4eaf3e9726275633603b5a)) +* Log-derivative based generic permutations for AVM ([#3428](https://github.com/AztecProtocol/aztec-packages/issues/3428)) ([379b5ad](https://github.com/AztecProtocol/aztec-packages/commit/379b5adc259ac69b01e61b852172cdfc87cf9350)) +* Merge recursive verifier ([#3588](https://github.com/AztecProtocol/aztec-packages/issues/3588)) ([cdd9259](https://github.com/AztecProtocol/aztec-packages/commit/cdd92595c313617189a530e0bfda987db211ae6b)) + + +### Bug Fixes + +* Aztec sandbox compose fixes ([#3634](https://github.com/AztecProtocol/aztec-packages/issues/3634)) ([765a19c](https://github.com/AztecProtocol/aztec-packages/commit/765a19c3aad3a2793a764b970b7cc8a819094da7)) +* Broken uint256_t implicit copy ([#3625](https://github.com/AztecProtocol/aztec-packages/issues/3625)) ([1a6b44d](https://github.com/AztecProtocol/aztec-packages/commit/1a6b44d67e077eb5904ab30255454693d6a1edac)) + + +### Miscellaneous + +* Nuke fib ([#3607](https://github.com/AztecProtocol/aztec-packages/issues/3607)) ([48e2e3d](https://github.com/AztecProtocol/aztec-packages/commit/48e2e3d261a7091cb0b87565ec8bc9ae595b3022)) + ## [0.16.7](https://github.com/AztecProtocol/aztec-packages/compare/barretenberg-v0.16.6...barretenberg-v0.16.7) (2023-12-06) diff --git a/barretenberg/cpp/CMakeLists.txt b/barretenberg/cpp/CMakeLists.txt index 56ea3977f17..022c288f097 100644 --- a/barretenberg/cpp/CMakeLists.txt +++ b/barretenberg/cpp/CMakeLists.txt @@ -6,7 +6,7 @@ cmake_minimum_required(VERSION 3.24) project( Barretenberg DESCRIPTION "BN254 elliptic curve library, and PLONK SNARK prover" - VERSION 0.16.7 # x-release-please-version + VERSION 0.16.8 # x-release-please-version LANGUAGES CXX C ) # Insert version into `bb` config file diff --git a/barretenberg/ts/CHANGELOG.md b/barretenberg/ts/CHANGELOG.md index fa0bef62e34..67ba10e3e4a 100644 --- a/barretenberg/ts/CHANGELOG.md +++ b/barretenberg/ts/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## [0.16.8](https://github.com/AztecProtocol/aztec-packages/compare/barretenberg.js-v0.16.7...barretenberg.js-v0.16.8) (2023-12-13) + + +### Bug Fixes + +* Aztec sandbox compose fixes ([#3634](https://github.com/AztecProtocol/aztec-packages/issues/3634)) ([765a19c](https://github.com/AztecProtocol/aztec-packages/commit/765a19c3aad3a2793a764b970b7cc8a819094da7)) +* Top level init bb.js, but better scoped imports to not incur cost too early ([#3629](https://github.com/AztecProtocol/aztec-packages/issues/3629)) ([cea862d](https://github.com/AztecProtocol/aztec-packages/commit/cea862dd7feec714a34eba6a3cf7a2a174a59a1b)) + ## [0.16.7](https://github.com/AztecProtocol/aztec-packages/compare/barretenberg.js-v0.16.6...barretenberg.js-v0.16.7) (2023-12-06) diff --git a/barretenberg/ts/package.json b/barretenberg/ts/package.json index 79ba376f8ae..948e4d0d5a8 100644 --- a/barretenberg/ts/package.json +++ b/barretenberg/ts/package.json @@ -1,6 +1,6 @@ { "name": "@aztec/bb.js", - "version": "0.16.7", + "version": "0.16.8", "homepage": "https://github.com/AztecProtocol/aztec-packages/tree/master/barretenberg/ts", "license": "MIT", "type": "module", From 9d7c58d4fe0f91c453c47d6be813325cff08907b Mon Sep 17 00:00:00 2001 From: spypsy Date: Wed, 13 Dec 2023 14:45:29 +0000 Subject: [PATCH 34/35] fix(ci): deploy_npm script (#3678) --- build-system/scripts/deploy_npm | 1 + 1 file changed, 1 insertion(+) diff --git a/build-system/scripts/deploy_npm b/build-system/scripts/deploy_npm index 22b5a63d9a7..dbadd385ee9 100755 --- a/build-system/scripts/deploy_npm +++ b/build-system/scripts/deploy_npm @@ -16,6 +16,7 @@ cd project/src/$(query_manifest relativeProjectDir $REPOSITORY) echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >.npmrc VERSION=$(extract_tag_version $REPOSITORY true) +PACKAGE_NAME=$(jq -r '.name' package.json) # If the commit tag itself has a dist-tag (e.g. v2.1.0-testnet.123), extract the dist-tag. TAG=$(echo "$VERSION" | grep -oP ".*-\K(.*)(?=\.\d+)" || true) From 4902f826d86b78824b607d1b29617270a2222630 Mon Sep 17 00:00:00 2001 From: Aztec Bot <49558828+AztecBot@users.noreply.github.com> Date: Wed, 13 Dec 2023 10:17:54 -0500 Subject: [PATCH 35/35] chore(master): Release 0.16.9 (#3679) :robot: I have created a release *beep* *boop* ---
aztec-packages: 0.16.9 ## [0.16.9](https://github.com/AztecProtocol/aztec-packages/compare/aztec-packages-v0.16.8...aztec-packages-v0.16.9) (2023-12-13) ### Bug Fixes * **ci:** Deploy_npm script ([#3678](https://github.com/AztecProtocol/aztec-packages/issues/3678)) ([9d7c58d](https://github.com/AztecProtocol/aztec-packages/commit/9d7c58d4fe0f91c453c47d6be813325cff08907b))
barretenberg.js: 0.16.9 ## [0.16.9](https://github.com/AztecProtocol/aztec-packages/compare/barretenberg.js-v0.16.8...barretenberg.js-v0.16.9) (2023-12-13) ### Miscellaneous * **barretenberg.js:** Synchronize aztec-packages versions
barretenberg: 0.16.9 ## [0.16.9](https://github.com/AztecProtocol/aztec-packages/compare/barretenberg-v0.16.8...barretenberg-v0.16.9) (2023-12-13) ### Miscellaneous * **barretenberg:** Synchronize aztec-packages versions
--- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- .release-please-manifest.json | 6 +++--- CHANGELOG.md | 7 +++++++ barretenberg/CHANGELOG.md | 7 +++++++ barretenberg/cpp/CMakeLists.txt | 2 +- barretenberg/ts/CHANGELOG.md | 7 +++++++ barretenberg/ts/package.json | 2 +- 6 files changed, 26 insertions(+), 5 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 067e66e27f2..1bbd6737356 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,5 +1,5 @@ { - ".": "0.16.8", - "barretenberg": "0.16.8", - "barretenberg/ts": "0.16.8" + ".": "0.16.9", + "barretenberg": "0.16.9", + "barretenberg/ts": "0.16.9" } diff --git a/CHANGELOG.md b/CHANGELOG.md index 4cb9d45e6a9..8b988d6e051 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [0.16.9](https://github.com/AztecProtocol/aztec-packages/compare/aztec-packages-v0.16.8...aztec-packages-v0.16.9) (2023-12-13) + + +### Bug Fixes + +* **ci:** Deploy_npm script ([#3678](https://github.com/AztecProtocol/aztec-packages/issues/3678)) ([9d7c58d](https://github.com/AztecProtocol/aztec-packages/commit/9d7c58d4fe0f91c453c47d6be813325cff08907b)) + ## [0.16.8](https://github.com/AztecProtocol/aztec-packages/compare/aztec-packages-v0.16.7...aztec-packages-v0.16.8) (2023-12-13) diff --git a/barretenberg/CHANGELOG.md b/barretenberg/CHANGELOG.md index 4e3132d30c1..5bf1ef25735 100644 --- a/barretenberg/CHANGELOG.md +++ b/barretenberg/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [0.16.9](https://github.com/AztecProtocol/aztec-packages/compare/barretenberg-v0.16.8...barretenberg-v0.16.9) (2023-12-13) + + +### Miscellaneous + +* **barretenberg:** Synchronize aztec-packages versions + ## [0.16.8](https://github.com/AztecProtocol/aztec-packages/compare/barretenberg-v0.16.7...barretenberg-v0.16.8) (2023-12-13) diff --git a/barretenberg/cpp/CMakeLists.txt b/barretenberg/cpp/CMakeLists.txt index 022c288f097..34fb0e10187 100644 --- a/barretenberg/cpp/CMakeLists.txt +++ b/barretenberg/cpp/CMakeLists.txt @@ -6,7 +6,7 @@ cmake_minimum_required(VERSION 3.24) project( Barretenberg DESCRIPTION "BN254 elliptic curve library, and PLONK SNARK prover" - VERSION 0.16.8 # x-release-please-version + VERSION 0.16.9 # x-release-please-version LANGUAGES CXX C ) # Insert version into `bb` config file diff --git a/barretenberg/ts/CHANGELOG.md b/barretenberg/ts/CHANGELOG.md index 67ba10e3e4a..679736a9350 100644 --- a/barretenberg/ts/CHANGELOG.md +++ b/barretenberg/ts/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [0.16.9](https://github.com/AztecProtocol/aztec-packages/compare/barretenberg.js-v0.16.8...barretenberg.js-v0.16.9) (2023-12-13) + + +### Miscellaneous + +* **barretenberg.js:** Synchronize aztec-packages versions + ## [0.16.8](https://github.com/AztecProtocol/aztec-packages/compare/barretenberg.js-v0.16.7...barretenberg.js-v0.16.8) (2023-12-13) diff --git a/barretenberg/ts/package.json b/barretenberg/ts/package.json index 948e4d0d5a8..46e8f3c8d2a 100644 --- a/barretenberg/ts/package.json +++ b/barretenberg/ts/package.json @@ -1,6 +1,6 @@ { "name": "@aztec/bb.js", - "version": "0.16.8", + "version": "0.16.9", "homepage": "https://github.com/AztecProtocol/aztec-packages/tree/master/barretenberg/ts", "license": "MIT", "type": "module",

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 JmKXk;-vE|H;nn~E diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/CMOV.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/CMOV.png index 7c1ac378dd3bf527c8e5aa6f0f9fdebddf1f2e1d..a46692edd84c5bba21d558c003a5f121c71dc0d3 100644 GIT binary patch literal 5853 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 R;s@AjoA2zc^Y(aN{3kT8+CTsR diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/COINBASE.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/COINBASE.png index f2e8eb1ff8e467b301e809e7b98599f0aff87eae..72e2f88758dc2a00b2f9dd13867aa5487d8470ee 100644 GIT binary patch literal 3542 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 literal 3200 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 literal 4158 zcmeHKYgAKL7Ctv12ug{%s$dYP)>;bkFhxLxq}56R6%C>#Dfpm*m-+lHu zXYcRqv+w!cyF5*dR~iEVOuW9|h6BI=*5HQ=4K#PX!8djQAQyOT`(|%!?&Q#T_>J1- z2Ho$zoK`=0t3W?Vx^{OZ>dh=3=fnCO_PaJ=VinEICC_PkY8tW?U>yE zJ9{V-R#IAbs=)S2mj?u6gmuxHb__taYsL4fGHFs_36i0P5GA=$vKjMt$b~GTZdmqz_mpQ$||na>kuoT zuGwh6MR+}4!b8KtNC|<~7vEYL1RJ@+P5~nj5F)_a&dgZltgIE7{br7Jv`*Z@bDf=|1S7CN&rpN7 zrpSSPn25#j+t^+`okRchCQM1CKMwmeH#__`N2viMcbqJ7Lco>AC8~?Fv)P zXC%RUE1y=OZ=qAge*KrNLz^M-UN$NPtxIt)qx<4(H?+*1CTPN_%(X+oE{=K&&4Rqc z(1U$*mRbo9Wdv)V0G!rL$FWK=!C)~5N5p8fE@j5rqG2%qicHaJz+e6|S^j_sxAtlG zCw0a?#f!!s>^R>u$*(4dT}7kayi+~Jg04;uTj**fl2SLt?Eqlv(VcyR{YfjA0qc!u z*x*;(riAABX~f}iC82Ggzv)IELD}yYx21$M?d~^6ZMfqLfauV49kZ(3FBkz@)&b+G zqevW4>?wDqZMapH$Fh$upFnvJC8X+s?n^ncJdNdpi!)%<_g<0{N9vg*qGbfJuf~>? z8-5jcC;1yJan!q=8};xGD&7Z`(Uiphc@exC?_6x1BVoRgpII3bH%6%^W-J5X zRb2hXJ(}4zlOY zbd9@)E6fYEzc8CBSJf2@Yp=H|Dy58^`GL(%WHSJ}X-xB6JHX2C!>%=PhJqsZ-kHpP zc66?CJr(0RCOLIdt{C}X03@Cc9D>87J}}EO$KG3&-RHN-ofcM~ql}x2y*;W?iwa2D zH(Dl#0B?p-^6+sM0KrILald8npte5CAni z?VlSH1R8>ZbX{n*qCwHw+G0ltxcX=VruDMJDjGJ(;ZDq>?M5-caiz=@IOaUsPjk}y50o3)(}ibl!{m?7C|>4Txz7io z7~$)98HEXb{Ts;<s%7x}<6FJn zZC?djfR^GBAkjqJ;@zr9!h-cg^cUV2O%@lLV;^r_k>7i^Z_9OKHbK6vgL#qvl+e#t(gj)790Aw|L6z;V?{4nHp1h=669fakTijF&y+5KPHnrjgy;|j)2$|Xt-ob z(kXT47~p(~jxkaSes0Ijny2x!TO8TWb}MMQyNdKxPds&TUDosUQw)-RWDVZ*v_#JEdl!RjfOwmn zyEbTuOv{E^K64wzsPQ>8D*wu`4GiGY$`$euD6rBQ^<>-#jG7ZNPXz*j5q$K;?}lzP zqeuXk9ZT4bI#O-9`dtlxXOda%4fdd2>Do(qedVsQLt)#W2*mfz7Jz}SR2Ea?VbumbI`?OjF;5R+sO^IQTcr2>{Kg{z zq92pHw@-2vs}6;hu4!MoerF7~@Tgpr*z_dUI+$b?KP;1mickJ_O-f!&aP7?~jtEJ& ztH*6>$|J1+4fpz-N@bTrm{A2e!Ht2y7p+I%n)(Ue=WqA>io@lp98UFkA4x*Ec=*_B zO5<4Sb+-SWI=N_1_qXb)sZqulySxL@-+Oq%^=1z6lQI%YV+(FD`1u~X9x~j*o@wq)24d>7Pc&n)B*7Szs$e-M9We`8x9O`Hf%f` Rqjj;@ce}Qge|zxs-vL9L4PgKP diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/DIV.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/DIV.png index 2a30fad2d2866f61f7e16e06ffebee0bfe45c42c..58fee0f68533d9140e600fa64632c6e19a644da1 100644 GIT binary patch literal 5438 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 G@B9za=YKx{ literal 5061 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 diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/EMITNOTEHASH.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/EMITNOTEHASH.png index 3f5f66fc40a3db4bf43988d278ed3701f26e8552..fd31987d317df00d3cc9b984b615a6895d7f5353 100644 GIT binary patch literal 3653 zcmdT{do#?jPsubN1t$wfFg)efCLlarv*qz zHf{Pli&nkrL>7{Kme!h$(pjZaLVq65!y?vC$PB^Eh}PE0m15y$L6h zw3(-4JA-i>fsOp|6W7N?xd;{~37NDWnBZ_^T910)@KD2CK39WJiGG4 z1+YbQR!y9aVA9%rW?%+AWo^D3$hlZxXTIFYnESs#U-!mn^n%IfgW#ra$_5Bt(b9LW zl_Kz>kpl5Bs?Q|+$e86DS*(&d(8!*LgI;QyZfO01UwUg?be4TiDYgwon+_w*oo}z@FooOg`9I3P|_{fcTnj$R&gCexBIjM`J8JxY3K<#lIQFcx(EKnk4Q{t z^`>=p-%}(>;27xw9gxN)TeU_+ari(J_5d5|(w5raGYh z!Yi?8@#cyuR8W2Wxi70Zn$O87A23@gk6gje}|jhyC|C8i&a^ zuk9l3%~9`2{V3z{d7!MrqoK)JtTDHginY~iBq&4PrO~kDF>jGU*Z5k?2mNt(DVZ4q z0aDQ!un?W>^SBIP98@|O*%vg_Zj?@0lr!evEw^4k@(CH)>6v}AH9iux_Sdn`g<}{(&*M=ui1*(*QddCUlqD$y&5&79CpG3k?n6MH36hh{G8E*|-bAan?)_I(Z z(8xaqoywSPJkKv?QNQu+yiwKt(ZN%Oq#3`7O;J^MQGN`skZGhfO<(qqvC?8z?-DB^Dr*rkr^XzaJanl^Hz3;ylOc+EAwHVR>Bmklrws2HC~pO z9PxH52=S38s8h6)j5Z|jEHs`?^dS+6l?y{exLrGW_wG9vbm}ILbYAVIROz_O<5(`K zAlqEL2*G%DEWxYFXXV(m`+FC+ucn?gQ}w|(CgeMgK_jjmVIpT8_DB?;laK};M63tm z+V;E#6vQA^zBS^tcn`@iVfe2u!F9v1R{dU~xNx(VwH&f=LsKlDr!-nB zzrWM~Jm~oH<9~8Tym*T8pFKT)IjttFxahZ6TnIgf~inw(r_7&4`1ss@2iNMAzR_`w`RZLU)!9qN8W3q+HQbj2TxkRleB+ z>~sDPa%p1;T&PF+uu=Ne8|adu0{p5j6p z;?5kiCDbqE(AOyDte(U5Lz&kmqc;?vKX?Q z5~7AXfh-(&UlLR{p)$OF+ijKFlpm<*i{&}+GgCY&#yqCjJ4oIG>+Oo|I8RhxaXPe92P z05R0jfE^>B>AuqJ+D3QuQ!#j#t_-O%Ttj~-8idThkf|1OroP76R7Z&Xsrtw)W2N$g0ubr*za8u_ST?k zpeK}=xS|O4h#)sjTTH8OtqLL9cf-RLy~2McupgN!U}W9vHA|3bs`Xi`X82}ayt4UKQQ@c^!BDsH_Q{J;G@<^^&S!rb%URTEA2`&Y#SEwxe3|88mhm-E|i f3i7|3)zX1c(MP*4(XCJ$4}y)A!_iX9b65TeRl}|L literal 3318 zcmdT`YgAKL7QP`ofvTJ!`YK8FrdW;4)*EXl-y+w5XBn9x(Q5f#w({`fOhR9wCdG$d2-kHCgAY zw6eP260|t)Kj-uZ7a)$KF*UtCY4Sw4a^os0Ina-0#Tn2;fB@)3*H{x^N{UpxKz-nr z|AZ;oD`s7|_Ea__=U;`CV*{quwUhj$ynEN-HZ+T=UYCs&R7H03;EYnVFVM*AbZ9u+ zh5U4MPI*q{y!D#GbPD3AgJI{tKBw}wQ`M~YcnZ={Ejqe3_oCF|MM5(KKn_tw58RB4 z@~wIZ)TCI8_C$jP+$RyKsjm75^E!F@rD}3UQ$(s_&1=jT61xwo4ImmWBh~DK2K^og zq>nVvdlMvu;d@4@e0ums*J#>Yeo*`b+ukWvu4j;23{uwM$v2 z=@yq1{XJFO_FLwE@wTfRV?GDd1{{1_SXBg@2Me+oAxezhJigU#$8t$XwFYPp^DT&1 zU&rFWQ{i*HuSRA?90UsMCc=pp;QT{)`olQtIpq@a1rD~M>J5yW-M`MMPe~S2~eAqeQ)t;2b z!m%7wX zHC*B`DbOn;_vffimZf_c?OqkKja%`fi9SdjT66-I!78+y6#ZnkW8fI{9M#@|BQ6Nx zCNN@NTRu9Pqm$=x0_)#OVG#+F5Iz$6aRbYkX|HuX=$i&v3s2~`2NTbk9hH^R`;{?7 z)@d%}89f3?p9hliAa2Ix(QOa!^bPng*A4DAA;a9w%`Z(tp5;Td`o5GxmU*8_Uh2vL zR%X8oh&=;C1KXIPjs;O_Ildb(8`rppnt(uEEjr)XxW|#EU_l?}@Ka}oFU-85MZ2TC zA@O4PE)Y-YxPGbhblxcPoD$JrP?bBFvv@PTdC#C|Mj!9zlfs6dDsfGCgGq-JA2&Db zD=|YDhs-}zu*NHbhpm6^=3y^+nxU`U=#PKJWLJ*?U0MAx6kl(06^Pq>Hy=(Pu&z(M z5f+ZZMi|PLNH^yADgow-1+XTfIQf8hxxhs&EF5syu^#m8-}~a#R6_w;ev*v($KIdI@1Oq(N4WwW;PdU3OYy9L`ohJ!H)HmX1VZg` zh39H^K+sAfrkF1TBo}pIj+xw_dHi;zXq55wc*Y5!W2N{%FOzZi` zErKnuDXxJ@=^3%C{NkBTfUZ53_hny~r#Z}+H9T=}Oe7uwe3*j%Wf%HDWnJN-(U{6s zsEs>-p$rgKcO_XkZbzbR7bI`b?U=z2GH26rxwt+LD6ly^D-~FAg}_pV3Px8@bd75G z^2Ad{ds$~=H=Vfqd3SRYyX)>3(ZLF9qAUz0=lRf7_Hyp%X>ma~R8Dxw&RNnVXwEN; zP*_|Z;k9UKs3cT8!pxv!-r2J``{lR5fZlF3bxIOjG`XcSg7CE1?JWjpqdon~mQedD zIiVEei}2I_oxm_ zmozyy+ruBbPG8oNV3f6GtQgVFTOZQr{64@lh)2FLdKq9FDVJ}047SCI#01#1KRk!g zZsac=wgFiFf?hf)po<}-(=^q?dxPa#7-RBR7t=P4P_ID9$X;y+ELS(5Xz(ouI61l1 zw1CtB?TD@c(ABibZ26-RF1yuf+o}%fLnL}=Dg0ep?}p+^r&%O&gXs}z)68tQk|8Q< zycBiRyb3PZtF#>_1e4#Vv#=gbF3dGAv3HB`U|VJtUe%hw+F@wECTs1oga&n4K5iV8 z_|4DWq7yAbM3O$5#ZlRu0OIx{d3v7ZTGk859ieI4E8(4t)aMIoF1>>DX%A`dYMcrqL2RgF5QWNm%PK*2CpF@z;!Ubr8&S(|wW7Ua z&4rfK(a%tX_>8J9RtM%)U4XC_HT-$PnqS;CXr^#>J|$Ygk9p`$#kCw^e(ttEv8e>L z=uBxyA*+3R<7VOl?JCb_A!rLmUcnF6^+SPQL(Uz}2+>>t^#y17mo-E+;!oar%ue91 z-JGT5_Pj~~$Z-{gw3k*Oj8VaVQntV6mGVFEvX?tAeI(D=@~Qe1$O+(a#QX3=H{7*f E0e&Sr2><{9 diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/EMITNULLIFIER.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/EMITNULLIFIER.png index d6e841d1c032d7834f3ae490c7f844f2f7fbaf1e..50c4328012c1dd29285d149ad759b639876ef661 100644 GIT binary patch literal 3593 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 aZ$JXG?{CBXt@fq}2x|*FbHd5XxBdZj@u18A literal 3274 zcmds3X;hO}8oq%*K%&XijuI3Il@=|VV_F1d2^LKegaM_|L=Z+HKxAKnQ6Q*Qsj?Ls za9Bb`u!3O^A?%7kB`nH7DoY3`5hR2V0Rx0(KI;7JIn(KnIcMhkai4q6{oeaN?|a`Z z@vkm~ty^@q006c+e(m5602~kPpJ}K=>mC%r831IOql5jam>j84l3Y-`L;ZQoDcQ!) z;`#HR;jAKSG5cd=ocrICJYl;#U%qL@KjbiXLZW!@c%dhRfKj4}--J0h76N>X3K{~e zHB18nbRK|1py3KsAh>P>U=Tdn&VW`h{y!nMHsZ;s&v1_uZIp7hT!mweJuik&9S{VlSXu0PCU+eBng(Ol_)2$Euy+o0WxJNE|oeaB2DjuG;nV4un zK<@fou{QBHVl#1Mg>5&#Qf9HTUJ)mWfA^cas{c~t5(C-d*&`zlGu~aMVIV8=Z<44( ziD*08&N0nEHf<*?*zLI6hNIIO0#xq%ba55IZGrv*@;{hSP>h4x$}ZFKMaTW!U{VF0|5|4ML3=fe{enu)OUz*_EI0|54K!{NdD zxRo9h)0rQlwAXZh;+5>u=EyeX)Gl*Urik1V!k^)NFRHX@w;&$;WmF}i&4OFH(e*k& zVgakn?vPhk{0K&Y1^og(}990~?mT#I1; zAR=}hjrjNoLROc@KV-9nv`QgnZt)PN-Tjgcd#k&HEbnZ%lQ*_NV(;^H@BJl zvdCO+a6}eLPSj;8sZr>D$VM13^U}nAbktt6OGlxDZKKpb8EL0Uh+;y@!;s!SjM!3bicR||KM66_icD=0=;;m7d#415v>NNi22Kve z`e{_1Ez#BT)t!}jY1Yc>nc=2G$hotS{`D^4IPo2=yG+f)-u=G@1A3^>=z?eg2bye*>nobiJMRkF!InJH_yD)+6c6R+oU6yAZxNrD*Ij;N$R zJ%bX|(RqjcBDD=CqT5By9nPscrY&0HY&y&d{*c)?RruIrre42R%gbsxh`kF_nG2<= z`Ve8T_CiQ$2NKP=8Lo!Lngv^F*fYWcpoiYhnESzHXI`sZ1Dy%I zhyI7u`0ZwcvX8yA6~lYDaiM5k6-@Z3f9P2lta+LKo-+6ER$NKbb|Ce{`@u3u6ZHM| zHUDX=gYp=7r?_`Y7U_+FY;JHo8%fLDp8ue?CM?j2%%kymi`6x}2yqtq9Md9B7H3tr zyJY~1o*Qzje3H%=qM(d$6^GFK-KK>mX7f@SW@w4I7Jk8s;nf9v2Dm-N#H%9ux4se& zdj1J!2@CAWP9CowjQ__?doLBVAN$iKVzdsS6kS_~CbFY$+4J{`FN(EQi;9ATg6Mlu zytju)LnDGv@9P$E0XNzu99hkMwkRy4{HVSDYE`Fu2z8s^4yxkN9B66R&BO0PVvD$jZ zdLaY%Xe&I$dU?Z{>e?OR87)=n4%)TMTeY(a3fZ=O2OGSU?V+@Q*z?X*5dsT*s!Vk| znI&i^*m0*0lhv_{1<1Ub(Me(Dh(sKtV)+%7tSd|#+bE7wmGjhYKvp{PuenAY*&QZW z<425-RJ)jWe=~$rTe%aicP9Al;hKvP!FC#s-bnIri(8IdaMvbi&?9J7(A+i>ysIL89D>Dl?VsrzGxV6YmWJ|b0LCuuv?9HnfH4S;Nukevx74b@k z5vn{PHn0EKf>-Ilh^4ZaTweTP=C8h?gUlTF6 z3J9Ku&hK(Hn|x7em6z~k6@~;O}jNW$Xg~RNe8{C5Z~(-EB^YC6Ni(_;~CTp5_KB) z!o9QXM)D(TczRcVJiunhx7!669l5{u3MveEz280dZcda&dkaTA;k8LCu6|H~!Rr+Y r0v9&NmFsVIXhZOSGd=&&fdqBe@)b#7YWO4M4B&Xw#i8_w_tk#_5@{E> diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/EQ.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/EQ.png index 18bd16ed228f94e49a875e755eef7429e19b393a..426d47621b060ebd7ee72baaccf245a42381881e 100644 GIT binary patch literal 5438 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 aT#<`4OyrPxdyUsz<7n@Er0!6_)xQFld#Ts} literal 3220 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 literal 4129 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 diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/GRANDROOT.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/GRANDROOT.png index 13638898ac8bea6231912e90e4c9d8fe25f76368..34d66c5a33146a4177a765465d920ced947428fd 100644 GIT binary patch literal 4453 zcmeHLXH-+$wq8M^fPxBFIG_mkilSmbDS`qa$dMu-AVmn$n-u9ydhy6nDFLO|b0Q)w z2m}xa5KjQgrCYK{VM`kKbi$_D-!3!}qHg$2CO?iDP3-(o|d z-`w$jiGJhpQd(X`IeQuhu)7;bS2rEvLLqlv z9a3S@%=z-6#CXf7Je3o9f%{q2Id%lV}&1aK4GFevbJsB;=PNIFh&&G$2ySJ zBxSzFn%u$IB!c`dIhX}3acFLfeteNGiR9AgBR8LsUBL>C-Rj7`rQQy?YzgIdvz_96 z*||u@z~UXMcsWkUx~1-Mhw(OCP)kkfCzN^j8c^7^$j$wu-8HGNukhe+RS&QngcQPhlrto zdGTD$;G4%A%FMyXE*2qJhHMPaF@NCm8OlhNd1No0-pnb4y>uX{WCCN`8@EH54gRjX zreDmSV2}0Bo9&lx|6E*jvL%^#ZdbIl&`>!O@1-RlGjjo&J<(3btUE!#``k8Gw~Z_B zA^;#dKzn^^Fzt`9W@+w3INWr~Wox|0AzRLLA9FjLgq(f151kiEJ`cDTw0x;Y@de-?-$`u=G0=`u%Ce5Q4*_#ZT5N>nuc$QNl5at~I< zNR@T3W^WSvNG;zbODXYAN;j!L!REMSj~@ZLcReGj_TJ>?rE{+9yN2~9o&2^MGkKDD~Xti!*m$Ng3X0Uz%cJEkxugI_fX z@5cq^b%`%Nj1T2movT}+O`joE+mh(z>*(a-m)}*V>g0X+G$8=B_H3q#83HRpMC28g zk)5yT6nuPsZ56HEq(*sk<}*)*hliCf>5b^4CII{+1E%$xVBQiD`e&n_dKov7>+T7Fk6Fx&PGx{R(!}xhRneo%L<<$6#A_kn27MloFbr@5*SbtqDj%%I zqqloESs8J4@~CrEm9;wne426-}^+?Mmgm+RRQzz86(8Qz+7|z>Ue`{65 z>y4R5``}M)Gt!x39wiv(kkjX7dqd>zY(oIK zdFL4LPap8pEob?kuDdoF`5wrt&aS8G6o<~7au5>C!3TVnf!*}Bi%L=;`fBh0 zp;;nr!43R#rie~jnxKsVYWD|Xzwd_Rw4ab**yq_ASKr4e@DvGlpo_<{j@-eCC!8bEc4L^GaN(gZ9TM!h z0K)9uMZm`+tcWZYE6=`14~->hsKBY4lM(|Ndfeds1i7bD=;N|90E}s4td7?@q?%oq z-)T)H4qVhUC6`>Q7TlZq(A6nrQh?%(@og}9szbc20Si?6t+ve#Ga@l9bn|sf;vY>V z&W;X|wi9^2_w{Eris4sRi*oNvdUX$S(v5r<&T4Z#r1$2ow$f^#yQ>(kpj}1D+W_xj zXG-WyQj+{71>S>Y%@G$vop-vp&95kV4w*31Q-hgHdTy(!HI%rY8YOklv&1ZWx+n58 zWiV0vqKW^E!ny(eT}|*1G`Qa`ohoY4qPsk@^06aq{pp9XTnMNg&okaq4&v+M4r^ya zWx3itHmR2KCUq9K66^|cVIjM}#s^N7ZMg{sT+K1|Q1eq3@)^HRp3U;|u_2kUeHMd& z0Ym<@vvx=p911pne!)%Gg!10jz`rCh&FtB(q^4=#BmIP$wxrO`JNXZV@me;fg1_ZPbKZD-CWSQMw0dnBXf;qUX-APv?i>kb*<@ zLNd5>?n}S6iVxKlYOa1cOT$9KXmXP6^!lDbEbFGVk+6&#l^fNe&G{T#B0Xy9FcSku zi-=^FzGWW^sHI<~W!Q`C-}_w#_@`0RXH${@)e72+Uf(xh2-#||g_ONlBfmUf`gsVV zwBtIx@~(Qhrk=&h5G2QuBKvD7MU3SOGY4QOPxdY-2K;8_n}Sn*XRQG&?+&`P*L|K> zG~Ck#OF=){8ao`XjS_eQ^$of_RI$;bYHMMiyE|@*^w9WXM>^T%?1;BnSU^8d=XQhp zVI!B7TUU$V^04d3V43YGNojyTVs~^|fk~xt_}aDd@02#3bDhn1`og7B&yT|Co|QyX z+^rY4&>|0SubjrD7*7??w@451gqqzXe;Ci3j%y2Gq z=NBOYG7?`w`9_?+{;njQ_w93KPJwA`JuN5T=9tYz+?Bv@YoUTOUcNBPnj$ZGNqNOT zKQ-WbAb`VwAK@U@+V6s7alZlS<>_2ZOB=+wRw6$2yecVPk`~(*iWS$()GOP;4d#C{ zYKIE#*Qn`)#D5vqKNG41K^okAJviU#>my;9P*C=1E&9a>%phAO61r&sqqN1Sq5CItyDisAZ6>%U;0W1hXBeRUTEh@eWp;kmt z1Qo+*hztpcOf41%Mi~MGND!1Mgh2v~rtg``h2y z=bzsnvr}HXc`X1y`N&~gCjgL;1iw;5N}llk83O=N3rB2ioG)eY2Dldj6xL5V}B41{4qd?@lx_I*zo|qwqyyQj3cU(g-4Q z(9?pXHDK0Jw9qo!##JDc*VWRr^*57l9PQcAyypfsGbkN zwW&TDt!ueR9(dmsOi#(fo|lIu`*p@~l6HfuPgJK87vCuWVJtKzaS}#B#eoCE8j)`5 z;cF^d{rWpm_5~kP@{m+bS;hJi^1&V{M;vkfJ#%xc6k{M zjMjb@dyHd1ijy$5QW^APS5ZdW#OS&-{wnag*~Y+g>-YyQ^DXf9W*vX9rbPFsgT zjbp2W;h^@91^U_bl|)I2JI`5=-m9^FM5;jWLiU25Sa9Wv#l^9G<*|Lqm11TTi4-Us zmwka0`rlINX(=Jcu%<&t^eLR&J{h4v=k1WK;a@kkb|_zp&zS2t3fVnM(Ogw(oRx~1 zimUy>R#GuSQ#KZ}?{8a&G@-a7`eM;)#$3GN1GNqx--+nu$FU@#vFuYsJW|D|Dy7}G zqIBL$YJp5Q{3(e(Ys~QH=6bDM9iBGV`uWP#bmo*VfGyXLF3P-*|D~hFh<;3JY9Z^+ z>=Sxb*NyZI6dJm(h0>jo{_1!MTF3|wEQ+men4QU)8y~ZVfeO1uTo7SPfFpoNJr@)9p>Qgp4)%`*RVjf|BcQg zCL{R*Vdd-@e+yUlNw?npDU~911#n;6gll244b-U{z)XMnwe9_DZmNfC2+6gv#@&CI zPuJILR7aGBKQ3E#y>0NUxV+43+&pH44nWyyr(IhI8rb{0(f|lbhpG0klX#ndd}V3i zB6`Z?WzFM0&Er3v*B>q8IgcN=6r_!)!NJtFB~zKYR?UMT}?;mIL?Q zh~3+yD-;;R6$gs+?<+n=RVkO(pzJ<;|F19RjNFlr1V1WIgywXvk z$ZaTxx;M7=`PY8{QRj4vQ#^KfTIHr%I~3lYQw4a{h=iS=Vz)LhUp;H5dub$3?rcp` zw%Se;R^-UTb3_t{79EweD?k(NFxtuIuvfI|0cgtK3j+;a$Tp1qx_N3hPu@^vxRqUP256NgWL;JK1ARVOxh6{mzm}QvN^u z2mH@o!x*y8!nQ1pZ>!UFvL}`KMrngpZyUtH2Q&VbI5EzgS@ zwg-0|ZA?4?o;(gsbPh2%5dw(Yfp-`C<|evAIW^bXT035!qz$*yL{*oSrfjF;9p_dI zf<4 z9fmY)*sVy9vx_nkZnh5SV2z zLIH1I-qOmXlUZ44{kxZ{?4|AzkwwQ;b?lpjLQ?lG8rqmw)i7Hg@i=RM)GY8LvPiFL zeiT%Mq$e@OUA?@?d8%I@BP`_I%cPqWRxbZ-8vVd|nsP@hb8MBC_@!O4+OR6HDxll4 zm|Q|PAoMwfr)1Pe|}Tnr!v^hAePn@6#7nmcO;KJ zJz52`&JqcqnetB)aoC!7)oFz;SbA{y<9l(mhG+yJp2Wr9B2!Q2nFFC77Li0Gzq$gO4S@hvpDf;x}Gz`qdYujb1oSBj!N-JCQ~DlZv=b+MeK!N zn;^3tIi;q*)c9+t34{4(T!fAVS-Fi1Eon|Dx6aL;p~V-%CZ)M2%a2EDs^mz z&3O8PpuG;Bu4VAsPzXYj%h+u%Nd;hPO#<*3_|&gh=EC~)y4 zwe?(f6Z4?$$|i6zvp6hWAdgSi8|*3Lzip)=TXq?fa50BX_(QJ~9$FBgt!_Nph(kwa zFT1^jVVJTU7s2#5F=)8*0lu%dn4WS6eqZtkUFj=(hCARvtIQrF zoJ^UzXSx$q=yoN=avv z*3+*(T+Ow)d|>$LFww(Dn|NWgi(x*ESF)44h3mtK(plo>TQ1)bCqx0={@8%oi0Stc z3V1ie7X{SwSp&2?!^`_&>_gyr0hNBdb+?!?UwWEK_ggW39`vHJ+Jv0{jOF4q=xId^ z@Nfo#LX!)bk0Y2wvA?-%yg;ov$Z~X-q2^0cUOp zw;XIe?x-)G_(kL7byUJ-53>~*^d^r4pf}4WR+TK)`}TN#Y?gF(epaXc*EvtxjaS*& zk4q%mM{_l?Nz#WU9umWW5jiE~l=zcgd#^E*N$~&u(edv;6*sMd-lVSVxy7Gsr6E4@ M-7(vuZ}C6<3l=l}d;kCd diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/JUMP.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/JUMP.png index d2048dc928c5021f6809a4c1504487c72901b179..9d9fd47b38b094e986aee20c8f5994f5f40bdb73 100644 GIT binary patch literal 2873 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 J1pe`7{sxU-I_Ura diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/JUMPI.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/JUMPI.png index 1c03b6a42ded245b8288fcba181edf9bbd296add..326a7971d4a5da91f56ee397e60f2acf72df98ed 100644 GIT binary patch literal 4232 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 XAme<3vGwCQZFhdQXDj>D!(aRjB|EwI diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/L1GAS.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/L1GAS.png index 66a53c795e650393f529183e90c959532eddd696..7ec775889c516d20ce5ff8b4f8731c39c6b64599 100644 GIT binary patch literal 3554 zcmdT{XH=6(7k(2uf+B(n5fM=VS+F1-0YyNJG_g=b1R_O{UP2ERLJ_hUiWGreiii?Q zAoLIgRJu|UYCs{d3Q5>dLJ{)4cs%=S&$_?9bM`%F+PyP(?%em8XJ+Co%#4KvB?SQh z5H`7Z;R*ookidF7KNQRpW_U+H`3sW^=dL2N>Eol7FEvDY^i?W2ob(Jnwy(%oi3q<4 zLN{>ZJ=D9C=NImPh>0k09ALfD{PMIQh&C4+=N9o~P?lby2*0%*2B|HCkM>joGcOQuG8LsPR#Zn85U5KPi^Fsp>;O zLFPgh`((Dz$7}+Zn7=tFm?T81n8v(gj_XlMZ^RL}QjDw=K{2w_2tym)X#rLNvk$70 z-@-GS?wtS|jjyo>UoX0AeYd88h9kFoK%rt_jzR%EU~%ZscO5_f_rX6@`iqc`g^E5B zeyyn`Z1qQ~+6wd5{oc8l&ipEl^7vNSOJtVW@5x-0(rHO{)<~{6V^$<9XcRL$7inNf zbA0JoeJXOOV>KEhA>Y_P&kLNlrU3h$y;8(qmCx#+m z#%x7gs7OuR2YSCHc$=QKnpZ~kGdw>(Do|6;7S9&+&ivK{KdzjzC6Uyo}D6$jl%S@-X5ofuT~K@~Lv zxWT|~*VvoyR~>gv@d3yzvYdYH!)>hoEpGk+Qa@A+!OMalP`EiF=OcTw+5>u(wUNOI zk7D*y^e%yjF9TywdKqZ1p7o@Q$Pc#f@Ctr7i2oh*3M*g%P(3ud5o(E&L^m^#C%k7w z4+32@$X`&N6wSdW&X9U@mdDqJ62dpS`t;&#HhChT>{CjTaPv>Y!}L(SwrYV zSl$Iz=ZBbA;vodlylnacH)5o=ws+Whz%*e?HSITq=ZKVz)*?1Lq2W2LXS}EsTk>YP z3RdHAY-OaMZjO9g`RYhaBIMvPo7bP2KT~Odxh!JR8a=_TGm($jD zVheRO$?M^{h|bTtm?yd7fp0o|l9n^epF0(+kvgTW@uoVVbW|)dgXu+`ujw)@2d7A) z`PKnT-(0v_x1Oy-=r|q%1(|9-FT2Ejov;ht-dHO0HjEpDE-1Q~ljpy^fMr7f!m@zj2Bu3j) z8Jrvg&>*<+fZ@AT(+M`7Euy)WRcXBJvex;Ikc9onXmI3hG))YvJ>CX{D1Xvy>1%?q zD9N~qS=Er{rEh&ZyzXj;Go^a4jW(R#g*Ja;%Jif2Iwr3_NT!zM7H*}Ap;|yMc)Ij8 zM|;o(zevR%gP|=u=dB{i!+AL_9zw~Q#sT-LWUSo>*2{=SrWUS%?u~s0h5JcDDcB>- zq`DW_&+23b*7;s06RTr<)qAJqjEyD_yrw^hk53ni)H3sC`>dnVAB2I4eT zLf$8%#e6G05Jo7g%E_|rxRm4Su09?t>?2vY|Mngg3qT`PB^yY$iiZe3jfRq5j73RK z`dvDu4}o;hhrA%(d1T1V?WMLJ)!8Pszdf1j$xJDlgeR!}@UTdhA2bSnP;=yC-+qC; zl&|$Oa*n<-Q|PmgrGd$Nw$1ljg?@JO{G364oLArMo1nmaU*P!c;+GBLT@E~S|(hEA<{w9mBIp|ABPdc>QWG`+wLpFCXLAjYcw^9uYFoe}Ar7w*2bg1Qf z`ui<%!IaabWmIh|9VXcOwqBRnYmu_VnP*1wxKd7W(a1ztX};6ya0V2<$IkOaE<(!@ z;chYLCIDQmJ_8d&ISW`Y?gYJ=UP#;1|6tIvuVSFZ?Ocm)I<-eO@i0EM;FS?P>GXz` zJtv7pZ^;<7OD8U+AvkTh9_}t-mHw!LO1QJj=zt7}*Ke*MhSNL4UgP)yBh- zUU#cPo|@_tIj6>|YPopetl6TwRnxX}>gR2vd^ze3O9#;5Q-#Z8OLf5U_Vn&cv$!|U z-iESr5X67`|e07%)X|Y^@!}&UeQs+xokyo49VC$-tsa~Fpcix0$m)IR43gNRbV>}TyV2_Qq||Qa+An~ z{qFktM(pxYn{GyV|I@V#$JG`9m%OpgzV3EcSomILt!G{uuIh!_4h4qIzM_oQ0k`&y zm2aMG&h(B@>kw3%o7rmgJArtZPwX^SWY-JLHM`;gs*k`(#XBIEkg~KI98TY;!!4uQ6-Dh)X#WC59OP_IX_>}gsh01Yxp4Uro`}Wq9 z2*my_JeCL=!21o^OkFkDQc6O9%1LVK4cG%`r&vrL+o^B@{|pgI#rIne_Q>r8<9`pt zrrS!%$F4SQxNzFY5p{2`-6Ocvxn?8ExdAsDBGofsvT&x|&(ix#J6BxzozeBfq+=WG zO10(eFDu!f3Dx}Gw%5Sj@_gp`aKjZ8$QdgqBZpd6Apo^#c~klaxBT?#`h!3|tQb7i z%QdG2-YEP2lAVCTV5FoJ;d6|S~0*N8}vG$zZp0n-l*|Y!j{xS2-nYnkq z`Q4d2^X=z87{p4el>h*Q_r5)T02rd7?p900)lxc45f!wCiQAu&~U55A)7 ziypoH$+HW2PYSZc0m+iGjX6CN`_KK{f@U{6)(B?|pq;B;S8&ZB4q~>!OqOL|0EgHQ z?~)-3rVVW&iuU*;s~&~KuaP=3vn7Qj5pIPS6weQf$!cA)QohKI39wO}EME>7o%$kv zXt>cV-jcj5J@k939F9oXJgy0yqs74hxEejqjjE7*!?i$v9|l=`ud#4XY*4pha&4?2 z(XSV$*StyAOX%T=sgB5|DT>p_%g2r<>K%j5vPKlUAORGVlvW!I{`IRU;3Vz!L8Dp3lUxv=!f)XvV31gBA_N4c|WhD+769PK~UKdL7ca3Iq9T*R|d zKd+xI(Y7Wk3vB!SbPRVVshko}-#A$tXQO#}D!tR(xSr>GsTc_%;2*2g7C4)H)O$F; z0%_ZSH@NV=p1-Th#^6&>FMaCDyLn#%SxxNZ`KfRD(wfkbXIZ3_5QHlzGRDpi9zNZD zW6`VP)j<3xY_81~>3-7G{EhdRm(!~TFoE2+m1Foy`&SWdW$kyCwg5EqBi>vdGVjhs zC*B_3U05*Hb>qd6RVYv1``m7Ma*-X;)qt|6(A`tS-{Dl`6hTI(CqF61_|Fe7qU)LN z3TxZmprND6TfRQY|ANZz0A>f=`uhd%aZ<#}3);ve?Q~^|m^7mjs8q6(TDJbByihK0 zYf};QPsB?4e}w;c9sTB|{dyNuh*LQJK;LiQsB~N|wV+$V0r{Sc<#aSX%ZgtEi#oLb zkbaz|L4vtE+2y02$KcCmFaNjF)5gZbq??)9Bz-WRSNY+i$MN(*oHP=c1~M(_$FDc(rL)zKeLGj&NEAD-Sc; zXZ(s0Q#r2}y}3C4t(Ctr+J1D9O{-QQscg0VRt()090;^>t!9@FB#6TrJem?A zAcLe6u=&BQ3JyX6E1#jM4y{FY?FI0dhg_rL8X<{9F~161nk2|?Z(A3-0~@;iabVOs z4Q0!9W^7Tty1~hQCqz&CPZZ3y5n~`5@!5N(}O|m{j z;&+xP3z@poRv=(P7%(htQEsy1v)E?u_9Tv>9ntsJ@ph29p^SwI5V_8;4drsG>CyIf zP5ybXccPwkP=({yFgtg#YYHM2NLtXeiMV8b2otjoypf;?&>u>1@T(RbvE)cY6TJH@ zD~!(&IL~XD=dHFs;0Nh&v-J*I%cbh<$$K;4!}?MJgk(_bJ9$3Vu_swolK8ePi%V$@ zsA+ZM7a#32i-o*zYI910!eYBXdDQ$Ws>iH}dj?8|a3hnZRtH2{@Cw5OCkV&b4ggE| zO8|hKU)DxK+TAJTnuCbz!SB5_m^ZY|>K<<)Znt@B0=+g+b^QDO4i@;NB&u6>i&vfbpMCWrW6gW0DZT!XJ(=0kLShevEjAc0$?g+ z*G13j>KYtU_(C;o%GCu;7A>q>IEa83N*zWFr8s7G|HZJ0c$U&Y+SmcYo*%oL$j_k^ zS5VIN8$Gye>4;7hvd?W-b*)}HC;=XHkmijIu%b>3(%|NFdz%_zKu0T{B>B*O`q5IsEQJlo8T}$rw@z{y|sUc8>n3CVyxSpttCbYA&T<`GrVqPmV z1Oo%E))zcriZ4vftN8Bs>mK}kvTvFfuKW17a5yAFuIyYnNK+^znqj7ZGr9n*OKP6+ zWb2>MDxU}Au3+(n@Tt}CRY%2|>YNSTdgk$sts=$ZdQ+R|lHIHji_R0p77rdXK%OW4 zf(MEyl|zB&_@;|y=5kr|kw4KVY0|XF9cStDhqt?y{Y0$FVQ(h7-7ZKPj-S&J?@%wz zn)MaeJVW8Q9YLu`MTQ>Q*SZx6vp=m0Nb@QnvfJnmgd5ei#hOft3>1zMf< z$(c7D{je#oSR5o5*D^nUiNGcU+znWZJwNJ1J!jUMo5@pQPqcTum+)O_WIph?+;1$y zQNJ_8ptrzGN`u_;`do5IwFvrlaO!5F-{7b|5wXj94fzbMDJFA6VbQH(Bf#&$>2;P9 zi|aFFaOY0*RS}n;)pmW^QdLb!qfubqe1%us-W_Uo<#VCzb_lo*Ik%zFiaL043pZ;F z(moZGMlYgnP?z!xkEB!k6gTZQW_`L^lj+4JB2Pb`>8W)Q=L@x&gDBf->s;Z^aC{w5 zL>QTrmdUI6MrN%w_x!J*hBU|6LiIISR&&p>l%dH?FUj#s-ArN|d3B#GW1E^9r$G=T z^svWksmLxn7xeozBYTT61Z5e)#Pea$wE9t1!--1d6`CRAWyiMgC~=@VX|8X~C(>g= zcO+ycLY~P)iHg_Q=UB^IcF*5FyfO)#?G(GzHDOX zqJ~EO2O4+;Ekm$Ckr~XfdT?Au@zMQ@EU!BOQK{a79ug>W)n}3F=_b$R#>;b-=7ZlJ zuzuaE8x@XC?`Hcc9N~j|b$25tJOSEsKdW~P37wJ=@jEZiA9*tVug7|=&C~NGr&cy@ RD1+bt-kE`ggC0Ey4f* diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/L2GAS.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/L2GAS.png index 1b9668c46bd17fccf6fc555201216c6b6435213a..fcf79de2f78af1cdca4d3ca7614bc8064285b7dc 100644 GIT binary patch literal 3565 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 literal 3232 zcmds3YgAKL7Cs5eO9X^k0Yz|RWYD5iw7em0tuGXmSkdqndB`&m7y<#45w+GT*cPKy zUKRuL2thz%!XrTxlpuis0TUol2nZwuNCG7xFqhH(=vrN~x@OIvnLm4s%4{{#OqeEq2( zr&d?T(Az_EMo%Zaq{nber%KQ8h?OR=A$Um-inRgSY2HsMTk`;Y0Hz5!eNO;~+zUej zWWn4zbI2l`|Cgcq{IU(`yIyUQMMfm~${L?v>KV#L#^S=V-?K73(mNu}3%hx8RRLf%5f5G!AUq3LMn*TbM{I&jZyP-t< zIZ3Xeg-@vfIkDb(aQ66Om}%e4m-#uO&g>Bcb@38f_AqN6S6YG3GgNPS^izaX4zs{f zr;&2OIZZ`yfd*oW?^2OBQeKxe?=x8JJ>@EUZD9271XYj7Tfv+XGdXIccM>}9% zZ+fHU+ZAIkG$2*}ol?JvcqiRdQ`W=yCN|8XY8^ifo{3qQCXJsqm!s z;6Z^MDZyp6$-ro>4)T9j2Y>cHL+sx5gu*PZmE}5aO3*RvO}3+S(hpyBd3DJIfZ@D$ z0Hb>!&)#S^ei;(fIsN@1VOlz!Pe()H+6D~&4 zR|YmqV)LQ^FfjrK$hfn=_Thwxn0E3ul{mQ=D zzL+v$=nn!BMVO|pmm?NA>N5Y1tEKR;1k8DO_xD`ObE(p??}%3SBNy$cBH@Gmmm8^B z7fdb{l+feH1oRM|l*6guVz4Y6EQP~4OBrn8eD-t>wA!j!^mDe=DYms%Z40~T0bKVqw1WuCD) zu(Zb^T%5FkFgTW=PU3=|{s+Vc%%4k-85vh?*RKNRB+*H*}*$I3pwr2S#^QG>d5|&+Qf- zy9H15Ot3jCy+H&e2hxeHb0=flT=^1d_>r)|=gNt7{y&hPR-2CkHRz37y*insfN9IoW z)q}Z9T$|AcY#X_f6mMc*+2X50N$J)~xTBQbo2=id`vX!v^8gaA=*-C zN}!Py06zAf6ojS($RC(k)b0N8ffmAu)O}5fc76Xz>-+Zj{h0hvqA^z#^G5p>MJwI5 zax+k17D|9R3Cy*FVeW>6lD$sd2j?`xo;krZe-kmW< z;qci{8BSB$0?weyM^GnQYIJY~xQJ*B1-rkE_@wJ=RHl1mK795gxc*t6?m05;LVd^` z8@sZLpIls8{>NF*5;t;yZiauMZskimm<`@(9_u*H>^=`~-YwCk2q*XXII$WW`^JjV zvWt{NE^=g`(u4ixEU&6PBs2c9wDI5~`)w7wWOR5L-q^((*L^y$Q*^7gJQ0t(i(ysW zr7fP6TPf6sFSUc9q)5hzyqCS&*SXy0k?ENO1wJO>9(U!s6Bf+-4SZiQ{~77jn3j7g zKtaECM@x*qB6`9hX)~_GHa43E_l#SJG9=V}stojH#l?+i9t~C3EbBq7F6YoFvBb?r z0EVcbWyiSSzfJN5MOp~^7kQqY`WFER9^cz3TMiM#!Hl4BQr$w#cxON2kNWZp_hy1c z@S?fX&$&2WfB1A<*FNwX8eRL`lUDL@;@N|d8k*MZvH&`AIag!nwqOZk>2zXvrnn;6 z>v?~|gsr-`!=>OW7IHKrDi$T#6Q4-vjQ2$;v&cgDv!9^asH*KY+4_l2>H@>wrr1{*({bB@*4Lv-?ZFjR^S;*u!%Ss zh+gQu!)>k7a;wTo+&SbFHTpOWTVsK?JW^|g;SbRTk3MbPlu1u(3)4{S0zsSsUMDf^ z6}#c@lX9|}QEpt3E!P^4w7lnEo#f!t0h=&ITUv{|z85F3TqT@^G=42!YMhTwB{bee zMfPEOj$1JfzLK?_w3*CS=mFWdV9t|jxPz`5hFTus_Gcfnl8Gt!z~@%NslPBodhjVl yD{4Si*n_&gvNkxviA>1-U%ZU}vuAz%DlGZaXXi(0GsbH|9Q(@SP{kL4SN;i@G&U6g diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/LT.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/LT.png index f6fcdf112faee2130aa3cf776701a55886fef0fb..59927272c47fff681b09ffbb1ab3e84fc4a8fe86 100644 GIT binary patch literal 5422 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 P8r(qFR0nqkdFwv_YW;Pe literal 5074 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 F{{xWI<;?&9 diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/LTE.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/LTE.png index 1af3baea07c3e55ee1ad0cdd084f109fced9bfb8..1b0e35cf2908875181345a8eaf6e7a66497de406 100644 GIT binary patch literal 5441 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 N&CRS16z{`a{6DM4e%Sy3 literal 5071 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 GJNplL0p4%` diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/MOV.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/MOV.png index 649465c7d042857bfb75512b59168d6dd258eb34..4d79281a5e34e1e15c15370d027e49081da1130c 100644 GIT binary patch literal 4293 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 literal 3994 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 EpS_mPO8@`> diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/MSGSROOT.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/MSGSROOT.png index 62aef1a1e301c4eb3604da3f4bff98139b205e88..d39c81f4564772e9c7711bd57f1a842b8f1d2872 100644 GIT binary patch literal 4441 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 literal 4139 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 Dx@Q$u diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/NOT.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/NOT.png index 05ddd512807b8fbf5eb226ec2a8d7f57c9756fec..34907da432a4bfd05d17f1150f100b8e82a70201 100644 GIT binary patch literal 4670 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� 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 PrrRukwK1(a>3QvMWG|3J literal 4173 zcmd^Cc~Fx{7Vi+`P>#%~$RWp!B{K+&VbF<)ka(iNfFc?dxy;HbphgH+!l$l)BZ7>G zh#Vq^Lm(hZ0uo5#puotb96BaR18qZ_B zMT)lZnc$w3qDO`oVNuoVseR;CBPFR#zoq17;XTZiU6tk6PyC6cQIzGhEexRo7^Iqo z3P1ts7!?4IwV==7!WRIhLh9>)nhI#`0qQD%NCR3bU}5;bJ5WyHJ(H=dtRB(4!XbFO zAqy~wipF7-C3s>l97Go?#3CsXvg;5eEut}rKEy>1e@CY7%&vPh<>rm4KEM2 zTDYZHo7!$-3M}qZSJ1P1s;@Xh^|Ld;{UXU;5$MjFLgq-gBn=Yusbc|V*zSjpTC3co ztE?mXC|C%#z#m_59H9EYs_(+}?(d zR;n?ltaP0ePnGdil^1_n%39)F$okS*zQTd8>9b>F8NZ`%e&J|BqSR3}Q&fNk0@;|= z6IB0j&TvV>GSP-q8gQXTeJ!$9@}YoII`lTSW-i?tJ3y*W&wz;S0j=iX(;_*U0Hcvk)9(}`XC4drYD_7Tvi(1q{ zYNyT}SV@*%(nu2lRx|gBJx!xkhw|ABai5uf6>YwtoQN)X^$h@``vk6+&p^2y42-S> z%dp0OJx&$%5IaRW6%oM|SMu#;$;SwVV*t#KJ(GG|)dolnHw7!%^(C(^^SR{}5> zPygWnP7O2`Dno{~6=5Gle2Z&d{c4p`9zcX!5 z%J|JT>sUZ*e0==54FUlAyp*D}$4b%7K{|r4#u5M*6({WBS|g=H=d}T=|MyiY+YEwl zm2U~%T1mNLl@tML_P)>;yg#tQ&G|}0CfA2QP*lXpWFv^}W2ZmRrn!vF0T?I1-_8)jmL?9wn>Gt*O0 znh(;fOKTnWP@I-*kd~V@Sr0qFiGiLwoR1z?B-5_x=y_5 zjcU&c*;HH2`T2Uhdj!|tl-un$9A6vZW1gOsc>002tdBSH;P5>mH88%zTB@+e?VgaF z$Wy!Hg0;=0Q5X9+vp9^twPAWA`8KfDvY)R7P4H*VS6eQWhnlzxS63zsn@68ZqI$XZ z%Xpj^kt9Ek2yK~sFXBD-Z<=_UnLBV|@~3z*wHPOyt+Do72VyG>+K1|nQ%m0jdwSu4 z%}Q{f@-HLSk9N*=_%@U>=_nIz+N{?b>cV7YcWZ*?o`H74BGEaT5bd|waYipHWam|T z6snek0*%|-?auBB(}SY3q2e|ItKz7>g8cZbF#S4pB*n1mSa7UuUS44@wSBTSgnvs& zE5LQy4ftt(^~IC@92Y-grDQri(&v51r-xMah!rzq)K8O7Iiv-$T+#OB2A@GnexZ^K z@n`zIs!MSKF0LdOKH}Q}M$eX-mx=7I^|($*YG?DkqiW{mN5TcSv(ak2qG*3Y36s-M zK1Pn|PlH7wLvbQ_u37eN7-U~n)tq*{y>Bh6tpnV>+_VwNJ7_G=8nPW6oje(PogQog z8xp!FjVJ$1_(kHV#RCEP#=*CgQ!N%`jPnI-Z75{4V~s=7EvXL38!x*S9Kqf7CJOd4W0Np*(bhJ6a7X71{hoN#YkunI8bu#`LPWK>AYw< zp^`%N&4}DNd~DT0H@@H~VHJ_`Q%}=;`UL|ifqeEZGx>?`es4YPx6Q9%tmyQg)c z*Hj?(n|{pq6;@hJx$#V>YxH>dDH8UQql@&BJ<+ut`Tkk%n~pK8naFl=>eZRI9rzDR z4xZYKJK8Sj%f&HHx*x)WN;e075&zq=EK+n^8u{tXojW$>DF7>^53Q`^l%(W*E&C5E zKfgOuUH`p5JV{&wEb5w9e1rCsAs@XCFNcHT0}24r){W;KN>XKgaQ?`@a&`P^Pr3iA cfo9OF_r0&2y7FM-Qmpsw_SjXmBjCc{0QQF@wEzGB diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/NULLIFIERSROOT.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/NULLIFIERSROOT.png index e8de85ffe1c2c36a833223f0a3881264cdea357f..fc8d2cd1050905e2e464dff88b46cfe9beb0895f 100644 GIT binary patch literal 4462 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 O-o9<8TlvONhz+h!i3ugv?Q-#8fWDxRs(@1~IO~ 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 diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/ORIGIN.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/ORIGIN.png index bcedd1c0a564f90bcc3713168aabe17703ac8db4..f712ff960843eb18e23d0282da8b1f5cfe82b50d 100644 GIT binary patch literal 3550 zcmdT{cT|&E7XL^n(iuUKCe{gppg?Gn!YG1B34#L}#0VmR01}$iKo|=H3e3=(5JA8K z0SrYtf{LMKh^sV7Kn0`*DZvoRemI^zXV00lGkf-&-Lu~x@80kJUcK-4?z=D6*2Y{? zOi>H~07;8ergi`z)B@`CZ4j`$JuW;5+6ygAe>fYGGdnz-lwG%7*fxN`+DtW)XZf93 z3)(NU=iIb^B-)3NaWW2MRJ75CX-XJthL6*tX3UECI;> zH5BDoW>QO?Zi@QE-x$=}T2@gcelG7BJ-ncJv9!m8w-Fq*Sr)?<0TH4GiJizy9>rjL z3FIxu!bc4_E`|#EMm{2Hc>^ZPG?KOxs)jXzDi4*c31QL1KstA?PU+LjOy*xF4KldqVJ3}wsq4T>Izri^+O zM&oIXZQ=c_QKUC#es`%ar(5J}%c^zfMhGz;#~oN%uktz`&~zPd=q~}&Nqb2TG=27J zK5W?c!2^W1UWxuoX(t8ryf*Y^aMrMZ$%E;-Nit6o)-H3S=!&`MzJkpOUHPJ2C*7`lT2$QCu3V^oO+h7mWG_jc}%RPz0R&NSnWHQ3rB% zVW=yrX^6ixp;`zYe@7jt(8!xQYPPk7d(<`nD7zvo_SW8>e5628J*C7Fu6q&fmiB|&TE{iU#^npaWe~}w$oO{R|V%TW8rD6RvK++IWo?x zFRTV&1e}V#yS}4v*B*vM%3@d3)V{^!)Vw2&sLO+>+NA+p&TN!@UW=CxsS|U)5E62) zaDPR_&9iX=`r6R31Jl~3I?bw87ucQ$ovuy=EZwG~&ZjqfGc{!UN+sF;%%U-NFtP$&SnH*!Wvwso5Ijg+b^?`m%r^=7Qsjg&%u5DKEEVYw9 zyLSQS8rg)|P(0(8XQ|(f#^S;TO4PK@a)ykqJ&`a8m@DVo$3>^>LWSn$e&L}kLp!1a zeqJa`Q9l=Es1axUz>kPF_F9+1e+S^}s^<>90C4UU6Wxy7%%oYUGA-Q+7-bJ{Gp=;ZtOEP?c55A;LdNXauUt{8(dh{=1>zqB2bme<9ezeq?&^RB^rBj)2V|vAt z^hws4O5F=PL`R-g@9eimN^d@rgO3M#))cG=@(n z=?R2r{yxDGofzEOk!gKzoF~$tDkT-cV7kU zdzktrs2kJz{`gDj@Lg!2WvDVzBv#?iZk|66A>Zz+FZE$U9wvQ3Z1fT-YBme7XKPln z#%nJM5RRx&j8@RZ)zVQ0^U=5yq#+s{Rg$kVXp`ut+8hW}Pt{$mcEv$n z8^RL(@<-`Agi5#OCeD#H>E>&bfUiRY86P8MYex3>GQXR-c5HHUfDM!6kv@#dY7i;~ zfk#s!)Qj?DSb#XAvCAey8Rh>zxcxcvgqlOq1*y$rGrF~kh_+8f*{PfwGs^^>`gLlQ zIgjfi)L*w$h_m40)@sw-t6|0>r_}59+^b1V#G8GZMI!M+q@5+iCJ*_jYvjin(f;-t z1MQz+ZO)cD$nyq+j+qYg5|$WsqvC^o*wt$~Wsd!u-CB+9d)Xl%mq=RV(+gK9bY4cyXV@@-BrM^b`btCK27ZkKiZ)tiPNt@GJv!(P(89P4M<@AlfbFCI=g zS%B}KEpd-gh3|Y7v2Tac)|hiwCPzQgBvIlOuL9d^^^ks(BM&2?dz3}>u>M6zr_a%` zKCBM$!)5`k(g=+0H2H*E9Q{m9%}41e0w+B=PYuV?wd^twe(+2p#mR|{xx=Nj71Onx zJI+lJt7Di|;}=`Y77Vb2%8ypY219pujI`ueY=#`;^UgEa7#6!Y)ne}fQ=54W8_gnm{7XC!)K&gP%Ri9-sdqs zes@5apWd_)Fy}qCQPxY6`FfI+R6-ty{vc#{ZIUh?`qc(P`ltN*f7j{@+REm%a40r?>%9S3oU}2e9>4U{-vQ^q BV#ELd literal 3197 zcmdT`X;f3!7Cs@!piC8)R51_*YEgk`icAT{p$5w&aR38BtU|;PKtcowLlmA`WqL}Z z6oa4)Dg-Q&Ff|0F1!@o~LIQyh>Htb4AP^!!l6R@={d;S@uD810TK#jryYJci-m~}q z_SyTp{eF1k^QJ@Z5Jq$7yst6tTKHW}Du z1xmG*s%*mz!4)!E`?5^MjE{ydLGp)cjB(E6uZ}->U3Q>G;(SmFvS%iWdfA;b2=(#aP)cb9TP< z32tw*hY8X;9plwzhnjLJ)<3c(1=eeA_N>PaHCf%jJJ>?%gq$;oI@KoYeTqymv^7^+ z#l^Mk-gb+;Gyda=t@N_N_qZ>-UEmikh0;^+WhI2*93z;xUCpol`7DH=fH9L25eY_S zeFW*@$@LrcJt24h90S?P)T(-AaN4L+wOy_GF;$*6t!7xJXoCdG9cLH$Sxpd0~OK&a2z&7M3 z0@4hPawTK$vP->>cxuTJP`PKe8ksTE8gldj_}T8?NFUb`@6o#RHNxWd~GH5C_*pM5ek8_ z6YMK#e>f^We~lHc(%tCoUp(*xoJU7-@PT3%rDd2PK++ZP#Bgd=1XH&zJOVGD?Lb?v zA0&1a4yHQ?VjiDSs1;~e6QH5t3+`s=*Rz1_xl)q{c;PT=@+D7QjLycle0;IYC0wd4gIVq@Z$WB_~71MMy;Urb^v3oLCt zHh)r3>LPu5-ae+eT76P!w?jd-@t^xrx9@%d=0fIBZ`!s4S{Rr{!T)GiP`;gVtZk|Z zm(~8n@f{%7cW$6Mf(d=*FX~#d1PhR4U;1&LFG@PT&-J;S#+Rd|#A=1(Mx1WI!n8`I zjGn;q9Q9jbpx?G8T7P(ItaB?YFHR?xLwNG70HqR$UV{%i(6}JyzI$_+=Ti+>vh&E< z&RE!nlT=~mp|ZD@%yM%kiZbETI=~+6Ig(TD#I_g6TMU%P^5S@LWuILtDs}MKb~w`5 zcdudatZ|D$h)!#X1G_&TA?+JH9>Nv1n`nl!2!4R)Myu?R?06FhvbVxBd_xh@)n?x+ zG8=w_gTx=Yk&hFXg&FCXX==Xeo5tQv`VNBvq%p;y4hR_w-Nw)}Y%V%|F<|_V{CfJZ_%8h2X2Kjqh zclc&+;Zvo(S}*LY2xe>}=ja#WT9Z|C(HE0>qMVK53hv9}Rh5eCa7^C-wQ7zkA%3~- zv7IO2bb{h5_X@7hE#HA`svs8tOxEevTGryXs~ybpL56SDS|3*rV-U4fRZ=gO)nu=K zXTdz{c&_*gy0EA?T@SE&iQ13JPcYXWrNVAR=owroi!SV+2`F-UY}&8ruqi=MaH|fe zkn(3;B)9GEt;37AkAe+oc!r=-I?s5^y;VKnj&og`ia9&-h~8DDADEHC;bH8H^J>Tvrr`7a{s7?uwCGvK} zdd^rW$1gVyQ1&-&&rKMD;cq@09e(DQ^V^(s&Ed=kY0R6Q;8+jqp@qMzWt{5B>Z*ia z$f<4H3q$;JSh|HJ9<_%4tNr=EEBdaW}Z})RRK=tFcf?vqshtD85)cCvW=B&M!8* zJhDYAtwG1A?7hF_JF`fcD^$w47ytBd3f1d~;WzdP7O?0$nrr!LQ;>_l$6dR)H2f7e k=q|PBzwwOwmki=s(2~bKk(?H^H2#BqU;FK;+7)*GU%jj1$p8QV diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/PORTAL.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/PORTAL.png index 19957ac6c8e08eddbc6ff259827551db051f364e..2aa7a82f2033168c88525edf69a806266970e105 100644 GIT binary patch literal 3547 zcmds4c~p~E7XQKyMW6&lK!J*Y$`VmPDM(NdL@+_DP+1}(AhK_TAV~;IK^8#)L6#Cm zL{N}@ktL8Spdlbd5X2_3qai4E2le zNWv|aaRg*t6B`uZPjE}D7BP8Jc6@7yv`yvw%ko%qJ7YzOw zu0ns2x;Zv^>L1Bzhj>Dz2-E_G)*?6(q*Dp3I{u#G85q%i^vqs_N5!2?-tE|=C0@(5 zvN98vL8W20bd&;oQBUy42qzj~RyNnd!z(0YV#Us^)D{cf8`xR7B5^78z%j=CSKM#< zxiK(^1WAe^W#?y#XsJAoKIFA{xAa3${F0y`L?Tc>t=C`rwX>2A9WGxb-KWQicQ?Ox zr41)zSaAnBotVlyS)!_rb*tW#w zt2HNS11{G>Y6C*F?5vKlJZJ9eR~bs(A|J=O^-9W(z3w$nzVK#3!G<;K1CvOtf)}3VES!!q@t1ks8y{>WCK!bLDKMw=XQXLW?pcZoSzySc$dYn+$GMgOJ@qS?ufaA&Qm*Kf*I5v#^3WonZ3LZ1c2_jO4HSUe9_s~H z@_+&c&TnfWshc?F_r_c`nQP_L$n(~6OQL1#*1uX8D!h);A1-_mT1{o+l6^T=~ zET2FoLftxS4vW0E!G|;qLhnXSPnpW6UyRVX<*jW_e&1kR8_v))lINVG#I;_C(!BiR z+|3j7&uv*hJffaPch^=NOt=HV+18Q*Iy~9z^Ll0(Ht5Rg@Z0t>_NmZhUPocWYA}Tz zDdUR`sbqt&%I?Azs>8KD#onJ(q#8_~>$3C5=NOku9_a!iy^8b~#xCT0`%XW9Bncfj!Fa@@HWxRAYoj>q3IUqM^b3+OmS?D-Qmmxw%xT=v?6Ps>;F>@(ygmTV*vh96;e4X-=e0|;=zaz_Pc zeMD6MGvyq^Nz{q&1%V# zq^Zts5uZ)Aua@j}ivwoutqP5!+B{1})f<13Kk3@YKUyfN-xFWWs(PzAMPM zWN#53m<{%8!k@640|G#gvZnsSPs4SNleR2r2-1P~nZd8)L8IUoa}}K$JSe`0^QncQ zc`aCNI#DfE1(@)6>WJ->{O{@NHcPmiT3FrgHA8+RKy_>IlXr?t{H?V#9IyLJK2_8)avWVHbQzCmTh=J?SW6`fKF!ack^`887c#<#ELi?^ z>d3R9LoPg1O13g8sqTFUYHYXv1h3cZCUxzeH0dGxNHAr;|8RH?Q>%yuL54o^+eYno zrd$eW8xot)=JVf#9DZgs+f^s>G4HHQZq)6CRB-H+ zNWlT#!OlxQi0wT`8k#6%WEN~8SDm3GIOHbMQ|uq8sp0&~65WHDuF+>=uRETR5Fe%V z()-CkhSq*sUBS@ZlpGZ8GPh`Usu0q+JFD;fyU*QI4hE2m^)aO&7=jI@jC~7yf;8p4 z>CK$n0QZlDvJxhphi5%&GHv^Yxnrn$b6&{p^&_W9W=#IQY5j z7&J>gw4^M5_9}(K3}A-@n7XGTRco41yHyB)A7#OleQV2dKVUq)OQ X=T#&v<_A(DpQo+QA}lJ;xW)b*e3XP~ literal 3204 zcmds3X=EgWpMGLp$@`{f#@nHyFk6{Zs{7HDBLlHpb^7$nfNI5jCYnbxhO zGD|J73~&p@EL$|U6jX2v%@UPdNlciR?x*`oacSdbDr&gp5>hX$&X+* zbMZ_70L->-*-QceI3E0dZGr$-Yc#D5j6H~mA#6!(Ng3SQnAo+DA00GJS z|7q5=GKgE6N@9B%g6Q+%U_9o1lM3x*DWj+J*`|b+`&mXz0n-kSI$2MNfAuZ!->;C^ zJm<LEKLoYHIOwy{9Ub^L2UE0Nf`J}cPtv9BA;mz3ArzqB8t zkEs}6zPa~G8_j@l)shwEqCMWLD&u9-TBhbIwv{}c;bwP>p`n!=P#48nRrOF4E1sfb z2zxy8;0tndZ2QqKTG(pjoIf(f81u0{H+3n(Y9E^kio$r`G> z8VH4*&JpRE9+nY+)I`=_oKt@nH+p)9tw@s$TgdZXimF=f@Y&@yGIOsElI?|UXk6}) zuPGMqk_Od)S!3e7P8Hc7lEQ|soio0)s)q}D!k^JFjJuG7Yfnb{6vW`DTgD!a62qUW zpj8JECa70DcORz!4F-Le@<5dgA=x&E8wI6E5V8Lx15+;FoDMvuF4SL=bHp85-Z;hJ zl5Yr;Xsp1!$o+;^W~Y}da=P=WzTvOo{~M|x;Amd&&_-oW>d4g4TI21{KblwRcjilR zDbRUK#$?RyT97qwoFANH0HjB@En@0V6RF1JIQie%_F`B7wWMv6qZ+b0Y58r7{MZl8 zPxLhsy$-DNF1KqCC@Md-U}1!f1nd}N-T)M|^*q`X9>Oh8U0%ACt7 z=7Fg9%;AD(fZ;$WE+yxaj!1jzmGJ&Y^$4rlRaBFKo3vGAMn=a*53Y8gg+;4%JogN7 z#9XQqP25aW*H^&;D^V#B8;|aT8bjoXgu(NRqpJ&3qeFw}s}Y zGosZKX?Cp1yBG7T(@4J7W=;VCwO<94dmi~gZOu%SX5Rwp54Pdsve<`tJ1x;so;dt3 zdDD;FmN~?uXMN~k#JP5+E0~gjwu!DVidxYyPVzvu3=KFN&zj-z>wmPzCw5q(>wN%dR6!{sQzY}^Xu!br4+`VJ z{YQKv71ZQ{9=v_=a4065⋙gPQ0J4n%8wSAaN!bH~lJPPT1gw+j;Vf5t7-V)$P@k z>J!hm2X@N)22AbXdJn?GZvZS|0;Us}e-Cs!bF zLJOHE5JdL7NZAtMO-bt9E()kPqPiwo_URJAbE8;vgBF371rD1iiq)mOuJyo|a<{h4 z;qFoq91Gjq57e2Mi(@{pDlhtbRw~u>UZ*JPZ&^A~Zvsm^s+W@lnQvez9|dACrYN&? zDe8T;CHfYV^S2fwHF2hn-4n>ppKTJ5&V`tOSC8_p>NVRL#a3 zQ84;-->KB@B2ex{a)5P4G^Fz7y)K7U|xqxNqot36p$|H>K-+50IE}F9eW+@ zZ<}n!lB4oSZ&bta?nmzgeP-1)1Z~qTtB@kVl&mPwK28*Ww$dTG6sGvAqPTnA z*|p(=4_^e*+Dev8=ZfNnB@?9DJ+)3yQ*v8D)}qC{mtvwdUp#@9oUzp*ZXxYX1vjSo z4P++^MAilw1n4u$v};LzfY|kT*x>1plGxH)A1c4Y5AVjD}A0Mh*|S{C#( z29Evub7*d_x=G*1y8rA_jx;!2va_SmWt>@kd@Qqf%IoN)$Gc=N+rG99WHF~lzwi1) zdqFrifDp8-KzNc)5z~AfU7R-@WD!ovWM$p2rcI+P(xs1%xSwIRYM&%fBa=dt2`SvFuWD0>8w@qCtT~@Kr64GRMLz2RUNgB_+LSfXdV`|68WdB z)@>}iXxBS8_%?-op6e-M*Fvi^KS)=S6-oxhzOJammfqg6qgNT-`lj)Cbi#!)$j78b z*d-Ba-qxaO8S{(2EHby84trZ%uwlii$k>?c4-&467hD*NI*-P$0ei)ZrtMq22Hh$A z5ARny+%08_O{Im7Q&e&_+c9&&mK8wo%9$sU;SBx5b2DO70+!J=Ey5|u* zy;a#P@UgJ(XdXx3k>q~4f(^MEf-w2*UWnhv_1&eya|t0nkgfNIyyJY_M9M6O;F9(pD}{CGFw0;yg1Cp^r3-G!@|# z*JV=|lo+gVAYJD9b7V0v1X{TsHYmJ@n5B{5sr879(Hv?er(3^VbUG(Tr^{J`NT8W* zlP64Y{!gUBGQlrLO&9%_(;i3;yPoI?Se{9A}gO|O& z7XGHOL>r;~__*O_ZG2O>Js-31I&fwmQGQPBzKQ)wLf7!s*_5J@CSG+sqTQ~6k7Z!WSPU^BMOBn<&O48N60=onE uSStBJgB2)Y{&u;;p9=mPo&P^94QEncx*Pxfm3R;bVC#>5n*|%Gzx)A@H2b~) diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/PUBLICDATAROOT.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/PUBLICDATAROOT.png index 21a2fe9b538cddad6368aad8f8e2b00136822605..44ddaf86bc26a92d81bee504b3b19bcc2f9acab6 100644 GIT binary patch literal 4473 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 QKgX~p23IfPeszxd8|o>S2LJ#7 literal 4165 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 diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/REFUNDEE.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/REFUNDEE.png index f4f89b595f6f6acb05259aa4f85115963d6ed6d5..70ccb4c1f5a91a886e62f0c399de9e395d585873 100644 GIT binary patch literal 3553 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 KJ?Yzk8-D{HsCw=I literal 3210 zcmdT`dsI^C7C#^w_7Zzcnv>DEMk|%Eth5ZJ8Iw%YQ74;F(US5(_#(qF1=GozOzT=G zBSOW1uh2pe82CU^V@sv{X2V~ zZ(sV}3%g?J`lSE>tZ+Zz>I(oc47hKC8-S~Y5!Mp`mixH7?)xEurR-N^a_@g(@O-jR zrn}ZFZ}c1`grgb)Ycx1tcV02Da$Cd9Z?`&dPmDlQOb87f1R_8$F~lswTNn}qOac@E z0&*_|4g!J=z(9a|15gmstN;iI4_4E`6&U(km@QDN0q-rmdF?!&xE2P6k7$vLRr18> zQPqQ@fj5mfeJ~X|oG**7psn*VUCaza;9ZyXxFwu&udy%ZEo$_KXe!7-K^f|RT->o7 zq!-qvWG2)T`51#%7g2MRAzz}c_qs*#1`igs znS+S5`fFu*Mi}Q-7lVf3>7QbECm##U3^qBU9(G9j_!a)pD8`_GX3i^_C^-Lp+jPf5 zL=D9g(c`~>--8M{-EQ44iw_hV?cV)z6EgzqFlXl&x0yGOFILDJ)4c3_Y=tu|5Lb0X zcg}cSE#eiIy9Bee^jvnQ?*fW9@2_b(*q_ewOi3X`3TR2eE4m@bQ~@<=^Nts$GyD9B zO7So-`JyS605V(*(T|TSm)(31F%}$3nMrKKC=-%7cZ)>v|vqk{H@8I}5BYr)|0^a?XJ+)ZnF*kgh>*~638*L1^ z)1~$@=c%wUovaMhaG(i}K-Ty+N8Z1yb^(Bp<^O7NzYux{pX=1cFZa}i5x{=WcnC+( zY4@|1fF=L+r(U<$x4c$0G)p`p$#Q;on=(@~!U{OqdSjlg+*Zk}u9{ktYhBq>t+mf8 z=psQ0(Lp2dx+9-U7~JaQYWyAw6T@>wFu)$WBukVb?VLR?b@|(1uJAJW ze8DpX^whWablUb+9?{sT*V}edzRCB=^rMUWH*5_bhD;oT9S8|68)IwXL`}!CXW%^pari3q%eY31Q#qp)&hN3nTblR1OJIPB zhL}}9IzjNp$a}1(nhU1bfro86QFGBS=CW|MbFv!U%hZ0juDCM^xPJJdw-AgVeT$tt zD?U_El9PDcHQnpmsIYTdN(OA~R+QcwN|rB|pBle}H#gZRbUK7Z`X z!x(yO1ekOv3|{Y11%)GWz_%aC9r9wCuT{_CeV+(cz%fQPN|HWoj6{L{k~~wu68;Z| zPSp9?;cbLhd~G%p?4+yd#z>HgNpPdjC(N6iz2VzIYxC7X=%>oFl6OM?cPH80)M*Hy z2LGyyR|jrmzt-QBjk3bP1f+@ZT3NS9pm{0&5}?^bVI~cf#^|Ee(+1q@tLce1eEnOO zdFT{DE9tuJ(6mEjt4`~(9iAe2v4JGZ7=?k=keId2d*ud$N*K~cTHO|-ZXzj*8(Xuo zx6ry%jK?2t9(glz&;qf~JK)T(Wo>4^WUQ)mbO0>u^e-H>wYqEXeVP)T72Amm?wy(2 zb#ON%oP08vr>kf%T1$`d9AvQz~?TI{*FoS-WnZ+OzH=ui6$huQ2<|cY})r%_l7w_20 zdKpSXN5-sM*eO+pMw%GqNTxyeK3ZeqFHBoQrg7NQ)CXDqM2Z__zokgfN>go^Dl7I5 zplDPLtH3Xn^W#HF z_uAMIsIcqrAIBw*)1K_gQKt?sb-XQlmLHkVj->>2iEApFtHPws(l`(K8o5Ep4mWyC zb=No90qQEF)x6>BA>}CNy;nm)+d~V!Eho&7SJ9tYbeQs_H>wC4V+;I{f(YO-vs1N~wqF!Bp7PsKL05XD{)%?ni>jYn&z07i$7A~?#eUVD*C>4u zEbGOn^9!%6=W4X6f5vY#Ix7P>=KrMgvP0mCv$I>5X~e_!E}>@8r~<49G&=4?UU}t& zHNQ8r%^Cl$u-9k6>1rO3wx3A;E|I;d?t_%eXl}=S(LipLj0oa4jKMiUE$rDkVV|@d zt6gGOP=Ky3&!6ZS4UpDyNpsgUjt{huIBQ{7M`*{vEp$zM`U$DN&F%Z?jfJ|8u3q^>3aB*D923s32jO$v{C!8_zn(Ev Yv=SCKaytL`u0=82_j|dPej9TBpVImNV*mgE diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/RETURN.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/RETURN.png index c81b8566e8f927b40d33e18281191d2d887c9761..e1bf7d6a19d527b8831e47e82329dfd6deeb7755 100644 GIT binary patch literal 4341 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 D(N$&@ literal 3895 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 G`26pWEt`t~ diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/REVERT.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/REVERT.png index f8de1fe51b4b54c4c67518bbedeec483f39647eb..67c12bd2d06e75353f09906558ebdc098920661e 100644 GIT binary patch literal 4341 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 Q6I;ZZ8Ce>ZU37{58()AmJ^%m! literal 3886 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 D+at77 diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/SENDL2TOL1MSG.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/SENDL2TOL1MSG.png index 0e0e529f3ab4204f068c073fcd7ef869534b224f..04611cd6a436c4c044f521bd731a3124d0c9307b 100644 GIT binary patch literal 3591 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 diff --git a/yellow-paper/docs/public-vm/gen/images/bit-formats/SET.png b/yellow-paper/docs/public-vm/gen/images/bit-formats/SET.png index 90b07c3bcbe61fdb866b5f8e5dc33ebb19a94648..9d68daa851d09c79f0d3765307cf1723a72e1ce4 100644 GIT binary patch literal 6614 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