Skip to content

Commit

Permalink
Foundations of circuit
Browse files Browse the repository at this point in the history
  • Loading branch information
ebfull committed Nov 27, 2015
0 parents commit 4b48e3f
Show file tree
Hide file tree
Showing 8 changed files with 239 additions and 0 deletions.
6 changes: 6 additions & 0 deletions .gitignore
@@ -0,0 +1,6 @@
test
*.o
*.d
depinst
depsrc

16 changes: 16 additions & 0 deletions Makefile
@@ -0,0 +1,16 @@
OPTFLAGS = -march=native -mtune=native -O2
CXXFLAGS += -g -Wall -Wextra -Wno-unused-parameter -std=c++11 -fPIC -Wno-unused-variable
CXXFLAGS += -I $(DEPINST)/include -I $(DEPINST)/include/libsnark -DUSE_ASM -DCURVE_ALT_BN128
LDFLAGS += -flto

DEPSRC=depsrc
DEPINST=depinst

LDLIBS += -L $(DEPINST)/lib -Wl,-rpath $(DEPINST)/lib -L . -lsnark -lgmpxx -lgmp

all:
$(CXX) -o test.o test.cpp -c -MMD $(CXXFLAGS)
$(CXX) -o test test.o $(CXXFLAGS) $(LDFLAGS) $(LDLIBS)

clean:
$(RM) test.o test
34 changes: 34 additions & 0 deletions gadget.hpp
@@ -0,0 +1,34 @@
#include "libsnark/gadgetlib1/gadgets/hashes/sha256/sha256_gadget.hpp"
#include "algebra/fields/field_utils.hpp"

const size_t sha256_digest_len = 256;

using namespace libsnark;

template<typename FieldT>
class example_gadget : public gadget<FieldT> {
public:
pb_variable_array<FieldT> input_as_field_elements; /* R1CS input */
pb_variable_array<FieldT> input_as_bits; /* unpacked R1CS input */
std::shared_ptr<multipacking_gadget<FieldT> > unpack_inputs; /* multipacking gadget */

std::shared_ptr<digest_variable<FieldT>> h1_var; /* H(R1) */

/*
std::shared_ptr<digest_variable<FieldT>> r1_var;
std::shared_ptr<digest_variable<FieldT>> h1_var;
std::shared_ptr<block_variable<FieldT>> h_r1_block;
std::shared_ptr<sha256_compression_function_gadget<FieldT>> h_r1;
*/


example_gadget(protoboard<FieldT> &pb);
void generate_r1cs_constraints();
void generate_r1cs_witness(const bit_vector &h1);
};

template<typename FieldT>
r1cs_primary_input<FieldT> example_input_map(const bit_vector &h1);

#include "gadget.tcc"
58 changes: 58 additions & 0 deletions gadget.tcc
@@ -0,0 +1,58 @@
template<typename FieldT>
example_gadget<FieldT>::example_gadget(protoboard<FieldT> &pb) :
gadget<FieldT>(pb, FMT(annotation_prefix, " example_gadget"))
{
// Allocate space for the verifier input.
const size_t input_size_in_bits = sha256_digest_len;
{
const size_t input_size_in_field_elements = div_ceil(input_size_in_bits, FieldT::capacity());
input_as_field_elements.allocate(pb, input_size_in_field_elements, "input_as_field_elements");
this->pb.set_input_sizes(input_size_in_field_elements);
}

h1_var.reset(new digest_variable<FieldT>(pb, sha256_digest_len, "h1"));
input_as_bits.insert(input_as_bits.end(), h1_var->bits.begin(), h1_var->bits.end());

// Multipacking
assert(input_as_bits.size() == input_size_in_bits);
unpack_inputs.reset(new multipacking_gadget<FieldT>(this->pb, input_as_bits, input_as_field_elements, FieldT::capacity(), FMT(this->annotation_prefix, " unpack_inputs")));


/*
pb_linear_combination_array<FieldT> IV = SHA256_default_IV(pb);
r1_var.reset(new digest_variable<FieldT>(pb, sha256_digest_len, "r1"));
h1_var.reset(new digest_variable<FieldT>(pb, sha256_digest_len, "h1"));
h_r1_block.reset(new block_variable<FieldT>(pb, {r1_var->bits}, "h_r1_block"));
h_r1.reset(new sha256_compression_function_gadget<FieldT>(pb,
IV,
h_r1_block->bits,
*h1_var, "h_r1"));
*/
}

template<typename FieldT>
void example_gadget<FieldT>::generate_r1cs_constraints()
{
unpack_inputs->generate_r1cs_constraints(true);
h1_var->generate_r1cs_constraints();
}

template<typename FieldT>
void example_gadget<FieldT>::generate_r1cs_witness(const bit_vector &h1
)
{
h1_var->bits.fill_with_bits(this->pb, h1);

unpack_inputs->generate_r1cs_witness_from_bits();
}

template<typename FieldT>
r1cs_primary_input<FieldT> example_input_map(const bit_vector &h1)
{
assert(h1.size() == sha256_digest_len);
bit_vector input_as_bits;
input_as_bits.insert(input_as_bits.end(), h1.begin(), h1.end());
std::vector<FieldT> input_as_field_elements = pack_bit_vector_into_field_element_vector<FieldT>(input_as_bits);
return input_as_field_elements;
}
39 changes: 39 additions & 0 deletions get-libsnark
@@ -0,0 +1,39 @@
#!/bin/bash
# To pass options options to libsnark Makefile, put them in env var LIBSNARK_FLAGS.
# To clone libsnark from an alternate location, set env var LIBSNARK_SRC. For example:
# LIBSNARK_SRC="$HOME/libsnark.git --branch master" ./get-libsnark
# To use curve ALT_BN128 instead of BN128 (which is x64-only), use:
# CURVE=ALT_BN128 ./get-libsnark

set -e

LIBSNARK_SRC=${LIBSNARK_SRC:-https://github.com/scipr-lab/libsnark}

CURVE=${CURVE:-BN128}

LIBSNARK_FLAGS="$LIBSNARK_FLAGS NO_SUPERCOP=1 NO_GTEST=1 NO_DOCS=1 CURVE=$CURVE"
if [[ `uname -s` == "Darwin" ]]; then
LIBSNARK_FLAGS="$LIBSNARK_FLAGS NO_PROCPS=1"
fi

set -x

DEPSRC=./depsrc
DEPINST=./depinst

mkdir -p $DEPINST
DEPINST=`pwd -P`/$DEPINST # remember absolute path

mkdir -p $DEPSRC
cd $DEPSRC

[ ! -d libsnark ] && git clone $LIBSNARK_SRC libsnark
cd libsnark
git pull
if [ "$CURVE" == "BN128" ]; then
# TODO: submit -fPIC patch to ate-pairing
INC_DIR=-fPIC ./prepare-depends.sh
fi
make clean
make lib $LIBSNARK_FLAGS
make install PREFIX=$DEPINST $LIBSNARK_FLAGS
22 changes: 22 additions & 0 deletions snark.hpp
@@ -0,0 +1,22 @@
#include "libsnark/gadgetlib1/gadgets/basic_gadgets.hpp"
#include "libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/r1cs_ppzksnark.hpp"
#include "libsnark/common/default_types/r1cs_ppzksnark_pp.hpp"
#include "libsnark/common/utils.hpp"

using namespace libsnark;

template<typename ppzksnark_ppT>
r1cs_ppzksnark_keypair<ppzksnark_ppT> generate_keypair();

template<typename ppzksnark_ppT>
r1cs_ppzksnark_proof<ppzksnark_ppT> generate_proof(r1cs_ppzksnark_proving_key<ppzksnark_ppT> proving_key,
const bit_vector &h1);

template<typename ppzksnark_ppT>
bool verify_proof(r1cs_ppzksnark_verification_key<ppzksnark_ppT> verification_key,
r1cs_ppzksnark_proof<ppzksnark_ppT> proof,
const bit_vector &h1
// ...
);

#include "snark.tcc"
45 changes: 45 additions & 0 deletions snark.tcc
@@ -0,0 +1,45 @@
#include "gadget.hpp"

template<typename ppzksnark_ppT>
r1cs_ppzksnark_keypair<ppzksnark_ppT> generate_keypair()
{
typedef Fr<ppzksnark_ppT> FieldT;

protoboard<FieldT> pb;
example_gadget<FieldT> g(pb);
g.generate_r1cs_constraints();
const r1cs_constraint_system<FieldT> constraint_system = pb.get_constraint_system();

return r1cs_ppzksnark_generator<ppzksnark_ppT>(constraint_system);
}

template<typename ppzksnark_ppT>
r1cs_ppzksnark_proof<ppzksnark_ppT> generate_proof(r1cs_ppzksnark_proving_key<ppzksnark_ppT> proving_key,
const bit_vector &h1
)
{
typedef Fr<ppzksnark_ppT> FieldT;

protoboard<FieldT> pb;
example_gadget<FieldT> g(pb);
g.generate_r1cs_constraints();
g.generate_r1cs_witness(h1);

assert(pb.is_satisfied());

return r1cs_ppzksnark_prover<ppzksnark_ppT>(proving_key, pb.primary_input(), pb.auxiliary_input());
}

template<typename ppzksnark_ppT>
bool verify_proof(r1cs_ppzksnark_verification_key<ppzksnark_ppT> verification_key,
r1cs_ppzksnark_proof<ppzksnark_ppT> proof,
const bit_vector &h1
// ...
)
{
typedef Fr<ppzksnark_ppT> FieldT;

const r1cs_primary_input<FieldT> input = example_input_map<FieldT>(h1);

return r1cs_ppzksnark_verifier_strong_IC<ppzksnark_ppT>(verification_key, input, proof);
}
19 changes: 19 additions & 0 deletions test.cpp
@@ -0,0 +1,19 @@
#include <stdlib.h>
#include <iostream>

#include "snark.hpp"

using namespace libsnark;
using namespace std;

int main()
{
default_r1cs_ppzksnark_pp::init_public_params();
auto keypair = generate_keypair<default_r1cs_ppzksnark_pp>();

std::vector<bool> h1(256, false);

auto proof = generate_proof<default_r1cs_ppzksnark_pp>(keypair.pk, h1);

assert(verify_proof(keypair.vk, proof, h1));
}

0 comments on commit 4b48e3f

Please sign in to comment.