-
Notifications
You must be signed in to change notification settings - Fork 316
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
feat: vk_as_fields, proof_as_fields flows for honk #6406
Changes from 8 commits
a15b58e
942e76f
3a272ac
131bb5a
d00ce3d
fcd4fa0
1769a99
a74b1b4
1d8acfe
1b0764d
aed566b
46a8a09
0f40b9c
3f5a4aa
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
#!/usr/bin/env bash | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. new one just for honk, could just merge into one potentially There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if we are going to get rid of the plonk one i could be OK without a merge There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. that's true, will just delete this down the line |
||
# 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 |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -678,6 +678,62 @@ template <IsUltraFlavor Flavor> void write_vk_honk(const std::string& bytecodePa | |
vinfo("vk written to: ", outputPath); | ||
} | ||
} | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. new flows for bb binary |
||
/** | ||
* @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<std::vector<bb::fr>>(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 <IsUltraFlavor Flavor> 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<VerificationKey>(from_buffer<VerificationKey>(read_file(vk_path))); | ||
std::vector<bb::fr> 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<GoblinUltraFlavor>(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<UltraFlavor>(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<GoblinUltraFlavor>(vk_path, output_path); | ||
} else { | ||
std::cerr << "Unknown command: " << command << "\n"; | ||
return 1; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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)); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. new flows for wasm There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. could add a comment here |
||
|
||
WASM_EXPORT void acir_proof_as_fields_ultra_honk(uint8_t const* proof_buf, fr::vec_out_buf out) | ||
{ | ||
auto proof = from_buffer<std::vector<bb::fr>>(from_buffer<std::vector<uint8_t>>(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<VerificationKey>(from_buffer<VerificationKey>(vk_buf)); | ||
std::vector<bb::fr> vkey_as_fields = verification_key->to_field_elements(); | ||
*out_vkey = to_heap_buffer(vkey_as_fields); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -546,6 +546,31 @@ class UltraFlavor { | |
table_4, | ||
lagrange_first, | ||
lagrange_last); | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. new serialization of vkey to field elements. Does not serialize the verifier commitment key. |
||
/** | ||
* @brief Serialize verification key to field elements | ||
* | ||
* @return std::vector<FF> | ||
*/ | ||
std::vector<FF> to_field_elements() | ||
{ | ||
std::vector<FF> elements; | ||
std::vector<FF> 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<FF> 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<FF> 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<FF> comm_elements = bb::field_conversion::convert_to_bn254_frs(comm); | ||
elements.insert(elements.end(), comm_elements.begin(), comm_elements.end()); | ||
} | ||
return elements; | ||
} | ||
}; | ||
|
||
/** | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -317,6 +317,43 @@ template <typename BuilderType> class UltraRecursiveFlavor_ { | |
this->lagrange_first = Commitment::from_witness(builder, native_key->lagrange_first); | ||
this->lagrange_last = Commitment::from_witness(builder, native_key->lagrange_last); | ||
}; | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. new deserialization of recursive vkey from field elements. Note that the witness values for circuit_size, num_public_inputs, and pub_inputs_offset are just discarded and their native values are stored instead. This probably deserves further scrutiny, but I don't think they have to be witness values because the proof contains them as witness values anyway. We should figure this out more clearly at some point. |
||
/** | ||
* @brief Deserialize a verification key from a vector of field elements | ||
* | ||
* @param builder | ||
* @param elements | ||
*/ | ||
VerificationKey(CircuitBuilder& builder, std::span<FF> elements) | ||
{ | ||
// deserialize circuit size | ||
size_t num_frs_read = 0; | ||
size_t num_element_frs = bb::stdlib::field_conversion::calc_num_bn254_frs<CircuitBuilder, FF>(); | ||
this->circuit_size = uint64_t(bb::stdlib::field_conversion::convert_from_bn254_frs<CircuitBuilder, FF>( | ||
builder, elements.subspan(num_frs_read, num_frs_read + num_element_frs)) | ||
.get_value()); | ||
num_frs_read += num_element_frs; | ||
num_element_frs = bb::stdlib::field_conversion::calc_num_bn254_frs<CircuitBuilder, FF>(); | ||
this->num_public_inputs = | ||
uint64_t(bb::stdlib::field_conversion::convert_from_bn254_frs<CircuitBuilder, FF>( | ||
builder, elements.subspan(num_frs_read, num_frs_read + num_element_frs)) | ||
.get_value()); | ||
num_frs_read += num_element_frs; | ||
|
||
num_element_frs = bb::stdlib::field_conversion::calc_num_bn254_frs<CircuitBuilder, FF>(); | ||
this->pub_inputs_offset = | ||
uint64_t(bb::stdlib::field_conversion::convert_from_bn254_frs<CircuitBuilder, FF>( | ||
builder, elements.subspan(num_frs_read, num_frs_read + num_element_frs)) | ||
.get_value()); | ||
num_frs_read += num_element_frs; | ||
|
||
for (Commitment& comm : this->get_all()) { | ||
num_element_frs = bb::stdlib::field_conversion::calc_num_bn254_frs<CircuitBuilder, Commitment>(); | ||
comm = bb::stdlib::field_conversion::convert_from_bn254_frs<CircuitBuilder, Commitment>( | ||
builder, elements.subspan(num_frs_read, num_frs_read + num_element_frs)); | ||
num_frs_read += num_element_frs; | ||
} | ||
} | ||
}; | ||
|
||
/** | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added a bunch of options because main.ts didn't set default options. This script did not work for the wasm flow before this