13 #include "zeth_config.h"
15 #include <boost/program_options.hpp>
17 #include <grpc/grpc.h>
18 #include <grpcpp/security/server_credentials.h>
19 #include <grpcpp/server.h>
20 #include <grpcpp/server_builder.h>
21 #include <grpcpp/server_context.h>
22 #include <libsnark/common/data_structures/merkle_tree.hpp>
26 #include <zeth/api/prover.grpc.pb.h>
34 namespace proto = google::protobuf;
35 namespace po = boost::program_options;
37 static void prover_configuration_to_proto(
38 zeth_proto::ProverConfiguration &prover_config_proto)
41 libzeth::pairing_parameters_to_proto<pp>(
42 *prover_config_proto.mutable_pairing_parameters());
54 snark::keypair keypair;
57 boost::filesystem::path extproof_json_output_file;
60 boost::filesystem::path proof_output_file;
63 boost::filesystem::path primary_output_file;
66 boost::filesystem::path assignment_output_file;
71 const snark::keypair &keypair,
72 const boost::filesystem::path &extproof_json_output_file,
73 const boost::filesystem::path &proof_output_file,
74 const boost::filesystem::path &primary_output_file,
75 const boost::filesystem::path &assignment_output_file)
78 , extproof_json_output_file(extproof_json_output_file)
79 , proof_output_file(proof_output_file)
80 , primary_output_file(primary_output_file)
81 , assignment_output_file(assignment_output_file)
86 grpc::ServerContext *,
88 zeth_proto::ProverConfiguration *response)
override
90 std::cout <<
"[ACK] Received the request for configuration\n";
91 prover_configuration_to_proto(*response);
92 return grpc::Status::OK;
96 grpc::ServerContext *,
100 std::cout <<
"[ACK] Received the request to get the verification key"
102 std::cout <<
"[DEBUG] Preparing verification key for response..."
105 api_handler::verification_key_to_proto(this->keypair.vk, response);
106 }
catch (
const std::exception &e) {
107 std::cout <<
"[ERROR] " << e.what() << std::endl;
109 grpc::StatusCode::INVALID_ARGUMENT, grpc::string(e.what()));
111 std::cout <<
"[ERROR] In catch all" << std::endl;
112 return grpc::Status(grpc::StatusCode::UNKNOWN,
"");
115 return grpc::Status::OK;
119 grpc::ServerContext *,
120 const zeth_proto::ProofInputs *proof_inputs,
121 zeth_proto::ExtendedProofAndPublicData *proof_and_public_data)
override
123 std::cout <<
"[ACK] Received the request to generate a proof"
125 std::cout <<
"[DEBUG] Parse received message to compute proof..."
132 Field root = libzeth::base_field_element_from_hex<Field>(
133 proof_inputs->mk_root());
143 if (libzeth::ZETH_NUM_JS_INPUTS != proof_inputs->js_inputs_size()) {
144 std::cout <<
"[INFO] Request with "
145 << proof_inputs->js_inputs_size()
146 <<
" inputs. Expecting "
147 << libzeth::ZETH_NUM_JS_INPUTS <<
"\n";
148 throw std::invalid_argument(
"Invalid number of JS inputs");
150 if (libzeth::ZETH_NUM_JS_OUTPUTS !=
151 proof_inputs->js_outputs_size()) {
152 throw std::invalid_argument(
"Invalid number of JS outputs");
155 std::cout <<
"[DEBUG] Process all inputs of the JoinSplit"
159 joinsplit_input<Field, libzeth::ZETH_MERKLE_TREE_DEPTH>,
160 libzeth::ZETH_NUM_JS_INPUTS>
162 for (
size_t i = 0; i < libzeth::ZETH_NUM_JS_INPUTS; i++) {
164 "\r input (%zu / %zu)\n", i, libzeth::ZETH_NUM_JS_INPUTS);
165 const zeth_proto::JoinsplitInput &received_input =
166 proof_inputs->js_inputs(i);
169 libzeth::ZETH_MERKLE_TREE_DEPTH>(received_input);
172 std::cout <<
"[DEBUG] Process all outputs of the JoinSplit"
174 std::array<libzeth::zeth_note, libzeth::ZETH_NUM_JS_OUTPUTS>
176 for (
size_t i = 0; i < libzeth::ZETH_NUM_JS_OUTPUTS; i++) {
178 "\r output (%zu / %zu)\n",
180 libzeth::ZETH_NUM_JS_OUTPUTS);
181 const zeth_proto::ZethNote &received_output =
182 proof_inputs->js_outputs(i);
185 joinsplit_outputs[i] = parsed_output;
188 std::cout <<
"[DEBUG] Data parsed successfully" << std::endl;
189 std::cout <<
"[DEBUG] Generating the proof..." << std::endl;
191 std::vector<Field> public_data;
203 std::cout <<
"[DEBUG] Displaying extended proof and public data\n";
205 for (
const Field &f : public_data) {
210 if (!extproof_json_output_file.empty()) {
211 std::cout <<
"[DEBUG] Writing extended proof (JSON) to "
212 << extproof_json_output_file <<
"\n";
213 std::ofstream out_s(extproof_json_output_file.c_str());
216 if (!proof_output_file.empty()) {
217 std::cout <<
"[DEBUG] Writing proof to " << proof_output_file
219 std::ofstream out_s =
221 snark::proof_write_bytes(ext_proof.
get_proof(), out_s);
223 if (!primary_output_file.empty()) {
224 std::cout <<
"[DEBUG] Writing primary input to "
225 << primary_output_file <<
"\n";
227 primary_output_file.c_str());
231 if (!assignment_output_file.empty()) {
232 std::cout <<
"[DEBUG] WARNING! Writing assignment to "
233 << assignment_output_file <<
"\n";
235 assignment_output_file.c_str());
240 std::cout <<
"[DEBUG] Preparing response..." << std::endl;
241 api_handler::extended_proof_to_proto(
242 ext_proof, proof_and_public_data->mutable_extended_proof());
243 for (
size_t i = 0; i < public_data.size(); ++i) {
244 proof_and_public_data->add_public_data(
248 }
catch (
const std::exception &e) {
249 std::cout <<
"[ERROR] " << e.what() << std::endl;
251 grpc::StatusCode::INVALID_ARGUMENT, grpc::string(e.what()));
253 std::cout <<
"[ERROR] In catch all" << std::endl;
254 return grpc::Status(grpc::StatusCode::UNKNOWN,
"");
257 return grpc::Status::OK;
267 buffer, 100,
"Version %d.%d", ZETH_VERSION_MAJOR, ZETH_VERSION_MINOR);
269 return "Version <Not specified>";
277 std::string copyright =
278 "Copyright (c) 2015-2022 Clearmatics Technologies Ltd";
279 std::string license =
"SPDX-License-Identifier: LGPL-3.0+";
280 std::string project =
281 "R&D Department: PoC for Zerocash on Ethereum/Autonity";
283 std::string warning =
"**WARNING:** This code is a research-quality proof "
284 "of concept, DO NOT use in production!";
286 std::cout <<
"\n=====================================================\n";
287 std::cout << copyright <<
"\n";
288 std::cout << license <<
"\n";
289 std::cout << project <<
"\n";
291 std::cout << warning <<
"\n";
292 std::cout <<
"=====================================================\n"
296 static void RunServer(
298 const typename snark::keypair &keypair,
299 const boost::filesystem::path &extproof_json_output_file,
300 const boost::filesystem::path &proof_output_file,
301 const boost::filesystem::path &primary_output_file,
302 const boost::filesystem::path &assignment_output_file)
305 std::string server_address(
"0.0.0.0:50051");
310 extproof_json_output_file,
313 assignment_output_file);
315 grpc::ServerBuilder builder;
318 builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
322 builder.RegisterService(&service);
325 std::unique_ptr<grpc::Server> server(builder.BuildAndStart());
326 std::cout <<
"[INFO] Server listening on " << server_address <<
"\n";
334 int main(
int argc,
char **argv)
337 po::options_description options(
"Options");
338 options.add_options()(
"help,h",
"This help");
339 options.add_options()(
341 po::value<boost::filesystem::path>(),
342 "file to load keypair from. If it doesn't exist, a new keypair will be "
343 "generated and written to this file. (default: "
344 "~/zeth_setup/keypair.bin)");
345 options.add_options()(
347 po::value<boost::filesystem::path>(),
348 "file in which to export the r1cs (in json format)");
349 options.add_options()(
350 "proving-key-output",
351 po::value<boost::filesystem::path>(),
352 "write proving key to file (if generated)");
353 options.add_options()(
354 "verification-key-output",
355 po::value<boost::filesystem::path>(),
356 "write verification key to file (if generated)");
357 options.add_options()(
358 "extproof-json-output",
359 po::value<boost::filesystem::path>(),
360 "(DEBUG) write generated extended proofs (JSON) to file");
361 options.add_options()(
363 po::value<boost::filesystem::path>(),
364 "(DEBUG) write generated proofs to file");
365 options.add_options()(
367 po::value<boost::filesystem::path>(),
368 "(DEBUG) write primary input to file");
369 options.add_options()(
371 po::value<boost::filesystem::path>(),
372 "(DEBUG) write full assignment to file (INSECURE!)");
375 std::cout <<
"Usage:"
377 <<
" " << argv[0] <<
" [<options>]\n"
379 std::cout << options;
380 std::cout << std::endl;
383 boost::filesystem::path keypair_file;
384 boost::filesystem::path r1cs_file;
385 boost::filesystem::path proving_key_output_file;
386 boost::filesystem::path verification_key_output_file;
387 boost::filesystem::path extproof_json_output_file;
388 boost::filesystem::path proof_output_file;
389 boost::filesystem::path primary_output_file;
390 boost::filesystem::path assignment_output_file;
392 po::variables_map vm;
394 po::command_line_parser(argc, argv).options(options).run(), vm);
395 if (vm.count(
"help")) {
399 if (vm.count(
"keypair")) {
400 keypair_file = vm[
"keypair"].as<boost::filesystem::path>();
402 if (vm.count(
"r1cs")) {
403 r1cs_file = vm[
"r1cs"].as<boost::filesystem::path>();
405 if (vm.count(
"proving-key-output")) {
406 proving_key_output_file =
407 vm[
"proving-key-output"].as<boost::filesystem::path>();
409 if (vm.count(
"verification-key-output")) {
410 verification_key_output_file =
411 vm[
"verification-key-output"].as<boost::filesystem::path>();
413 if (vm.count(
"extproof-json-output")) {
414 extproof_json_output_file =
415 vm[
"extproof-json-output"].as<boost::filesystem::path>();
417 if (vm.count(
"proof-output")) {
419 vm[
"proof-output"].as<boost::filesystem::path>();
421 if (vm.count(
"primary-output")) {
422 primary_output_file =
423 vm[
"primary-output"].as<boost::filesystem::path>();
425 if (vm.count(
"assignment-output")) {
426 assignment_output_file =
427 vm[
"assignment-output"].as<boost::filesystem::path>();
429 }
catch (po::error &error) {
430 std::cerr <<
" ERROR: " << error.what() << std::endl;
436 if (keypair_file.empty()) {
437 boost::filesystem::path setup_dir =
439 if (!setup_dir.empty()) {
440 boost::filesystem::create_directories(setup_dir);
442 keypair_file = setup_dir /
"keypair.bin";
446 std::cout <<
"[INFO] Init params (" << libzeth::pp_name<pp>() <<
")\n";
447 pp::init_public_params();
452 snark::keypair keypair = [&keypair_file,
453 &proving_key_output_file,
454 &verification_key_output_file,
456 if (boost::filesystem::exists(keypair_file)) {
457 std::cout <<
"[INFO] Loading keypair: " << keypair_file <<
"\n";
459 snark::keypair keypair;
462 snark::keypair_read_bytes(keypair, in_s);
466 std::cout <<
"[INFO] No keypair file " << keypair_file
467 <<
". Generating.\n";
470 if (!proving_key_output_file.empty()) {
471 std::cout <<
"[DEBUG] Writing separate proving key to "
472 << proving_key_output_file <<
"\n";
474 proving_key_output_file.c_str());
475 snark::proving_key_write_bytes(keypair.pk, out_s);
477 if (!verification_key_output_file.empty()) {
478 std::cout <<
"[DEBUG] Writing separate verification key to "
479 << verification_key_output_file <<
"\n";
481 verification_key_output_file.c_str());
482 snark::verification_key_write_bytes(keypair.vk, out_s);
487 std::cout <<
"[INFO] Writing new keypair to " << keypair_file <<
"\n";
488 std::ofstream out_s =
490 snark::keypair_write_bytes(keypair, out_s);
497 if (!r1cs_file.empty()) {
498 std::cout <<
"[INFO] Writing R1CS to " << r1cs_file <<
"\n";
499 std::ofstream r1cs_stream(r1cs_file.c_str());
503 std::cout <<
"[INFO] Setup successful, starting the server..." << std::endl;
507 extproof_json_output_file,
510 assignment_output_file);