diff --git a/qa/rpc-tests/test_framework/script.py b/qa/rpc-tests/test_framework/script.py index ad64d7c84a8..6287588c246 100644 --- a/qa/rpc-tests/test_framework/script.py +++ b/qa/rpc-tests/test_framework/script.py @@ -235,7 +235,7 @@ def __new__(cls, n): OP_NOP1 = CScriptOp(0xb0) OP_CHECKLOCKTIMEVERIFY = CScriptOp(0xb1) OP_CHECKSEQUENCEVERIFY = CScriptOp(0xb2) -OP_CHECKGROTH16VERIFY = CScriptOp(0xb3) +OP_CHECKZKPVERIFY = CScriptOp(0xb3) OP_NOP5 = CScriptOp(0xb4) OP_NOP6 = CScriptOp(0xb5) OP_NOP7 = CScriptOp(0xb6) @@ -362,7 +362,7 @@ def __new__(cls, n): OP_NOP1, OP_CHECKLOCKTIMEVERIFY, OP_CHECKSEQUENCEVERIFY, - OP_CHECKGROTH16VERIFY, + OP_CHECKZKPVERIFY, OP_NOP5, OP_NOP6, OP_NOP7, @@ -481,7 +481,7 @@ def __new__(cls, n): OP_NOP1 : 'OP_NOP1', OP_CHECKLOCKTIMEVERIFY : 'OP_CHECKLOCKTIMEVERIFY', OP_CHECKSEQUENCEVERIFY : 'OP_CHECKSEQUENCEVERIFY', - OP_CHECKGROTH16VERIFY : 'OP_CHECKGROTH16VERIFY', + OP_CHECKZKPVERIFY : 'OP_CHECKZKPVERIFY', OP_NOP5 : 'OP_NOP5', OP_NOP6 : 'OP_NOP6', OP_NOP7 : 'OP_NOP7', @@ -600,7 +600,7 @@ def __new__(cls, n): 'OP_NOP1' : OP_NOP1, 'OP_CHECKLOCKTIMEVERIFY' : OP_CHECKLOCKTIMEVERIFY, 'OP_CHECKSEQUENCEVERIFY' : OP_CHECKSEQUENCEVERIFY, - 'OP_CHECKGROTH16VERIFY' : OP_CHECKGROTH16VERIFY, + 'OP_CHECKZKPVERIFY' : OP_CHECKZKPVERIFY, 'OP_NOP5' : OP_NOP5, 'OP_NOP6' : OP_NOP6, 'OP_NOP7' : OP_NOP7, diff --git a/src/Makefile.am b/src/Makefile.am index d245d60b6ed..2739da7c484 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -509,7 +509,7 @@ $(top_srcdir)/$(subdir)/config/bitcoin-config.h.in: $(am__configure_deps) clean-local: -$(MAKE) -C secp256k1 clean - -$(MAKE) -C bls clean + -$(MAKE) -C bls12-381 clean -$(MAKE) -C univalue clean -rm -f leveldb/*/*.gcda leveldb/*/*.gcno leveldb/helpers/memenv/*.gcda leveldb/helpers/memenv/*.gcno -rm -f config.h diff --git a/src/Makefile.bench.include b/src/Makefile.bench.include index 2483f927763..b3ddcd8620d 100644 --- a/src/Makefile.bench.include +++ b/src/Makefile.bench.include @@ -24,6 +24,7 @@ bench_bench_dogecoin_SOURCES = \ bench/lockedpool.cpp \ bench/perf.cpp \ bench/perf.h \ + bench/verify_script.cpp \ bench/scrypt.cpp # bench_bench_dogecoin_SOURCES_DISABLED = \ diff --git a/src/bench/verify_script.cpp b/src/bench/verify_script.cpp index 23bbadc88d0..9b3c8695089 100644 --- a/src/bench/verify_script.cpp +++ b/src/bench/verify_script.cpp @@ -10,6 +10,7 @@ #include "script/script.h" #include "script/sign.h" #include "streams.h" +#include // FIXME: Dedup with BuildCreditingTransaction in test/script_tests.cpp. static CMutableTransaction BuildCreditingTransaction(const CScript& scriptPubKey) @@ -99,4 +100,41 @@ static void VerifyScriptBench(benchmark::State& state) } } +static void VerifyGROTH16ScriptBench(benchmark::State& state) +{ + const int flags = SCRIPT_VERIFY_P2SH; + + CMutableTransaction txCredit; + DecodeHexTx(txCredit, "0200000001d5258a4fd597edc59d3a9166557c078f05bb992c926d90a0f18c75302d93f99000000000fd0203307f4e6a794e3317a1a2f06a8163ebd70a4a714a5f712d4259a9387d6589615bf63e95bb9233b844f47f5e2a0a312cb300308ddb1235bf6f33189982611ce46edbf62762cf1bda4e245c28c9622452e579078384c4a7c83b00b9b5cb96eaca9abe1130a882ef4edc6a154f1f62d53bf8bf55daeabdf528bbdc9fc7935f37449bafd302aaf19156548ba8b28d29a278ea92f094302882cbef8b8e4f89687f9e8eedc70e8400b0293c05e41c29252683855ecab667100996bda1d61091ccec5c61db9508814c50b9d96fecdd99ff136355dc90772a2ef7788afe1f8a332b34e8a30402477f8e38e874eba3946f6f4ba8c794a09d266507dd66ecb824f911036f2b6bf63ee7a5feb52105bdf466dac06ca427711d5b52c24de90120caec89bedcab3ce707981a6fa86d27b87b2c0a732feee3717aaddd6728877c007c76a82081c202329a17f5756142a72734f6832f7784e22b1e17260901039f504f9098a3884c5090c10d96e70d136fac9a3634428f3792e9b8d02eb903783f71fc8e6937f7f8b1360c8bee9146041a79251614eee9689073af20af273a280e841b078837e65a862279849c1251e1761bb6ac35f2649ea34c50fe63d02ab4af4ab3448fe5e8d4fff135d510a38558c9daee4ae190303c18368ce2ba9fd21e8d1ab0f617a9d249621b56f224b69f6c3a3e008a40b3aea5a5ab77eed73711e93c896023475b27e3a4f6124c50189647ab2c8de2fc37ef189f803704cc55087bfe1c56dcabbb2f343dc145a0470d18317696e1023a7574e8745e0ea301cc6cd679a61133a1c560d5aa3d38d91a999a8f666109495402c553bd7c82056b4c50bf358e5097046487c370c1dd6781dc11d6518717e23b334d4b09892a9763f09059687a7c136f6189568edd6d6f357c1c199a39fa0f723d2218762766f67fa8171b10e8b7e5dd88155651d37ca6b59c754c50092d3dfea8804a69cab1f76133032b85ee7e850977dd1fe578f3d9663bb43a08502a8fd7cb8c7f79c39fbe49f9cee082bf68dfd65e70ccdbfb4c6f834d5dcb3e4619bc44de9ca8aca12b502e74b7b50451b36d6d6d6d6d6d51ffffffff0100113d550200000017a914fda635e6bc2ef7efa82521342c1e3ab932153c628700000000"); + CMutableTransaction txSpend; + DecodeHexTx(txSpend, "0200000002952da86dd9c8e4f2587be7adfa9ebe531cc05a8e733f7bd6c02c7ac9f03503b300000000fd020330a1cf4fd86ec455bbe8b983c0dd64abe78ef065724960fecce845873a9df15e10e16c60e948fddd722bd68ed469cca20e30a9cb9215f93c6d926a22367fab2e95d54560a06412ca51304da82d2ee75521a6f58996298c14fe566795d2f654efda0130f23b6a58474bfc3e89499bce8bf7b280b2d84707ffa7f86bc9c94a8174b99f7df7be7e531e8ea759f60abdb4864ad7023016e9e0aa1e58d75831dd90aef95657a5a5e96e9196e6a02f6cb8c6371d311d5654dda6dfd522626f4c90aa0861b067024c50b9d96fecdd99ff136355dc90772a2ef7788afe1f8a332b34e8a30402477f8e38e874eba3946f6f4ba8c794a09d266507dd66ecb824f911036f2b6bf63ee7a5feb52105bdf466dac06ca427711d5b52c24de9012000f3a40258113d7544ec3a1c548047ab9a14e5488320414a311d8de59b7414007c76a82081c202329a17f5756142a72734f6832f7784e22b1e17260901039f504f9098a3884c5090c10d96e70d136fac9a3634428f3792e9b8d02eb903783f71fc8e6937f7f8b1360c8bee9146041a79251614eee9689073af20af273a280e841b078837e65a862279849c1251e1761bb6ac35f2649ea34c50fe63d02ab4af4ab3448fe5e8d4fff135d510a38558c9daee4ae190303c18368ce2ba9fd21e8d1ab0f617a9d249621b56f224b69f6c3a3e008a40b3aea5a5ab77eed73711e93c896023475b27e3a4f6124c50189647ab2c8de2fc37ef189f803704cc55087bfe1c56dcabbb2f343dc145a0470d18317696e1023a7574e8745e0ea301cc6cd679a61133a1c560d5aa3d38d91a999a8f666109495402c553bd7c82056b4c50bf358e5097046487c370c1dd6781dc11d6518717e23b334d4b09892a9763f09059687a7c136f6189568edd6d6f357c1c199a39fa0f723d2218762766f67fa8171b10e8b7e5dd88155651d37ca6b59c754c50092d3dfea8804a69cab1f76133032b85ee7e850977dd1fe578f3d9663bb43a08502a8fd7cb8c7f79c39fbe49f9cee082bf68dfd65e70ccdbfb4c6f834d5dcb3e4619bc44de9ca8aca12b502e74b7b50451b36d6d6d6d6d6d51ffffffffa75fe7d127ffba6a51a6aa750aec49d6861b7e3cc809f259cfcf3d95c71574b900000000fd02033091d0f9aff7bd3da433eb5706a7914bc49d19ea781a9b8eee183929cdfc7a79773a244992d5afd3e9ddc61d70f73b0194300739ce49ac859b19f03d3c0c2bbb7ffb24e64c32e4e632fe74e3a53f5e5aa10ee3551061b3818aa3e126d960cb593f163035c36460f49449043c7892acebd0518122551501a7abd5a00df0962ce1f6977399a5ef4762c0d80ceec2c9833891c617301120658e06a7ede8415aded94c242e8a6d661732a1b8826114814421aff13fec59f847961ae3181b7a533d40f4aa3a924c50b9d96fecdd99ff136355dc90772a2ef7788afe1f8a332b34e8a30402477f8e38e874eba3946f6f4ba8c794a09d266507dd66ecb824f911036f2b6bf63ee7a5feb52105bdf466dac06ca427711d5b52c24de9012000f3a40258113d7544ec3a1c548047ab9a14e5488320414a311d8de59b7414007c76a82081c202329a17f5756142a72734f6832f7784e22b1e17260901039f504f9098a3884c5090c10d96e70d136fac9a3634428f3792e9b8d02eb903783f71fc8e6937f7f8b1360c8bee9146041a79251614eee9689073af20af273a280e841b078837e65a862279849c1251e1761bb6ac35f2649ea34c50fe63d02ab4af4ab3448fe5e8d4fff135d510a38558c9daee4ae190303c18368ce2ba9fd21e8d1ab0f617a9d249621b56f224b69f6c3a3e008a40b3aea5a5ab77eed73711e93c896023475b27e3a4f6124c50189647ab2c8de2fc37ef189f803704cc55087bfe1c56dcabbb2f343dc145a0470d18317696e1023a7574e8745e0ea301cc6cd679a61133a1c560d5aa3d38d91a999a8f666109495402c553bd7c82056b4c50bf358e5097046487c370c1dd6781dc11d6518717e23b334d4b09892a9763f09059687a7c136f6189568edd6d6f357c1c199a39fa0f723d2218762766f67fa8171b10e8b7e5dd88155651d37ca6b59c754c50092d3dfea8804a69cab1f76133032b85ee7e850977dd1fe578f3d9663bb43a08502a8fd7cb8c7f79c39fbe49f9cee082bf68dfd65e70ccdbfb4c6f834d5dcb3e4619bc44de9ca8aca12b502e74b7b50451b36d6d6d6d6d6d51ffffffff01003e6e560200000017a9149faff0ec8c48761a48a8023ed8fd7b8af103c0888700000000"); + + // Benchmark. + while (state.KeepRunning()) { + ScriptError err; + bool success = VerifyScript( + txSpend.vin[0].scriptSig, + txCredit.vout[0].scriptPubKey, + &txSpend.vin[0].scriptWitness, + flags, + MutableTransactionSignatureChecker(&txSpend, 0, txCredit.vout[0].nValue), + &err); + assert(err == SCRIPT_ERR_OK); + assert(success); + +// #if defined(HAVE_CONSENSUS_LIB) +// CDataStream stream(SER_NETWORK, PROTOCOL_VERSION); +// stream << txSpend; +// int csuccess = bitcoinconsensus_verify_script_with_amount( +// txCredit.vout[0].scriptPubKey.data(), +// txCredit.vout[0].scriptPubKey.size(), +// txCredit.vout[0].nValue, +// (const unsigned char*)stream.data(), stream.size(), 0, flags, nullptr); +// assert(csuccess == 1); +// #endif + } +} + + +BENCHMARK(VerifyGROTH16ScriptBench); BENCHMARK(VerifyScriptBench); diff --git a/src/bls12-381/.gitignore b/src/bls12-381/.gitignore new file mode 100644 index 00000000000..e2712ccb833 --- /dev/null +++ b/src/bls12-381/.gitignore @@ -0,0 +1,37 @@ +Makefile +configure +.libs/ +Makefile.in +aclocal.m4 +autom4te.cache/ +config.log +config.status +conftest* +*.tar.gz +*.la +libtool +.deps/ +.dirstamp +*.lo +*.o +*~ +*.log + + +src/bls-config.h +src/libbls-config.h.in +build-aux/ar-lib +build-aux/config.guess +build-aux/config.sub +build-aux/depcomp +build-aux/install-sh +build-aux/ltmain.sh +build-aux/m4/libtool.m4 +build-aux/m4/lt~obsolete.m4 +build-aux/m4/ltoptions.m4 +build-aux/m4/ltsugar.m4 +build-aux/m4/ltversion.m4 +build-aux/missing +build-aux/compile +build-aux/test-driver +libbls.pc diff --git a/src/bls12-381/Makefile.am b/src/bls12-381/Makefile.am index ca4ef1bc205..2b472aa336a 100644 --- a/src/bls12-381/Makefile.am +++ b/src/bls12-381/Makefile.am @@ -1,12 +1,8 @@ -ACLOCAL_AMFLAGS = -I build-aux/m4 -AM_CXXFLAGS = -std=c++17 -fpic -O2 -AM_CPPFLAGS = -std=c++17 -fpic -O2 +AM_CXXFLAGS = $(CXXFLAGS) -AM_CFLAGS = --fpic -O2 +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = libbls.pc lib_LTLIBRARIES = libbls.la libbls_la_SOURCES = src/groth16.cpp src/arithmetic.cpp src/fp.cpp src/g.cpp src/pairing.cpp src/scalar.cpp src/utils.cpp - -pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_DATA = libbls.pc diff --git a/src/bls12-381/configure.ac b/src/bls12-381/configure.ac index 9642d712f55..14cb9411835 100644 --- a/src/bls12-381/configure.ac +++ b/src/bls12-381/configure.ac @@ -13,55 +13,48 @@ AC_INIT([libbls], m4_join([.], _PKG_VERSION_MAJOR, _PKG_VERSION_MINOR, _PKG_VERS AC_SUBST(LIB_VERSION_CURRENT, _LIB_VERSION_CURRENT) AC_SUBST(LIB_VERSION_REVISION, _LIB_VERSION_REVISION) AC_SUBST(LIB_VERSION_AGE, _LIB_VERSION_AGE) -AC_CONFIG_AUX_DIR([build-aux]) -AC_CONFIG_MACRO_DIR([build-aux/m4]) -AC_CANONICAL_HOST -AH_TOP([#ifndef LIBMCL_CONFIG_H]) -AH_TOP([#define LIBMCL_CONFIG_H]) -AH_BOTTOM([#endif /*LIBMCL_CONFIG_H*/]) AM_INIT_AUTOMAKE([1.11.2 foreign subdir-objects]) -m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) +AC_ARG_ENABLE([blsasm], [AS_HELP_STRING([--enable-blsasm=yes|no], [Enable blsasm option])], [], [enable_blsasm=no]) AC_PROG_CXX -AC_PROG_CC AM_PROG_AR LT_INIT([win32-dll]) + +CXXFLAGS="-O3 -I include" + AC_CANONICAL_HOST -case "$host_os" in - *mingw64*) - CXXFLAGS="$CXXFLAGS -D__USE_MINGW_ANSI_STDIO=1" - ;; - *cygwin*) - ;; - *darwin*) - AC_DEFINE([DARWIN], [1], [Define if on Darwin/Mac OS X]) - ;; - *openbsd*) - CXXFLAGS="$CXXFLAGS -I/usr/local/include" - LDFLAGS="$LDFLAGS -L/usr/local/lib" - ;; - *freebsd*) - CXXFLAGS="$CXXFLAGS -I/usr/local/include" - LDFLAGS="$LDFLAGS -L/usr/local/lib" - ;; - *linux*) - CXXFLAGS="$CXXFLAGS -I/usr/local/include" - LDFLAGS="$LDFLAGS -L/usr/local/lib" - ;; +AC_CANONICAL_TARGET +case $target_cpu in + x86_64*) + AC_MSG_NOTICE(["The target platform is $target_cpu"]) + if test "x$enable_blsasm" = "xyes"; then + AC_MSG_NOTICE(["Enable blsasm"]) + CXXFLAGS="$CXXFLAGS -D__x86_64_asm__" + else + AC_MSG_NOTICE(["Disable blsasm $host_os"]) + case $host_os in + darwin*) + CXXFLAGS="$CXXFLAGS" + ;; + *) + CXXFLAGS="$CXXFLAGS -flto" + ;; + esac + fi + ;; + *) + AC_MSG_NOTICE([The target platform is not x86_64]) + CXXFLAGS="$CXXFLAGS -flto" + ;; esac -CXXFLAGS_WARN="-Wall -Wextra -Wformat=2 -Wcast-qual -Wcast-align -Wwrite-strings -Wfloat-equal -Wpointer-arith -Wundef" -CXXFLAGS="$CXXFLAGS $CXXFLAGS_WARN -I include -I src" - -AC_SUBST(CXXFLAGS) -AC_SUBST(LDFLAGS) AC_SUBST(CXX) -AC_SUBST(CC) +AC_SUBST(CXXFLAGS) AC_CONFIG_FILES([Makefile libbls.pc]) @@ -76,4 +69,5 @@ echo " CPPFLAGS = $CPPFLAGS" echo " CXX = $CXX" echo " CXXFLAGS = $CXXFLAGS" echo " LDFLAGS = $LDFLAGS" +echo " ENABLE_BLSASM = $enable_blsasm" echo diff --git a/src/bls12-381/include/bls12-381/arithmetic.hpp b/src/bls12-381/include/bls12-381/arithmetic.hpp index 1006b5561c9..eecbf02b451 100644 --- a/src/bls12-381/include/bls12-381/arithmetic.hpp +++ b/src/bls12-381/include/bls12-381/arithmetic.hpp @@ -1,8 +1,11 @@ #include #include +#if defined(UINT128_MAX) || defined(__SIZEOF_INT128__) +#define USE_INT128 typedef __int128 int128_t; typedef unsigned __int128 uint128_t; +#endif namespace bls12_381 { @@ -27,9 +30,7 @@ void _lsubtract(fp* z, const fp* x, const fp* y); // The "smaller than 4p" here means the montgomery form itself as number is less than 4p. // Therefore, at most ONE _ladd/_lsubstract/_ldouble is allowed before passing the result to _multiply, // unless the algorithm makes sure the number is small. -#if defined(__x86_64__) && defined(__ELF__) -extern void _multiply(fp*, const fp*, const fp*); -#elif defined(__x86_64__) +#if defined(__x86_64_asm__) extern void (*_multiply)(fp*, const fp*, const fp*); #else void _multiply(fp*, const fp*, const fp*); @@ -40,7 +41,7 @@ void _multiply(fp*, const fp*, const fp*); // The carryOut output is guaranteed to be 0 or 1. // // This function's execution time does not depend on the inputs. -std::tuple Add64( +inline std::tuple Add64( const uint64_t& x, const uint64_t& y, const uint64_t& carry @@ -62,12 +63,12 @@ std::tuple Sub64( // half returned in lo. // // This function's execution time does not depend on the inputs. -std::tuple Mul64( +inline std::tuple Mul64( const uint64_t& x, const uint64_t& y ); -std::tuple madd( +inline std::tuple madd( const uint64_t& a, const uint64_t& b, const uint64_t& t, @@ -76,21 +77,21 @@ std::tuple madd( ); // madd0 hi = a*b + c (discards lo bits) -uint64_t madd0( +inline uint64_t madd0( const uint64_t& a, const uint64_t& b, const uint64_t& c ); // madd1 hi, lo = a*b + c -std::tuple madd1( +inline std::tuple madd1( const uint64_t& a, const uint64_t& b, const uint64_t& c ); // madd2 hi, lo = a*b + c + d -std::tuple madd2( +inline std::tuple madd2( const uint64_t& a, const uint64_t& b, const uint64_t& c, @@ -98,7 +99,7 @@ std::tuple madd2( ); // madd2s superhi, hi, lo = 2*a*b + c + d + e -std::tuple madd2s( +inline std::tuple madd2s( const uint64_t& a, const uint64_t& b, const uint64_t& c, @@ -106,27 +107,27 @@ std::tuple madd2s( const uint64_t& e ); -std::tuple madd1s( +inline std::tuple madd1s( const uint64_t& a, const uint64_t& b, const uint64_t& d, const uint64_t& e ); -std::tuple madd2sb( +inline std::tuple madd2sb( const uint64_t& a, const uint64_t& b, const uint64_t& c, const uint64_t& e ); -std::tuple madd1sb( +inline std::tuple madd1sb( const uint64_t& a, const uint64_t& b, const uint64_t& e ); -std::tuple madd3( +inline std::tuple madd3( const uint64_t& a, const uint64_t& b, const uint64_t& c, diff --git a/src/bls12-381/include/bls12-381/g.hpp b/src/bls12-381/include/bls12-381/g.hpp index de0e4cc483e..562b4705b5e 100644 --- a/src/bls12-381/include/bls12-381/g.hpp +++ b/src/bls12-381/include/bls12-381/g.hpp @@ -38,13 +38,11 @@ class g1 void toAffineBytesBE(const tcb::span out, const from_mont fm = from_mont::yes) const; void toAffineBytesLE(const tcb::span out, const from_mont fm = from_mont::yes) const; void toCompressedBytesBE(const tcb::span out) const; - void toCompressedMCLBytesLE(const tcb::span out) const; std::array toJacobianBytesBE(const from_mont fm = from_mont::yes) const; std::array toJacobianBytesLE(const from_mont fm = from_mont::yes) const; std::array toAffineBytesBE(const from_mont fm = from_mont::yes) const; std::array toAffineBytesLE(const from_mont fm = from_mont::yes) const; std::array toCompressedBytesBE() const; - std::array toCompressedMCLBytesLE() const; static g1 zero(); static g1 one(); bool isZero() const; @@ -134,13 +132,11 @@ class g2 void toAffineBytesBE(const tcb::span out, const from_mont fm = from_mont::yes) const; void toAffineBytesLE(const tcb::span out, const from_mont fm = from_mont::yes) const; void toCompressedBytesBE(const tcb::span out) const; - void toCompressedMCLBytesLE(const tcb::span out) const; std::array toJacobianBytesBE(const from_mont fm = from_mont::yes) const; std::array toJacobianBytesLE(const from_mont fm = from_mont::yes) const; std::array toAffineBytesBE(const from_mont fm = from_mont::yes) const; std::array toAffineBytesLE(const from_mont fm = from_mont::yes) const; std::array toCompressedBytesBE() const; - std::array toCompressedMCLBytesLE() const; static g2 zero(); static g2 one(); bool isZero() const; diff --git a/src/bls12-381/include/bls12-381/scalar.hpp b/src/bls12-381/include/bls12-381/scalar.hpp index e48d997f7b8..13698600e85 100644 --- a/src/bls12-381/include/bls12-381/scalar.hpp +++ b/src/bls12-381/include/bls12-381/scalar.hpp @@ -364,44 +364,4 @@ g2 g2::scale(const std::array& s) const return q; } -template -std::string bytesToHex(const tcb::span& in) -{ - char hexmap[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; - std::string s(2 + N * 2, ' '); - s[0] = '0'; - s[1] = 'x'; - for(uint64_t i = 0; i < N; i++) - { - s[2 + 2*i] = hexmap[(in[i] & 0xF0) >> 4]; - s[2 + 2*i+1] = hexmap[ in[i] & 0x0F ]; - } - return s; -} -std::string bytesToHex(tcb::span in); - -template -void hexToBytes(const std::string& s, tcb::span out) -{ - // No checks on the string length in the compile time version! - uint64_t start_idx = 0; - if(s[0] == '0' && s[1] == 'x') - { - start_idx = 2; - } - - for(size_t i = 0, j = start_idx; i < N; i++, j += 2) - { - out[i] = (s[j] % 32 + 9) % 25 * 16 + (s[j+1] % 32 + 9) % 25; - } -} -template -std::array hexToBytes(const std::string& s) -{ - std::array out; - hexToBytes(s, out); - return out; -} -std::vector hexToBytes(std::string &s); - } // namespace bls12_381 diff --git a/src/bls12-381/include/groth16/serialize.hpp b/src/bls12-381/include/groth16/serialize.hpp index d50c9453624..aa63a41198a 100644 --- a/src/bls12-381/include/groth16/serialize.hpp +++ b/src/bls12-381/include/groth16/serialize.hpp @@ -3,7 +3,5 @@ namespace bls12_381_groth16 { bool deserializeG1FromVector(bls12_381::g1 *out, const std::vector *v, size_t startIndex); - bool deserializeG2FromVector(bls12_381::g1 *out, const std::vector *v, size_t startIndex); - bool deserializeFpFromVector(bls12_381::fp *out, const std::vector *v, size_t startIndex); bool deserializeScalarFromVector(const std::array &out, const std::vector *v, size_t startIndex); } \ No newline at end of file diff --git a/src/bls12-381/libbls.pc.in b/src/bls12-381/libbls.pc.in index e8cf3caa83e..0a672b5b23c 100644 --- a/src/bls12-381/libbls.pc.in +++ b/src/bls12-381/libbls.pc.in @@ -3,7 +3,7 @@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ -Name: libmcl +Name: libbls Description: Pairing Library URL: https://github.com/QEDProtocol/bls12-381 Version: @PACKAGE_VERSION@ diff --git a/src/bls12-381/src/arithmetic.cpp b/src/bls12-381/src/arithmetic.cpp index d5f2650ae8f..0a9d19c3d06 100644 --- a/src/bls12-381/src/arithmetic.cpp +++ b/src/bls12-381/src/arithmetic.cpp @@ -1,5 +1,5 @@ #include -#ifdef __x86_64__ +#ifdef __x86_64_asm__ #include #endif @@ -8,7 +8,7 @@ using namespace std; namespace bls12_381 { -#ifdef __x86_64__ +#ifdef __x86_64_asm__ void _add(fp* z, const fp* x, const fp* y) { // x86_64 calling convention (https://en.wikipedia.org/wiki/X86_calling_conventions#System_V_AMD64_ABI): @@ -96,7 +96,7 @@ void _add(fp* z, const fp* x, const fp* y) } #endif -#ifdef __x86_64__ +#ifdef __x86_64_asm__ void _ladd(fp* z, const fp* x, const fp* y) { // x86_64 calling convention (https://en.wikipedia.org/wiki/X86_calling_conventions#System_V_AMD64_ABI): @@ -136,7 +136,7 @@ void _ladd(fp* z, const fp* x, const fp* y) } #endif -#ifdef __x86_64__ +#ifdef __x86_64_asm__ void _double(fp* z, const fp* x) { // x86_64 calling convention (https://en.wikipedia.org/wiki/X86_calling_conventions#System_V_AMD64_ABI): @@ -223,7 +223,7 @@ void _double(fp* z, const fp* x) } #endif -#ifdef __x86_64__ +#ifdef __x86_64_asm__ void _ldouble(fp* z, const fp* x) { // x86_64 calling convention (https://en.wikipedia.org/wiki/X86_calling_conventions#System_V_AMD64_ABI): @@ -263,7 +263,7 @@ void _ldouble(fp* z, const fp* x) } #endif -#ifdef __x86_64__ +#ifdef __x86_64_asm__ void _subtract(fp* z, const fp* x, const fp* y) { // x86_64 calling convention (https://en.wikipedia.org/wiki/X86_calling_conventions#System_V_AMD64_ABI): @@ -342,7 +342,7 @@ void _subtract(fp* z, const fp* x, const fp* y) } #endif -#ifdef __x86_64__ +#ifdef __x86_64_asm__ void _lsubtract(fp* z, const fp* x, const fp* y) { // x86_64 calling convention (https://en.wikipedia.org/wiki/X86_calling_conventions#System_V_AMD64_ABI): @@ -382,7 +382,7 @@ void _lsubtract(fp* z, const fp* x, const fp* y) } #endif -#ifdef __x86_64__ +#ifdef __x86_64_asm__ void __negate(fp* z, const fp* x) { // x86_64 calling convention (https://en.wikipedia.org/wiki/X86_calling_conventions#System_V_AMD64_ABI): @@ -436,7 +436,7 @@ void _negate(fp* z, const fp* x) } #endif -#ifdef __x86_64__ +#ifdef __x86_64_asm__ void __multiply(fp* z, const fp* x, const fp* y) { // x86_64 calling convention (https://en.wikipedia.org/wiki/X86_calling_conventions#System_V_AMD64_ABI): @@ -1490,25 +1490,6 @@ static bool cpu_has_bmi2_and_adx() { return false; } -#ifdef __ELF__ -extern "C" char** _dl_argv; - -extern "C" blsmul_func_t __attribute__((no_sanitize_address)) resolve_blsmul() { - int argc = *(int*)(_dl_argv - 1); - char** my_environ = (char**)(_dl_argv + argc + 1); - while(*my_environ != nullptr) { - const char disable_str[] = "BLS_DISABLE_BMI2"; - if(strncmp(*my_environ++, disable_str, strlen(disable_str)) == 0) - return __multiply; - } - - if(cpu_has_bmi2_and_adx()) - return __mul_ex; - return __multiply; -} - -void _multiply(fp*, const fp*, const fp*) __attribute__((ifunc("resolve_blsmul"))); -#else blsmul_func_t _multiply = __multiply; struct bls_mul_init { @@ -1519,7 +1500,7 @@ struct bls_mul_init { }; static bls_mul_init the_bls_mul_init; -#endif //__ELF__ + #else void _multiply(fp* z, const fp* x, const fp* y) { @@ -1643,7 +1624,7 @@ void _multiply(fp* z, const fp* x, const fp* y) } #endif -#ifdef __x86_64__ +#ifdef __x86_64_asm__ void _square(fp* z, const fp* x) { #ifdef __clang__ @@ -1807,9 +1788,23 @@ tuple Mul64( const uint64_t& y ) { + #if defined(USE_INT128) uint128_t result = static_cast(x) * static_cast(y); uint64_t lo = result; uint64_t hi = result >> 64; + #else + uint64_t lo, hi, mid = 0; + uint64_t lo_carry, hi_carry, mid_carry = 0; + uint64_t hix = x >> 32; + uint64_t lox = x & 0xFFFFFFFF; + uint64_t hiy = y >> 32; + uint64_t loy = y & 0xFFFFFFFF; + tie(mid, mid_carry) = Add64(hix * loy, hiy * lox, 0); + tie(lo, lo_carry) = Add64(lox * loy, (mid & 0xFFFFFFFF) << 32, 0); + lo_carry += mid_carry << 32; + tie(hi, hi_carry) = Add64(hix * hiy, mid >> 32, lo_carry); + #endif + return {hi, lo}; } diff --git a/src/bls12-381/src/fp.cpp b/src/bls12-381/src/fp.cpp index 29c30250d76..b19d503c045 100644 --- a/src/bls12-381/src/fp.cpp +++ b/src/bls12-381/src/fp.cpp @@ -341,12 +341,12 @@ bool fp::isQuadraticNonResidue() const bool fp::isLexicographicallyLargest() const { array halfQ = { - 0x0D00'88F5'1CBF'F34D, - 0x258D'D3DB'21A5'D66B, - 0xB23B'A5C2'79C2'895F, - 0xB398'6950'7B58'7B12, - 0x0F55'FFFF'58A9'FFFF, - 0xDCFF'7FFF'FFFF'D556 + 0x0D0088F51CBFF34D, + 0x258DD3DB21A5D66B, + 0xB23BA5C279C2895F, + 0xB39869507B587B12, + 0x0F55FFFF58A9FFFF, + 0xDCFF7FFFFFFFD556 }; array yValue = fromMont().d; @@ -364,93 +364,93 @@ bool fp::isLexicographicallyLargest() const const fp fp::MODULUS = fp( { - 0xb9fe'ffff'ffff'aaab, - 0x1eab'fffe'b153'ffff, - 0x6730'd2a0'f6b0'f624, - 0x6477'4b84'f385'12bf, - 0x4b1b'a7b6'434b'acd7, - 0x1a01'11ea'397f'e69a, + 0xb9feffffffffaaab, + 0x1eabfffeb153ffff, + 0x6730d2a0f6b0f624, + 0x64774b84f38512bf, + 0x4b1ba7b6434bacd7, + 0x1a0111ea397fe69a, }); -const uint64_t fp::INP = 0x89f3'fffc'fffc'fffd; +const uint64_t fp::INP = 0x89f3fffcfffcfffd; const fp fp::R1 = fp({ - 0x7609'0000'0002'fffd, - 0xebf4'000b'c40c'0002, - 0x5f48'9857'53c7'58ba, - 0x77ce'5853'7052'5745, - 0x5c07'1a97'a256'ec6d, - 0x15f6'5ec3'fa80'e493, + 0x760900000002fffd, + 0xebf4000bc40c0002, + 0x5f48985753c758ba, + 0x77ce585370525745, + 0x5c071a97a256ec6d, + 0x15f65ec3fa80e493, }); const fp fp::R2 = fp({ - 0xf4df'1f34'1c34'1746, - 0x0a76'e6a6'09d1'04f1, - 0x8de5'476c'4c95'b6d5, - 0x67eb'88a9'939d'83c0, - 0x9a79'3e85'b519'952d, - 0x1198'8fe5'92ca'e3aa, + 0xf4df1f341c341746, + 0x0a76e6a609d104f1, + 0x8de5476c4c95b6d5, + 0x67eb88a9939d83c0, + 0x9a793e85b519952d, + 0x11988fe592cae3aa, }); const fp fp::B = fp({ - 0xaa27'0000'000c'fff3, - 0x53cc'0032'fc34'000a, - 0x478f'e97a'6b0a'807f, - 0xb1d3'7ebe'e6ba'24d7, - 0x8ec9'733b'bf78'ab2f, - 0x09d6'4551'3d83'de7e, + 0xaa270000000cfff3, + 0x53cc0032fc34000a, + 0x478fe97a6b0a807f, + 0xb1d37ebee6ba24d7, + 0x8ec9733bbf78ab2f, + 0x09d645513d83de7e, }); const fp fp::twoInv = fp({ - 0x1804'0000'0001'5554, - 0x8550'0005'3ab0'0001, - 0x633c'b57c'253c'276f, - 0x6e22'd1ec'31eb'b502, - 0xd391'6126'f2d1'4ca2, - 0x17fb'b857'1a00'6596 + 0x1804000000015554, + 0x855000053ab00001, + 0x633cb57c253c276f, + 0x6e22d1ec31ebb502, + 0xd3916126f2d14ca2, + 0x17fbb8571a006596 }); const fp fp::glvPhi1 = fp({ - 0xcd03'c9e4'8671'f071, - 0x5dab'2246'1fcd'a5d2, - 0x5870'42af'd385'1b95, - 0x8eb6'0ebe'01ba'cb9e, - 0x03f9'7d6e'83d0'50d2, - 0x18f0'2065'5463'8741 + 0xcd03c9e48671f071, + 0x5dab22461fcda5d2, + 0x587042afd3851b95, + 0x8eb60ebe01bacb9e, + 0x03f97d6e83d050d2, + 0x18f0206554638741 }); const array fp::Q = { - 0xffff'ffff'0000'0001, - 0x53bd'a402'fffe'5bfe, - 0x3339'd808'09a1'd805, - 0x73ed'a753'299d'7d48 + 0xffffffff00000001, + 0x53bda402fffe5bfe, + 0x3339d80809a1d805, + 0x73eda753299d7d48 }; const array fp::pPlus1Over4 = { - 0xee7f'bfff'ffff'eaab, - 0x07aa'ffff'ac54'ffff, - 0xd9cc'34a8'3dac'3d89, - 0xd91d'd2e1'3ce1'44af, - 0x92c6'e9ed'90d2'eb35, - 0x0680'447a'8e5f'f9a6 + 0xee7fbfffffffeaab, + 0x07aaffffac54ffff, + 0xd9cc34a83dac3d89, + 0xd91dd2e13ce144af, + 0x92c6e9ed90d2eb35, + 0x0680447a8e5ff9a6 }; const array fp::pMinus1Over2 = { - 0xdcff'7fff'ffff'd555, - 0x0f55'ffff'58a9'ffff, - 0xb398'6950'7b58'7b12, - 0xb23b'a5c2'79c2'895f, - 0x258d'd3db'21a5'd66b, - 0x0d00'88f5'1cbf'f34d + 0xdcff7fffffffd555, + 0x0f55ffff58a9ffff, + 0xb39869507b587b12, + 0xb23ba5c279c2895f, + 0x258dd3db21a5d66b, + 0x0d0088f51cbff34d }; const array fp::pMinus3Over4 = { - 0xee7f'bfff'ffff'eaaa, - 0x07aa'ffff'ac54'ffff, - 0xd9cc'34a8'3dac'3d89, - 0xd91d'd2e1'3ce1'44af, - 0x92c6'e9ed'90d2'eb35, - 0x0680'447a'8e5f'f9a6 + 0xee7fbfffffffeaaa, + 0x07aaffffac54ffff, + 0xd9cc34a83dac3d89, + 0xd91dd2e13ce144af, + 0x92c6e9ed90d2eb35, + 0x0680447a8e5ff9a6 }; fp2::fp2() : c0(fp()), c1(fp()) @@ -739,77 +739,77 @@ bool fp2::isLexicographicallyLargest() const const fp2 fp2::negativeOne2 = fp2({ fp({ - 0x43f5'ffff'fffc'aaae, - 0x32b7'fff2'ed47'fffd, - 0x07e8'3a49'a2e9'9d69, - 0xeca8'f331'8332'bb7a, - 0xef14'8d1e'a0f4'c069, - 0x040a'b326'3eff'0206 + 0x43f5fffffffcaaae, + 0x32b7fff2ed47fffd, + 0x07e83a49a2e99d69, + 0xeca8f3318332bb7a, + 0xef148d1ea0f4c069, + 0x040ab3263eff0206 }), fp({ - 0x0000'0000'0000'0000, - 0x0000'0000'0000'0000, - 0x0000'0000'0000'0000, - 0x0000'0000'0000'0000, - 0x0000'0000'0000'0000, - 0x0000'0000'0000'0000 + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000 }), }); const fp2 fp2::B = fp2({ fp({ - 0xaa27'0000'000c'fff3, - 0x53cc'0032'fc34'000a, - 0x478f'e97a'6b0a'807f, - 0xb1d3'7ebe'e6ba'24d7, - 0x8ec9'733b'bf78'ab2f, - 0x09d6'4551'3d83'de7e, + 0xaa270000000cfff3, + 0x53cc0032fc34000a, + 0x478fe97a6b0a807f, + 0xb1d37ebee6ba24d7, + 0x8ec9733bbf78ab2f, + 0x09d645513d83de7e, }), fp({ - 0xaa27'0000'000c'fff3, - 0x53cc'0032'fc34'000a, - 0x478f'e97a'6b0a'807f, - 0xb1d3'7ebe'e6ba'24d7, - 0x8ec9'733b'bf78'ab2f, - 0x09d6'4551'3d83'de7e, + 0xaa270000000cfff3, + 0x53cc0032fc34000a, + 0x478fe97a6b0a807f, + 0xb1d37ebee6ba24d7, + 0x8ec9733bbf78ab2f, + 0x09d645513d83de7e, }), }); const fp2 fp2::psiX = fp2({ fp({ - 0x0000'0000'0000'0000, - 0x0000'0000'0000'0000, - 0x0000'0000'0000'0000, - 0x0000'0000'0000'0000, - 0x0000'0000'0000'0000, - 0x0000'0000'0000'0000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, }), fp({ - 0x890d'c9e4'8675'45c3, - 0x2af3'2253'3285'a5d5, - 0x5088'0866'309b'7e2c, - 0xa20d'1b8c'7e88'1024, - 0x14e4'f04f'e2db'9068, - 0x14e5'6d3f'1564'853a, + 0x890dc9e4867545c3, + 0x2af322533285a5d5, + 0x50880866309b7e2c, + 0xa20d1b8c7e881024, + 0x14e4f04fe2db9068, + 0x14e56d3f1564853a, }), }); const fp2 fp2::psiY = fp2({ fp({ - 0x3e2f'585d'a55c'9ad1, - 0x4294'213d'86c1'8183, - 0x3828'44c8'8b62'3732, - 0x92ad'2afd'1910'3e18, - 0x1d79'4e4f'ac7c'f0b9, - 0x0bd5'92fc'7d82'5ec8, + 0x3e2f585da55c9ad1, + 0x4294213d86c18183, + 0x382844c88b623732, + 0x92ad2afd19103e18, + 0x1d794e4fac7cf0b9, + 0x0bd592fc7d825ec8, }), fp({ - 0x7bcf'a7a2'5aa3'0fda, - 0xdc17'dec1'2a92'7e7c, - 0x2f08'8dd8'6b4e'bef1, - 0xd1ca'2087'da74'd4a7, - 0x2da2'5966'96ce'bc1d, - 0x0e2b'7eed'bbfd'87d2, + 0x7bcfa7a25aa30fda, + 0xdc17dec12a927e7c, + 0x2f088dd86b4ebef1, + 0xd1ca2087da74d4a7, + 0x2da2596696cebc1d, + 0x0e2b7eedbbfd87d2, }), }); diff --git a/src/bls12-381/src/g.cpp b/src/bls12-381/src/g.cpp index bc4fee45623..bc243dbfab8 100644 --- a/src/bls12-381/src/g.cpp +++ b/src/bls12-381/src/g.cpp @@ -227,19 +227,6 @@ void g1::toCompressedBytesBE(const tcb::span out) const out[0] |= 0x80; } -void g1::toCompressedMCLBytesLE(const tcb::span out) const -{ - // check: https://github.com/zcash/librustzcash/blob/6e0364cd42a2b3d2b958a54771ef51a8db79dd29/pairing/src/bls12_381/README.md#serialization - g1 p = affine(); - memcpy(out.data(), p.x.toBytesLE().data(), 48); - // checks if y component is odd - if((p.y.fromMont().d[0] & 1) == 1) - { - // set top bit of most significanty byte if y is odd - out[47] |= 0x80; - } -} - array g1::toJacobianBytesBE(const from_mont fm /* = from_mont::yes */) const { array out; @@ -275,12 +262,6 @@ array g1::toCompressedBytesBE() const return out; } -array g1::toCompressedMCLBytesLE() const -{ - array out; - toCompressedMCLBytesLE(out); - return out; -} g1 g1::zero() { @@ -526,7 +507,7 @@ g1 g1::weightedSum(tcb::span points, tcb::span= 32) { - c = (std::numeric_limits::digits - qcountl_zero(effective_size))/3 + 2; + c = (sizeof(size_t) * 8 - qcountl_zero(effective_size))/3 + 2; } uint64_t bucketSize = (1< out) const out[0] |= 0x80; } -void g2::toCompressedMCLBytesLE(const tcb::span out) const -{ - // check: https://github.com/zcash/librustzcash/blob/6e0364cd42a2b3d2b958a54771ef51a8db79dd29/pairing/src/bls12_381/README.md#serialization - g2 p = affine(); - memcpy(out.data(), p.x.c0.toBytesLE().data(), 48); - memcpy(out.data() + 48, p.x.c1.toBytesLE().data(), 48); - - // check if p.y.c0 is odd - if((p.y.c0.fromMont().d[0] & 1) == 1) - { - // if odd, set the top bit of the last byte (most significant byte of p.x.c1) - out[95] |= 0x80; - } -} - array g2::toJacobianBytesBE(const from_mont fm /* = from_mont::yes */) const { array out; @@ -1053,13 +1019,6 @@ array g2::toCompressedBytesBE() const return out; } -array g2::toCompressedMCLBytesLE() const -{ - array out; - toCompressedMCLBytesLE(out); - return out; -} - g2 g2::zero() { return g2({ @@ -1349,7 +1308,7 @@ g2 g2::weightedSum(tcb::span points, tcb::span= 32) { - c = (std::numeric_limits::digits - qcountl_zero(effective_size))/3 + 2; + c = (sizeof(size_t) * 8 - qcountl_zero(effective_size))/3 + 2; } uint64_t bucketSize = (1< *v, size_t startIndex) - { - if (v->size() < (96 + startIndex)) - { - return false; - } - std::array s1; - std::copy(v->begin() + startIndex, v->begin() + startIndex + 96, s1.begin()); - auto g2Option = g2::fromCompressedMCLBytesLE(s1); - if (!g2Option.has_value()) - { - return false; - } - else - { - *out = g2Option.value(); - return true; - } - } - bool deserializeFpFromVector(bls12_381::fp *out, const std::vector *v, size_t startIndex) - { - if (v->size() < (48 + startIndex)) - { - return false; - } - tcb::span s(v->data() + startIndex, 48); - auto fpOption = fp::fromBytesLE(s); - if (!fpOption.has_value()) - { - return false; - } - else - { - *out = fpOption.value(); - return true; - } - } bool deserializeScalarFromVector(std::array &out, const std::vector *v, size_t startIndex) { if (v->size() < (32 + startIndex)) @@ -216,11 +179,6 @@ namespace bls12_381_groth16 precomputed->gammaNeg = vk->gamma.negate(); return 1; } - fp12 computeMillerLoopSingle(g1 a, g2 b) { - std::vector> v; - pairing::add_pair(v, a, b); - return pairing::miller_loop(v, std::function()); - } int verifyProofWith2PublicInputs( const Groth16ProofWith2PublicInputs *proof, const Groth16VerifierKeyInput *vk, @@ -242,20 +200,7 @@ namespace bls12_381_groth16 pairing::add_pair(v, proof->pi_1, proof->pi_2); pairing::add_pair(v, sumKTimesPub, precomputed->gammaNeg); pairing::add_pair(v, proof->pi_3, precomputed->deltaNeg); -/* - // compute e([π₁]₁, [π₂]₂) - fp12 ePi1Pi2 = computeMillerLoopSingle(proof->pi_1, proof->pi_2); - - // compute e( [Σᵥ (Kᵥ₊₁ * publicInputs[v])]₁, -[γ]₂ ) - fp12 eSumKTimesPubGammaNeg = computeMillerLoopSingle(sumKTimesPub, precomputed->gammaNeg); - // compute e([π₃]₁, -[δ]₂) - fp12 ePi3DeltaNeg = computeMillerLoopSingle(proof->pi_3, precomputed->deltaNeg); - - // compute z = e(α, β) * e( [Σᵥ (Kᵥ₊₁ * publicInputs[v])]₁, -[γ]₂ ) * e([π₃]1, -[δ]₂) - fp12 z = ePi1Pi2.multiply(eSumKTimesPubGammaNeg).multiply(ePi3DeltaNeg); - - */ fp12 z = pairing::miller_loop(v, std::function()); pairing::final_exponentiation(z); if(z.equal(precomputed->eAlphaBeta)){ @@ -264,5 +209,5 @@ namespace bls12_381_groth16 return 0; } } - + } \ No newline at end of file diff --git a/src/bls12-381/src/pairing.cpp b/src/bls12-381/src/pairing.cpp index a4e7379ab01..15b8ae8c63c 100644 --- a/src/bls12-381/src/pairing.cpp +++ b/src/bls12-381/src/pairing.cpp @@ -99,7 +99,7 @@ fp12 miller_loop(tcb::span> pairs, std::function(pairs[i])); + pre_compute(ellCoeffs[i], get<1>(pairs[i])); } if(pairs.size() >= 20 && yield) { @@ -116,8 +116,8 @@ fp12 miller_loop(tcb::span> pairs, std::function(pairs[j]).y); - t[1] = ellCoeffs[j][k][1].mulByFq(get(pairs[j]).x); + t[0] = ellCoeffs[j][k][2].mulByFq(get<0>(pairs[j]).y); + t[1] = ellCoeffs[j][k][1].mulByFq(get<0>(pairs[j]).x); f.mulBy014Assign(ellCoeffs[j][k][0], t[1], t[0]); } if(((g2::cofactorEFF[0] >> i) & 1) == 1) @@ -125,8 +125,8 @@ fp12 miller_loop(tcb::span> pairs, std::function(pairs[j]).y); - t[1] = ellCoeffs[j][k][1].mulByFq(get(pairs[j]).x); + t[0] = ellCoeffs[j][k][2].mulByFq(get<0>(pairs[j]).y); + t[1] = ellCoeffs[j][k][1].mulByFq(get<0>(pairs[j]).x); f.mulBy014Assign(ellCoeffs[j][k][0], t[1], t[0]); } } diff --git a/src/bls12-381/src/scalar.cpp b/src/bls12-381/src/scalar.cpp index 18b9ccca5f3..cd98f1462d0 100644 --- a/src/bls12-381/src/scalar.cpp +++ b/src/bls12-381/src/scalar.cpp @@ -4,47 +4,6 @@ using namespace std; namespace bls12_381 { - -vector hexToBytes(std::string s) -{ - uint64_t start_idx = 0; - if(s[0] == '0' && s[1] == 'x') - { - start_idx = 2; - } - - if(s.length() % 2 != 0) - { - // string length invalid! - return {}; - } - - vector bytes; - uint64_t num_bytes = (s.length() - start_idx) / 2; - bytes.reserve(num_bytes); - for(size_t i = 0, j = start_idx; i < num_bytes; i++, j += 2) - { - bytes.push_back((s[j] % 32 + 9) % 25 * 16 + (s[j+1] % 32 + 9) % 25); - } - - return bytes; -} - -string bytesToHex(tcb::span in) -{ - constexpr char hexmap[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; - string s(2 + in.size() * 2, ' '); - s[0] = '0'; - s[1] = 'x'; - for(uint64_t i = 0; i < in.size(); ++i) - { - s[2 + 2*i] = hexmap[(in[i] & 0xF0) >> 4]; - s[2 + 2*i+1] = hexmap[ in[i] & 0x0F ]; - } - return s; -} - - // HELPER FUNCTIONS // for p mod q calculations #define RLC_MASK(B) ((-(uint64_t)((B) >= 64)) | (((uint64_t)1 << ((B) % 64)) - 1)) @@ -146,7 +105,12 @@ uint64_t bn_mul1_low(uint64_t *c, const uint64_t *a, uint64_t digit, int size) uint64_t r0, r1, carry = 0; for(int i = 0; i < size; i++, a++, c++) { + #if defined(USE_INT128) r1 = (static_cast<__uint128_t>(*a) * static_cast<__uint128_t>(digit)) >> (64); + #else + uint64_t rlow = 0;; + tie(r1, rlow) = Mul64(*a, digit); + #endif r0 = (*a) * (digit); *c = r0 + carry; carry = r1 + (*c < carry); @@ -293,7 +257,36 @@ void bn_divn_low(uint64_t *c, uint64_t *d, uint64_t *a, int sa, uint64_t *b, int } else { + #if defined(USE_INT128) c[i - t - 1] = (((__uint128_t)(a[i]) << (64)) | (a[i - 1])) / (b[t]); + #else + uint64_t a1 = a[i]; + uint64_t a0 = a[i - 1]; + uint64_t bt = b[t]; + uint64_t res_q = 0; + uint64_t uint64_max = UINT64_MAX; + uint64_t u64_quotient = uint64_max / bt; + uint64_t u64_remainder = uint64_max % bt + 1; + + while (a1 != 0 || a0 > bt) + { + uint64_t a1_quotient = a1 / bt; + uint64_t a1_remainder = a1 % bt; + uint64_t a0_quotient = a0 / bt; + uint64_t a0_remainder = a0 % bt; + + // (a1_quotient * b + a1_remainder) * (u64_quotient * b + u64_remainder) = (a1_quotient * b * u64_quotient + a1_remainder * u64_quotient + a1_quotient * u64_remainder) * b + (a1_remainder * u64_remainder) + res_q += (a1_quotient * bt * u64_quotient + a1_remainder * u64_quotient + a1_quotient * u64_remainder) + a0_quotient; + tie(a1, a0) = Mul64(a1_remainder, u64_remainder); + a0 += a0_remainder; + if (a0 < a0_remainder) + { + a1++; + } + } + c[i - t - 1] = res_q; + + #endif } c[i - t - 1]++; diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index 67c99c71ff6..203e02356de 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -255,6 +255,7 @@ bool EvalScript(vector >& stack, const CScript& script, un static const valtype vchFalse(0); static const valtype vchZero(0); static const valtype vchTrue(1, 1); + bool zkpOpIsUsed = false; CScript::const_iterator pc = script.begin(); CScript::const_iterator pend = script.end(); @@ -1025,8 +1026,16 @@ bool EvalScript(vector >& stack, const CScript& script, un } } break; - case OP_CHECKGROTH16VERIFY: + case OP_CHECKZKPVERIFY: { + if (zkpOpIsUsed) + { + return set_error(serror, SCRIPT_ERR_BAD_OPCODE); + }else + { + zkpOpIsUsed = true; + } + // Ensure stack has enough elements for the groth16 proof verification if (stack.size() < 12) return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION); @@ -1043,8 +1052,8 @@ bool EvalScript(vector >& stack, const CScript& script, un return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION); } - // Only modes 0 and 1 are implemented; others return an error - if(mode.getint() != 1 && mode.getint() != 0){ + // Only modes 1 is implemented; Mode 0 is deprecated; others return an error + if(mode.getint() != 1){ // TODO: Implement mode 2 and 3 return set_error(serror, SCRIPT_ERR_SIG_DER); } @@ -1056,12 +1065,6 @@ bool EvalScript(vector >& stack, const CScript& script, un valtype& verfierDataB = stacktop(-6); valtype& verfierDataA = stacktop(-7); - /* TODO: drop the proof? - // Drop the signature in pre-segwit scripts but not segwit scripts - if (sigversion == SIGVERSION_BASE) { - scriptCode.FindAndDelete(CScript(vchSig)); - } - */ valtype publicInput1(32); // Initialize a 32-byte array for tx_hash if(mode.getint()==1){ CScript scriptCode(pbegincodehash, pend); @@ -1085,21 +1088,26 @@ bool EvalScript(vector >& stack, const CScript& script, un // Deserialize the proof and verifier key input bls12_381_groth16::Groth16ProofWith2PublicInputs proof; - bls12_381_groth16::Groth16VerifierKeyInput vk; - bls12_381_groth16::Groth16VerifierKeyPrecomputedValues precomputed; + static bls12_381_groth16::Groth16VerifierKeyInput vk; + static bls12_381_groth16::Groth16VerifierKeyPrecomputedValues precomputed; + static valtype verfierDataACopy; // Check the proof and verifier key deserialization if(!bls12_381_groth16::deserializeProofWith2PublicInputs(&proof, &piA, &piB0, &piB1, &piC, &public_input_0, &public_input_1)){ return set_error(serror, SCRIPT_ERR_CHECKMULTISIGVERIFY); } - if(!bls12_381_groth16::deserializeVerifierKeyInput(&vk, &verfierDataA, &verfierDataB, &verfierDataC, &verfierDataD, &verfierDataE, &verfierDataF)){ - return set_error(serror, SCRIPT_ERR_CHECKMULTISIGVERIFY); - } + if (verfierDataA.size() != verfierDataACopy.size() || !std::equal(verfierDataA.begin(), verfierDataA.end(), verfierDataACopy.begin())) + { + verfierDataACopy = verfierDataA; + if(!bls12_381_groth16::deserializeVerifierKeyInput(&vk, &verfierDataA, &verfierDataB, &verfierDataC, &verfierDataD, &verfierDataE, &verfierDataF)){ + return set_error(serror, SCRIPT_ERR_CHECKMULTISIGVERIFY); + } - // Precompute the verifier key - if(!bls12_381_groth16::precomputeVerifierKey(&precomputed, &vk)){ - return set_error(serror, SCRIPT_ERR_CHECKMULTISIGVERIFY); + // Precompute the verifier key + if(!bls12_381_groth16::precomputeVerifierKey(&precomputed, &vk)){ + return set_error(serror, SCRIPT_ERR_CHECKMULTISIGVERIFY); + } } // Verify the proof diff --git a/src/script/script.cpp b/src/script/script.cpp index 817b46fda9f..76974510329 100644 --- a/src/script/script.cpp +++ b/src/script/script.cpp @@ -133,7 +133,7 @@ const char* GetOpName(opcodetype opcode) case OP_NOP1 : return "OP_NOP1"; case OP_CHECKLOCKTIMEVERIFY : return "OP_CHECKLOCKTIMEVERIFY"; case OP_CHECKSEQUENCEVERIFY : return "OP_CHECKSEQUENCEVERIFY"; - case OP_CHECKGROTH16VERIFY : return "OP_CHECKGROTH16VERIFY"; + case OP_CHECKZKPVERIFY : return "OP_CHECKZKPVERIFY"; case OP_NOP5 : return "OP_NOP5"; case OP_NOP6 : return "OP_NOP6"; case OP_NOP7 : return "OP_NOP7"; diff --git a/src/script/script.h b/src/script/script.h index c43907e6327..d75012e5b2b 100644 --- a/src/script/script.h +++ b/src/script/script.h @@ -169,7 +169,7 @@ enum opcodetype OP_NOP2 = OP_CHECKLOCKTIMEVERIFY, OP_CHECKSEQUENCEVERIFY = 0xb2, OP_NOP3 = OP_CHECKSEQUENCEVERIFY, - OP_CHECKGROTH16VERIFY = 0xb3, + OP_CHECKZKPVERIFY = 0xb3, OP_NOP5 = 0xb4, OP_NOP6 = 0xb5, OP_NOP7 = 0xb6, diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp index 4f7a84ad348..4d40e3166a1 100644 --- a/src/test/script_tests.cpp +++ b/src/test/script_tests.cpp @@ -1085,6 +1085,27 @@ BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG12) BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err)); } +BOOST_AUTO_TEST_CASE(script_CHECKZKPVERIFY) +{ + const int flags = SCRIPT_VERIFY_P2SH; + + CMutableTransaction txCredit; + DecodeHexTx(txCredit, "0200000001d5258a4fd597edc59d3a9166557c078f05bb992c926d90a0f18c75302d93f99000000000fd0203307f4e6a794e3317a1a2f06a8163ebd70a4a714a5f712d4259a9387d6589615bf63e95bb9233b844f47f5e2a0a312cb300308ddb1235bf6f33189982611ce46edbf62762cf1bda4e245c28c9622452e579078384c4a7c83b00b9b5cb96eaca9abe1130a882ef4edc6a154f1f62d53bf8bf55daeabdf528bbdc9fc7935f37449bafd302aaf19156548ba8b28d29a278ea92f094302882cbef8b8e4f89687f9e8eedc70e8400b0293c05e41c29252683855ecab667100996bda1d61091ccec5c61db9508814c50b9d96fecdd99ff136355dc90772a2ef7788afe1f8a332b34e8a30402477f8e38e874eba3946f6f4ba8c794a09d266507dd66ecb824f911036f2b6bf63ee7a5feb52105bdf466dac06ca427711d5b52c24de90120caec89bedcab3ce707981a6fa86d27b87b2c0a732feee3717aaddd6728877c007c76a82081c202329a17f5756142a72734f6832f7784e22b1e17260901039f504f9098a3884c5090c10d96e70d136fac9a3634428f3792e9b8d02eb903783f71fc8e6937f7f8b1360c8bee9146041a79251614eee9689073af20af273a280e841b078837e65a862279849c1251e1761bb6ac35f2649ea34c50fe63d02ab4af4ab3448fe5e8d4fff135d510a38558c9daee4ae190303c18368ce2ba9fd21e8d1ab0f617a9d249621b56f224b69f6c3a3e008a40b3aea5a5ab77eed73711e93c896023475b27e3a4f6124c50189647ab2c8de2fc37ef189f803704cc55087bfe1c56dcabbb2f343dc145a0470d18317696e1023a7574e8745e0ea301cc6cd679a61133a1c560d5aa3d38d91a999a8f666109495402c553bd7c82056b4c50bf358e5097046487c370c1dd6781dc11d6518717e23b334d4b09892a9763f09059687a7c136f6189568edd6d6f357c1c199a39fa0f723d2218762766f67fa8171b10e8b7e5dd88155651d37ca6b59c754c50092d3dfea8804a69cab1f76133032b85ee7e850977dd1fe578f3d9663bb43a08502a8fd7cb8c7f79c39fbe49f9cee082bf68dfd65e70ccdbfb4c6f834d5dcb3e4619bc44de9ca8aca12b502e74b7b50451b36d6d6d6d6d6d51ffffffff0100113d550200000017a914fda635e6bc2ef7efa82521342c1e3ab932153c628700000000"); + CMutableTransaction txSpend; + DecodeHexTx(txSpend, "0200000002952da86dd9c8e4f2587be7adfa9ebe531cc05a8e733f7bd6c02c7ac9f03503b300000000fd020330a1cf4fd86ec455bbe8b983c0dd64abe78ef065724960fecce845873a9df15e10e16c60e948fddd722bd68ed469cca20e30a9cb9215f93c6d926a22367fab2e95d54560a06412ca51304da82d2ee75521a6f58996298c14fe566795d2f654efda0130f23b6a58474bfc3e89499bce8bf7b280b2d84707ffa7f86bc9c94a8174b99f7df7be7e531e8ea759f60abdb4864ad7023016e9e0aa1e58d75831dd90aef95657a5a5e96e9196e6a02f6cb8c6371d311d5654dda6dfd522626f4c90aa0861b067024c50b9d96fecdd99ff136355dc90772a2ef7788afe1f8a332b34e8a30402477f8e38e874eba3946f6f4ba8c794a09d266507dd66ecb824f911036f2b6bf63ee7a5feb52105bdf466dac06ca427711d5b52c24de9012000f3a40258113d7544ec3a1c548047ab9a14e5488320414a311d8de59b7414007c76a82081c202329a17f5756142a72734f6832f7784e22b1e17260901039f504f9098a3884c5090c10d96e70d136fac9a3634428f3792e9b8d02eb903783f71fc8e6937f7f8b1360c8bee9146041a79251614eee9689073af20af273a280e841b078837e65a862279849c1251e1761bb6ac35f2649ea34c50fe63d02ab4af4ab3448fe5e8d4fff135d510a38558c9daee4ae190303c18368ce2ba9fd21e8d1ab0f617a9d249621b56f224b69f6c3a3e008a40b3aea5a5ab77eed73711e93c896023475b27e3a4f6124c50189647ab2c8de2fc37ef189f803704cc55087bfe1c56dcabbb2f343dc145a0470d18317696e1023a7574e8745e0ea301cc6cd679a61133a1c560d5aa3d38d91a999a8f666109495402c553bd7c82056b4c50bf358e5097046487c370c1dd6781dc11d6518717e23b334d4b09892a9763f09059687a7c136f6189568edd6d6f357c1c199a39fa0f723d2218762766f67fa8171b10e8b7e5dd88155651d37ca6b59c754c50092d3dfea8804a69cab1f76133032b85ee7e850977dd1fe578f3d9663bb43a08502a8fd7cb8c7f79c39fbe49f9cee082bf68dfd65e70ccdbfb4c6f834d5dcb3e4619bc44de9ca8aca12b502e74b7b50451b36d6d6d6d6d6d51ffffffffa75fe7d127ffba6a51a6aa750aec49d6861b7e3cc809f259cfcf3d95c71574b900000000fd02033091d0f9aff7bd3da433eb5706a7914bc49d19ea781a9b8eee183929cdfc7a79773a244992d5afd3e9ddc61d70f73b0194300739ce49ac859b19f03d3c0c2bbb7ffb24e64c32e4e632fe74e3a53f5e5aa10ee3551061b3818aa3e126d960cb593f163035c36460f49449043c7892acebd0518122551501a7abd5a00df0962ce1f6977399a5ef4762c0d80ceec2c9833891c617301120658e06a7ede8415aded94c242e8a6d661732a1b8826114814421aff13fec59f847961ae3181b7a533d40f4aa3a924c50b9d96fecdd99ff136355dc90772a2ef7788afe1f8a332b34e8a30402477f8e38e874eba3946f6f4ba8c794a09d266507dd66ecb824f911036f2b6bf63ee7a5feb52105bdf466dac06ca427711d5b52c24de9012000f3a40258113d7544ec3a1c548047ab9a14e5488320414a311d8de59b7414007c76a82081c202329a17f5756142a72734f6832f7784e22b1e17260901039f504f9098a3884c5090c10d96e70d136fac9a3634428f3792e9b8d02eb903783f71fc8e6937f7f8b1360c8bee9146041a79251614eee9689073af20af273a280e841b078837e65a862279849c1251e1761bb6ac35f2649ea34c50fe63d02ab4af4ab3448fe5e8d4fff135d510a38558c9daee4ae190303c18368ce2ba9fd21e8d1ab0f617a9d249621b56f224b69f6c3a3e008a40b3aea5a5ab77eed73711e93c896023475b27e3a4f6124c50189647ab2c8de2fc37ef189f803704cc55087bfe1c56dcabbb2f343dc145a0470d18317696e1023a7574e8745e0ea301cc6cd679a61133a1c560d5aa3d38d91a999a8f666109495402c553bd7c82056b4c50bf358e5097046487c370c1dd6781dc11d6518717e23b334d4b09892a9763f09059687a7c136f6189568edd6d6f357c1c199a39fa0f723d2218762766f67fa8171b10e8b7e5dd88155651d37ca6b59c754c50092d3dfea8804a69cab1f76133032b85ee7e850977dd1fe578f3d9663bb43a08502a8fd7cb8c7f79c39fbe49f9cee082bf68dfd65e70ccdbfb4c6f834d5dcb3e4619bc44de9ca8aca12b502e74b7b50451b36d6d6d6d6d6d51ffffffff01003e6e560200000017a9149faff0ec8c48761a48a8023ed8fd7b8af103c0888700000000"); + + ScriptError err; + bool success = VerifyScript(txSpend.vin[0].scriptSig, + txCredit.vout[0].scriptPubKey, + &txSpend.vin[0].scriptWitness, + flags, + MutableTransactionSignatureChecker(&txSpend, 0, txCredit.vout[0].nValue), + &err); + + BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); + BOOST_CHECK(success); +} + BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG23) { ScriptError err;