Skip to content

Commit

Permalink
feat: bb faster init (#2776)
Browse files Browse the repository at this point in the history
Faster init. At least in most cases. It builds the circuit first, to
determine number of gates, then only loads the amount of CRS actually
needed. This speeds up startup time a lot.

The tradeoff however is that for larger circuits you may spend a lot of
time building the circuit, at which point you'd have been faster just
ripping in the whole CRS. Still, for most of our cases right now this is
the better option.
  • Loading branch information
charlielye authored Oct 11, 2023
1 parent d9c458d commit c794533
Show file tree
Hide file tree
Showing 6 changed files with 40 additions and 23 deletions.
8 changes: 5 additions & 3 deletions barretenberg/acir_tests/flows/all_cmds.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ $BIN verify -k vk -p proof $FLAGS
# Check supplemental functions.
# Grep to determine success.
$BIN contract -k vk $BFLAG -o - | grep "Verification Key Hash" > /dev/null
# Use jq to determine success.
$BIN proof_as_fields -k vk -p proof -o - | jq . > /dev/null
$BIN vk_as_fields -k vk -o - > vk_as_fields | jq . > /dev/null
# Use jq to determine success, and also check result not empty.
OUTPUT=$($BIN proof_as_fields -k vk -p proof -o - | jq .)
[ -n "$OUTPUT" ] || exit 1
OUTPUT=$($BIN vk_as_fields -k vk -o - | jq .)
[ -n "$OUTPUT" ] || exit 1
5 changes: 3 additions & 2 deletions barretenberg/cpp/src/barretenberg/bb/file_io.hpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
#pragma once
#include <barretenberg/common/log.hpp>
#include <fstream>
#include <ios>
#include <vector>

inline std::vector<uint8_t> read_file(const std::string& filename)
inline std::vector<uint8_t> read_file(const std::string& filename, size_t bytes = 0)
{
// Open the file in binary mode and move to the end.
std::ifstream file(filename, std::ios::binary | std::ios::ate);
Expand All @@ -12,7 +13,7 @@ inline std::vector<uint8_t> read_file(const std::string& filename)
}

// Get the file size.
std::streamsize size = file.tellg();
std::streamsize size = bytes == 0 ? (std::streamsize)file.tellg() : (std::streamsize)bytes;
if (size <= 0) {
throw std::runtime_error("File is empty or there's an error reading it: " + filename);
}
Expand Down
2 changes: 1 addition & 1 deletion barretenberg/cpp/src/barretenberg/bb/get_crs.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ inline std::vector<barretenberg::g1::affine_element> get_g1_data(const std::file
}
if (size >= num_points) {
vinfo("using cached crs at: ", path);
auto data = read_file(path / "g1.dat");
auto data = read_file(path / "g1.dat", 28 + num_points * 64);
auto points = std::vector<barretenberg::g1::affine_element>(num_points);
auto size_of_points_in_bytes = num_points * 64;
barretenberg::srs::IO<curve::BN254>::read_affine_elements_from_buffer(
Expand Down
46 changes: 29 additions & 17 deletions barretenberg/cpp/src/barretenberg/bb/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,29 @@
#include <vector>

using namespace barretenberg;
// Transcript downloading code only supports fetching and parsing the first transcript file.
const uint32_t MAX_CIRCUIT_SIZE = 1 << 22;
std::string CRS_PATH = "./crs";
bool verbose = false;

void init()
acir_proofs::AcirComposer init(acir_format::acir_format& constraint_system)
{
acir_proofs::AcirComposer acir_composer(0, verbose);
acir_composer.create_circuit(constraint_system);
auto subgroup_size = acir_composer.get_circuit_subgroup_size();

// Must +1!
auto g1_data = get_g1_data(CRS_PATH, MAX_CIRCUIT_SIZE + 1);
auto g1_data = get_g1_data(CRS_PATH, subgroup_size + 1);
auto g2_data = get_g2_data(CRS_PATH);
srs::init_crs_factory(g1_data, g2_data);

return acir_composer;
}

acir_proofs::AcirComposer init()
{
acir_proofs::AcirComposer acir_composer(0, verbose);
auto g2_data = get_g2_data(CRS_PATH);
srs::init_crs_factory({}, g2_data);
return acir_composer;
}

acir_format::WitnessVector get_witness(std::string const& witness_path)
Expand Down Expand Up @@ -53,9 +65,10 @@ acir_format::acir_format get_constraint_system(std::string const& bytecode_path)
*/
bool proveAndVerify(const std::string& bytecodePath, const std::string& witnessPath, bool recursive)
{
acir_proofs::AcirComposer acir_composer(MAX_CIRCUIT_SIZE, verbose);
auto constraint_system = get_constraint_system(bytecodePath);
auto witness = get_witness(witnessPath);
auto acir_composer = init(constraint_system);

auto proof = acir_composer.create_proof(constraint_system, witness, recursive);
auto verified = acir_composer.verify_proof(proof, recursive);

Expand All @@ -80,9 +93,9 @@ void prove(const std::string& bytecodePath,
bool recursive,
const std::string& outputPath)
{
acir_proofs::AcirComposer acir_composer(MAX_CIRCUIT_SIZE, verbose);
auto constraint_system = get_constraint_system(bytecodePath);
auto witness = get_witness(witnessPath);
auto acir_composer = init(constraint_system);
auto proof = acir_composer.create_proof(constraint_system, witness, recursive);

if (outputPath == "-") {
Expand All @@ -104,9 +117,8 @@ void prove(const std::string& bytecodePath,
*/
void gateCount(const std::string& bytecodePath)
{
acir_proofs::AcirComposer acir_composer(MAX_CIRCUIT_SIZE, verbose);
auto constraint_system = get_constraint_system(bytecodePath);
acir_composer.create_circuit(constraint_system);
auto acir_composer = init(constraint_system);
auto gate_count = acir_composer.get_total_circuit_size();

writeUint64AsRawBytesToStdout(static_cast<uint64_t>(gate_count));
Expand All @@ -131,7 +143,7 @@ void gateCount(const std::string& bytecodePath)
*/
bool verify(const std::string& proof_path, bool recursive, const std::string& vk_path)
{
acir_proofs::AcirComposer acir_composer(MAX_CIRCUIT_SIZE, verbose);
auto acir_composer = init();
auto vk_data = from_buffer<plonk::verification_key_data>(read_file(vk_path));
acir_composer.load_verification_key(std::move(vk_data));
auto verified = acir_composer.verify_proof(read_file(proof_path), recursive);
Expand All @@ -153,8 +165,8 @@ bool verify(const std::string& proof_path, bool recursive, const std::string& vk
*/
void writeVk(const std::string& bytecodePath, const std::string& outputPath)
{
acir_proofs::AcirComposer acir_composer(MAX_CIRCUIT_SIZE, verbose);
auto constraint_system = get_constraint_system(bytecodePath);
auto acir_composer = init(constraint_system);
acir_composer.init_proving_key(constraint_system);
auto vk = acir_composer.init_verification_key();
auto serialized_vk = to_buffer(*vk);
Expand Down Expand Up @@ -182,7 +194,7 @@ void writeVk(const std::string& bytecodePath, const std::string& outputPath)
*/
void contract(const std::string& output_path, const std::string& vk_path)
{
acir_proofs::AcirComposer acir_composer(MAX_CIRCUIT_SIZE, verbose);
auto acir_composer = init();
auto vk_data = from_buffer<plonk::verification_key_data>(read_file(vk_path));
acir_composer.load_verification_key(std::move(vk_data));
auto contract = acir_composer.get_solidity_verifier();
Expand Down Expand Up @@ -223,7 +235,7 @@ void contract(const std::string& output_path, const std::string& vk_path)
*/
void proofAsFields(const std::string& proof_path, std::string const& vk_path, const std::string& output_path)
{
acir_proofs::AcirComposer acir_composer(MAX_CIRCUIT_SIZE, verbose);
auto acir_composer = init();
auto vk_data = from_buffer<plonk::verification_key_data>(read_file(vk_path));
auto data = acir_composer.serialize_proof_into_fields(read_file(proof_path), vk_data.num_public_inputs);
auto json = format("[", join(map(data, [](auto fr) { return format("\"", fr, "\""); })), "]");
Expand Down Expand Up @@ -252,7 +264,7 @@ void proofAsFields(const std::string& proof_path, std::string const& vk_path, co
*/
void vkAsFields(const std::string& vk_path, const std::string& output_path)
{
acir_proofs::AcirComposer acir_composer(MAX_CIRCUIT_SIZE, verbose);
auto acir_composer = init();
auto vk_data = from_buffer<plonk::verification_key_data>(read_file(vk_path));
acir_composer.load_verification_key(std::move(vk_data));
auto data = acir_composer.serialize_verification_key_into_fields();
Expand Down Expand Up @@ -338,17 +350,17 @@ int main(int argc, char* argv[])
if (command == "--version") {
writeStringToStdout(BB_VERSION);
return 0;
} else if (command == "info") {
}
if (command == "info") {
std::string output_path = getOption(args, "-o", "info.json");
acvmInfo(output_path);
return 0;
}

init();

if (command == "prove_and_verify") {
return proveAndVerify(bytecode_path, witness_path, recursive) ? 0 : 1;
} else if (command == "prove") {
}
if (command == "prove") {
std::string output_path = getOption(args, "-o", "./proofs/proof");
prove(bytecode_path, witness_path, recursive, output_path);
} else if (command == "gates") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ std::vector<uint8_t> AcirComposer::create_proof(acir_format::acir_format& constr
composer_ = acir_format::Composer(/*p_key=*/0, /*v_key=*/0);

vinfo("building circuit...");
builder_ = acir_format::Builder(size_hint_);
create_circuit_with_witness(builder_, constraint_system, witness);
vinfo("gates: ", builder_.get_total_circuit_size());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class AcirComposer {
std::string get_solidity_verifier();
size_t get_exact_circuit_size() { return exact_circuit_size_; };
size_t get_total_circuit_size() { return total_circuit_size_; };
size_t get_circuit_subgroup_size() { return circuit_subgroup_size_; };

std::vector<barretenberg::fr> serialize_proof_into_fields(std::vector<uint8_t> const& proof,
size_t num_inner_public_inputs);
Expand Down

0 comments on commit c794533

Please sign in to comment.