diff --git a/.github/spot-runner-action/dist/index.js b/.github/spot-runner-action/dist/index.js index e2097f038769..bca6f38f5f87 100644 --- a/.github/spot-runner-action/dist/index.js +++ b/.github/spot-runner-action/dist/index.js @@ -754,8 +754,10 @@ function requestAndWaitForSpot(config) { // wait 10 seconds yield new Promise((r) => setTimeout(r, 5000 * Math.pow(2, backoff))); backoff += 1; - core.info("Polling to see if we somehow have an instance up"); - instanceId = yield ((_a = ec2Client.getInstancesForTags("running")[0]) === null || _a === void 0 ? void 0 : _a.instanceId); + if (config.githubActionRunnerConcurrency > 0) { + core.info("Polling to see if we somehow have an instance up"); + instanceId = yield ((_a = ec2Client.getInstancesForTags("running")[0]) === null || _a === void 0 ? void 0 : _a.instanceId); + } } if (instanceId) { core.info("Successfully requested/found instance with ID " + instanceId); diff --git a/.github/spot-runner-action/src/main.ts b/.github/spot-runner-action/src/main.ts index 7b7173f57955..00cbe457dd08 100644 --- a/.github/spot-runner-action/src/main.ts +++ b/.github/spot-runner-action/src/main.ts @@ -88,8 +88,10 @@ async function requestAndWaitForSpot(config: ActionConfig): Promise { // wait 10 seconds await new Promise((r) => setTimeout(r, 5000 * 2 ** backoff)); backoff += 1; - core.info("Polling to see if we somehow have an instance up"); - instanceId = await ec2Client.getInstancesForTags("running")[0]?.instanceId; + if (config.githubActionRunnerConcurrency > 0) { + core.info("Polling to see if we somehow have an instance up"); + instanceId = await ec2Client.getInstancesForTags("running")[0]?.instanceId; + } } if (instanceId) { core.info("Successfully requested/found instance with ID " + instanceId); diff --git a/barretenberg/acir_tests/gen_inner_proof_inputs.sh b/barretenberg/acir_tests/gen_inner_proof_inputs.sh index ea3a2ced8e0a..38392d84d894 100755 --- a/barretenberg/acir_tests/gen_inner_proof_inputs.sh +++ b/barretenberg/acir_tests/gen_inner_proof_inputs.sh @@ -28,18 +28,18 @@ VFLAG=${VERBOSE:+-v} RFLAG=${RECURSIVE:+-r} echo "Write VK to file for assert_statement..." -$BIN write_vk $VFLAG -c $CRS_PATH -o +$BIN write_vk $VFLAG -c $CRS_PATH -o ./target/vk echo "Write VK as fields for recursion..." -$BIN vk_as_fields $VFLAG -c $CRS_PATH +$BIN vk_as_fields $VFLAG -c $CRS_PATH -k ./target/vk -o ./target/vk_fields.json echo "Generate proof to file..." [ -d "$PROOF_DIR" ] || mkdir $PWD/proofs [ -e "$PROOF_PATH" ] || touch $PROOF_PATH -$BIN prove $VFLAG -c $CRS_PATH -b ./target/program.json -o "./proofs/$PROOF_NAME" $RFLAG +$BIN prove $VFLAG -c $CRS_PATH -b ./target/program.json -o "./proofs/$PROOF_NAME" echo "Write proof as fields for recursion..." -$BIN proof_as_fields $VFLAG -c $CRS_PATH -p "./proofs/$PROOF_NAME" +$BIN proof_as_fields $VFLAG -c $CRS_PATH -p "./proofs/$PROOF_NAME" -k ./target/vk -o "./proofs/${PROOF_NAME}_fields.json" cat ./proofs/${PROOF_NAME}_fields.json echo diff --git a/barretenberg/acir_tests/gen_inner_proof_inputs_ultra_honk.sh b/barretenberg/acir_tests/gen_inner_proof_inputs_ultra_honk.sh new file mode 100755 index 000000000000..511a6e9f03ab --- /dev/null +++ b/barretenberg/acir_tests/gen_inner_proof_inputs_ultra_honk.sh @@ -0,0 +1,45 @@ +#!/usr/bin/env bash +# Env var overrides: +# BIN: to specify a different binary to test with (e.g. bb.js or bb.js-dev). +set -eu + +BIN=${BIN:-../cpp/build/bin/bb} +CRS_PATH=~/.bb-crs +BRANCH=master +VERBOSE=${VERBOSE:-} +RECURSIVE=true +PROOF_NAME="proof_a" + +if [ -f $BIN ]; then + BIN=$(realpath $BIN) +else + BIN=$(realpath $(which $BIN)) +fi + +export BRANCH + +./clone_test_vectors.sh + +cd acir_tests/assert_statement_recursive + +PROOF_DIR=$PWD/proofs +PROOF_PATH=$PROOF_DIR/$PROOF_NAME +VFLAG=${VERBOSE:+-v} +RFLAG=${RECURSIVE:+-r} + +echo "Write VK to file for assert_statement..." +$BIN write_vk_ultra_honk $VFLAG -c $CRS_PATH -o ./target/vk + +echo "Write VK as fields for recursion..." +$BIN vk_as_fields_ultra_honk $VFLAG -c $CRS_PATH -k ./target/vk -o ./target/vk_fields.json + +echo "Generate proof to file..." +[ -d "$PROOF_DIR" ] || mkdir $PWD/proofs +[ -e "$PROOF_PATH" ] || touch $PROOF_PATH +$BIN prove_ultra_honk $VFLAG -c $CRS_PATH -b ./target/program.json -o "./proofs/$PROOF_NAME" + +echo "Write proof as fields for recursion..." +$BIN proof_as_fields_honk $VFLAG -c $CRS_PATH -p "./proofs/$PROOF_NAME" -o "./proofs/${PROOF_NAME}_fields.json" + +cat ./proofs/${PROOF_NAME}_fields.json +echo diff --git a/barretenberg/cpp/src/barretenberg/bb/main.cpp b/barretenberg/cpp/src/barretenberg/bb/main.cpp index 9b1df6689436..f8308b5e7c07 100644 --- a/barretenberg/cpp/src/barretenberg/bb/main.cpp +++ b/barretenberg/cpp/src/barretenberg/bb/main.cpp @@ -678,6 +678,62 @@ template void write_vk_honk(const std::string& bytecodePa vinfo("vk written to: ", outputPath); } } + +/** + * @brief Outputs proof as vector of field elements in readable format. + * + * Communication: + * - stdout: The proof as a list of field elements is written to stdout as a string + * - Filesystem: The proof as a list of field elements is written to the path specified by outputPath + * + * + * @param proof_path Path to the file containing the serialized proof + * @param output_path Path to write the proof to + */ +void proof_as_fields_honk(const std::string& proof_path, const std::string& output_path) +{ + auto proof = from_buffer>(read_file(proof_path)); + auto json = proof_to_json(proof); + + if (output_path == "-") { + writeStringToStdout(json); + vinfo("proof as fields written to stdout"); + } else { + write_file(output_path, { json.begin(), json.end() }); + vinfo("proof as fields written to: ", output_path); + } +} + +/** + * @brief Converts a verification key from a byte array into a list of field elements + * + * Why is this needed? + * This follows the same rationale as `proofAsFields`. + * + * Communication: + * - stdout: The verification key as a list of field elements is written to stdout as a string + * - Filesystem: The verification key as a list of field elements is written to the path specified by outputPath + * + * @param vk_path Path to the file containing the serialized verification key + * @param output_path Path to write the verification key to + */ +template void vk_as_fields_honk(const std::string& vk_path, const std::string& output_path) +{ + using VerificationKey = Flavor::VerificationKey; + + auto verification_key = std::make_shared(from_buffer(read_file(vk_path))); + std::vector data = verification_key->to_field_elements(); + + auto json = vk_to_json(data); + if (output_path == "-") { + writeStringToStdout(json); + vinfo("vk as fields written to stdout"); + } else { + write_file(output_path, { json.begin(), json.end() }); + vinfo("vk as fields written to: ", output_path); + } +} + /** * @brief Creates a proof for an ACIR circuit, outputs the proof and verification key in binary and 'field' format * @@ -831,6 +887,15 @@ int main(int argc, char* argv[]) } else if (command == "write_vk_goblin_ultra_honk") { std::string output_path = get_option(args, "-o", "./target/vk"); write_vk_honk(bytecode_path, output_path); + } else if (command == "proof_as_fields_honk") { + std::string output_path = get_option(args, "-o", proof_path + "_fields.json"); + proof_as_fields_honk(proof_path, output_path); + } else if (command == "vk_as_fields_ultra_honk") { + std::string output_path = get_option(args, "-o", vk_path + "_fields.json"); + vk_as_fields_honk(vk_path, output_path); + } else if (command == "vk_as_fields_goblin_ultra_honk") { + std::string output_path = get_option(args, "-o", vk_path + "_fields.json"); + vk_as_fields_honk(vk_path, output_path); } else { std::cerr << "Unknown command: " << command << "\n"; return 1; diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/c_bind.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/c_bind.cpp index 8e1a602a5760..defc038a4d83 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/c_bind.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/c_bind.cpp @@ -230,4 +230,19 @@ WASM_EXPORT void acir_write_vk_ultra_honk(uint8_t const* acir_vec, uint8_t** out ProverInstance prover_inst(builder); VerificationKey vk(prover_inst.proving_key); *out = to_heap_buffer(to_buffer(vk)); +} + +WASM_EXPORT void acir_proof_as_fields_ultra_honk(uint8_t const* proof_buf, fr::vec_out_buf out) +{ + auto proof = from_buffer>(from_buffer>(proof_buf)); + *out = to_heap_buffer(proof); +} + +WASM_EXPORT void acir_vk_as_fields_ultra_honk(uint8_t const* vk_buf, fr::vec_out_buf out_vkey) +{ + using VerificationKey = UltraFlavor::VerificationKey; + + auto verification_key = std::make_shared(from_buffer(vk_buf)); + std::vector vkey_as_fields = verification_key->to_field_elements(); + *out_vkey = to_heap_buffer(vkey_as_fields); } \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/ecc/fields/field_conversion.hpp b/barretenberg/cpp/src/barretenberg/ecc/fields/field_conversion.hpp index 3e6cd34f41e0..e19c535da318 100644 --- a/barretenberg/cpp/src/barretenberg/ecc/fields/field_conversion.hpp +++ b/barretenberg/cpp/src/barretenberg/ecc/fields/field_conversion.hpp @@ -18,7 +18,7 @@ namespace bb::field_conversion { */ template constexpr size_t calc_num_bn254_frs() { - if constexpr (IsAnyOf) { + if constexpr (IsAnyOf) { return 1; } else if constexpr (IsAnyOf) { return T::Params::NUM_BN254_SCALARS; @@ -48,7 +48,7 @@ template T convert_from_bn254_frs(std::span fr_vec) if constexpr (IsAnyOf) { ASSERT(fr_vec.size() == 1); return bool(fr_vec[0]); - } else if constexpr (IsAnyOf) { + } else if constexpr (IsAnyOf) { ASSERT(fr_vec.size() == 1); return static_cast(fr_vec[0]); } else if constexpr (IsAnyOf) { @@ -89,7 +89,7 @@ std::vector convert_grumpkin_fr_to_bn254_frs(const grumpkin::fr& val); */ template std::vector convert_to_bn254_frs(const T& val) { - if constexpr (IsAnyOf) { + if constexpr (IsAnyOf) { std::vector fr_vec{ val }; return fr_vec; } else if constexpr (IsAnyOf) { diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/goblin_ultra_flavor.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/goblin_ultra_flavor.hpp index 7fcfa4d483ef..a417fbe4a97a 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/goblin_ultra_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/goblin_ultra_flavor.hpp @@ -575,6 +575,31 @@ class GoblinUltraFlavor { lagrange_last, lagrange_ecc_op, databus_id); + + /** + * @brief Serialize verification key to field elements + * + * @return std::vector + */ + std::vector to_field_elements() + { + std::vector elements; + std::vector circuit_size_elements = bb::field_conversion::convert_to_bn254_frs(this->circuit_size); + elements.insert(elements.end(), circuit_size_elements.begin(), circuit_size_elements.end()); + // do the same for the rest of the fields + std::vector num_public_inputs_elements = + bb::field_conversion::convert_to_bn254_frs(this->num_public_inputs); + elements.insert(elements.end(), num_public_inputs_elements.begin(), num_public_inputs_elements.end()); + std::vector pub_inputs_offset_elements = + bb::field_conversion::convert_to_bn254_frs(this->pub_inputs_offset); + elements.insert(elements.end(), pub_inputs_offset_elements.begin(), pub_inputs_offset_elements.end()); + + for (Commitment& comm : this->get_all()) { + std::vector comm_elements = bb::field_conversion::convert_to_bn254_frs(comm); + elements.insert(elements.end(), comm_elements.begin(), comm_elements.end()); + } + return elements; + } }; /** * @brief A container for storing the partially evaluated multivariates produced by sumcheck. diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/goblin_ultra_recursive_flavor.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/goblin_ultra_recursive_flavor.hpp index 44f046554295..393014d1f483 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/goblin_ultra_recursive_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/goblin_ultra_recursive_flavor.hpp @@ -102,6 +102,7 @@ template class GoblinUltraRecursiveFlavor_ { public: VerificationKey(const size_t circuit_size, const size_t num_public_inputs) { + // TODO(https://github.com/AztecProtocol/barretenberg/issues/983): Think about if these should be witnesses this->circuit_size = circuit_size; this->log_circuit_size = numeric::get_msb(circuit_size); this->num_public_inputs = num_public_inputs; @@ -151,6 +152,40 @@ template class GoblinUltraRecursiveFlavor_ { this->lagrange_ecc_op = Commitment::from_witness(builder, native_key->lagrange_ecc_op); this->databus_id = Commitment::from_witness(builder, native_key->databus_id); }; + + /** + * @brief Deserialize a verification key from a vector of field elements + * + * @param builder + * @param elements + */ + VerificationKey(CircuitBuilder& builder, std::span elements) + { + // deserialize circuit size + size_t num_frs_read = 0; + size_t num_frs_FF = bb::stdlib::field_conversion::calc_num_bn254_frs(); + size_t num_frs_Comm = bb::stdlib::field_conversion::calc_num_bn254_frs(); + + this->circuit_size = uint64_t(stdlib::field_conversion::convert_from_bn254_frs( + builder, elements.subspan(num_frs_read, num_frs_read + num_frs_FF)) + .get_value()); + num_frs_read += num_frs_FF; + this->num_public_inputs = uint64_t(stdlib::field_conversion::convert_from_bn254_frs( + builder, elements.subspan(num_frs_read, num_frs_read + num_frs_FF)) + .get_value()); + num_frs_read += num_frs_FF; + + this->pub_inputs_offset = uint64_t(stdlib::field_conversion::convert_from_bn254_frs( + builder, elements.subspan(num_frs_read, num_frs_read + num_frs_FF)) + .get_value()); + num_frs_read += num_frs_FF; + + for (Commitment& comm : this->get_all()) { + comm = bb::stdlib::field_conversion::convert_from_bn254_frs( + builder, elements.subspan(num_frs_read, num_frs_read + num_frs_Comm)); + num_frs_read += num_frs_Comm; + } + } }; /** diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_flavor.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_flavor.hpp index fe5dca553f4e..5422535e0d25 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_flavor.hpp @@ -546,6 +546,31 @@ class UltraFlavor { table_4, lagrange_first, lagrange_last); + + /** + * @brief Serialize verification key to field elements + * + * @return std::vector + */ + std::vector to_field_elements() + { + std::vector elements; + std::vector circuit_size_elements = bb::field_conversion::convert_to_bn254_frs(this->circuit_size); + elements.insert(elements.end(), circuit_size_elements.begin(), circuit_size_elements.end()); + // do the same for the rest of the fields + std::vector num_public_inputs_elements = + bb::field_conversion::convert_to_bn254_frs(this->num_public_inputs); + elements.insert(elements.end(), num_public_inputs_elements.begin(), num_public_inputs_elements.end()); + std::vector pub_inputs_offset_elements = + bb::field_conversion::convert_to_bn254_frs(this->pub_inputs_offset); + elements.insert(elements.end(), pub_inputs_offset_elements.begin(), pub_inputs_offset_elements.end()); + + for (Commitment& comm : this->get_all()) { + std::vector comm_elements = bb::field_conversion::convert_to_bn254_frs(comm); + elements.insert(elements.end(), comm_elements.begin(), comm_elements.end()); + } + return elements; + } }; /** diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_recursive_flavor.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_recursive_flavor.hpp index bf2204753412..e72937089d6b 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_recursive_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_recursive_flavor.hpp @@ -274,6 +274,7 @@ template class UltraRecursiveFlavor_ { public: VerificationKey(const size_t circuit_size, const size_t num_public_inputs) { + // TODO(https://github.com/AztecProtocol/barretenberg/issues/983): Think about if these should be witnesses this->circuit_size = circuit_size; this->log_circuit_size = numeric::get_msb(circuit_size); this->num_public_inputs = num_public_inputs; @@ -317,6 +318,40 @@ template class UltraRecursiveFlavor_ { this->lagrange_first = Commitment::from_witness(builder, native_key->lagrange_first); this->lagrange_last = Commitment::from_witness(builder, native_key->lagrange_last); }; + + /** + * @brief Deserialize a verification key from a vector of field elements + * + * @param builder + * @param elements + */ + VerificationKey(CircuitBuilder& builder, std::span elements) + { + // deserialize circuit size + size_t num_frs_read = 0; + size_t num_frs_FF = bb::stdlib::field_conversion::calc_num_bn254_frs(); + size_t num_frs_Comm = bb::stdlib::field_conversion::calc_num_bn254_frs(); + + this->circuit_size = uint64_t(stdlib::field_conversion::convert_from_bn254_frs( + builder, elements.subspan(num_frs_read, num_frs_read + num_frs_FF)) + .get_value()); + num_frs_read += num_frs_FF; + this->num_public_inputs = uint64_t(stdlib::field_conversion::convert_from_bn254_frs( + builder, elements.subspan(num_frs_read, num_frs_read + num_frs_FF)) + .get_value()); + num_frs_read += num_frs_FF; + + this->pub_inputs_offset = uint64_t(stdlib::field_conversion::convert_from_bn254_frs( + builder, elements.subspan(num_frs_read, num_frs_read + num_frs_FF)) + .get_value()); + num_frs_read += num_frs_FF; + + for (Commitment& comm : this->get_all()) { + comm = bb::stdlib::field_conversion::convert_from_bn254_frs( + builder, elements.subspan(num_frs_read, num_frs_read + num_frs_Comm)); + num_frs_read += num_frs_Comm; + } + } }; /** diff --git a/barretenberg/ts/src/barretenberg_api/index.ts b/barretenberg/ts/src/barretenberg_api/index.ts index 44b10c57d8d6..c7972d388693 100644 --- a/barretenberg/ts/src/barretenberg_api/index.ts +++ b/barretenberg/ts/src/barretenberg_api/index.ts @@ -603,6 +603,30 @@ export class BarretenbergApi { const out = result.map((r, i) => outTypes[i].fromBuffer(r)); return out[0]; } + + async acirProofAsFieldsUltraHonk(proofBuf: Uint8Array): Promise { + const inArgs = [proofBuf].map(serializeBufferable); + const outTypes: OutputType[] = [VectorDeserializer(Fr)]; + const result = await this.wasm.callWasmExport( + 'acir_proof_as_fields_ultra_honk', + inArgs, + outTypes.map(t => t.SIZE_IN_BYTES), + ); + const out = result.map((r, i) => outTypes[i].fromBuffer(r)); + return out[0]; + } + + async acirVkAsFieldsUltraHonk(vkBuf: Uint8Array): Promise { + const inArgs = [vkBuf].map(serializeBufferable); + const outTypes: OutputType[] = [VectorDeserializer(Fr)]; + const result = await this.wasm.callWasmExport( + 'acir_vk_as_fields_ultra_honk', + inArgs, + outTypes.map(t => t.SIZE_IN_BYTES), + ); + const out = result.map((r, i) => outTypes[i].fromBuffer(r)); + return out as any; + } } export class BarretenbergApiSync { constructor(protected wasm: BarretenbergWasm) {} @@ -1183,4 +1207,28 @@ export class BarretenbergApiSync { const out = result.map((r, i) => outTypes[i].fromBuffer(r)); return out[0]; } + + acirProofAsFieldsUltraHonk(proofBuf: Uint8Array): Fr[] { + const inArgs = [proofBuf].map(serializeBufferable); + const outTypes: OutputType[] = [VectorDeserializer(Fr)]; + const result = this.wasm.callWasmExport( + 'acir_proof_as_fields_ultra_honk', + inArgs, + outTypes.map(t => t.SIZE_IN_BYTES), + ); + const out = result.map((r, i) => outTypes[i].fromBuffer(r)); + return out[0]; + } + + acirVkAsFieldsUltraHonk(vkBuf: Uint8Array): Fr[] { + const inArgs = [vkBuf].map(serializeBufferable); + const outTypes: OutputType[] = [VectorDeserializer(Fr)]; + const result = this.wasm.callWasmExport( + 'acir_vk_as_fields_ultra_honk', + inArgs, + outTypes.map(t => t.SIZE_IN_BYTES), + ); + const out = result.map((r, i) => outTypes[i].fromBuffer(r)); + return out as any; + } } diff --git a/barretenberg/ts/src/main.ts b/barretenberg/ts/src/main.ts index 2ac32e235442..5e864f7867d8 100755 --- a/barretenberg/ts/src/main.ts +++ b/barretenberg/ts/src/main.ts @@ -416,6 +416,50 @@ export async function verifyUltraHonk(proofPath: string, vkPath: string) { await api.destroy(); } } + +export async function proofAsFieldsUltraHonk(proofPath: string, outputPath: string) { + const { api } = await initLite(); + try { + debug('outputting proof as vector of fields'); + const proofAsFields = await api.acirProofAsFieldsUltraHonk(readFileSync(proofPath)); + const jsonProofAsFields = JSON.stringify(proofAsFields.map(f => f.toString())); + + if (outputPath === '-') { + process.stdout.write(jsonProofAsFields); + debug(`proofAsFieldsUltraHonk written to stdout`); + } else { + writeFileSync(outputPath, jsonProofAsFields); + debug(`proofAsFieldsUltraHonk written to: ${outputPath}`); + } + + debug('done.'); + } finally { + await api.destroy(); + } +} + +export async function vkAsFieldsUltraHonk(vkPath: string, vkeyOutputPath: string) { + const { api } = await initLite(); + + try { + debug('serializing vk byte array into field elements'); + const vkAsFields = await api.acirVkAsFieldsUltraHonk(new RawBuffer(readFileSync(vkPath))); + const jsonVKAsFields = JSON.stringify(vkAsFields.map(f => f.toString())); + + if (vkeyOutputPath === '-') { + process.stdout.write(jsonVKAsFields); + debug(`vkAsFieldsUltraHonk written to stdout`); + } else { + writeFileSync(vkeyOutputPath, jsonVKAsFields); + debug(`vkAsFieldsUltraHonk written to: ${vkeyOutputPath}`); + } + + debug('done.'); + } finally { + await api.destroy(); + } +} + const program = new Command(); program.option('-v, --verbose', 'enable verbose logging', false); @@ -430,7 +474,7 @@ function handleGlobalOptions() { program .command('prove_and_verify') .description('Generate a proof and verify it. Process exits with success or failure code.') - .option('-b, --bytecode-path ', 'Specify the bytecode path', './target/acir.gz') + .option('-b, --bytecode-path ', 'Specify the bytecode path', './target/program.json') .option('-w, --witness-path ', 'Specify the witness path', './target/witness.gz') .action(async ({ bytecodePath, witnessPath, crsPath }) => { handleGlobalOptions(); @@ -441,7 +485,7 @@ program program .command('prove_and_verify_ultra_honk') .description('Generate an UltraHonk proof and verify it. Process exits with success or failure code.') - .option('-b, --bytecode-path ', 'Specify the bytecode path', './target/acir.gz') + .option('-b, --bytecode-path ', 'Specify the bytecode path', './target/program.json') .option('-w, --witness-path ', 'Specify the witness path', './target/witness.gz') .action(async ({ bytecodePath, witnessPath, crsPath }) => { handleGlobalOptions(); @@ -452,7 +496,7 @@ program program .command('prove_and_verify_goblin_ultra_honk') .description('Generate a GUH proof and verify it. Process exits with success or failure code.') - .option('-b, --bytecode-path ', 'Specify the bytecode path', './target/acir.gz') + .option('-b, --bytecode-path ', 'Specify the bytecode path', './target/program.json') .option('-w, --witness-path ', 'Specify the witness path', './target/witness.gz') .action(async ({ bytecodePath, witnessPath, crsPath }) => { handleGlobalOptions(); @@ -463,7 +507,7 @@ program program .command('prove_and_verify_goblin') .description('Generate a Goblin proof and verify it. Process exits with success or failure code.') - .option('-b, --bytecode-path ', 'Specify the bytecode path', './target/acir.gz') + .option('-b, --bytecode-path ', 'Specify the bytecode path', './target/program.json') .option('-w, --witness-path ', 'Specify the witness path', './target/witness.gz') .action(async ({ bytecodePath, witnessPath, crsPath }) => { handleGlobalOptions(); @@ -474,7 +518,7 @@ program program .command('prove') .description('Generate a proof and write it to a file.') - .option('-b, --bytecode-path ', 'Specify the bytecode path', './target/acir.gz') + .option('-b, --bytecode-path ', 'Specify the bytecode path', './target/program.json') .option('-w, --witness-path ', 'Specify the witness path', './target/witness.gz') .option('-o, --output-path ', 'Specify the proof output path', './proofs/proof') .action(async ({ bytecodePath, witnessPath, outputPath, crsPath }) => { @@ -485,7 +529,7 @@ program program .command('gates') .description('Print gate count to standard output.') - .option('-b, --bytecode-path ', 'Specify the bytecode path', './target/acir.gz') + .option('-b, --bytecode-path ', 'Specify the bytecode path', './target/program.json') .action(async ({ bytecodePath: bytecodePath }) => { handleGlobalOptions(); await gateCount(bytecodePath); @@ -505,7 +549,7 @@ program program .command('contract') .description('Output solidity verification key contract.') - .option('-b, --bytecode-path ', 'Specify the bytecode path', './target/acir.gz') + .option('-b, --bytecode-path ', 'Specify the bytecode path', './target/program.json') .option('-o, --output-path ', 'Specify the path to write the contract', './target/contract.sol') .requiredOption('-k, --vk-path ', 'Path to a verification key. avoids recomputation.') .action(async ({ outputPath, vkPath }) => { @@ -516,8 +560,8 @@ program program .command('write_vk') .description('Output verification key.') - .option('-b, --bytecode-path ', 'Specify the bytecode path', './target/acir.gz') - .requiredOption('-o, --output-path ', 'Specify the path to write the key') + .option('-b, --bytecode-path ', 'Specify the bytecode path', './target/program.json') + .option('-o, --output-path ', 'Specify the path to write the key') .action(async ({ bytecodePath, outputPath, crsPath }) => { handleGlobalOptions(); await writeVk(bytecodePath, crsPath, outputPath); @@ -526,7 +570,7 @@ program program .command('write_pk') .description('Output proving key.') - .option('-b, --bytecode-path ', 'Specify the bytecode path', './target/acir.gz') + .option('-b, --bytecode-path ', 'Specify the bytecode path', './target/program.json') .requiredOption('-o, --output-path ', 'Specify the path to write the key') .action(async ({ bytecodePath, outputPath, crsPath }) => { handleGlobalOptions(); @@ -566,7 +610,7 @@ program program .command('prove_ultra_honk') .description('Generate a proof and write it to a file.') - .option('-b, --bytecode-path ', 'Specify the bytecode path', './target/acir.gz') + .option('-b, --bytecode-path ', 'Specify the bytecode path', './target/program.json') .option('-w, --witness-path ', 'Specify the witness path', './target/witness.gz') .option('-o, --output-path ', 'Specify the proof output path', './proofs/proof') .action(async ({ bytecodePath, witnessPath, outputPath, crsPath }) => { @@ -577,7 +621,7 @@ program program .command('write_vk_ultra_honk') .description('Output verification key.') - .option('-b, --bytecode-path ', 'Specify the bytecode path', './target/acir.gz') + .option('-b, --bytecode-path ', 'Specify the bytecode path', './target/program.json') .requiredOption('-o, --output-path ', 'Specify the path to write the key') .action(async ({ bytecodePath, outputPath, crsPath }) => { handleGlobalOptions(); @@ -595,4 +639,24 @@ program process.exit(result ? 0 : 1); }); +program + .command('proof_as_fields_honk') + .description('Return the proof as fields elements') + .requiredOption('-p, --proof-path ', 'Specify the proof path') + .requiredOption('-o, --output-path ', 'Specify the JSON path to write the proof fields') + .action(async ({ proofPath, outputPath }) => { + handleGlobalOptions(); + await proofAsFieldsUltraHonk(proofPath, outputPath); + }); + +program + .command('vk_as_fields_ultra_honk') + .description('Return the verification key represented as fields elements.') + .requiredOption('-k, --vk-path ', 'Path to verification key.') + .requiredOption('-o, --output-path ', 'Specify the JSON path to write the verification key fields.') + .action(async ({ vkPath, outputPath }) => { + handleGlobalOptions(); + await vkAsFieldsUltraHonk(vkPath, outputPath); + }); + program.name('bb.js').parse(process.argv);