From b3af1463ed6b7858252ab4779f8c747a6de47363 Mon Sep 17 00:00:00 2001 From: Jean M <132435771+jeanmon@users.noreply.github.com> Date: Tue, 28 Nov 2023 21:53:32 +0100 Subject: [PATCH] feat(AVM): First version for mini AVM (ADD, RETURN, CALLDATACOPY) (#3439) First version of a mini AVM. Resolves #3376 Resolves #3378 Resolves #3379 Resolves #3380 Resolves #3320 Resolves #3321 --------- Co-authored-by: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> --- barretenberg/cpp/pil/avm/avm_mini.pil | 97 ++++ barretenberg/cpp/pil/avm/avm_mini_opt.pil | 37 ++ barretenberg/cpp/pil/fib/fibonacci.pil | 18 + barretenberg/cpp/pil/fib/fibonacci_opt.pil | 8 + barretenberg/cpp/src/CMakeLists.txt | 1 + .../flavor/generated/AvmMini_flavor.hpp | 486 ++++++++++++++++++ .../flavor/generated/Fib_flavor.hpp | 322 ++++++++++++ .../circuit_builder/AvmMini_helper.cpp | 59 +++ .../circuit_builder/AvmMini_helper.hpp | 17 + .../circuit_builder/AvmMini_trace.cpp | 444 ++++++++++++++++ .../circuit_builder/AvmMini_trace.hpp | 76 +++ .../generated/AvmMini_circuit_builder.hpp | 119 +++++ .../generated/Fib_circuit_builder.hpp | 99 ++++ .../circuit_builder/generated/Fib_trace.cpp | 62 +++ .../circuit_builder/generated/Fib_trace.hpp | 22 + .../relations/generated/AvmMini.hpp | 185 +++++++ .../barretenberg/relations/generated/Fib.hpp | 64 +++ .../cpp/src/barretenberg/vm/CMakeLists.txt | 1 + .../vm/generated/AvmMini_composer.cpp | 105 ++++ .../vm/generated/AvmMini_composer.hpp | 69 +++ .../vm/generated/AvmMini_composer.test.cpp | 60 +++ .../vm/generated/AvmMini_prover.cpp | 159 ++++++ .../vm/generated/AvmMini_prover.hpp | 62 +++ .../vm/generated/AvmMini_verifier.cpp | 114 ++++ .../vm/generated/AvmMini_verifier.hpp | 32 ++ .../vm/generated/Fib_composer.cpp | 85 +++ .../vm/generated/Fib_composer.hpp | 69 +++ .../vm/generated/Fib_composer.test.cpp | 55 ++ .../barretenberg/vm/generated/Fib_prover.cpp | 136 +++++ .../barretenberg/vm/generated/Fib_prover.hpp | 62 +++ .../vm/generated/Fib_verifier.cpp | 88 ++++ .../vm/generated/Fib_verifier.hpp | 32 ++ 32 files changed, 3245 insertions(+) create mode 100644 barretenberg/cpp/pil/avm/avm_mini.pil create mode 100644 barretenberg/cpp/pil/avm/avm_mini_opt.pil create mode 100644 barretenberg/cpp/pil/fib/fibonacci.pil create mode 100644 barretenberg/cpp/pil/fib/fibonacci_opt.pil create mode 100644 barretenberg/cpp/src/barretenberg/flavor/generated/AvmMini_flavor.hpp create mode 100644 barretenberg/cpp/src/barretenberg/flavor/generated/Fib_flavor.hpp create mode 100644 barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/AvmMini_helper.cpp create mode 100644 barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/AvmMini_helper.hpp create mode 100644 barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/AvmMini_trace.cpp create mode 100644 barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/AvmMini_trace.hpp create mode 100644 barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/generated/AvmMini_circuit_builder.hpp create mode 100644 barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/generated/Fib_circuit_builder.hpp create mode 100644 barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/generated/Fib_trace.cpp create mode 100644 barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/generated/Fib_trace.hpp create mode 100644 barretenberg/cpp/src/barretenberg/relations/generated/AvmMini.hpp create mode 100644 barretenberg/cpp/src/barretenberg/relations/generated/Fib.hpp create mode 100644 barretenberg/cpp/src/barretenberg/vm/CMakeLists.txt create mode 100644 barretenberg/cpp/src/barretenberg/vm/generated/AvmMini_composer.cpp create mode 100644 barretenberg/cpp/src/barretenberg/vm/generated/AvmMini_composer.hpp create mode 100644 barretenberg/cpp/src/barretenberg/vm/generated/AvmMini_composer.test.cpp create mode 100644 barretenberg/cpp/src/barretenberg/vm/generated/AvmMini_prover.cpp create mode 100644 barretenberg/cpp/src/barretenberg/vm/generated/AvmMini_prover.hpp create mode 100644 barretenberg/cpp/src/barretenberg/vm/generated/AvmMini_verifier.cpp create mode 100644 barretenberg/cpp/src/barretenberg/vm/generated/AvmMini_verifier.hpp create mode 100644 barretenberg/cpp/src/barretenberg/vm/generated/Fib_composer.cpp create mode 100644 barretenberg/cpp/src/barretenberg/vm/generated/Fib_composer.hpp create mode 100644 barretenberg/cpp/src/barretenberg/vm/generated/Fib_composer.test.cpp create mode 100644 barretenberg/cpp/src/barretenberg/vm/generated/Fib_prover.cpp create mode 100644 barretenberg/cpp/src/barretenberg/vm/generated/Fib_prover.hpp create mode 100644 barretenberg/cpp/src/barretenberg/vm/generated/Fib_verifier.cpp create mode 100644 barretenberg/cpp/src/barretenberg/vm/generated/Fib_verifier.hpp diff --git a/barretenberg/cpp/pil/avm/avm_mini.pil b/barretenberg/cpp/pil/avm/avm_mini.pil new file mode 100644 index 00000000000..80103c91057 --- /dev/null +++ b/barretenberg/cpp/pil/avm/avm_mini.pil @@ -0,0 +1,97 @@ +constant %N = 256; + +namespace avmMini(%N); + + //===== CONSTANT POLYNOMIALS ================================================== + pol constant clk(i) { i }; + pol constant first = [1] + [0]*; // Used mostly to toggle off the first row consisting + // only in first element of shifted polynomials. + + //===== TABLE SUBOP-TR ======================================================== + // Enum over sub operations + // 0: VOID + // 1: ADD + pol commit subop; + + // Intermediate register values + pol commit ia; + pol commit ib; + pol commit ic; + + // Memory operation per intermediate register + pol commit mem_op_a; + pol commit mem_op_b; + pol commit mem_op_c; + + // Read-write flag per intermediate register: Read = 0, Write = 1 + pol commit rwa; + pol commit rwb; + pol commit rwc; + + // Memory index involved into a memory operation per pertaining intermediate register + // We should range constrain it to 32 bits ultimately. For first mini-AVM, + // we will assume that these columns are of the right type. + pol commit mem_idx_a; + pol commit mem_idx_b; + pol commit mem_idx_c; + + + // Track the last line of the execution trace. It does NOT correspond to the last row of the whole table + // of size N. As this depends on the supplied bytecode, this polynomial cannot be constant. + pol commit last; + + // Relations on type constraints + subop * (1 - subop) = 0; + mem_op_a * (1 - mem_op_a) = 0; + mem_op_b * (1 - mem_op_b) = 0; + mem_op_c * (1 - mem_op_c) = 0; + rwa * (1 - rwa) = 0; + rwb * (1 - rwb) = 0; + rwc * (1 - rwc) = 0; + + // Relation for addition over the finite field + subop * (ia + ib - ic) = 0; + + // ========= Table MEM-TR ================= + pol commit m_clk; + pol commit m_sub_clk; + pol commit m_addr; + pol commit m_val; + pol commit m_lastAccess; // Boolean (1 when this row is the last of a given address) + pol commit m_rw; // Enum: 0 (read), 1 (write) + + // Type constraints + m_lastAccess * (1 - m_lastAccess) = 0; + m_rw * (1 - m_rw) = 0; + + // m_lastAccess == 0 ==> m_addr' == m_addr + (1 - first) * (1 - m_lastAccess) * (m_addr' - m_addr) = 0; + + // We need: m_lastAccess == 1 ==> m_addr' > m_addr + // The above implies: m_addr' == m_addr ==> m_lastAccess == 0 + // This condition does not apply on the last row. + // clk + 1 used as an expression for positive integers + // TODO: Uncomment when lookups are supported + // (1 - first) * (1 - last) * m_lastAccess { (m_addr' - m_addr) } in clk + 1; // Gated inclusion check. Is it supported? + + // TODO: following constraint + // m_addr' == m_addr && m_clk == m_clk' ==> m_sub_clk' - m_sub_clk > 0 + // Can be enforced with (1 - first) * (1 - last) * (1 - m_lastAccess) { 6 * (m_clk' - m_clk) + m_sub_clk' - m_sub_clk } in clk + 1 + + // Alternatively to the above, one could require + // that m_addr' - m_addr is 0 or 1 (needs to add placeholders m_addr values): + // (m_addr' - m_addr) * (m_addr' - m_addr) - (m_addr' - m_addr) = 0; + // if m_addr' - m_addr is 0 or 1, the following is equiv. to m_lastAccess + // (m_addr' - m_addr) + + // m_lastAccess == 0 && m_rw' == 0 ==> m_val == m_val' + // This condition does not apply on the last row. + // Note: in barretenberg, a shifted polynomial will be 0 on the last row (shift is not cyclic) + // Note2: in barretenberg, if a poynomial is shifted, its non-shifted equivalent must be 0 on the first row + + (1 - first) * (1 - last) * (1 - m_lastAccess) * (1 - m_rw') * (m_val' - m_val) = 0; + + // TODO: Constraint the first load from a given adress has value 0. (Consistency of memory initialization.) + // TODO: when introducing load/store as sub-operations, we will have to add consistency of intermediate + // register values ia, ib, ic + \ No newline at end of file diff --git a/barretenberg/cpp/pil/avm/avm_mini_opt.pil b/barretenberg/cpp/pil/avm/avm_mini_opt.pil new file mode 100644 index 00000000000..82a456a38ca --- /dev/null +++ b/barretenberg/cpp/pil/avm/avm_mini_opt.pil @@ -0,0 +1,37 @@ +constant %N = 256; +namespace avmMini(256); + col fixed clk(i) { i }; + col fixed positive(i) { (i + 1) }; + col fixed first = [1] + [0]*; + col witness subop; + col witness ia; + col witness ib; + col witness ic; + col witness mem_op_a; + col witness mem_op_b; + col witness mem_op_c; + col witness rwa; + col witness rwb; + col witness rwc; + col witness mem_idx_a; + col witness mem_idx_b; + col witness mem_idx_c; + col witness last; + (avmMini.subop * (1 - avmMini.subop)) = 0; + (avmMini.mem_op_a * (1 - avmMini.mem_op_a)) = 0; + (avmMini.mem_op_b * (1 - avmMini.mem_op_b)) = 0; + (avmMini.mem_op_c * (1 - avmMini.mem_op_c)) = 0; + (avmMini.rwa * (1 - avmMini.rwa)) = 0; + (avmMini.rwb * (1 - avmMini.rwb)) = 0; + (avmMini.rwc * (1 - avmMini.rwc)) = 0; + (avmMini.subop * ((avmMini.ia + avmMini.ib) - avmMini.ic)) = 0; + col witness m_clk; + col witness m_sub_clk; + col witness m_addr; + col witness m_val; + col witness m_lastAccess; + col witness m_rw; + (avmMini.m_lastAccess * (1 - avmMini.m_lastAccess)) = 0; + (avmMini.m_rw * (1 - avmMini.m_rw)) = 0; + (((1 - avmMini.first) * (1 - avmMini.m_lastAccess)) * (avmMini.m_addr' - avmMini.m_addr)) = 0; + (((((1 - avmMini.first) * (1 - avmMini.last)) * (1 - avmMini.m_lastAccess)) * (1 - avmMini.m_rw')) * (avmMini.m_val' - avmMini.m_val)) = 0; diff --git a/barretenberg/cpp/pil/fib/fibonacci.pil b/barretenberg/cpp/pil/fib/fibonacci.pil new file mode 100644 index 00000000000..993a675e7d2 --- /dev/null +++ b/barretenberg/cpp/pil/fib/fibonacci.pil @@ -0,0 +1,18 @@ +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 new file mode 100644 index 00000000000..2c36cd15327 --- /dev/null +++ b/barretenberg/cpp/pil/fib/fibonacci_opt.pil @@ -0,0 +1,8 @@ +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/CMakeLists.txt b/barretenberg/cpp/src/CMakeLists.txt index b74bc2f99b5..b09a2181ebc 100644 --- a/barretenberg/cpp/src/CMakeLists.txt +++ b/barretenberg/cpp/src/CMakeLists.txt @@ -76,6 +76,7 @@ add_subdirectory(barretenberg/sumcheck) add_subdirectory(barretenberg/transcript) add_subdirectory(barretenberg/translator_vm) add_subdirectory(barretenberg/ultra_honk) +add_subdirectory(barretenberg/vm) add_subdirectory(barretenberg/wasi) diff --git a/barretenberg/cpp/src/barretenberg/flavor/generated/AvmMini_flavor.hpp b/barretenberg/cpp/src/barretenberg/flavor/generated/AvmMini_flavor.hpp new file mode 100644 index 00000000000..9e0c6c9bc34 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/flavor/generated/AvmMini_flavor.hpp @@ -0,0 +1,486 @@ + + +#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/polynomials/evaluation_domain.hpp" +#include "barretenberg/polynomials/polynomial.hpp" +#include "barretenberg/relations/generated/AvmMini.hpp" +#include "barretenberg/transcript/transcript.hpp" + +namespace proof_system::honk { +namespace flavor { + +class AvmMiniFlavor { + 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 = 3; + static constexpr size_t NUM_WITNESS_ENTITIES = 20; + 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 = 26; + + 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 PrecomputedEntities_ { + public: + DataType avmMini_clk; + DataType avmMini_positive; + DataType avmMini_first; + + DEFINE_POINTER_VIEW(NUM_PRECOMPUTED_ENTITIES, &avmMini_clk, &avmMini_positive, &avmMini_first) + + std::vector get_selectors() override + { + return { + avmMini_clk, + avmMini_positive, + avmMini_first, + }; + }; + + std::vector get_sigma_polynomials() override { return {}; }; + std::vector get_id_polynomials() override { return {}; }; + std::vector get_table_polynomials() { return {}; }; + }; + + template + class WitnessEntities : public WitnessEntities_ { + public: + DataType avmMini_subop; + DataType avmMini_ia; + DataType avmMini_ib; + DataType avmMini_ic; + DataType avmMini_mem_op_a; + DataType avmMini_mem_op_b; + DataType avmMini_mem_op_c; + DataType avmMini_rwa; + DataType avmMini_rwb; + DataType avmMini_rwc; + DataType avmMini_mem_idx_a; + DataType avmMini_mem_idx_b; + DataType avmMini_mem_idx_c; + DataType avmMini_last; + DataType avmMini_m_clk; + DataType avmMini_m_sub_clk; + DataType avmMini_m_addr; + DataType avmMini_m_val; + DataType avmMini_m_lastAccess; + DataType avmMini_m_rw; + + DEFINE_POINTER_VIEW(NUM_WITNESS_ENTITIES, + &avmMini_subop, + &avmMini_ia, + &avmMini_ib, + &avmMini_ic, + &avmMini_mem_op_a, + &avmMini_mem_op_b, + &avmMini_mem_op_c, + &avmMini_rwa, + &avmMini_rwb, + &avmMini_rwc, + &avmMini_mem_idx_a, + &avmMini_mem_idx_b, + &avmMini_mem_idx_c, + &avmMini_last, + &avmMini_m_clk, + &avmMini_m_sub_clk, + &avmMini_m_addr, + &avmMini_m_val, + &avmMini_m_lastAccess, + &avmMini_m_rw) + + std::vector get_wires() override + { + return { + avmMini_subop, avmMini_ia, avmMini_ib, avmMini_ic, avmMini_mem_op_a, + avmMini_mem_op_b, avmMini_mem_op_c, avmMini_rwa, avmMini_rwb, avmMini_rwc, + avmMini_mem_idx_a, avmMini_mem_idx_b, avmMini_mem_idx_c, avmMini_last, avmMini_m_clk, + avmMini_m_sub_clk, avmMini_m_addr, avmMini_m_val, avmMini_m_lastAccess, avmMini_m_rw, + + }; + }; + + std::vector get_sorted_polynomials() { return {}; }; + }; + + template + class AllEntities : public AllEntities_ { + public: + DataType avmMini_clk; + DataType avmMini_positive; + DataType avmMini_first; + + DataType avmMini_subop; + DataType avmMini_ia; + DataType avmMini_ib; + DataType avmMini_ic; + DataType avmMini_mem_op_a; + DataType avmMini_mem_op_b; + DataType avmMini_mem_op_c; + DataType avmMini_rwa; + DataType avmMini_rwb; + DataType avmMini_rwc; + DataType avmMini_mem_idx_a; + DataType avmMini_mem_idx_b; + DataType avmMini_mem_idx_c; + DataType avmMini_last; + DataType avmMini_m_clk; + DataType avmMini_m_sub_clk; + DataType avmMini_m_addr; + DataType avmMini_m_val; + DataType avmMini_m_lastAccess; + DataType avmMini_m_rw; + + DataType avmMini_m_val_shift; + DataType avmMini_m_addr_shift; + DataType avmMini_m_rw_shift; + + DEFINE_POINTER_VIEW(NUM_ALL_ENTITIES, + &avmMini_clk, + &avmMini_positive, + &avmMini_first, + &avmMini_subop, + &avmMini_ia, + &avmMini_ib, + &avmMini_ic, + &avmMini_mem_op_a, + &avmMini_mem_op_b, + &avmMini_mem_op_c, + &avmMini_rwa, + &avmMini_rwb, + &avmMini_rwc, + &avmMini_mem_idx_a, + &avmMini_mem_idx_b, + &avmMini_mem_idx_c, + &avmMini_last, + &avmMini_m_clk, + &avmMini_m_sub_clk, + &avmMini_m_addr, + &avmMini_m_val, + &avmMini_m_lastAccess, + &avmMini_m_rw, + &avmMini_m_val_shift, + &avmMini_m_addr_shift, + &avmMini_m_rw_shift) + + std::vector get_wires() override + { + return { + avmMini_clk, avmMini_positive, avmMini_first, avmMini_subop, avmMini_ia, + avmMini_ib, avmMini_ic, avmMini_mem_op_a, avmMini_mem_op_b, avmMini_mem_op_c, + avmMini_rwa, avmMini_rwb, avmMini_rwc, avmMini_mem_idx_a, avmMini_mem_idx_b, + avmMini_mem_idx_c, avmMini_last, avmMini_m_clk, avmMini_m_sub_clk, avmMini_m_addr, + avmMini_m_val, avmMini_m_lastAccess, avmMini_m_rw, avmMini_m_val_shift, avmMini_m_addr_shift, + avmMini_m_rw_shift, + + }; + }; + + std::vector get_unshifted() override + { + return { + avmMini_clk, avmMini_positive, avmMini_first, avmMini_subop, avmMini_ia, + avmMini_ib, avmMini_ic, avmMini_mem_op_a, avmMini_mem_op_b, avmMini_mem_op_c, + avmMini_rwa, avmMini_rwb, avmMini_rwc, avmMini_mem_idx_a, avmMini_mem_idx_b, + avmMini_mem_idx_c, avmMini_last, avmMini_m_clk, avmMini_m_sub_clk, avmMini_m_addr, + avmMini_m_val, avmMini_m_lastAccess, avmMini_m_rw, + + }; + }; + + std::vector get_to_be_shifted() override + { + return { + avmMini_m_val, + avmMini_m_addr, + avmMini_m_rw, + + }; + }; + + std::vector get_shifted() override + { + return { + avmMini_m_val_shift, + avmMini_m_addr_shift, + avmMini_m_rw_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, PolynomialHandle>; + + 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->avmMini_clk.size(); } + [[nodiscard]] AllValues get_row(const size_t row_idx) const + { + AllValues result; + for (auto [result_field, polynomial] : zip_view(result.pointer_view(), pointer_view())) { + *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 : pointer_view()) { + *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, barretenberg::Univariate>; + + /** + * @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::avmMini_clk = "avmMini_clk"; + Base::avmMini_positive = "avmMini_positive"; + Base::avmMini_first = "avmMini_first"; + Base::avmMini_subop = "avmMini_subop"; + Base::avmMini_ia = "avmMini_ia"; + Base::avmMini_ib = "avmMini_ib"; + Base::avmMini_ic = "avmMini_ic"; + Base::avmMini_mem_op_a = "avmMini_mem_op_a"; + Base::avmMini_mem_op_b = "avmMini_mem_op_b"; + Base::avmMini_mem_op_c = "avmMini_mem_op_c"; + Base::avmMini_rwa = "avmMini_rwa"; + Base::avmMini_rwb = "avmMini_rwb"; + Base::avmMini_rwc = "avmMini_rwc"; + Base::avmMini_mem_idx_a = "avmMini_mem_idx_a"; + Base::avmMini_mem_idx_b = "avmMini_mem_idx_b"; + Base::avmMini_mem_idx_c = "avmMini_mem_idx_c"; + Base::avmMini_last = "avmMini_last"; + Base::avmMini_m_clk = "avmMini_m_clk"; + Base::avmMini_m_sub_clk = "avmMini_m_sub_clk"; + Base::avmMini_m_addr = "avmMini_m_addr"; + Base::avmMini_m_val = "avmMini_m_val"; + Base::avmMini_m_lastAccess = "avmMini_m_lastAccess"; + Base::avmMini_m_rw = "avmMini_m_rw"; + }; + }; + + class VerifierCommitments : public AllEntities { + private: + using Base = AllEntities; + + public: + VerifierCommitments(const std::shared_ptr& verification_key, + const BaseTranscript& transcript) + { + static_cast(transcript); + avmMini_clk = verification_key->avmMini_clk; + avmMini_positive = verification_key->avmMini_positive; + avmMini_first = verification_key->avmMini_first; + } + }; + + class Transcript : public BaseTranscript { + public: + uint32_t circuit_size; + + Commitment avmMini_subop; + Commitment avmMini_ia; + Commitment avmMini_ib; + Commitment avmMini_ic; + Commitment avmMini_mem_op_a; + Commitment avmMini_mem_op_b; + Commitment avmMini_mem_op_c; + Commitment avmMini_rwa; + Commitment avmMini_rwb; + Commitment avmMini_rwc; + Commitment avmMini_mem_idx_a; + Commitment avmMini_mem_idx_b; + Commitment avmMini_mem_idx_c; + Commitment avmMini_last; + Commitment avmMini_m_clk; + Commitment avmMini_m_sub_clk; + Commitment avmMini_m_addr; + Commitment avmMini_m_val; + Commitment avmMini_m_lastAccess; + Commitment avmMini_m_rw; + + 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() override + { + 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); + + avmMini_subop = deserialize_from_buffer(BaseTranscript::proof_data, num_bytes_read); + avmMini_ia = deserialize_from_buffer(BaseTranscript::proof_data, num_bytes_read); + avmMini_ib = deserialize_from_buffer(BaseTranscript::proof_data, num_bytes_read); + avmMini_ic = deserialize_from_buffer(BaseTranscript::proof_data, num_bytes_read); + avmMini_mem_op_a = deserialize_from_buffer(BaseTranscript::proof_data, num_bytes_read); + avmMini_mem_op_b = deserialize_from_buffer(BaseTranscript::proof_data, num_bytes_read); + avmMini_mem_op_c = deserialize_from_buffer(BaseTranscript::proof_data, num_bytes_read); + avmMini_rwa = deserialize_from_buffer(BaseTranscript::proof_data, num_bytes_read); + avmMini_rwb = deserialize_from_buffer(BaseTranscript::proof_data, num_bytes_read); + avmMini_rwc = deserialize_from_buffer(BaseTranscript::proof_data, num_bytes_read); + avmMini_mem_idx_a = deserialize_from_buffer(BaseTranscript::proof_data, num_bytes_read); + avmMini_mem_idx_b = deserialize_from_buffer(BaseTranscript::proof_data, num_bytes_read); + avmMini_mem_idx_c = deserialize_from_buffer(BaseTranscript::proof_data, num_bytes_read); + avmMini_last = deserialize_from_buffer(BaseTranscript::proof_data, num_bytes_read); + avmMini_m_clk = deserialize_from_buffer(BaseTranscript::proof_data, num_bytes_read); + avmMini_m_sub_clk = deserialize_from_buffer(BaseTranscript::proof_data, num_bytes_read); + avmMini_m_addr = deserialize_from_buffer(BaseTranscript::proof_data, num_bytes_read); + avmMini_m_val = deserialize_from_buffer(BaseTranscript::proof_data, num_bytes_read); + avmMini_m_lastAccess = deserialize_from_buffer(BaseTranscript::proof_data, num_bytes_read); + avmMini_m_rw = 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() override + { + 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(avmMini_subop, BaseTranscript::proof_data); + serialize_to_buffer(avmMini_ia, BaseTranscript::proof_data); + serialize_to_buffer(avmMini_ib, BaseTranscript::proof_data); + serialize_to_buffer(avmMini_ic, BaseTranscript::proof_data); + serialize_to_buffer(avmMini_mem_op_a, BaseTranscript::proof_data); + serialize_to_buffer(avmMini_mem_op_b, BaseTranscript::proof_data); + serialize_to_buffer(avmMini_mem_op_c, BaseTranscript::proof_data); + serialize_to_buffer(avmMini_rwa, BaseTranscript::proof_data); + serialize_to_buffer(avmMini_rwb, BaseTranscript::proof_data); + serialize_to_buffer(avmMini_rwc, BaseTranscript::proof_data); + serialize_to_buffer(avmMini_mem_idx_a, BaseTranscript::proof_data); + serialize_to_buffer(avmMini_mem_idx_b, BaseTranscript::proof_data); + serialize_to_buffer(avmMini_mem_idx_c, BaseTranscript::proof_data); + serialize_to_buffer(avmMini_last, BaseTranscript::proof_data); + serialize_to_buffer(avmMini_m_clk, BaseTranscript::proof_data); + serialize_to_buffer(avmMini_m_sub_clk, BaseTranscript::proof_data); + serialize_to_buffer(avmMini_m_addr, BaseTranscript::proof_data); + serialize_to_buffer(avmMini_m_val, BaseTranscript::proof_data); + serialize_to_buffer(avmMini_m_lastAccess, BaseTranscript::proof_data); + serialize_to_buffer(avmMini_m_rw, 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/flavor/generated/Fib_flavor.hpp b/barretenberg/cpp/src/barretenberg/flavor/generated/Fib_flavor.hpp new file mode 100644 index 00000000000..281587d0f42 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/flavor/generated/Fib_flavor.hpp @@ -0,0 +1,322 @@ + + +#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/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 PrecomputedEntities_ { + public: + DataType Fibonacci_LAST; + DataType Fibonacci_FIRST; + + DEFINE_POINTER_VIEW(NUM_PRECOMPUTED_ENTITIES, &Fibonacci_LAST, &Fibonacci_FIRST) + + std::vector get_selectors() override + { + return { + Fibonacci_LAST, + Fibonacci_FIRST, + }; + }; + + std::vector get_sigma_polynomials() override { return {}; }; + std::vector get_id_polynomials() override { return {}; }; + std::vector get_table_polynomials() { return {}; }; + }; + + template + class WitnessEntities : public WitnessEntities_ { + public: + DataType Fibonacci_x; + DataType Fibonacci_y; + + DEFINE_POINTER_VIEW(NUM_WITNESS_ENTITIES, &Fibonacci_x, &Fibonacci_y) + + std::vector get_wires() override + { + return { + Fibonacci_x, + Fibonacci_y, + + }; + }; + + std::vector get_sorted_polynomials() { return {}; }; + }; + + template + class AllEntities : public AllEntities_ { + public: + DataType Fibonacci_LAST; + DataType Fibonacci_FIRST; + + DataType Fibonacci_x; + DataType Fibonacci_y; + + DataType Fibonacci_x_shift; + DataType Fibonacci_y_shift; + + DEFINE_POINTER_VIEW(NUM_ALL_ENTITIES, + &Fibonacci_LAST, + &Fibonacci_FIRST, + &Fibonacci_x, + &Fibonacci_y, + &Fibonacci_x_shift, + &Fibonacci_y_shift) + + std::vector get_wires() override + { + return { + Fibonacci_LAST, Fibonacci_FIRST, Fibonacci_x, Fibonacci_y, Fibonacci_x_shift, Fibonacci_y_shift, + + }; + }; + + std::vector get_unshifted() override + { + return { + Fibonacci_LAST, + Fibonacci_FIRST, + Fibonacci_x, + Fibonacci_y, + + }; + }; + + std::vector get_to_be_shifted() override + { + return { + Fibonacci_x, + Fibonacci_y, + + }; + }; + + std::vector get_shifted() override + { + 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, PolynomialHandle>; + + 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.pointer_view(), pointer_view())) { + *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 : pointer_view()) { + *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, barretenberg::Univariate>; + + /** + * @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, + const BaseTranscript& transcript) + { + static_cast(transcript); + 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() override + { + 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() override + { + 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/AvmMini_helper.cpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/AvmMini_helper.cpp new file mode 100644 index 00000000000..51f96447da9 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/AvmMini_helper.cpp @@ -0,0 +1,59 @@ +#include "barretenberg/ecc/curves/bn254/fr.hpp" +#include "barretenberg/proof_system/circuit_builder/circuit_builder_base.hpp" + +#include "barretenberg/flavor/generated/AvmMini_flavor.hpp" +#include "barretenberg/relations/generated/AvmMini.hpp" + +#include "./AvmMini_helper.hpp" + +namespace proof_system { + +/** + * @brief Routine to log some slice of a trace of the AVM. Used to debug or in some unit tests. + * + * @param trace The whole trace for AVM as a vector of rows. + * @param beg The index of the beginning of the slice. (included) + * @param end The index of the end of the slice (not included). + */ +void log_avmMini_trace(std::vector const& trace, size_t beg, size_t end) +{ + info("Built circuit with ", trace.size(), " trace"); + + for (size_t i = beg; i < end; i++) { + info("================================================================================"); + info("== ROW ", i); + info("================================================================================"); + + info("m_addr: ", trace.at(i).avmMini_m_addr); + info("m_clk: ", trace.at(i).avmMini_m_clk); + info("m_sub_clk: ", trace.at(i).avmMini_m_sub_clk); + info("m_val: ", trace.at(i).avmMini_m_val); + info("m_lastAccess: ", trace.at(i).avmMini_m_lastAccess); + info("m_rw: ", trace.at(i).avmMini_m_rw); + info("m_val_shift: ", trace.at(i).avmMini_m_val_shift); + info("first: ", trace.at(i).avmMini_first); + info("last: ", trace.at(i).avmMini_last); + + info("=======MEM_OP_A================================================================="); + info("clk: ", trace.at(i).avmMini_clk); + info("mem_op_a: ", trace.at(i).avmMini_mem_op_a); + info("mem_idx_a: ", trace.at(i).avmMini_mem_idx_a); + info("ia: ", trace.at(i).avmMini_ia); + info("rwa: ", trace.at(i).avmMini_rwa); + + info("=======MEM_OP_B================================================================="); + info("mem_op_b: ", trace.at(i).avmMini_mem_op_b); + info("mem_idx_b: ", trace.at(i).avmMini_mem_idx_b); + info("ib: ", trace.at(i).avmMini_ib); + info("rwb: ", trace.at(i).avmMini_rwb); + + info("=======MEM_OP_C================================================================="); + info("mem_op_c: ", trace.at(i).avmMini_mem_op_c); + info("mem_idx_c: ", trace.at(i).avmMini_mem_idx_c); + info("ic: ", trace.at(i).avmMini_ic); + info("rwc: ", trace.at(i).avmMini_rwc); + info("\n"); + } +} + +} // namespace proof_system \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/AvmMini_helper.hpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/AvmMini_helper.hpp new file mode 100644 index 00000000000..c84b65b1dc6 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/AvmMini_helper.hpp @@ -0,0 +1,17 @@ +#pragma once + +#include "barretenberg/ecc/curves/bn254/fr.hpp" +#include "barretenberg/proof_system/circuit_builder/circuit_builder_base.hpp" + +#include "barretenberg/flavor/generated/AvmMini_flavor.hpp" +#include "barretenberg/relations/generated/AvmMini.hpp" + +namespace proof_system { + +using Flavor = proof_system::honk::flavor::AvmMiniFlavor; +using FF = Flavor::FF; +using Row = proof_system::AvmMini_vm::Row; + +void log_avmMini_trace(std::vector const& trace, size_t beg, size_t end); + +} // namespace proof_system \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/AvmMini_trace.cpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/AvmMini_trace.cpp new file mode 100644 index 00000000000..8e44891850a --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/AvmMini_trace.cpp @@ -0,0 +1,444 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "./AvmMini_trace.hpp" + +#include "barretenberg/relations/generated/AvmMini.hpp" +namespace proof_system { + +/** + * @brief Constructor of a trace builder of AVM. Only serves to set the capacity of the + * underlying traces. + */ +AvmMiniTraceBuilder::AvmMiniTraceBuilder() +{ + mainTrace.reserve(N); + memTrace.reserve(N); +} + +/** + * @brief Resetting the internal state so that a new trace can be rebuilt using the same object. + * + */ +void AvmMiniTraceBuilder::reset() +{ + mainTrace.clear(); + memTrace.clear(); + ffMemory.fill(FF(0)); +} + +/** + * @brief A comparator on MemoryTraceEntry to be used by sorting algorithm. + * + */ +bool AvmMiniTraceBuilder::compareMemEntries(const MemoryTraceEntry& left, const MemoryTraceEntry& right) +{ + if (left.m_addr < right.m_addr) { + return true; + } + + if (left.m_addr > right.m_addr) { + return false; + } + + if (left.m_clk < right.m_clk) { + return true; + } + + if (left.m_clk > right.m_clk) { + return false; + } + + // No safeguard in case they are equal. The caller should ensure this property. + // Otherwise, relation will not be satisfied. + return left.m_sub_clk < right.m_sub_clk; +} + +/** + * @brief A method to insert a row/entry in the memory trace. + * + * @param m_clk Main clock + * @param m_sub_clk Sub-clock used to order load/store sub operations + * @param m_addr Address pertaining to the memory operation + * @param m_val Value (FF) pertaining to the memory operation + * @param m_rw Boolean telling whether it is a load (false) or store operation (true). + */ +void AvmMiniTraceBuilder::insertInMemTrace(uint32_t m_clk, uint32_t m_sub_clk, uint32_t m_addr, FF m_val, bool m_rw) +{ + memTrace.emplace_back(MemoryTraceEntry{ + .m_clk = m_clk, + .m_sub_clk = m_sub_clk, + .m_addr = m_addr, + .m_val = m_val, + .m_rw = m_rw, + }); +} + +// Memory operations need to be performed before the addition of the corresponding row in +// mainTrace, otherwise the m_clk value will be wrong. This applies to: +// loadAInMemTrace, loadBInMemTrace, loadCInMemTrace +// storeAInMemTrace, storeBInMemTrace, storeCInMemTrace + +/** + * @brief Add a memory trace entry corresponding to a memory load into the intermediate + * register Ia. + * + * @param addr The memory address + * @param val The value to be loaded + */ +void AvmMiniTraceBuilder::loadAInMemTrace(uint32_t addr, FF val) +{ + insertInMemTrace(static_cast(mainTrace.size()), SubClkLoadA, addr, val, false); +} + +/** + * @brief Add a memory trace entry corresponding to a memory load into the intermediate + * register Ib. + * + * @param addr The memory address + * @param val The value to be loaded + */ +void AvmMiniTraceBuilder::loadBInMemTrace(uint32_t addr, FF val) +{ + insertInMemTrace(static_cast(mainTrace.size()), SubClkLoadB, addr, val, false); +} + +/** + * @brief Add a memory trace entry corresponding to a memory load into the intermediate + * register Ic. + * + * @param addr The memory address + * @param val The value to be loaded + */ +void AvmMiniTraceBuilder::loadCInMemTrace(uint32_t addr, FF val) +{ + insertInMemTrace(static_cast(mainTrace.size()), SubClkLoadC, addr, val, false); +} + +/** + * @brief Add a memory trace entry corresponding to a memory store from the intermediate + * register Ia. + * + * @param addr The memory address + * @param val The value to be stored + */ +void AvmMiniTraceBuilder::storeAInMemTrace(uint32_t addr, FF val) +{ + insertInMemTrace(static_cast(mainTrace.size()), SubClkStoreA, addr, val, true); +} + +/** + * @brief Add a memory trace entry corresponding to a memory store from the intermediate + * register Ib. + * + * @param addr The memory address + * @param val The value to be stored + */ +void AvmMiniTraceBuilder::storeBInMemTrace(uint32_t addr, FF val) +{ + insertInMemTrace(static_cast(mainTrace.size()), SubClkStoreB, addr, val, true); +} + +/** + * @brief Add a memory trace entry corresponding to a memory store from the intermediate + * register Ic. + * + * @param addr The memory address + * @param val The value to be stored + */ +void AvmMiniTraceBuilder::storeCInMemTrace(uint32_t addr, FF val) +{ + insertInMemTrace(static_cast(mainTrace.size()), SubClkStoreC, addr, val, true); +} + +/** + * @brief Addition over finite field with direct memory access. + * + * @param s0 An index in ffMemory pointing to the first operand of the addition. + * @param s1 An index in ffMemory pointing to the second operand of the addition. + * @param d0 An index in ffMemory pointing to the output of the addition. + */ +void AvmMiniTraceBuilder::add(uint32_t s0, uint32_t s1, uint32_t d0) +{ + // a + b = c + FF a = ffMemory.at(s0); + FF b = ffMemory.at(s1); + FF c = a + b; + ffMemory.at(d0) = c; + + auto clk = mainTrace.size(); + + // Loading into Ia + loadAInMemTrace(s0, a); + + // Loading into Ib + loadBInMemTrace(s1, b); + + // Storing from Ic + storeCInMemTrace(d0, c); + + mainTrace.push_back(Row{ + .avmMini_clk = clk, + .avmMini_subop = FF(1), + .avmMini_ia = a, + .avmMini_ib = b, + .avmMini_ic = c, + .avmMini_mem_op_a = FF(1), + .avmMini_mem_op_b = FF(1), + .avmMini_mem_op_c = FF(1), + .avmMini_rwc = FF(1), + .avmMini_mem_idx_a = FF(s0), + .avmMini_mem_idx_b = FF(s1), + .avmMini_mem_idx_c = FF(d0), + }); +}; + +/** + * @brief CALLDATACOPY opcode with direct memory access, i.e., + * M_F[d0:d0+s1] = M_calldata[s0:s0+s1] + * Simplified version with exclusively memory store operations and + * values from M_calldata passed by an array and loaded into + * intermediate registers. + * Assume that caller passes callDataMem which is large enough so that + * no out-of-bound memory issues occur. + * TODO: Implement the indirect memory version (maybe not required) + * TODO: taking care of intermediate register values consistency and propagating their + * values to the next row when not overwritten. + * + * @param s0 The starting index of the region in calldata to be copied. + * @param s1 The number of finite field elements to be copied into memory. + * @param d0 The starting index of memory where calldata will be copied to. + * @param callDataMem The vector containing calldata. + */ +void AvmMiniTraceBuilder::callDataCopy(uint32_t s0, uint32_t s1, uint32_t d0, std::vector const& callDataMem) +{ + // We parallelize storing memory operations in chunk of 3, i.e., 1 per intermediate register. + // This offset points to the first storing operation (pertaining to intermediate register Ia). + // s0 + offset: Ia memory store operation + // s0 + offset + 1: Ib memory store operation + // s0 + offset + 2: Ic memory store operation + + uint32_t offset = 0; + + while (offset < s1) { + FF ib(0); + FF ic(0); + uint32_t mem_op_b(0); + uint32_t mem_op_c(0); + uint32_t mem_idx_b(0); + uint32_t mem_idx_c(0); + uint32_t rwb(0); + uint32_t rwc(0); + auto clk = mainTrace.size(); + + FF ia = callDataMem.at(s0 + offset); + uint32_t mem_op_a(1); + uint32_t mem_idx_a = d0 + offset; + uint32_t rwa = 1; + + // Storing from Ia + ffMemory.at(mem_idx_a) = ia; + storeAInMemTrace(mem_idx_a, ia); + + if (s1 - offset > 1) { + ib = callDataMem.at(s0 + offset + 1); + mem_op_b = 1; + mem_idx_b = d0 + offset + 1; + rwb = 1; + + // Storing from Ib + ffMemory.at(mem_idx_b) = ib; + storeBInMemTrace(mem_idx_b, ib); + } + + if (s1 - offset > 2) { + ic = callDataMem.at(s0 + offset + 2); + mem_op_c = 1; + mem_idx_c = d0 + offset + 2; + rwc = 1; + + // Storing from Ic + ffMemory.at(mem_idx_c) = ic; + storeCInMemTrace(mem_idx_c, ic); + } + + mainTrace.push_back(Row{ + .avmMini_clk = clk, + .avmMini_ia = ia, + .avmMini_ib = ib, + .avmMini_ic = ic, + .avmMini_mem_op_a = FF(mem_op_a), + .avmMini_mem_op_b = FF(mem_op_b), + .avmMini_mem_op_c = FF(mem_op_c), + .avmMini_rwa = FF(rwa), + .avmMini_rwb = FF(rwb), + .avmMini_rwc = FF(rwc), + .avmMini_mem_idx_a = FF(mem_idx_a), + .avmMini_mem_idx_b = FF(mem_idx_b), + .avmMini_mem_idx_c = FF(mem_idx_c), + }); + + if (s1 - offset > 2) { // Guard to prevent overflow if s1 is close to uint32_t maximum value. + offset += 3; + } else { + offset = s1; + } + } +} + +/** + * @brief RETURN opcode with direct memory access, i.e., + * return M_F[s0:s0+s1] + * Simplified version with exclusively memory load operations into + * intermediate registers and then values are copied to the returned vector. + * TODO: Implement the indirect memory version (maybe not required) + * TODO: taking care of flagging this row as the last one? Special STOP flag? + * + * @param s0 The starting index of the memory region to be returned. + * @param s1 The number of elements to be returned. + * @return The returned memory region as a std::vector. + */ + +std::vector AvmMiniTraceBuilder::returnOP(uint32_t s0, uint32_t s1) +{ + // We parallelize loading memory operations in chunk of 3, i.e., 1 per intermediate register. + // This offset points to the first loading operation (pertaining to intermediate register Ia). + // s0 + offset: Ia memory load operation + // s0 + offset + 1: Ib memory load operation + // s0 + offset + 2: Ic memory load operation + + uint32_t offset = 0; + std::vector returnMem; + + while (offset < s1) { + FF ib(0); + FF ic(0); + uint32_t mem_op_b(0); + uint32_t mem_op_c(0); + uint32_t mem_idx_b(0); + uint32_t mem_idx_c(0); + auto clk = mainTrace.size(); + + uint32_t mem_op_a(1); + uint32_t mem_idx_a = s0 + offset; + FF ia = ffMemory.at(mem_idx_a); + + // Loading from Ia + returnMem.push_back(ia); + loadAInMemTrace(mem_idx_a, ia); + + if (s1 - offset > 1) { + mem_op_b = 1; + mem_idx_b = s0 + offset + 1; + ib = ffMemory.at(mem_idx_b); + + // Loading from Ib + returnMem.push_back(ib); + loadBInMemTrace(mem_idx_b, ib); + } + + if (s1 - offset > 2) { + mem_op_c = 1; + mem_idx_c = s0 + offset + 2; + ic = ffMemory.at(mem_idx_c); + + // Loading from Ic + returnMem.push_back(ic); + loadCInMemTrace(mem_idx_c, ic); + } + + mainTrace.push_back(Row{ + .avmMini_clk = clk, + .avmMini_ia = ia, + .avmMini_ib = ib, + .avmMini_ic = ic, + .avmMini_mem_op_a = FF(mem_op_a), + .avmMini_mem_op_b = FF(mem_op_b), + .avmMini_mem_op_c = FF(mem_op_c), + .avmMini_mem_idx_a = FF(mem_idx_a), + .avmMini_mem_idx_b = FF(mem_idx_b), + .avmMini_mem_idx_c = FF(mem_idx_c), + }); + + if (s1 - offset > 2) { // Guard to prevent overflow if s1 is close to uint32_t maximum value. + offset += 3; + } else { + offset = s1; + } + } + return returnMem; +} + +/** + * @brief Helper to initialize ffMemory. (Testing purpose mostly.) + * + */ +void AvmMiniTraceBuilder::setFFMem(size_t idx, FF el) +{ + ffMemory.at(idx) = el; +}; + +/** + * @brief Finalisation of the memory trace and incorporating it to the main trace. + * In particular, sorting the memory trace, setting .m_lastAccess and + * adding shifted values (first row). The main trace is moved at the end of + * this call. + * + * @return The main trace + */ +std::vector AvmMiniTraceBuilder::finalize() +{ + size_t memTraceSize = memTrace.size(); + size_t mainTraceSize = mainTrace.size(); + + // TODO: We will have to handle this through error handling and not an assertion + // Smaller than N because we have to add an extra initial row to support shifted + // elements + assert(memTraceSize < N); + assert(mainTraceSize < N); + + // Sort memTrace + std::sort(memTrace.begin(), memTrace.end(), compareMemEntries); + + // Fill the rest with zeros. + size_t zeroRowsNum = N - mainTraceSize - 1; + while (zeroRowsNum-- > 0) { + mainTrace.push_back(Row{}); + } + + size_t lastIndex = (memTraceSize > mainTraceSize) ? memTraceSize - 1 : mainTraceSize - 1; + mainTrace.at(lastIndex).avmMini_last = FF(1); + + for (size_t i = 0; i < memTraceSize; i++) { + auto const& src = memTrace.at(i); + auto& dest = mainTrace.at(i); + + dest.avmMini_m_clk = FF(src.m_clk); + dest.avmMini_m_sub_clk = FF(src.m_sub_clk); + dest.avmMini_m_addr = FF(src.m_addr); + dest.avmMini_m_val = src.m_val; + dest.avmMini_m_rw = FF(static_cast(src.m_rw)); + + if (i + 1 < memTraceSize) { + auto const& next = memTrace.at(i + 1); + dest.avmMini_m_lastAccess = FF(static_cast(src.m_addr != next.m_addr)); + } else { + dest.avmMini_m_lastAccess = FF(1); + } + } + + // Adding extra row for the shifted values at the top of the execution trace. + Row first_row = Row{ .avmMini_first = 1 }; + mainTrace.insert(mainTrace.begin(), first_row); + + return std::move(mainTrace); +} + +} // namespace proof_system \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/AvmMini_trace.hpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/AvmMini_trace.hpp new file mode 100644 index 00000000000..b1fc703544e --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/AvmMini_trace.hpp @@ -0,0 +1,76 @@ +#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/AvmMini_flavor.hpp" +#include "barretenberg/relations/generated/AvmMini.hpp" + +using Flavor = proof_system::honk::flavor::AvmMiniFlavor; +using FF = Flavor::FF; +using Row = proof_system::AvmMini_vm::Row; + +namespace proof_system { + +// This is the internal context that we keep along the lifecycle of bytecode execution +// to iteratively build the whole trace. This is effectively performing witness generation. +// At the end of circuit building, mainTrace can be moved to AvmMiniCircuitBuilder by calling +// AvmMiniCircuitBuilder::set_trace(rows). +class AvmMiniTraceBuilder { + + public: + // Number of rows + static const size_t N = 256; + static const size_t MemSize = 1024; + + static const uint32_t SubClkLoadA = 0; + static const uint32_t SubClkLoadB = 1; + static const uint32_t SubClkLoadC = 2; + static const uint32_t SubClkStoreA = 3; + static const uint32_t SubClkStoreB = 4; + static const uint32_t SubClkStoreC = 5; + + AvmMiniTraceBuilder(); + + // Temporary helper to initialize memory. + void setFFMem(size_t idx, FF el); + + std::vector finalize(); + void reset(); + + // Addition over finite field with direct memory access. + void add(uint32_t s0, uint32_t s1, uint32_t d0); + + // CALLDATACOPY opcode with direct memory access, i.e., + // M_F[d0:d0+s1] = M_calldata[s0:s0+s1] + void callDataCopy(uint32_t s0, uint32_t s1, uint32_t d0, std::vector const& callDataMem); + + // RETURN opcode with direct memory access, i.e., + // return M_F[s0:s0+s1] + std::vector returnOP(uint32_t s0, uint32_t s1); + + private: + struct MemoryTraceEntry { + uint32_t m_clk; + uint32_t m_sub_clk; + uint32_t m_addr; + FF m_val; + bool m_rw; + }; + + std::vector mainTrace; + std::vector memTrace; // Entries will be sorted by m_clk, m_sub_clk after finalize(). + std::array ffMemory{}; // Memory table for finite field elements + // Used for simulation of memory table + + static bool compareMemEntries(const MemoryTraceEntry& left, const MemoryTraceEntry& right); + void insertInMemTrace(uint32_t m_clk, uint32_t m_sub_clk, uint32_t m_addr, FF m_val, bool m_rw); + void loadAInMemTrace(uint32_t addr, FF val); + void loadBInMemTrace(uint32_t addr, FF val); + void loadCInMemTrace(uint32_t addr, FF val); + void storeAInMemTrace(uint32_t addr, FF val); + void storeBInMemTrace(uint32_t addr, FF val); + void storeCInMemTrace(uint32_t addr, FF val); +}; +} // namespace proof_system diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/generated/AvmMini_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/generated/AvmMini_circuit_builder.hpp new file mode 100644 index 00000000000..1bf6093681e --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/generated/AvmMini_circuit_builder.hpp @@ -0,0 +1,119 @@ + + +// 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/AvmMini_flavor.hpp" +#include "barretenberg/relations/generated/AvmMini.hpp" + +using namespace barretenberg; + +namespace proof_system { + +class AvmMiniCircuitBuilder { + public: + using Flavor = proof_system::honk::flavor::AvmMiniFlavor; + using FF = Flavor::FF; + using Row = AvmMini_vm::Row; + + // TODO: template + using Polynomial = Flavor::Polynomial; + using AllPolynomials = Flavor::AllPolynomials; + + static constexpr size_t num_fixed_columns = 26; + static constexpr size_t num_polys = 23; + 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.pointer_view()) { + *poly = Polynomial(num_rows); + } + + for (size_t i = 0; i < rows.size(); i++) { + polys.avmMini_clk[i] = rows[i].avmMini_clk; + polys.avmMini_positive[i] = rows[i].avmMini_positive; + polys.avmMini_first[i] = rows[i].avmMini_first; + polys.avmMini_subop[i] = rows[i].avmMini_subop; + polys.avmMini_ia[i] = rows[i].avmMini_ia; + polys.avmMini_ib[i] = rows[i].avmMini_ib; + polys.avmMini_ic[i] = rows[i].avmMini_ic; + polys.avmMini_mem_op_a[i] = rows[i].avmMini_mem_op_a; + polys.avmMini_mem_op_b[i] = rows[i].avmMini_mem_op_b; + polys.avmMini_mem_op_c[i] = rows[i].avmMini_mem_op_c; + polys.avmMini_rwa[i] = rows[i].avmMini_rwa; + polys.avmMini_rwb[i] = rows[i].avmMini_rwb; + polys.avmMini_rwc[i] = rows[i].avmMini_rwc; + polys.avmMini_mem_idx_a[i] = rows[i].avmMini_mem_idx_a; + polys.avmMini_mem_idx_b[i] = rows[i].avmMini_mem_idx_b; + polys.avmMini_mem_idx_c[i] = rows[i].avmMini_mem_idx_c; + polys.avmMini_last[i] = rows[i].avmMini_last; + polys.avmMini_m_clk[i] = rows[i].avmMini_m_clk; + polys.avmMini_m_sub_clk[i] = rows[i].avmMini_m_sub_clk; + polys.avmMini_m_addr[i] = rows[i].avmMini_m_addr; + polys.avmMini_m_val[i] = rows[i].avmMini_m_val; + polys.avmMini_m_lastAccess[i] = rows[i].avmMini_m_lastAccess; + polys.avmMini_m_rw[i] = rows[i].avmMini_m_rw; + } + + polys.avmMini_m_val_shift = Polynomial(polys.avmMini_m_val.shifted()); + polys.avmMini_m_addr_shift = Polynomial(polys.avmMini_m_addr.shifted()); + polys.avmMini_m_rw_shift = Polynomial(polys.avmMini_m_rw.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()>("AvmMini"); + } + + [[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_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/generated/Fib_circuit_builder.hpp new file mode 100644 index 00000000000..3af3ba87fac --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/generated/Fib_circuit_builder.hpp @@ -0,0 +1,99 @@ + + +// 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.pointer_view()) { + *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 new file mode 100644 index 00000000000..d2d86ba4993 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/generated/Fib_trace.cpp @@ -0,0 +1,62 @@ +#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 new file mode 100644 index 00000000000..856400d82b4 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/generated/Fib_trace.hpp @@ -0,0 +1,22 @@ +#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/AvmMini.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/AvmMini.hpp new file mode 100644 index 00000000000..056d6464cf1 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/relations/generated/AvmMini.hpp @@ -0,0 +1,185 @@ + +#pragma once +#include "../relation_parameters.hpp" +#include "../relation_types.hpp" + +namespace proof_system::AvmMini_vm { + +template struct Row { + FF avmMini_clk{}; + FF avmMini_positive{}; + FF avmMini_first{}; + FF avmMini_subop{}; + FF avmMini_ia{}; + FF avmMini_ib{}; + FF avmMini_ic{}; + FF avmMini_mem_op_a{}; + FF avmMini_mem_op_b{}; + FF avmMini_mem_op_c{}; + FF avmMini_rwa{}; + FF avmMini_rwb{}; + FF avmMini_rwc{}; + FF avmMini_mem_idx_a{}; + FF avmMini_mem_idx_b{}; + FF avmMini_mem_idx_c{}; + FF avmMini_last{}; + FF avmMini_m_clk{}; + FF avmMini_m_sub_clk{}; + FF avmMini_m_addr{}; + FF avmMini_m_val{}; + FF avmMini_m_lastAccess{}; + FF avmMini_m_rw{}; + FF avmMini_m_val_shift{}; + FF avmMini_m_addr_shift{}; + FF avmMini_m_rw_shift{}; +}; + +#define DECLARE_VIEWS(index) \ + using View = typename std::tuple_element::type; \ + [[maybe_unused]] auto avmMini_clk = View(new_term.avmMini_clk); \ + [[maybe_unused]] auto avmMini_positive = View(new_term.avmMini_positive); \ + [[maybe_unused]] auto avmMini_first = View(new_term.avmMini_first); \ + [[maybe_unused]] auto avmMini_subop = View(new_term.avmMini_subop); \ + [[maybe_unused]] auto avmMini_ia = View(new_term.avmMini_ia); \ + [[maybe_unused]] auto avmMini_ib = View(new_term.avmMini_ib); \ + [[maybe_unused]] auto avmMini_ic = View(new_term.avmMini_ic); \ + [[maybe_unused]] auto avmMini_mem_op_a = View(new_term.avmMini_mem_op_a); \ + [[maybe_unused]] auto avmMini_mem_op_b = View(new_term.avmMini_mem_op_b); \ + [[maybe_unused]] auto avmMini_mem_op_c = View(new_term.avmMini_mem_op_c); \ + [[maybe_unused]] auto avmMini_rwa = View(new_term.avmMini_rwa); \ + [[maybe_unused]] auto avmMini_rwb = View(new_term.avmMini_rwb); \ + [[maybe_unused]] auto avmMini_rwc = View(new_term.avmMini_rwc); \ + [[maybe_unused]] auto avmMini_mem_idx_a = View(new_term.avmMini_mem_idx_a); \ + [[maybe_unused]] auto avmMini_mem_idx_b = View(new_term.avmMini_mem_idx_b); \ + [[maybe_unused]] auto avmMini_mem_idx_c = View(new_term.avmMini_mem_idx_c); \ + [[maybe_unused]] auto avmMini_last = View(new_term.avmMini_last); \ + [[maybe_unused]] auto avmMini_m_clk = View(new_term.avmMini_m_clk); \ + [[maybe_unused]] auto avmMini_m_sub_clk = View(new_term.avmMini_m_sub_clk); \ + [[maybe_unused]] auto avmMini_m_addr = View(new_term.avmMini_m_addr); \ + [[maybe_unused]] auto avmMini_m_val = View(new_term.avmMini_m_val); \ + [[maybe_unused]] auto avmMini_m_lastAccess = View(new_term.avmMini_m_lastAccess); \ + [[maybe_unused]] auto avmMini_m_rw = View(new_term.avmMini_m_rw); \ + [[maybe_unused]] auto avmMini_m_val_shift = View(new_term.avmMini_m_val_shift); \ + [[maybe_unused]] auto avmMini_m_addr_shift = View(new_term.avmMini_m_addr_shift); \ + [[maybe_unused]] auto avmMini_m_rw_shift = View(new_term.avmMini_m_rw_shift); + +template class AvmMiniImpl { + public: + using FF = FF_; + + static constexpr std::array SUBRELATION_PARTIAL_LENGTHS{ + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + }; + + 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 = (avmMini_subop * (-avmMini_subop + FF(1))); + tmp *= scaling_factor; + std::get<0>(evals) += tmp; + } + // Contribution 1 + { + DECLARE_VIEWS(1); + + auto tmp = (avmMini_mem_op_a * (-avmMini_mem_op_a + FF(1))); + tmp *= scaling_factor; + std::get<1>(evals) += tmp; + } + // Contribution 2 + { + DECLARE_VIEWS(2); + + auto tmp = (avmMini_mem_op_b * (-avmMini_mem_op_b + FF(1))); + tmp *= scaling_factor; + std::get<2>(evals) += tmp; + } + // Contribution 3 + { + DECLARE_VIEWS(3); + + auto tmp = (avmMini_mem_op_c * (-avmMini_mem_op_c + FF(1))); + tmp *= scaling_factor; + std::get<3>(evals) += tmp; + } + // Contribution 4 + { + DECLARE_VIEWS(4); + + auto tmp = (avmMini_rwa * (-avmMini_rwa + FF(1))); + tmp *= scaling_factor; + std::get<4>(evals) += tmp; + } + // Contribution 5 + { + DECLARE_VIEWS(5); + + auto tmp = (avmMini_rwb * (-avmMini_rwb + FF(1))); + tmp *= scaling_factor; + std::get<5>(evals) += tmp; + } + // Contribution 6 + { + DECLARE_VIEWS(6); + + auto tmp = (avmMini_rwc * (-avmMini_rwc + FF(1))); + tmp *= scaling_factor; + std::get<6>(evals) += tmp; + } + // Contribution 7 + { + DECLARE_VIEWS(7); + + auto tmp = (avmMini_subop * ((avmMini_ia + avmMini_ib) - avmMini_ic)); + tmp *= scaling_factor; + std::get<7>(evals) += tmp; + } + // Contribution 8 + { + DECLARE_VIEWS(8); + + auto tmp = (avmMini_m_lastAccess * (-avmMini_m_lastAccess + FF(1))); + tmp *= scaling_factor; + std::get<8>(evals) += tmp; + } + // Contribution 9 + { + DECLARE_VIEWS(9); + + auto tmp = (avmMini_m_rw * (-avmMini_m_rw + FF(1))); + tmp *= scaling_factor; + std::get<9>(evals) += tmp; + } + // Contribution 10 + { + DECLARE_VIEWS(10); + + auto tmp = (((-avmMini_first + FF(1)) * (-avmMini_m_lastAccess + FF(1))) * + (avmMini_m_addr_shift - avmMini_m_addr)); + tmp *= scaling_factor; + std::get<10>(evals) += tmp; + } + // Contribution 11 + { + DECLARE_VIEWS(11); + + auto tmp = (((((-avmMini_first + FF(1)) * (-avmMini_last + FF(1))) * (-avmMini_m_lastAccess + FF(1))) * + (-avmMini_m_rw_shift + FF(1))) * + (avmMini_m_val_shift - avmMini_m_val)); + tmp *= scaling_factor; + std::get<11>(evals) += tmp; + } + } +}; + +template using AvmMini = Relation>; + +} // namespace proof_system::AvmMini_vm \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/Fib.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/Fib.hpp new file mode 100644 index 00000000000..428c6a1208b --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/relations/generated/Fib.hpp @@ -0,0 +1,64 @@ + +#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/CMakeLists.txt b/barretenberg/cpp/src/barretenberg/vm/CMakeLists.txt new file mode 100644 index 00000000000..c6c16ebdc44 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm/CMakeLists.txt @@ -0,0 +1 @@ +barretenberg_module(vm honk sumcheck protogalaxy) \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/AvmMini_composer.cpp b/barretenberg/cpp/src/barretenberg/vm/generated/AvmMini_composer.cpp new file mode 100644 index 00000000000..b0d8a156711 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm/generated/AvmMini_composer.cpp @@ -0,0 +1,105 @@ + + +#include "./AvmMini_composer.hpp" +#include "barretenberg/proof_system/circuit_builder/generated/AvmMini_circuit_builder.hpp" +#include "barretenberg/proof_system/composer/composer_lib.hpp" +#include "barretenberg/proof_system/composer/permutation_lib.hpp" +#include "barretenberg/vm/generated/AvmMini_verifier.hpp" + +namespace proof_system::honk { + +using Flavor = honk::flavor::AvmMiniFlavor; +void AvmMiniComposer::compute_witness(CircuitConstructor& circuit) +{ + if (computed_witness) { + return; + } + + auto polynomials = circuit.compute_polynomials(); + + proving_key->avmMini_clk = polynomials.avmMini_clk; + proving_key->avmMini_positive = polynomials.avmMini_positive; + proving_key->avmMini_first = polynomials.avmMini_first; + proving_key->avmMini_subop = polynomials.avmMini_subop; + proving_key->avmMini_ia = polynomials.avmMini_ia; + proving_key->avmMini_ib = polynomials.avmMini_ib; + proving_key->avmMini_ic = polynomials.avmMini_ic; + proving_key->avmMini_mem_op_a = polynomials.avmMini_mem_op_a; + proving_key->avmMini_mem_op_b = polynomials.avmMini_mem_op_b; + proving_key->avmMini_mem_op_c = polynomials.avmMini_mem_op_c; + proving_key->avmMini_rwa = polynomials.avmMini_rwa; + proving_key->avmMini_rwb = polynomials.avmMini_rwb; + proving_key->avmMini_rwc = polynomials.avmMini_rwc; + proving_key->avmMini_mem_idx_a = polynomials.avmMini_mem_idx_a; + proving_key->avmMini_mem_idx_b = polynomials.avmMini_mem_idx_b; + proving_key->avmMini_mem_idx_c = polynomials.avmMini_mem_idx_c; + proving_key->avmMini_last = polynomials.avmMini_last; + proving_key->avmMini_m_clk = polynomials.avmMini_m_clk; + proving_key->avmMini_m_sub_clk = polynomials.avmMini_m_sub_clk; + proving_key->avmMini_m_addr = polynomials.avmMini_m_addr; + proving_key->avmMini_m_val = polynomials.avmMini_m_val; + proving_key->avmMini_m_lastAccess = polynomials.avmMini_m_lastAccess; + proving_key->avmMini_m_rw = polynomials.avmMini_m_rw; + + computed_witness = true; +} + +AvmMiniProver AvmMiniComposer::create_prover(CircuitConstructor& circuit_constructor) +{ + compute_proving_key(circuit_constructor); + compute_witness(circuit_constructor); + compute_commitment_key(circuit_constructor.get_circuit_subgroup_size()); + + AvmMiniProver output_state(proving_key, commitment_key); + + return output_state; +} + +AvmMiniVerifier AvmMiniComposer::create_verifier(CircuitConstructor& circuit_constructor) +{ + auto verification_key = compute_verification_key(circuit_constructor); + + AvmMiniVerifier 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 AvmMiniComposer::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 AvmMiniComposer::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/AvmMini_composer.hpp b/barretenberg/cpp/src/barretenberg/vm/generated/AvmMini_composer.hpp new file mode 100644 index 00000000000..f9458a7389d --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm/generated/AvmMini_composer.hpp @@ -0,0 +1,69 @@ + + +#pragma once + +#include "barretenberg/proof_system/circuit_builder/generated/AvmMini_circuit_builder.hpp" +#include "barretenberg/proof_system/composer/composer_lib.hpp" +#include "barretenberg/srs/global_crs.hpp" +#include "barretenberg/vm/generated/AvmMini_prover.hpp" +#include "barretenberg/vm/generated/AvmMini_verifier.hpp" + +namespace proof_system::honk { +class AvmMiniComposer { + public: + using Flavor = honk::flavor::AvmMiniFlavor; + using CircuitConstructor = AvmMiniCircuitBuilder; + 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 = "AvmMini"; + 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; + + AvmMiniComposer() { crs_factory_ = barretenberg::srs::get_crs_factory(); } + + AvmMiniComposer(std::shared_ptr p_key, std::shared_ptr v_key) + : proving_key(std::move(p_key)) + , verification_key(std::move(v_key)) + {} + + AvmMiniComposer(AvmMiniComposer&& other) noexcept = default; + AvmMiniComposer(AvmMiniComposer const& other) noexcept = default; + AvmMiniComposer& operator=(AvmMiniComposer&& other) noexcept = default; + AvmMiniComposer& operator=(AvmMiniComposer const& other) noexcept = default; + ~AvmMiniComposer() = 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); + + AvmMiniProver create_prover(CircuitConstructor& circuit_constructor); + AvmMiniVerifier 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/AvmMini_composer.test.cpp b/barretenberg/cpp/src/barretenberg/vm/generated/AvmMini_composer.test.cpp new file mode 100644 index 00000000000..349238fc984 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm/generated/AvmMini_composer.test.cpp @@ -0,0 +1,60 @@ +#include "barretenberg/vm/generated/AvmMini_composer.hpp" +#include "barretenberg/ecc/curves/bn254/fr.hpp" +#include "barretenberg/flavor/generated/AvmMini_flavor.hpp" +#include "barretenberg/numeric/uint256/uint256.hpp" +#include "barretenberg/proof_system/circuit_builder/AvmMini_helper.hpp" +#include "barretenberg/proof_system/circuit_builder/AvmMini_trace.hpp" +#include "barretenberg/sumcheck/sumcheck_round.hpp" +#include "barretenberg/vm/generated/AvmMini_prover.hpp" +#include "barretenberg/vm/generated/AvmMini_verifier.hpp" + +#include +#include +#include +#include +#include + +using namespace proof_system::honk; + +namespace example_relation_honk_composer { + +class AvmMiniTests : 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(AvmMiniTests, basic) +{ + auto trace_builder = proof_system::AvmMiniTraceBuilder(); + auto circuit_builder = proof_system::AvmMiniCircuitBuilder(); + + trace_builder.callDataCopy(0, 3, 2, std::vector{ 45, 23, 12 }); + + trace_builder.add(2, 3, 4); + trace_builder.add(4, 5, 5); + trace_builder.add(5, 5, 5); + trace_builder.add(5, 6, 7); + + trace_builder.returnOP(1, 8); + + auto trace = trace_builder.finalize(); + proof_system::log_avmMini_trace(trace, 0, 7); + circuit_builder.set_trace(std::move(trace)); + + ASSERT_TRUE(circuit_builder.check_circuit()); + + auto composer = AvmMiniComposer(); + 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); +} + +} // namespace example_relation_honk_composer \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/AvmMini_prover.cpp b/barretenberg/cpp/src/barretenberg/vm/generated/AvmMini_prover.cpp new file mode 100644 index 00000000000..730aab4ba4f --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm/generated/AvmMini_prover.cpp @@ -0,0 +1,159 @@ + + +#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/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::AvmMiniFlavor; + +/** + * Create AvmMiniProver from proving key, witness and manifest. + * + * @param input_key Proving key. + * @param input_manifest Input manifest + * + * @tparam settings Settings class. + * */ +AvmMiniProver::AvmMiniProver(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.avmMini_clk = key->avmMini_clk; + prover_polynomials.avmMini_positive = key->avmMini_positive; + prover_polynomials.avmMini_first = key->avmMini_first; + prover_polynomials.avmMini_subop = key->avmMini_subop; + prover_polynomials.avmMini_ia = key->avmMini_ia; + prover_polynomials.avmMini_ib = key->avmMini_ib; + prover_polynomials.avmMini_ic = key->avmMini_ic; + prover_polynomials.avmMini_mem_op_a = key->avmMini_mem_op_a; + prover_polynomials.avmMini_mem_op_b = key->avmMini_mem_op_b; + prover_polynomials.avmMini_mem_op_c = key->avmMini_mem_op_c; + prover_polynomials.avmMini_rwa = key->avmMini_rwa; + prover_polynomials.avmMini_rwb = key->avmMini_rwb; + prover_polynomials.avmMini_rwc = key->avmMini_rwc; + prover_polynomials.avmMini_mem_idx_a = key->avmMini_mem_idx_a; + prover_polynomials.avmMini_mem_idx_b = key->avmMini_mem_idx_b; + prover_polynomials.avmMini_mem_idx_c = key->avmMini_mem_idx_c; + prover_polynomials.avmMini_last = key->avmMini_last; + prover_polynomials.avmMini_m_clk = key->avmMini_m_clk; + prover_polynomials.avmMini_m_sub_clk = key->avmMini_m_sub_clk; + prover_polynomials.avmMini_m_addr = key->avmMini_m_addr; + prover_polynomials.avmMini_m_val = key->avmMini_m_val; + prover_polynomials.avmMini_m_lastAccess = key->avmMini_m_lastAccess; + prover_polynomials.avmMini_m_rw = key->avmMini_m_rw; + + prover_polynomials.avmMini_m_val = key->avmMini_m_val; + prover_polynomials.avmMini_m_val_shift = key->avmMini_m_val.shifted(); + + prover_polynomials.avmMini_m_addr = key->avmMini_m_addr; + prover_polynomials.avmMini_m_addr_shift = key->avmMini_m_addr.shifted(); + + prover_polynomials.avmMini_m_rw = key->avmMini_m_rw; + prover_polynomials.avmMini_m_rw_shift = key->avmMini_m_rw.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 AvmMiniProver::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 AvmMiniProver::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 AvmMiniProver::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 AvmMiniProver::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& AvmMiniProver::export_proof() +{ + proof.proof_data = transcript.proof_data; + return proof; +} + +plonk::proof& AvmMiniProver::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/AvmMini_prover.hpp b/barretenberg/cpp/src/barretenberg/vm/generated/AvmMini_prover.hpp new file mode 100644 index 00000000000..792140b2ece --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm/generated/AvmMini_prover.hpp @@ -0,0 +1,62 @@ + + +#pragma once +#include "barretenberg/commitment_schemes/zeromorph/zeromorph.hpp" +#include "barretenberg/flavor/generated/AvmMini_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 AvmMiniProver { + + using Flavor = honk::flavor::AvmMiniFlavor; + 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 AvmMiniProver(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(); + + Transcript transcript; + + 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/AvmMini_verifier.cpp b/barretenberg/cpp/src/barretenberg/vm/generated/AvmMini_verifier.cpp new file mode 100644 index 00000000000..575d55bd00c --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm/generated/AvmMini_verifier.cpp @@ -0,0 +1,114 @@ + + +#include "./AvmMini_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 { +AvmMiniVerifier::AvmMiniVerifier(std::shared_ptr verifier_key) + : key(verifier_key) +{} + +AvmMiniVerifier::AvmMiniVerifier(AvmMiniVerifier&& other) noexcept + : key(std::move(other.key)) + , pcs_verification_key(std::move(other.pcs_verification_key)) +{} + +AvmMiniVerifier& AvmMiniVerifier::operator=(AvmMiniVerifier&& other) noexcept +{ + key = other.key; + pcs_verification_key = (std::move(other.pcs_verification_key)); + commitments.clear(); + return *this; +} + +/** + * @brief This function verifies an AvmMini Honk proof for given program settings. + * + */ +bool AvmMiniVerifier::verify_proof(const plonk::proof& proof) +{ + using Flavor = honk::flavor::AvmMiniFlavor; + 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; + + RelationParameters relation_parameters; + + transcript = BaseTranscript{ proof.proof_data }; + + auto commitments = VerifierCommitments(key, transcript); + auto commitment_labels = CommitmentLabels(); + + 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.avmMini_subop = transcript.template receive_from_prover(commitment_labels.avmMini_subop); + commitments.avmMini_ia = transcript.template receive_from_prover(commitment_labels.avmMini_ia); + commitments.avmMini_ib = transcript.template receive_from_prover(commitment_labels.avmMini_ib); + commitments.avmMini_ic = transcript.template receive_from_prover(commitment_labels.avmMini_ic); + commitments.avmMini_mem_op_a = + transcript.template receive_from_prover(commitment_labels.avmMini_mem_op_a); + commitments.avmMini_mem_op_b = + transcript.template receive_from_prover(commitment_labels.avmMini_mem_op_b); + commitments.avmMini_mem_op_c = + transcript.template receive_from_prover(commitment_labels.avmMini_mem_op_c); + commitments.avmMini_rwa = transcript.template receive_from_prover(commitment_labels.avmMini_rwa); + commitments.avmMini_rwb = transcript.template receive_from_prover(commitment_labels.avmMini_rwb); + commitments.avmMini_rwc = transcript.template receive_from_prover(commitment_labels.avmMini_rwc); + commitments.avmMini_mem_idx_a = + transcript.template receive_from_prover(commitment_labels.avmMini_mem_idx_a); + commitments.avmMini_mem_idx_b = + transcript.template receive_from_prover(commitment_labels.avmMini_mem_idx_b); + commitments.avmMini_mem_idx_c = + transcript.template receive_from_prover(commitment_labels.avmMini_mem_idx_c); + commitments.avmMini_last = transcript.template receive_from_prover(commitment_labels.avmMini_last); + commitments.avmMini_m_clk = transcript.template receive_from_prover(commitment_labels.avmMini_m_clk); + commitments.avmMini_m_sub_clk = + transcript.template receive_from_prover(commitment_labels.avmMini_m_sub_clk); + commitments.avmMini_m_addr = transcript.template receive_from_prover(commitment_labels.avmMini_m_addr); + commitments.avmMini_m_val = transcript.template receive_from_prover(commitment_labels.avmMini_m_val); + commitments.avmMini_m_lastAccess = + transcript.template receive_from_prover(commitment_labels.avmMini_m_lastAccess); + commitments.avmMini_m_rw = transcript.template receive_from_prover(commitment_labels.avmMini_m_rw); + + // 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/AvmMini_verifier.hpp b/barretenberg/cpp/src/barretenberg/vm/generated/AvmMini_verifier.hpp new file mode 100644 index 00000000000..5c8ef05d160 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm/generated/AvmMini_verifier.hpp @@ -0,0 +1,32 @@ + + +#pragma once +#include "barretenberg/flavor/generated/AvmMini_flavor.hpp" +#include "barretenberg/plonk/proof_system/types/proof.hpp" +#include "barretenberg/sumcheck/sumcheck.hpp" + +namespace proof_system::honk { +class AvmMiniVerifier { + using Flavor = honk::flavor::AvmMiniFlavor; + using FF = Flavor::FF; + using Commitment = Flavor::Commitment; + using VerificationKey = Flavor::VerificationKey; + using VerifierCommitmentKey = Flavor::VerifierCommitmentKey; + + public: + explicit AvmMiniVerifier(std::shared_ptr verifier_key = nullptr); + AvmMiniVerifier(AvmMiniVerifier&& other) noexcept; + AvmMiniVerifier(const AvmMiniVerifier& other) = delete; + + AvmMiniVerifier& operator=(const AvmMiniVerifier& other) = delete; + AvmMiniVerifier& operator=(AvmMiniVerifier&& other) noexcept; + + bool verify_proof(const plonk::proof& proof); + + std::shared_ptr key; + std::map commitments; + std::shared_ptr pcs_verification_key; + BaseTranscript transcript; +}; + +} // namespace proof_system::honk diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/Fib_composer.cpp b/barretenberg/cpp/src/barretenberg/vm/generated/Fib_composer.cpp new file mode 100644 index 00000000000..7a78c264e75 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm/generated/Fib_composer.cpp @@ -0,0 +1,85 @@ + + +#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 new file mode 100644 index 00000000000..99c71c1913f --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm/generated/Fib_composer.hpp @@ -0,0 +1,69 @@ + + +#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 new file mode 100644 index 00000000000..7dfd82fbeeb --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm/generated/Fib_composer.test.cpp @@ -0,0 +1,55 @@ +#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(); + info("circuit gud"); + ASSERT_TRUE(circuit_gud); + + auto prover = composer.create_prover(circuit_builder); + auto proof = prover.construct_proof(); + info(proof); + + auto verifier = composer.create_verifier(circuit_builder); + bool verified = verifier.verify_proof(proof); + ASSERT_TRUE(verified); + + info("We verified a 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 new file mode 100644 index 00000000000..4fc64409547 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm/generated/Fib_prover.cpp @@ -0,0 +1,136 @@ + + +#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/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 new file mode 100644 index 00000000000..7a3c80cbe6b --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm/generated/Fib_prover.hpp @@ -0,0 +1,62 @@ + + +#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(); + + Transcript transcript; + + 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 new file mode 100644 index 00000000000..b413390e897 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm/generated/Fib_verifier.cpp @@ -0,0 +1,88 @@ + + +#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; + + RelationParameters relation_parameters; + + transcript = BaseTranscript{ proof.proof_data }; + + auto commitments = VerifierCommitments(key, transcript); + auto commitment_labels = CommitmentLabels(); + + 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 new file mode 100644 index 00000000000..85d98c492ee --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm/generated/Fib_verifier.hpp @@ -0,0 +1,32 @@ + + +#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; + + 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; + BaseTranscript transcript; +}; + +} // namespace proof_system::honk