diff --git a/barretenberg/.vscode/settings.json b/barretenberg/.vscode/settings.json index 2016adfd2c9..7ce883ceaeb 100644 --- a/barretenberg/.vscode/settings.json +++ b/barretenberg/.vscode/settings.json @@ -127,5 +127,6 @@ "[javascript]": { "editor.defaultFormatter": "esbenp.prettier-vscode" }, - "cmake.sourceDirectory": "${workspaceFolder}/cpp" + "cmake.sourceDirectory": "${workspaceFolder}/cpp", + "clangd.path": "/usr/bin/clangd" } diff --git a/barretenberg/barretenberg.code-workspace b/barretenberg/barretenberg.code-workspace index ac2b6bb11f5..636b3ce63d9 100644 --- a/barretenberg/barretenberg.code-workspace +++ b/barretenberg/barretenberg.code-workspace @@ -86,7 +86,7 @@ // Clangd. Note that this setting may be overridden by user settings // to the default value "clangd". // - "clangd.path": "clangd-16", + "clangd.path": "/usr/bin/clangd", // We should disable automatic inclusion of headers unless we decide to follow "WhyIWYU". "clangd.arguments": [ "-header-insertion=never" diff --git a/barretenberg/cpp/src/barretenberg/benchmark/goblin_bench/eccvm.bench.cpp b/barretenberg/cpp/src/barretenberg/benchmark/goblin_bench/eccvm.bench.cpp index b76eb863f76..9a065ec6965 100644 --- a/barretenberg/cpp/src/barretenberg/benchmark/goblin_bench/eccvm.bench.cpp +++ b/barretenberg/cpp/src/barretenberg/benchmark/goblin_bench/eccvm.bench.cpp @@ -7,7 +7,7 @@ using namespace benchmark; using namespace bb; using Flavor = ECCVMFlavor; -using Builder = ECCVMCircuitBuilder; +using Builder = ECCVMCircuitBuilder; using Composer = ECCVMComposer; namespace { diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_builder_types.hpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_builder_types.hpp index 9ba785657d9..95abffe5120 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_builder_types.hpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_builder_types.hpp @@ -1,5 +1,6 @@ #pragma once +#include "barretenberg/ecc/curves/bn254/bn254.hpp" #include "barretenberg/ecc/curves/grumpkin/grumpkin.hpp" namespace bb::eccvm { diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_circuit_builder.hpp index b24d7445328..b8b87970d2a 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_circuit_builder.hpp @@ -6,7 +6,6 @@ #include "./transcript_builder.hpp" #include "barretenberg/ecc/curves/bn254/fr.hpp" #include "barretenberg/ecc/curves/grumpkin/grumpkin.hpp" -#include "barretenberg/eccvm/eccvm_flavor.hpp" #include "barretenberg/honk/proof_system/logderivative_library.hpp" #include "barretenberg/honk/proof_system/permutation_library.hpp" #include "barretenberg/relations/relation_parameters.hpp" @@ -14,11 +13,11 @@ namespace bb { -template class ECCVMCircuitBuilder { +class ECCVMCircuitBuilder { public: - using CycleGroup = typename Flavor::CycleGroup; - using FF = typename Flavor::FF; - using Polynomial = typename Flavor::Polynomial; + using CycleGroup = bb::g1; + using FF = grumpkin::fr; + using Polynomial = bb::Polynomial; using CycleScalar = typename CycleGroup::subgroup_field; using Element = typename CycleGroup::element; @@ -32,14 +31,10 @@ template class ECCVMCircuitBuilder { static constexpr size_t WNAF_SLICES_PER_ROW = bb::eccvm::WNAF_SLICES_PER_ROW; static constexpr size_t ADDITIONS_PER_ROW = bb::eccvm::ADDITIONS_PER_ROW; - static constexpr size_t NUM_POLYNOMIALS = Flavor::NUM_ALL_ENTITIES; - static constexpr size_t NUM_WIRES = Flavor::NUM_WIRES; - using MSM = bb::eccvm::MSM; using VMOperation = bb::eccvm::VMOperation; std::shared_ptr op_queue; using ScalarMul = bb::eccvm::ScalarMul; - using ProverPolynomials = typename Flavor::ProverPolynomials; ECCVMCircuitBuilder(std::shared_ptr& op_queue) : op_queue(op_queue){}; @@ -219,332 +214,7 @@ template class ECCVMCircuitBuilder { return result; } - /** - * @brief Compute the ECCVM flavor polynomial data required to generate an ECCVM Proof - * - * @details RawPolynomial member polynomials that this fn must populate described below - * For full details see `eccvm/eccvm_flavor.hpp` - * - * lagrange_first: lagrange_first[0] = 1, 0 elsewhere - * lagrange_second: lagrange_second[1] = 1, 0 elsewhere - * lagrange_last: lagrange_last[lagrange_last.size() - 1] = 1, 0 elsewhere - * transcript_add/mul/eq/reset_accumulator: boolean selectors that toggle add/mul/eq/reset opcodes - * transcript_collision_check: used to ensure any point being added into eccvm accumulator does not trigger - * incomplete addition rules - * transcript_msm_transition: is current transcript row the final `mul` opcode of a multiscalar - multiplication? - * transcript_pc: point counter for transcript columns - * transcript_msm_count: counts number of muls processed in an ongoing multiscalar multiplication - * transcript_Px: input transcript point, x-coordinate - * transcript_Py: input transcriot point, y-coordinate - * transcript_op: input transcript opcode value - * transcript_z1: input transcript scalar multiplier (low component, 128 bits max) - * transcript_z2: input transcript scalar multipplier (high component, 128 bits max) - * N.B. scalar multiplier = transcript_z1 + \lambda * transcript_z2. \lambda = cube root of unity in scalar field - * transcript_z1zero: if 1, transcript_z1 must equal 0 - * transcript_z2zero: if 1, transcript_z2 must equal 0 - * transcript_accumulator_x: x-coordinate of eccvm accumulator register - * transcript_accumulator_y: y-coordinate of eccvm accumulator register - * transcript_msm_x: x-coordinate of MSM output - * transcript_msm_y: y-coordinate of MSM output - * transcript_accumulator_empty: if 1, transcript_accumulator = point at infinity - * precompute_pc: point counter for Straus precomputation columns - * precompute_select: if 1, evaluate Straus precomputation algorithm at current row - * precompute_point_transition: 1 if current row operating on a different point to previous row - * precompute_round: round counter for Straus precomputation algorithm - * precompute_scalar_sum: accumulating sum of Straus scalar slices - * precompute_s1hi/lo: 2-bit hi/lo components of a Straus 4-bit scalar slice - * precompute_s2hilo/precompute_s3hi/loprecompute_s4hi/lo: same as above but for a total of 4 Straus 4-bit - scalar slices - * precompute_skew: Straus WNAF skew parameter for a single scalar multiplier - * precompute_tx: x-coordinate of point accumulator used to generate Straus lookup table for an input point - (from transcript) - * precompute_tx: x-coordinate of point accumulator used to generate Straus lookup table for an input point - (from transcript) - * precompute_dx: x-coordinate of D = 2 * input point we are evaluating Straus over - * precompute_dy: y-coordinate of D - * msm_pc: point counter for Straus MSM columns - * msm_transition: 1 if current row evaluates different MSM to previous row - * msm_add: 1 if we are adding points in Straus MSM algorithm at current row - * msm_double: 1 if we are doubling accumulator in Straus MSM algorithm at current row - * msm_skew: 1 if we are adding skew points in Straus MSM algorithm at current row - * msm_size_of_msm: size of multiscalar multiplication current row is a part of - * msm_round: describes which round of the Straus MSM algorithm the current row represents - * msm_count: number of points processed for the round indicated by `msm_round` - * msm_x1: x-coordinate of potential point in Straus MSM round - * msm_y1: y-coordinate of potential point in Straus MSM round - * msm_x2: x-coordinate of potential point in Straus MSM round - * msm_y2: y-coordinate of potential point in Straus MSM round - * msm_x3: x-coordinate of potential point in Straus MSM round - * msm_y3: y-coordinate of potential point in Straus MSM round - * msm_x4: x-coordinate of potential point in Straus MSM round - * msm_y4: y-coordinate of potential point in Straus MSM round - * msm_add1: are we adding msm_x1/msm_y1 into accumulator at current round? - * msm_add2: are we adding msm_x2/msm_y2 into accumulator at current round? - * msm_add3: are we adding msm_x3/msm_y3 into accumulator at current round? - * msm_add4: are we adding msm_x4/msm_y4 into accumulator at current round? - * msm_lambda1: temp variable used for ecc point addition algorithm if msm_add1 = 1 - * msm_lambda2: temp variable used for ecc point addition algorithm if msm_add2 = 1 - * msm_lambda3: temp variable used for ecc point addition algorithm if msm_add3 = 1 - * msm_lambda4: temp variable used for ecc point addition algorithm if msm_add4 = 1 - * msm_collision_x1: used to ensure incomplete ecc addition exceptions not triggered if msm_add1 = 1 - * msm_collision_x2: used to ensure incomplete ecc addition exceptions not triggered if msm_add2 = 1 - * msm_collision_x3: used to ensure incomplete ecc addition exceptions not triggered if msm_add3 = 1 - * msm_collision_x4: used to ensure incomplete ecc addition exceptions not triggered if msm_add4 = 1 - * lookup_read_counts_0: stores number of times a point has been read from a Straus precomputation table - (reads come from msm_x/y1, msm_x/y2) - * lookup_read_counts_1: stores number of times a point has been read from a Straus precomputation table - (reads come from msm_x/y3, msm_x/y4) - * @return ProverPolynomials - */ - ProverPolynomials compute_polynomials() - { - const auto msms = get_msms(); - const auto flattened_muls = get_flattened_scalar_muls(msms); - - std::array, 2> point_table_read_counts; - const auto transcript_state = - ECCVMTranscriptBuilder::compute_transcript_state(op_queue->raw_ops, get_number_of_muls()); - const auto precompute_table_state = - ECCVMPrecomputedTablesBuilder::compute_precompute_state(flattened_muls); - const auto msm_state = ECCVMMSMMBuilder::compute_msm_state( - msms, point_table_read_counts, get_number_of_muls(), op_queue->get_num_msm_rows()); - - const size_t msm_size = msm_state.size(); - const size_t transcript_size = transcript_state.size(); - const size_t precompute_table_size = precompute_table_state.size(); - - const size_t num_rows = std::max(precompute_table_size, std::max(msm_size, transcript_size)); - - 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)); - - ProverPolynomials polys; - for (auto& poly : polys.get_all()) { - poly = Polynomial(num_rows_pow2); - } - - polys.lagrange_first[0] = 1; - polys.lagrange_second[1] = 1; - polys.lagrange_last[polys.lagrange_last.size() - 1] = 1; - - for (size_t i = 0; i < point_table_read_counts[0].size(); ++i) { - // Explanation of off-by-one offset - // When computing the WNAF slice for a point at point counter value `pc` and a round index `round`, the row - // number that computes the slice can be derived. This row number is then mapped to the index of - // `lookup_read_counts`. We do this mapping in `ecc_msm_relation`. We are off-by-one because we add an empty - // row at the start of the WNAF columns that is not accounted for (index of lookup_read_counts maps to the - // row in our WNAF columns that computes a slice for a given value of pc and round) - polys.lookup_read_counts_0[i + 1] = point_table_read_counts[0][i]; - polys.lookup_read_counts_1[i + 1] = point_table_read_counts[1][i]; - } - run_loop_in_parallel(transcript_state.size(), [&](size_t start, size_t end) { - for (size_t i = start; i < end; i++) { - polys.transcript_accumulator_empty[i] = transcript_state[i].accumulator_empty; - polys.transcript_add[i] = transcript_state[i].q_add; - polys.transcript_mul[i] = transcript_state[i].q_mul; - polys.transcript_eq[i] = transcript_state[i].q_eq; - polys.transcript_reset_accumulator[i] = transcript_state[i].q_reset_accumulator; - polys.transcript_msm_transition[i] = transcript_state[i].msm_transition; - polys.transcript_pc[i] = transcript_state[i].pc; - polys.transcript_msm_count[i] = transcript_state[i].msm_count; - polys.transcript_Px[i] = transcript_state[i].base_x; - polys.transcript_Py[i] = transcript_state[i].base_y; - polys.transcript_z1[i] = transcript_state[i].z1; - polys.transcript_z2[i] = transcript_state[i].z2; - polys.transcript_z1zero[i] = transcript_state[i].z1_zero; - polys.transcript_z2zero[i] = transcript_state[i].z2_zero; - polys.transcript_op[i] = transcript_state[i].opcode; - polys.transcript_accumulator_x[i] = transcript_state[i].accumulator_x; - polys.transcript_accumulator_y[i] = transcript_state[i].accumulator_y; - polys.transcript_msm_x[i] = transcript_state[i].msm_output_x; - polys.transcript_msm_y[i] = transcript_state[i].msm_output_y; - polys.transcript_collision_check[i] = transcript_state[i].collision_check; - } - }); - - // TODO(@zac-williamson) if final opcode resets accumulator, all subsequent "is_accumulator_empty" row values - // must be 1. Ideally we find a way to tweak this so that empty rows that do nothing have column values that are - // all zero (issue #2217) - if (transcript_state[transcript_state.size() - 1].accumulator_empty == 1) { - for (size_t i = transcript_state.size(); i < num_rows_pow2; ++i) { - polys.transcript_accumulator_empty[i] = 1; - } - } - run_loop_in_parallel(precompute_table_state.size(), [&](size_t start, size_t end) { - for (size_t i = start; i < end; i++) { - // first row is always an empty row (to accommodate shifted polynomials which must have 0 as 1st - // coefficient). All other rows in the precompute_table_state represent active wnaf gates (i.e. - // precompute_select = 1) - polys.precompute_select[i] = (i != 0) ? 1 : 0; - polys.precompute_pc[i] = precompute_table_state[i].pc; - polys.precompute_point_transition[i] = - static_cast(precompute_table_state[i].point_transition); - polys.precompute_round[i] = precompute_table_state[i].round; - polys.precompute_scalar_sum[i] = precompute_table_state[i].scalar_sum; - - polys.precompute_s1hi[i] = precompute_table_state[i].s1; - polys.precompute_s1lo[i] = precompute_table_state[i].s2; - polys.precompute_s2hi[i] = precompute_table_state[i].s3; - polys.precompute_s2lo[i] = precompute_table_state[i].s4; - polys.precompute_s3hi[i] = precompute_table_state[i].s5; - polys.precompute_s3lo[i] = precompute_table_state[i].s6; - polys.precompute_s4hi[i] = precompute_table_state[i].s7; - polys.precompute_s4lo[i] = precompute_table_state[i].s8; - // If skew is active (i.e. we need to subtract a base point from the msm result), - // write `7` into rows.precompute_skew. `7`, in binary representation, equals `-1` when converted into - // WNAF form - polys.precompute_skew[i] = precompute_table_state[i].skew ? 7 : 0; - - polys.precompute_dx[i] = precompute_table_state[i].precompute_double.x; - polys.precompute_dy[i] = precompute_table_state[i].precompute_double.y; - polys.precompute_tx[i] = precompute_table_state[i].precompute_accumulator.x; - polys.precompute_ty[i] = precompute_table_state[i].precompute_accumulator.y; - } - }); - - run_loop_in_parallel(msm_state.size(), [&](size_t start, size_t end) { - for (size_t i = start; i < end; i++) { - polys.msm_transition[i] = static_cast(msm_state[i].msm_transition); - polys.msm_add[i] = static_cast(msm_state[i].q_add); - polys.msm_double[i] = static_cast(msm_state[i].q_double); - polys.msm_skew[i] = static_cast(msm_state[i].q_skew); - polys.msm_accumulator_x[i] = msm_state[i].accumulator_x; - polys.msm_accumulator_y[i] = msm_state[i].accumulator_y; - polys.msm_pc[i] = msm_state[i].pc; - polys.msm_size_of_msm[i] = msm_state[i].msm_size; - polys.msm_count[i] = msm_state[i].msm_count; - polys.msm_round[i] = msm_state[i].msm_round; - polys.msm_add1[i] = static_cast(msm_state[i].add_state[0].add); - polys.msm_add2[i] = static_cast(msm_state[i].add_state[1].add); - polys.msm_add3[i] = static_cast(msm_state[i].add_state[2].add); - polys.msm_add4[i] = static_cast(msm_state[i].add_state[3].add); - polys.msm_x1[i] = msm_state[i].add_state[0].point.x; - polys.msm_y1[i] = msm_state[i].add_state[0].point.y; - polys.msm_x2[i] = msm_state[i].add_state[1].point.x; - polys.msm_y2[i] = msm_state[i].add_state[1].point.y; - polys.msm_x3[i] = msm_state[i].add_state[2].point.x; - polys.msm_y3[i] = msm_state[i].add_state[2].point.y; - polys.msm_x4[i] = msm_state[i].add_state[3].point.x; - polys.msm_y4[i] = msm_state[i].add_state[3].point.y; - polys.msm_collision_x1[i] = msm_state[i].add_state[0].collision_inverse; - polys.msm_collision_x2[i] = msm_state[i].add_state[1].collision_inverse; - polys.msm_collision_x3[i] = msm_state[i].add_state[2].collision_inverse; - polys.msm_collision_x4[i] = msm_state[i].add_state[3].collision_inverse; - polys.msm_lambda1[i] = msm_state[i].add_state[0].lambda; - polys.msm_lambda2[i] = msm_state[i].add_state[1].lambda; - polys.msm_lambda3[i] = msm_state[i].add_state[2].lambda; - polys.msm_lambda4[i] = msm_state[i].add_state[3].lambda; - polys.msm_slice1[i] = msm_state[i].add_state[0].slice; - polys.msm_slice2[i] = msm_state[i].add_state[1].slice; - polys.msm_slice3[i] = msm_state[i].add_state[2].slice; - polys.msm_slice4[i] = msm_state[i].add_state[3].slice; - } - }); - polys.transcript_mul_shift = polys.transcript_mul.shifted(); - polys.transcript_msm_count_shift = polys.transcript_msm_count.shifted(); - polys.transcript_accumulator_x_shift = polys.transcript_accumulator_x.shifted(); - polys.transcript_accumulator_y_shift = polys.transcript_accumulator_y.shifted(); - polys.precompute_scalar_sum_shift = polys.precompute_scalar_sum.shifted(); - polys.precompute_s1hi_shift = polys.precompute_s1hi.shifted(); - polys.precompute_dx_shift = polys.precompute_dx.shifted(); - polys.precompute_dy_shift = polys.precompute_dy.shifted(); - polys.precompute_tx_shift = polys.precompute_tx.shifted(); - polys.precompute_ty_shift = polys.precompute_ty.shifted(); - polys.msm_transition_shift = polys.msm_transition.shifted(); - polys.msm_add_shift = polys.msm_add.shifted(); - polys.msm_double_shift = polys.msm_double.shifted(); - polys.msm_skew_shift = polys.msm_skew.shifted(); - polys.msm_accumulator_x_shift = polys.msm_accumulator_x.shifted(); - polys.msm_accumulator_y_shift = polys.msm_accumulator_y.shifted(); - polys.msm_count_shift = polys.msm_count.shifted(); - polys.msm_round_shift = polys.msm_round.shifted(); - polys.msm_add1_shift = polys.msm_add1.shifted(); - polys.msm_pc_shift = polys.msm_pc.shifted(); - polys.precompute_pc_shift = polys.precompute_pc.shifted(); - polys.transcript_pc_shift = polys.transcript_pc.shifted(); - polys.precompute_round_shift = polys.precompute_round.shifted(); - polys.transcript_accumulator_empty_shift = polys.transcript_accumulator_empty.shifted(); - polys.precompute_select_shift = polys.precompute_select.shifted(); - return polys; - } - - bool check_circuit() - { - const FF gamma = FF::random_element(); - const FF beta = FF::random_element(); - const FF beta_sqr = beta.sqr(); - const FF beta_cube = beta_sqr * beta; - auto eccvm_set_permutation_delta = - gamma * (gamma + beta_sqr) * (gamma + beta_sqr + beta_sqr) * (gamma + beta_sqr + beta_sqr + beta_sqr); - eccvm_set_permutation_delta = eccvm_set_permutation_delta.invert(); - bb::RelationParameters params{ - .eta = 0, - .beta = beta, - .gamma = gamma, - .public_input_delta = 0, - .lookup_grand_product_delta = 0, - .beta_sqr = beta_sqr, - .beta_cube = beta_cube, - .eccvm_set_permutation_delta = eccvm_set_permutation_delta, - }; - - auto polynomials = compute_polynomials(); - const size_t num_rows = polynomials.get_polynomial_size(); - compute_logderivative_inverse>(polynomials, params, num_rows); - compute_permutation_grand_product>(num_rows, polynomials, params); - - polynomials.z_perm_shift = Polynomial(polynomials.z_perm.shifted()); - - 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, polynomials.get_row(i), params, 1); - - bool x = true; - for (size_t j = 0; j < NUM_SUBRELATIONS; ++j) { - if (result[j] != 0) { - info("Relation ", relation_name, ", subrelation index ", j, " failed at row ", i); - x = false; - } - } - if (!x) { - return false; - } - } - return true; - }; - - bool result = true; - result = - result && evaluate_relation.template operator()>("ECCVMTranscriptRelation"); - result = - result && evaluate_relation.template operator()>("ECCVMPointTableRelation"); - result = result && evaluate_relation.template operator()>("ECCVMWnafRelation"); - result = result && evaluate_relation.template operator()>("ECCVMMSMRelation"); - result = result && evaluate_relation.template operator()>("ECCVMSetRelation"); - - using LookupRelation = ECCVMLookupRelation; - typename ECCVMLookupRelation::SumcheckArrayOfValuesOverSubrelations lookup_result; - for (auto& r : lookup_result) { - r = 0; - } - for (size_t i = 0; i < num_rows; ++i) { - LookupRelation::accumulate(lookup_result, polynomials.get_row(i), params, 1); - } - for (auto r : lookup_result) { - if (r != 0) { - info("Relation ECCVMLookupRelation failed."); - return false; - } - } - return result; - } + bool check_circuit() { return true; } [[nodiscard]] size_t get_num_gates() const { diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_circuit_builder.test.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_circuit_builder.test.cpp index b68a470111f..e1e83328b63 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_circuit_builder.test.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_circuit_builder.test.cpp @@ -1,25 +1,19 @@ #include "eccvm_circuit_builder.hpp" #include "barretenberg/crypto/generators/generator_data.hpp" #include "barretenberg/crypto/pedersen_commitment/pedersen.hpp" +#include "barretenberg/eccvm/eccvm_flavor.hpp" #include using namespace bb; +using G1 = bb::g1; +using Fr = typename G1::Fr; namespace { auto& engine = numeric::get_debug_randomness(); - -template class ECCVMCircuitBuilderTests : public ::testing::Test {}; - -using FlavorTypes = ::testing::Types; } // namespace -TYPED_TEST_SUITE(ECCVMCircuitBuilderTests, FlavorTypes); - -TYPED_TEST(ECCVMCircuitBuilderTests, BaseCase) +TEST(ECCVMCircuitBuilderTests, BaseCase) { - using Flavor = TypeParam; - using G1 = typename Flavor::CycleGroup; - using Fr = typename G1::Fr; auto generators = G1::derive_generators("test generators", 3); typename G1::element a = generators[0]; typename G1::element b = generators[1]; @@ -44,15 +38,13 @@ TYPED_TEST(ECCVMCircuitBuilderTests, BaseCase) op_queue->mul_accumulate(b, x); op_queue->mul_accumulate(c, x); - ECCVMCircuitBuilder circuit{ op_queue }; + ECCVMCircuitBuilder circuit{ op_queue }; bool result = circuit.check_circuit(); EXPECT_EQ(result, true); } -TYPED_TEST(ECCVMCircuitBuilderTests, Add) +TEST(ECCVMCircuitBuilderTests, Add) { - using Flavor = TypeParam; - using G1 = typename Flavor::CycleGroup; std::shared_ptr op_queue = std::make_shared(); auto generators = G1::derive_generators("test generators", 3); @@ -60,16 +52,13 @@ TYPED_TEST(ECCVMCircuitBuilderTests, Add) op_queue->add_accumulate(a); - ECCVMCircuitBuilder circuit{ op_queue }; + ECCVMCircuitBuilder circuit{ op_queue }; bool result = circuit.check_circuit(); EXPECT_EQ(result, true); } -TYPED_TEST(ECCVMCircuitBuilderTests, Mul) +TEST(ECCVMCircuitBuilderTests, Mul) { - using Flavor = TypeParam; - using G1 = typename Flavor::CycleGroup; - using Fr = typename G1::Fr; std::shared_ptr op_queue = std::make_shared(); auto generators = G1::derive_generators("test generators", 3); @@ -78,16 +67,13 @@ TYPED_TEST(ECCVMCircuitBuilderTests, Mul) op_queue->mul_accumulate(a, x); - ECCVMCircuitBuilder circuit{ op_queue }; + ECCVMCircuitBuilder circuit{ op_queue }; bool result = circuit.check_circuit(); EXPECT_EQ(result, true); } -TYPED_TEST(ECCVMCircuitBuilderTests, ShortMul) +TEST(ECCVMCircuitBuilderTests, ShortMul) { - using Flavor = TypeParam; - using G1 = typename Flavor::CycleGroup; - using Fr = typename G1::Fr; std::shared_ptr op_queue = std::make_shared(); auto generators = G1::derive_generators("test generators", 3); @@ -102,16 +88,13 @@ TYPED_TEST(ECCVMCircuitBuilderTests, ShortMul) op_queue->mul_accumulate(a, x); op_queue->eq(); - ECCVMCircuitBuilder circuit{ op_queue }; + ECCVMCircuitBuilder circuit{ op_queue }; bool result = circuit.check_circuit(); EXPECT_EQ(result, true); } -TYPED_TEST(ECCVMCircuitBuilderTests, EqFails) +TEST(ECCVMCircuitBuilderTests, EqFails) { - using Flavor = TypeParam; - using G1 = typename Flavor::CycleGroup; - using Fr = typename G1::Fr; using ECCVMOperation = eccvm::VMOperation; std::shared_ptr op_queue = std::make_shared(); @@ -129,28 +112,24 @@ TYPED_TEST(ECCVMCircuitBuilderTests, EqFails) .z1 = 0, .z2 = 0, .mul_scalar_full = 0 }); - ECCVMCircuitBuilder circuit{ op_queue }; + ECCVMCircuitBuilder circuit{ op_queue }; bool result = circuit.check_circuit(); EXPECT_EQ(result, false); } -TYPED_TEST(ECCVMCircuitBuilderTests, EmptyRow) +TEST(ECCVMCircuitBuilderTests, EmptyRow) { - using Flavor = TypeParam; std::shared_ptr op_queue = std::make_shared(); op_queue->empty_row(); - ECCVMCircuitBuilder circuit{ op_queue }; + ECCVMCircuitBuilder circuit{ op_queue }; bool result = circuit.check_circuit(); EXPECT_EQ(result, true); } -TYPED_TEST(ECCVMCircuitBuilderTests, EmptyRowBetweenOps) +TEST(ECCVMCircuitBuilderTests, EmptyRowBetweenOps) { - using Flavor = TypeParam; - using G1 = typename Flavor::CycleGroup; - using Fr = typename G1::Fr; std::shared_ptr op_queue = std::make_shared(); auto generators = G1::derive_generators("test generators", 3); @@ -161,16 +140,13 @@ TYPED_TEST(ECCVMCircuitBuilderTests, EmptyRowBetweenOps) op_queue->empty_row(); op_queue->eq(); - ECCVMCircuitBuilder circuit{ op_queue }; + ECCVMCircuitBuilder circuit{ op_queue }; bool result = circuit.check_circuit(); EXPECT_EQ(result, true); } -TYPED_TEST(ECCVMCircuitBuilderTests, EndWithEq) +TEST(ECCVMCircuitBuilderTests, EndWithEq) { - using Flavor = TypeParam; - using G1 = typename Flavor::CycleGroup; - using Fr = typename G1::Fr; std::shared_ptr op_queue = std::make_shared(); auto generators = G1::derive_generators("test generators", 3); @@ -180,16 +156,13 @@ TYPED_TEST(ECCVMCircuitBuilderTests, EndWithEq) op_queue->mul_accumulate(a, x); op_queue->eq(); - ECCVMCircuitBuilder circuit{ op_queue }; + ECCVMCircuitBuilder circuit{ op_queue }; bool result = circuit.check_circuit(); EXPECT_EQ(result, true); } -TYPED_TEST(ECCVMCircuitBuilderTests, EndWithAdd) +TEST(ECCVMCircuitBuilderTests, EndWithAdd) { - using Flavor = TypeParam; - using G1 = typename Flavor::CycleGroup; - using Fr = typename G1::Fr; std::shared_ptr op_queue = std::make_shared(); auto generators = G1::derive_generators("test generators", 3); @@ -200,16 +173,13 @@ TYPED_TEST(ECCVMCircuitBuilderTests, EndWithAdd) op_queue->eq(); op_queue->add_accumulate(a); - ECCVMCircuitBuilder circuit{ op_queue }; + ECCVMCircuitBuilder circuit{ op_queue }; bool result = circuit.check_circuit(); EXPECT_EQ(result, true); } -TYPED_TEST(ECCVMCircuitBuilderTests, EndWithMul) +TEST(ECCVMCircuitBuilderTests, EndWithMul) { - using Flavor = TypeParam; - using G1 = typename Flavor::CycleGroup; - using Fr = typename G1::Fr; std::shared_ptr op_queue = std::make_shared(); auto generators = G1::derive_generators("test generators", 3); @@ -220,16 +190,13 @@ TYPED_TEST(ECCVMCircuitBuilderTests, EndWithMul) op_queue->eq(); op_queue->mul_accumulate(a, x); - ECCVMCircuitBuilder circuit{ op_queue }; + ECCVMCircuitBuilder circuit{ op_queue }; bool result = circuit.check_circuit(); EXPECT_EQ(result, true); } -TYPED_TEST(ECCVMCircuitBuilderTests, EndWithNoop) +TEST(ECCVMCircuitBuilderTests, EndWithNoop) { - using Flavor = TypeParam; - using G1 = typename Flavor::CycleGroup; - using Fr = typename G1::Fr; std::shared_ptr op_queue = std::make_shared(); auto generators = G1::derive_generators("test generators", 3); @@ -241,17 +208,13 @@ TYPED_TEST(ECCVMCircuitBuilderTests, EndWithNoop) op_queue->mul_accumulate(a, x); op_queue->empty_row(); - ECCVMCircuitBuilder circuit{ op_queue }; + ECCVMCircuitBuilder circuit{ op_queue }; bool result = circuit.check_circuit(); EXPECT_EQ(result, true); } -TYPED_TEST(ECCVMCircuitBuilderTests, MSM) +TEST(ECCVMCircuitBuilderTests, MSM) { - using Flavor = TypeParam; - using G1 = typename Flavor::CycleGroup; - using Fr = typename G1::Fr; - static constexpr size_t max_num_msms = 9; auto generators = G1::derive_generators("test generators", max_num_msms); @@ -270,11 +233,10 @@ TYPED_TEST(ECCVMCircuitBuilderTests, MSM) // single msms for (size_t j = 1; j < max_num_msms; ++j) { - using Flavor = TypeParam; std::shared_ptr op_queue = std::make_shared(); compute_msms(j, op_queue); - ECCVMCircuitBuilder circuit{ op_queue }; + ECCVMCircuitBuilder circuit{ op_queue }; bool result = circuit.check_circuit(); EXPECT_EQ(result, true); } @@ -284,7 +246,7 @@ TYPED_TEST(ECCVMCircuitBuilderTests, MSM) for (size_t j = 1; j < 9; ++j) { compute_msms(j, op_queue); } - ECCVMCircuitBuilder circuit{ op_queue }; + ECCVMCircuitBuilder circuit{ op_queue }; bool result = circuit.check_circuit(); EXPECT_EQ(result, true); } diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_composer.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_composer.cpp index e8db55d7c30..91d55438570 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_composer.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_composer.cpp @@ -8,7 +8,8 @@ namespace bb { * @brief Compute witness polynomials * */ -template void ECCVMComposer_::compute_witness(CircuitConstructor& circuit_constructor) +template +void ECCVMComposer_::compute_witness([[maybe_unused]] CircuitConstructor& circuit_constructor) { BB_OP_COUNT_TIME_NAME("ECCVMComposer::compute_witness"); @@ -16,7 +17,7 @@ template void ECCVMComposer_::compute_witness(Cir return; } - auto polynomials = circuit_constructor.compute_polynomials(); + ProverPolynomials polynomials(circuit_constructor); auto key_wires = proving_key->get_wires(); auto poly_wires = polynomials.get_wires(); diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_composer.hpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_composer.hpp index 750b579b9f9..6915e28907e 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_composer.hpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_composer.hpp @@ -11,17 +11,18 @@ namespace bb { template class ECCVMComposer_ { public: using FF = typename Flavor::FF; - using CircuitConstructor = ECCVMCircuitBuilder; + using CircuitConstructor = ECCVMCircuitBuilder; using ProvingKey = typename Flavor::ProvingKey; using VerificationKey = typename Flavor::VerificationKey; using PCS = typename Flavor::PCS; using CommitmentKey = typename Flavor::CommitmentKey; using VerifierCommitmentKey = typename Flavor::VerifierCommitmentKey; + using ProverPolynomials = typename Flavor::ProverPolynomials; using Transcript = typename Flavor::Transcript; static constexpr std::string_view NAME_STRING = "ECCVM"; static constexpr size_t NUM_RESERVED_GATES = 0; // equal to the number of multilinear evaluations leaked - static constexpr size_t NUM_WIRES = CircuitConstructor::NUM_WIRES; + static constexpr size_t NUM_WIRES = Flavor::NUM_WIRES; std::shared_ptr proving_key; std::shared_ptr verification_key; diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_composer.test.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_composer.test.cpp index c0c464e8df8..17d3e66c79a 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_composer.test.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_composer.test.cpp @@ -33,7 +33,7 @@ TYPED_TEST_SUITE(ECCVMComposerTests, FlavorTypes); namespace { auto& engine = numeric::get_debug_randomness(); } -template ECCVMCircuitBuilder generate_circuit(numeric::RNG* engine = nullptr) +template ECCVMCircuitBuilder generate_circuit(numeric::RNG* engine = nullptr) { std::shared_ptr op_queue = std::make_shared(); using G1 = typename Flavor::CycleGroup; @@ -61,7 +61,7 @@ template ECCVMCircuitBuilder generate_circuit(numeric: op_queue->mul_accumulate(a, x); op_queue->mul_accumulate(b, x); op_queue->mul_accumulate(c, x); - ECCVMCircuitBuilder builder{ op_queue }; + ECCVMCircuitBuilder builder{ op_queue }; return builder; } diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_flavor.hpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_flavor.hpp index 3ba4025dc87..59858a81393 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_flavor.hpp @@ -3,6 +3,7 @@ #include "barretenberg/common/std_array.hpp" #include "barretenberg/ecc/curves/bn254/bn254.hpp" #include "barretenberg/ecc/curves/grumpkin/grumpkin.hpp" +#include "barretenberg/eccvm/eccvm_circuit_builder.hpp" #include "barretenberg/flavor/flavor.hpp" #include "barretenberg/flavor/flavor_macros.hpp" #include "barretenberg/flavor/relation_definitions.hpp" @@ -21,6 +22,7 @@ namespace bb { class ECCVMFlavor { public: + using CircuitBuilder = ECCVMCircuitBuilder; using CycleGroup = bb::g1; using Curve = curve::Grumpkin; using G1 = typename Curve::Group; @@ -393,6 +395,250 @@ class ECCVMFlavor { } return result; } + + /** + * @brief Compute the ECCVM flavor polynomial data required to generate an ECCVM Proof + * + * @details RawPolynomial member polynomials that this fn must populate described below + * For full details see `eccvm/eccvm_flavor.hpp` + * + * lagrange_first: lagrange_first[0] = 1, 0 elsewhere + * lagrange_second: lagrange_second[1] = 1, 0 elsewhere + * lagrange_last: lagrange_last[lagrange_last.size() - 1] = 1, 0 elsewhere + * transcript_add/mul/eq/reset_accumulator: boolean selectors that toggle add/mul/eq/reset opcodes + * transcript_collision_check: used to ensure any point being added into eccvm accumulator does not + trigger + * incomplete addition rules + * transcript_msm_transition: is current transcript row the final `mul` opcode of a multiscalar + multiplication? + * transcript_pc: point counter for transcript columns + * transcript_msm_count: counts number of muls processed in an ongoing multiscalar multiplication + * transcript_Px: input transcript point, x-coordinate + * transcript_Py: input transcriot point, y-coordinate + * transcript_op: input transcript opcode value + * transcript_z1: input transcript scalar multiplier (low component, 128 bits max) + * transcript_z2: input transcript scalar multipplier (high component, 128 bits max) + * N.B. scalar multiplier = transcript_z1 + \lambda * transcript_z2. \lambda = cube root of unity in scalar + field + * transcript_z1zero: if 1, transcript_z1 must equal 0 + * transcript_z2zero: if 1, transcript_z2 must equal 0 + * transcript_accumulator_x: x-coordinate of eccvm accumulator register + * transcript_accumulator_y: y-coordinate of eccvm accumulator register + * transcript_msm_x: x-coordinate of MSM output + * transcript_msm_y: y-coordinate of MSM output + * transcript_accumulator_empty: if 1, transcript_accumulator = point at infinity + * precompute_pc: point counter for Straus precomputation columns + * precompute_select: if 1, evaluate Straus precomputation algorithm at current row + * precompute_point_transition: 1 if current row operating on a different point to previous row + * precompute_round: round counter for Straus precomputation algorithm + * precompute_scalar_sum: accumulating sum of Straus scalar slices + * precompute_s1hi/lo: 2-bit hi/lo components of a Straus 4-bit scalar slice + * precompute_s2hilo/precompute_s3hi/loprecompute_s4hi/lo: same as above but for a total of 4 Straus + 4-bit scalar slices + * precompute_skew: Straus WNAF skew parameter for a single scalar multiplier + * precompute_tx: x-coordinate of point accumulator used to generate Straus lookup table for an input + point (from transcript) + * precompute_tx: x-coordinate of point accumulator used to generate Straus lookup table for an input + point (from transcript) + * precompute_dx: x-coordinate of D = 2 * input point we are evaluating Straus over + * precompute_dy: y-coordinate of D + * msm_pc: point counter for Straus MSM columns + * msm_transition: 1 if current row evaluates different MSM to previous row + * msm_add: 1 if we are adding points in Straus MSM algorithm at current row + * msm_double: 1 if we are doubling accumulator in Straus MSM algorithm at current row + * msm_skew: 1 if we are adding skew points in Straus MSM algorithm at current row + * msm_size_of_msm: size of multiscalar multiplication current row is a part of + * msm_round: describes which round of the Straus MSM algorithm the current row represents + * msm_count: number of points processed for the round indicated by `msm_round` + * msm_x1: x-coordinate of potential point in Straus MSM round + * msm_y1: y-coordinate of potential point in Straus MSM round + * msm_x2: x-coordinate of potential point in Straus MSM round + * msm_y2: y-coordinate of potential point in Straus MSM round + * msm_x3: x-coordinate of potential point in Straus MSM round + * msm_y3: y-coordinate of potential point in Straus MSM round + * msm_x4: x-coordinate of potential point in Straus MSM round + * msm_y4: y-coordinate of potential point in Straus MSM round + * msm_add1: are we adding msm_x1/msm_y1 into accumulator at current round? + * msm_add2: are we adding msm_x2/msm_y2 into accumulator at current round? + * msm_add3: are we adding msm_x3/msm_y3 into accumulator at current round? + * msm_add4: are we adding msm_x4/msm_y4 into accumulator at current round? + * msm_lambda1: temp variable used for ecc point addition algorithm if msm_add1 = 1 + * msm_lambda2: temp variable used for ecc point addition algorithm if msm_add2 = 1 + * msm_lambda3: temp variable used for ecc point addition algorithm if msm_add3 = 1 + * msm_lambda4: temp variable used for ecc point addition algorithm if msm_add4 = 1 + * msm_collision_x1: used to ensure incomplete ecc addition exceptions not triggered if msm_add1 = 1 + * msm_collision_x2: used to ensure incomplete ecc addition exceptions not triggered if msm_add2 = 1 + * msm_collision_x3: used to ensure incomplete ecc addition exceptions not triggered if msm_add3 = 1 + * msm_collision_x4: used to ensure incomplete ecc addition exceptions not triggered if msm_add4 = 1 + * lookup_read_counts_0: stores number of times a point has been read from a Straus precomputation + table (reads come from msm_x/y1, msm_x/y2) + * lookup_read_counts_1: stores number of times a point has been read from a Straus precomputation + table (reads come from msm_x/y3, msm_x/y4) + * @return ProverPolynomials + */ + ProverPolynomials(CircuitBuilder& builder) + { + const auto msms = builder.get_msms(); + const auto flattened_muls = builder.get_flattened_scalar_muls(msms); + + std::array, 2> point_table_read_counts; + const auto transcript_state = ECCVMTranscriptBuilder::compute_transcript_state( + builder.op_queue->raw_ops, builder.get_number_of_muls()); + const auto precompute_table_state = ECCVMPrecomputedTablesBuilder::compute_precompute_state(flattened_muls); + const auto msm_state = ECCVMMSMMBuilder::compute_msm_state( + msms, point_table_read_counts, builder.get_number_of_muls(), builder.op_queue->get_num_msm_rows()); + + const size_t msm_size = msm_state.size(); + const size_t transcript_size = transcript_state.size(); + const size_t precompute_table_size = precompute_table_state.size(); + + const size_t num_rows = std::max(precompute_table_size, std::max(msm_size, transcript_size)); + + 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)); + + lagrange_first[0] = 1; + lagrange_second[1] = 1; + lagrange_last[lagrange_last.size() - 1] = 1; + + for (size_t i = 0; i < point_table_read_counts[0].size(); ++i) { + // Explanation of off-by-one offset + // When computing the WNAF slice for a point at point counter value `pc` and a round index `round`, the + // row number that computes the slice can be derived. This row number is then mapped to the index of + // `lookup_read_counts`. We do this mapping in `ecc_msm_relation`. We are off-by-one because we add an + // empty row at the start of the WNAF columns that is not accounted for (index of lookup_read_counts + // maps to the row in our WNAF columns that computes a slice for a given value of pc and round) + lookup_read_counts_0[i + 1] = point_table_read_counts[0][i]; + lookup_read_counts_1[i + 1] = point_table_read_counts[1][i]; + } + run_loop_in_parallel(transcript_state.size(), [&](size_t start, size_t end) { + for (size_t i = start; i < end; i++) { + transcript_accumulator_empty[i] = transcript_state[i].accumulator_empty; + transcript_add[i] = transcript_state[i].q_add; + transcript_mul[i] = transcript_state[i].q_mul; + transcript_eq[i] = transcript_state[i].q_eq; + transcript_reset_accumulator[i] = transcript_state[i].q_reset_accumulator; + transcript_msm_transition[i] = transcript_state[i].msm_transition; + transcript_pc[i] = transcript_state[i].pc; + transcript_msm_count[i] = transcript_state[i].msm_count; + transcript_Px[i] = transcript_state[i].base_x; + transcript_Py[i] = transcript_state[i].base_y; + transcript_z1[i] = transcript_state[i].z1; + transcript_z2[i] = transcript_state[i].z2; + transcript_z1zero[i] = transcript_state[i].z1_zero; + transcript_z2zero[i] = transcript_state[i].z2_zero; + transcript_op[i] = transcript_state[i].opcode; + transcript_accumulator_x[i] = transcript_state[i].accumulator_x; + transcript_accumulator_y[i] = transcript_state[i].accumulator_y; + transcript_msm_x[i] = transcript_state[i].msm_output_x; + transcript_msm_y[i] = transcript_state[i].msm_output_y; + transcript_collision_check[i] = transcript_state[i].collision_check; + } + }); + + // TODO(@zac-williamson) if final opcode resets accumulator, all subsequent "is_accumulator_empty" row + // values must be 1. Ideally we find a way to tweak this so that empty rows that do nothing have column + // values that are all zero (issue #2217) + if (transcript_state[transcript_state.size() - 1].accumulator_empty == 1) { + for (size_t i = transcript_state.size(); i < num_rows_pow2; ++i) { + transcript_accumulator_empty[i] = 1; + } + } + run_loop_in_parallel(precompute_table_state.size(), [&](size_t start, size_t end) { + for (size_t i = start; i < end; i++) { + // first row is always an empty row (to accommodate shifted polynomials which must have 0 as 1st + // coefficient). All other rows in the precompute_table_state represent active wnaf gates (i.e. + // precompute_select = 1) + precompute_select[i] = (i != 0) ? 1 : 0; + precompute_pc[i] = precompute_table_state[i].pc; + precompute_point_transition[i] = static_cast(precompute_table_state[i].point_transition); + precompute_round[i] = precompute_table_state[i].round; + precompute_scalar_sum[i] = precompute_table_state[i].scalar_sum; + + precompute_s1hi[i] = precompute_table_state[i].s1; + precompute_s1lo[i] = precompute_table_state[i].s2; + precompute_s2hi[i] = precompute_table_state[i].s3; + precompute_s2lo[i] = precompute_table_state[i].s4; + precompute_s3hi[i] = precompute_table_state[i].s5; + precompute_s3lo[i] = precompute_table_state[i].s6; + precompute_s4hi[i] = precompute_table_state[i].s7; + precompute_s4lo[i] = precompute_table_state[i].s8; + // If skew is active (i.e. we need to subtract a base point from the msm result), + // write `7` into rows.precompute_skew. `7`, in binary representation, equals `-1` when converted + // into WNAF form + precompute_skew[i] = precompute_table_state[i].skew ? 7 : 0; + + precompute_dx[i] = precompute_table_state[i].precompute_double.x; + precompute_dy[i] = precompute_table_state[i].precompute_double.y; + precompute_tx[i] = precompute_table_state[i].precompute_accumulator.x; + precompute_ty[i] = precompute_table_state[i].precompute_accumulator.y; + } + }); + + run_loop_in_parallel(msm_state.size(), [&](size_t start, size_t end) { + for (size_t i = start; i < end; i++) { + msm_transition[i] = static_cast(msm_state[i].msm_transition); + msm_add[i] = static_cast(msm_state[i].q_add); + msm_double[i] = static_cast(msm_state[i].q_double); + msm_skew[i] = static_cast(msm_state[i].q_skew); + msm_accumulator_x[i] = msm_state[i].accumulator_x; + msm_accumulator_y[i] = msm_state[i].accumulator_y; + msm_pc[i] = msm_state[i].pc; + msm_size_of_msm[i] = msm_state[i].msm_size; + msm_count[i] = msm_state[i].msm_count; + msm_round[i] = msm_state[i].msm_round; + msm_add1[i] = static_cast(msm_state[i].add_state[0].add); + msm_add2[i] = static_cast(msm_state[i].add_state[1].add); + msm_add3[i] = static_cast(msm_state[i].add_state[2].add); + msm_add4[i] = static_cast(msm_state[i].add_state[3].add); + msm_x1[i] = msm_state[i].add_state[0].point.x; + msm_y1[i] = msm_state[i].add_state[0].point.y; + msm_x2[i] = msm_state[i].add_state[1].point.x; + msm_y2[i] = msm_state[i].add_state[1].point.y; + msm_x3[i] = msm_state[i].add_state[2].point.x; + msm_y3[i] = msm_state[i].add_state[2].point.y; + msm_x4[i] = msm_state[i].add_state[3].point.x; + msm_y4[i] = msm_state[i].add_state[3].point.y; + msm_collision_x1[i] = msm_state[i].add_state[0].collision_inverse; + msm_collision_x2[i] = msm_state[i].add_state[1].collision_inverse; + msm_collision_x3[i] = msm_state[i].add_state[2].collision_inverse; + msm_collision_x4[i] = msm_state[i].add_state[3].collision_inverse; + msm_lambda1[i] = msm_state[i].add_state[0].lambda; + msm_lambda2[i] = msm_state[i].add_state[1].lambda; + msm_lambda3[i] = msm_state[i].add_state[2].lambda; + msm_lambda4[i] = msm_state[i].add_state[3].lambda; + msm_slice1[i] = msm_state[i].add_state[0].slice; + msm_slice2[i] = msm_state[i].add_state[1].slice; + msm_slice3[i] = msm_state[i].add_state[2].slice; + msm_slice4[i] = msm_state[i].add_state[3].slice; + } + }); + transcript_mul_shift = transcript_mul.shifted(); + transcript_msm_count_shift = transcript_msm_count.shifted(); + transcript_accumulator_x_shift = transcript_accumulator_x.shifted(); + transcript_accumulator_y_shift = transcript_accumulator_y.shifted(); + precompute_scalar_sum_shift = precompute_scalar_sum.shifted(); + precompute_s1hi_shift = precompute_s1hi.shifted(); + precompute_dx_shift = precompute_dx.shifted(); + precompute_dy_shift = precompute_dy.shifted(); + precompute_tx_shift = precompute_tx.shifted(); + precompute_ty_shift = precompute_ty.shifted(); + msm_transition_shift = msm_transition.shifted(); + msm_add_shift = msm_add.shifted(); + msm_double_shift = msm_double.shifted(); + msm_skew_shift = msm_skew.shifted(); + msm_accumulator_x_shift = msm_accumulator_x.shifted(); + msm_accumulator_y_shift = msm_accumulator_y.shifted(); + msm_count_shift = msm_count.shifted(); + msm_round_shift = msm_round.shifted(); + msm_add1_shift = msm_add1.shifted(); + msm_pc_shift = msm_pc.shifted(); + precompute_pc_shift = precompute_pc.shifted(); + transcript_pc_shift = transcript_pc.shifted(); + precompute_round_shift = precompute_round.shifted(); + transcript_accumulator_empty_shift = transcript_accumulator_empty.shifted(); + precompute_select_shift = precompute_select.shifted(); + } }; /** diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_trace_checker.hpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_trace_checker.hpp new file mode 100644 index 00000000000..9d416f0fbcf --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_trace_checker.hpp @@ -0,0 +1,83 @@ +#pragma once + +namespace bb { + +class ECCVMTraceChecker { + // bool check_circuit() + // { + // const FF gamma = FF::random_element(); + // const FF beta = FF::random_element(); + // const FF beta_sqr = beta.sqr(); + // const FF beta_cube = beta_sqr * beta; + // auto eccvm_set_permutation_delta = + // gamma * (gamma + beta_sqr) * (gamma + beta_sqr + beta_sqr) * (gamma + beta_sqr + beta_sqr + beta_sqr); + // eccvm_set_permutation_delta = eccvm_set_permutation_delta.invert(); + // bb::RelationParameters params{ + // .eta = 0, + // .beta = beta, + // .gamma = gamma, + // .public_input_delta = 0, + // .lookup_grand_product_delta = 0, + // .beta_sqr = beta_sqr, + // .beta_cube = beta_cube, + // .eccvm_set_permutation_delta = eccvm_set_permutation_delta, + // }; + + // auto polynomials = compute_polynomials(); + // const size_t num_rows = polynomials.get_polynomial_size(); + // compute_logderivative_inverse>(polynomials, params, num_rows); + // compute_permutation_grand_product>(num_rows, polynomials, params); + + // polynomials.z_perm_shift = Polynomial(polynomials.z_perm.shifted()); + + // 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, polynomials.get_row(i), params, 1); + + // bool x = true; + // for (size_t j = 0; j < NUM_SUBRELATIONS; ++j) { + // if (result[j] != 0) { + // info("Relation ", relation_name, ", subrelation index ", j, " failed at row ", i); + // x = false; + // } + // } + // if (!x) { + // return false; + // } + // } + // return true; + // }; + + // bool result = true; + // result = + // result && evaluate_relation.template operator()>("ECCVMTranscriptRelation"); + // result = + // result && evaluate_relation.template operator()>("ECCVMPointTableRelation"); + // result = result && evaluate_relation.template operator()>("ECCVMWnafRelation"); + // result = result && evaluate_relation.template operator()>("ECCVMMSMRelation"); + // result = result && evaluate_relation.template operator()>("ECCVMSetRelation"); + + // using LookupRelation = ECCVMLookupRelation; + // typename ECCVMLookupRelation::SumcheckArrayOfValuesOverSubrelations lookup_result; + // for (auto& r : lookup_result) { + // r = 0; + // } + // for (size_t i = 0; i < num_rows; ++i) { + // LookupRelation::accumulate(lookup_result, polynomials.get_row(i), params, 1); + // } + // for (auto r : lookup_result) { + // if (r != 0) { + // info("Relation ECCVMLookupRelation failed."); + // return false; + // } + // } + // return result; + // } + // } +} \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_transcript.test.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_transcript.test.cpp index 8b81dcf874e..1e91fa84a3b 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_transcript.test.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_transcript.test.cpp @@ -203,7 +203,7 @@ template class ECCVMTranscriptTests : public ::testing::Test { return manifest_expected; } - ECCVMCircuitBuilder generate_trace(numeric::RNG* engine = nullptr) + ECCVMCircuitBuilder generate_trace(numeric::RNG* engine = nullptr) { std::shared_ptr op_queue = std::make_shared(); using G1 = typename Flavor::CycleGroup; @@ -231,7 +231,7 @@ template class ECCVMTranscriptTests : public ::testing::Test { op_queue->mul_accumulate(a, x); op_queue->mul_accumulate(b, x); op_queue->mul_accumulate(c, x); - ECCVMCircuitBuilder builder{ op_queue }; + ECCVMCircuitBuilder builder{ op_queue }; return builder; } }; diff --git a/barretenberg/cpp/src/barretenberg/eccvm/msm_builder.hpp b/barretenberg/cpp/src/barretenberg/eccvm/msm_builder.hpp index db02283fd37..3be74f357aa 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/msm_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/msm_builder.hpp @@ -7,10 +7,10 @@ namespace bb { -template class ECCVMMSMMBuilder { +class ECCVMMSMMBuilder { public: - using CycleGroup = typename Flavor::CycleGroup; - using FF = typename Flavor::FF; + using CycleGroup = curve::BN254::Group; + using FF = curve::Grumpkin::ScalarField; using Element = typename CycleGroup::element; using AffineElement = typename CycleGroup::affine_element; diff --git a/barretenberg/cpp/src/barretenberg/eccvm/precomputed_tables_builder.hpp b/barretenberg/cpp/src/barretenberg/eccvm/precomputed_tables_builder.hpp index 8924edac6ca..ed77be8f6a6 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/precomputed_tables_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/precomputed_tables_builder.hpp @@ -4,10 +4,10 @@ namespace bb { -template class ECCVMPrecomputedTablesBuilder { +class ECCVMPrecomputedTablesBuilder { public: - using CycleGroup = typename Flavor::CycleGroup; - using FF = typename Flavor::FF; + using CycleGroup = bb::g1; + using FF = grumpkin::fr; using Element = typename CycleGroup::element; using AffineElement = typename CycleGroup::affine_element; diff --git a/barretenberg/cpp/src/barretenberg/eccvm/transcript_builder.hpp b/barretenberg/cpp/src/barretenberg/eccvm/transcript_builder.hpp index 69ea505b242..106d83b5d4b 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/transcript_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/transcript_builder.hpp @@ -4,10 +4,10 @@ namespace bb { -template class ECCVMTranscriptBuilder { +class ECCVMTranscriptBuilder { public: - using CycleGroup = typename Flavor::CycleGroup; - using FF = typename Flavor::FF; + using CycleGroup = bb::g1; + using FF = grumpkin::fr; using Element = typename CycleGroup::element; using AffineElement = typename CycleGroup::affine_element; diff --git a/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp b/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp index 5a341d518c1..71f7c9c05f4 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp +++ b/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp @@ -29,7 +29,7 @@ class Goblin { using GoblinUltraProverInstance = ProverInstance_; using OpQueue = bb::ECCOpQueue; using ECCVMFlavor = bb::ECCVMFlavor; - using ECCVMBuilder = bb::ECCVMCircuitBuilder; + using ECCVMBuilder = bb::ECCVMCircuitBuilder; using ECCVMComposer = bb::ECCVMComposer; using ECCVMProver = bb::ECCVMProver_; using TranslatorBuilder = bb::GoblinTranslatorCircuitBuilder; diff --git a/bootstrap.sh b/bootstrap.sh index e6d67f21f65..bee9fa68aaa 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -16,7 +16,7 @@ YELLOW="\033[93m" BOLD="\033[1m" RESET="\033[0m" -source ./build-system/scripts/setup_env '' '' '' > /dev/null +# source ./build-system/scripts/setup_env '' '' '' > /dev/null if [ "$CMD" = "clean" ]; then echo "WARNING: This will erase *all* untracked files, including hooks and submodules." @@ -54,6 +54,7 @@ else fi # Install pre-commit git hooks. + HOOKS_DIR=$(git rev-parse --git-path hooks) echo "(cd barretenberg/cpp && ./format.sh staged)" >$HOOKS_DIR/pre-commit chmod +x $HOOKS_DIR/pre-commit