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

Commit

Permalink
Merge pull request #3587 from ethereum/snark
Browse files Browse the repository at this point in the history
Integrate libsnark
  • Loading branch information
pirapira authored Jun 13, 2017
2 parents 74e3a61 + 8eee78c commit 8f8edab
Show file tree
Hide file tree
Showing 18 changed files with 683 additions and 21 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ cache:
# build external dependencies next build.
- $TRAVIS_BUILD_DIR/deps
install:
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then clang --version; brew install llvm; $(brew --prefix llvm)/bin/clang --version; export PATH=$(brew --prefix llvm)/bin:$PATH; export CC=$(brew --prefix llvm)/bin/clang; export CXX=$(brew --prefix llvm)/bin/clang++; fi
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then ./scripts/install_cmake.sh; fi
- ./scripts/install_deps.sh
before_script:
Expand Down
3 changes: 1 addition & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,7 @@ include(ProjectCryptopp)
include(ProjectJsonCpp)
include(ProjectJsonRpcCpp)
include(ProjectSecp256k1)


include(ProjectSnark)

configure_project()

Expand Down
19 changes: 10 additions & 9 deletions cmake/ProjectBoost.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -36,45 +36,46 @@ ExternalProject_Add(boost
--with-regex
--with-test
--with-thread
--with-program_options # libff wants it, we may need it in future.
LOG_BUILD 1
INSTALL_COMMAND ""
)

ExternalProject_Get_Property(boost SOURCE_DIR)
set(BOOST_INCLUDE_DIR ${SOURCE_DIR})
set(BOOST_LIB_DIR ${SOURCE_DIR}/stage/lib)
set(BOOST_LIBRARY_DIR ${SOURCE_DIR}/stage/lib)
unset(BUILD_DIR)

add_library(Boost::Chrono STATIC IMPORTED)
set_property(TARGET Boost::Chrono PROPERTY IMPORTED_LOCATION ${BOOST_LIB_DIR}/libboost_chrono${BOOST_LIBRARY_SUFFIX})
set_property(TARGET Boost::Chrono PROPERTY IMPORTED_LOCATION ${BOOST_LIBRARY_DIR}/libboost_chrono${BOOST_LIBRARY_SUFFIX})
add_dependencies(Boost::Chrono boost)

add_library(Boost::DataTime STATIC IMPORTED)
set_property(TARGET Boost::DataTime PROPERTY IMPORTED_LOCATION ${BOOST_LIB_DIR}/libboost_date_time${BOOST_LIBRARY_SUFFIX})
set_property(TARGET Boost::DataTime PROPERTY IMPORTED_LOCATION ${BOOST_LIBRARY_DIR}/libboost_date_time${BOOST_LIBRARY_SUFFIX})
add_dependencies(Boost::DataTime boost)

add_library(Boost::Regex STATIC IMPORTED)
set_property(TARGET Boost::Regex PROPERTY IMPORTED_LOCATION ${BOOST_LIB_DIR}/libboost_regex${BOOST_LIBRARY_SUFFIX})
set_property(TARGET Boost::Regex PROPERTY IMPORTED_LOCATION ${BOOST_LIBRARY_DIR}/libboost_regex${BOOST_LIBRARY_SUFFIX})
add_dependencies(Boost::Regex boost)

add_library(Boost::System STATIC IMPORTED)
set_property(TARGET Boost::System PROPERTY IMPORTED_LOCATION ${BOOST_LIB_DIR}/libboost_system${BOOST_LIBRARY_SUFFIX})
set_property(TARGET Boost::System PROPERTY IMPORTED_LOCATION ${BOOST_LIBRARY_DIR}/libboost_system${BOOST_LIBRARY_SUFFIX})
add_dependencies(Boost::System boost)

add_library(Boost::Filesystem STATIC IMPORTED)
set_property(TARGET Boost::Filesystem PROPERTY IMPORTED_LOCATION ${BOOST_LIB_DIR}/libboost_filesystem${BOOST_LIBRARY_SUFFIX})
set_property(TARGET Boost::Filesystem PROPERTY IMPORTED_LOCATION ${BOOST_LIBRARY_DIR}/libboost_filesystem${BOOST_LIBRARY_SUFFIX})
set_property(TARGET Boost::Filesystem PROPERTY INTERFACE_LINK_LIBRARIES Boost::System)
add_dependencies(Boost::Filesystem boost)

add_library(Boost::Random STATIC IMPORTED)
set_property(TARGET Boost::Random PROPERTY IMPORTED_LOCATION ${BOOST_LIB_DIR}/libboost_random${BOOST_LIBRARY_SUFFIX})
set_property(TARGET Boost::Random PROPERTY IMPORTED_LOCATION ${BOOST_LIBRARY_DIR}/libboost_random${BOOST_LIBRARY_SUFFIX})
add_dependencies(Boost::Random boost)

add_library(Boost::UnitTestFramework STATIC IMPORTED)
set_property(TARGET Boost::UnitTestFramework PROPERTY IMPORTED_LOCATION ${BOOST_LIB_DIR}/libboost_unit_test_framework${BOOST_LIBRARY_SUFFIX})
set_property(TARGET Boost::UnitTestFramework PROPERTY IMPORTED_LOCATION ${BOOST_LIBRARY_DIR}/libboost_unit_test_framework${BOOST_LIBRARY_SUFFIX})
add_dependencies(Boost::UnitTestFramework boost)

add_library(Boost::Thread STATIC IMPORTED)
set_property(TARGET Boost::Thread PROPERTY IMPORTED_LOCATION ${BOOST_LIB_DIR}/libboost_thread${BOOST_LIBRARY_SUFFIX})
set_property(TARGET Boost::Thread PROPERTY IMPORTED_LOCATION ${BOOST_LIBRARY_DIR}/libboost_thread${BOOST_LIBRARY_SUFFIX})
set_property(TARGET Boost::Thread PROPERTY INTERFACE_LINK_LIBRARIES Boost::Chrono Boost::DataTime Boost::Regex)
add_dependencies(Boost::Thread boost)
19 changes: 19 additions & 0 deletions cmake/ProjectMPIR.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
ExternalProject_Add(mpir
PREFIX ${CMAKE_SOURCE_DIR}/deps
DOWNLOAD_NAME mpir-cmake.tar.gz
DOWNLOAD_NO_PROGRESS TRUE
URL https://github.com/chfast/mpir/archive/cmake.tar.gz
URL_HASH SHA256=2bf35ad7aa2b61bf4c2dcdab9aab48b2b4f9d6db8b937be4b0b5fe3b5efbdfa6
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=<INSTALL_DIR>
-DCMAKE_BUILD_TYPE=Debug
-DMPIR_GMP=On
)

ExternalProject_Get_Property(mpir INSTALL_DIR)
add_library(MPIR::mpir STATIC IMPORTED)
set(MPIR_LIBRARY ${INSTALL_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}mpir${CMAKE_STATIC_LIBRARY_SUFFIX})
set(MPIR_INCLUDE_DIR ${INSTALL_DIR}/include)
set_property(TARGET MPIR::mpir PROPERTY IMPORTED_LOCATION ${MPIR_LIBRARY})
set_property(TARGET MPIR::mpir PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${MPIR_INCLUDE_DIR})
add_dependencies(MPIR::mpir mpir)
unset(INSTALL_DIR)
33 changes: 33 additions & 0 deletions cmake/ProjectSnark.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
include(ProjectMPIR)

# FIXME: Rename to LibFF as that's the name of the library.

ExternalProject_Add(snark
PREFIX ${CMAKE_SOURCE_DIR}/deps
DOWNLOAD_NAME libff-97d3fa6c.tar.gz
DOWNLOAD_NO_PROGRESS TRUE
URL https://github.com/chfast/libff/archive/97d3fa6cdbd4b7549c7a8a179dc97308dbfd044d.tar.gz
URL_HASH SHA256=f102f3ee43c96c9a81c20d8c0446c805c6b8c0e3121518b3625f08e2c230096e
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=<INSTALL_DIR>
-DGMP_INCLUDE_DIR=${MPIR_INCLUDE_DIR}
-DGMP_LIBRARIES=${MPIR_LIBRARY}
-DGMPXX_LIBRARIES=${MPIR_LIBRARY}
-DCURVE=ALT_BN128 -DPERFORMANCE=Off -DWITH_PROCPS=Off
-DUSE_PT_COMPRESSION=Off
BUILD_COMMAND ${CMAKE_COMMAND} --build <BINARY_DIR> --config Release
INSTALL_COMMAND ${CMAKE_COMMAND} --build <BINARY_DIR> --config Release --target install
)
add_dependencies(snark boost)
add_dependencies(snark mpir)

# 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}ff${CMAKE_STATIC_LIBRARY_SUFFIX})
set(SNARK_INCLUDE_DIR ${INSTALL_DIR}/include/libff)
file(MAKE_DIRECTORY ${SNARK_INCLUDE_DIR})
set_property(TARGET Snark PROPERTY IMPORTED_LOCATION ${SNARK_LIBRARY})
set_property(TARGET Snark PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${SNARK_INCLUDE_DIR})
set_property(TARGET Snark PROPERTY INTERFACE_LINK_LIBRARIES MPIR::mpir)
add_dependencies(Snark snark)
unset(INSTALL_DIR)
2 changes: 2 additions & 0 deletions eth/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@
#include <libethashseal/GenesisInfo.h>
#include <libwebthree/WebThree.h>

#include <libdevcrypto/LibSnark.h>

#include <libweb3jsonrpc/AccountHolder.h>
#include <libweb3jsonrpc/Eth.h>
#include <libweb3jsonrpc/SafeHttpServer.h>
Expand Down
2 changes: 1 addition & 1 deletion libdevcrypto/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ add_library(devcrypto ${SOURCES} ${HEADERS})
find_package(Utils)
target_include_directories(devcrypto PRIVATE ..)
target_include_directories(devcrypto PRIVATE ../utils)
target_link_libraries(devcrypto Secp256k1 Cryptopp ${Utils_SCRYPT_LIBRARIES} devcore)
target_link_libraries(devcrypto Secp256k1 Snark Cryptopp ${Utils_SCRYPT_LIBRARIES} devcore)
202 changes: 202 additions & 0 deletions libdevcrypto/LibSnark.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/

#include <libdevcrypto/LibSnark.h>

#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 <common/profiling.hpp>

#include <libdevcore/Exceptions.h>
#include <libdevcore/Log.h>

using namespace std;
using namespace dev;
using namespace dev::crypto;

namespace
{

DEV_SIMPLE_EXCEPTION(InvalidEncoding);

void initLibSnark() noexcept
{
static bool s_initialized = []() noexcept
{
libff::inhibit_profiling_info = true;
libff::inhibit_profiling_counters = true;
libff::alt_bn128_pp::init_public_params();
return true;
}();
(void)s_initialized;
}

libff::bigint<libff::alt_bn128_q_limbs> toLibsnarkBigint(h256 const& _x)
{
libff::bigint<libff::alt_bn128_q_limbs> b;
auto const N = b.N;
constexpr size_t L = sizeof(b.data[0]);
static_assert(sizeof(mp_limb_t) == L, "Unexpected limb size in libff::bigint.");
for (size_t i = 0; i < N; i++)
for (size_t j = 0; j < L; j++)
b.data[N - 1 - i] |= mp_limb_t(_x[i * L + j]) << (8 * (L - 1 - j));
return b;
}

h256 fromLibsnarkBigint(libff::bigint<libff::alt_bn128_q_limbs> const& _b)
{
static size_t const N = static_cast<size_t>(_b.N);
static size_t const L = sizeof(_b.data[0]);
static_assert(sizeof(mp_limb_t) == L, "Unexpected limb size in libff::bigint.");
h256 x;
for (size_t i = 0; i < N; i++)
for (size_t j = 0; j < L; j++)
x[i * L + j] = uint8_t(_b.data[N - 1 - i] >> (8 * (L - 1 - j)));
return x;
}

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);
// TODO: Consider using a compiler time constant for comparison.
if (u256(xbin) >= u256(fromLibsnarkBigint(libff::alt_bn128_Fq::mod)))
BOOST_THROW_EXCEPTION(InvalidEncoding());
return toLibsnarkBigint(xbin);
}

libff::alt_bn128_G1 decodePointG1(dev::bytesConstRef _data)
{
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(libff::alt_bn128_G1 _p)
{
if (_p.is_zero())
return bytes(64, 0);
_p.to_affine_coordinates();
return
fromLibsnarkBigint(_p.X.as_bigint()).asBytes() +
fromLibsnarkBigint(_p.Y.as_bigint()).asBytes();
}

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

libff::alt_bn128_G2 decodePointG2(dev::bytesConstRef _data)
{
libff::alt_bn128_Fq2 const x = decodeFq2Element(_data);
libff::alt_bn128_Fq2 const 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;
}

}

pair<bool, bytes> dev::crypto::alt_bn128_pairing_product(dev::bytesConstRef _in)
{
// Input: list of pairs of G1 and G2 points
// Output: 1 if pairing evaluates to 1, 0 otherwise (left-padded to 32 bytes)

size_t constexpr pairSize = 2 * 32 + 2 * 64;
size_t const pairs = _in.size() / pairSize;
if (pairs * pairSize != _in.size())
// Invalid length.
return {false, bytes{}};

try
{
initLibSnark();
libff::alt_bn128_Fq12 x = libff::alt_bn128_Fq12::one();
for (size_t i = 0; i < pairs; ++i)
{
bytesConstRef const pair = _in.cropped(i * pairSize, pairSize);
libff::alt_bn128_G2 const 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()};
if (p.is_zero())
continue; // the pairing is one
if (decodePointG1(pair).is_zero())
continue; // the pairing is one
x = x * libff::alt_bn128_miller_loop(
libff::alt_bn128_precompute_G1(decodePointG1(pair)),
libff::alt_bn128_precompute_G2(p)
);
}
bool const result = libff::alt_bn128_final_exponentiation(x) == libff::alt_bn128_GT::one();
return {true, h256{result}.asBytes()};
}
catch (InvalidEncoding const&)
{
// Signal the call failure for invalid input.
return {false, bytes{}};
}
}

pair<bool, bytes> dev::crypto::alt_bn128_G1_add(dev::bytesConstRef _in)
{
try
{
initLibSnark();
libff::alt_bn128_G1 const p1 = decodePointG1(_in);
libff::alt_bn128_G1 const p2 = decodePointG1(_in.cropped(32 * 2));
return {true, encodePointG1(p1 + p2)};
}
catch (InvalidEncoding const&)
{
// Signal the call failure for invalid input.
return {false, bytes{}};
}
}

pair<bool, bytes> dev::crypto::alt_bn128_G1_mul(dev::bytesConstRef _in)
{
try
{
initLibSnark();
libff::alt_bn128_G1 const p = decodePointG1(_in.cropped(0));
libff::alt_bn128_G1 const result = toLibsnarkBigint(h256(_in.cropped(64), h256::AlignLeft)) * p;
return {true, encodePointG1(result)};
}
catch (InvalidEncoding const&)
{
// Signal the call failure for invalid input.
return {false, bytes{}};
}
}
35 changes: 35 additions & 0 deletions libdevcrypto/LibSnark.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file LibSnark.h
*/

#pragma once

#include <libdevcore/Common.h>

namespace dev
{
namespace crypto
{

std::pair<bool, bytes> alt_bn128_pairing_product(bytesConstRef _in);
std::pair<bool, bytes> alt_bn128_G1_add(bytesConstRef _in);
std::pair<bool, bytes> alt_bn128_G1_mul(bytesConstRef _in);

}
}
3 changes: 3 additions & 0 deletions libethashseal/genesis/mainNetwork.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ R"E(
"0000000000000000000000000000000000000002": { "precompiled": { "name": "sha256", "linear": { "base": 60, "word": 12 } } },
"0000000000000000000000000000000000000003": { "precompiled": { "name": "ripemd160", "linear": { "base": 600, "word": 120 } } },
"0000000000000000000000000000000000000004": { "precompiled": { "name": "identity", "linear": { "base": 15, "word": 3 } } },
"0000000000000000000000000000000000000006": { "precompiled": { "name": "alt_bn128_G1_add", "startingBlock": "0xffffffffffffffffff", "linear": { "base": 500, "word": 0 } } },
"0000000000000000000000000000000000000007": { "precompiled": { "name": "alt_bn128_G1_mul", "startingBlock": "0xffffffffffffffffff", "linear": { "base": 2000, "word": 0 } } },
"0000000000000000000000000000000000000008": { "precompiled": { "name": "alt_bn128_pairing_product", "startingBlock": "0xffffffffffffffffff" } },
"3282791d6fd713f1e94f4bfd565eaa78b3a0599d": {
"balance": "1337000000000000000000"
},
Expand Down
Loading

0 comments on commit 8f8edab

Please sign in to comment.