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

Md/brillig #1

Closed
wants to merge 16 commits into from
Prev Previous commit
Next Next commit
feat: prover and verifier generation (#2)
Maddiaa0 authored Oct 16, 2023

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
commit cf670c0bffe3b3029b38dc8bd34af65d0218a3a9
118 changes: 113 additions & 5 deletions bberg/src/circuit_builder.rs
Original file line number Diff line number Diff line change
@@ -13,13 +13,30 @@ use number::{BigInt, DegreeType, FieldElement};

use pil_analyzer::pil_analyzer::inline_intermediate_polynomials;

use crate::{flavor_builder, trace_builder::TraceBuilder};
use crate::prover_builder::{prover_builder_cpp, prover_builder_hpp};
use crate::verifier_builder::{verifier_builder_cpp, verifier_builder_hpp};
use crate::{
composer_builder::{composer_builder_cpp, composer_builder_hpp},
flavor_builder,
trace_builder::TraceBuilder,
};

pub struct BBFiles {
pub relation_hpp: Option<String>,
pub arith_hpp: Option<String>,
pub trace_hpp: Option<String>,
pub flavor_hpp: Option<String>,
// composer
pub composer_cpp: Option<String>,
pub composer_hpp: Option<String>,

// prover
pub prover_cpp: Option<String>,
pub prover_hpp: Option<String>,

// verifier
pub verifier_cpp: Option<String>,
pub verifier_hpp: Option<String>,

// Relative paths
pub file_name: String,
@@ -28,11 +45,13 @@ pub struct BBFiles {
pub arith: String,
pub trace: String,
pub flavor: String,
pub composer: String,
pub prover: String, // path for both prover and verifier files
}

impl BBFiles {
pub fn default(file_name: String) -> Self {
Self::new(file_name, None, None, None, None, None)
Self::new(file_name, None, None, None, None, None, None, None)
}

pub fn new(
@@ -42,24 +61,37 @@ impl BBFiles {
arith: Option<String>,
trace: Option<String>,
flavor: Option<String>,
composer: Option<String>,
prover: Option<String>,
) -> Self {
let base = base.unwrap_or("src/barretenberg".to_owned());
let rel = rel.unwrap_or("proof_system/relations/generated".to_owned());
let arith = arith.unwrap_or("proof_system/arithmetization/generated".to_owned());
let trace = trace.unwrap_or("proof_system/circuit_builder/generated".to_owned());
let flavor = flavor.unwrap_or("honk/flavor/generated".to_owned());
let composer = composer.unwrap_or("honk/composer/generated".to_owned());
let prover = prover.unwrap_or("honk/proof_system/generated".to_owned());

Self {
file_name,
relation_hpp: None,
arith_hpp: None,
trace_hpp: None,
flavor_hpp: None,
composer_cpp: None,
composer_hpp: None,
prover_cpp: None,
prover_hpp: None,
verifier_cpp: None,
verifier_hpp: None,

base,
rel,
arith,
trace,
flavor,
composer,
prover,
}
}

@@ -69,11 +101,25 @@ impl BBFiles {
arith_hpp: String,
trace_hpp: String,
flavor_hpp: String,
composer_cpp: String,
composer_hpp: String,
verifier_cpp: String,
verifier_hpp: String,
prover_cpp: String,
prover_hpp: String,
) {
self.relation_hpp = Some(relation_hpp);
self.arith_hpp = Some(arith_hpp);
self.trace_hpp = Some(trace_hpp);
self.flavor_hpp = Some(flavor_hpp);
self.composer_cpp = Some(composer_cpp);
self.composer_hpp = Some(composer_hpp);

self.verifier_cpp = Some(verifier_cpp);
self.verifier_hpp = Some(verifier_hpp);

self.prover_cpp = Some(prover_cpp);
self.prover_hpp = Some(prover_hpp);
}

pub fn write(&self) {
@@ -97,6 +143,41 @@ impl BBFiles {
&format!("{}_flavor.hpp", self.file_name),
&self.flavor_hpp.clone().unwrap(),
);
// Composer
self.write_file(
&self.composer,
&format!("{}_composer.cpp", self.file_name),
&self.composer_cpp.clone().unwrap(),
);
self.write_file(
&self.composer,
&format!("{}_composer.hpp", self.file_name),
&self.composer_hpp.clone().unwrap(),
);

// Prover
self.write_file(
&self.prover,
&format!("{}_prover.cpp", self.file_name),
&self.prover_cpp.clone().unwrap(),
);
self.write_file(
&self.prover,
&format!("{}_prover.hpp", self.file_name),
&self.prover_hpp.clone().unwrap(),
);

// Verifier
self.write_file(
&self.prover,
&format!("{}_verifier.cpp", self.file_name),
&self.verifier_cpp.clone().unwrap(),
);
self.write_file(
&self.prover,
&format!("{}_verifier.hpp", self.file_name),
&self.verifier_hpp.clone().unwrap(),
);
}

fn write_file(&self, folder: &str, filename: &str, contents: &String) {
@@ -144,8 +225,21 @@ pub(crate) fn analyzed_to_cpp<F: FieldElement>(
// ----------------------- Create the read from powdr columns file -----------------------
let trace_hpp = bb_files.create_trace_builder(file_name, fixed, witness);

// ----------------------- Create the flavor file -----------------------
let flavor_hpp =
flavor_builder::create_flavor_hpp(file_name, all_cols, &fixed_names, &witness_names);
flavor_builder::create_flavor_hpp(file_name, &all_cols, &fixed_names, &witness_names);

// ----------------------- Create the composer files -----------------------
let composer_cpp = composer_builder_cpp(file_name);
let composer_hpp = composer_builder_hpp(file_name);

// ----------------------- Create the prover files -----------------------
let verifier_cpp = verifier_builder_cpp(file_name, &all_cols);
let verifier_hpp = verifier_builder_hpp(file_name);

// ----------------------- Create the verifier files -----------------------
let prover_cpp = prover_builder_cpp(file_name, &fixed_names, &witness_names);
let prover_hpp = prover_builder_hpp(file_name);

// These are all of the exotic ish data structures we will need
// let mut lookups = vec![];
@@ -157,7 +251,18 @@ pub(crate) fn analyzed_to_cpp<F: FieldElement>(
// // Note: we do not have lookups yet
// assert!(lookups.len() == 0, "lookups not implemented");

bb_files.add_files(relation_hpp, arith_hpp, trace_hpp, flavor_hpp);
bb_files.add_files(
relation_hpp,
arith_hpp,
trace_hpp,
flavor_hpp,
composer_cpp,
composer_hpp,
verifier_cpp,
verifier_hpp,
prover_cpp,
prover_hpp,
);
bb_files
}

@@ -340,7 +445,10 @@ fn get_cols_in_identity(row_index: usize, all_rows: &Vec<String>) -> String {
.iter()
.map(|col_name| {
let name = col_name.replace(".", "_");
format!(" auto {} = View(new_term.{});", name, name)
format!(
" [[maybe_unused]] auto {} = View(new_term.{});",
name, name
)
})
.collect();

142 changes: 142 additions & 0 deletions bberg/src/composer_builder.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
fn cpp_includes(name: &str) -> String {
format!(
"
#include \"barretenberg/honk/composer/generated/{name}_composer.hpp\"
#include \"barretenberg/honk/proof_system/grand_product_library.hpp\"
#include \"barretenberg/proof_system/circuit_builder/generated/{name}_builder.hpp\"
#include \"barretenberg/proof_system/composer/composer_lib.hpp\"
#include \"barretenberg/proof_system/composer/permutation_lib.hpp\"
"
)
}

pub fn composer_builder_cpp(name: &str) -> String {
// Create a composer file, this is used to a prover and verifier for our flavour
let include_str = cpp_includes(name);

format!(
"
{include_str}

namespace proof_system::honk {{

template <typename Flavor>
std::shared_ptr<ProverInstance_<Flavor>> {name}Composer_<Flavor>::create_instance(CircuitBuilder& circuit)
{{
circuit.build_circuit();
auto instance = std::make_shared<Instance>(circuit);
instance->commitment_key = compute_commitment_key(instance->proving_key->circuit_size);
return instance;
}}

template <typename Flavor>
{name}Prover_<Flavor> {name}Composer_<Flavor>::create_prover(const std::shared_ptr<Instance>& instance)
{{
return {name}Prover_<Flavor>(instance);
}}

template <typename Flavor>
{name}Verifier_<Flavor> {name}Composer_<Flavor>::create_verifier(const std::shared_ptr<Instance>& instance)
{{
auto vk = instance->compute_verification_key();
{name}Verifier_<Flavor> output_state(vk);
auto pcs_vk = std::make_unique<VerifierCommitmentKey>(verification_key->circuit_size, crs_factory_);
output_state.pcs_verification_key = std::move(pcs_vk);

return output_state;
}}

template class {name}Composer_<honk::flavor::{name}Flavor>;

}}
")
}

pub fn hpp_includes(name: &str) -> String {
format!(
"
#pragma once

#include \"barretenberg/honk/proof_system/generated/{name}_prover.hpp\"
#include \"barretenberg/honk/proof_system/generated/{name}_verifier.hpp\"
#include \"barretenberg/proof_system/circuit_builder/generated/{name}_builder.hpp\"
#include \"barretenberg/proof_system/composer/composer_lib.hpp\"
#include \"barretenberg/srs/factories/file_crs_factory.hpp\"
"
)
}

pub fn composer_builder_hpp(name: &str) -> String {
let include_str = hpp_includes(name);

format!(
"
{include_str}

namespace proof_system::honk {{
template <typename Flavor> class {name}Composer_ {{
public:
// using CircuitConstructor = ECCVMCircuitBuilder<Flavor>; // TODO what should this be?
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;

// TODO: which of these will we really need
static constexpr std::string_view NAME_STRING = \"{name}\";
static constexpr size_t NUM_RESERVED_GATES = 0;
static constexpr size_t NUM_WIRES = CircuitConstructor::NUM_WIRES;

std::shared_ptr<ProvingKey> proving_key;
std::shared_ptr<VerificationKey> verification_key;

// The crs_factory holds the path to the srs and exposes methods to extract the srs elements
std::shared_ptr<barretenberg::srs::factories::CrsFactory<typename Flavor::Curve>> crs_factory_;

// The commitment key is passed to the prover but also used herein to compute the verfication key commitments
std::shared_ptr<CommitmentKey> commitment_key;

std::vector<uint32_t> recursive_proof_public_input_indices;
bool contains_recursive_proof = false;
bool computer_witness = false;

{name}Composer_() requires(std::same_as<Flavor, honk::flavor::{name}Flavor)
{{
crs_factory_ = barretenberg::srs::get_crs_factory();
}}

{name}Composer_(std::shared_ptr<ProvingKey> p_key, std::shared_ptr<VerificationKey> v_key)
: proving_key(std::move(p_key))
, verification_key(std::move(v_key))
{{}}

{name}Composer_(ECCVMComposer_&& other) noexcept = default;
{name}Composer_(ECCVMComposer_ const& other) noexcept = default;
{name}Composer_& operator=(ECCVMComposer_&& other) noexcept = default;
{name}Composer_& operator=(ECCVMComposer_ const& other) noexcept = default;
~{name}Composer_() = default;

std::shared_ptr<ProvingKey> compute_proving_key(CircuitConstructor& circuit_constructor);
std::shared_ptr<VerificationKey> compute_verification_key(CircuitConstructor& circuit_constructor);

void compute_witness(CircuitConstructor& circuit_constructor);

{name}Prover_<Flavor> create_prover(CircuitConstructor& circuit_constructor);
{name}Verifier_<Flavor> 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<CommitmentKey>(circuit_size, crs_factory_);
}};
}};

extern template class {name}Composer_<honk::flavor::{name}Flavor>;
using {name}Composer = {name}Composer_<honk::flavor::{name}Flavor>;

}} // namespace proof_system::honk
"
)
}
2 changes: 1 addition & 1 deletion bberg/src/flavor_builder.rs
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@

pub(crate) fn create_flavor_hpp(
name: &str,
relations: Vec<String>,
relations: &Vec<String>,
fixed: &Vec<String>,
witness: &Vec<String>,
) -> String {
4 changes: 4 additions & 0 deletions bberg/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
pub mod bberg_codegen;
pub mod circuit_builder;
pub mod composer_builder;
pub mod flavor_builder;
pub mod prover_builder;
pub mod relation_builder;
pub mod trace_builder;
pub mod verifier_builder;
Loading