Skip to content

Commit

Permalink
Prover constructs sumcheck (#61)
Browse files Browse the repository at this point in the history
* Hack poly mfst to get multivariates from pk.
* d is not a template param
* Prover executes sumcheck.
* Address some comments from Luke.
  • Loading branch information
codygunton authored Jan 17, 2023
1 parent d126e58 commit ed5eecf
Show file tree
Hide file tree
Showing 20 changed files with 259 additions and 111 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ inline std::vector<std::string> standard_selector_names()
class StandardCircuitConstructor : public CircuitConstructorBase<STANDARD_HONK_WIDTH> {
public:
// TODO: replace this with Honk enums after we have a verifier and no longer depend on plonk prover/verifier
static constexpr waffle::ComposerType type = waffle::ComposerType::STANDARD;
static constexpr waffle::ComposerType type = waffle::ComposerType::STANDARD_HONK;
static constexpr size_t UINT_LOG2_BASE = 2;

// These are variables that we have used a gate on, to enforce that they are
Expand Down
10 changes: 7 additions & 3 deletions cpp/src/aztec/honk/composer/composer_helper/composer_helper.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "composer_helper.hpp"
#include "polynomials/polynomial.hpp"
#include <cstddef>
#include <proof_system/flavor/flavor.hpp>
#include <honk/pcs/commitment_key.hpp>
Expand Down Expand Up @@ -42,8 +43,8 @@ std::shared_ptr<waffle::proving_key> ComposerHelper<CircuitConstructor>::compute

// Initialize circuit_proving_key
// TODO: replace composer types.
circuit_proving_key =
std::make_shared<waffle::proving_key>(subgroup_size, public_inputs.size(), crs, waffle::ComposerType::STANDARD);
circuit_proving_key = std::make_shared<waffle::proving_key>(
subgroup_size, public_inputs.size(), crs, waffle::ComposerType::STANDARD_HONK);

for (size_t i = 0; i < constructor.num_selectors; ++i) {
std::vector<barretenberg::fr>& selector_values = selectors[i];
Expand Down Expand Up @@ -224,7 +225,7 @@ std::shared_ptr<waffle::proving_key> ComposerHelper<CircuitConstructor>::compute
return circuit_proving_key;
}
// Compute q_l, q_r, q_o, etc polynomials
ComposerHelper::compute_proving_key_base(circuit_constructor, waffle::ComposerType::STANDARD);
ComposerHelper::compute_proving_key_base(circuit_constructor, waffle::ComposerType::STANDARD_HONK);

// Compute sigma polynomials (we should update that late)
compute_standard_honk_sigma_permutations<CircuitConstructor::program_width>(circuit_constructor,
Expand All @@ -233,6 +234,9 @@ std::shared_ptr<waffle::proving_key> ComposerHelper<CircuitConstructor>::compute

compute_first_and_last_lagrange_polynomials(circuit_proving_key.get());

// TODO(Cody): this is a workaround
circuit_proving_key->polynomial_cache.put("z_perm", Polynomial<barretenberg::fr>(1));

return circuit_proving_key;
}

Expand Down
2 changes: 1 addition & 1 deletion cpp/src/aztec/honk/composer/standard_honk_composer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ namespace honk {
*/
class StandardHonkComposer {
public:
static constexpr waffle::ComposerType type = waffle::ComposerType::STANDARD;
static constexpr waffle::ComposerType type = waffle::ComposerType::STANDARD_HONK;

static constexpr size_t UINT_LOG2_BASE = 2;
// An instantiation of the circuit constructor that only depends on arithmetization, not on the proof system
Expand Down
6 changes: 4 additions & 2 deletions cpp/src/aztec/honk/composer/standard_honk_composer.test.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
#include "standard_honk_composer.hpp"
#include "numeric/uint256/uint256.hpp"
#include "plonk/proof_system/types/polynomial_manifest.hpp"
#include <cstdint>
#include <honk/proof_system/prover.hpp>

#include <honk/sumcheck/polynomials/multivariates.hpp>
#include <gtest/gtest.h>

using namespace honk;
Expand Down Expand Up @@ -264,7 +265,8 @@ TEST(StandarHonkComposer, BaseCase)

auto prover = composer.create_unrolled_prover();
// waffle::Verifier verifier = composer.create_verifier();

auto multivariates = honk::sumcheck::Multivariates<fr, waffle::STANDARD_HONK_MANIFEST_SIZE>(prover.proving_key);
(void)multivariates;
waffle::plonk_proof proof = prover.construct_proof();

// bool result = verifier.verify_proof(proof); // instance, prover.reference_string.SRS_T2);
Expand Down
63 changes: 39 additions & 24 deletions cpp/src/aztec/honk/proof_system/prover.cpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
#include "prover.hpp"
// #include <honk/sumcheck/sumcheck.hpp> // will need
#include <honk/sumcheck/sumcheck.hpp> // will need
#include <array>
#include <honk/sumcheck/polynomials/univariate.hpp> // will go away
#include <honk/pcs/commitment_key.hpp>
#include <vector>
#include "ecc/curves/bn254/fr.hpp"
#include "ecc/curves/bn254/g1.hpp"
#include <honk/sumcheck/polynomials/multivariates.hpp>
#include <honk/sumcheck/relations/arithmetic_relation.hpp>
#include <honk/sumcheck/relations/grand_product_computation_relation.hpp>
#include <honk/sumcheck/relations/grand_product_initialization_relation.hpp>
#include "plonk/proof_system/types/polynomial_manifest.hpp"
#include "proof_system/flavor/flavor.hpp"
#include "transcript/transcript_wrappers.hpp"

namespace honk {

Expand Down Expand Up @@ -273,32 +280,40 @@ template <typename settings> void Prover<settings>::execute_relation_check_round
{
// queue.flush_queue(); // NOTE: Don't remove; we may reinstate the queue

using Multivariates = sumcheck::Multivariates<barretenberg::fr, waffle::STANDARD_HONK_MANIFEST_SIZE>;
using Transcript = transcript::StandardTranscript;
using Sumcheck = sumcheck::Sumcheck<Multivariates,
Transcript,
sumcheck::ArithmeticRelation,
sumcheck::GrandProductComputationRelation,
sumcheck::GrandProductInitializationRelation>;

// Compute alpha challenge
transcript.apply_fiat_shamir("alpha");

// TODO(luke): Run Sumcheck. For now, mock univariates.
for (size_t round_idx = 0; round_idx < proving_key->log_n; round_idx++) {
honk::sumcheck::Univariate<barretenberg::fr, honk::StandardHonk::MAX_RELATION_LENGTH> round_univariate;
for (auto eval : round_univariate.evaluations) {
eval = round_idx;
}
transcript.add_element("univariate_" + std::to_string(proving_key->log_n - round_idx),
round_univariate.to_buffer());
transcript.apply_fiat_shamir("u_" + std::to_string(proving_key->log_n - round_idx));
}

transcript.add_element("w_1", barretenberg::fr(100).to_buffer());
transcript.add_element("w_2", barretenberg::fr(101).to_buffer());
transcript.add_element("w_3", barretenberg::fr(102).to_buffer());
transcript.add_element("sigma_1", barretenberg::fr(103).to_buffer());
transcript.add_element("sigma_2", barretenberg::fr(104).to_buffer());
transcript.add_element("sigma_3", barretenberg::fr(105).to_buffer());
transcript.add_element("q_1", barretenberg::fr(106).to_buffer());
transcript.add_element("q_2", barretenberg::fr(107).to_buffer());
transcript.add_element("q_3", barretenberg::fr(108).to_buffer());
transcript.add_element("q_m", barretenberg::fr(109).to_buffer());
transcript.add_element("q_c", barretenberg::fr(110).to_buffer());
transcript.add_element("z_perm", barretenberg::fr(111).to_buffer());
auto multivariates = Multivariates(proving_key);
auto sumcheck = Sumcheck(multivariates, transcript);

sumcheck.execute_prover();

// TODO(Cody): Execute as a loop over polynomial manifest? Things thare are called *_lagrange
transcript.add_element("w_1", multivariates.folded_polynomials[1][0].to_buffer());
transcript.add_element("w_2", multivariates.folded_polynomials[1][0].to_buffer());
transcript.add_element("w_3", multivariates.folded_polynomials[2][0].to_buffer());
transcript.add_element("z_perm", multivariates.folded_polynomials[3][0].to_buffer());
transcript.add_element("q_m", multivariates.folded_polynomials[4][0].to_buffer());
transcript.add_element("q_1", multivariates.folded_polynomials[5][0].to_buffer());
transcript.add_element("q_2", multivariates.folded_polynomials[6][0].to_buffer());
transcript.add_element("q_3", multivariates.folded_polynomials[7][0].to_buffer());
transcript.add_element("q_c", multivariates.folded_polynomials[8][0].to_buffer());
transcript.add_element("sigma_1", multivariates.folded_polynomials[9][0].to_buffer());
transcript.add_element("sigma_2", multivariates.folded_polynomials[10][0].to_buffer());
transcript.add_element("sigma_3", multivariates.folded_polynomials[11][0].to_buffer());
transcript.add_element("id_1", multivariates.folded_polynomials[12][0].to_buffer());
transcript.add_element("id_2", multivariates.folded_polynomials[13][0].to_buffer());
transcript.add_element("id_3", multivariates.folded_polynomials[14][0].to_buffer());
transcript.add_element("L_first", multivariates.folded_polynomials[15][0].to_buffer());
transcript.add_element("L_last", multivariates.folded_polynomials[16][0].to_buffer());
}

/**
Expand Down
4 changes: 3 additions & 1 deletion cpp/src/aztec/honk/proof_system/verifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
#include <polynomials/polynomial_arithmetic.hpp>
#include <math.h>

#pragma GCC diagnostic ignored "-Wunused-variable"

using namespace barretenberg;
using namespace honk::sumcheck;

Expand Down Expand Up @@ -72,7 +74,7 @@ template <typename program_settings> bool Verifier<program_settings>::verify_pro
const size_t num_polys = program_settings::num_polys;
using FF = typename program_settings::fr;
using Transcript = typename program_settings::Transcript;
using Multivariates = Multivariates<FF, num_polys, multivariate_d>;
using Multivariates = Multivariates<FF, num_polys>;

key->program_width = program_settings::program_width;

Expand Down
48 changes: 39 additions & 9 deletions cpp/src/aztec/honk/sumcheck/polynomials/multivariates.hpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
#pragma once // just adding these willy-nilly
#include "numeric/bitop/get_msb.hpp"
#include "proof_system/proving_key/proving_key.hpp"
#include "transcript/transcript_wrappers.hpp"
#include <array>
#include <algorithm>
#include <span>
Expand Down Expand Up @@ -54,25 +57,54 @@ bool span_arrays_equal(auto& lhs, auto& rhs)
* NOTE: With ~40 columns, prob only want to allocate 256 EdgeGroup's at once to keep stack under 1MB?
* TODO(Cody): might want to just do C-style multidimensional array? for guaranteed adjacency?
*/
template <class FF_, size_t num_polys, size_t num_vars> class Multivariates {
template <class FF_, size_t num_polys> class Multivariates {
public:
using FF = FF_;
const static size_t multivariate_d = num_vars;
const static size_t multivariate_n = 1 << num_vars;
const size_t multivariate_n;
const size_t multivariate_d;
static constexpr size_t num = num_polys;

std::array<std::span<FF>, num_polys> full_polynomials;
// TODO(Cody): adjacency issues with std::array of std::arrays?
// TODO(Cody): adjacency issues with std::array of std::vectors?
// IMPROVEMENT(Cody): for each round after the first, we could release half of the memory reserved by
// folded_polynomials.
std::array<std::array<FF, (multivariate_n >> 1)>, num_polys> folded_polynomials;
std::array<std::vector<FF>, num_polys> folded_polynomials;

Multivariates() = default;

// TODO(Cody): static span extent below more efficient
explicit Multivariates(std::array<std::span<FF>, num_polys> full_polynomials)
: full_polynomials(full_polynomials){};
: multivariate_n(full_polynomials[0].size())
, multivariate_d(numeric::get_msb(multivariate_n))
, full_polynomials(full_polynomials)
{
for (auto& polynomial : folded_polynomials) {
polynomial.resize(multivariate_n >> 1);
}
};

explicit Multivariates(const std::shared_ptr<waffle::proving_key>& proving_key)
: multivariate_n(proving_key->n)
, multivariate_d(proving_key->log_n)
{
for (size_t i = 0; i < waffle::STANDARD_HONK_MANIFEST_SIZE; i++) {
auto label = proving_key->polynomial_manifest[i].polynomial_label;
full_polynomials[i] = proving_key->polynomial_cache.get(std::string(label));
}

for (auto& polynomial : folded_polynomials) {
polynomial.resize(multivariate_n >> 1);
}
}

explicit Multivariates(transcript::StandardTranscript transcript)
: multivariate_n(
static_cast<size_t>(transcript.get_field_element("circuit_size").from_montgomery_form().data[0]))
, multivariate_d(numeric::get_msb(multivariate_n))
{}

// TODO(Cody): Rename. fold is not descriptive, and it's already in use in the Gemini context.
// Probably just call it partial_evaluation?
/**
* @brief Evaluate at the round challenge and prepare class for next round.
* Illustration of layout in example of first round when d==3 (showing just one Honk polynomial,
Expand All @@ -90,7 +122,6 @@ template <class FF_, size_t num_polys, size_t num_vars> class Multivariates {
*
* @param challenge
*/

void fold(auto& polynomials, size_t round_size, const FF& round_challenge)
{
// after the first round, operate in place on folded_polynomials
Expand All @@ -102,11 +133,10 @@ template <class FF_, size_t num_polys, size_t num_vars> class Multivariates {
}
};

std::array<FF, num_polys> batch_evaluate(std::array<FF, num_vars> input)
std::array<FF, num_polys> batch_evaluate()
{
// TODO(Cody): these just get extracted from the folded multivariates
// For now, at least initialize properly.
static_cast<void>(input);
std::array<FF, num_polys> result;
for (auto& entry : result) {
entry = 1;
Expand Down
62 changes: 48 additions & 14 deletions cpp/src/aztec/honk/sumcheck/polynomials/multivariates.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace test_sumcheck_polynomials {
template <class FF> class MultivariatesTests : public testing::Test {
public:
// template <size_t num_polys, size_t multivariate_d>
// using Multivariates = Multivariates<FF, num_polys, multivariate_d>;
// using Multivariates = Multivariates<FF, num_polys>;
// TODO(Cody): reinstate this
// /*
// u2 = 1
Expand All @@ -37,7 +37,7 @@ template <class FF> class MultivariatesTests : public testing::Test {
// auto group_2 = EdgeGroup<num_polys>({ Y12, Y22 });

// std::array<EdgeGroup<num_polys>, multivariate_d> groups{ group_1, group_2 };
// auto polys = Multivariates<num_polys, multivariate_d>(groups);
// auto polys = Multivariates<num_polys>(groups);

// FF u2 = 1;
// polys.fold(n, u2);
Expand All @@ -60,7 +60,7 @@ TYPED_TEST(MultivariatesTests, Constructor)
MULTIVARIATES_TESTS_TYPE_ALIASES

const size_t num_polys(4);
const size_t multivariate_d(2);
// const size_t multivariate_d(2);
// const size_t multivariate_n(1 << multivariate_d);

std::array<FF, 3> f0 = { 0, 0, 1 };
Expand All @@ -69,7 +69,7 @@ TYPED_TEST(MultivariatesTests, Constructor)
std::array<FF, 3> f3 = { -1, -1, 1 };

auto full_polynomials = std::array<std::span<FF>, num_polys>({ f0, f1, f2, f3 });
auto multivariates = Multivariates<FF, num_polys, multivariate_d>(full_polynomials);
auto multivariates = Multivariates<FF, num_polys>(full_polynomials);

ASSERT_TRUE(span_arrays_equal(full_polynomials, multivariates.full_polynomials));
}
Expand All @@ -85,37 +85,71 @@ TYPED_TEST(MultivariatesTests, Constructor)
(v01 * (1-X1) + v11 * X1) * X2 ~~> (v00 * (1-u2) + v01 * u2) * (1-X1)
+ (v00 * (1-X1) + v10 * X1) * (1-X2) ~~> + (v11 * u2 + v10 * (1-u2)) * X1
*/
TYPED_TEST(MultivariatesTests, FoldTwo)
TYPED_TEST(MultivariatesTests, FoldTwoRoundsSpecial)
{
MULTIVARIATES_TESTS_TYPE_ALIASES

const size_t num_polys(2);
const size_t multivariate_d(1);
const size_t num_polys(1);
const size_t multivariate_d(2);
const size_t multivariate_n(1 << multivariate_d);

FF v00 = 1;
FF v01 = 2;
FF v10 = 3;
FF v11 = 4;

std::array<FF, 4> f0 = { v00, v01, v10, v11 };

auto full_polynomials = std::array<std::span<FF>, 1>({ f0 });
auto multivariates = Multivariates<FF, num_polys>(full_polynomials);

FF round_challenge_2 = 1;
FF expected_lo = v00 * (FF(1) - round_challenge_2) + v01 * round_challenge_2; // 2
FF expected_hi = v11 * round_challenge_2 + v10 * (FF(1) - round_challenge_2); // 4

multivariates.fold(multivariates.full_polynomials, multivariate_n, round_challenge_2);

EXPECT_EQ(multivariates.folded_polynomials[0][0], expected_lo);
EXPECT_EQ(multivariates.folded_polynomials[0][1], expected_hi);

FF round_challenge_1 = 2;
FF expected_val = expected_lo * (FF(1) - round_challenge_1) + expected_hi * round_challenge_1; // 6

multivariates.fold(multivariates.folded_polynomials, multivariate_n >> 1, round_challenge_1);
EXPECT_EQ(multivariates.folded_polynomials[0][0], expected_val);
}

TYPED_TEST(MultivariatesTests, FoldTwoRoundsGeneric)
{
MULTIVARIATES_TESTS_TYPE_ALIASES

const size_t num_polys(1);
const size_t multivariate_d(2);
const size_t multivariate_n(1 << multivariate_d);

FF v00 = FF::random_element();
FF v01 = FF::random_element();
FF v10 = FF::random_element();
FF v11 = FF::random_element();

std::array<FF, 2> f0 = { v00, v10 };
std::array<FF, 2> f1 = { v01, v11 };
std::array<FF, 4> f0 = { v00, v01, v10, v11 };

auto full_polynomials = std::array<std::span<FF>, 2>({ f0, f1 });
auto multivariates = Multivariates<FF, num_polys, multivariate_d>(full_polynomials);
auto full_polynomials = std::array<std::span<FF>, 1>({ f0 });
auto multivariates = Multivariates<FF, num_polys>(full_polynomials);

FF round_challenge_2 = FF::random_element();
FF expected_lo = v00 * (FF(1) - round_challenge_2) + v10 * round_challenge_2;
FF expected_hi = v11 * round_challenge_2 + v01 * (FF(1) - round_challenge_2);
FF expected_lo = v00 * (FF(1) - round_challenge_2) + v01 * round_challenge_2;
FF expected_hi = v11 * round_challenge_2 + v10 * (FF(1) - round_challenge_2);

multivariates.fold(multivariates.full_polynomials, multivariate_n, round_challenge_2);

EXPECT_EQ(multivariates.folded_polynomials[0][0], expected_lo);
EXPECT_EQ(multivariates.folded_polynomials[1][0], expected_hi);
EXPECT_EQ(multivariates.folded_polynomials[0][1], expected_hi);

FF round_challenge_1 = FF::random_element();
FF expected_val = expected_lo * (FF(1) - round_challenge_1) + expected_hi * round_challenge_1;

info(expected_val);
multivariates.fold(multivariates.folded_polynomials, multivariate_n >> 1, round_challenge_1);
EXPECT_EQ(multivariates.folded_polynomials[0][0], expected_val);
}
Expand Down
Loading

0 comments on commit ed5eecf

Please sign in to comment.