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

chore(acir)!: Move is_recursive flag to be part of the circuit definition #4221

Merged
merged 34 commits into from
Feb 1, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
993cc52
move recursive flag onto the circuit itself rather than having it be …
vezenovm Jan 25, 2024
51709d8
missed bberg files
vezenovm Jan 25, 2024
a746985
remove is_recursive flag and add recursive flag to AcirComposer
vezenovm Jan 25, 2024
192beeb
use throw_or_abort
vezenovm Jan 25, 2024
a3a7800
remove is_recursive flag
vezenovm Jan 25, 2024
bc3843f
update dsl bberg tests to use new AcirFormat
vezenovm Jan 25, 2024
3fd6edc
uncomment serde_reflection test
vezenovm Jan 25, 2024
18532f1
Merge branch 'master' into mv/is-recursive-on-circuit
vezenovm Jan 25, 2024
4c074be
make a separate test for recursive assert_statement
vezenovm Jan 25, 2024
018f25f
update noir js to not distinguish between intermediate and final proofs
vezenovm Jan 25, 2024
73975d1
update comment
vezenovm Jan 25, 2024
3c67a55
bb js foramt
vezenovm Jan 25, 2024
545e6f0
missed recursive flag in acir format test
vezenovm Jan 25, 2024
b37e972
remove unused flags
vezenovm Jan 25, 2024
2eba28f
browser-test-app in acir_tests
vezenovm Jan 25, 2024
0b5931c
move is_recursive_circuit to vkey
vezenovm Jan 26, 2024
c9d1629
remove old comment
vezenovm Jan 26, 2024
847fa25
bring back test comment
vezenovm Jan 26, 2024
91b2a16
remove old recursive_ field on acir composer
vezenovm Jan 26, 2024
d2a7e98
cleanup info
vezenovm Jan 26, 2024
2cbeb9c
merge conflicts
vezenovm Jan 29, 2024
3d4ff84
Merge branch 'master' into mv/is-recursive-on-circuit
vezenovm Jan 29, 2024
4a99457
update dep for noir_js_backend_barretenberg
vezenovm Jan 29, 2024
87459cf
docs updates after bootstrapping
vezenovm Jan 29, 2024
07436ed
move back to 0.19.0
vezenovm Jan 29, 2024
a9b123c
resolve merge conflicts w/ master
vezenovm Jan 30, 2024
a706c47
Update barretenberg/cpp/src/barretenberg/proof_system/circuit_builder…
vezenovm Jan 30, 2024
c2abde7
remove floating false on GoblinUltraCircuitBuilder_
vezenovm Jan 30, 2024
64375f4
slight format update
vezenovm Jan 30, 2024
bce2607
merge conflcits w/ master
vezenovm Jan 31, 2024
6a70ef0
don't commit codegen'd docs
vezenovm Jan 31, 2024
4266015
resolve merge conflicts w/ master
vezenovm Feb 1, 2024
2a1b16b
regenerate bindings
kevaundray Feb 1, 2024
11e7571
Empty-Commit
vezenovm Feb 1, 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
30 changes: 12 additions & 18 deletions barretenberg/cpp/src/barretenberg/bb/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ acir_format::AcirFormat get_constraint_system(std::string const& bytecode_path)
* @return true if the proof is valid
* @return false if the proof is invalid
*/
bool proveAndVerify(const std::string& bytecodePath, const std::string& witnessPath, bool recursive)
bool proveAndVerify(const std::string& bytecodePath, const std::string& witnessPath)
{
auto constraint_system = get_constraint_system(bytecodePath);
auto witness = get_witness(witnessPath);
Expand All @@ -109,14 +109,14 @@ bool proveAndVerify(const std::string& bytecodePath, const std::string& witnessP
write_benchmark("subgroup_size", acir_composer.get_dyadic_circuit_size(), "acir_test", current_dir);

Timer proof_timer;
auto proof = acir_composer.create_proof(recursive);
auto proof = acir_composer.create_proof();
write_benchmark("proof_construction_time", proof_timer.milliseconds(), "acir_test", current_dir);

Timer vk_timer;
acir_composer.init_verification_key();
write_benchmark("vk_construction_time", vk_timer.milliseconds(), "acir_test", current_dir);

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

vinfo("verified: ", verified);
return verified;
Expand Down Expand Up @@ -172,9 +172,7 @@ bool accumulateAndVerifyGoblin(const std::string& bytecodePath, const std::strin
* @return true if the proof is valid
* @return false if the proof is invalid
*/
bool proveAndVerifyGoblin(const std::string& bytecodePath,
const std::string& witnessPath,
[[maybe_unused]] bool recursive)
bool proveAndVerifyGoblin(const std::string& bytecodePath, const std::string& witnessPath)
{
// Populate the acir constraint system and witness from gzipped data
auto constraint_system = get_constraint_system(bytecodePath);
Expand Down Expand Up @@ -212,10 +210,7 @@ bool proveAndVerifyGoblin(const std::string& bytecodePath,
* @param recursive Whether to use recursive proof generation of non-recursive
* @param outputPath Path to write the proof to
*/
void prove(const std::string& bytecodePath,
const std::string& witnessPath,
bool recursive,
const std::string& outputPath)
void prove(const std::string& bytecodePath, const std::string& witnessPath, const std::string& outputPath)
{
auto constraint_system = get_constraint_system(bytecodePath);
auto witness = get_witness(witnessPath);
Expand All @@ -224,7 +219,7 @@ void prove(const std::string& bytecodePath,
acir_composer.create_circuit(constraint_system, witness);
init_bn254_crs(acir_composer.get_dyadic_circuit_size());
acir_composer.init_proving_key();
auto proof = acir_composer.create_proof(recursive);
auto proof = acir_composer.create_proof();

if (outputPath == "-") {
writeRawBytesToStdout(proof);
Expand Down Expand Up @@ -270,12 +265,12 @@ void gateCount(const std::string& bytecodePath)
* @return true If the proof is valid
* @return false If the proof is invalid
*/
bool verify(const std::string& proof_path, bool recursive, const std::string& vk_path)
bool verify(const std::string& proof_path, const std::string& vk_path)
{
auto acir_composer = verifier_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);
auto verified = acir_composer.verify_proof(read_file(proof_path));

vinfo("verified: ", verified);
return verified;
Expand Down Expand Up @@ -491,7 +486,6 @@ int main(int argc, char* argv[])
std::string vk_path = get_option(args, "-k", "./target/vk");
std::string pk_path = get_option(args, "-r", "./target/pk");
CRS_PATH = get_option(args, "-c", CRS_PATH);
bool recursive = flag_present(args, "-r") || flag_present(args, "--recursive");

// Skip CRS initialization for any command which doesn't require the CRS.
if (command == "--version") {
Expand All @@ -504,21 +498,21 @@ int main(int argc, char* argv[])
return 0;
}
if (command == "prove_and_verify") {
return proveAndVerify(bytecode_path, witness_path, recursive) ? 0 : 1;
return proveAndVerify(bytecode_path, witness_path) ? 0 : 1;
}
if (command == "accumulate_and_verify_goblin") {
return accumulateAndVerifyGoblin(bytecode_path, witness_path) ? 0 : 1;
}
if (command == "prove_and_verify_goblin") {
return proveAndVerifyGoblin(bytecode_path, witness_path, recursive) ? 0 : 1;
return proveAndVerifyGoblin(bytecode_path, witness_path) ? 0 : 1;
}
if (command == "prove") {
std::string output_path = get_option(args, "-o", "./proofs/proof");
prove(bytecode_path, witness_path, recursive, output_path);
prove(bytecode_path, witness_path, output_path);
} else if (command == "gates") {
gateCount(bytecode_path);
} else if (command == "verify") {
return verify(proof_path, recursive, vk_path) ? 0 : 1;
return verify(proof_path, vk_path) ? 0 : 1;
} else if (command == "contract") {
std::string output_path = get_option(args, "-o", "./target/contract.sol");
contract(output_path, vk_path);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ namespace acir_format {
struct AcirFormat {
// The number of witnesses in the circuit
uint32_t varnum;
// Specifies whether a prover that produces SNARK recursion friendly proofs should be used.
// The proof produced when this flag is true should be friendly for recursive verification inside
// of another SNARK. For example, a recursive friendly proof may use Blake3Pedersen for
// hashing in its transcript, while we still want a prove that uses Keccak for its transcript in order
// to be able to verify SNARKs on Ethereum.
bool recursive;

std::vector<uint32_t> public_inputs;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,7 @@ AcirFormat circuit_buf_to_acir_format(std::vector<uint8_t> const& buf)
AcirFormat af;
// `varnum` is the true number of variables, thus we add one to the index which starts at zero
af.varnum = circuit.current_witness_index + 1;
af.recursive = circuit.recursive;
af.public_inputs = join({ map(circuit.public_parameters.value, [](auto e) { return e.value; }),
map(circuit.return_values.value, [](auto e) { return e.value; }) });
std::map<uint32_t, BlockConstraint> block_id_to_block_constraint;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1082,6 +1082,7 @@ struct Circuit {
PublicInputs public_parameters;
PublicInputs return_values;
std::vector<std::tuple<OpcodeLocation, std::string>> assert_messages;
bool recursive;

friend bool operator==(const Circuit&, const Circuit&);
std::vector<uint8_t> bincodeSerialize() const;
Expand Down Expand Up @@ -5719,6 +5720,9 @@ inline bool operator==(const Circuit& lhs, const Circuit& rhs)
if (!(lhs.assert_messages == rhs.assert_messages)) {
return false;
}
if (!(lhs.recursive == rhs.recursive)) {
return false;
}
return true;
}

Expand Down Expand Up @@ -5752,6 +5756,7 @@ void serde::Serializable<Circuit::Circuit>::serialize(const Circuit::Circuit& ob
serde::Serializable<decltype(obj.public_parameters)>::serialize(obj.public_parameters, serializer);
serde::Serializable<decltype(obj.return_values)>::serialize(obj.return_values, serializer);
serde::Serializable<decltype(obj.assert_messages)>::serialize(obj.assert_messages, serializer);
serde::Serializable<decltype(obj.recursive)>::serialize(obj.recursive, serializer);
serializer.decrease_container_depth();
}

Expand All @@ -5767,6 +5772,7 @@ Circuit::Circuit serde::Deserializable<Circuit::Circuit>::deserialize(Deserializ
obj.public_parameters = serde::Deserializable<decltype(obj.public_parameters)>::deserialize(deserializer);
obj.return_values = serde::Deserializable<decltype(obj.return_values)>::deserialize(deserializer);
obj.assert_messages = serde::Deserializable<decltype(obj.assert_messages)>::deserialize(deserializer);
obj.recursive = serde::Deserializable<decltype(obj.recursive)>::deserialize(deserializer);
deserializer.decrease_container_depth();
return obj;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ void AcirComposer::create_circuit(acir_format::AcirFormat& constraint_system, Wi
vinfo("building circuit...");
builder_ = acir_format::create_circuit<Builder>(constraint_system, size_hint_, witness);
vinfo("gates: ", builder_.get_total_circuit_size());
recursive_ = constraint_system.recursive;
vinfo("circuit is recursive friendly: ", recursive_);
}

std::shared_ptr<bb::plonk::proving_key> AcirComposer::init_proving_key()
Expand All @@ -39,7 +41,7 @@ std::shared_ptr<bb::plonk::proving_key> AcirComposer::init_proving_key()
return proving_key_;
}

std::vector<uint8_t> AcirComposer::create_proof(bool is_recursive)
std::vector<uint8_t> AcirComposer::create_proof()
{
if (!proving_key_) {
throw_or_abort("Must compute proving key before constructing proof.");
Expand All @@ -49,7 +51,7 @@ std::vector<uint8_t> AcirComposer::create_proof(bool is_recursive)

vinfo("creating proof...");
std::vector<uint8_t> proof;
if (is_recursive) {
if (recursive_) {
auto prover = composer.create_prover(builder_);
proof = prover.construct_proof().proof_data;
} else {
Expand Down Expand Up @@ -78,7 +80,7 @@ void AcirComposer::load_verification_key(bb::plonk::verification_key_data&& data
std::make_shared<bb::plonk::verification_key>(std::move(data), srs::get_crs_factory()->get_verifier_crs());
}

bool AcirComposer::verify_proof(std::vector<uint8_t> const& proof, bool is_recursive)
bool AcirComposer::verify_proof(std::vector<uint8_t> const& proof)
{
acir_format::Composer composer(proving_key_, verification_key_);

Expand All @@ -91,17 +93,7 @@ bool AcirComposer::verify_proof(std::vector<uint8_t> const& proof, bool is_recur
// Hack. Shouldn't need to do this. 2144 is size with no public inputs.
builder_.public_inputs.resize((proof.size() - 2144) / 32);

// TODO: We could get rid of this, if we made the Noir program specify whether something should be
// TODO: created with the recursive setting or not. ie:
//
// #[recursive_friendly]
// fn main() {}
// would put in the ACIR that we want this to be recursion friendly with a flag maybe and the backend
// would set the is_recursive flag to be true.
// This would eliminate the need for nargo to have a --recursive flag
//
// End result is that we may just be able to get it off of builder_, like builder_.is_recursive_friendly
Copy link
Contributor Author

@vezenovm vezenovm Jan 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I settled on this flag living on the composer as I didn't feel the need to thread it down to the builder. The builder is created when we a create a circuit anyway which is the same time this flag is set.

EDIT: I realized that in order to specify whether a circuit is recursive friendly during verification without the circuit description we need the recursive flag to live on the verification key. I ended up putting is_recursive_circuit flag on the builder and setting a new field on the verification key when we compute the key.

if (is_recursive) {
if (recursive_) {
auto verifier = composer.create_verifier(builder_);
return verifier.verify_proof({ proof });
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@ class AcirComposer {

std::shared_ptr<bb::plonk::proving_key> init_proving_key();

std::vector<uint8_t> create_proof(bool is_recursive);
std::vector<uint8_t> create_proof();

void load_verification_key(bb::plonk::verification_key_data&& data);

std::shared_ptr<bb::plonk::verification_key> init_verification_key();

bool verify_proof(std::vector<uint8_t> const& proof, bool is_recursive);
bool verify_proof(std::vector<uint8_t> const& proof);

std::string get_solidity_verifier();
size_t get_total_circuit_size() { return builder_.get_total_circuit_size(); };
Expand All @@ -43,6 +43,7 @@ class AcirComposer {
std::shared_ptr<bb::plonk::proving_key> proving_key_;
std::shared_ptr<bb::plonk::verification_key> verification_key_;
bool verbose_ = true;
bool recursive_ = false;

template <typename... Args> inline void vinfo(Args... args)
{
Expand Down
10 changes: 3 additions & 7 deletions barretenberg/cpp/src/barretenberg/dsl/acir_proofs/c_bind.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ WASM_EXPORT void acir_init_proving_key(in_ptr acir_composer_ptr, uint8_t const*
WASM_EXPORT void acir_create_proof(in_ptr acir_composer_ptr,
uint8_t const* acir_vec,
uint8_t const* witness_vec,
bool const* is_recursive,
uint8_t** out)
{
auto acir_composer = reinterpret_cast<acir_proofs::AcirComposer*>(*acir_composer_ptr);
Expand All @@ -59,7 +58,7 @@ WASM_EXPORT void acir_create_proof(in_ptr acir_composer_ptr,
acir_composer->create_circuit(constraint_system, witness);

acir_composer->init_proving_key();
auto proof_data = acir_composer->create_proof(*is_recursive);
auto proof_data = acir_composer->create_proof();
*out = to_heap_buffer(proof_data);
}

Expand Down Expand Up @@ -136,14 +135,11 @@ WASM_EXPORT void acir_goblin_verify(in_ptr acir_composer_ptr, uint8_t const* pro
*result = acir_composer->verify(proof);
}

WASM_EXPORT void acir_verify_proof(in_ptr acir_composer_ptr,
uint8_t const* proof_buf,
bool const* is_recursive,
bool* result)
WASM_EXPORT void acir_verify_proof(in_ptr acir_composer_ptr, uint8_t const* proof_buf, bool* result)
{
auto acir_composer = reinterpret_cast<acir_proofs::AcirComposer*>(*acir_composer_ptr);
auto proof = from_buffer<std::vector<uint8_t>>(proof_buf);
*result = acir_composer->verify_proof(proof, *is_recursive);
*result = acir_composer->verify_proof(proof);
}

WASM_EXPORT void acir_get_solidity_verifier(in_ptr acir_composer_ptr, out_str_buf out)
Expand Down
6 changes: 1 addition & 5 deletions barretenberg/cpp/src/barretenberg/dsl/acir_proofs/c_bind.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ WASM_EXPORT void acir_init_proving_key(in_ptr acir_composer_ptr, uint8_t const*
WASM_EXPORT void acir_create_proof(in_ptr acir_composer_ptr,
uint8_t const* constraint_system_buf,
uint8_t const* witness_buf,
bool const* is_recursive,
uint8_t** out);

/**
Expand Down Expand Up @@ -62,10 +61,7 @@ WASM_EXPORT void acir_get_verification_key(in_ptr acir_composer_ptr, uint8_t** o

WASM_EXPORT void acir_get_proving_key(in_ptr acir_composer_ptr, uint8_t const* acir_vec, uint8_t** out);

WASM_EXPORT void acir_verify_proof(in_ptr acir_composer_ptr,
uint8_t const* proof_buf,
bool const* is_recursive,
bool* result);
WASM_EXPORT void acir_verify_proof(in_ptr acir_composer_ptr, uint8_t const* proof_buf, bool* result);

/**
* @brief Verifies a GUH proof produced during goblin accumulation
Expand Down
4 changes: 4 additions & 0 deletions noir/acvm-repo/acir/codegen/acir.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1024,6 +1024,7 @@ namespace Circuit {
Circuit::PublicInputs public_parameters;
Circuit::PublicInputs return_values;
std::vector<std::tuple<Circuit::OpcodeLocation, std::string>> assert_messages;
bool recursive;

friend bool operator==(const Circuit&, const Circuit&);
std::vector<uint8_t> bincodeSerialize() const;
Expand Down Expand Up @@ -4718,6 +4719,7 @@ namespace Circuit {
if (!(lhs.public_parameters == rhs.public_parameters)) { return false; }
if (!(lhs.return_values == rhs.return_values)) { return false; }
if (!(lhs.assert_messages == rhs.assert_messages)) { return false; }
if (!(lhs.recursive == rhs.recursive)) { return false; }
return true;
}

Expand Down Expand Up @@ -4748,6 +4750,7 @@ void serde::Serializable<Circuit::Circuit>::serialize(const Circuit::Circuit &ob
serde::Serializable<decltype(obj.public_parameters)>::serialize(obj.public_parameters, serializer);
serde::Serializable<decltype(obj.return_values)>::serialize(obj.return_values, serializer);
serde::Serializable<decltype(obj.assert_messages)>::serialize(obj.assert_messages, serializer);
serde::Serializable<decltype(obj.recursive)>::serialize(obj.recursive, serializer);
serializer.decrease_container_depth();
}

Expand All @@ -4762,6 +4765,7 @@ Circuit::Circuit serde::Deserializable<Circuit::Circuit>::deserialize(Deserializ
obj.public_parameters = serde::Deserializable<decltype(obj.public_parameters)>::deserialize(deserializer);
obj.return_values = serde::Deserializable<decltype(obj.return_values)>::deserialize(deserializer);
obj.assert_messages = serde::Deserializable<decltype(obj.assert_messages)>::deserialize(deserializer);
obj.recursive = serde::Deserializable<decltype(obj.recursive)>::deserialize(deserializer);
deserializer.decrease_container_depth();
return obj;
}
Expand Down
7 changes: 7 additions & 0 deletions noir/acvm-repo/acir/src/circuit/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ pub struct Circuit {
// c++ code at the moment when it is, due to OpcodeLocation needing a comparison
// implementation which is never generated.
pub assert_messages: Vec<(OpcodeLocation, String)>,

/// States whether the backend should use a SNARK recursion friendly prover.
/// If implemented by a backend, this means that proofs generated with this circuit
/// will be friendly for recursively verifying inside of another SNARK.
pub recursive: bool,
}

impl Circuit {
Expand Down Expand Up @@ -318,6 +323,7 @@ mod tests {
public_parameters: PublicInputs(BTreeSet::from_iter(vec![Witness(2), Witness(12)])),
return_values: PublicInputs(BTreeSet::from_iter(vec![Witness(4), Witness(12)])),
assert_messages: Default::default(),
recursive: false,
};

fn read_write(circuit: Circuit) -> (Circuit, Circuit) {
Expand Down Expand Up @@ -348,6 +354,7 @@ mod tests {
public_parameters: PublicInputs(BTreeSet::from_iter(vec![Witness(2)])),
return_values: PublicInputs(BTreeSet::from_iter(vec![Witness(2)])),
assert_messages: Default::default(),
recursive: false,
};

let json = serde_json::to_string_pretty(&circuit).unwrap();
Expand Down
8 changes: 4 additions & 4 deletions noir/acvm-repo/acir/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,10 @@ mod reflection {
generator.output(&mut source, &registry).unwrap();

// Comment this out to write updated C++ code to file.
if let Some(old_hash) = old_hash {
let new_hash = fxhash::hash64(&source);
assert_eq!(new_hash, old_hash, "Serialization format has changed");
}
// if let Some(old_hash) = old_hash {
// let new_hash = fxhash::hash64(&source);
// assert_eq!(new_hash, old_hash, "Serialization format has changed");
vezenovm marked this conversation as resolved.
Show resolved Hide resolved
// }

write_to_file(&source, &path);
}
Expand Down
2 changes: 2 additions & 0 deletions noir/compiler/noirc_evaluator/src/ssa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ pub fn create_circuit(
enable_brillig_logging: bool,
) -> Result<(Circuit, DebugInfo, Vec<Witness>, Vec<Witness>, Vec<SsaReport>), RuntimeError> {
let func_sig = program.main_function_signature.clone();
let recursive = program.recursive;
let mut generated_acir =
optimize_into_acir(program, enable_ssa_logging, enable_brillig_logging)?;
let opcodes = generated_acir.take_opcodes();
Expand All @@ -112,6 +113,7 @@ pub fn create_circuit(
public_parameters,
return_values,
assert_messages: assert_messages.into_iter().collect(),
recursive,
};

// This converts each im::Vector in the BTreeMap to a Vec
Expand Down
Loading
Loading