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(avm): re-enable bb-prover tests in CI, change some to check-circuit-only, enable multi-enqueued call tests #11180

Merged
merged 13 commits into from
Jan 13, 2025
58 changes: 33 additions & 25 deletions barretenberg/cpp/src/barretenberg/bb/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -683,14 +683,17 @@ void vk_as_fields(const std::string& vk_path, const std::string& output_path)
*/
void avm_prove(const std::filesystem::path& public_inputs_path,
const std::filesystem::path& hints_path,
const std::filesystem::path& output_path)
const std::filesystem::path& output_path,
const bool check_circuit_only)
{

const auto avm_public_inputs = AvmPublicInputs::from(read_file(public_inputs_path));
const auto avm_hints = bb::avm_trace::ExecutionHints::from(read_file(hints_path));

// Using [0] is fine now for the top-level call, but we might need to index by address in future
vinfo("bytecode size: ", avm_hints.all_contract_bytecode[0].bytecode.size());
if (avm_hints.all_contract_bytecode.size() > 0) {
// Using [0] is fine now for the top-level call, but we might need to index by address in future
vinfo("bytecode size: ", avm_hints.all_contract_bytecode[0].bytecode.size());
}
vinfo("hints.storage_read_hints size: ", avm_hints.storage_read_hints.size());
vinfo("hints.storage_write_hints size: ", avm_hints.storage_write_hints.size());
vinfo("hints.nullifier_read_hints size: ", avm_hints.nullifier_read_hints.size());
Expand All @@ -704,27 +707,31 @@ void avm_prove(const std::filesystem::path& public_inputs_path,
vinfo("initializing crs with size: ", avm_trace::Execution::SRS_SIZE);
init_bn254_crs(avm_trace::Execution::SRS_SIZE);

// Prove execution and return vk
auto const [verification_key, proof] =
AVM_TRACK_TIME_V("prove/all", avm_trace::Execution::prove(avm_public_inputs, avm_hints));

std::vector<fr> vk_as_fields = verification_key.to_field_elements();

vinfo("vk fields size: ", vk_as_fields.size());
vinfo("circuit size: ", static_cast<uint64_t>(vk_as_fields[0]));
vinfo("num of pub inputs: ", static_cast<uint64_t>(vk_as_fields[1]));

std::string vk_json = to_json(vk_as_fields);
const auto proof_path = output_path / "proof";
const auto vk_path = output_path / "vk";
const auto vk_fields_path = output_path / "vk_fields.json";

write_file(proof_path, to_buffer(proof));
vinfo("proof written to: ", proof_path);
write_file(vk_path, to_buffer(vk_as_fields));
vinfo("vk written to: ", vk_path);
write_file(vk_fields_path, { vk_json.begin(), vk_json.end() });
vinfo("vk as fields written to: ", vk_fields_path);
if (check_circuit_only) {
avm_trace::Execution::check_circuit(avm_public_inputs, avm_hints);
} else {
// Prove execution and return vk
auto const [verification_key, proof] =
AVM_TRACK_TIME_V("prove/all", avm_trace::Execution::prove(avm_public_inputs, avm_hints));

std::vector<fr> vk_as_fields = verification_key.to_field_elements();

vinfo("vk fields size: ", vk_as_fields.size());
vinfo("circuit size: ", static_cast<uint64_t>(vk_as_fields[0]));
vinfo("num of pub inputs: ", static_cast<uint64_t>(vk_as_fields[1]));

std::string vk_json = to_json(vk_as_fields);
const auto proof_path = output_path / "proof";
const auto vk_path = output_path / "vk";
const auto vk_fields_path = output_path / "vk_fields.json";

write_file(proof_path, to_buffer(proof));
vinfo("proof written to: ", proof_path);
write_file(vk_path, to_buffer(vk_as_fields));
vinfo("vk written to: ", vk_path);
write_file(vk_fields_path, { vk_json.begin(), vk_json.end() });
vinfo("vk as fields written to: ", vk_fields_path);
}

#ifdef AVM_TRACK_STATS
info("------- STATS -------");
Expand Down Expand Up @@ -1390,7 +1397,8 @@ int main(int argc, char* argv[])
std::filesystem::path output_path = get_option(args, "-o", "./proofs");
extern std::filesystem::path avm_dump_trace_path;
avm_dump_trace_path = get_option(args, "--avm-dump-trace", "");
avm_prove(avm_public_inputs_path, avm_hints_path, output_path);
const bool check_circuit_only = flag_present(args, "--check-circuit-only");
avm_prove(avm_public_inputs_path, avm_hints_path, output_path, check_circuit_only);
} else if (command == "avm_verify") {
return avm_verify(proof_path, vk_path) ? 0 : 1;
#endif
Expand Down
37 changes: 37 additions & 0 deletions barretenberg/cpp/src/barretenberg/vm/avm/trace/execution.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,43 @@ std::vector<FF> Execution::getDefaultPublicInputs()
return public_inputs_vec;
}

/**
* @brief Run the bytecode, generate the corresponding execution trace and check the circuit for
* execution of the supplied bytecode.
*
* @throws runtime_error exception when the bytecode is invalid.
*/
void Execution::check_circuit(AvmPublicInputs const& public_inputs, ExecutionHints const& execution_hints)
dbanks12 marked this conversation as resolved.
Show resolved Hide resolved
{
std::vector<FF> returndata;
std::vector<FF> calldata;
for (const auto& enqueued_call_hints : execution_hints.enqueued_call_hints) {
calldata.insert(calldata.end(), enqueued_call_hints.calldata.begin(), enqueued_call_hints.calldata.end());
}
std::vector<Row> trace = AVM_TRACK_TIME_V(
"prove/gen_trace", gen_trace(public_inputs, returndata, execution_hints, /*apply_e2e_assertions=*/true));
if (!avm_dump_trace_path.empty()) {
info("Dumping trace as CSV to: " + avm_dump_trace_path.string());
dump_trace_as_csv(trace, avm_dump_trace_path);
}
auto circuit_builder = bb::avm::AvmCircuitBuilder();
circuit_builder.set_trace(std::move(trace));
vinfo("Circuit subgroup size: 2^",
// this calculates the integer log2
std::bit_width(circuit_builder.get_circuit_subgroup_size()) - 1);

if (circuit_builder.get_circuit_subgroup_size() > SRS_SIZE) {
throw_or_abort("Circuit subgroup size (" + std::to_string(circuit_builder.get_circuit_subgroup_size()) +
") exceeds SRS_SIZE (" + std::to_string(SRS_SIZE) + ")");
}

vinfo("------- CHECKING CIRCUIT -------");
AVM_TRACK_TIME("prove/check_circuit", circuit_builder.check_circuit());
// Reclaim memory. Ideally this would be done as soon as the polynomials are created, but the above flow requires
// the trace both in creation of the prover and the verifier.
circuit_builder.clear_trace();
dbanks12 marked this conversation as resolved.
Show resolved Hide resolved
}

/**
* @brief Run the bytecode, generate the corresponding execution trace and prove the correctness
* of the execution of the supplied bytecode.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ class Execution {

static std::tuple<bb::avm::AvmFlavor::VerificationKey, bb::HonkProof> prove(
AvmPublicInputs const& public_inputs = AvmPublicInputs(), ExecutionHints const& execution_hints = {});
static void check_circuit(AvmPublicInputs const& public_inputs = AvmPublicInputs(),
ExecutionHints const& execution_hints = {});
static bool verify(bb::avm::AvmFlavor::VerificationKey vk, HonkProof const& proof);

private:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,11 @@ contract AvmTest {
storage.single.read()
}

#[public]
fn read_assert_storage_single(a: Field) {
assert(a == storage.single.read(), "Storage value does not match input");
}

// should still be able to use ` -> pub *` for return type even though macro forces `pub`
#[public]
fn set_read_storage_single(a: Field) -> pub Field {
Expand Down
Loading
Loading