-
Notifications
You must be signed in to change notification settings - Fork 310
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: solidity honk verifier (#5485)
This PR introduces a Honk Verifier for 3 different types of circuit. - The logic in each circuit is duplicated as (at the time of writing) solidity does not allow for generic data structures, so as the constants (LOG_N) are different, then each transcript needs to compile with a new log_n value. - In follow up prs i will adjust the tests to run against acir artifacts, where we will codegen the verifier, so i can remove all but the basic case in this test suite Note: this is not an optimal impl, that will follow As this uses padded proofs, in which N is 2^28, the proof verification cost has shot up to 1 793 675.
- Loading branch information
Showing
52 changed files
with
8,038 additions
and
164 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
18 changes: 17 additions & 1 deletion
18
barretenberg/cpp/src/barretenberg/solidity_helpers/CMakeLists.txt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
90 changes: 90 additions & 0 deletions
90
barretenberg/cpp/src/barretenberg/solidity_helpers/honk_key_gen.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
|
||
#include <iostream> | ||
#include <memory> | ||
|
||
#include "barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp" | ||
#include "barretenberg/ultra_honk/ultra_prover.hpp" | ||
#include "barretenberg/ultra_honk/ultra_verifier.hpp" | ||
|
||
#include "./honk_sol_gen.hpp" | ||
|
||
#include "circuits/add_2_circuit.hpp" | ||
#include "circuits/blake_circuit.hpp" | ||
#include "circuits/ecdsa_circuit.hpp" | ||
|
||
using namespace bb; | ||
|
||
using ProverInstance = ProverInstance_<UltraKeccakFlavor>; | ||
using VerificationKey = UltraKeccakFlavor::VerificationKey; | ||
|
||
template <template <typename> typename Circuit> | ||
void generate_keys_honk(std::string output_path, std::string flavour_prefix, std::string circuit_name) | ||
{ | ||
uint256_t public_inputs[4] = { 0, 0, 0, 0 }; | ||
UltraCircuitBuilder builder = Circuit<UltraCircuitBuilder>::generate(public_inputs); | ||
|
||
auto instance = std::make_shared<ProverInstance>(builder); | ||
UltraKeccakProver prover(instance); | ||
auto verification_key = std::make_shared<VerificationKey>(instance->proving_key); | ||
|
||
// Make verification key file upper case | ||
circuit_name.at(0) = static_cast<char>(std::toupper(static_cast<unsigned char>(circuit_name.at(0)))); | ||
flavour_prefix.at(0) = static_cast<char>(std::toupper(static_cast<unsigned char>(flavour_prefix.at(0)))); | ||
|
||
std::string vk_class_name = circuit_name + flavour_prefix + "VerificationKey"; | ||
std::string base_class_name = "Base" + flavour_prefix + "Verifier"; | ||
std::string instance_class_name = circuit_name + flavour_prefix + "Verifier"; | ||
|
||
{ | ||
auto vk_filename = output_path + "/keys/" + vk_class_name + ".sol"; | ||
std::ofstream os(vk_filename); | ||
bb::output_vk_sol_ultra_honk(os, verification_key, vk_class_name); | ||
info("VK contract written to: ", vk_filename); | ||
} | ||
} | ||
|
||
/* | ||
* @brief Main entry point for the verification key generator | ||
* | ||
* 1. project_root_path: path to the solidity project root | ||
* 2. srs_path: path to the srs db | ||
*/ | ||
int main(int argc, char** argv) | ||
{ | ||
std::vector<std::string> args(argv, argv + argc); | ||
|
||
if (args.size() < 5) { | ||
info("usage: ", args[0], "[plonk flavour] [circuit flavour] [output path] [srs path]"); | ||
return 1; | ||
} | ||
|
||
const std::string plonk_flavour = args[1]; | ||
const std::string circuit_flavour = args[2]; | ||
const std::string output_path = args[3]; | ||
const std::string srs_path = args[4]; | ||
|
||
bb::srs::init_crs_factory(srs_path); | ||
// @todo - Add support for unrolled standard verifier. Needs a new solidity verifier contract. | ||
|
||
if (plonk_flavour != "honk") { | ||
info("honk"); | ||
return 1; | ||
} | ||
|
||
info("Generating ", plonk_flavour, " keys for ", circuit_flavour, " circuit"); | ||
|
||
if (plonk_flavour == "honk") { | ||
if (circuit_flavour == "add2") { | ||
generate_keys_honk<Add2Circuit>(output_path, plonk_flavour, circuit_flavour); | ||
} else if (circuit_flavour == "blake") { | ||
generate_keys_honk<BlakeCircuit>(output_path, plonk_flavour, circuit_flavour); | ||
} else if (circuit_flavour == "ecdsa") { | ||
generate_keys_honk<bb::EcdsaCircuit>(output_path, plonk_flavour, circuit_flavour); | ||
// TODO: recursive proofs | ||
} else { | ||
info("Unsupported circuit"); | ||
return 1; | ||
} | ||
} | ||
return 0; | ||
} // namespace bb |
105 changes: 105 additions & 0 deletions
105
barretenberg/cpp/src/barretenberg/solidity_helpers/honk_proof_gen.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
|
||
#include "barretenberg/honk/proof_system/types/proof.hpp" | ||
#include "barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp" | ||
#include "barretenberg/ultra_honk/ultra_prover.hpp" | ||
#include "barretenberg/ultra_honk/ultra_verifier.hpp" | ||
|
||
#include "circuits/add_2_circuit.hpp" | ||
#include "circuits/blake_circuit.hpp" | ||
#include "circuits/ecdsa_circuit.hpp" | ||
#include "utils/utils.hpp" | ||
|
||
#include <iostream> | ||
#include <sstream> | ||
|
||
using namespace bb; | ||
using numeric::uint256_t; | ||
|
||
using ProverInstance = ProverInstance_<UltraKeccakFlavor>; | ||
using VerificationKey = UltraKeccakFlavor::VerificationKey; | ||
using Prover = UltraKeccakProver; | ||
using Verifier = UltraKeccakVerifier; | ||
|
||
template <template <typename> typename Circuit> void generate_proof(uint256_t inputs[]) | ||
{ | ||
|
||
UltraCircuitBuilder builder = Circuit<UltraCircuitBuilder>::generate(inputs); | ||
|
||
auto instance = std::make_shared<ProverInstance>(builder); | ||
Prover prover(instance); | ||
auto verification_key = std::make_shared<VerificationKey>(instance->proving_key); | ||
Verifier verifier(verification_key); | ||
|
||
HonkProof proof = prover.construct_proof(); | ||
{ | ||
if (!verifier.verify_proof(proof)) { | ||
throw_or_abort("Verification failed"); | ||
} | ||
|
||
std::vector<uint8_t> proof_bytes = to_buffer(proof); | ||
std::string p = bytes_to_hex_string(proof_bytes); | ||
std::cout << p; | ||
} | ||
} | ||
|
||
std::string pad_left(std::string input, size_t length) | ||
{ | ||
return std::string(length - std::min(length, input.length()), '0') + input; | ||
} | ||
|
||
/** | ||
* @brief Main entry point for the proof generator. | ||
* Expected inputs: | ||
* 1. plonk_flavour: ultra | ||
* 2. circuit_flavour: blake, add2 | ||
* 3. public_inputs: comma separated list of public inputs | ||
* 4. project_root_path: path to the solidity project root | ||
* 5. srs_path: path to the srs db | ||
*/ | ||
int main(int argc, char** argv) | ||
{ | ||
std::vector<std::string> args(argv, argv + argc); | ||
|
||
if (args.size() < 5) { | ||
info("usage: ", args[0], "[plonk flavour] [circuit flavour] [srs path] [public inputs]"); | ||
return 1; | ||
} | ||
|
||
const std::string plonk_flavour = args[1]; | ||
const std::string circuit_flavour = args[2]; | ||
const std::string srs_path = args[3]; | ||
const std::string string_input = args[4]; | ||
|
||
bb::srs::init_crs_factory(srs_path); | ||
|
||
// @todo dynamically allocate this | ||
uint256_t inputs[] = { 0, 0, 0, 0, 0, 0 }; | ||
|
||
size_t count = 0; | ||
std::stringstream s_stream(string_input); | ||
while (s_stream.good()) { | ||
std::string sub; | ||
getline(s_stream, sub, ','); | ||
if (sub.substr(0, 2) == "0x") { | ||
sub = sub.substr(2); | ||
} | ||
std::string padded = pad_left(sub, 64); | ||
inputs[count++] = uint256_t(padded); | ||
} | ||
|
||
if (plonk_flavour != "honk") { | ||
info("Only honk flavor allowed"); | ||
return 1; | ||
} | ||
|
||
if (circuit_flavour == "blake") { | ||
generate_proof<BlakeCircuit>(inputs); | ||
} else if (circuit_flavour == "add2") { | ||
generate_proof<Add2Circuit>(inputs); | ||
} else if (circuit_flavour == "ecdsa") { | ||
generate_proof<EcdsaCircuit>(inputs); | ||
} else { | ||
info("Invalid circuit flavour: " + circuit_flavour); | ||
return 1; | ||
} | ||
} |
Oops, something went wrong.