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: codegen public input columns #56

Merged
merged 10 commits into from
May 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
7 changes: 7 additions & 0 deletions bberg/src/flavor_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -498,7 +498,14 @@ fn create_commitment_labels(all_ents: &[String]) -> String {
)
}

/// Create the compute_logderivative_inverses function
///
/// If we do not have any lookups, we do not need to include this round
fn create_compute_logderivative_inverses(flavor_name: &str, lookups: &[String]) -> String {
if lookups.is_empty() {
return "".to_string();
}

let compute_inverse_transformation = |lookup_name: &String| {
format!("bb::compute_logderivative_inverse<{flavor_name}Flavor, {lookup_name}_relation<FF>>(prover_polynomials, relation_parameters, this->circuit_size);")
};
Expand Down
14 changes: 12 additions & 2 deletions bberg/src/prover_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ pub trait ProverBuilder {
impl ProverBuilder for BBFiles {
fn create_prover_hpp(&mut self, name: &str) {
let include_str = includes_hpp(&snake_case(name));

let prover_hpp = format!("
{include_str}
namespace bb {{
Expand Down Expand Up @@ -91,7 +92,16 @@ impl ProverBuilder for BBFiles {
let include_str = includes_cpp(&snake_case(name));

let polynomial_commitment_phase = create_commitments_phase(commitment_polys);
let log_derivative_inverse_phase = create_log_derivative_inverse_round(lookup_names);

let (call_log_derivative_phase, log_derivative_inverse_phase): (String, String) =
if lookup_names.is_empty() {
("".to_owned(), "".to_owned())
} else {
(
"execute_log_derivative_inverse_round();".to_owned(),
create_log_derivative_inverse_round(lookup_names),
)
};

let prover_cpp = format!("
{include_str}
Expand Down Expand Up @@ -208,7 +218,7 @@ impl ProverBuilder for BBFiles {
execute_wire_commitments_round();

// Compute sorted list accumulator and commitment
execute_log_derivative_inverse_round();
{call_log_derivative_phase}

// Fiat-Shamir: alpha
// Run sumcheck subprotocol.
Expand Down
94 changes: 85 additions & 9 deletions bberg/src/verifier_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,25 @@ use crate::{
};

pub trait VerifierBuilder {
fn create_verifier_cpp(&mut self, name: &str, witness: &[String], inverses: &[String]);
fn create_verifier_cpp(
&mut self,
name: &str,
witness: &[String],
inverses: &[String],
public_cols: &[String],
);

fn create_verifier_hpp(&mut self, name: &str);
fn create_verifier_hpp(&mut self, name: &str, public_cols: &[String]);
}

impl VerifierBuilder for BBFiles {
fn create_verifier_cpp(&mut self, name: &str, witness: &[String], inverses: &[String]) {
fn create_verifier_cpp(
&mut self,
name: &str,
witness: &[String],
inverses: &[String],
public_cols: &[String],
) {
let include_str = includes_cpp(&snake_case(name));

let wire_transformation = |n: &String| {
Expand All @@ -19,12 +31,63 @@ impl VerifierBuilder for BBFiles {
)
};
let wire_commitments = map_with_newline(witness, wire_transformation);

let has_public_input_columns = !public_cols.is_empty();
let has_inverses = !inverses.is_empty();

let get_inverse_challenges = if has_inverses {
"
auto [beta, gamm] = transcript->template get_challenges<FF>(\"beta\", \"gamma\");
relation_parameters.beta = beta;
relation_parameters.gamma = gamm;
"
.to_string()
} else {
"".to_owned()
};

let verify_proof_function_declaration: String = if has_public_input_columns {
format!("bool {name}Verifier::verify_proof(const HonkProof& proof, const std::vector<FF>& public_inputs)")
} else {
format!("bool {name}Verifier::verify_proof(const HonkProof& proof)")
};

let (public_inputs_check, evaluate_public_inputs) = if has_public_input_columns {
let public_inputs_column = public_cols[0].clone(); // asserted to be 1 for the meantime, this will be generalized when required
let inputs_check = format!(
"
FF public_column_evaluation = evaluate_public_input_column(public_inputs, multivariate_challenge);
if (public_column_evaluation != claimed_evaluations.{public_inputs_column}) {{
return false;
}}
"
);
let evaluate_public_inputs = format!(
"

using FF = {name}Flavor::FF;

// Evaluate the given public input column over the multivariate challenge points
[[maybe_unused]] FF evaluate_public_input_column(std::vector<FF> points, std::vector<FF> challenges) {{
Polynomial<FF> polynomial(points);
return polynomial.evaluate_mle(challenges);
}}
"
);

(inputs_check, evaluate_public_inputs)
} else {
("".to_owned(), "".to_owned())
};

let inverse_commitments = map_with_newline(inverses, wire_transformation);

let ver_cpp = format!("
{include_str}

namespace bb {{


{name}Verifier::{name}Verifier(std::shared_ptr<Flavor::VerificationKey> verifier_key)
: key(verifier_key)
{{}}
Expand All @@ -41,12 +104,15 @@ impl VerifierBuilder for BBFiles {
commitments.clear();
return *this;
}}

{evaluate_public_inputs}


/**
* @brief This function verifies an {name} Honk proof for given program settings.
*
*/
bool {name}Verifier::verify_proof(const HonkProof& proof)
{verify_proof_function_declaration}
{{
using Flavor = {name}Flavor;
using FF = Flavor::FF;
Expand All @@ -72,9 +138,7 @@ impl VerifierBuilder for BBFiles {
// Get commitments to VM wires
{wire_commitments}

auto [beta, gamm] = transcript->template get_challenges<FF>(\"beta\", \"gamma\");
relation_parameters.beta = beta;
relation_parameters.gamma = gamm;
{get_inverse_challenges}

// Get commitments to inverses
{inverse_commitments}
Expand All @@ -97,6 +161,8 @@ impl VerifierBuilder for BBFiles {
if (sumcheck_verified.has_value() && !sumcheck_verified.value()) {{
return false;
}}

{public_inputs_check}

// Execute ZeroMorph rounds. See https://hackmd.io/dlf9xEwhTQyE3hiGbq4FsA?view for a complete description of the
// unrolled protocol.
Expand Down Expand Up @@ -126,8 +192,17 @@ impl VerifierBuilder for BBFiles {
);
}

fn create_verifier_hpp(&mut self, name: &str) {
fn create_verifier_hpp(&mut self, name: &str, public_cols: &[String]) {
let include_str = include_hpp(&snake_case(name));

// If there are public input columns, then the generated verifier must take them in as an argument for the verify_proof
let verify_proof = if !public_cols.is_empty() {
"bool verify_proof(const HonkProof& proof, const std::vector<FF>& public_inputs);"
.to_string()
} else {
"bool verify_proof(const HonkProof& proof);".to_owned()
};

let ver_hpp = format!(
"
{include_str}
Expand All @@ -149,7 +224,7 @@ impl VerifierBuilder for BBFiles {
{name}Verifier& operator=(const {name}Verifier& other) = delete;
{name}Verifier& operator=({name}Verifier&& other) noexcept;

bool verify_proof(const HonkProof& proof);
{verify_proof}

std::shared_ptr<VerificationKey> key;
std::map<std::string, Commitment> commitments;
Expand Down Expand Up @@ -188,6 +263,7 @@ fn includes_cpp(name: &str) -> String {
#include \"./{name}_verifier.hpp\"
#include \"barretenberg/commitment_schemes/zeromorph/zeromorph.hpp\"
#include \"barretenberg/numeric/bitop/get_msb.hpp\"
#include \"barretenberg/polynomials/polynomial.hpp\"
#include \"barretenberg/transcript/transcript.hpp\"
"
)
Expand Down
30 changes: 28 additions & 2 deletions bberg/src/vm_builder.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use ast::analyzed::Analyzed;

use itertools::Itertools;
use number::FieldElement;

use crate::circuit_builder::CircuitBuilder;
Expand Down Expand Up @@ -29,6 +30,8 @@ struct ColumnGroups {
fixed: Vec<String>,
/// witness or commit columns in pil -> will be found in proof
witness: Vec<String>,
// public input columns, evaluations will be calculated within the verifier
public: Vec<String>,
/// witness or commit columns in pil, with out the inverse columns
witnesses_without_inverses: Vec<String>,
/// fixed + witness columns without lookup inverses
Expand Down Expand Up @@ -89,6 +92,7 @@ pub(crate) fn analyzed_to_cpp<F: FieldElement>(
let ColumnGroups {
fixed,
witness,
public,
witnesses_without_inverses,
all_cols,
all_cols_without_inverses,
Expand Down Expand Up @@ -130,8 +134,8 @@ pub(crate) fn analyzed_to_cpp<F: FieldElement>(
bb_files.create_composer_hpp(file_name);

// ----------------------- Create the Verifier files -----------------------
bb_files.create_verifier_cpp(file_name, &witnesses_without_inverses, &inverses);
bb_files.create_verifier_hpp(file_name);
bb_files.create_verifier_cpp(file_name, &witnesses_without_inverses, &inverses, &public);
bb_files.create_verifier_hpp(file_name, &public);

// ----------------------- Create the Prover files -----------------------
bb_files.create_prover_cpp(file_name, &witnesses_without_inverses, &inverses);
Expand Down Expand Up @@ -166,6 +170,7 @@ fn get_all_col_names<F: FieldElement>(
// Gather sanitized column names
let fixed_names = collect_col(fixed, sanitize);
let witness_names = collect_col(witness, sanitize);
let (witness_names, public_input_column_names) = extract_public_input_columns(witness_names);

let inverses = flatten(&[perm_inverses, lookup_inverses]);
let witnesses_without_inverses = flatten(&[witness_names.clone(), lookup_counts.clone()]);
Expand All @@ -190,6 +195,7 @@ fn get_all_col_names<F: FieldElement>(
ColumnGroups {
fixed: fixed_names,
witness: witnesses_with_inverses,
public: public_input_column_names,
all_cols_without_inverses,
witnesses_without_inverses,
all_cols,
Expand All @@ -200,3 +206,23 @@ fn get_all_col_names<F: FieldElement>(
inverses,
}
}

/// Extract public input columns
/// The compiler automatically suffixes the public input columns with "__is_public"
/// This function removes the suffix and collects the columns into their own container
pub fn extract_public_input_columns(witness_columns: Vec<String>) -> (Vec<String>, Vec<String>) {
let witness_names: Vec<String> = witness_columns
.clone();
let public_input_column_names: Vec<String> = witness_columns
.into_iter()
.filter(|name|
name.ends_with("__is_public")
)
.collect();

assert!(
public_input_column_names.len() <= 1,
"There should only be one public input column (for now)"
);
(witness_names, public_input_column_names)
}
3 changes: 2 additions & 1 deletion parser/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@ mod test {
name: "t".to_string(),
array_size: None
}],
None
None,
false
)
])
);
Expand Down
Loading