Skip to content
This repository has been archived by the owner on Oct 28, 2021. It is now read-only.

Commit

Permalink
ProjectSnark: switch to libff
Browse files Browse the repository at this point in the history
  • Loading branch information
chfast committed Mar 14, 2017
1 parent 4407831 commit e70dec2
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 64 deletions.
29 changes: 13 additions & 16 deletions cmake/ProjectSnark.cmake
Original file line number Diff line number Diff line change
@@ -1,28 +1,25 @@
include(ExternalProject)

ExternalProject_Add(snark
PREFIX deps
# This points to a February 2017 version.
DOWNLOAD_NAME snark-6b7e494c.tar.gz
URL https://github.com/scipr-lab/libsnark/archive/6b7e494c2407eb8e91ad78635788decb2d736596.tar.gz
URL_HASH SHA256=c40ee69a15c8a5baf3980d3686112ccbe8511071faa1cda3875d43e693fc90e4
PREFIX ${CMAKE_SOURCE_DIR}/deps
DOWNLOAD_NAME libff-2fa434b3.tar.gz
DOWNLOAD_NO_PROGRESS TRUE
BUILD_IN_SOURCE 1
CONFIGURE_COMMAND ""
BUILD_COMMAND CXX=${CMAKE_CXX_COMPILER} CC=${CMAKE_C_COMPILER} make
NO_PROCPS=1 STATIC=1 NO_SUPERCOP=1 NO_GTEST=1 NO_DOCS=1 CURVE=ALT_BN128
FEATUREFLAGS="-DBINARY_OUTPUT=1 -DMONTGOMERY_OUTPUT=1 -DNO_PT_COMPRESSION=1"
lib PREFIX=<INSTALL_DIR> install
INSTALL_COMMAND ""
URL https://github.com/scipr-lab/libff/archive/2fa434b3d6e9163beedaefffa85043a1180a05e6.tar.gz
URL_HASH SHA256=d3266f95a86bbfc908a7a9531df08a47cdd026e76b6290465fb8dfa203606a21

PATCH_COMMAND ${CMAKE_COMMAND} -E touch <SOURCE_DIR>/third_party/gtest/CMakeLists.txt
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=<INSTALL_DIR>
-DCURVE=ALT_BN128 -DPERFORMANCE=Off -DWITH_PROCPS=Off
-DUSE_PT_COMPRESSION=Off
)

# Create snark imported library
ExternalProject_Get_Property(snark INSTALL_DIR)
add_library(Snark STATIC IMPORTED)
set(SNARK_LIBRARY ${INSTALL_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}snark${CMAKE_STATIC_LIBRARY_SUFFIX})
file(MAKE_DIRECTORY ${INSTALL_DIR}/include/libsnark) # Must exist.
set(SNARK_INCLUDE_DIRS ${INSTALL_DIR}/include ${INSTALL_DIR}/include/libsnark)
set(SNARK_LIBRARY ${INSTALL_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}ff${CMAKE_STATIC_LIBRARY_SUFFIX})
set(SNARK_INCLUDE_DIR ${INSTALL_DIR}/include/libff)
set_property(TARGET Snark PROPERTY IMPORTED_LOCATION ${SNARK_LIBRARY})
set_property(TARGET Snark PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${SNARK_INCLUDE_DIRS})
set_property(TARGET Snark PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${SNARK_INCLUDE_DIR})
set_property(TARGET Snark PROPERTY INTERFACE_LINK_LIBRARIES gmp)
add_dependencies(Snark snark)
unset(INSTALL_DIR)
86 changes: 38 additions & 48 deletions libdevcrypto/LibSnark.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,25 +19,16 @@
*/

#include <libdevcrypto/LibSnark.h>
// libsnark has to be compiled with exactly the same switches:
// sudo PREFIX=/usr/local make NO_PROCPS=1 NO_GTEST=1 NO_DOCS=1 CURVE=ALT_BN128 FEATUREFLAGS="-DBINARY_OUTPUT=1 -DMONTGOMERY_OUTPUT=1 -DNO_PT_COMPRESSION=1" lib install
#define BINARY_OUTPUT 1
#define MONTGOMERY_OUTPUT 1
#define NO_PT_COMPRESSION 1

#include <libsnark/algebra/curves/alt_bn128/alt_bn128_g1.hpp>
#include <libsnark/algebra/curves/alt_bn128/alt_bn128_g2.hpp>
#include <libsnark/algebra/curves/alt_bn128/alt_bn128_pairing.hpp>
#include <libsnark/algebra/curves/alt_bn128/alt_bn128_pp.hpp>
#include <libsnark/zk_proof_systems/ppzksnark/r1cs_ppzksnark/r1cs_ppzksnark.hpp>

#include <algebra/curves/alt_bn128/alt_bn128_g1.hpp>
#include <algebra/curves/alt_bn128/alt_bn128_g2.hpp>
#include <algebra/curves/alt_bn128/alt_bn128_pairing.hpp>
#include <algebra/curves/alt_bn128/alt_bn128_pp.hpp>

#include <libdevcrypto/Exceptions.h>

#include <libdevcore/CommonIO.h>
#include <libdevcore/Log.h>
#include <libdevcore/FixedHash.h>

#include <fstream>

using namespace std;
using namespace dev;
Expand All @@ -51,24 +42,23 @@ void initLibSnark()
static bool initialized = 0;
if (!initialized)
{
libsnark::alt_bn128_pp::init_public_params();
// FIXME: This is race condition!!!
libff::alt_bn128_pp::init_public_params();
// Otherwise the library would output profiling info for each run.
libsnark::inhibit_profiling_counters = true;
libsnark::inhibit_profiling_info = true;
initialized = true;
}
}

libsnark::bigint<libsnark::alt_bn128_q_limbs> toLibsnarkBigint(h256 const& _x)
libff::bigint<libff::alt_bn128_q_limbs> toLibsnarkBigint(h256 const& _x)
{
libsnark::bigint<libsnark::alt_bn128_q_limbs> x;
libff::bigint<libff::alt_bn128_q_limbs> x;
for (unsigned i = 0; i < 4; i++)
for (unsigned j = 0; j < 8; j++)
x.data[3 - i] |= uint64_t(_x[i * 8 + j]) << (8 * (7 - j));
return x;
}

h256 fromLibsnarkBigint(libsnark::bigint<libsnark::alt_bn128_q_limbs> _x)
h256 fromLibsnarkBigint(libff::bigint<libff::alt_bn128_q_limbs> _x)
{
h256 x;
for (unsigned i = 0; i < 4; i++)
Expand All @@ -77,29 +67,29 @@ h256 fromLibsnarkBigint(libsnark::bigint<libsnark::alt_bn128_q_limbs> _x)
return x;
}

libsnark::alt_bn128_Fq decodeFqElement(dev::bytesConstRef _data)
libff::alt_bn128_Fq decodeFqElement(dev::bytesConstRef _data)
{
// h256::AlignLeft ensures that the h256 is zero-filled on the right if _data
// is too short.
h256 xbin(_data, h256::AlignLeft);
if (u256(xbin) >= u256(fromLibsnarkBigint(libsnark::alt_bn128_Fq::mod)))
if (u256(xbin) >= u256(fromLibsnarkBigint(libff::alt_bn128_Fq::mod)))
BOOST_THROW_EXCEPTION(InvalidEncoding());
return toLibsnarkBigint(xbin);
}

libsnark::alt_bn128_G1 decodePointG1(dev::bytesConstRef _data)
libff::alt_bn128_G1 decodePointG1(dev::bytesConstRef _data)
{
libsnark::alt_bn128_Fq X = decodeFqElement(_data.cropped(0));
libsnark::alt_bn128_Fq Y = decodeFqElement(_data.cropped(32));
if (X == libsnark::alt_bn128_Fq::zero() && Y == libsnark::alt_bn128_Fq::zero())
return libsnark::alt_bn128_G1::zero();
libsnark::alt_bn128_G1 p(X, Y, libsnark::alt_bn128_Fq::one());
libff::alt_bn128_Fq X = decodeFqElement(_data.cropped(0));
libff::alt_bn128_Fq Y = decodeFqElement(_data.cropped(32));
if (X == libff::alt_bn128_Fq::zero() && Y == libff::alt_bn128_Fq::zero())
return libff::alt_bn128_G1::zero();
libff::alt_bn128_G1 p(X, Y, libff::alt_bn128_Fq::one());
if (!p.is_well_formed())
BOOST_THROW_EXCEPTION(InvalidEncoding());
return p;
}

bytes encodePointG1(libsnark::alt_bn128_G1 _p)
bytes encodePointG1(libff::alt_bn128_G1 _p)
{
if (_p.is_zero())
return h256().asBytes() + h256().asBytes();
Expand All @@ -109,24 +99,24 @@ bytes encodePointG1(libsnark::alt_bn128_G1 _p)
fromLibsnarkBigint(_p.Y.as_bigint()).asBytes();
}

libsnark::alt_bn128_Fq2 decodeFq2Element(dev::bytesConstRef _data)
libff::alt_bn128_Fq2 decodeFq2Element(dev::bytesConstRef _data)
{
// Encoding: c1 (256 bits) c0 (256 bits)
// "Big endian", just like the numbers
return libsnark::alt_bn128_Fq2(
return libff::alt_bn128_Fq2(
decodeFqElement(_data.cropped(32)),
decodeFqElement(_data.cropped(0))
);
}


libsnark::alt_bn128_G2 decodePointG2(dev::bytesConstRef _data)
libff::alt_bn128_G2 decodePointG2(dev::bytesConstRef _data)
{
libsnark::alt_bn128_Fq2 X = decodeFq2Element(_data);
libsnark::alt_bn128_Fq2 Y = decodeFq2Element(_data.cropped(64));
if (X == libsnark::alt_bn128_Fq2::zero() && Y == libsnark::alt_bn128_Fq2::zero())
return libsnark::alt_bn128_G2::zero();
libsnark::alt_bn128_G2 p(X, Y, libsnark::alt_bn128_Fq2::one());
libff::alt_bn128_Fq2 X = decodeFq2Element(_data);
libff::alt_bn128_Fq2 Y = decodeFq2Element(_data.cropped(64));
if (X == libff::alt_bn128_Fq2::zero() && Y == libff::alt_bn128_Fq2::zero())
return libff::alt_bn128_G2::zero();
libff::alt_bn128_G2 p(X, Y, libff::alt_bn128_Fq2::one());
if (!p.is_well_formed())
BOOST_THROW_EXCEPTION(InvalidEncoding());
return p;
Expand All @@ -150,20 +140,20 @@ pair<bool, bytes> dev::crypto::alt_bn128_pairing_product(dev::bytesConstRef _in)
try
{
initLibSnark();
libsnark::alt_bn128_Fq12 x = libsnark::alt_bn128_Fq12::one();
libff::alt_bn128_Fq12 x = libff::alt_bn128_Fq12::one();
for (size_t i = 0; i < pairs; ++i)
{
dev::bytesConstRef pair = _in.cropped(i * pairSize, pairSize);
libsnark::alt_bn128_G2 p = decodePointG2(pair.cropped(2 * 32));
if (-libsnark::alt_bn128_G2::scalar_field::one() * p + p != libsnark::alt_bn128_G2::zero())
libff::alt_bn128_G2 p = decodePointG2(pair.cropped(2 * 32));
if (-libff::alt_bn128_G2::scalar_field::one() * p + p != libff::alt_bn128_G2::zero())
// p is not an element of the group (has wrong order)
return {false, bytes()};
x = x * libsnark::alt_bn128_miller_loop(
libsnark::alt_bn128_precompute_G1(decodePointG1(pair)),
libsnark::alt_bn128_precompute_G2(p)
x = x * libff::alt_bn128_miller_loop(
libff::alt_bn128_precompute_G1(decodePointG1(pair)),
libff::alt_bn128_precompute_G2(p)
);
}
result = libsnark::alt_bn128_final_exponentiation(x) == libsnark::alt_bn128_GT::one();
result = libff::alt_bn128_final_exponentiation(x) == libff::alt_bn128_GT::one();
}
catch (InvalidEncoding const&)
{
Expand All @@ -185,8 +175,8 @@ pair<bool, bytes> dev::crypto::alt_bn128_G1_add(dev::bytesConstRef _in)
try
{
initLibSnark();
libsnark::alt_bn128_G1 p1 = decodePointG1(_in);
libsnark::alt_bn128_G1 p2 = decodePointG1(_in.cropped(32 * 2));
libff::alt_bn128_G1 p1 = decodePointG1(_in);
libff::alt_bn128_G1 p2 = decodePointG1(_in.cropped(32 * 2));

return {true, encodePointG1(p1 + p2)};
}
Expand All @@ -205,9 +195,9 @@ pair<bool, bytes> dev::crypto::alt_bn128_G1_mul(dev::bytesConstRef _in)
try
{
initLibSnark();
libsnark::alt_bn128_G1 p = decodePointG1(_in.cropped(0));
libff::alt_bn128_G1 p = decodePointG1(_in.cropped(0));

libsnark::alt_bn128_G1 result = toLibsnarkBigint(h256(_in.cropped(64), h256::AlignLeft)) * p;
libff::alt_bn128_G1 result = toLibsnarkBigint(h256(_in.cropped(64), h256::AlignLeft)) * p;

return {true, encodePointG1(result)};
}
Expand Down

0 comments on commit e70dec2

Please sign in to comment.