Skip to content

Commit

Permalink
libzecale: verification key hash check in aggregator circuit
Browse files Browse the repository at this point in the history
  • Loading branch information
dtebbs committed Aug 24, 2020
1 parent 7b60e59 commit 58525f1
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 22 deletions.
10 changes: 6 additions & 4 deletions aggregator_server/aggregator_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,13 @@ using napi_handler = libzeth::groth16_api_handler<npp>;
#endif

using nsnark = typename nverifier::snark;
using hash = libzeth::BLAKE2s_256<libff::Fr<wpp>>;

static const size_t batch_size = 2;
static const size_t num_inputs_per_nested_proof = 1;

using aggregator_circuit_wrapper =
libzecale::aggregator_circuit_wrapper<wpp, wsnark, nverifier, batch_size>;
using aggregator_circuit_wrapper = libzecale::
aggregator_circuit_wrapper<wpp, wsnark, nverifier, hash, batch_size>;

/// The aggregator_server class inherits from the Aggregator service defined in
/// the proto files, and provides an implementation of the service.
Expand Down Expand Up @@ -401,8 +402,9 @@ int main(int argc, char **argv)
npp::init_public_params();
wpp::init_public_params();

libzecale::aggregator_circuit_wrapper<wpp, wsnark, nverifier, batch_size>
aggregator(num_inputs_per_nested_proof);
libzecale::
aggregator_circuit_wrapper<wpp, wsnark, nverifier, hash, batch_size>
aggregator(num_inputs_per_nested_proof);
wsnark::keypair keypair = [&keypair_file, &aggregator]() {
if (!keypair_file.empty()) {
#ifdef ZKSNARK_GROTH16
Expand Down
32 changes: 31 additions & 1 deletion libzecale/circuits/aggregator_circuit_wrapper.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include "libzecale/circuits/aggregator_gadget.hpp"
#include "libzecale/circuits/pairing/pairing_params.hpp"
#include "libzecale/circuits/verification_key_hash_gadget.hpp"

#include <libzeth/core/extended_proof.hpp>

Expand All @@ -15,7 +16,26 @@ using namespace libzeth;
namespace libzecale
{

template<typename wppT, typename wsnarkT, typename nverifierT, size_t NumProofs>
/// Creates a circuit for creating a wrapping proof aggregating a batch of
/// nested proofs. Inputs are allocated as follows:
///
/// [hash of nested verfication key]
///
/// [proof 1, input 1] ... [proof 1, input M]
/// [proof 1 result (0 or 1)]
///
/// ...
///
/// [proof N, input 1] ... [proof N, input M]
/// [proof N result (0 or 1)]
///
/// (where N = NumProofs, M = num_inputs_per_nested_proof)
template<
typename wppT,
typename wsnarkT,
typename nverifierT,
typename hashT,
size_t NumProofs>
class aggregator_circuit_wrapper
{
private:
Expand All @@ -29,6 +49,11 @@ class aggregator_circuit_wrapper

libsnark::protoboard<libff::Fr<wppT>> _pb;

/// (Primary) Variable holding the hash of the verification key for nested
/// proofs. Verified against the actual verification key values, by the
/// _nested_vk_hash_gadget.
libsnark::pb_variable<libff::Fr<wppT>> _nested_vk_hash;

/// (Primary) The nested primary inputs lie in the scalar field
/// `libff::Fr<nppT>`, and must be represented as elements of
/// `libff::Fr<wppT>` for use in the wrapper proof.
Expand All @@ -54,6 +79,11 @@ class aggregator_circuit_wrapper
std::array<std::shared_ptr<proof_variable_gadget>, NumProofs>
_nested_proofs;

/// Gadget to check the hash of the nested verification key.
std::shared_ptr<verification_key_hash_gadget<wppT, nverifierT, hashT>>
_nested_vk_hash_gadget;

/// Gadget to aggregate proofs.
std::shared_ptr<aggregator_gadget<wppT, nverifierT, NumProofs>>
_aggregator_gadget;

Expand Down
52 changes: 45 additions & 7 deletions libzecale/circuits/aggregator_circuit_wrapper.tcc
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,22 @@ using namespace libzeth;
namespace libzecale
{

template<typename wppT, typename wsnarkT, typename nverifierT, size_t NumProofs>
aggregator_circuit_wrapper<wppT, wsnarkT, nverifierT, NumProofs>::
template<
typename wppT,
typename wsnarkT,
typename nverifierT,
typename hashT,
size_t NumProofs>
aggregator_circuit_wrapper<wppT, wsnarkT, nverifierT, hashT, NumProofs>::
aggregator_circuit_wrapper(const size_t inputs_per_nested_proof)
: _num_inputs_per_nested_proof(inputs_per_nested_proof), _pb()
{
// The order of allocation here is important as it determines which inputs
// are primary.

// Input for hash of nested verification key.
_nested_vk_hash.allocate(_pb, FMT("", "_nested_vk_hash"));

// For each proof in a batch, allocate primary inputs and results. These
// are the primary inputs. Note: both inputs and results will be
// populated by the aggregator gadget.
Expand All @@ -37,7 +45,7 @@ aggregator_circuit_wrapper<wppT, wsnarkT, nverifierT, NumProofs>::

// Set the number of primary inputs.
const size_t total_primary_inputs =
NumProofs * (inputs_per_nested_proof + 1);
1 + NumProofs * (inputs_per_nested_proof + 1);
_pb.set_input_sizes(total_primary_inputs);

// Allocate vk and the intermediate bit representation
Expand All @@ -55,6 +63,15 @@ aggregator_circuit_wrapper<wppT, wsnarkT, nverifierT, NumProofs>::
new proof_variable_gadget(_pb, FMT("", "_nested_proofs[%zu]", i)));
}

// Nested verification key hash gadget
_nested_vk_hash_gadget.reset(
new verification_key_hash_gadget<wppT, nverifierT, hashT>(
_pb,
*_nested_vk,
_nested_vk_hash,
FMT("", "_nested_vk_hash_gadget")));

// Aggregator gadget
_aggregator_gadget.reset(new aggregator_gadget<wppT, nverifierT, NumProofs>(
_pb,
*_nested_vk,
Expand All @@ -68,33 +85,51 @@ aggregator_circuit_wrapper<wppT, wsnarkT, nverifierT, NumProofs>::
for (size_t i = 0; i < NumProofs; ++i) {
_nested_proofs[i]->generate_r1cs_constraints();
}
_nested_vk_hash_gadget->generate_r1cs_constraints();
_aggregator_gadget->generate_r1cs_constraints();
}

template<typename wppT, typename wsnarkT, typename nverifierT, size_t NumProofs>
template<
typename wppT,
typename wsnarkT,
typename nverifierT,
typename hashT,
size_t NumProofs>
typename wsnarkT::keypair aggregator_circuit_wrapper<
wppT,
wsnarkT,
nverifierT,
hashT,
NumProofs>::generate_trusted_setup() const
{
// Generate a verification and proving key (trusted setup)
return wsnarkT::generate_setup(_pb);
}

template<typename wppT, typename wsnarkT, typename nverifierT, size_t NumProofs>
template<
typename wppT,
typename wsnarkT,
typename nverifierT,
typename hashT,
size_t NumProofs>
const libsnark::protoboard<libff::Fr<wppT>>
&aggregator_circuit_wrapper<wppT, wsnarkT, nverifierT, NumProofs>::
&aggregator_circuit_wrapper<wppT, wsnarkT, nverifierT, hashT, NumProofs>::
get_constraint_system() const
{
return _pb;
}

template<typename wppT, typename wsnarkT, typename nverifierT, size_t NumProofs>
template<
typename wppT,
typename wsnarkT,
typename nverifierT,
typename hashT,
size_t NumProofs>
libzeth::extended_proof<wppT, wsnarkT> aggregator_circuit_wrapper<
wppT,
wsnarkT,
nverifierT,
hashT,
NumProofs>::
prove(
const typename nsnark::verification_key &nested_vk,
Expand All @@ -121,6 +156,9 @@ libzeth::extended_proof<wppT, wsnarkT> aggregator_circuit_wrapper<
// Witness the verification key
_nested_vk->generate_r1cs_witness(nested_vk);

// Witness hash of verification keypair
_nested_vk_hash_gadget->generate_r1cs_witness();

// Pass the input values (in npp) to the aggregator gadget.
_aggregator_gadget->generate_r1cs_witness(nested_inputs);

Expand Down
34 changes: 30 additions & 4 deletions libzecale/tests/aggregator/aggregator_dummy_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,12 @@
#include "libzecale/tests/circuits/dummy_application.hpp"

#include <gtest/gtest.h>
#include <libzeth/circuits/blake2s/blake2s.hpp>

using namespace libzecale;

template<typename wppT> using hash = libzeth::BLAKE2s_256<libff::Fr<wppT>>;

namespace
{

Expand Down Expand Up @@ -45,14 +48,19 @@ template<
typename nverifierT,
size_t batch_size>
void test_aggregator_with_batch(
const size_t num_inputs_per_nested_proof,
const typename nverifierT::snark::keypair &nkp,
const proof_batch<
libzecale::other_curve<wppT>,
typename nverifierT::snark,
batch_size> &batch,
const typename wsnarkT::keypair &wkeypair,
aggregator_circuit_wrapper<wppT, wsnarkT, nverifierT, batch_size>
&aggregator,
aggregator_circuit_wrapper<
wppT,
wsnarkT,
nverifierT,
hash<wppT>,
batch_size> &aggregator,
const std::array<libff::Fr<wppT>, batch_size> &expected_results)
{
using npp = libzecale::other_curve<wppT>;
Expand All @@ -70,6 +78,12 @@ void test_aggregator_with_batch(
wpf.get_primary_inputs();
size_t winput_idx = 0;

// Check the nested vk hash
libff::Fr<wppT> expect_nested_vk_hash =
verification_key_hash_gadget<wppT, nverifierT, hash<wppT>>::
compute_hash(nkp.vk, num_inputs_per_nested_proof);
ASSERT_EQ(expect_nested_vk_hash, winputs[winput_idx++]);

for (size_t proof_idx = 0; proof_idx < batch_size; ++proof_idx) {
// Check that each input from the batch appears as expected in the
// nested primary input list.
Expand Down Expand Up @@ -111,13 +125,19 @@ void test_aggregate_dummy_application()
npf2.write_json(std::cout);

// Wrapper keypair
aggregator_circuit_wrapper<wppT, wsnarkT, nverifierT, batch_size>
aggregator_circuit_wrapper<
wppT,
wsnarkT,
nverifierT,
hash<wppT>,
batch_size>
aggregator(public_inputs_per_proof);
const typename wsnarkT::keypair wkeypair =
aggregator.generate_trusted_setup();

// Create and check a batched proof.
test_aggregator_with_batch(
public_inputs_per_proof,
nkp,
{{&npf1, &npf2}},
wkeypair,
Expand Down Expand Up @@ -159,13 +179,19 @@ void test_aggregate_dummy_application_with_invalid_proof()
npf2_invalid.write_json(std::cout);

// Wrapper keypair
aggregator_circuit_wrapper<wppT, wsnarkT, nverifierT, batch_size>
aggregator_circuit_wrapper<
wppT,
wsnarkT,
nverifierT,
hash<wppT>,
batch_size>
aggregator(public_inputs_per_proof);
const typename wsnarkT::keypair wkeypair =
aggregator.generate_trusted_setup();

// Create and check a batched proof
test_aggregator_with_batch(
public_inputs_per_proof,
nkp,
{{&npf1, &npf2_invalid}},
wkeypair,
Expand Down
18 changes: 12 additions & 6 deletions libzecale/tests/aggregator/aggregator_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -196,8 +196,12 @@ libzeth::extended_proof<nppT, snarkT> generate_valid_zeth_proof(
/// We use the same SNARK for simplicity.
template<typename wppT, typename wsnarkT, typename nverifierT>
bool test_valid_aggregation_batch_proofs(
aggregator_circuit_wrapper<wppT, wsnarkT, nverifierT, batch_size>
&aggregator_prover,
aggregator_circuit_wrapper<
wppT,
wsnarkT,
nverifierT,
hash<wppT>,
batch_size> &aggregator_prover,
typename wsnarkT::keypair &aggregator_keypair,
typename nverifierT::snark::keypair &zeth_keypair,
const std::array<
Expand All @@ -206,9 +210,6 @@ bool test_valid_aggregation_batch_proofs(
typename nverifierT::snark> *,
batch_size> &nested_proofs)
{
using npp = libzecale::other_curve<wppT>;
using nsnark = typename nverifierT::snark;

libff::enter_block("Generate Aggregate proof", true);
libzeth::extended_proof<wppT, wsnarkT> ext_proof = aggregator_prover.prove(
// This should cause a crash because the primary inputs are
Expand Down Expand Up @@ -277,7 +278,12 @@ void aggregator_test()

std::cout << "[DEBUG] Before creation of the Aggregator prover"
<< std::endl;
aggregator_circuit_wrapper<wppT, wsnarkT, nverifierT, batch_size>
aggregator_circuit_wrapper<
wppT,
wsnarkT,
nverifierT,
hash<wppT>,
batch_size>
aggregator_prover(num_zeth_inputs);
std::cout << "[DEBUG] Before gen Aggregator setup" << std::endl;
typename wsnarkT::keypair aggregator_keypair =
Expand Down

0 comments on commit 58525f1

Please sign in to comment.