Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: gate blocks #4741

Merged
merged 32 commits into from
Feb 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
0450817
express conventional gates as block in builders
ledwards2225 Feb 21, 2024
d357085
builders now construct everything in blocks
ledwards2225 Feb 22, 2024
74e0fa2
standard builder uses templated getters in gate fctns
ledwards2225 Feb 22, 2024
dcc7123
building with new traceBlocks for standard only, need to update all o…
ledwards2225 Feb 23, 2024
1fc15fb
all builders using blocks, builds
ledwards2225 Feb 23, 2024
f21c58e
ultra honk/plonk tests pass
ledwards2225 Feb 23, 2024
867de1d
disable direct wires access in field tests
ledwards2225 Feb 23, 2024
20b15b9
add typename
ledwards2225 Feb 23, 2024
844c91c
another typename
ledwards2225 Feb 23, 2024
4cf99e5
one more typemane
ledwards2225 Feb 23, 2024
c6cfa2e
no more wire/selector getters in builders
ledwards2225 Feb 23, 2024
01e6790
use populate wires
ledwards2225 Feb 24, 2024
992268c
use populate where possible
ledwards2225 Feb 24, 2024
386ebfb
delete dead code
ledwards2225 Feb 24, 2024
a19b776
builder copy constructor and ==
ledwards2225 Feb 24, 2024
c63bb13
remove unneeded circuit data backup logic
ledwards2225 Feb 24, 2024
0720c6c
cleanup and naming
ledwards2225 Feb 24, 2024
2302323
inheritize Arith
ledwards2225 Feb 24, 2024
c76afae
WiP move op wire construction to trace
ledwards2225 Feb 24, 2024
0da188a
use populate in standard
ledwards2225 Feb 25, 2024
a4af8d7
cleanup
ledwards2225 Feb 25, 2024
018aa1e
format
ledwards2225 Feb 25, 2024
37331b3
move ecc op wires construction to trace
ledwards2225 Feb 25, 2024
b37bf0b
use pop wires in gob
ledwards2225 Feb 26, 2024
f34244c
Merge branch 'master' into lde/gate_blocks
ledwards2225 Feb 26, 2024
f2dad93
comments
ledwards2225 Feb 26, 2024
9c4daab
comment
ledwards2225 Feb 26, 2024
029e34a
Merge branch 'master' into lde/gate_blocks
ledwards2225 Feb 26, 2024
75bbe9c
resolve review comments from kesha
ledwards2225 Feb 27, 2024
869f33c
Merge branch 'master' into lde/gate_blocks
ledwards2225 Feb 27, 2024
8ae0abb
rename generate to populate
ledwards2225 Feb 27, 2024
2d14e2e
Merge branch 'master' into lde/gate_blocks
ledwards2225 Feb 27, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ namespace bb::plonk {
*
* @return Pointer to the initialized proving key updated with selector polynomials.
* */
std::shared_ptr<plonk::proving_key> StandardComposer::compute_proving_key(const CircuitBuilder& circuit_constructor)
std::shared_ptr<plonk::proving_key> StandardComposer::compute_proving_key(CircuitBuilder& circuit_constructor)
ledwards2225 marked this conversation as resolved.
Show resolved Hide resolved
{
if (circuit_proving_key) {
return circuit_proving_key;
Expand All @@ -41,7 +41,7 @@ std::shared_ptr<plonk::proving_key> StandardComposer::compute_proving_key(const
subgroup_size, circuit_constructor.public_inputs.size(), crs, CircuitType::STANDARD);

// Construct and add to proving key the wire, selector and copy constraint polynomials
Trace::generate(circuit_constructor, circuit_proving_key);
Trace::populate(circuit_constructor, circuit_proving_key);

// Make all selectors nonzero
enforce_nonzero_selector_polynomials(circuit_constructor, circuit_proving_key.get());
Expand All @@ -62,8 +62,7 @@ std::shared_ptr<plonk::proving_key> StandardComposer::compute_proving_key(const
*
* @return Pointer to created circuit verification key.
* */
std::shared_ptr<plonk::verification_key> StandardComposer::compute_verification_key(
const CircuitBuilder& circuit_constructor)
std::shared_ptr<plonk::verification_key> StandardComposer::compute_verification_key(CircuitBuilder& circuit_constructor)
{
if (circuit_verification_key) {
return circuit_verification_key;
Expand All @@ -89,7 +88,7 @@ std::shared_ptr<plonk::verification_key> StandardComposer::compute_verification_
*
* @return The verifier.
* */
plonk::Verifier StandardComposer::create_verifier(const CircuitBuilder& circuit_constructor)
plonk::Verifier StandardComposer::create_verifier(CircuitBuilder& circuit_constructor)
{
auto verification_key = compute_verification_key(circuit_constructor);

Expand All @@ -112,7 +111,7 @@ plonk::Verifier StandardComposer::create_verifier(const CircuitBuilder& circuit_
*
* @return Initialized prover.
* */
plonk::Prover StandardComposer::create_prover(const CircuitBuilder& circuit_constructor)
plonk::Prover StandardComposer::create_prover(CircuitBuilder& circuit_constructor)
{
compute_proving_key(circuit_constructor);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,11 @@ class StandardComposer {
};
return result;
}
std::shared_ptr<plonk::proving_key> compute_proving_key(const CircuitBuilder& circuit_constructor);
std::shared_ptr<plonk::verification_key> compute_verification_key(const CircuitBuilder& circuit_constructor);
std::shared_ptr<plonk::proving_key> compute_proving_key(CircuitBuilder& circuit_constructor);
std::shared_ptr<plonk::verification_key> compute_verification_key(CircuitBuilder& circuit_constructor);

plonk::Verifier create_verifier(const CircuitBuilder& circuit_constructor);
plonk::Prover create_prover(const CircuitBuilder& circuit_constructor);
plonk::Verifier create_verifier(CircuitBuilder& circuit_constructor);
plonk::Prover create_prover(CircuitBuilder& circuit_constructor);

/**
* Create a manifest, which specifies proof rounds, elements and who supplies them.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ std::shared_ptr<proving_key> UltraComposer::compute_proving_key(CircuitBuilder&
std::make_shared<plonk::proving_key>(subgroup_size, circuit.public_inputs.size(), crs, CircuitType::ULTRA);

// Construct and add to proving key the wire, selector and copy constraint polynomials
Trace::generate(circuit, circuit_proving_key);
Trace::populate(circuit, circuit_proving_key);

enforce_nonzero_selector_polynomials(circuit, circuit_proving_key.get());

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#pragma once
#include "barretenberg/common/ref_array.hpp"
#include "barretenberg/ecc/curves/bn254/bn254.hpp"
#include "barretenberg/proof_system/types/circuit_type.hpp"
#include <array>
Expand Down Expand Up @@ -31,37 +32,72 @@ namespace bb {
* We should only do this if it becomes necessary or convenient.
*/

/**
* @brief Basic structure for storing gate data in a builder
*
* @tparam FF
* @tparam NUM_WIRES
* @tparam NUM_SELECTORS
*/
template <typename FF, size_t NUM_WIRES, size_t NUM_SELECTORS> class ExecutionTraceBlock {
public:
using SelectorType = std::vector<FF, bb::ContainerSlabAllocator<FF>>;
using WireType = std::vector<uint32_t, bb::ContainerSlabAllocator<uint32_t>>;
using Selectors = std::array<SelectorType, NUM_SELECTORS>;
using Wires = std::array<WireType, NUM_WIRES>;

Wires wires; // vectors of indices into a witness variables array
Selectors selectors;

bool operator==(const ExecutionTraceBlock& other) const = default;

void reserve(size_t size_hint)
{
for (auto& w : wires) {
w.reserve(size_hint);
}
for (auto& p : selectors) {
p.reserve(size_hint);
}
}
};

// These are not magic numbers and they should not be written with global constants. These parameters are not
// accessible through clearly named static class members.
template <typename FF_> class StandardArith {
public:
static constexpr size_t NUM_WIRES = 3;
static constexpr size_t NUM_SELECTORS = 5;
using FF = FF_;
using SelectorType = std::vector<FF, bb::ContainerSlabAllocator<FF>>;

std::array<SelectorType, NUM_SELECTORS> selectors;
class StandardTraceBlock : public ExecutionTraceBlock<FF, NUM_WIRES, NUM_SELECTORS> {
public:
void populate_wires(const uint32_t& idx_1, const uint32_t& idx_2, const uint32_t& idx_3)
{
this->wires[0].emplace_back(idx_1);
this->wires[1].emplace_back(idx_2);
this->wires[2].emplace_back(idx_3);
}

SelectorType& q_m() { return selectors[0]; };
SelectorType& q_1() { return selectors[1]; };
SelectorType& q_2() { return selectors[2]; };
SelectorType& q_3() { return selectors[3]; };
SelectorType& q_c() { return selectors[4]; };
auto& w_l() { return std::get<0>(this->wires); };
auto& w_r() { return std::get<1>(this->wires); };
auto& w_o() { return std::get<2>(this->wires); };

const SelectorType& q_m() const { return selectors[0]; };
const SelectorType& q_1() const { return selectors[1]; };
const SelectorType& q_2() const { return selectors[2]; };
const SelectorType& q_3() const { return selectors[3]; };
const SelectorType& q_c() const { return selectors[4]; };
auto& q_m() { return this->selectors[0]; };
auto& q_1() { return this->selectors[1]; };
auto& q_2() { return this->selectors[2]; };
auto& q_3() { return this->selectors[3]; };
auto& q_c() { return this->selectors[4]; };
};

auto& get() { return selectors; };
struct TraceBlocks {
StandardTraceBlock pub_inputs;
StandardTraceBlock arithmetic;

void reserve(size_t size_hint)
{
for (auto& p : selectors) {
p.reserve(size_hint);
}
}
auto get() { return RefArray{ pub_inputs, arithmetic }; }

bool operator==(const TraceBlocks& other) const = default;
};

// Note: These are needed for Plonk only (for poly storage in a std::map). Must be in same order as above struct.
inline static const std::vector<std::string> selector_names = { "q_m", "q_1", "q_2", "q_3", "q_c" };
Expand All @@ -72,44 +108,43 @@ template <typename FF_> class UltraArith {
static constexpr size_t NUM_WIRES = 4;
static constexpr size_t NUM_SELECTORS = 11;
using FF = FF_;
using SelectorType = std::vector<FF, bb::ContainerSlabAllocator<FF>>;

private:
std::array<SelectorType, NUM_SELECTORS> selectors;
class UltraTraceBlock : public ExecutionTraceBlock<FF, NUM_WIRES, NUM_SELECTORS> {
public:
void populate_wires(const uint32_t& idx_1, const uint32_t& idx_2, const uint32_t& idx_3, const uint32_t& idx_4)
{
this->wires[0].emplace_back(idx_1);
this->wires[1].emplace_back(idx_2);
this->wires[2].emplace_back(idx_3);
this->wires[3].emplace_back(idx_4);
}

public:
SelectorType& q_m() { return selectors[0]; };
SelectorType& q_c() { return selectors[1]; };
SelectorType& q_1() { return selectors[2]; };
SelectorType& q_2() { return selectors[3]; };
SelectorType& q_3() { return selectors[4]; };
SelectorType& q_4() { return selectors[5]; };
SelectorType& q_arith() { return selectors[6]; };
SelectorType& q_sort() { return selectors[7]; };
SelectorType& q_elliptic() { return selectors[8]; };
SelectorType& q_aux() { return selectors[9]; };
SelectorType& q_lookup_type() { return selectors[10]; };

const SelectorType& q_m() const { return selectors[0]; };
const SelectorType& q_c() const { return selectors[1]; };
const SelectorType& q_1() const { return selectors[2]; };
const SelectorType& q_2() const { return selectors[3]; };
const SelectorType& q_3() const { return selectors[4]; };
const SelectorType& q_4() const { return selectors[5]; };
const SelectorType& q_arith() const { return selectors[6]; };
const SelectorType& q_sort() const { return selectors[7]; };
const SelectorType& q_elliptic() const { return selectors[8]; };
const SelectorType& q_aux() const { return selectors[9]; };
const SelectorType& q_lookup_type() const { return selectors[10]; };

auto& get() { return selectors; };
auto& w_l() { return std::get<0>(this->wires); };
auto& w_r() { return std::get<1>(this->wires); };
auto& w_o() { return std::get<2>(this->wires); };
auto& w_4() { return std::get<3>(this->wires); };

auto& q_m() { return this->selectors[0]; };
auto& q_c() { return this->selectors[1]; };
auto& q_1() { return this->selectors[2]; };
auto& q_2() { return this->selectors[3]; };
auto& q_3() { return this->selectors[4]; };
auto& q_4() { return this->selectors[5]; };
auto& q_arith() { return this->selectors[6]; };
auto& q_sort() { return this->selectors[7]; };
auto& q_elliptic() { return this->selectors[8]; };
auto& q_aux() { return this->selectors[9]; };
auto& q_lookup_type() { return this->selectors[10]; };
};

void reserve(size_t size_hint)
{
for (auto& vec : selectors) {
vec.reserve(size_hint);
}
}
struct TraceBlocks {
UltraTraceBlock pub_inputs;
UltraTraceBlock main;

auto get() { return RefArray{ pub_inputs, main }; }

bool operator==(const TraceBlocks& other) const = default;
};

// Note: These are needed for Plonk only (for poly storage in a std::map). Must be in same order as above struct.
inline static const std::vector<std::string> selector_names = { "q_m", "q_c", "q_1", "q_2",
Expand All @@ -128,75 +163,72 @@ template <typename FF_> class UltraHonkArith {
static constexpr size_t NUM_WIRES = 4;
static constexpr size_t NUM_SELECTORS = 14;
using FF = FF_;
using SelectorType = std::vector<FF, bb::ContainerSlabAllocator<FF>>;

private:
std::array<SelectorType, NUM_SELECTORS> selectors;

public:
SelectorType& q_m() { return selectors[0]; };
SelectorType& q_c() { return selectors[1]; };
SelectorType& q_1() { return selectors[2]; };
SelectorType& q_2() { return selectors[3]; };
SelectorType& q_3() { return selectors[4]; };
SelectorType& q_4() { return selectors[5]; };
SelectorType& q_arith() { return selectors[6]; };
SelectorType& q_sort() { return selectors[7]; };
SelectorType& q_elliptic() { return selectors[8]; };
SelectorType& q_aux() { return selectors[9]; };
SelectorType& q_lookup_type() { return selectors[10]; };
SelectorType& q_busread() { return selectors[11]; };
SelectorType& q_poseidon2_external() { return this->selectors[12]; };
SelectorType& q_poseidon2_internal() { return this->selectors[13]; };

const SelectorType& q_m() const { return selectors[0]; };
const SelectorType& q_c() const { return selectors[1]; };
const SelectorType& q_1() const { return selectors[2]; };
const SelectorType& q_2() const { return selectors[3]; };
const SelectorType& q_3() const { return selectors[4]; };
const SelectorType& q_4() const { return selectors[5]; };
const SelectorType& q_arith() const { return selectors[6]; };
const SelectorType& q_sort() const { return selectors[7]; };
const SelectorType& q_elliptic() const { return selectors[8]; };
const SelectorType& q_aux() const { return selectors[9]; };
const SelectorType& q_lookup_type() const { return selectors[10]; };
const SelectorType& q_busread() const { return selectors[11]; };
const SelectorType& q_poseidon2_external() const { return this->selectors[12]; };
const SelectorType& q_poseidon2_internal() const { return this->selectors[13]; };

auto& get() { return selectors; };

void reserve(size_t size_hint)
{
for (auto& vec : selectors) {
vec.reserve(size_hint);
class UltraHonkTraceBlock : public ExecutionTraceBlock<FF, NUM_WIRES, NUM_SELECTORS> {
public:
void populate_wires(const uint32_t& idx_1, const uint32_t& idx_2, const uint32_t& idx_3, const uint32_t& idx_4)
{
this->wires[0].emplace_back(idx_1);
this->wires[1].emplace_back(idx_2);
this->wires[2].emplace_back(idx_3);
this->wires[3].emplace_back(idx_4);
}
}

/**
* @brief Add zeros to all selectors which are not part of the conventional Ultra arithmetization
* @details Facilitates reuse of Ultra gate construction functions in arithmetizations which extend the conventional
* Ultra arithmetization
*
*/
void pad_additional()
{
q_busread().emplace_back(0);
q_poseidon2_external().emplace_back(0);
q_poseidon2_internal().emplace_back(0);
auto& w_l() { return std::get<0>(this->wires); };
auto& w_r() { return std::get<1>(this->wires); };
auto& w_o() { return std::get<2>(this->wires); };
auto& w_4() { return std::get<3>(this->wires); };

auto& q_m() { return this->selectors[0]; };
auto& q_c() { return this->selectors[1]; };
auto& q_1() { return this->selectors[2]; };
auto& q_2() { return this->selectors[3]; };
auto& q_3() { return this->selectors[4]; };
auto& q_4() { return this->selectors[5]; };
auto& q_arith() { return this->selectors[6]; };
auto& q_sort() { return this->selectors[7]; };
auto& q_elliptic() { return this->selectors[8]; };
auto& q_aux() { return this->selectors[9]; };
auto& q_lookup_type() { return this->selectors[10]; };
auto& q_busread() { return this->selectors[11]; };
auto& q_poseidon2_external() { return this->selectors[12]; };
auto& q_poseidon2_internal() { return this->selectors[13]; };

/**
* @brief Add zeros to all selectors which are not part of the conventional Ultra arithmetization
* @details Facilitates reuse of Ultra gate construction functions in arithmetizations which extend the
* conventional Ultra arithmetization
*
*/
void pad_additional()
{
q_busread().emplace_back(0);
q_poseidon2_external().emplace_back(0);
q_poseidon2_internal().emplace_back(0);
};

/**
* @brief Resizes all selectors which are not part of the conventional Ultra arithmetization
* @details Facilitates reuse of Ultra gate construction functions in arithmetizations which extend the
* conventional Ultra arithmetization
* @param new_size
*/
void resize_additional(size_t new_size)
{
q_busread().resize(new_size);
q_poseidon2_external().resize(new_size);
q_poseidon2_internal().resize(new_size);
};
};

/**
* @brief Resizes all selectors which are not part of the conventional Ultra arithmetization
* @details Facilitates reuse of Ultra gate construction functions in arithmetizations which extend the conventional
* Ultra arithmetization
* @param new_size
*/
void resize_additional(size_t new_size)
{
q_busread().resize(new_size);
q_poseidon2_external().resize(new_size);
q_poseidon2_internal().resize(new_size);
struct TraceBlocks {
UltraHonkTraceBlock ecc_op;
UltraHonkTraceBlock pub_inputs;
UltraHonkTraceBlock main;

auto get() { return RefArray{ ecc_op, pub_inputs, main }; }

bool operator==(const TraceBlocks& other) const = default;
};

// Note: Unused. Needed only for consistency with Ultra arith (which is used by Plonk)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ template <typename FF_> class CircuitBuilderBase {
CircuitBuilderBase& operator=(CircuitBuilderBase&& other) noexcept = default;
virtual ~CircuitBuilderBase() = default;

bool operator==(const CircuitBuilderBase& other) const = default;
ledwards2225 marked this conversation as resolved.
Show resolved Hide resolved

virtual size_t get_num_gates() const { return num_gates; }
virtual void print_num_gates() const { std::cout << num_gates << std::endl; }
virtual size_t get_num_variables() const { return variables.size(); }
Expand Down
Loading
Loading