Skip to content
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
12 changes: 9 additions & 3 deletions barretenberg/acir_tests/bbjs-test/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@ import assert from "assert";
createDebug.enable("*");
const debug = createDebug("bbjs-test");

const UH_PROOF_FIELDS_LENGTH = 440;
const UH_PROOF_FIELDS_LENGTH = 456;
const BYTES_PER_FIELD = 32;
const UH_PROOF_LENGTH_IN_BYTES = UH_PROOF_FIELDS_LENGTH * BYTES_PER_FIELD;

const proofPath = (dir: string) => path.join(dir, "proof");
const proofAsFieldsPath = (dir: string) => path.join(dir, "proof_fields.json");
const publicInputsAsFieldsPath = (dir: string) =>
path.join(dir, "public_inputs_fields.json");
const vkeyPath = (dir: string) => path.join(dir, "vk");
Expand All @@ -29,7 +30,7 @@ async function generateProof({
oracleHash?: string;
multiThreaded?: boolean;
}) {
const { UltraHonkBackend } = await import("@aztec/bb.js");
const { UltraHonkBackend, deflattenFields } = await import("@aztec/bb.js");

debug(`Generating proof for ${bytecodePath}...`);
const circuitArtifact = await fs.readFile(bytecodePath);
Expand Down Expand Up @@ -58,6 +59,11 @@ async function generateProof({
"Public inputs written to " + publicInputsAsFieldsPath(outputDirectory)
);

await fs.writeFile(
Copy link
Contributor Author

Choose a reason for hiding this comment

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

write proof out to a file here. In the future, when we update the solidity verifier interface to take in the agg obj as part of the proof, we wouldn't need to do this

proofAsFieldsPath(outputDirectory),
JSON.stringify(deflattenFields(proof.proof))
);

const verificationKey = await backend.getVerificationKey({
keccak: oracleHash === "keccak",
});
Expand All @@ -75,7 +81,7 @@ async function verifyProof({ directory }: { directory: string }) {
const proof = await fs.readFile(proofPath(directory));
assert(
proof.length === UH_PROOF_LENGTH_IN_BYTES,
`Unexpected proof length ${proof.length}`
`Unexpected proof length ${proof.length}, expected ${UH_PROOF_LENGTH_IN_BYTES}`
);

const publicInputs = JSON.parse(
Expand Down
4 changes: 2 additions & 2 deletions barretenberg/acir_tests/bootstrap.sh
Original file line number Diff line number Diff line change
Expand Up @@ -179,8 +179,8 @@ function test_cmds_internal {
for t in $honk_tests; do
echo SYS=ultra_honk FLOW=prove_then_verify $run_test $(basename $t)
done
echo SYS=ultra_honk FLOW=prove_then_verify RECURSIVE=true $run_test assert_statement
echo SYS=ultra_honk FLOW=prove_then_verify RECURSIVE=true $run_test double_verify_honk_proof
echo SYS=ultra_honk FLOW=prove_then_verify $run_test assert_statement
echo SYS=ultra_honk FLOW=prove_then_verify $run_test double_verify_honk_proof
echo SYS=ultra_honk FLOW=prove_then_verify HASH=keccak $run_test assert_statement
echo SYS=ultra_honk FLOW=prove_then_verify ROLLUP=true $run_test verify_rollup_honk_proof

Expand Down
1 change: 1 addition & 0 deletions barretenberg/acir_tests/flows/bbjs_prove_sol_verify.sh
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ $BIN write_solidity_verifier --scheme ultra_honk -k $VK -o $VERIFIER_PATH

# Verify the proof using the solidity verifier
export PROOF=$output_dir/proof
export PROOF_AS_FIELDS=$output_dir/proof_fields.json
export PUBLIC_INPUTS_AS_FIELDS=$output_dir/public_inputs_fields.json
export TEST_PATH=$(realpath "../../sol-test/HonkTest.sol")
export TESTING_HONK="true"
Expand Down
1 change: 0 additions & 1 deletion barretenberg/acir_tests/flows/sol_honk.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ set -eu
VFLAG=${VERBOSE:+-v}
BFLAG="-b ./target/program.json"
FLAGS="-c $CRS_PATH $VFLAG --scheme ultra_honk"
[ "${RECURSIVE}" = "true" ] && FLAGS+=" --recursive"
PROVE_FLAGS="$FLAGS $BFLAG --oracle_hash keccak --output_format bytes_and_fields --write_vk --input_type single_circuit"
VERIFY_FLAGS="$FLAGS --oracle_hash keccak"

Expand Down
1 change: 0 additions & 1 deletion barretenberg/acir_tests/flows/sol_honk_zk.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ set -eux
VFLAG=${VERBOSE:+-v}
BFLAG="-b ./target/program.json"
FLAGS="-c $CRS_PATH $VFLAG --scheme ultra_honk --zk"
[ "${RECURSIVE}" = "true" ] && FLAGS+=" --recursive"
PROTOCOL_FLAGS=" --honk_recursion 1 --oracle_hash keccak"

outdir=$(mktemp -d)
Expand Down
16 changes: 4 additions & 12 deletions barretenberg/acir_tests/sol-test/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -225,19 +225,11 @@ try {
const proof = readFileSync(proofPath);
proofStr = proof.toString("hex");

let publicInputsAsFieldsPath; // PUBLIC_INPUTS_AS_FIELDS is not defined for bb plonk, but is for bb honk and bbjs honk.
try {
publicInputsAsFieldsPath = getEnvVar("PUBLIC_INPUTS_AS_FIELDS");
} catch (e) {
// noop
}
let publicInputsAsFieldsPath = getEnvVarCanBeUndefined(
Copy link
Contributor Author

Choose a reason for hiding this comment

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

didn't realize getEnvVarCanBeUndefined exists lol

"PUBLIC_INPUTS_AS_FIELDS"
); // PUBLIC_INPUTS_AS_FIELDS is not defined for bb plonk, but is for bb honk and bbjs honk.
var publicInputs;
let proofAsFieldsPath; // PROOF_AS_FIELDS is not defined for bbjs, but is for bb plonk and bb honk.
try {
proofAsFieldsPath = getEnvVar("PROOF_AS_FIELDS");
} catch (e) {
// noop
}
let proofAsFieldsPath = getEnvVarCanBeUndefined("PROOF_AS_FIELDS"); // PROOF_AS_FIELDS is not defined for bbjs, but is for bb plonk and bb honk.
let numExtraPublicInputs = 0;
let extraPublicInputs = [];
if (proofAsFieldsPath) {
Expand Down
50 changes: 19 additions & 31 deletions barretenberg/cpp/src/barretenberg/api/api_ultra_honk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,7 @@ namespace bb {
extern std::string CRS_PATH;

template <typename Flavor, typename Circuit = typename Flavor::CircuitBuilder>
Circuit _compute_circuit(const std::string& bytecode_path,
const std::string& witness_path,
const bool init_kzg_accumulator)
Circuit _compute_circuit(const std::string& bytecode_path, const std::string& witness_path)
{
uint32_t honk_recursion = 0;
if constexpr (IsAnyOf<Flavor, UltraFlavor, UltraKeccakFlavor, UltraKeccakZKFlavor>) {
Expand All @@ -34,7 +32,7 @@ Circuit _compute_circuit(const std::string& bytecode_path,
// TODO(https://github.com/AztecProtocol/barretenberg/issues/1180): Don't init grumpkin crs when unnecessary.
init_grumpkin_crs(1 << CONST_ECCVM_LOG_N);

const acir_format::ProgramMetadata metadata{ .recursive = init_kzg_accumulator, .honk_recursion = honk_recursion };
const acir_format::ProgramMetadata metadata{ .honk_recursion = honk_recursion };
acir_format::AcirProgram program{ get_constraint_system(bytecode_path, metadata.honk_recursion) };

if (!witness_path.empty()) {
Expand All @@ -44,11 +42,9 @@ Circuit _compute_circuit(const std::string& bytecode_path,
}

template <typename Flavor>
UltraProver_<Flavor> _compute_prover(const std::string& bytecode_path,
const std::string& witness_path,
const bool init_kzg_accumulator)
UltraProver_<Flavor> _compute_prover(const std::string& bytecode_path, const std::string& witness_path)
{
auto prover = UltraProver_<Flavor>{ _compute_circuit<Flavor>(bytecode_path, witness_path, init_kzg_accumulator) };
auto prover = UltraProver_<Flavor>{ _compute_circuit<Flavor>(bytecode_path, witness_path) };

size_t required_crs_size = prover.proving_key->proving_key.circuit_size;
if constexpr (Flavor::HasZK) {
Expand All @@ -59,27 +55,23 @@ UltraProver_<Flavor> _compute_prover(const std::string& bytecode_path,
}

template <typename Flavor, typename VK = typename Flavor::VerificationKey>
PubInputsProofAndKey<VK> _compute_vk(const bool init_kzg_accumulator,
const std::filesystem::path& bytecode_path,
PubInputsProofAndKey<VK> _compute_vk(const std::filesystem::path& bytecode_path,
const std::filesystem::path& witness_path)
{
auto prover = _compute_prover<Flavor>(bytecode_path.string(), witness_path.string(), init_kzg_accumulator);
auto prover = _compute_prover<Flavor>(bytecode_path.string(), witness_path.string());
return { PublicInputsVector{}, HonkProof{}, std::make_shared<VK>(prover.proving_key->proving_key) };
}

template <typename Flavor, typename VK = typename Flavor::VerificationKey>
PubInputsProofAndKey<VK> _prove(const bool compute_vk,
const bool init_kzg_accumulator,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

bye

const std::filesystem::path& bytecode_path,
const std::filesystem::path& witness_path)
{
auto prover = _compute_prover<Flavor>(bytecode_path.string(), witness_path.string(), init_kzg_accumulator);
auto prover = _compute_prover<Flavor>(bytecode_path.string(), witness_path.string());
HonkProof concat_pi_and_proof = prover.construct_proof();
size_t num_inner_public_inputs = prover.proving_key->proving_key.num_public_inputs;
if (init_kzg_accumulator) {
ASSERT(num_inner_public_inputs >= PAIRING_POINT_ACCUMULATOR_SIZE);
num_inner_public_inputs -= PAIRING_POINT_ACCUMULATOR_SIZE;
}
ASSERT(num_inner_public_inputs >= PAIRING_POINT_ACCUMULATOR_SIZE);
num_inner_public_inputs -= PAIRING_POINT_ACCUMULATOR_SIZE;
if constexpr (HasIPAAccumulator<Flavor>) {
ASSERT(num_inner_public_inputs >= IPA_CLAIM_SIZE);
num_inner_public_inputs -= IPA_CLAIM_SIZE;
Expand Down Expand Up @@ -167,16 +159,14 @@ void UltraHonkAPI::prove(const Flags& flags,
write(_prove_output, flags.output_format, flags.write_vk ? "proof_and_vk" : "proof", output_dir);
};

const bool init = flags.init_kzg_accumulator;

if (flags.ipa_accumulation) {
_write(_prove<UltraRollupFlavor>(flags.write_vk, init, bytecode_path, witness_path));
_write(_prove<UltraRollupFlavor>(flags.write_vk, bytecode_path, witness_path));
} else if (flags.oracle_hash_type == "poseidon2") {
_write(_prove<UltraFlavor>(flags.write_vk, init, bytecode_path, witness_path));
_write(_prove<UltraFlavor>(flags.write_vk, bytecode_path, witness_path));
} else if (flags.oracle_hash_type == "keccak" && !flags.zk) {
_write(_prove<UltraKeccakFlavor>(flags.write_vk, init, bytecode_path, witness_path));
_write(_prove<UltraKeccakFlavor>(flags.write_vk, bytecode_path, witness_path));
} else if (flags.oracle_hash_type == "keccak" && flags.zk) {
_write(_prove<UltraKeccakZKFlavor>(flags.write_vk, init, bytecode_path, witness_path));
_write(_prove<UltraKeccakZKFlavor>(flags.write_vk, bytecode_path, witness_path));
} else {
throw_or_abort("Invalid proving options specified in _prove");
}
Expand Down Expand Up @@ -217,16 +207,14 @@ void UltraHonkAPI::write_vk(const Flags& flags,
{
const auto _write = [&](auto&& _prove_output) { write(_prove_output, flags.output_format, "vk", output_path); };

const bool init = flags.init_kzg_accumulator;

if (flags.ipa_accumulation) {
_write(_compute_vk<UltraRollupFlavor>(init, bytecode_path, ""));
_write(_compute_vk<UltraRollupFlavor>(bytecode_path, ""));
} else if (flags.oracle_hash_type == "poseidon2") {
_write(_compute_vk<UltraFlavor>(init, bytecode_path, ""));
_write(_compute_vk<UltraFlavor>(bytecode_path, ""));
} else if (flags.oracle_hash_type == "keccak" && !flags.zk) {
_write(_compute_vk<UltraKeccakFlavor>(init, bytecode_path, ""));
_write(_compute_vk<UltraKeccakFlavor>(bytecode_path, ""));
} else if (flags.oracle_hash_type == "keccak" && flags.zk) {
_write(_compute_vk<UltraKeccakZKFlavor>(init, bytecode_path, ""));
_write(_compute_vk<UltraKeccakZKFlavor>(bytecode_path, ""));
} else {
throw_or_abort("Invalid proving options specified in _prove");
}
Expand All @@ -235,7 +223,7 @@ void UltraHonkAPI::write_vk(const Flags& flags,
void UltraHonkAPI::gates([[maybe_unused]] const Flags& flags,
[[maybe_unused]] const std::filesystem::path& bytecode_path)
{
gate_count(bytecode_path, flags.recursive, flags.honk_recursion, flags.include_gates_per_opcode);
gate_count(bytecode_path, /*useless=*/false, flags.honk_recursion, flags.include_gates_per_opcode);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

still need to pass something in here because gate_count is shared with plonk

}

void UltraHonkAPI::write_solidity_verifier(const Flags& flags,
Expand Down Expand Up @@ -273,7 +261,7 @@ void write_recursion_inputs_ultra_honk(const std::string& bytecode_path,
init_grumpkin_crs(1 << CONST_ECCVM_LOG_N);
ipa_accumulation = true;
}
const acir_format::ProgramMetadata metadata{ .recursive = true, .honk_recursion = honk_recursion };
const acir_format::ProgramMetadata metadata{ .honk_recursion = honk_recursion };

acir_format::AcirProgram program;
program.constraints = get_constraint_system(bytecode_path, metadata.honk_recursion);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ void build_constraints(Builder& builder, AcirProgram& program, const ProgramMeta
!constraint_system.avm_recursion_constraints.empty()) {
ASSERT(metadata.honk_recursion != 0);
current_aggregation_object.set_public();
} else if (metadata.honk_recursion != 0 && builder.is_recursive_circuit) {
} else if (metadata.honk_recursion != 0) {
// Make sure the verification key records the public input indices of the
// final recursion output.
current_aggregation_object.set_public();
Expand Down
36 changes: 12 additions & 24 deletions barretenberg/cpp/src/barretenberg/dsl/acir_proofs/c_bind.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,9 @@ WASM_EXPORT void acir_create_proof(
*out = to_heap_buffer(proof_data);
}

WASM_EXPORT void acir_prove_and_verify_ultra_honk(uint8_t const* acir_vec,
bool const* recursive,
uint8_t const* witness_vec,
bool* result)
WASM_EXPORT void acir_prove_and_verify_ultra_honk(uint8_t const* acir_vec, uint8_t const* witness_vec, bool* result)
{
const acir_format::ProgramMetadata metadata{ .recursive = *recursive, .honk_recursion = 1 };
const acir_format::ProgramMetadata metadata{ .honk_recursion = 1 };
acir_format::AcirProgram program{
acir_format::circuit_buf_to_acir_format(from_buffer<std::vector<uint8_t>>(acir_vec), metadata.honk_recursion),
acir_format::witness_buf_to_witness_data(from_buffer<std::vector<uint8_t>>(witness_vec))
Expand All @@ -87,12 +84,9 @@ WASM_EXPORT void acir_prove_and_verify_ultra_honk(uint8_t const* acir_vec,
info("verified: ", *result);
}

WASM_EXPORT void acir_prove_and_verify_mega_honk(uint8_t const* acir_vec,
bool const* recursive,
uint8_t const* witness_vec,
bool* result)
WASM_EXPORT void acir_prove_and_verify_mega_honk(uint8_t const* acir_vec, uint8_t const* witness_vec, bool* result)
{
const acir_format::ProgramMetadata metadata{ .recursive = *recursive, .honk_recursion = 0 };
const acir_format::ProgramMetadata metadata{ .honk_recursion = 0 };

acir_format::AcirProgram program{
acir_format::circuit_buf_to_acir_format(from_buffer<std::vector<uint8_t>>(acir_vec), metadata.honk_recursion),
Expand Down Expand Up @@ -309,14 +303,11 @@ WASM_EXPORT void acir_verify_aztec_client(uint8_t const* proof_buf, uint8_t cons
*result = ClientIVC::verify(proof, vk);
}

WASM_EXPORT void acir_prove_ultra_honk(uint8_t const* acir_vec,
bool const* recursive,
uint8_t const* witness_vec,
uint8_t** out)
WASM_EXPORT void acir_prove_ultra_honk(uint8_t const* acir_vec, uint8_t const* witness_vec, uint8_t** out)
{
// Lambda function to ensure things get freed before proving.
UltraProver prover = [&] {
const acir_format::ProgramMetadata metadata{ .recursive = *recursive, .honk_recursion = 1 };
const acir_format::ProgramMetadata metadata{ .honk_recursion = 1 };
acir_format::AcirProgram program{ acir_format::circuit_buf_to_acir_format(
from_buffer<std::vector<uint8_t>>(acir_vec), metadata.honk_recursion),
acir_format::witness_buf_to_witness_data(
Expand All @@ -330,14 +321,11 @@ WASM_EXPORT void acir_prove_ultra_honk(uint8_t const* acir_vec,
*out = to_heap_buffer(to_buffer(proof));
}

WASM_EXPORT void acir_prove_ultra_keccak_honk(uint8_t const* acir_vec,
bool const* recursive,
uint8_t const* witness_vec,
uint8_t** out)
WASM_EXPORT void acir_prove_ultra_keccak_honk(uint8_t const* acir_vec, uint8_t const* witness_vec, uint8_t** out)
{
// Lambda function to ensure things get freed before proving.
UltraKeccakProver prover = [&] {
const acir_format::ProgramMetadata metadata{ .recursive = *recursive, .honk_recursion = 1 };
const acir_format::ProgramMetadata metadata{ .honk_recursion = 1 };
acir_format::AcirProgram program{ acir_format::circuit_buf_to_acir_format(
from_buffer<std::vector<uint8_t>>(acir_vec), metadata.honk_recursion),
acir_format::witness_buf_to_witness_data(
Expand Down Expand Up @@ -380,13 +368,13 @@ WASM_EXPORT void acir_verify_ultra_keccak_honk(uint8_t const* proof_buf, uint8_t
*result = verifier.verify_proof(proof);
}

WASM_EXPORT void acir_write_vk_ultra_honk(uint8_t const* acir_vec, bool const* recursive, uint8_t** out)
WASM_EXPORT void acir_write_vk_ultra_honk(uint8_t const* acir_vec, uint8_t** out)
{
using DeciderProvingKey = DeciderProvingKey_<UltraFlavor>;
using VerificationKey = UltraFlavor::VerificationKey;
// lambda to free the builder
DeciderProvingKey proving_key = [&] {
const acir_format::ProgramMetadata metadata{ .recursive = *recursive, .honk_recursion = 1 };
const acir_format::ProgramMetadata metadata{ .honk_recursion = 1 };
acir_format::AcirProgram program{ acir_format::circuit_buf_to_acir_format(
from_buffer<std::vector<uint8_t>>(acir_vec), metadata.honk_recursion) };
auto builder = acir_format::create_circuit<UltraCircuitBuilder>(program, metadata);
Expand All @@ -397,14 +385,14 @@ WASM_EXPORT void acir_write_vk_ultra_honk(uint8_t const* acir_vec, bool const* r
*out = to_heap_buffer(to_buffer(vk));
}

WASM_EXPORT void acir_write_vk_ultra_keccak_honk(uint8_t const* acir_vec, bool const* recursive, uint8_t** out)
WASM_EXPORT void acir_write_vk_ultra_keccak_honk(uint8_t const* acir_vec, uint8_t** out)
{
using DeciderProvingKey = DeciderProvingKey_<UltraKeccakFlavor>;
using VerificationKey = UltraKeccakFlavor::VerificationKey;

// lambda to free the builder
DeciderProvingKey proving_key = [&] {
const acir_format::ProgramMetadata metadata{ .recursive = *recursive, .honk_recursion = 1 };
const acir_format::ProgramMetadata metadata{ .honk_recursion = 1 };
acir_format::AcirProgram program{ acir_format::circuit_buf_to_acir_format(
from_buffer<std::vector<uint8_t>>(acir_vec), metadata.honk_recursion) };
auto builder = acir_format::create_circuit<UltraCircuitBuilder>(program, metadata);
Expand Down
Loading