From 656f479b535bc7837c8b1fa8532e1c2088d648e5 Mon Sep 17 00:00:00 2001 From: Duncan Tebbs Date: Wed, 31 Mar 2021 12:28:01 +0100 Subject: [PATCH] verifier: simple app to verify generated proof against verification key --- CMakeLists.txt | 1 + verifier/CMakeLists.txt | 14 ++++ verifier/verifier.cpp | 163 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 178 insertions(+) create mode 100644 verifier/CMakeLists.txt create mode 100644 verifier/verifier.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 69f4b17e4..ca975bf20 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -315,6 +315,7 @@ add_subdirectory(libzeth) # If zeth is being used as a dependency, skip the tools build if ("${IS_ZETH_PARENT}") add_subdirectory(prover_server) + add_subdirectory(verifier) # For now the MPC for Groth16 only is tailored to the alt_bn128 pairing group if((${ZETH_SNARK} STREQUAL "GROTH16") AND (${MPC})) add_subdirectory(mpc_tools) diff --git a/verifier/CMakeLists.txt b/verifier/CMakeLists.txt new file mode 100644 index 000000000..58a39be0e --- /dev/null +++ b/verifier/CMakeLists.txt @@ -0,0 +1,14 @@ + +find_package(Boost REQUIRED COMPONENTS system filesystem program_options) + +file(GLOB_RECURSE VERIFIER_SOURCE **.?pp **.tcc) +add_executable(verifier ${VERIFIER_SOURCE}) +target_include_directories(verifier PRIVATE SYSTEM ${Boost_INCLUDE_DIR}) +target_link_libraries( + verifier + + zeth + ${Boost_SYSTEM_LIBRARY} + ${Boost_FILESYSTEM_LIBRARY} + ${Boost_PROGRAM_OPTIONS_LIBRARY} + ) diff --git a/verifier/verifier.cpp b/verifier/verifier.cpp new file mode 100644 index 000000000..f85624ea3 --- /dev/null +++ b/verifier/verifier.cpp @@ -0,0 +1,163 @@ +// Copyright (c) 2015-2021 Clearmatics Technologies Ltd +// +// SPDX-License-Identifier: LGPL-3.0+ + +#include "libzeth/serialization/r1cs_variable_assignment_serialization.hpp" +#include "libzeth/snarks/groth16/groth16_snark.hpp" +#include "libzeth/snarks/pghr13/pghr13_snark.hpp" + +#include +#include +#include +#include +#include +#include + +namespace po = boost::program_options; + +static std::ifstream open_file(const std::string &filename) +{ + std::ifstream in_s( + filename.c_str(), std::ios_base::in | std::ios_base::binary); + in_s.exceptions( + std::ios_base::eofbit | std::ios_base::badbit | std::ios_base::failbit); + return in_s; +} + +template +int verifier_main( + const std::string &vk_file, + const std::string &primary_input_file, + const std::string &proof_file) +{ + ppT::init_public_params(); + libff::inhibit_profiling_info = true; + libff::inhibit_profiling_counters = true; + + typename snarkT::verification_key verification_key; + { + std::ifstream in_s = open_file(vk_file); + snarkT::verification_key_read_bytes(verification_key, in_s); + } + + libsnark::r1cs_primary_input> primary_input; + { + std::ifstream in_s = open_file(primary_input_file); + libzeth::r1cs_variable_assignment_read_bytes(primary_input, in_s); + } + + typename snarkT::proof proof; + { + std::ifstream in_s = open_file(proof_file); + snarkT::proof_read_bytes(proof, in_s); + } + + if (!snarkT::verify(primary_input, proof, verification_key)) { + std::cout << "verification failed.\n"; + return 1; + } + + return 0; +} + +template +int verifier_resolve_snark( + const std::string &vk_file, + const std::string &primary_input_file, + const std::string &proof_file, + const std::string &snark) +{ + if (snark == "groth16") { + return verifier_main>( + vk_file, primary_input_file, proof_file); + } else if (snark == "pghr13") { + return verifier_main>( + vk_file, primary_input_file, proof_file); + } + + throw po::error("unrecognized snark"); +} + +int verifier_resolve_curve( + const std::string &vk_file, + const std::string &primary_input_file, + const std::string &proof_file, + const std::string &curve, + const std::string &snark) +{ + if (curve == "alt-bn128") { + return verifier_resolve_snark( + vk_file, primary_input_file, proof_file, snark); + } else if (curve == "bls12-377") { + return verifier_resolve_snark( + vk_file, primary_input_file, proof_file, snark); + } else if (curve == "bw6-761") { + return verifier_resolve_snark( + vk_file, primary_input_file, proof_file, snark); + } + + throw po::error("unrecognized curve"); +} + +int main(int argc, char **argv) +{ + // Options + po::options_description options("Options"); + options.add_options()( + "curve,c", + po::value(), + "Curve: alt-bn128, bls12-377 or bw6-761"); + options.add_options()( + "snark,s", po::value(), "Snark: groth16 or pghr13"); + + po::options_description all_options(options); + all_options.add_options()( + "vk_file", po::value(), "Verification key file"); + all_options.add_options()( + "primary_input_file", po::value(), "Proof file"); + all_options.add_options()( + "proof_file", po::value(), "Proof file"); + + po::positional_options_description pos; + pos.add("vk_file", 1); + pos.add("primary_input_file", 1); + pos.add("proof_file", 1); + + try { + po::parsed_options parsed = po::command_line_parser{argc, argv} + .options(all_options) + .positional(pos) + .run(); + po::variables_map vm; + po::store(parsed, vm); + + if (0 == vm.count("vk_file")) { + throw po::error("vk_file not specified"); + } + if (0 == vm.count("primary_input_file")) { + throw po::error("primary_input_file not specified"); + } + if (0 == vm.count("proof_file")) { + throw po::error("proof_file not specified"); + } + std::string vk_file = vm["vk_file"].as(); + std::string proof_file = vm["proof_file"].as(); + std::string primary_input_file = + vm["primary_input_file"].as(); + std::string curve = + vm.count("curve") ? vm["curve"].as() : "alt-bn128"; + std::string snark = + vm.count("snark") ? vm["snark"].as() : "groth16"; + + verifier_resolve_curve( + vk_file, primary_input_file, proof_file, curve, snark); + } catch (po::error &error) { + std::cerr << " ERROR: " << error.what() << "\n"; + std::cout + << "Usage:\n" + << " " << argv[0] + << " [] \n\n" + << options << std::endl; + return 1; + } +}