diff --git a/configure.ac b/configure.ac index ce2c51429b..8248ba244f 100644 --- a/configure.ac +++ b/configure.ac @@ -1,1363 +1,1407 @@ dnl require autoconf 2.60 (AS_ECHO/AS_ECHO_N) AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 0) define(_CLIENT_VERSION_MINOR, 18) define(_CLIENT_VERSION_REVISION, 3) define(_CLIENT_VERSION_BUILD, 0) define(_CLIENT_VERSION_IS_RELEASE, true) define(_COPYRIGHT_YEAR, 2018) define(_COPYRIGHT_HOLDERS,[The %s developers]) define(_COPYRIGHT_HOLDERS_SUBSTITUTION,[[Bitcoin]]) AC_INIT([Bitcoin ABC],[_CLIENT_VERSION_MAJOR._CLIENT_VERSION_MINOR._CLIENT_VERSION_REVISION],[https://github.com/Bitcoin-ABC/bitcoin-abc/issues],[bitcoin-abc],[https://bitcoinabc.org/]) AC_CONFIG_SRCDIR([src/validation.cpp]) AC_CONFIG_HEADERS([src/config/bitcoin-config.h]) AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_MACRO_DIR([build-aux/m4]) BITCOIN_DAEMON_NAME=bitcoind BITCOIN_GUI_NAME=bitcoin-qt BITCOIN_CLI_NAME=bitcoin-cli BITCOIN_TX_NAME=bitcoin-tx BITCOIN_SEEDER_NAME=bitcoin-seeder AC_CANONICAL_HOST AH_TOP([#ifndef BITCOIN_BITCOIN_CONFIG_H]) AH_TOP([#define BITCOIN_BITCOIN_CONFIG_H]) AH_BOTTOM([#endif // BITCOIN_BITCOIN_CONFIG_H]) dnl faketime breaks configure and is only needed for make. Disable it here. unset FAKETIME dnl Automake init set-up and checks AM_INIT_AUTOMAKE([no-define subdir-objects foreign]) dnl faketime messes with timestamps and causes configure to be re-run. dnl --disable-maintainer-mode can be used to bypass this. AM_MAINTAINER_MODE([enable]) dnl make the compilation flags quiet unless V=1 is used m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) dnl Compiler checks (here before libtool). if test "x${CXXFLAGS+set}" = "xset"; then CXXFLAGS_overridden=yes else CXXFLAGS_overridden=no fi AC_PROG_CXX dnl By default, libtool for mingw refuses to link static libs into a dll for dnl fear of mixing pic/non-pic objects, and import/export complications. Since dnl we have those under control, re-enable that functionality. case $host in *mingw*) lt_cv_deplibs_check_method="pass_all" ;; esac dnl Require C++11 compiler (no GNU extensions) AX_CXX_COMPILE_STDCXX([11], [noext], [mandatory], [nodefault]) dnl Check if -latomic is required for CHECK_ATOMIC dnl Unless the user specified OBJCXX, force it to be the same as CXX. This ensures dnl that we get the same -std flags for both. m4_ifdef([AC_PROG_OBJCXX],[ if test "x${OBJCXX+set}" = "x"; then OBJCXX="${CXX}" fi AC_PROG_OBJCXX ]) dnl Libtool init checks. LT_INIT([pic-only]) dnl Check/return PATH for base programs. AC_PATH_TOOL(AR, ar) AC_PATH_TOOL(RANLIB, ranlib) AC_PATH_TOOL(STRIP, strip) AC_PATH_TOOL(GCOV, gcov) AC_PATH_PROG(LCOV, lcov) dnl Python 3.x is supported from 3.4 on (see https://github.com/bitcoin/bitcoin/issues/7893) AC_PATH_PROGS([PYTHON], [python3.6 python3.5 python3.4 python3 python2.7 python2 python]) AC_PATH_PROG(GENHTML, genhtml) AC_PATH_PROG([GIT], [git]) AC_PATH_PROG(CCACHE,ccache) AC_PATH_PROG(XGETTEXT,xgettext) AC_PATH_PROG(HEXDUMP,hexdump) AC_PATH_TOOL(READELF, readelf) AC_PATH_TOOL(CPPFILT, c++filt) AC_PATH_TOOL(OBJCOPY, objcopy) AC_ARG_VAR(PYTHONPATH, Augments the default search path for python module files) # Enable wallet AC_ARG_ENABLE([wallet], [AS_HELP_STRING([--disable-wallet], [disable wallet (enabled by default)])], [enable_wallet=$enableval], [enable_wallet=yes]) AC_ARG_WITH([miniupnpc], [AS_HELP_STRING([--with-miniupnpc], [enable UPNP (default is yes if libminiupnpc is found)])], [use_upnp=$withval], [use_upnp=auto]) AC_ARG_ENABLE([upnp-default], [AS_HELP_STRING([--enable-upnp-default], [if UPNP is enabled, turn it on at startup (default is no)])], [use_upnp_default=$enableval], [use_upnp_default=no]) AC_ARG_ENABLE(tests, AS_HELP_STRING([--disable-tests],[do not compile tests (default is to compile)]), [use_tests=$enableval], [use_tests=yes]) AC_ARG_ENABLE(gui-tests, AS_HELP_STRING([--disable-gui-tests],[do not compile GUI tests (default is to compile if GUI and tests enabled)]), [use_gui_tests=$enableval], [use_gui_tests=$use_tests]) AC_ARG_ENABLE(bench, AS_HELP_STRING([--disable-bench],[do not compile benchmarks (default is to compile)]), [use_bench=$enableval], [use_bench=yes]) AC_ARG_ENABLE([extended-functional-tests], AS_HELP_STRING([--enable-extended-functional-tests],[enable expensive functional tests when using lcov (default no)]), [use_extended_functional_tests=$enableval], [use_extended_functional_tests=no]) AC_ARG_WITH([qrencode], [AS_HELP_STRING([--with-qrencode], [enable QR code support (default is yes if qt is enabled and libqrencode is found)])], [use_qr=$withval], [use_qr=auto]) AC_ARG_ENABLE([hardening], [AS_HELP_STRING([--disable-hardening], [do not attempt to harden the resulting executables (default is to harden)])], [use_hardening=$enableval], [use_hardening=yes]) AC_ARG_ENABLE([reduce-exports], [AS_HELP_STRING([--enable-reduce-exports], [attempt to reduce exported symbols in the resulting executables (default is no)])], [use_reduce_exports=$enableval], [use_reduce_exports=no]) AC_ARG_ENABLE([ccache], [AS_HELP_STRING([--disable-ccache], [do not use ccache for building (default is to use if found)])], [use_ccache=$enableval], [use_ccache=auto]) AC_ARG_ENABLE([lcov], [AS_HELP_STRING([--enable-lcov], [enable lcov testing (default is no)])], [use_lcov=yes], [use_lcov=no]) AC_ARG_ENABLE([glibc-back-compat], [AS_HELP_STRING([--enable-glibc-back-compat], [enable backwards compatibility with glibc])], [use_glibc_compat=$enableval], [use_glibc_compat=no]) AC_ARG_ENABLE([asm], [AS_HELP_STRING([--enable-asm], [Enable assembly routines (default is yes)])], [use_asm=$enableval], [use_asm=yes]) if test "x$use_asm" = xyes; then AC_DEFINE(USE_ASM, 1, [Define this symbol to build in assembly routines]) fi AC_ARG_WITH([system-univalue], [AS_HELP_STRING([--with-system-univalue], [Build with system UniValue (default is no)])], [system_univalue=$withval], [system_univalue=no] ) AC_ARG_ENABLE([zmq], [AS_HELP_STRING([--disable-zmq], [disable ZMQ notifications])], [use_zmq=$enableval], [use_zmq=yes]) AC_ARG_WITH([protoc-bindir],[AS_HELP_STRING([--with-protoc-bindir=BIN_DIR],[specify protoc bin path])], [protoc_bin_path=$withval], []) AC_ARG_ENABLE(man, [AS_HELP_STRING([--disable-man], [do not install man pages (default is to install)])],, enable_man=yes) AM_CONDITIONAL(ENABLE_MAN, test "$enable_man" != no) # Enable debug AC_ARG_ENABLE([debug], [AS_HELP_STRING([--enable-debug], [use debug compiler flags and macros (default is no)])], [enable_debug=$enableval], [enable_debug=no]) # Enable ASAN AC_ARG_ENABLE([asan], [AS_HELP_STRING([--enable-asan], [enable address sanitizer compiler flags (implies --enable-debug, default is no)])], [enable_asan=$enableval], [enable_asan=no]) # Enable TSAN AC_ARG_ENABLE([tsan], [AS_HELP_STRING([--enable-tsan], [enable thread sanitizer compiler flags; requires 64-bit target architecture (implies --enable-debug, default is no)])], [enable_tsan=$enableval], [enable_tsan=no]) # Enable UBSAN AC_ARG_ENABLE([ubsan], [AS_HELP_STRING([--enable-ubsan], [enable undefined behavior sanitizer compiler flags (implies --enable-debug, default is no)])], [enable_ubsan=$enableval], [enable_ubsan=no]) # Turn warnings into errors AC_ARG_ENABLE([werror], [AS_HELP_STRING([--enable-werror], [Treat certain compiler warnings as errors (default is no)])], [enable_werror=$enableval], [enable_werror=no]) AC_LANG_PUSH([C++]) AX_CHECK_COMPILE_FLAG([-Werror],[CXXFLAG_WERROR="-Werror"],[CXXFLAG_WERROR=""]) if test "x$enable_asan" = xyes; then enable_debug=yes asan_failed=no AX_CHECK_COMPILE_FLAG([-fsanitize=address], [CXXFLAGS="$CXXFLAGS -fsanitize=address"], [asan_failed=yes]) AX_CHECK_LINK_FLAG([-fsanitize=address], [LDFLAGS="$LDFLAGS -fsanitize=address"], [asan_failed=yes]) AX_CHECK_COMPILE_FLAG([-fno-omit-frame-pointer], [CXXFLAGS="$CXXFLAGS -fno-omit-frame-pointer"], [asan_failed=yes]) if test "x$asan_failed" = xyes; then AC_MSG_ERROR("ASAN is not supported") fi # fix linkage in MacOs [LIBTOOL_APP_LDFLAGS="$LIBTOOL_APP_LDFLAGS -fsanitize=address"], fi if test "x$enable_tsan" = xyes; then enable_debug=yes tsan_failed=no AX_CHECK_COMPILE_FLAG([-fsanitize=thread], [CXXFLAGS="$CXXFLAGS -fsanitize=thread"], [tsan_failed=yes]) AX_CHECK_LINK_FLAG([-fsanitize=thread], [LDFLAGS="$LDFLAGS -fsanitize=thread"], [tsan_failed=yes]) AX_CHECK_COMPILE_FLAG([-fno-omit-frame-pointer], [CXXFLAGS="$CXXFLAGS -fno-omit-frame-pointer"], [tsan_failed=yes]) if test "x$tsan_failed" = xyes; then AC_MSG_ERROR("TSAN is not supported") fi fi if test "x$enable_ubsan" = xyes; then enable_debug=yes ubsan_failed=no AX_CHECK_COMPILE_FLAG([-fsanitize=undefined], [CXXFLAGS="$CXXFLAGS -fsanitize=undefined"], [ubsan_failed=yes]) AX_CHECK_LINK_FLAG([-fsanitize=undefined], [LDFLAGS="$LDFLAGS -fsanitize=undefined"], [ubsan_failed=yes]) AX_CHECK_COMPILE_FLAG([-fno-omit-frame-pointer], [CXXFLAGS="$CXXFLAGS -fno-omit-frame-pointer"], [ubsan_failed=yes]) if test "x$ubsan_failed" = xyes; then AC_MSG_ERROR("UBSAN is not supported") fi fi if test "x$enable_debug" = xyes; then CPPFLAGS="$CPPFLAGS -DDEBUG -DDEBUG_LOCKORDER" if test "x$GCC" = xyes; then CFLAGS="$CFLAGS -g3 -O0" fi if test "x$GXX" = xyes; then CXXFLAGS="$CXXFLAGS -g3 -O0" fi fi ERROR_CXXFLAGS= if test "x$enable_werror" = "xyes"; then if test "x$CXXFLAG_WERROR" = "x"; then AC_MSG_ERROR("enable-werror set but -Werror is not usable") fi AX_CHECK_COMPILE_FLAG([-Werror=vla],[ERROR_CXXFLAGS="$ERROR_CXXFLAGS -Werror=vla"],,[[$CXXFLAG_WERROR]]) fi if test "x$CXXFLAGS_overridden" = "xno"; then AX_CHECK_COMPILE_FLAG([-Wall],[CXXFLAGS="$CXXFLAGS -Wall"],,[[$CXXFLAG_WERROR]]) AX_CHECK_COMPILE_FLAG([-Wextra],[CXXFLAGS="$CXXFLAGS -Wextra"],,[[$CXXFLAG_WERROR]]) AX_CHECK_COMPILE_FLAG([-Wformat],[CXXFLAGS="$CXXFLAGS -Wformat"],,[[$CXXFLAG_WERROR]]) AX_CHECK_COMPILE_FLAG([-Wvla],[CXXFLAGS="$CXXFLAGS -Wvla"],,[[$CXXFLAG_WERROR]]) AX_CHECK_COMPILE_FLAG([-Wformat-security],[CXXFLAGS="$CXXFLAGS -Wformat-security"],,[[$CXXFLAG_WERROR]]) AX_CHECK_COMPILE_FLAG([-Wshadow],[CXXFLAGS="$CXXFLAGS -Wshadow"],,[[$CXXFLAG_WERROR]]) ## Some compilers (gcc) ignore unknown -Wno-* options, but warn about all ## unknown options if any other warning is produced. Test the -Wfoo case, and ## set the -Wno-foo case if it works. AX_CHECK_COMPILE_FLAG([-Wunused-parameter],[CXXFLAGS="$CXXFLAGS -Wno-unused-parameter"],,[[$CXXFLAG_WERROR]]) fi # Check for optional instruction set support. Enabling these does _not_ imply that all code will # be compiled with them, rather that specific objects/libs may use them after checking for runtime # compatibility. AX_CHECK_COMPILE_FLAG([-msse4.2],[[SSE42_CXXFLAGS="-msse4.2"]],,[[$CXXFLAG_WERROR]]) +AX_CHECK_COMPILE_FLAG([-msse4.1],[[SSE41_CXXFLAGS="-msse4.1"]],,[[$CXXFLAG_WERROR]]) +AX_CHECK_COMPILE_FLAG([-mavx -mavx2],[[AVX2_CXXFLAGS="-mavx -mavx2"]],,[[$CXXFLAG_WERROR]]) TEMP_CXXFLAGS="$CXXFLAGS" CXXFLAGS="$CXXFLAGS $SSE42_CXXFLAGS" AC_MSG_CHECKING(for assembler crc32 support) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #if defined(_MSC_VER) #include #elif defined(__GNUC__) && defined(__SSE4_2__) #include #endif ]],[[ uint64_t l = 0; l = _mm_crc32_u8(l, 0); l = _mm_crc32_u32(l, 0); l = _mm_crc32_u64(l, 0); return l; ]])], [ AC_MSG_RESULT(yes); enable_hwcrc32=yes], [ AC_MSG_RESULT(no)] ) CXXFLAGS="$TEMP_CXXFLAGS" +TEMP_CXXFLAGS="$CXXFLAGS" +CXXFLAGS="$CXXFLAGS $SSE41_CXXFLAGS" +AC_MSG_CHECKING(for SSE4.1 intrinsics) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ + #include + #if defined(_MSC_VER) + #include + #elif defined(__GNUC__) + #include + #endif + ]],[[ + __m128i l = _mm_set1_epi32(0); + return _mm_extract_epi32(l, 3); + ]])], + [ AC_MSG_RESULT(yes); enable_sse41=yes; AC_DEFINE(ENABLE_SSE41, 1, [Define this symbol to build code that uses SSE4.1 intrinsics]) ], + [ AC_MSG_RESULT(no)] +) +CXXFLAGS="$TEMP_CXXFLAGS" + +TEMP_CXXFLAGS="$CXXFLAGS" +CXXFLAGS="$CXXFLAGS $AVX2_CXXFLAGS" +AC_MSG_CHECKING(for AVX2 intrinsics) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ + #include + #if defined(_MSC_VER) + #include + #elif defined(__GNUC__) && defined(__AVX2__) + #include + #endif + ]],[[ + __m256i l = _mm256_set1_epi32(0); + return _mm256_extract_epi32(l, 7); + ]])], + [ AC_MSG_RESULT(yes); enable_avx2=yes; AC_DEFINE(ENABLE_AVX2, 1, [Define this symbol to build code that uses AVX2 intrinsics]) ], + [ AC_MSG_RESULT(no)] +) +CXXFLAGS="$TEMP_CXXFLAGS" + CPPFLAGS="$CPPFLAGS -DHAVE_BUILD_INFO -D__STDC_FORMAT_MACROS" AC_ARG_WITH([utils], [AS_HELP_STRING([--with-utils], [build bitcoin-cli bitcoin-tx (default=yes)])], [build_bitcoin_utils=$withval], [build_bitcoin_utils=yes]) AC_ARG_WITH([libs], [AS_HELP_STRING([--with-libs], [build libraries (default=yes)])], [build_bitcoin_libs=$withval], [build_bitcoin_libs=yes]) AC_ARG_WITH([daemon], [AS_HELP_STRING([--with-daemon], [build bitcoind daemon (default=yes)])], [build_bitcoind=$withval], [build_bitcoind=yes]) AC_ARG_WITH([seeder], [AS_HELP_STRING([--with-seeder], [build seeder (default=yes)])], [build_bitcoin_seeder=$withval], [build_bitcoin_seeder=yes]) use_pkgconfig=yes case $host in *mingw*) #pkgconfig does more harm than good with MinGW use_pkgconfig=no TARGET_OS=windows AC_CHECK_LIB([mingwthrd], [main],, AC_MSG_ERROR(lib missing)) AC_CHECK_LIB([kernel32], [main],, AC_MSG_ERROR(lib missing)) AC_CHECK_LIB([user32], [main],, AC_MSG_ERROR(lib missing)) AC_CHECK_LIB([gdi32], [main],, AC_MSG_ERROR(lib missing)) AC_CHECK_LIB([comdlg32], [main],, AC_MSG_ERROR(lib missing)) AC_CHECK_LIB([winspool], [main],, AC_MSG_ERROR(lib missing)) AC_CHECK_LIB([winmm], [main],, AC_MSG_ERROR(lib missing)) AC_CHECK_LIB([shell32], [main],, AC_MSG_ERROR(lib missing)) AC_CHECK_LIB([comctl32], [main],, AC_MSG_ERROR(lib missing)) AC_CHECK_LIB([ole32], [main],, AC_MSG_ERROR(lib missing)) AC_CHECK_LIB([oleaut32], [main],, AC_MSG_ERROR(lib missing)) AC_CHECK_LIB([uuid], [main],, AC_MSG_ERROR(lib missing)) AC_CHECK_LIB([rpcrt4], [main],, AC_MSG_ERROR(lib missing)) AC_CHECK_LIB([advapi32], [main],, AC_MSG_ERROR(lib missing)) AC_CHECK_LIB([ws2_32], [main],, AC_MSG_ERROR(lib missing)) AC_CHECK_LIB([mswsock], [main],, AC_MSG_ERROR(lib missing)) AC_CHECK_LIB([shlwapi], [main],, AC_MSG_ERROR(lib missing)) AC_CHECK_LIB([iphlpapi], [main],, AC_MSG_ERROR(lib missing)) AC_CHECK_LIB([crypt32], [main],, AC_MSG_ERROR(lib missing)) # -static is interpreted by libtool, where it has a different meaning. # In libtool-speak, it's -all-static. AX_CHECK_LINK_FLAG([[-static]],[LIBTOOL_APP_LDFLAGS="$LIBTOOL_APP_LDFLAGS -all-static"]) AC_PATH_PROG([MAKENSIS], [makensis], none) if test x$MAKENSIS = xnone; then AC_MSG_WARN("makensis not found. Cannot create installer.") fi AC_PATH_TOOL(WINDRES, windres, none) if test x$WINDRES = xnone; then AC_MSG_ERROR("windres not found") fi CPPFLAGS="$CPPFLAGS -D_MT -DWIN32 -D_WINDOWS -DBOOST_THREAD_USE_LIB" LEVELDB_TARGET_FLAGS="-DOS_WINDOWS" if test "x$CXXFLAGS_overridden" = "xno"; then CXXFLAGS="$CXXFLAGS -w" fi case $host in i?86-*) WINDOWS_BITS=32 ;; x86_64-*) WINDOWS_BITS=64 ;; *) AC_MSG_ERROR("Could not determine win32/win64 for installer") ;; esac AC_SUBST(WINDOWS_BITS) dnl libtool insists upon adding -nostdlib and a list of objects/libs to link against. dnl That breaks our ability to build dll's with static libgcc/libstdc++/libssp. Override dnl its command here, with the predeps/postdeps removed, and -static inserted. Postdeps are dnl also overridden to prevent their insertion later. dnl This should only affect dll's. archive_cmds_CXX="\$CC -shared \$libobjs \$deplibs \$compiler_flags -static -o \$output_objdir/\$soname \${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker \$lib" postdeps_CXX= ;; *darwin*) TARGET_OS=darwin LEVELDB_TARGET_FLAGS="-DOS_MACOSX" if test x$cross_compiling != xyes; then BUILD_OS=darwin AC_CHECK_PROG([PORT],port, port) if test x$PORT = xport; then dnl add default macports paths CPPFLAGS="$CPPFLAGS -isystem /opt/local/include" LIBS="$LIBS -L/opt/local/lib" if test -d /opt/local/include/db48; then CPPFLAGS="$CPPFLAGS -I/opt/local/include/db48" LIBS="$LIBS -L/opt/local/lib/db48" fi fi AC_PATH_PROGS([RSVG_CONVERT], [rsvg-convert rsvg],rsvg-convert) AC_CHECK_PROG([BREW],brew, brew) if test x$BREW = xbrew; then dnl These Homebrew packages may be keg-only, meaning that they won't be found dnl in expected paths because they may conflict with system files. Ask dnl Homebrew where each one is located, then adjust paths accordingly. dnl It's safe to add these paths even if the functionality is disabled by dnl the user (--without-wallet or --without-gui for example). openssl_prefix=`$BREW --prefix openssl 2>/dev/null` bdb_prefix=`$BREW --prefix berkeley-db 2>/dev/null` qt5_prefix=`$BREW --prefix qt5 2>/dev/null` if test x$openssl_prefix != x; then PKG_CONFIG_PATH="$openssl_prefix/lib/pkgconfig:$PKG_CONFIG_PATH" export PKG_CONFIG_PATH fi if test x$bdb_prefix != x; then CPPFLAGS="$CPPFLAGS -I$bdb_prefix/include" LIBS="$LIBS -L$bdb_prefix/lib" fi if test x$qt5_prefix != x; then PKG_CONFIG_PATH="$qt5_prefix/lib/pkgconfig:$PKG_CONFIG_PATH" export PKG_CONFIG_PATH fi fi else case $build_os in *darwin*) BUILD_OS=darwin ;; *) AC_PATH_TOOL([INSTALLNAMETOOL], [install_name_tool], install_name_tool) AC_PATH_TOOL([OTOOL], [otool], otool) AC_PATH_PROGS([GENISOIMAGE], [genisoimage mkisofs],genisoimage) AC_PATH_PROGS([RSVG_CONVERT], [rsvg-convert rsvg],rsvg-convert) AC_PATH_PROGS([IMAGEMAGICK_CONVERT], [convert],convert) AC_PATH_PROGS([TIFFCP], [tiffcp],tiffcp) dnl libtool will try to strip the static lib, which is a problem for dnl cross-builds because strip attempts to call a hard-coded ld, dnl which may not exist in the path. Stripping the .a is not dnl necessary, so just disable it. old_striplib= ;; esac fi AX_CHECK_LINK_FLAG([[-Wl,-headerpad_max_install_names]], [LDFLAGS="$LDFLAGS -Wl,-headerpad_max_install_names"]) CPPFLAGS="$CPPFLAGS -DMAC_OSX" OBJCXXFLAGS="$CXXFLAGS" ;; *linux*) TARGET_OS=linux LEVELDB_TARGET_FLAGS="-DOS_LINUX" ;; *freebsd*) LEVELDB_TARGET_FLAGS="-DOS_FREEBSD" ;; *openbsd*) LEVELDB_TARGET_FLAGS="-DOS_OPENBSD" ;; *) OTHER_OS=`echo ${host_os} | awk '{print toupper($0)}'` AC_MSG_WARN([Guessing LevelDB OS as OS_${OTHER_OS}, please check whether this is correct, if not add an entry to configure.ac.]) LEVELDB_TARGET_FLAGS="-DOS_${OTHER_OS}" ;; esac if test x$use_pkgconfig = xyes; then m4_ifndef([PKG_PROG_PKG_CONFIG], [AC_MSG_ERROR(PKG_PROG_PKG_CONFIG macro not found. Please install pkg-config and re-run autogen.sh.)]) m4_ifdef([PKG_PROG_PKG_CONFIG], [ PKG_PROG_PKG_CONFIG if test x"$PKG_CONFIG" = "x"; then AC_MSG_ERROR(pkg-config not found.) fi ]) fi if test x$use_extended_functional_tests != xno; then AC_SUBST(EXTENDED_FUNCTIONAL_TESTS, --extended) fi if test x$use_lcov = xyes; then if test x$LCOV = x; then AC_MSG_ERROR("lcov testing requested but lcov not found") fi if test x$GCOV = x; then AC_MSG_ERROR("lcov testing requested but gcov not found") fi if test x$PYTHON = x; then AC_MSG_ERROR("lcov testing requested but python not found") fi if test x$GENHTML = x; then AC_MSG_ERROR("lcov testing requested but genhtml not found") fi LCOV="$LCOV --gcov-tool=$GCOV" AX_CHECK_LINK_FLAG([[--coverage]], [LDFLAGS="$LDFLAGS --coverage"], [AC_MSG_ERROR("lcov testing requested but --coverage linker flag does not work")]) AX_CHECK_COMPILE_FLAG([--coverage],[CXXFLAGS="$CXXFLAGS --coverage"], [AC_MSG_ERROR("lcov testing requested but --coverage flag does not work")]) fi dnl Check for endianness AC_C_BIGENDIAN dnl Check for pthread compile/link requirements AX_PTHREAD # The following macro will add the necessary defines to bitcoin-config.h, but # they also need to be passed down to any subprojects. Pull the results out of # the cache and add them to CPPFLAGS. AC_SYS_LARGEFILE # detect POSIX or GNU variant of strerror_r AC_FUNC_STRERROR_R if test x$ac_cv_sys_file_offset_bits != x && test x$ac_cv_sys_file_offset_bits != xno && test x$ac_cv_sys_file_offset_bits != xunknown; then CPPFLAGS="$CPPFLAGS -D_FILE_OFFSET_BITS=$ac_cv_sys_file_offset_bits" fi if test x$ac_cv_sys_large_files != x && test x$ac_cv_sys_large_files != xno && test x$ac_cv_sys_large_files != xunknown; then CPPFLAGS="$CPPFLAGS -D_LARGE_FILES=$ac_cv_sys_large_files" fi AX_CHECK_LINK_FLAG([[-Wl,--large-address-aware]], [LDFLAGS="$LDFLAGS -Wl,--large-address-aware"]) AX_GCC_FUNC_ATTRIBUTE([visibility]) AX_GCC_FUNC_ATTRIBUTE([dllexport]) AX_GCC_FUNC_ATTRIBUTE([dllimport]) if test x$use_glibc_compat != xno; then #glibc absorbed clock_gettime in 2.17. librt (its previous location) is safe to link #in anyway for back-compat. AC_CHECK_LIB([rt],[clock_gettime],, AC_MSG_ERROR(lib missing)) #__fdelt_chk's params and return type have changed from long unsigned int to long int. # See which one is present here. AC_MSG_CHECKING(__fdelt_chk type) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#ifdef _FORTIFY_SOURCE #undef _FORTIFY_SOURCE #endif #define _FORTIFY_SOURCE 2 #include extern "C" long unsigned int __fdelt_warn(long unsigned int);]],[[]])], [ fdelt_type="long unsigned int"], [ fdelt_type="long int"]) AC_MSG_RESULT($fdelt_type) AC_DEFINE_UNQUOTED(FDELT_TYPE, $fdelt_type,[parameter and return value type for __fdelt_chk]) AX_CHECK_LINK_FLAG([[-Wl,--wrap=__divmoddi4]], [COMPAT_LDFLAGS="$COMPAT_LDFLAGS -Wl,--wrap=__divmoddi4"]) AX_CHECK_LINK_FLAG([[-Wl,--wrap=log2f]], [COMPAT_LDFLAGS="$COMPAT_LDFLAGS -Wl,--wrap=log2f"]) else AC_SEARCH_LIBS([clock_gettime],[rt]) fi if test x$TARGET_OS != xwindows; then # All windows code is PIC, forcing it on just adds useless compile warnings AX_CHECK_COMPILE_FLAG([-fPIC],[PIC_FLAGS="-fPIC"]) fi if test x$use_hardening != xno; then AX_CHECK_COMPILE_FLAG([-Wstack-protector],[HARDENED_CXXFLAGS="$HARDENED_CXXFLAGS -Wstack-protector"]) AX_CHECK_COMPILE_FLAG([-fstack-protector-all],[HARDENED_CXXFLAGS="$HARDENED_CXXFLAGS -fstack-protector-all"]) AX_CHECK_PREPROC_FLAG([-D_FORTIFY_SOURCE=2],[ AX_CHECK_PREPROC_FLAG([-U_FORTIFY_SOURCE],[ HARDENED_CPPFLAGS="$HARDENED_CPPFLAGS -U_FORTIFY_SOURCE" ]) HARDENED_CPPFLAGS="$HARDENED_CPPFLAGS -D_FORTIFY_SOURCE=2" ]) AX_CHECK_LINK_FLAG([[-Wl,--dynamicbase]], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,--dynamicbase"]) AX_CHECK_LINK_FLAG([[-Wl,--nxcompat]], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,--nxcompat"]) AX_CHECK_LINK_FLAG([[-Wl,--high-entropy-va]], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,--high-entropy-va"]) AX_CHECK_LINK_FLAG([[-Wl,-z,relro]], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,-z,relro"]) AX_CHECK_LINK_FLAG([[-Wl,-z,now]], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,-z,now"]) if test x$TARGET_OS != xwindows; then AX_CHECK_COMPILE_FLAG([-fPIE],[PIE_FLAGS="-fPIE"]) AX_CHECK_LINK_FLAG([[-pie]], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -pie"]) fi case $host in *mingw*) AC_CHECK_LIB([ssp], [main],, AC_MSG_ERROR(lib missing)) ;; esac fi dnl this flag screws up non-darwin gcc even when the check fails. special-case it. if test x$TARGET_OS = xdarwin; then AX_CHECK_LINK_FLAG([[-Wl,-dead_strip]], [LDFLAGS="$LDFLAGS -Wl,-dead_strip"]) fi AC_CHECK_HEADERS([endian.h sys/endian.h byteswap.h stdio.h stdlib.h unistd.h strings.h sys/types.h sys/stat.h sys/select.h sys/prctl.h]) AC_CHECK_DECLS([strnlen]) # Check for daemon(3), unrelated to --with-daemon (although used by it) AC_CHECK_DECLS([daemon]) AC_CHECK_DECLS([le16toh, le32toh, le64toh, htole16, htole32, htole64, be16toh, be32toh, be64toh, htobe16, htobe32, htobe64],,, [#if HAVE_ENDIAN_H #include #elif HAVE_SYS_ENDIAN_H #include #endif]) AC_CHECK_DECLS([bswap_16, bswap_32, bswap_64],,, [#if HAVE_BYTESWAP_H #include #endif]) AC_CHECK_DECLS([__builtin_clz, __builtin_clzl, __builtin_clzll]) dnl Check for mallopt(M_ARENA_MAX) (to set glibc arenas) AC_MSG_CHECKING(for mallopt M_ARENA_MAX) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ mallopt(M_ARENA_MAX, 1); ]])], [ AC_MSG_RESULT(yes); AC_DEFINE(HAVE_MALLOPT_ARENA_MAX, 1,[Define this symbol if you have mallopt with M_ARENA_MAX]) ], [ AC_MSG_RESULT(no)] ) AC_MSG_CHECKING([for visibility attribute]) AC_LINK_IFELSE([AC_LANG_SOURCE([ int foo_def( void ) __attribute__((visibility("default"))); int main(){} ])], [ AC_DEFINE(HAVE_VISIBILITY_ATTRIBUTE,1,[Define if the visibility attribute is supported.]) AC_MSG_RESULT(yes) ], [ AC_MSG_RESULT(no) if test x$use_reduce_exports = xyes; then AC_MSG_ERROR([Cannot find a working visibility attribute. Use --disable-reduce-exports.]) fi ] ) # Check for different ways of gathering OS randomness AC_MSG_CHECKING(for Linux getrandom syscall) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include #include #include ]], [[ syscall(SYS_getrandom, nullptr, 32, 0); ]])], [ AC_MSG_RESULT(yes); AC_DEFINE(HAVE_SYS_GETRANDOM, 1,[Define this symbol if the Linux getrandom system call is available]) ], [ AC_MSG_RESULT(no)] ) AC_MSG_CHECKING(for getentropy) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ getentropy(nullptr, 32) ]])], [ AC_MSG_RESULT(yes); AC_DEFINE(HAVE_GETENTROPY, 1,[Define this symbol if the BSD getentropy system call is available]) ], [ AC_MSG_RESULT(no)] ) AC_MSG_CHECKING(for getentropy via random.h) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include #include ]], [[ getentropy(nullptr, 32) ]])], [ AC_MSG_RESULT(yes); AC_DEFINE(HAVE_GETENTROPY_RAND, 1,[Define this symbol if the BSD getentropy system call is available with sys/random.h]) ], [ AC_MSG_RESULT(no)] ) AC_MSG_CHECKING(for sysctl KERN_ARND) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include #include ]], [[ static const int name[2] = {CTL_KERN, KERN_ARND}; sysctl(name, 2, nullptr, nullptr, nullptr, 0); ]])], [ AC_MSG_RESULT(yes); AC_DEFINE(HAVE_SYSCTL_ARND, 1,[Define this symbol if the BSD sysctl(KERN_ARND) is available]) ], [ AC_MSG_RESULT(no)] ) # Check for reduced exports if test x$use_reduce_exports = xyes; then AX_CHECK_COMPILE_FLAG([-fvisibility=hidden],[RE_CXXFLAGS="-fvisibility=hidden"], [AC_MSG_ERROR([Cannot set default symbol visibility. Use --disable-reduce-exports.])]) fi LEVELDB_CPPFLAGS= LIBLEVELDB= LIBMEMENV= AM_CONDITIONAL([EMBEDDED_LEVELDB],[true]) AC_SUBST(LEVELDB_CPPFLAGS) AC_SUBST(LIBLEVELDB) AC_SUBST(LIBMEMENV) if test x$enable_wallet != xno; then dnl Check for libdb_cxx only if wallet enabled BITCOIN_FIND_BDB53 fi dnl Check for libminiupnpc (optional) if test x$use_upnp != xno; then AC_CHECK_HEADERS( [miniupnpc/miniwget.h miniupnpc/miniupnpc.h miniupnpc/upnpcommands.h miniupnpc/upnperrors.h], [AC_CHECK_LIB([miniupnpc], [upnpDiscover], [MINIUPNPC_LIBS=-lminiupnpc], [have_miniupnpc=no])], [have_miniupnpc=no] ) fi BITCOIN_QT_INIT dnl sets $bitcoin_enable_qt, $bitcoin_enable_qt_test, $bitcoin_enable_qt_dbus BITCOIN_QT_CONFIGURE([$use_pkgconfig]) if test x$build_bitcoin_utils$build_bitcoind$bitcoin_enable_qt$build_bitcoin_seeder$use_tests$use_bench = xnononononono; then use_boost=no else use_boost=yes fi if test x$use_boost = xyes; then dnl Minimum required Boost version define(MINIMUM_REQUIRED_BOOST, 1.58.0) dnl Check for boost libs AX_BOOST_BASE([MINIMUM_REQUIRED_BOOST]) AX_BOOST_SYSTEM AX_BOOST_FILESYSTEM AX_BOOST_PROGRAM_OPTIONS AX_BOOST_THREAD AX_BOOST_CHRONO dnl Boost 1.56 through 1.62 allow using std::atomic instead of its own atomic dnl counter implementations. In 1.63 and later the std::atomic approach is default. m4_pattern_allow(DBOOST_AC_USE_STD_ATOMIC) dnl otherwise it's treated like a macro BOOST_CPPFLAGS="-DBOOST_SP_USE_STD_ATOMIC -DBOOST_AC_USE_STD_ATOMIC $BOOST_CPPFLAGS" if test x$use_reduce_exports = xyes; then AC_MSG_CHECKING([for working boost reduced exports]) TEMP_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$BOOST_CPPFLAGS $CPPFLAGS" AC_PREPROC_IFELSE([AC_LANG_PROGRAM([[ @%:@include ]], [[ #if BOOST_VERSION >= 104900 // Everything is okay #else # error Boost version is too old #endif ]])],[ AC_MSG_RESULT(yes) ],[ AC_MSG_ERROR([boost versions < 1.49 are known to be broken with reduced exports. Use --disable-reduce-exports.]) ]) CPPFLAGS="$TEMP_CPPFLAGS" fi fi if test x$use_reduce_exports = xyes; then CXXFLAGS="$CXXFLAGS $RE_CXXFLAGS" AX_CHECK_LINK_FLAG([[-Wl,--exclude-libs,ALL]], [RELDFLAGS="-Wl,--exclude-libs,ALL"]) fi if test x$use_tests = xyes; then if test x$HEXDUMP = x; then AC_MSG_ERROR(hexdump is required for tests) fi if test x$use_boost = xyes; then AX_BOOST_UNIT_TEST_FRAMEWORK dnl Determine if -DBOOST_TEST_DYN_LINK is needed AC_MSG_CHECKING([for dynamic linked boost test]) TEMP_LIBS="$LIBS" LIBS="$LIBS $BOOST_LDFLAGS $BOOST_UNIT_TEST_FRAMEWORK_LIB" TEMP_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" AC_LINK_IFELSE([AC_LANG_SOURCE([ #define BOOST_TEST_DYN_LINK #define BOOST_TEST_MAIN #include ])], [AC_MSG_RESULT(yes)] [TESTDEFS="$TESTDEFS -DBOOST_TEST_DYN_LINK"], [AC_MSG_RESULT(no)]) LIBS="$TEMP_LIBS" CPPFLAGS="$TEMP_CPPFLAGS" fi fi if test x$use_boost = xyes; then BOOST_LIBS="$BOOST_LDFLAGS $BOOST_SYSTEM_LIB $BOOST_FILESYSTEM_LIB $BOOST_PROGRAM_OPTIONS_LIB $BOOST_THREAD_LIB $BOOST_CHRONO_LIB" dnl If boost (prior to 1.57) was built without c++11, it emulated scoped enums dnl using c++98 constructs. Unfortunately, this implementation detail leaked into dnl the abi. This was fixed in 1.57. dnl When building against that installed version using c++11, the headers pick up dnl on the native c++11 scoped enum support and enable it, however it will fail to dnl link. This can be worked around by disabling c++11 scoped enums if linking will dnl fail. dnl BOOST_NO_SCOPED_ENUMS was changed to BOOST_NO_CXX11_SCOPED_ENUMS in 1.51. TEMP_LIBS="$LIBS" LIBS="$BOOST_LIBS $LIBS" TEMP_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" AC_MSG_CHECKING([for mismatched boost c++11 scoped enums]) AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include #include #if !defined(BOOST_NO_SCOPED_ENUMS) && !defined(BOOST_NO_CXX11_SCOPED_ENUMS) && BOOST_VERSION < 105700 #define BOOST_NO_SCOPED_ENUMS #define BOOST_NO_CXX11_SCOPED_ENUMS #define CHECK #endif #include ]],[[ #if defined(CHECK) boost::filesystem::copy_file("foo", "bar"); #else choke; #endif ]])], [AC_MSG_RESULT(mismatched); BOOST_CPPFLAGS="$BOOST_CPPFLAGS -DBOOST_NO_SCOPED_ENUMS -DBOOST_NO_CXX11_SCOPED_ENUMS"], [AC_MSG_RESULT(ok)]) LIBS="$TEMP_LIBS" CPPFLAGS="$TEMP_CPPFLAGS" dnl Boost >= 1.50 uses sleep_for rather than the now-deprecated sleep, however dnl it was broken from 1.50 to 1.52 when backed by nanosleep. Use sleep_for if dnl a working version is available, else fall back to sleep. sleep was removed dnl after 1.56. dnl If neither is available, abort. TEMP_LIBS="$LIBS" LIBS="$BOOST_LIBS $LIBS" TEMP_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include #include ]],[[ #if BOOST_VERSION >= 105000 && (!defined(BOOST_HAS_NANOSLEEP) || BOOST_VERSION >= 105200) boost::this_thread::sleep_for(boost::chrono::milliseconds(0)); #else choke me #endif ]])], [boost_sleep=yes; AC_DEFINE(HAVE_WORKING_BOOST_SLEEP_FOR, 1, [Define this symbol if boost sleep_for works])], [boost_sleep=no]) LIBS="$TEMP_LIBS" CPPFLAGS="$TEMP_CPPFLAGS" if test x$boost_sleep != xyes; then TEMP_LIBS="$LIBS" LIBS="$BOOST_LIBS $LIBS" TEMP_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include #include #include ]],[[ #if BOOST_VERSION <= 105600 boost::this_thread::sleep(boost::posix_time::milliseconds(0)); #else choke me #endif ]])], [boost_sleep=yes; AC_DEFINE(HAVE_WORKING_BOOST_SLEEP, 1, [Define this symbol if boost sleep works])], [boost_sleep=no]) LIBS="$TEMP_LIBS" CPPFLAGS="$TEMP_CPPFLAGS" fi if test x$boost_sleep != xyes; then AC_MSG_ERROR(No working boost sleep implementation found.) fi fi if test x$use_pkgconfig = xyes; then : dnl m4_ifdef( [PKG_CHECK_MODULES], [ PKG_CHECK_MODULES([SSL], [libssl],, [AC_MSG_ERROR(openssl not found.)]) PKG_CHECK_MODULES([CRYPTO], [libcrypto],,[AC_MSG_ERROR(libcrypto not found.)]) BITCOIN_QT_CHECK([PKG_CHECK_MODULES([PROTOBUF], [protobuf], [have_protobuf=yes], [BITCOIN_QT_FAIL(libprotobuf not found)])]) if test x$use_qr != xno; then BITCOIN_QT_CHECK([PKG_CHECK_MODULES([QR], [libqrencode], [have_qrencode=yes], [have_qrencode=no])]) fi if test x$build_bitcoin_utils$build_bitcoind$bitcoin_enable_qt$use_tests != xnononono; then PKG_CHECK_MODULES([EVENT], [libevent],, [AC_MSG_ERROR(libevent not found.)]) if test x$TARGET_OS != xwindows; then PKG_CHECK_MODULES([EVENT_PTHREADS], [libevent_pthreads],, [AC_MSG_ERROR(libevent_pthreads not found.)]) fi fi if test "x$use_zmq" = "xyes"; then PKG_CHECK_MODULES([ZMQ],[libzmq >= 4], [AC_DEFINE([ENABLE_ZMQ],[1],[Define to 1 to enable ZMQ functions])], [AC_DEFINE([ENABLE_ZMQ],[0],[Define to 1 to enable ZMQ functions]) AC_MSG_WARN([libzmq version 4.x or greater not found, disabling]) use_zmq=no]) else AC_DEFINE_UNQUOTED([ENABLE_ZMQ],[0],[Define to 1 to enable ZMQ functions]) fi ] ) else AC_CHECK_HEADER([openssl/crypto.h],,AC_MSG_ERROR(libcrypto headers missing)) AC_CHECK_LIB([crypto], [main],CRYPTO_LIBS=-lcrypto, AC_MSG_ERROR(libcrypto missing)) AC_CHECK_HEADER([openssl/ssl.h],, AC_MSG_ERROR(libssl headers missing),) AC_CHECK_LIB([ssl], [main],SSL_LIBS=-lssl, AC_MSG_ERROR(libssl missing)) if test x$build_bitcoin_utils$build_bitcoind$bitcoin_enable_qt$use_tests != xnononono; then AC_CHECK_HEADER([event2/event.h],, AC_MSG_ERROR(libevent headers missing),) AC_CHECK_LIB([event],[main],EVENT_LIBS=-levent,AC_MSG_ERROR(libevent missing)) if test x$TARGET_OS != xwindows; then AC_CHECK_LIB([event_pthreads],[main],EVENT_PTHREADS_LIBS=-levent_pthreads,AC_MSG_ERROR(libevent_pthreads missing)) fi fi if test "x$use_zmq" = "xyes"; then AC_CHECK_HEADER([zmq.h], [AC_DEFINE([ENABLE_ZMQ],[1],[Define to 1 to enable ZMQ functions])], [AC_MSG_WARN([zmq.h not found, disabling zmq support]) use_zmq=no AC_DEFINE([ENABLE_ZMQ],[0],[Define to 1 to enable ZMQ functions])]) AC_CHECK_LIB([zmq],[zmq_ctx_shutdown],ZMQ_LIBS=-lzmq, [AC_MSG_WARN([libzmq >= 4.0 not found, disabling zmq support]) use_zmq=no AC_DEFINE([ENABLE_ZMQ],[0],[Define to 1 to enable ZMQ functions])]) else AC_DEFINE_UNQUOTED([ENABLE_ZMQ],[0],[Define to 1 to enable ZMQ functions]) fi if test "x$use_zmq" = "xyes"; then dnl Assume libzmq was built for static linking case $host in *mingw*) ZMQ_CFLAGS="$ZMQ_CFLAGS -DZMQ_STATIC" ;; esac fi BITCOIN_QT_CHECK(AC_CHECK_LIB([protobuf] ,[main],[PROTOBUF_LIBS=-lprotobuf], BITCOIN_QT_FAIL(libprotobuf not found))) if test x$use_qr != xno; then BITCOIN_QT_CHECK([AC_CHECK_LIB([qrencode], [main],[QR_LIBS=-lqrencode], [have_qrencode=no])]) BITCOIN_QT_CHECK([AC_CHECK_HEADER([qrencode.h],, have_qrencode=no)]) fi fi save_CXXFLAGS="${CXXFLAGS}" CXXFLAGS="${CXXFLAGS} ${CRYPTO_CFLAGS} ${SSL_CFLAGS}" AC_CHECK_DECLS([EVP_MD_CTX_new],,,[AC_INCLUDES_DEFAULT #include ]) CXXFLAGS="${save_CXXFLAGS}" dnl univalue check need_bundled_univalue=yes if test x$build_bitcoin_utils$build_bitcoind$bitcoin_enable_qt$use_tests$use_bench = xnonononono; then need_bundled_univalue=no else if test x$system_univalue != xno ; then found_univalue=no if test x$use_pkgconfig = xyes; then : #NOP m4_ifdef( [PKG_CHECK_MODULES], [ PKG_CHECK_MODULES([UNIVALUE],[libunivalue],[found_univalue=yes],[true]) ] ) else AC_CHECK_HEADER([univalue.h],[ AC_CHECK_LIB([univalue], [main],[ UNIVALUE_LIBS=-lunivalue found_univalue=yes ],[true]) ],[true]) fi if test x$found_univalue = xyes ; then system_univalue=yes need_bundled_univalue=no elif test x$system_univalue = xyes ; then AC_MSG_ERROR([univalue not found]) else system_univalue=no fi fi if test x$need_bundled_univalue = xyes ; then UNIVALUE_CFLAGS='-I$(srcdir)/univalue/include' UNIVALUE_LIBS='univalue/libunivalue.la' fi fi AM_CONDITIONAL([EMBEDDED_UNIVALUE],[test x$need_bundled_univalue = xyes]) AC_SUBST(UNIVALUE_CFLAGS) AC_SUBST(UNIVALUE_LIBS) BITCOIN_QT_PATH_PROGS([PROTOC], [protoc],$protoc_bin_path) AC_MSG_CHECKING([whether to build bitcoind]) AM_CONDITIONAL([BUILD_BITCOIND], [test x$build_bitcoind = xyes]) AC_MSG_RESULT($build_bitcoind) AC_MSG_CHECKING([whether to build bitcoin-seeder]) AM_CONDITIONAL([BUILD_BITCOIN_SEEDER], [test x$build_bitcoin_seeder = xyes]) AC_MSG_RESULT($build_bitcoin_seeder) AC_MSG_CHECKING([whether to build utils (bitcoin-cli bitcoin-tx)]) AM_CONDITIONAL([BUILD_BITCOIN_UTILS], [test x$build_bitcoin_utils = xyes]) AC_MSG_RESULT($build_bitcoin_utils) AC_MSG_CHECKING([whether to build libraries]) AM_CONDITIONAL([BUILD_BITCOIN_LIBS], [test x$build_bitcoin_libs = xyes]) if test x$build_bitcoin_libs = xyes; then AC_DEFINE(HAVE_CONSENSUS_LIB, 1, [Define this symbol if the consensus lib has been built]) AC_CONFIG_FILES([libbitcoinconsensus.pc:libbitcoinconsensus.pc.in]) fi AC_MSG_RESULT($build_bitcoin_libs) AC_LANG_POP if test "x$use_ccache" != "xno"; then AC_MSG_CHECKING(if ccache should be used) if test x$CCACHE = x; then if test "x$use_ccache" = "xyes"; then AC_MSG_ERROR([ccache not found.]); else use_ccache=no fi else use_ccache=yes CC="$ac_cv_path_CCACHE $CC" CXX="$ac_cv_path_CCACHE $CXX" fi AC_MSG_RESULT($use_ccache) fi if test "x$use_ccache" = "xyes"; then AX_CHECK_PREPROC_FLAG([-Qunused-arguments],[CPPFLAGS="-Qunused-arguments $CPPFLAGS"]) fi dnl enable wallet AC_MSG_CHECKING([if wallet should be enabled]) if test x$enable_wallet != xno; then AC_MSG_RESULT(yes) AC_DEFINE_UNQUOTED([ENABLE_WALLET],[1],[Define to 1 to enable wallet functions]) else AC_MSG_RESULT(no) fi dnl enable upnp support AC_MSG_CHECKING([whether to build with support for UPnP]) if test x$have_miniupnpc = xno; then if test x$use_upnp = xyes; then AC_MSG_ERROR("UPnP requested but cannot be built. use --without-miniupnpc") fi AC_MSG_RESULT(no) else if test x$use_upnp != xno; then AC_MSG_RESULT(yes) AC_MSG_CHECKING([whether to build with UPnP enabled by default]) use_upnp=yes upnp_setting=0 if test x$use_upnp_default != xno; then use_upnp_default=yes upnp_setting=1 fi AC_MSG_RESULT($use_upnp_default) AC_DEFINE_UNQUOTED([USE_UPNP],[$upnp_setting],[UPnP support not compiled if undefined, otherwise value (0 or 1) determines default state]) if test x$TARGET_OS = xwindows; then MINIUPNPC_CPPFLAGS="-DSTATICLIB -DMINIUPNP_STATICLIB" fi else AC_MSG_RESULT(no) fi fi dnl these are only used when qt is enabled BUILD_TEST_QT="" if test x$bitcoin_enable_qt != xno; then dnl enable dbus support AC_MSG_CHECKING([whether to build GUI with support for D-Bus]) if test x$bitcoin_enable_qt_dbus != xno; then AC_DEFINE([USE_DBUS],[1],[Define if dbus support should be compiled in]) fi AC_MSG_RESULT($bitcoin_enable_qt_dbus) dnl enable qr support AC_MSG_CHECKING([whether to build GUI with support for QR codes]) if test x$have_qrencode = xno; then if test x$use_qr = xyes; then AC_MSG_ERROR("QR support requested but cannot be built. use --without-qrencode") fi AC_MSG_RESULT(no) else if test x$use_qr != xno; then AC_MSG_RESULT(yes) AC_DEFINE([USE_QRCODE],[1],[Define if QR support should be compiled in]) use_qr=yes else AC_MSG_RESULT(no) fi fi if test x$XGETTEXT = x; then AC_MSG_WARN("xgettext is required to update qt translations") fi AC_MSG_CHECKING([whether to build test_bitcoin-qt]) if test x$use_gui_tests$bitcoin_enable_qt_test = xyesyes; then AC_MSG_RESULT([yes]) BUILD_TEST_QT="yes" else AC_MSG_RESULT([no]) fi fi AM_CONDITIONAL([ENABLE_ZMQ], [test "x$use_zmq" = "xyes"]) AC_MSG_CHECKING([whether to build test_bitcoin]) if test x$use_tests = xyes; then AC_MSG_RESULT([yes]) BUILD_TEST="yes" else AC_MSG_RESULT([no]) BUILD_TEST="" fi AC_MSG_CHECKING([whether to reduce exports]) if test x$use_reduce_exports = xyes; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi if test x$build_bitcoin_utils$build_bitcoin_libs$build_bitcoind$bitcoin_enable_qt$use_bench$use_tests = xnononononono; then AC_MSG_ERROR([No targets! Please specify at least one of: --with-utils --with-libs --with-daemon --with-seeder --with-gui --enable-bench or --enable-tests]) fi AM_CONDITIONAL([TARGET_DARWIN], [test x$TARGET_OS = xdarwin]) AM_CONDITIONAL([BUILD_DARWIN], [test x$BUILD_OS = xdarwin]) AM_CONDITIONAL([TARGET_WINDOWS], [test x$TARGET_OS = xwindows]) AM_CONDITIONAL([ENABLE_WALLET],[test x$enable_wallet = xyes]) AM_CONDITIONAL([ENABLE_TESTS],[test x$BUILD_TEST = xyes]) AM_CONDITIONAL([ENABLE_QT],[test x$bitcoin_enable_qt = xyes]) AM_CONDITIONAL([ENABLE_QT_TESTS],[test x$BUILD_TEST_QT = xyes]) AM_CONDITIONAL([ENABLE_BENCH],[test x$use_bench = xyes]) AM_CONDITIONAL([USE_QRCODE], [test x$use_qr = xyes]) AM_CONDITIONAL([USE_LCOV],[test x$use_lcov = xyes]) AM_CONDITIONAL([GLIBC_BACK_COMPAT],[test x$use_glibc_compat = xyes]) AM_CONDITIONAL([HARDEN],[test x$use_hardening = xyes]) AM_CONDITIONAL([ENABLE_HWCRC32],[test x$enable_hwcrc32 = xyes]) +AM_CONDITIONAL([ENABLE_SSE41],[test x$enable_sse41 = xyes]) +AM_CONDITIONAL([ENABLE_AVX2],[test x$enable_avx2 = xyes]) AM_CONDITIONAL([USE_ASM],[test x$use_asm = xyes]) AC_DEFINE(CLIENT_VERSION_MAJOR, _CLIENT_VERSION_MAJOR, [Major version]) AC_DEFINE(CLIENT_VERSION_MINOR, _CLIENT_VERSION_MINOR, [Minor version]) AC_DEFINE(CLIENT_VERSION_REVISION, _CLIENT_VERSION_REVISION, [Build revision]) AC_DEFINE(CLIENT_VERSION_BUILD, _CLIENT_VERSION_BUILD, [Version Build]) AC_DEFINE(CLIENT_VERSION_IS_RELEASE, _CLIENT_VERSION_IS_RELEASE, [Version is release]) AC_DEFINE(COPYRIGHT_YEAR, _COPYRIGHT_YEAR, [Copyright year]) AC_DEFINE(COPYRIGHT_HOLDERS, "_COPYRIGHT_HOLDERS", [Copyright holder(s) before %s replacement]) AC_DEFINE(COPYRIGHT_HOLDERS_SUBSTITUTION, "_COPYRIGHT_HOLDERS_SUBSTITUTION", [Replacement for %s in copyright holders string]) define(_COPYRIGHT_HOLDERS_FINAL, [patsubst(_COPYRIGHT_HOLDERS, [%s], [_COPYRIGHT_HOLDERS_SUBSTITUTION])]) AC_DEFINE(COPYRIGHT_HOLDERS_FINAL, "_COPYRIGHT_HOLDERS_FINAL", [Copyright holder(s)]) AC_SUBST(CLIENT_VERSION_MAJOR, _CLIENT_VERSION_MAJOR) AC_SUBST(CLIENT_VERSION_MINOR, _CLIENT_VERSION_MINOR) AC_SUBST(CLIENT_VERSION_REVISION, _CLIENT_VERSION_REVISION) AC_SUBST(CLIENT_VERSION_BUILD, _CLIENT_VERSION_BUILD) AC_SUBST(CLIENT_VERSION_IS_RELEASE, _CLIENT_VERSION_IS_RELEASE) AC_SUBST(COPYRIGHT_YEAR, _COPYRIGHT_YEAR) AC_SUBST(COPYRIGHT_HOLDERS, "_COPYRIGHT_HOLDERS") AC_SUBST(COPYRIGHT_HOLDERS_SUBSTITUTION, "_COPYRIGHT_HOLDERS_SUBSTITUTION") AC_SUBST(COPYRIGHT_HOLDERS_FINAL, "_COPYRIGHT_HOLDERS_FINAL") AC_SUBST(BITCOIN_DAEMON_NAME) AC_SUBST(BITCOIN_GUI_NAME) AC_SUBST(BITCOIN_CLI_NAME) AC_SUBST(BITCOIN_TX_NAME) AC_SUBST(BITCOIN_SEEDER_NAME) AC_SUBST(RELDFLAGS) AC_SUBST(COMPAT_LDFLAGS) AC_SUBST(ERROR_CXXFLAGS) AC_SUBST(HARDENED_CXXFLAGS) AC_SUBST(HARDENED_CPPFLAGS) AC_SUBST(HARDENED_LDFLAGS) AC_SUBST(PIC_FLAGS) AC_SUBST(PIE_FLAGS) AC_SUBST(SSE42_CXXFLAGS) +AC_SUBST(SSE41_CXXFLAGS) +AC_SUBST(AVX2_CXXFLAGS) AC_SUBST(LIBTOOL_APP_LDFLAGS) AC_SUBST(USE_UPNP) AC_SUBST(USE_QRCODE) AC_SUBST(BOOST_LIBS) AC_SUBST(TESTDEFS) AC_SUBST(LEVELDB_TARGET_FLAGS) AC_SUBST(MINIUPNPC_CPPFLAGS) AC_SUBST(MINIUPNPC_LIBS) AC_SUBST(CRYPTO_LIBS) AC_SUBST(SSL_LIBS) AC_SUBST(EVENT_LIBS) AC_SUBST(EVENT_PTHREADS_LIBS) AC_SUBST(ZMQ_LIBS) AC_SUBST(PROTOBUF_LIBS) AC_SUBST(QR_LIBS) AC_CONFIG_FILES([Makefile src/Makefile doc/man/Makefile share/setup.nsi share/qt/Info.plist test/config.ini]) AC_CONFIG_FILES([contrib/devtools/split-debug.sh],[chmod +x contrib/devtools/split-debug.sh]) AC_CONFIG_LINKS([test/functional/test_runner.py:test/functional/test_runner.py]) AC_CONFIG_LINKS([test/util/bitcoin-util-test.py:test/util/bitcoin-util-test.py]) dnl boost's m4 checks do something really nasty: they export these vars. As a dnl result, they leak into secp256k1's configure and crazy things happen. dnl Until this is fixed upstream and we've synced, we'll just un-export them. CPPFLAGS_TEMP="$CPPFLAGS" unset CPPFLAGS CPPFLAGS="$CPPFLAGS_TEMP" LDFLAGS_TEMP="$LDFLAGS" unset LDFLAGS LDFLAGS="$LDFLAGS_TEMP" LIBS_TEMP="$LIBS" unset LIBS LIBS="$LIBS_TEMP" PKGCONFIG_PATH_TEMP="$PKG_CONFIG_PATH" unset PKG_CONFIG_PATH PKG_CONFIG_PATH="$PKGCONFIG_PATH_TEMP" PKGCONFIG_LIBDIR_TEMP="$PKG_CONFIG_LIBDIR" unset PKG_CONFIG_LIBDIR PKG_CONFIG_LIBDIR="$PKGCONFIG_LIBDIR_TEMP" if test x$need_bundled_univalue = xyes; then AC_CONFIG_SUBDIRS([src/univalue]) fi ac_configure_args="${ac_configure_args} --disable-shared --with-pic --with-bignum=no --enable-module-recovery --enable-module-multiset --disable-jni" AC_CONFIG_SUBDIRS([src/secp256k1]) AC_OUTPUT dnl Taken from https://wiki.debian.org/RpathIssue case $host in *-*-linux-gnu) AC_MSG_RESULT([Fixing libtool for -rpath problems.]) sed < libtool > libtool-2 \ 's/^hardcode_libdir_flag_spec.*$'/'hardcode_libdir_flag_spec=" -D__LIBTOOL_IS_A_FOOL__ "/' mv libtool-2 libtool chmod 755 libtool ;; esac dnl Replace the BUILDDIR path with the correct Windows path if compiling on Native Windows case ${OS} in *Windows*) sed 's/BUILDDIR="\/\([[a-z]]\)/BUILDDIR="\1:/' test/config.ini > test/config-2.ini mv test/config-2.ini test/config.ini ;; esac echo echo "Options used to compile and link:" echo " with wallet = $enable_wallet" echo " with gui / qt = $bitcoin_enable_qt" if test x$bitcoin_enable_qt != xno; then echo " with qr = $use_qr" fi echo " with zmq = $use_zmq" echo " with test = $use_tests" echo " with bench = $use_bench" echo " with upnp = $use_upnp" echo " use asm = $use_asm" echo " debug enabled = $enable_debug" echo " werror = $enable_werror" echo echo " sanitizers " echo " asan = $enable_asan" echo " tsan = $enable_tsan" echo " ubsan = $enable_ubsan" echo echo " target os = $TARGET_OS" echo " build os = $BUILD_OS" echo echo " CC = $CC" echo " CFLAGS = $CFLAGS" echo " CPPFLAGS = $CPPFLAGS" echo " CXX = $CXX" echo " CXXFLAGS = $CXXFLAGS" echo " LDFLAGS = $LDFLAGS" echo diff --git a/doc/release-notes.md b/doc/release-notes.md index 6fe54528cf..ae1b454680 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -1,8 +1,9 @@ Bitcoin ABC version 0.18.3 is now available from: This release includes the following features and fixes: - Remove support for Qt4 - Upgrade reproducible build to us Qt 5.9.6 + - Improve SHA256 performance using SSE4.1 or AVX2 if available. diff --git a/src/Makefile.am b/src/Makefile.am index 1419eaeec6..3ced42ff54 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,604 +1,632 @@ # Copyright (c) 2013-2016 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. DIST_SUBDIRS = secp256k1 univalue AM_LDFLAGS = $(PTHREAD_CFLAGS) $(LIBTOOL_LDFLAGS) $(HARDENED_LDFLAGS) AM_CXXFLAGS = $(HARDENED_CXXFLAGS) $(ERROR_CXXFLAGS) AM_CPPFLAGS = $(HARDENED_CPPFLAGS) EXTRA_LIBRARIES = if EMBEDDED_UNIVALUE LIBUNIVALUE = univalue/libunivalue.la $(LIBUNIVALUE): $(wildcard univalue/lib/*) $(wildcard univalue/include/*) $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F) else LIBUNIVALUE = $(UNIVALUE_LIBS) endif BITCOIN_INCLUDES=-I$(builddir) -I$(builddir)/obj $(BDB_CPPFLAGS) $(BOOST_CPPFLAGS) $(LEVELDB_CPPFLAGS) $(CRYPTO_CFLAGS) $(SSL_CFLAGS) BITCOIN_INCLUDES += -I$(srcdir)/secp256k1/include BITCOIN_INCLUDES += $(UNIVALUE_CFLAGS) BITCOIN_SEEDER_INCLUDES = -I$(srcdir)/seeder BITCOIN_SEEDER_INCLUDES += $(BITCOIN_INCLUDES) LIBBITCOIN_SERVER=libbitcoin_server.a LIBBITCOIN_COMMON=libbitcoin_common.a LIBBITCOIN_CONSENSUS=libbitcoin_consensus.a LIBBITCOIN_CLI=libbitcoin_cli.a LIBBITCOIN_UTIL=libbitcoin_util.a LIBBITCOIN_CRYPTO=crypto/libbitcoin_crypto.a +LIBBITCOIN_CRYPTO_SSE41=crypto/libbitcoin_crypto_sse41.a +LIBBITCOIN_CRYPTO_AVX2=crypto/libbitcoin_crypto_avx2.a LIBBITCOINQT=qt/libbitcoinqt.a LIBSECP256K1=secp256k1/libsecp256k1.la if ENABLE_ZMQ LIBBITCOIN_ZMQ=libbitcoin_zmq.a endif if BUILD_BITCOIN_LIBS LIBBITCOINCONSENSUS=libbitcoinconsensus.la endif if BUILD_BITCOIN_SEEDER LIBBITCOIN_SEEDER=libbitcoin_seeder.a endif if ENABLE_WALLET LIBBITCOIN_WALLET=libbitcoin_wallet.a endif $(LIBSECP256K1): $(wildcard secp256k1/src/*) $(wildcard secp256k1/include/*) $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F) # Make is not made aware of per-object dependencies to avoid limiting building parallelization # But to build the less dependent modules first, we manually select their order here: EXTRA_LIBRARIES += \ $(LIBBITCOIN_CRYPTO) \ + $(LIBBITCOIN_CRYPTO_SSE41) \ + $(LIBBITCOIN_CRYPTO_AVX2) \ $(LIBBITCOIN_UTIL) \ $(LIBBITCOIN_COMMON) \ $(LIBBITCOIN_CONSENSUS) \ $(LIBBITCOIN_SERVER) \ $(LIBBITCOIN_CLI) \ $(LIBBITCOIN_SEEDER) \ $(LIBBITCOIN_WALLET) \ $(LIBBITCOIN_ZMQ) lib_LTLIBRARIES = $(LIBBITCOINCONSENSUS) bin_PROGRAMS = noinst_PROGRAMS = TESTS = BENCHMARKS = if BUILD_BITCOIND bin_PROGRAMS += bitcoind endif if BUILD_BITCOIN_SEEDER bin_PROGRAMS += bitcoin-seeder endif if BUILD_BITCOIN_UTILS bin_PROGRAMS += bitcoin-cli bitcoin-tx endif .PHONY: FORCE check-symbols check-security # bitcoin core # BITCOIN_CORE_H = \ addrdb.h \ addrman.h \ base58.h \ bloom.h \ blockencodings.h \ blockfileinfo.h \ blockindexworkcomparator.h \ blockstatus.h \ blockvalidity.h \ cashaddr.h \ cashaddrenc.h \ chain.h \ chainparams.h \ chainparamsbase.h \ chainparamsseeds.h \ checkpoints.h \ checkqueue.h \ clientversion.h \ coins.h \ compat.h \ compat/byteswap.h \ compat/endian.h \ compat/sanity.h \ compressor.h \ config.h \ consensus/activation.h \ consensus/consensus.h \ consensus/tx_verify.h \ core_io.h \ core_memusage.h \ cuckoocache.h \ diskblockpos.h \ dstencode.h \ fs.h \ globals.h \ httprpc.h \ httpserver.h \ indirectmap.h \ init.h \ key.h \ keystore.h \ dbwrapper.h \ limitedmap.h \ logging.h \ memusage.h \ merkleblock.h \ miner.h \ net.h \ net_processing.h \ netaddress.h \ netbase.h \ netmessagemaker.h \ noui.h \ policy/fees.h \ policy/policy.h \ pow.h \ protocol.h \ random.h \ reverselock.h \ rpc/blockchain.h \ rpc/client.h \ rpc/jsonrpcrequest.h \ rpc/mining.h \ rpc/misc.h \ rpc/protocol.h \ rpc/server.h \ rpc/tojson.h \ rpc/register.h \ scheduler.h \ script/scriptcache.h \ script/sigcache.h \ script/sign.h \ script/standard.h \ script/ismine.h \ streams.h \ support/allocators/secure.h \ support/allocators/zeroafterfree.h \ support/cleanse.h \ support/events.h \ support/lockedpool.h \ sync.h \ threadsafety.h \ threadinterrupt.h \ timedata.h \ torcontrol.h \ txdb.h \ txmempool.h \ ui_interface.h \ undo.h \ util.h \ utilmoneystr.h \ utiltime.h \ validation.h \ validationinterface.h \ versionbits.h \ wallet/coincontrol.h \ wallet/crypter.h \ wallet/db.h \ wallet/finaltx.h \ wallet/rpcdump.h \ wallet/fees.h \ wallet/init.h \ wallet/rpcwallet.h \ wallet/wallet.h \ wallet/walletdb.h \ warnings.h \ zmq/zmqabstractnotifier.h \ zmq/zmqconfig.h\ zmq/zmqnotificationinterface.h \ zmq/zmqpublishnotifier.h obj/build.h: FORCE @$(MKDIR_P) "$(builddir)/obj" @$(top_srcdir)/share/genbuild.sh "$(abs_top_builddir)/src/obj/build.h" \ "$(abs_top_srcdir)" libbitcoin_util_a-clientversion.$(OBJEXT): obj/build.h # server: shared between bitcoind and bitcoin-qt libbitcoin_server_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(MINIUPNPC_CPPFLAGS) $(EVENT_CFLAGS) $(EVENT_PTHREADS_CFLAGS) libbitcoin_server_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) libbitcoin_server_a_SOURCES = \ addrman.cpp \ addrdb.cpp \ bloom.cpp \ blockencodings.cpp \ chain.cpp \ checkpoints.cpp \ config.cpp \ consensus/activation.cpp \ consensus/tx_verify.cpp \ globals.cpp \ httprpc.cpp \ httpserver.cpp \ init.cpp \ dbwrapper.cpp \ merkleblock.cpp \ miner.cpp \ net.cpp \ net_processing.cpp \ noui.cpp \ policy/fees.cpp \ policy/policy.cpp \ pow.cpp \ rest.cpp \ rpc/abc.cpp \ rpc/blockchain.cpp \ rpc/jsonrpcrequest.cpp \ rpc/mining.cpp \ rpc/misc.cpp \ rpc/net.cpp \ rpc/rawtransaction.cpp \ rpc/server.cpp \ script/scriptcache.cpp \ script/sigcache.cpp \ script/ismine.cpp \ timedata.cpp \ torcontrol.cpp \ txdb.cpp \ txmempool.cpp \ ui_interface.cpp \ validation.cpp \ validationinterface.cpp \ versionbits.cpp \ $(BITCOIN_CORE_H) if ENABLE_ZMQ libbitcoin_zmq_a_CPPFLAGS = $(BITCOIN_INCLUDES) $(ZMQ_CFLAGS) libbitcoin_zmq_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) libbitcoin_zmq_a_SOURCES = \ zmq/zmqabstractnotifier.cpp \ zmq/zmqnotificationinterface.cpp \ zmq/zmqpublishnotifier.cpp endif # wallet: shared between bitcoind and bitcoin-qt, but only linked # when wallet enabled libbitcoin_wallet_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) libbitcoin_wallet_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) libbitcoin_wallet_a_SOURCES = \ wallet/crypter.cpp \ wallet/db.cpp \ wallet/finaltx.cpp \ wallet/fees.cpp \ wallet/init.cpp \ wallet/rpcdump.cpp \ wallet/rpcwallet.cpp \ wallet/wallet.cpp \ wallet/walletdb.cpp \ $(BITCOIN_CORE_H) # crypto primitives library crypto_libbitcoin_crypto_a_CPPFLAGS = $(AM_CPPFLAGS) crypto_libbitcoin_crypto_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) crypto_libbitcoin_crypto_a_SOURCES = \ crypto/aes.cpp \ crypto/aes.h \ crypto/chacha20.h \ crypto/chacha20.cpp \ crypto/common.h \ crypto/hmac_sha256.cpp \ crypto/hmac_sha256.h \ crypto/hmac_sha512.cpp \ crypto/hmac_sha512.h \ crypto/ripemd160.cpp \ crypto/ripemd160.h \ crypto/sha1.cpp \ crypto/sha1.h \ crypto/sha256.cpp \ crypto/sha256.h \ crypto/sha512.cpp \ crypto/sha512.h if USE_ASM crypto_libbitcoin_crypto_a_SOURCES += crypto/sha256_sse4.cpp endif +crypto_libbitcoin_crypto_sse41_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) +crypto_libbitcoin_crypto_sse41_a_CPPFLAGS = $(AM_CPPFLAGS) +if ENABLE_SSE41 +crypto_libbitcoin_crypto_sse41_a_CXXFLAGS += $(SSE41_CXXFLAGS) +crypto_libbitcoin_crypto_sse41_a_CPPFLAGS += -DENABLE_SSE41 +endif +crypto_libbitcoin_crypto_sse41_a_SOURCES = crypto/sha256_sse41.cpp + +crypto_libbitcoin_crypto_avx2_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) +crypto_libbitcoin_crypto_avx2_a_CPPFLAGS = $(AM_CPPFLAGS) +if ENABLE_AVX2 +crypto_libbitcoin_crypto_avx2_a_CXXFLAGS += $(AVX2_CXXFLAGS) +crypto_libbitcoin_crypto_avx2_a_CPPFLAGS += -DENABLE_AVX2 +endif +crypto_libbitcoin_crypto_avx2_a_SOURCES = crypto/sha256_avx2.cpp + # consensus: shared between all executables that validate any consensus rules. libbitcoin_consensus_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) libbitcoin_consensus_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) libbitcoin_consensus_a_SOURCES = \ amount.h \ arith_uint256.cpp \ arith_uint256.h \ consensus/merkle.cpp \ consensus/merkle.h \ consensus/params.h \ consensus/validation.h \ feerate.h \ hash.cpp \ hash.h \ prevector.h \ primitives/block.cpp \ primitives/block.h \ primitives/transaction.cpp \ primitives/transaction.h \ primitives/txid.h \ pubkey.cpp \ pubkey.h \ script/bitcoinconsensus.cpp \ script/sighashtype.h \ script/interpreter.cpp \ script/interpreter.h \ script/script.cpp \ script/script.h \ script/script_error.cpp \ script/script_error.h \ script/script_flags.h \ script/sigencoding.cpp \ script/sigencoding.h \ serialize.h \ tinyformat.h \ uint256.cpp \ uint256.h \ utilstrencodings.cpp \ utilstrencodings.h \ version.h # common: shared between bitcoind, and bitcoin-qt and non-server tools libbitcoin_common_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) libbitcoin_common_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) libbitcoin_common_a_SOURCES = \ amount.cpp \ base58.cpp \ cashaddr.cpp \ cashaddrenc.cpp \ chainparams.cpp \ config.cpp \ coins.cpp \ compressor.cpp \ dstencode.cpp \ feerate.cpp \ globals.cpp \ core_read.cpp \ core_write.cpp \ key.cpp \ keystore.cpp \ netaddress.cpp \ netbase.cpp \ protocol.cpp \ scheduler.cpp \ script/sign.cpp \ script/standard.cpp \ warnings.cpp \ $(BITCOIN_CORE_H) # util: shared between all executables. # This library *must* be included to make sure that the glibc # backward-compatibility objects and their sanity checks are linked. libbitcoin_util_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) libbitcoin_util_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) libbitcoin_util_a_SOURCES = \ support/lockedpool.cpp \ chainparamsbase.cpp \ clientversion.cpp \ compat/glibc_sanity.cpp \ compat/glibcxx_sanity.cpp \ compat/strnlen.cpp \ fs.cpp \ logging.cpp \ random.cpp \ rpc/protocol.cpp \ support/cleanse.cpp \ sync.cpp \ threadinterrupt.cpp \ uint256.cpp \ uint256.h \ util.cpp \ utilmoneystr.cpp \ utilstrencodings.cpp \ utiltime.cpp \ $(BITCOIN_CORE_H) if GLIBC_BACK_COMPAT libbitcoin_util_a_SOURCES += compat/glibc_compat.cpp AM_LDFLAGS += $(COMPAT_LDFLAGS) endif # cli: shared between bitcoin-cli and bitcoin-qt libbitcoin_cli_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) libbitcoin_cli_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) libbitcoin_cli_a_SOURCES = \ rpc/client.cpp \ $(BITCOIN_CORE_H) # seeder library libbitcoin_seeder_a_CPPFLAGS = $(AM_CPPFLAGS) $(PIE_FLAGS) $(BITCOIN_SEEDER_INCLUDES) libbitcoin_seeder_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) libbitcoin_seeder_a_SOURCES = \ seeder/bitcoin.cpp \ seeder/bitcoin.h \ seeder/compat.h \ seeder/db.cpp \ seeder/db.h \ seeder/dns.cpp \ seeder/dns.h \ seeder/strlcpy.h \ seeder/util.h nodist_libbitcoin_util_a_SOURCES = $(srcdir)/obj/build.h # # bitcoind binary # bitcoind_SOURCES = bitcoind.cpp bitcoind_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) bitcoind_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) bitcoind_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) if TARGET_WINDOWS bitcoind_SOURCES += bitcoind-res.rc endif bitcoind_LDADD = \ $(LIBBITCOIN_SERVER) \ $(LIBBITCOIN_COMMON) \ $(LIBUNIVALUE) \ $(LIBBITCOIN_UTIL) \ $(LIBBITCOIN_WALLET) \ $(LIBBITCOIN_ZMQ) \ $(LIBBITCOIN_CONSENSUS) \ $(LIBBITCOIN_CRYPTO) \ + $(LIBBITCOIN_CRYPTO_SSE41) \ + $(LIBBITCOIN_CRYPTO_AVX2) \ $(LIBLEVELDB) \ $(LIBLEVELDB_SSE42) \ $(LIBMEMENV) \ $(LIBSECP256K1) bitcoind_LDADD += $(BOOST_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(ZMQ_LIBS) # bitcoin-cli binary # bitcoin_cli_SOURCES = bitcoin-cli.cpp bitcoin_cli_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(EVENT_CFLAGS) bitcoin_cli_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) bitcoin_cli_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) if TARGET_WINDOWS bitcoin_cli_SOURCES += bitcoin-cli-res.rc endif bitcoin_cli_LDADD = \ $(LIBBITCOIN_CLI) \ $(LIBUNIVALUE) \ $(LIBBITCOIN_UTIL) \ - $(LIBBITCOIN_CRYPTO) + $(LIBBITCOIN_CRYPTO) \ + $(LIBBITCOIN_CRYPTO_SSE41) \ + $(LIBBITCOIN_CRYPTO_AVX2) bitcoin_cli_LDADD += $(BOOST_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(EVENT_LIBS) # # bitcoin-seeder binary # bitcoin_seeder_SOURCES = seeder/main.cpp bitcoin_seeder_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_SEEDER_INCLUDES) bitcoin_seeder_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) bitcoin_seeder_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) bitcoin_seeder_LDADD = \ $(LIBBITCOIN_SEEDER) \ $(LIBBITCOIN_COMMON) \ $(LIBBITCOIN_UTIL) \ - $(LIBBITCOIN_CRYPTO) + $(LIBBITCOIN_CRYPTO) \ + $(LIBBITCOIN_CRYPTO_SSE41) \ + $(LIBBITCOIN_CRYPTO_AVX2) bitcoin_seeder_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS) # # bitcoin-tx binary # bitcoin_tx_SOURCES = bitcoin-tx.cpp bitcoin_tx_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) bitcoin_tx_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) bitcoin_tx_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) if TARGET_WINDOWS bitcoin_tx_SOURCES += bitcoin-tx-res.rc endif bitcoin_tx_LDADD = \ $(LIBUNIVALUE) \ $(LIBBITCOIN_COMMON) \ $(LIBBITCOIN_UTIL) \ $(LIBBITCOIN_CONSENSUS) \ $(LIBBITCOIN_CRYPTO) \ + $(LIBBITCOIN_CRYPTO_SSE41) \ + $(LIBBITCOIN_CRYPTO_AVX2) \ $(LIBSECP256K1) bitcoin_tx_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS) # # bitcoinconsensus library # if BUILD_BITCOIN_LIBS include_HEADERS = script/bitcoinconsensus.h libbitcoinconsensus_la_SOURCES = $(crypto_libbitcoin_crypto_a_SOURCES) $(libbitcoin_consensus_a_SOURCES) if GLIBC_BACK_COMPAT libbitcoinconsensus_la_SOURCES += compat/glibc_compat.cpp endif libbitcoinconsensus_la_LDFLAGS = $(AM_LDFLAGS) -no-undefined $(RELDFLAGS) libbitcoinconsensus_la_LIBADD = $(LIBSECP256K1) libbitcoinconsensus_la_CPPFLAGS = $(AM_CPPFLAGS) -I$(builddir)/obj -I$(srcdir)/secp256k1/include -DBUILD_BITCOIN_INTERNAL libbitcoinconsensus_la_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) endif # CTAES_DIST = crypto/ctaes/bench.c CTAES_DIST += crypto/ctaes/ctaes.c CTAES_DIST += crypto/ctaes/ctaes.h CTAES_DIST += crypto/ctaes/README.md CTAES_DIST += crypto/ctaes/test.c CLEANFILES = $(EXTRA_LIBRARIES) CLEANFILES += *.gcda *.gcno CLEANFILES += compat/*.gcda compat/*.gcno CLEANFILES += consensus/*.gcda consensus/*.gcno CLEANFILES += crypto/*.gcda crypto/*.gcno CLEANFILES += policy/*.gcda policy/*.gcno CLEANFILES += primitives/*.gcda primitives/*.gcno CLEANFILES += script/*.gcda script/*.gcno CLEANFILES += support/*.gcda support/*.gcno CLEANFILES += univalue/*.gcda univalue/*.gcno CLEANFILES += wallet/*.gcda wallet/*.gcno CLEANFILES += wallet/test/*.gcda wallet/test/*.gcno CLEANFILES += zmq/*.gcda zmq/*.gcno DISTCLEANFILES = obj/build.h EXTRA_DIST = $(CTAES_DIST) clean-local: -$(MAKE) -C secp256k1 clean -$(MAKE) -C univalue clean -rm -f leveldb/*/*.gcda leveldb/*/*.gcno leveldb/helpers/memenv/*.gcda leveldb/helpers/memenv/*.gcno -rm -rf test/__pycache__ .rc.o: @test -f $(WINDRES) ## FIXME: How to get the appropriate modulename_CPPFLAGS in here? $(AM_V_GEN) $(WINDRES) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CPPFLAGS) -DWINDRES_PREPROC -i $< -o $@ .mm.o: $(AM_V_CXX) $(OBJCXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CXXFLAGS) $(QT_INCLUDES) $(AM_CXXFLAGS) $(PIE_FLAGS) $(CXXFLAGS) -c -o $@ $< check-symbols: $(bin_PROGRAMS) if GLIBC_BACK_COMPAT @echo "Checking glibc back compat..." $(AM_V_at) READELF=$(READELF) CPPFILT=$(CPPFILT) $(top_srcdir)/contrib/devtools/symbol-check.py < $(bin_PROGRAMS) endif check-security: $(bin_PROGRAMS) if HARDEN @echo "Checking binary security..." $(AM_V_at) READELF=$(READELF) OBJDUMP=$(OBJDUMP) $(top_srcdir)/contrib/devtools/security-check.py < $(bin_PROGRAMS) endif %.pb.cc %.pb.h: %.proto @test -f $(PROTOC) $(AM_V_GEN) $(PROTOC) --cpp_out=$(@D) --proto_path=$( "$@.new" && mv -f "$@.new" "$@" @echo "Generated $@" diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include index 960ae4bc8f..11f72b2afd 100644 --- a/src/Makefile.qt.include +++ b/src/Makefile.qt.include @@ -1,463 +1,463 @@ # Copyright (c) 2013-2016 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. bin_PROGRAMS += qt/bitcoin-qt EXTRA_LIBRARIES += qt/libbitcoinqt.a # bitcoin qt core # QT_TS = \ qt/locale/bitcoin_af.ts \ qt/locale/bitcoin_af_ZA.ts \ qt/locale/bitcoin_ar.ts \ qt/locale/bitcoin_be_BY.ts \ qt/locale/bitcoin_bg_BG.ts \ qt/locale/bitcoin_bg.ts \ qt/locale/bitcoin_ca_ES.ts \ qt/locale/bitcoin_ca.ts \ qt/locale/bitcoin_ca@valencia.ts \ qt/locale/bitcoin_cs.ts \ qt/locale/bitcoin_cy.ts \ qt/locale/bitcoin_da.ts \ qt/locale/bitcoin_de.ts \ qt/locale/bitcoin_el_GR.ts \ qt/locale/bitcoin_el.ts \ qt/locale/bitcoin_en_GB.ts \ qt/locale/bitcoin_en.ts \ qt/locale/bitcoin_eo.ts \ qt/locale/bitcoin_es_AR.ts \ qt/locale/bitcoin_es_CL.ts \ qt/locale/bitcoin_es_CO.ts \ qt/locale/bitcoin_es_DO.ts \ qt/locale/bitcoin_es_ES.ts \ qt/locale/bitcoin_es_MX.ts \ qt/locale/bitcoin_es.ts \ qt/locale/bitcoin_es_UY.ts \ qt/locale/bitcoin_es_VE.ts \ qt/locale/bitcoin_et_EE.ts \ qt/locale/bitcoin_et.ts \ qt/locale/bitcoin_eu_ES.ts \ qt/locale/bitcoin_fa_IR.ts \ qt/locale/bitcoin_fa.ts \ qt/locale/bitcoin_fi.ts \ qt/locale/bitcoin_fr_CA.ts \ qt/locale/bitcoin_fr_FR.ts \ qt/locale/bitcoin_fr.ts \ qt/locale/bitcoin_gl.ts \ qt/locale/bitcoin_he.ts \ qt/locale/bitcoin_hi_IN.ts \ qt/locale/bitcoin_hr.ts \ qt/locale/bitcoin_hu.ts \ qt/locale/bitcoin_id_ID.ts \ qt/locale/bitcoin_it_IT.ts \ qt/locale/bitcoin_it.ts \ qt/locale/bitcoin_ja.ts \ qt/locale/bitcoin_ka.ts \ qt/locale/bitcoin_kk_KZ.ts \ qt/locale/bitcoin_ko_KR.ts \ qt/locale/bitcoin_ku_IQ.ts \ qt/locale/bitcoin_ky.ts \ qt/locale/bitcoin_la.ts \ qt/locale/bitcoin_lt.ts \ qt/locale/bitcoin_lv_LV.ts \ qt/locale/bitcoin_mk_MK.ts \ qt/locale/bitcoin_mn.ts \ qt/locale/bitcoin_ms_MY.ts \ qt/locale/bitcoin_nb.ts \ qt/locale/bitcoin_ne.ts \ qt/locale/bitcoin_nl.ts \ qt/locale/bitcoin_pam.ts \ qt/locale/bitcoin_pl.ts \ qt/locale/bitcoin_pt_BR.ts \ qt/locale/bitcoin_pt_PT.ts \ qt/locale/bitcoin_ro_RO.ts \ qt/locale/bitcoin_ro.ts \ qt/locale/bitcoin_ru_RU.ts \ qt/locale/bitcoin_ru.ts \ qt/locale/bitcoin_sk.ts \ qt/locale/bitcoin_sl_SI.ts \ qt/locale/bitcoin_sq.ts \ qt/locale/bitcoin_sr@latin.ts \ qt/locale/bitcoin_sr.ts \ qt/locale/bitcoin_sv.ts \ qt/locale/bitcoin_ta.ts \ qt/locale/bitcoin_th_TH.ts \ qt/locale/bitcoin_tr_TR.ts \ qt/locale/bitcoin_tr.ts \ qt/locale/bitcoin_uk.ts \ qt/locale/bitcoin_ur_PK.ts \ qt/locale/bitcoin_uz@Cyrl.ts \ qt/locale/bitcoin_vi.ts \ qt/locale/bitcoin_vi_VN.ts \ qt/locale/bitcoin_zh_CN.ts \ qt/locale/bitcoin_zh_HK.ts \ qt/locale/bitcoin_zh.ts \ qt/locale/bitcoin_zh_TW.ts QT_FORMS_UI = \ qt/forms/addressbookpage.ui \ qt/forms/askpassphrasedialog.ui \ qt/forms/coincontroldialog.ui \ qt/forms/editaddressdialog.ui \ qt/forms/helpmessagedialog.ui \ qt/forms/intro.ui \ qt/forms/modaloverlay.ui \ qt/forms/openuridialog.ui \ qt/forms/optionsdialog.ui \ qt/forms/overviewpage.ui \ qt/forms/receivecoinsdialog.ui \ qt/forms/receiverequestdialog.ui \ qt/forms/debugwindow.ui \ qt/forms/sendcoinsdialog.ui \ qt/forms/sendcoinsentry.ui \ qt/forms/signverifymessagedialog.ui \ qt/forms/transactiondescdialog.ui QT_MOC_CPP = \ qt/moc_addressbookpage.cpp \ qt/moc_addresstablemodel.cpp \ qt/moc_askpassphrasedialog.cpp \ qt/moc_bantablemodel.cpp \ qt/moc_bitcoinaddressvalidator.cpp \ qt/moc_bitcoinamountfield.cpp \ qt/moc_bitcoingui.cpp \ qt/moc_bitcoinunits.cpp \ qt/moc_clientmodel.cpp \ qt/moc_coincontroldialog.cpp \ qt/moc_coincontroltreewidget.cpp \ qt/moc_csvmodelwriter.cpp \ qt/moc_editaddressdialog.cpp \ qt/moc_guiutil.cpp \ qt/moc_intro.cpp \ qt/moc_macdockiconhandler.cpp \ qt/moc_macnotificationhandler.cpp \ qt/moc_modaloverlay.cpp \ qt/moc_notificator.cpp \ qt/moc_openuridialog.cpp \ qt/moc_optionsdialog.cpp \ qt/moc_optionsmodel.cpp \ qt/moc_overviewpage.cpp \ qt/moc_peertablemodel.cpp \ qt/moc_paymentserver.cpp \ qt/moc_qvalidatedlineedit.cpp \ qt/moc_qvaluecombobox.cpp \ qt/moc_receivecoinsdialog.cpp \ qt/moc_receiverequestdialog.cpp \ qt/moc_recentrequeststablemodel.cpp \ qt/moc_rpcconsole.cpp \ qt/moc_sendcoinsdialog.cpp \ qt/moc_sendcoinsentry.cpp \ qt/moc_signverifymessagedialog.cpp \ qt/moc_splashscreen.cpp \ qt/moc_trafficgraphwidget.cpp \ qt/moc_transactiondesc.cpp \ qt/moc_transactiondescdialog.cpp \ qt/moc_transactionfilterproxy.cpp \ qt/moc_transactiontablemodel.cpp \ qt/moc_transactionview.cpp \ qt/moc_utilitydialog.cpp \ qt/moc_walletframe.cpp \ qt/moc_walletmodel.cpp \ qt/moc_walletview.cpp BITCOIN_MM = \ qt/macdockiconhandler.mm \ qt/macnotificationhandler.mm QT_MOC = \ qt/bitcoin.moc \ qt/bitcoinamountfield.moc \ qt/intro.moc \ qt/overviewpage.moc \ qt/rpcconsole.moc QT_QRC_CPP = qt/qrc_bitcoin.cpp QT_QRC = qt/bitcoin.qrc QT_QRC_LOCALE_CPP = qt/qrc_bitcoin_locale.cpp QT_QRC_LOCALE = qt/bitcoin_locale.qrc PROTOBUF_CC = qt/paymentrequest.pb.cc PROTOBUF_H = qt/paymentrequest.pb.h PROTOBUF_PROTO = qt/paymentrequest.proto BITCOIN_QT_H = \ qt/addressbookpage.h \ qt/addresstablemodel.h \ qt/askpassphrasedialog.h \ qt/bantablemodel.h \ qt/bitcoinaddressvalidator.h \ qt/bitcoinamountfield.h \ qt/bitcoingui.h \ qt/bitcoinunits.h \ qt/clientmodel.h \ qt/coincontroldialog.h \ qt/coincontroltreewidget.h \ qt/csvmodelwriter.h \ qt/editaddressdialog.h \ qt/guiconstants.h \ qt/guiutil.h \ qt/intro.h \ qt/macdockiconhandler.h \ qt/macnotificationhandler.h \ qt/modaloverlay.h \ qt/networkstyle.h \ qt/notificator.h \ qt/openuridialog.h \ qt/optionsdialog.h \ qt/optionsmodel.h \ qt/overviewpage.h \ qt/paymentrequestplus.h \ qt/paymentserver.h \ qt/peertablemodel.h \ qt/platformstyle.h \ qt/qvalidatedlineedit.h \ qt/qvaluecombobox.h \ qt/receivecoinsdialog.h \ qt/receiverequestdialog.h \ qt/recentrequeststablemodel.h \ qt/rpcconsole.h \ qt/sendcoinsdialog.h \ qt/sendcoinsentry.h \ qt/signverifymessagedialog.h \ qt/splashscreen.h \ qt/trafficgraphwidget.h \ qt/transactiondesc.h \ qt/transactiondescdialog.h \ qt/transactionfilterproxy.h \ qt/transactionrecord.h \ qt/transactiontablemodel.h \ qt/transactionview.h \ qt/utilitydialog.h \ qt/walletframe.h \ qt/walletmodel.h \ qt/walletmodeltransaction.h \ qt/walletview.h \ qt/winshutdownmonitor.h RES_ICONS = \ qt/res/icons/add.png \ qt/res/icons/address-book.png \ qt/res/icons/about.png \ qt/res/icons/about_qt.png \ qt/res/icons/bitcoin.ico \ qt/res/icons/bitcoin_testnet.ico \ qt/res/icons/bitcoin.png \ qt/res/icons/chevron.png \ qt/res/icons/clock1.png \ qt/res/icons/clock2.png \ qt/res/icons/clock3.png \ qt/res/icons/clock4.png \ qt/res/icons/clock5.png \ qt/res/icons/configure.png \ qt/res/icons/connect0.png \ qt/res/icons/connect1.png \ qt/res/icons/connect2.png \ qt/res/icons/connect3.png \ qt/res/icons/connect4.png \ qt/res/icons/debugwindow.png \ qt/res/icons/edit.png \ qt/res/icons/editcopy.png \ qt/res/icons/editpaste.png \ qt/res/icons/export.png \ qt/res/icons/eye.png \ qt/res/icons/eye_minus.png \ qt/res/icons/eye_plus.png \ qt/res/icons/filesave.png \ qt/res/icons/fontbigger.png \ qt/res/icons/fontsmaller.png \ qt/res/icons/hd_disabled.png \ qt/res/icons/hd_enabled.png \ qt/res/icons/history.png \ qt/res/icons/info.png \ qt/res/icons/key.png \ qt/res/icons/lock_closed.png \ qt/res/icons/lock_open.png \ qt/res/icons/network_disabled.png \ qt/res/icons/open.png \ qt/res/icons/overview.png \ qt/res/icons/quit.png \ qt/res/icons/receive.png \ qt/res/icons/remove.png \ qt/res/icons/send.png \ qt/res/icons/synced.png \ qt/res/icons/transaction0.png \ qt/res/icons/transaction2.png \ qt/res/icons/transaction_abandoned.png \ qt/res/icons/transaction_conflicted.png \ qt/res/icons/tx_inout.png \ qt/res/icons/tx_input.png \ qt/res/icons/tx_output.png \ qt/res/icons/tx_mined.png \ qt/res/icons/warning.png \ qt/res/icons/verify.png BITCOIN_QT_BASE_CPP = \ qt/bantablemodel.cpp \ qt/bitcoinaddressvalidator.cpp \ qt/bitcoinamountfield.cpp \ qt/bitcoingui.cpp \ qt/bitcoinunits.cpp \ qt/clientmodel.cpp \ qt/csvmodelwriter.cpp \ qt/guiutil.cpp \ qt/intro.cpp \ qt/modaloverlay.cpp \ qt/networkstyle.cpp \ qt/notificator.cpp \ qt/optionsdialog.cpp \ qt/optionsmodel.cpp \ qt/peertablemodel.cpp \ qt/platformstyle.cpp \ qt/qvalidatedlineedit.cpp \ qt/qvaluecombobox.cpp \ qt/rpcconsole.cpp \ qt/splashscreen.cpp \ qt/trafficgraphwidget.cpp \ qt/utilitydialog.cpp BITCOIN_QT_WINDOWS_CPP = qt/winshutdownmonitor.cpp BITCOIN_QT_WALLET_CPP = \ qt/addressbookpage.cpp \ qt/addresstablemodel.cpp \ qt/askpassphrasedialog.cpp \ qt/coincontroldialog.cpp \ qt/coincontroltreewidget.cpp \ qt/editaddressdialog.cpp \ qt/openuridialog.cpp \ qt/overviewpage.cpp \ qt/paymentrequestplus.cpp \ qt/paymentserver.cpp \ qt/receivecoinsdialog.cpp \ qt/receiverequestdialog.cpp \ qt/recentrequeststablemodel.cpp \ qt/sendcoinsdialog.cpp \ qt/sendcoinsentry.cpp \ qt/signverifymessagedialog.cpp \ qt/transactiondesc.cpp \ qt/transactiondescdialog.cpp \ qt/transactionfilterproxy.cpp \ qt/transactionrecord.cpp \ qt/transactiontablemodel.cpp \ qt/transactionview.cpp \ qt/walletframe.cpp \ qt/walletmodel.cpp \ qt/walletmodeltransaction.cpp \ qt/walletview.cpp BITCOIN_QT_CPP = $(BITCOIN_QT_BASE_CPP) if TARGET_WINDOWS BITCOIN_QT_CPP += $(BITCOIN_QT_WINDOWS_CPP) endif if ENABLE_WALLET BITCOIN_QT_CPP += $(BITCOIN_QT_WALLET_CPP) endif RES_IMAGES = RES_MOVIES = $(wildcard $(srcdir)/qt/res/movies/spinner-*.png) BITCOIN_RC = qt/res/bitcoin-qt-res.rc BITCOIN_QT_INCLUDES = -I$(builddir)/qt -I$(srcdir)/qt -I$(srcdir)/qt/forms \ -I$(builddir)/qt/forms -DQT_NO_KEYWORDS qt_libbitcoinqt_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(BITCOIN_QT_INCLUDES) \ $(QT_INCLUDES) $(QT_DBUS_INCLUDES) $(PROTOBUF_CFLAGS) $(QR_CFLAGS) qt_libbitcoinqt_a_CXXFLAGS = $(AM_CXXFLAGS) $(QT_PIE_FLAGS) qt_libbitcoinqt_a_SOURCES = $(BITCOIN_QT_CPP) $(BITCOIN_QT_H) $(QT_FORMS_UI) \ $(QT_QRC) $(QT_QRC_LOCALE) $(QT_TS) $(PROTOBUF_PROTO) $(RES_ICONS) $(RES_IMAGES) $(RES_MOVIES) nodist_qt_libbitcoinqt_a_SOURCES = $(QT_MOC_CPP) $(QT_MOC) $(PROTOBUF_CC) \ $(PROTOBUF_H) $(QT_QRC_CPP) $(QT_QRC_LOCALE_CPP) # forms/foo.h -> forms/ui_foo.h QT_FORMS_H=$(join $(dir $(QT_FORMS_UI)),$(addprefix ui_, $(notdir $(QT_FORMS_UI:.ui=.h)))) # Most files will depend on the forms and moc files as includes. Generate them # before anything else. $(QT_MOC): $(QT_FORMS_H) $(qt_libbitcoinqt_a_OBJECTS) $(qt_bitcoin_qt_OBJECTS) : | $(QT_MOC) #Generating these with a half-written protobuf header leads to wacky results. #This makes sure it's done. $(QT_MOC): $(PROTOBUF_H) $(QT_MOC_CPP): $(PROTOBUF_H) # bitcoin-qt binary # qt_bitcoin_qt_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(BITCOIN_QT_INCLUDES) \ $(QT_INCLUDES) $(PROTOBUF_CFLAGS) $(QR_CFLAGS) qt_bitcoin_qt_CXXFLAGS = $(AM_CXXFLAGS) $(QT_PIE_FLAGS) qt_bitcoin_qt_SOURCES = qt/bitcoin.cpp if TARGET_DARWIN qt_bitcoin_qt_SOURCES += $(BITCOIN_MM) endif if TARGET_WINDOWS qt_bitcoin_qt_SOURCES += $(BITCOIN_RC) endif qt_bitcoin_qt_LDADD = qt/libbitcoinqt.a $(LIBBITCOIN_SERVER) if ENABLE_WALLET qt_bitcoin_qt_LDADD += $(LIBBITCOIN_WALLET) endif if ENABLE_ZMQ qt_bitcoin_qt_LDADD += $(LIBBITCOIN_ZMQ) $(ZMQ_LIBS) endif -qt_bitcoin_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBUNIVALUE) $(LIBLEVELDB) $(LIBLEVELDB_SSE42) $(LIBMEMENV) \ +qt_bitcoin_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBBITCOIN_CRYPTO_SSE41) $(LIBBITCOIN_CRYPTO_AVX2) $(LIBUNIVALUE) $(LIBLEVELDB) $(LIBLEVELDB_SSE42) $(LIBMEMENV) \ $(BOOST_LIBS) $(QT_LIBS) $(QT_DBUS_LIBS) $(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(LIBSECP256K1) \ $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) qt_bitcoin_qt_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(QT_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) qt_bitcoin_qt_LIBTOOLFLAGS = --tag CXX #locale/foo.ts -> locale/foo.qm QT_QM=$(QT_TS:.ts=.qm) SECONDARY: $(QT_QM) $(srcdir)/qt/bitcoinstrings.cpp: $(libbitcoin_server_a_SOURCES) $(libbitcoin_wallet_a_SOURCES) $(libbitcoin_common_a_SOURCES) $(libbitcoin_zmq_a_SOURCES) $(libbitcoin_consensus_a_SOURCES) $(libbitcoin_util_a_SOURCES) @test -n $(XGETTEXT) || echo "xgettext is required for updating translations" $(AM_V_GEN) cd $(srcdir); XGETTEXT=$(XGETTEXT) PACKAGE_NAME="$(PACKAGE_NAME)" COPYRIGHT_HOLDERS="$(COPYRIGHT_HOLDERS)" COPYRIGHT_HOLDERS_SUBSTITUTION="$(COPYRIGHT_HOLDERS_SUBSTITUTION)" $(PYTHON) ../share/qt/extract_strings_qt.py $^ translate: $(srcdir)/qt/bitcoinstrings.cpp $(QT_FORMS_UI) $(QT_FORMS_UI) $(BITCOIN_QT_BASE_CPP) qt/bitcoin.cpp $(BITCOIN_QT_WINDOWS_CPP) $(BITCOIN_QT_WALLET_CPP) $(BITCOIN_QT_H) $(BITCOIN_MM) @test -n $(LUPDATE) || echo "lupdate is required for updating translations" $(AM_V_GEN) QT_SELECT=$(QT_SELECT) $(LUPDATE) $^ -locations relative -no-obsolete -ts $(srcdir)/qt/locale/bitcoin_en.ts $(QT_QRC_LOCALE_CPP): $(QT_QRC_LOCALE) $(QT_QM) @test -f $(RCC) @cp -f $< $(@D)/temp_$( $@ @rm $(@D)/temp_$( $@ CLEAN_QT = $(nodist_qt_libbitcoinqt_a_SOURCES) $(QT_QM) $(QT_FORMS_H) qt/*.gcda qt/*.gcno CLEANFILES += $(CLEAN_QT) bitcoin_qt_clean: FORCE rm -f $(CLEAN_QT) $(qt_libbitcoinqt_a_OBJECTS) $(qt_bitcoin_qt_OBJECTS) qt/bitcoin-qt$(EXEEXT) $(LIBBITCOINQT) bitcoin_qt : qt/bitcoin-qt$(EXEEXT) ui_%.h: %.ui @test -f $(UIC) @$(MKDIR_P) $(@D) $(AM_V_GEN) QT_SELECT=$(QT_SELECT) $(UIC) -o $@ $< || (echo "Error creating $@"; false) %.moc: %.cpp $(AM_V_GEN) QT_SELECT=$(QT_SELECT) $(MOC) $(DEFAULT_INCLUDES) $(QT_INCLUDES) $(MOC_DEFS) $< | \ $(SED) -e '/^\*\*.*Created:/d' -e '/^\*\*.*by:/d' > $@ moc_%.cpp: %.h $(AM_V_GEN) QT_SELECT=$(QT_SELECT) $(MOC) $(DEFAULT_INCLUDES) $(QT_INCLUDES) $(MOC_DEFS) $< | \ $(SED) -e '/^\*\*.*Created:/d' -e '/^\*\*.*by:/d' > $@ %.qm: %.ts @test -f $(LRELEASE) @$(MKDIR_P) $(@D) $(AM_V_GEN) QT_SELECT=$(QT_SELECT) $(LRELEASE) -silent $< -qm $@ diff --git a/src/Makefile.qttest.include b/src/Makefile.qttest.include index 4e2acd5252..7fd3c7f082 100644 --- a/src/Makefile.qttest.include +++ b/src/Makefile.qttest.include @@ -1,84 +1,84 @@ # Copyright (c) 2013-2016 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. bin_PROGRAMS += qt/test/test_bitcoin-qt TESTS += qt/test/test_bitcoin-qt TEST_QT_MOC_CPP = \ qt/test/moc_bitcoinaddressvalidatortests.cpp \ qt/test/moc_compattests.cpp \ qt/test/moc_guiutiltests.cpp \ qt/test/moc_rpcnestedtests.cpp \ qt/test/moc_uritests.cpp if ENABLE_WALLET TEST_QT_MOC_CPP += \ qt/test/moc_paymentservertests.cpp \ qt/test/moc_wallettests.cpp endif TEST_QT_H = \ qt/test/bitcoinaddressvalidatortests.h \ qt/test/compattests.h \ qt/test/guiutiltests.h \ qt/test/rpcnestedtests.h \ qt/test/uritests.h \ qt/test/paymentrequestdata.h \ qt/test/paymentservertests.h \ qt/test/wallettests.h TEST_BITCOIN_CPP = \ test/test_bitcoin.cpp \ test/testutil.cpp TEST_BITCOIN_H = \ test/test_bitcoin.h \ test/testutil.h qt_test_test_bitcoin_qt_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(BITCOIN_QT_INCLUDES) \ $(QT_INCLUDES) $(QT_TEST_INCLUDES) $(PROTOBUF_CFLAGS) qt_test_test_bitcoin_qt_SOURCES = \ qt/test/bitcoinaddressvalidatortests.cpp \ qt/test/compattests.cpp \ qt/test/guiutiltests.cpp \ qt/test/rpcnestedtests.cpp \ qt/test/test_main.cpp \ qt/test/uritests.cpp \ $(TEST_QT_H) \ $(TEST_BITCOIN_CPP) \ $(TEST_BITCOIN_H) if ENABLE_WALLET qt_test_test_bitcoin_qt_SOURCES += \ qt/test/paymentservertests.cpp \ qt/test/wallettests.cpp endif nodist_qt_test_test_bitcoin_qt_SOURCES = $(TEST_QT_MOC_CPP) qt_test_test_bitcoin_qt_LDADD = $(LIBBITCOINQT) $(LIBBITCOIN_SERVER) if ENABLE_WALLET qt_test_test_bitcoin_qt_LDADD += $(LIBBITCOIN_WALLET) endif if ENABLE_ZMQ qt_test_test_bitcoin_qt_LDADD += $(LIBBITCOIN_ZMQ) $(ZMQ_LIBS) endif -qt_test_test_bitcoin_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBUNIVALUE) $(LIBLEVELDB) \ +qt_test_test_bitcoin_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBBITCOIN_CRYPTO_SSE41) $(LIBBITCOIN_CRYPTO_AVX2) $(LIBUNIVALUE) $(LIBLEVELDB) \ $(LIBLEVELDB_SSE42) $(LIBMEMENV) $(BOOST_LIBS) $(QT_DBUS_LIBS) $(QT_TEST_LIBS) $(QT_LIBS) \ $(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(LIBSECP256K1) \ $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) qt_test_test_bitcoin_qt_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(QT_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) qt_test_test_bitcoin_qt_CXXFLAGS = $(AM_CXXFLAGS) $(QT_PIE_FLAGS) CLEAN_BITCOIN_QT_TEST = $(TEST_QT_MOC_CPP) qt/test/*.gcda qt/test/*.gcno CLEANFILES += $(CLEAN_BITCOIN_QT_TEST) test_bitcoin_qt : qt/test/test_bitcoin-qt$(EXEEXT) test_bitcoin_qt_check : qt/test/test_bitcoin-qt$(EXEEXT) FORCE $(MAKE) check-TESTS TESTS=$^ test_bitcoin_qt_clean: FORCE rm -f $(CLEAN_BITCOIN_QT_TEST) $(qt_test_test_bitcoin_qt_OBJECTS) diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 4a64145c4d..f96ce0ac3b 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -1,193 +1,196 @@ # Copyright (c) 2013-2016 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. TESTS += test/test_bitcoin LOG_DRIVER = $(srcdir)/test/test-bitcoin-driver EXTRA_DIST += test/test-bitcoin-driver bin_PROGRAMS += test/test_bitcoin noinst_PROGRAMS += test/test_bitcoin_fuzzy TEST_SRCDIR = test TEST_BINARY=test/test_bitcoin$(EXEEXT) JSON_TEST_FILES = \ test/data/script_tests.json \ test/data/base58_keys_valid.json \ test/data/base58_encode_decode.json \ test/data/base58_keys_invalid.json \ test/data/tx_invalid.json \ test/data/tx_valid.json \ test/data/sighash.json RAW_TEST_FILES = GENERATED_TEST_FILES = $(JSON_TEST_FILES:.json=.json.h) $(RAW_TEST_FILES:.raw=.raw.h) # test_bitcoin binary # BITCOIN_TESTS =\ test/arith_uint256_tests.cpp \ test/scriptnum10.h \ test/addrman_tests.cpp \ test/amount_tests.cpp \ test/allocator_tests.cpp \ test/base32_tests.cpp \ test/base58_tests.cpp \ test/base64_tests.cpp \ test/bip32_tests.cpp \ test/blockcheck_tests.cpp \ test/blockencodings_tests.cpp \ test/blockindex_tests.cpp \ test/blockstatus_tests.cpp \ test/bloom_tests.cpp \ test/bswap_tests.cpp \ test/cashaddr_tests.cpp \ test/cashaddrenc_tests.cpp \ test/checkdatasig_tests.cpp \ test/checkpoints_tests.cpp \ test/checkqueue_tests.cpp \ test/coins_tests.cpp \ test/compress_tests.cpp \ test/config_tests.cpp \ test/core_io_tests.cpp \ test/crypto_tests.cpp \ test/cuckoocache_tests.cpp \ test/dbwrapper_tests.cpp \ test/DoS_tests.cpp \ test/dstencode_tests.cpp \ test/excessiveblock_tests.cpp \ test/feerate_tests.cpp \ test/getarg_tests.cpp \ test/hash_tests.cpp \ test/inv_tests.cpp \ test/jsonutil.cpp \ test/jsonutil.h \ test/key_tests.cpp \ test/limitedmap_tests.cpp \ test/main_tests.cpp \ test/mempool_tests.cpp \ test/merkle_tests.cpp \ test/miner_tests.cpp \ test/monolith_opcodes.cpp \ test/multisig_tests.cpp \ test/net_tests.cpp \ test/netbase_tests.cpp \ test/pmt_tests.cpp \ test/policyestimator_tests.cpp \ test/pow_tests.cpp \ test/prevector_tests.cpp \ test/raii_event_tests.cpp \ test/random_tests.cpp \ test/reverselock_tests.cpp \ test/rpc_tests.cpp \ test/sanity_tests.cpp \ test/scheduler_tests.cpp \ test/script_commitment_tests.cpp \ test/script_P2SH_tests.cpp \ test/script_tests.cpp \ test/scriptflags.cpp \ test/scriptflags.h \ test/scriptnum_tests.cpp \ test/serialize_tests.cpp \ test/sigencoding_tests.cpp \ test/sighash_tests.cpp \ test/sighashtype_tests.cpp \ test/sigopcount_tests.cpp \ test/sigutil.cpp \ test/sigutil.h \ test/skiplist_tests.cpp \ test/streams_tests.cpp \ test/test_bitcoin.cpp \ test/test_bitcoin.h \ test/test_bitcoin_main.cpp \ test/testutil.cpp \ test/testutil.h \ test/timedata_tests.cpp \ test/transaction_tests.cpp \ test/txvalidationcache_tests.cpp \ test/versionbits_tests.cpp \ test/uint256_tests.cpp \ test/undo_tests.cpp \ test/univalue_tests.cpp \ test/util_tests.cpp \ test/validation_tests.cpp \ test/work_comparator_tests.cpp if ENABLE_WALLET BITCOIN_TESTS += \ wallet/test/wallet_test_fixture.cpp \ wallet/test/wallet_test_fixture.h \ wallet/test/accounting_tests.cpp \ wallet/test/wallet_tests.cpp \ wallet/test/walletdb_tests.cpp \ wallet/test/crypto_tests.cpp endif test_test_bitcoin_SOURCES = $(BITCOIN_TESTS) $(JSON_TEST_FILES) $(RAW_TEST_FILES) test_test_bitcoin_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -I$(builddir)/test/ $(TESTDEFS) $(EVENT_CFLAGS) test_test_bitcoin_LDADD = if ENABLE_WALLET test_test_bitcoin_LDADD += $(LIBBITCOIN_WALLET) endif -test_test_bitcoin_LDADD += $(LIBBITCOIN_SERVER) $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBUNIVALUE) \ + +test_test_bitcoin_LDADD += $(LIBBITCOIN_SERVER) $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBBITCOIN_CRYPTO_SSE41) $(LIBBITCOIN_CRYPTO_AVX2) $(LIBUNIVALUE) \ $(LIBLEVELDB) $(LIBLEVELDB_SSE42) $(LIBMEMENV) $(BOOST_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIB) $(LIBSECP256K1) $(EVENT_LIBS) $(EVENT_PTHREADS_LIBS) test_test_bitcoin_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) test_test_bitcoin_LDADD += $(LIBBITCOIN_CONSENSUS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) test_test_bitcoin_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) -static if ENABLE_ZMQ test_test_bitcoin_LDADD += $(ZMQ_LIBS) endif # # test_bitcoin_fuzzy binary # test_test_bitcoin_fuzzy_SOURCES = test/test_bitcoin_fuzzy.cpp test_test_bitcoin_fuzzy_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) test_test_bitcoin_fuzzy_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) test_test_bitcoin_fuzzy_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) test_test_bitcoin_fuzzy_LDADD = \ $(LIBUNIVALUE) \ $(LIBBITCOIN_SERVER) \ $(LIBBITCOIN_COMMON) \ $(LIBBITCOIN_UTIL) \ $(LIBBITCOIN_CONSENSUS) \ $(LIBBITCOIN_CRYPTO) \ + $(LIBBITCOIN_CRYPTO_SSE41) \ + $(LIBBITCOIN_CRYPTO_AVX2) \ $(LIBSECP256K1) test_test_bitcoin_fuzzy_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS) # nodist_test_test_bitcoin_SOURCES = $(GENERATED_TEST_FILES) $(BITCOIN_TESTS): $(GENERATED_TEST_FILES) CLEAN_BITCOIN_TEST = test/*.gcda test/*.gcno $(GENERATED_TEST_FILES) CLEANFILES += $(CLEAN_BITCOIN_TEST) bitcoin_test: $(TEST_BINARY) bitcoin_test_check: $(TEST_BINARY) FORCE $(MAKE) check-TESTS TESTS=$^ bitcoin_test_clean : FORCE rm -f $(CLEAN_BITCOIN_TEST) $(test_test_bitcoin_OBJECTS) $(TEST_BINARY) check-local: @echo "Running test/util/bitcoin-util-test.py..." $(top_builddir)/test/util/bitcoin-util-test.py $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C secp256k1 check if EMBEDDED_UNIVALUE $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C univalue check endif %.json.h: %.json @$(MKDIR_P) $(@D) @{ \ echo "namespace json_tests{" && \ echo "static unsigned const char $(*F)[] = {" && \ $(HEXDUMP) -v -e '8/1 "0x%02x, "' -e '"\n"' $< | $(SED) -e 's/0x ,//g' && \ echo "};};"; \ } > "$@.new" && mv -f "$@.new" "$@" @echo "Generated $@" diff --git a/src/bench/crypto_hash.cpp b/src/bench/crypto_hash.cpp index a3213c70a1..3ab00d7ce0 100644 --- a/src/bench/crypto_hash.cpp +++ b/src/bench/crypto_hash.cpp @@ -1,88 +1,96 @@ // Copyright (c) 2016 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include #include "bench.h" #include "bloom.h" #include "crypto/ripemd160.h" #include "crypto/sha1.h" #include "crypto/sha256.h" #include "crypto/sha512.h" #include "hash.h" #include "random.h" #include "uint256.h" #include "utiltime.h" /* Number of bytes to hash per iteration */ static const uint64_t BUFFER_SIZE = 1000 * 1000; static void RIPEMD160(benchmark::State &state) { uint8_t hash[CRIPEMD160::OUTPUT_SIZE]; std::vector in(BUFFER_SIZE, 0); while (state.KeepRunning()) CRIPEMD160().Write(in.data(), in.size()).Finalize(hash); } static void SHA1(benchmark::State &state) { uint8_t hash[CSHA1::OUTPUT_SIZE]; std::vector in(BUFFER_SIZE, 0); while (state.KeepRunning()) CSHA1().Write(in.data(), in.size()).Finalize(hash); } static void SHA256(benchmark::State &state) { uint8_t hash[CSHA256::OUTPUT_SIZE]; std::vector in(BUFFER_SIZE, 0); while (state.KeepRunning()) CSHA256().Write(in.data(), in.size()).Finalize(hash); } static void SHA256_32b(benchmark::State &state) { std::vector in(32, 0); while (state.KeepRunning()) { CSHA256().Write(in.data(), in.size()).Finalize(in.data()); } } +static void SHA256D64_1024(benchmark::State &state) { + std::vector in(64 * 1024, 0); + while (state.KeepRunning()) { + SHA256D64(in.data(), in.data(), 1024); + } +} + static void SHA512(benchmark::State &state) { uint8_t hash[CSHA512::OUTPUT_SIZE]; std::vector in(BUFFER_SIZE, 0); while (state.KeepRunning()) CSHA512().Write(in.data(), in.size()).Finalize(hash); } static void SipHash_32b(benchmark::State &state) { uint256 x; uint64_t k1 = 0; while (state.KeepRunning()) { *((uint64_t *)x.begin()) = SipHashUint256(0, ++k1, x); } } static void FastRandom_32bit(benchmark::State &state) { FastRandomContext rng(true); uint32_t x = 0; while (state.KeepRunning()) { x += rng.rand32(); } } static void FastRandom_1bit(benchmark::State &state) { FastRandomContext rng(true); uint32_t x = 0; while (state.KeepRunning()) { x += rng.randbool(); } } BENCHMARK(RIPEMD160, 440); BENCHMARK(SHA1, 570); BENCHMARK(SHA256, 340); BENCHMARK(SHA512, 330); BENCHMARK(SHA256_32b, 4700 * 1000); BENCHMARK(SipHash_32b, 40 * 1000 * 1000); +BENCHMARK(SHA256D64_1024, 7400); BENCHMARK(FastRandom_32bit, 110 * 1000 * 1000); BENCHMARK(FastRandom_1bit, 440 * 1000 * 1000); diff --git a/src/bench/merkle_root.cpp b/src/bench/merkle_root.cpp new file mode 100644 index 0000000000..4db163ffde --- /dev/null +++ b/src/bench/merkle_root.cpp @@ -0,0 +1,26 @@ +// Copyright (c) 2016 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "bench.h" + +#include "consensus/merkle.h" +#include "random.h" +#include "uint256.h" + +static void MerkleRoot(benchmark::State &state) { + FastRandomContext rng(true); + std::vector leaves; + leaves.resize(9001); + for (auto &item : leaves) { + item = rng.rand256(); + } + while (state.KeepRunning()) { + bool mutation = false; + uint256 hash = + ComputeMerkleRoot(std::vector(leaves), &mutation); + leaves[mutation] = hash; + } +} + +BENCHMARK(MerkleRoot, 800); diff --git a/src/consensus/merkle.cpp b/src/consensus/merkle.cpp index 75685212ec..e6df3e0d62 100644 --- a/src/consensus/merkle.cpp +++ b/src/consensus/merkle.cpp @@ -1,191 +1,71 @@ // Copyright (c) 2015-2016 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "merkle.h" #include "hash.h" #include "utilstrencodings.h" /* WARNING! If you're reading this because you're learning about crypto and/or designing a new system that will use merkle trees, keep in mind that the following merkle tree algorithm has a serious flaw related to duplicate txids, resulting in a vulnerability (CVE-2012-2459). The reason is that if the number of hashes in the list at a given time is odd, the last one is duplicated before computing the next level (which is unusual in Merkle trees). This results in certain sequences of transactions leading to the same merkle root. For example, these two trees: A A / \ / \ B C B C / \ | / \ / \ D E F D E F F / \ / \ / \ / \ / \ / \ / \ 1 2 3 4 5 6 1 2 3 4 5 6 5 6 for transaction lists [1,2,3,4,5,6] and [1,2,3,4,5,6,5,6] (where 5 and 6 are repeated) result in the same root hash A (because the hash of both of (F) and (F,F) is C). The vulnerability results from being able to send a block with such a transaction list, with the same merkle root, and the same block hash as the original without duplication, resulting in failed validation. If the receiving node proceeds to mark that block as permanently invalid however, it will fail to accept further unmodified (and thus potentially valid) versions of the same block. We defend against this by detecting the case where we would hash two identical hashes at the end of the list together, and treating that identically to the block having an invalid merkle root. Assuming no double-SHA256 collisions, this will detect all known ways of changing the transactions without affecting the merkle root. */ -/* This implements a constant-space merkle root/path calculator, limited to 2^32 - * leaves. */ -static void MerkleComputation(const std::vector &leaves, - uint256 *proot, bool *pmutated, - uint32_t branchpos, - std::vector *pbranch) { - if (pbranch) pbranch->clear(); - if (leaves.size() == 0) { - if (pmutated) *pmutated = false; - if (proot) *proot = uint256(); - return; - } - bool mutated = false; - // count is the number of leaves processed so far. - uint32_t count = 0; - // inner is an array of eagerly computed subtree hashes, indexed by tree - // level (0 being the leaves). - // For example, when count is 25 (11001 in binary), inner[4] is the hash of - // the first 16 leaves, inner[3] of the next 8 leaves, and inner[0] equal to - // the last leaf. The other inner entries are undefined. - uint256 inner[32]; - // Which position in inner is a hash that depends on the matching leaf. - int matchlevel = -1; - // First process all leaves into 'inner' values. - while (count < leaves.size()) { - uint256 h = leaves[count]; - bool matchh = count == branchpos; - count++; - int level; - // For each of the lower bits in count that are 0, do 1 step. Each - // corresponds to an inner value that existed before processing the - // current leaf, and each needs a hash to combine it. - for (level = 0; !(count & (((uint32_t)1) << level)); level++) { - if (pbranch) { - if (matchh) { - pbranch->push_back(inner[level]); - } else if (matchlevel == level) { - pbranch->push_back(h); - matchh = true; - } +uint256 ComputeMerkleRoot(std::vector hashes, bool *mutated) { + bool mutation = false; + while (hashes.size() > 1) { + if (mutated) { + for (size_t pos = 0; pos + 1 < hashes.size(); pos += 2) { + if (hashes[pos] == hashes[pos + 1]) mutation = true; } - mutated |= (inner[level] == h); - CHash256() - .Write(inner[level].begin(), 32) - .Write(h.begin(), 32) - .Finalize(h.begin()); - } - // Store the resulting hash at inner position level. - inner[level] = h; - if (matchh) { - matchlevel = level; - } - } - // Do a final 'sweep' over the rightmost branch of the tree to process - // odd levels, and reduce everything to a single top value. - // Level is the level (counted from the bottom) up to which we've sweeped. - int level = 0; - // As long as bit number level in count is zero, skip it. It means there - // is nothing left at this level. - while (!(count & (((uint32_t)1) << level))) { - level++; - } - uint256 h = inner[level]; - bool matchh = matchlevel == level; - while (count != (((uint32_t)1) << level)) { - // If we reach this point, h is an inner value that is not the top. - // We combine it with itself (Bitcoin's special rule for odd levels in - // the tree) to produce a higher level one. - if (pbranch && matchh) { - pbranch->push_back(h); } - CHash256() - .Write(h.begin(), 32) - .Write(h.begin(), 32) - .Finalize(h.begin()); - // Increment count to the value it would have if two entries at this - // level had existed. - count += (((uint32_t)1) << level); - level++; - // And propagate the result upwards accordingly. - while (!(count & (((uint32_t)1) << level))) { - if (pbranch) { - if (matchh) { - pbranch->push_back(inner[level]); - } else if (matchlevel == level) { - pbranch->push_back(h); - matchh = true; - } - } - CHash256() - .Write(inner[level].begin(), 32) - .Write(h.begin(), 32) - .Finalize(h.begin()); - level++; + if (hashes.size() & 1) { + hashes.push_back(hashes.back()); } + SHA256D64(hashes[0].begin(), hashes[0].begin(), hashes.size() / 2); + hashes.resize(hashes.size() / 2); } - // Return result. - if (pmutated) *pmutated = mutated; - if (proot) *proot = h; -} - -uint256 ComputeMerkleRoot(const std::vector &leaves, bool *mutated) { - uint256 hash; - MerkleComputation(leaves, &hash, mutated, -1, nullptr); - return hash; -} - -std::vector ComputeMerkleBranch(const std::vector &leaves, - uint32_t position) { - std::vector ret; - MerkleComputation(leaves, nullptr, nullptr, position, &ret); - return ret; -} - -uint256 ComputeMerkleRootFromBranch(const uint256 &leaf, - const std::vector &vMerkleBranch, - uint32_t nIndex) { - uint256 hash = leaf; - for (std::vector::const_iterator it = vMerkleBranch.begin(); - it != vMerkleBranch.end(); ++it) { - if (nIndex & 1) { - hash = Hash(BEGIN(*it), END(*it), BEGIN(hash), END(hash)); - } else { - hash = Hash(BEGIN(hash), END(hash), BEGIN(*it), END(*it)); - } - nIndex >>= 1; - } - return hash; + if (mutated) *mutated = mutation; + if (hashes.size() == 0) return uint256(); + return hashes[0]; } uint256 BlockMerkleRoot(const CBlock &block, bool *mutated) { std::vector leaves; leaves.resize(block.vtx.size()); for (size_t s = 0; s < block.vtx.size(); s++) { leaves[s] = block.vtx[s]->GetId(); } - return ComputeMerkleRoot(leaves, mutated); -} - -std::vector BlockMerkleBranch(const CBlock &block, uint32_t position) { - std::vector leaves; - leaves.resize(block.vtx.size()); - for (size_t s = 0; s < block.vtx.size(); s++) { - leaves[s] = block.vtx[s]->GetId(); - } - return ComputeMerkleBranch(leaves, position); + return ComputeMerkleRoot(std::move(leaves), mutated); } diff --git a/src/consensus/merkle.h b/src/consensus/merkle.h index 3b952e495a..22e9a3bbae 100644 --- a/src/consensus/merkle.h +++ b/src/consensus/merkle.h @@ -1,35 +1,23 @@ // Copyright (c) 2015 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef BITCOIN_MERKLE #define BITCOIN_MERKLE #include #include #include "primitives/block.h" #include "primitives/transaction.h" #include "uint256.h" -uint256 ComputeMerkleRoot(const std::vector &leaves, - bool *mutated = nullptr); -std::vector ComputeMerkleBranch(const std::vector &leaves, - uint32_t position); -uint256 ComputeMerkleRootFromBranch(const uint256 &leaf, - const std::vector &branch, - uint32_t position); +uint256 ComputeMerkleRoot(std::vector hashes, bool *mutated = nullptr); /** * Compute the Merkle root of the transactions in a block. * *mutated is set to true if a duplicated subtree was found. */ uint256 BlockMerkleRoot(const CBlock &block, bool *mutated = nullptr); -/** - * Compute the Merkle branch for the tree of transactions in a block, for a - * given position. This can be verified using ComputeMerkleRootFromBranch. - */ -std::vector BlockMerkleBranch(const CBlock &block, uint32_t position); - -#endif +#endif // BITCOIN_CONSENSUS_MERKLE_H diff --git a/src/crypto/sha256.cpp b/src/crypto/sha256.cpp index 04b53b7fb0..601b53a47a 100644 --- a/src/crypto/sha256.cpp +++ b/src/crypto/sha256.cpp @@ -1,324 +1,780 @@ // Copyright (c) 2014 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "crypto/sha256.h" #include "crypto/common.h" #include #include #include #if defined(__x86_64__) || defined(__amd64__) #if defined(USE_ASM) #include namespace sha256_sse4 { void Transform(uint32_t *s, const uint8_t *chunk, size_t blocks); } #endif #endif +namespace sha256d64_sse41 { +void Transform_4way(uint8_t *out, const uint8_t *in); +} + +namespace sha256d64_avx2 { +void Transform_8way(uint8_t *out, const uint8_t *in); +} + // Internal implementation code. namespace { /// Internal SHA-256 implementation. namespace sha256 { inline uint32_t Ch(uint32_t x, uint32_t y, uint32_t z) { return z ^ (x & (y ^ z)); } inline uint32_t Maj(uint32_t x, uint32_t y, uint32_t z) { return (x & y) | (z & (x | y)); } inline uint32_t Sigma0(uint32_t x) { return (x >> 2 | x << 30) ^ (x >> 13 | x << 19) ^ (x >> 22 | x << 10); } inline uint32_t Sigma1(uint32_t x) { return (x >> 6 | x << 26) ^ (x >> 11 | x << 21) ^ (x >> 25 | x << 7); } inline uint32_t sigma0(uint32_t x) { return (x >> 7 | x << 25) ^ (x >> 18 | x << 14) ^ (x >> 3); } inline uint32_t sigma1(uint32_t x) { return (x >> 17 | x << 15) ^ (x >> 19 | x << 13) ^ (x >> 10); } /** One round of SHA-256. */ inline void Round(uint32_t a, uint32_t b, uint32_t c, uint32_t &d, uint32_t e, uint32_t f, uint32_t g, uint32_t &h, - uint32_t k, uint32_t w) { - uint32_t t1 = h + Sigma1(e) + Ch(e, f, g) + k + w; + uint32_t k) { + uint32_t t1 = h + Sigma1(e) + Ch(e, f, g) + k; uint32_t t2 = Sigma0(a) + Maj(a, b, c); d += t1; h = t1 + t2; } /** Initialize SHA-256 state. */ inline void Initialize(uint32_t *s) { s[0] = 0x6a09e667ul; s[1] = 0xbb67ae85ul; s[2] = 0x3c6ef372ul; s[3] = 0xa54ff53aul; s[4] = 0x510e527ful; s[5] = 0x9b05688cul; s[6] = 0x1f83d9abul; s[7] = 0x5be0cd19ul; } - /** Perform a number of SHA-256 transformations, processing 64-byte chunks. + /** + * Perform a number of SHA-256 transformations, processing 64-byte chunks. */ void Transform(uint32_t *s, const uint8_t *chunk, size_t blocks) { while (blocks--) { uint32_t a = s[0], b = s[1], c = s[2], d = s[3], e = s[4], f = s[5], g = s[6], h = s[7]; uint32_t w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15; - Round(a, b, c, d, e, f, g, h, 0x428a2f98, w0 = ReadBE32(chunk + 0)); - Round(h, a, b, c, d, e, f, g, 0x71374491, w1 = ReadBE32(chunk + 4)); - Round(g, h, a, b, c, d, e, f, 0xb5c0fbcf, w2 = ReadBE32(chunk + 8)); - Round(f, g, h, a, b, c, d, e, 0xe9b5dba5, - w3 = ReadBE32(chunk + 12)); - Round(e, f, g, h, a, b, c, d, 0x3956c25b, - w4 = ReadBE32(chunk + 16)); - Round(d, e, f, g, h, a, b, c, 0x59f111f1, - w5 = ReadBE32(chunk + 20)); - Round(c, d, e, f, g, h, a, b, 0x923f82a4, - w6 = ReadBE32(chunk + 24)); - Round(b, c, d, e, f, g, h, a, 0xab1c5ed5, - w7 = ReadBE32(chunk + 28)); - Round(a, b, c, d, e, f, g, h, 0xd807aa98, - w8 = ReadBE32(chunk + 32)); - Round(h, a, b, c, d, e, f, g, 0x12835b01, - w9 = ReadBE32(chunk + 36)); - Round(g, h, a, b, c, d, e, f, 0x243185be, - w10 = ReadBE32(chunk + 40)); - Round(f, g, h, a, b, c, d, e, 0x550c7dc3, - w11 = ReadBE32(chunk + 44)); - Round(e, f, g, h, a, b, c, d, 0x72be5d74, - w12 = ReadBE32(chunk + 48)); - Round(d, e, f, g, h, a, b, c, 0x80deb1fe, - w13 = ReadBE32(chunk + 52)); - Round(c, d, e, f, g, h, a, b, 0x9bdc06a7, - w14 = ReadBE32(chunk + 56)); - Round(b, c, d, e, f, g, h, a, 0xc19bf174, - w15 = ReadBE32(chunk + 60)); - - Round(a, b, c, d, e, f, g, h, 0xe49b69c1, - w0 += sigma1(w14) + w9 + sigma0(w1)); - Round(h, a, b, c, d, e, f, g, 0xefbe4786, - w1 += sigma1(w15) + w10 + sigma0(w2)); - Round(g, h, a, b, c, d, e, f, 0x0fc19dc6, - w2 += sigma1(w0) + w11 + sigma0(w3)); - Round(f, g, h, a, b, c, d, e, 0x240ca1cc, - w3 += sigma1(w1) + w12 + sigma0(w4)); - Round(e, f, g, h, a, b, c, d, 0x2de92c6f, - w4 += sigma1(w2) + w13 + sigma0(w5)); - Round(d, e, f, g, h, a, b, c, 0x4a7484aa, - w5 += sigma1(w3) + w14 + sigma0(w6)); - Round(c, d, e, f, g, h, a, b, 0x5cb0a9dc, - w6 += sigma1(w4) + w15 + sigma0(w7)); - Round(b, c, d, e, f, g, h, a, 0x76f988da, - w7 += sigma1(w5) + w0 + sigma0(w8)); - Round(a, b, c, d, e, f, g, h, 0x983e5152, - w8 += sigma1(w6) + w1 + sigma0(w9)); - Round(h, a, b, c, d, e, f, g, 0xa831c66d, - w9 += sigma1(w7) + w2 + sigma0(w10)); - Round(g, h, a, b, c, d, e, f, 0xb00327c8, - w10 += sigma1(w8) + w3 + sigma0(w11)); - Round(f, g, h, a, b, c, d, e, 0xbf597fc7, - w11 += sigma1(w9) + w4 + sigma0(w12)); - Round(e, f, g, h, a, b, c, d, 0xc6e00bf3, - w12 += sigma1(w10) + w5 + sigma0(w13)); - Round(d, e, f, g, h, a, b, c, 0xd5a79147, - w13 += sigma1(w11) + w6 + sigma0(w14)); - Round(c, d, e, f, g, h, a, b, 0x06ca6351, - w14 += sigma1(w12) + w7 + sigma0(w15)); - Round(b, c, d, e, f, g, h, a, 0x14292967, - w15 += sigma1(w13) + w8 + sigma0(w0)); - - Round(a, b, c, d, e, f, g, h, 0x27b70a85, - w0 += sigma1(w14) + w9 + sigma0(w1)); - Round(h, a, b, c, d, e, f, g, 0x2e1b2138, - w1 += sigma1(w15) + w10 + sigma0(w2)); - Round(g, h, a, b, c, d, e, f, 0x4d2c6dfc, - w2 += sigma1(w0) + w11 + sigma0(w3)); - Round(f, g, h, a, b, c, d, e, 0x53380d13, - w3 += sigma1(w1) + w12 + sigma0(w4)); - Round(e, f, g, h, a, b, c, d, 0x650a7354, - w4 += sigma1(w2) + w13 + sigma0(w5)); - Round(d, e, f, g, h, a, b, c, 0x766a0abb, - w5 += sigma1(w3) + w14 + sigma0(w6)); - Round(c, d, e, f, g, h, a, b, 0x81c2c92e, - w6 += sigma1(w4) + w15 + sigma0(w7)); - Round(b, c, d, e, f, g, h, a, 0x92722c85, - w7 += sigma1(w5) + w0 + sigma0(w8)); - Round(a, b, c, d, e, f, g, h, 0xa2bfe8a1, - w8 += sigma1(w6) + w1 + sigma0(w9)); - Round(h, a, b, c, d, e, f, g, 0xa81a664b, - w9 += sigma1(w7) + w2 + sigma0(w10)); - Round(g, h, a, b, c, d, e, f, 0xc24b8b70, - w10 += sigma1(w8) + w3 + sigma0(w11)); - Round(f, g, h, a, b, c, d, e, 0xc76c51a3, - w11 += sigma1(w9) + w4 + sigma0(w12)); - Round(e, f, g, h, a, b, c, d, 0xd192e819, - w12 += sigma1(w10) + w5 + sigma0(w13)); - Round(d, e, f, g, h, a, b, c, 0xd6990624, - w13 += sigma1(w11) + w6 + sigma0(w14)); - Round(c, d, e, f, g, h, a, b, 0xf40e3585, - w14 += sigma1(w12) + w7 + sigma0(w15)); - Round(b, c, d, e, f, g, h, a, 0x106aa070, - w15 += sigma1(w13) + w8 + sigma0(w0)); - - Round(a, b, c, d, e, f, g, h, 0x19a4c116, - w0 += sigma1(w14) + w9 + sigma0(w1)); - Round(h, a, b, c, d, e, f, g, 0x1e376c08, - w1 += sigma1(w15) + w10 + sigma0(w2)); - Round(g, h, a, b, c, d, e, f, 0x2748774c, - w2 += sigma1(w0) + w11 + sigma0(w3)); - Round(f, g, h, a, b, c, d, e, 0x34b0bcb5, - w3 += sigma1(w1) + w12 + sigma0(w4)); - Round(e, f, g, h, a, b, c, d, 0x391c0cb3, - w4 += sigma1(w2) + w13 + sigma0(w5)); - Round(d, e, f, g, h, a, b, c, 0x4ed8aa4a, - w5 += sigma1(w3) + w14 + sigma0(w6)); - Round(c, d, e, f, g, h, a, b, 0x5b9cca4f, - w6 += sigma1(w4) + w15 + sigma0(w7)); - Round(b, c, d, e, f, g, h, a, 0x682e6ff3, - w7 += sigma1(w5) + w0 + sigma0(w8)); - Round(a, b, c, d, e, f, g, h, 0x748f82ee, - w8 += sigma1(w6) + w1 + sigma0(w9)); - Round(h, a, b, c, d, e, f, g, 0x78a5636f, - w9 += sigma1(w7) + w2 + sigma0(w10)); - Round(g, h, a, b, c, d, e, f, 0x84c87814, - w10 += sigma1(w8) + w3 + sigma0(w11)); - Round(f, g, h, a, b, c, d, e, 0x8cc70208, - w11 += sigma1(w9) + w4 + sigma0(w12)); - Round(e, f, g, h, a, b, c, d, 0x90befffa, - w12 += sigma1(w10) + w5 + sigma0(w13)); - Round(d, e, f, g, h, a, b, c, 0xa4506ceb, - w13 += sigma1(w11) + w6 + sigma0(w14)); - Round(c, d, e, f, g, h, a, b, 0xbef9a3f7, - w14 + sigma1(w12) + w7 + sigma0(w15)); - Round(b, c, d, e, f, g, h, a, 0xc67178f2, - w15 + sigma1(w13) + w8 + sigma0(w0)); + Round(a, b, c, d, e, f, g, h, + 0x428a2f98 + (w0 = ReadBE32(chunk + 0))); + Round(h, a, b, c, d, e, f, g, + 0x71374491 + (w1 = ReadBE32(chunk + 4))); + Round(g, h, a, b, c, d, e, f, + 0xb5c0fbcf + (w2 = ReadBE32(chunk + 8))); + Round(f, g, h, a, b, c, d, e, + 0xe9b5dba5 + (w3 = ReadBE32(chunk + 12))); + Round(e, f, g, h, a, b, c, d, + 0x3956c25b + (w4 = ReadBE32(chunk + 16))); + Round(d, e, f, g, h, a, b, c, + 0x59f111f1 + (w5 = ReadBE32(chunk + 20))); + Round(c, d, e, f, g, h, a, b, + 0x923f82a4 + (w6 = ReadBE32(chunk + 24))); + Round(b, c, d, e, f, g, h, a, + 0xab1c5ed5 + (w7 = ReadBE32(chunk + 28))); + Round(a, b, c, d, e, f, g, h, + 0xd807aa98 + (w8 = ReadBE32(chunk + 32))); + Round(h, a, b, c, d, e, f, g, + 0x12835b01 + (w9 = ReadBE32(chunk + 36))); + Round(g, h, a, b, c, d, e, f, + 0x243185be + (w10 = ReadBE32(chunk + 40))); + Round(f, g, h, a, b, c, d, e, + 0x550c7dc3 + (w11 = ReadBE32(chunk + 44))); + Round(e, f, g, h, a, b, c, d, + 0x72be5d74 + (w12 = ReadBE32(chunk + 48))); + Round(d, e, f, g, h, a, b, c, + 0x80deb1fe + (w13 = ReadBE32(chunk + 52))); + Round(c, d, e, f, g, h, a, b, + 0x9bdc06a7 + (w14 = ReadBE32(chunk + 56))); + Round(b, c, d, e, f, g, h, a, + 0xc19bf174 + (w15 = ReadBE32(chunk + 60))); + + Round(a, b, c, d, e, f, g, h, + 0xe49b69c1 + (w0 += sigma1(w14) + w9 + sigma0(w1))); + Round(h, a, b, c, d, e, f, g, + 0xefbe4786 + (w1 += sigma1(w15) + w10 + sigma0(w2))); + Round(g, h, a, b, c, d, e, f, + 0x0fc19dc6 + (w2 += sigma1(w0) + w11 + sigma0(w3))); + Round(f, g, h, a, b, c, d, e, + 0x240ca1cc + (w3 += sigma1(w1) + w12 + sigma0(w4))); + Round(e, f, g, h, a, b, c, d, + 0x2de92c6f + (w4 += sigma1(w2) + w13 + sigma0(w5))); + Round(d, e, f, g, h, a, b, c, + 0x4a7484aa + (w5 += sigma1(w3) + w14 + sigma0(w6))); + Round(c, d, e, f, g, h, a, b, + 0x5cb0a9dc + (w6 += sigma1(w4) + w15 + sigma0(w7))); + Round(b, c, d, e, f, g, h, a, + 0x76f988da + (w7 += sigma1(w5) + w0 + sigma0(w8))); + Round(a, b, c, d, e, f, g, h, + 0x983e5152 + (w8 += sigma1(w6) + w1 + sigma0(w9))); + Round(h, a, b, c, d, e, f, g, + 0xa831c66d + (w9 += sigma1(w7) + w2 + sigma0(w10))); + Round(g, h, a, b, c, d, e, f, + 0xb00327c8 + (w10 += sigma1(w8) + w3 + sigma0(w11))); + Round(f, g, h, a, b, c, d, e, + 0xbf597fc7 + (w11 += sigma1(w9) + w4 + sigma0(w12))); + Round(e, f, g, h, a, b, c, d, + 0xc6e00bf3 + (w12 += sigma1(w10) + w5 + sigma0(w13))); + Round(d, e, f, g, h, a, b, c, + 0xd5a79147 + (w13 += sigma1(w11) + w6 + sigma0(w14))); + Round(c, d, e, f, g, h, a, b, + 0x06ca6351 + (w14 += sigma1(w12) + w7 + sigma0(w15))); + Round(b, c, d, e, f, g, h, a, + 0x14292967 + (w15 += sigma1(w13) + w8 + sigma0(w0))); + + Round(a, b, c, d, e, f, g, h, + 0x27b70a85 + (w0 += sigma1(w14) + w9 + sigma0(w1))); + Round(h, a, b, c, d, e, f, g, + 0x2e1b2138 + (w1 += sigma1(w15) + w10 + sigma0(w2))); + Round(g, h, a, b, c, d, e, f, + 0x4d2c6dfc + (w2 += sigma1(w0) + w11 + sigma0(w3))); + Round(f, g, h, a, b, c, d, e, + 0x53380d13 + (w3 += sigma1(w1) + w12 + sigma0(w4))); + Round(e, f, g, h, a, b, c, d, + 0x650a7354 + (w4 += sigma1(w2) + w13 + sigma0(w5))); + Round(d, e, f, g, h, a, b, c, + 0x766a0abb + (w5 += sigma1(w3) + w14 + sigma0(w6))); + Round(c, d, e, f, g, h, a, b, + 0x81c2c92e + (w6 += sigma1(w4) + w15 + sigma0(w7))); + Round(b, c, d, e, f, g, h, a, + 0x92722c85 + (w7 += sigma1(w5) + w0 + sigma0(w8))); + Round(a, b, c, d, e, f, g, h, + 0xa2bfe8a1 + (w8 += sigma1(w6) + w1 + sigma0(w9))); + Round(h, a, b, c, d, e, f, g, + 0xa81a664b + (w9 += sigma1(w7) + w2 + sigma0(w10))); + Round(g, h, a, b, c, d, e, f, + 0xc24b8b70 + (w10 += sigma1(w8) + w3 + sigma0(w11))); + Round(f, g, h, a, b, c, d, e, + 0xc76c51a3 + (w11 += sigma1(w9) + w4 + sigma0(w12))); + Round(e, f, g, h, a, b, c, d, + 0xd192e819 + (w12 += sigma1(w10) + w5 + sigma0(w13))); + Round(d, e, f, g, h, a, b, c, + 0xd6990624 + (w13 += sigma1(w11) + w6 + sigma0(w14))); + Round(c, d, e, f, g, h, a, b, + 0xf40e3585 + (w14 += sigma1(w12) + w7 + sigma0(w15))); + Round(b, c, d, e, f, g, h, a, + 0x106aa070 + (w15 += sigma1(w13) + w8 + sigma0(w0))); + + Round(a, b, c, d, e, f, g, h, + 0x19a4c116 + (w0 += sigma1(w14) + w9 + sigma0(w1))); + Round(h, a, b, c, d, e, f, g, + 0x1e376c08 + (w1 += sigma1(w15) + w10 + sigma0(w2))); + Round(g, h, a, b, c, d, e, f, + 0x2748774c + (w2 += sigma1(w0) + w11 + sigma0(w3))); + Round(f, g, h, a, b, c, d, e, + 0x34b0bcb5 + (w3 += sigma1(w1) + w12 + sigma0(w4))); + Round(e, f, g, h, a, b, c, d, + 0x391c0cb3 + (w4 += sigma1(w2) + w13 + sigma0(w5))); + Round(d, e, f, g, h, a, b, c, + 0x4ed8aa4a + (w5 += sigma1(w3) + w14 + sigma0(w6))); + Round(c, d, e, f, g, h, a, b, + 0x5b9cca4f + (w6 += sigma1(w4) + w15 + sigma0(w7))); + Round(b, c, d, e, f, g, h, a, + 0x682e6ff3 + (w7 += sigma1(w5) + w0 + sigma0(w8))); + Round(a, b, c, d, e, f, g, h, + 0x748f82ee + (w8 += sigma1(w6) + w1 + sigma0(w9))); + Round(h, a, b, c, d, e, f, g, + 0x78a5636f + (w9 += sigma1(w7) + w2 + sigma0(w10))); + Round(g, h, a, b, c, d, e, f, + 0x84c87814 + (w10 += sigma1(w8) + w3 + sigma0(w11))); + Round(f, g, h, a, b, c, d, e, + 0x8cc70208 + (w11 += sigma1(w9) + w4 + sigma0(w12))); + Round(e, f, g, h, a, b, c, d, + 0x90befffa + (w12 += sigma1(w10) + w5 + sigma0(w13))); + Round(d, e, f, g, h, a, b, c, + 0xa4506ceb + (w13 += sigma1(w11) + w6 + sigma0(w14))); + Round(c, d, e, f, g, h, a, b, + 0xbef9a3f7 + (w14 + sigma1(w12) + w7 + sigma0(w15))); + Round(b, c, d, e, f, g, h, a, + 0xc67178f2 + (w15 + sigma1(w13) + w8 + sigma0(w0))); s[0] += a; s[1] += b; s[2] += c; s[3] += d; s[4] += e; s[5] += f; s[6] += g; s[7] += h; chunk += 64; } } + void TransformD64(uint8_t *out, const uint8_t *in) { + // Transform 1 + uint32_t a = 0x6a09e667ul; + uint32_t b = 0xbb67ae85ul; + uint32_t c = 0x3c6ef372ul; + uint32_t d = 0xa54ff53aul; + uint32_t e = 0x510e527ful; + uint32_t f = 0x9b05688cul; + uint32_t g = 0x1f83d9abul; + uint32_t h = 0x5be0cd19ul; + + uint32_t w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, + w14, w15; + + Round(a, b, c, d, e, f, g, h, 0x428a2f98ul + (w0 = ReadBE32(in + 0))); + Round(h, a, b, c, d, e, f, g, 0x71374491ul + (w1 = ReadBE32(in + 4))); + Round(g, h, a, b, c, d, e, f, 0xb5c0fbcful + (w2 = ReadBE32(in + 8))); + Round(f, g, h, a, b, c, d, e, 0xe9b5dba5ul + (w3 = ReadBE32(in + 12))); + Round(e, f, g, h, a, b, c, d, 0x3956c25bul + (w4 = ReadBE32(in + 16))); + Round(d, e, f, g, h, a, b, c, 0x59f111f1ul + (w5 = ReadBE32(in + 20))); + Round(c, d, e, f, g, h, a, b, 0x923f82a4ul + (w6 = ReadBE32(in + 24))); + Round(b, c, d, e, f, g, h, a, 0xab1c5ed5ul + (w7 = ReadBE32(in + 28))); + Round(a, b, c, d, e, f, g, h, 0xd807aa98ul + (w8 = ReadBE32(in + 32))); + Round(h, a, b, c, d, e, f, g, 0x12835b01ul + (w9 = ReadBE32(in + 36))); + Round(g, h, a, b, c, d, e, f, 0x243185beul + (w10 = ReadBE32(in + 40))); + Round(f, g, h, a, b, c, d, e, 0x550c7dc3ul + (w11 = ReadBE32(in + 44))); + Round(e, f, g, h, a, b, c, d, 0x72be5d74ul + (w12 = ReadBE32(in + 48))); + Round(d, e, f, g, h, a, b, c, 0x80deb1feul + (w13 = ReadBE32(in + 52))); + Round(c, d, e, f, g, h, a, b, 0x9bdc06a7ul + (w14 = ReadBE32(in + 56))); + Round(b, c, d, e, f, g, h, a, 0xc19bf174ul + (w15 = ReadBE32(in + 60))); + Round(a, b, c, d, e, f, g, h, + 0xe49b69c1ul + (w0 += sigma1(w14) + w9 + sigma0(w1))); + Round(h, a, b, c, d, e, f, g, + 0xefbe4786ul + (w1 += sigma1(w15) + w10 + sigma0(w2))); + Round(g, h, a, b, c, d, e, f, + 0x0fc19dc6ul + (w2 += sigma1(w0) + w11 + sigma0(w3))); + Round(f, g, h, a, b, c, d, e, + 0x240ca1ccul + (w3 += sigma1(w1) + w12 + sigma0(w4))); + Round(e, f, g, h, a, b, c, d, + 0x2de92c6ful + (w4 += sigma1(w2) + w13 + sigma0(w5))); + Round(d, e, f, g, h, a, b, c, + 0x4a7484aaul + (w5 += sigma1(w3) + w14 + sigma0(w6))); + Round(c, d, e, f, g, h, a, b, + 0x5cb0a9dcul + (w6 += sigma1(w4) + w15 + sigma0(w7))); + Round(b, c, d, e, f, g, h, a, + 0x76f988daul + (w7 += sigma1(w5) + w0 + sigma0(w8))); + Round(a, b, c, d, e, f, g, h, + 0x983e5152ul + (w8 += sigma1(w6) + w1 + sigma0(w9))); + Round(h, a, b, c, d, e, f, g, + 0xa831c66dul + (w9 += sigma1(w7) + w2 + sigma0(w10))); + Round(g, h, a, b, c, d, e, f, + 0xb00327c8ul + (w10 += sigma1(w8) + w3 + sigma0(w11))); + Round(f, g, h, a, b, c, d, e, + 0xbf597fc7ul + (w11 += sigma1(w9) + w4 + sigma0(w12))); + Round(e, f, g, h, a, b, c, d, + 0xc6e00bf3ul + (w12 += sigma1(w10) + w5 + sigma0(w13))); + Round(d, e, f, g, h, a, b, c, + 0xd5a79147ul + (w13 += sigma1(w11) + w6 + sigma0(w14))); + Round(c, d, e, f, g, h, a, b, + 0x06ca6351ul + (w14 += sigma1(w12) + w7 + sigma0(w15))); + Round(b, c, d, e, f, g, h, a, + 0x14292967ul + (w15 += sigma1(w13) + w8 + sigma0(w0))); + Round(a, b, c, d, e, f, g, h, + 0x27b70a85ul + (w0 += sigma1(w14) + w9 + sigma0(w1))); + Round(h, a, b, c, d, e, f, g, + 0x2e1b2138ul + (w1 += sigma1(w15) + w10 + sigma0(w2))); + Round(g, h, a, b, c, d, e, f, + 0x4d2c6dfcul + (w2 += sigma1(w0) + w11 + sigma0(w3))); + Round(f, g, h, a, b, c, d, e, + 0x53380d13ul + (w3 += sigma1(w1) + w12 + sigma0(w4))); + Round(e, f, g, h, a, b, c, d, + 0x650a7354ul + (w4 += sigma1(w2) + w13 + sigma0(w5))); + Round(d, e, f, g, h, a, b, c, + 0x766a0abbul + (w5 += sigma1(w3) + w14 + sigma0(w6))); + Round(c, d, e, f, g, h, a, b, + 0x81c2c92eul + (w6 += sigma1(w4) + w15 + sigma0(w7))); + Round(b, c, d, e, f, g, h, a, + 0x92722c85ul + (w7 += sigma1(w5) + w0 + sigma0(w8))); + Round(a, b, c, d, e, f, g, h, + 0xa2bfe8a1ul + (w8 += sigma1(w6) + w1 + sigma0(w9))); + Round(h, a, b, c, d, e, f, g, + 0xa81a664bul + (w9 += sigma1(w7) + w2 + sigma0(w10))); + Round(g, h, a, b, c, d, e, f, + 0xc24b8b70ul + (w10 += sigma1(w8) + w3 + sigma0(w11))); + Round(f, g, h, a, b, c, d, e, + 0xc76c51a3ul + (w11 += sigma1(w9) + w4 + sigma0(w12))); + Round(e, f, g, h, a, b, c, d, + 0xd192e819ul + (w12 += sigma1(w10) + w5 + sigma0(w13))); + Round(d, e, f, g, h, a, b, c, + 0xd6990624ul + (w13 += sigma1(w11) + w6 + sigma0(w14))); + Round(c, d, e, f, g, h, a, b, + 0xf40e3585ul + (w14 += sigma1(w12) + w7 + sigma0(w15))); + Round(b, c, d, e, f, g, h, a, + 0x106aa070ul + (w15 += sigma1(w13) + w8 + sigma0(w0))); + Round(a, b, c, d, e, f, g, h, + 0x19a4c116ul + (w0 += sigma1(w14) + w9 + sigma0(w1))); + Round(h, a, b, c, d, e, f, g, + 0x1e376c08ul + (w1 += sigma1(w15) + w10 + sigma0(w2))); + Round(g, h, a, b, c, d, e, f, + 0x2748774cul + (w2 += sigma1(w0) + w11 + sigma0(w3))); + Round(f, g, h, a, b, c, d, e, + 0x34b0bcb5ul + (w3 += sigma1(w1) + w12 + sigma0(w4))); + Round(e, f, g, h, a, b, c, d, + 0x391c0cb3ul + (w4 += sigma1(w2) + w13 + sigma0(w5))); + Round(d, e, f, g, h, a, b, c, + 0x4ed8aa4aul + (w5 += sigma1(w3) + w14 + sigma0(w6))); + Round(c, d, e, f, g, h, a, b, + 0x5b9cca4ful + (w6 += sigma1(w4) + w15 + sigma0(w7))); + Round(b, c, d, e, f, g, h, a, + 0x682e6ff3ul + (w7 += sigma1(w5) + w0 + sigma0(w8))); + Round(a, b, c, d, e, f, g, h, + 0x748f82eeul + (w8 += sigma1(w6) + w1 + sigma0(w9))); + Round(h, a, b, c, d, e, f, g, + 0x78a5636ful + (w9 += sigma1(w7) + w2 + sigma0(w10))); + Round(g, h, a, b, c, d, e, f, + 0x84c87814ul + (w10 += sigma1(w8) + w3 + sigma0(w11))); + Round(f, g, h, a, b, c, d, e, + 0x8cc70208ul + (w11 += sigma1(w9) + w4 + sigma0(w12))); + Round(e, f, g, h, a, b, c, d, + 0x90befffaul + (w12 += sigma1(w10) + w5 + sigma0(w13))); + Round(d, e, f, g, h, a, b, c, + 0xa4506cebul + (w13 += sigma1(w11) + w6 + sigma0(w14))); + Round(c, d, e, f, g, h, a, b, + 0xbef9a3f7ul + (w14 + sigma1(w12) + w7 + sigma0(w15))); + Round(b, c, d, e, f, g, h, a, + 0xc67178f2ul + (w15 + sigma1(w13) + w8 + sigma0(w0))); + + a += 0x6a09e667ul; + b += 0xbb67ae85ul; + c += 0x3c6ef372ul; + d += 0xa54ff53aul; + e += 0x510e527ful; + f += 0x9b05688cul; + g += 0x1f83d9abul; + h += 0x5be0cd19ul; + + uint32_t t0 = a, t1 = b, t2 = c, t3 = d, t4 = e, t5 = f, t6 = g, t7 = h; + + // Transform 2 + Round(a, b, c, d, e, f, g, h, 0xc28a2f98ul); + Round(h, a, b, c, d, e, f, g, 0x71374491ul); + Round(g, h, a, b, c, d, e, f, 0xb5c0fbcful); + Round(f, g, h, a, b, c, d, e, 0xe9b5dba5ul); + Round(e, f, g, h, a, b, c, d, 0x3956c25bul); + Round(d, e, f, g, h, a, b, c, 0x59f111f1ul); + Round(c, d, e, f, g, h, a, b, 0x923f82a4ul); + Round(b, c, d, e, f, g, h, a, 0xab1c5ed5ul); + Round(a, b, c, d, e, f, g, h, 0xd807aa98ul); + Round(h, a, b, c, d, e, f, g, 0x12835b01ul); + Round(g, h, a, b, c, d, e, f, 0x243185beul); + Round(f, g, h, a, b, c, d, e, 0x550c7dc3ul); + Round(e, f, g, h, a, b, c, d, 0x72be5d74ul); + Round(d, e, f, g, h, a, b, c, 0x80deb1feul); + Round(c, d, e, f, g, h, a, b, 0x9bdc06a7ul); + Round(b, c, d, e, f, g, h, a, 0xc19bf374ul); + Round(a, b, c, d, e, f, g, h, 0x649b69c1ul); + Round(h, a, b, c, d, e, f, g, 0xf0fe4786ul); + Round(g, h, a, b, c, d, e, f, 0x0fe1edc6ul); + Round(f, g, h, a, b, c, d, e, 0x240cf254ul); + Round(e, f, g, h, a, b, c, d, 0x4fe9346ful); + Round(d, e, f, g, h, a, b, c, 0x6cc984beul); + Round(c, d, e, f, g, h, a, b, 0x61b9411eul); + Round(b, c, d, e, f, g, h, a, 0x16f988faul); + Round(a, b, c, d, e, f, g, h, 0xf2c65152ul); + Round(h, a, b, c, d, e, f, g, 0xa88e5a6dul); + Round(g, h, a, b, c, d, e, f, 0xb019fc65ul); + Round(f, g, h, a, b, c, d, e, 0xb9d99ec7ul); + Round(e, f, g, h, a, b, c, d, 0x9a1231c3ul); + Round(d, e, f, g, h, a, b, c, 0xe70eeaa0ul); + Round(c, d, e, f, g, h, a, b, 0xfdb1232bul); + Round(b, c, d, e, f, g, h, a, 0xc7353eb0ul); + Round(a, b, c, d, e, f, g, h, 0x3069bad5ul); + Round(h, a, b, c, d, e, f, g, 0xcb976d5ful); + Round(g, h, a, b, c, d, e, f, 0x5a0f118ful); + Round(f, g, h, a, b, c, d, e, 0xdc1eeefdul); + Round(e, f, g, h, a, b, c, d, 0x0a35b689ul); + Round(d, e, f, g, h, a, b, c, 0xde0b7a04ul); + Round(c, d, e, f, g, h, a, b, 0x58f4ca9dul); + Round(b, c, d, e, f, g, h, a, 0xe15d5b16ul); + Round(a, b, c, d, e, f, g, h, 0x007f3e86ul); + Round(h, a, b, c, d, e, f, g, 0x37088980ul); + Round(g, h, a, b, c, d, e, f, 0xa507ea32ul); + Round(f, g, h, a, b, c, d, e, 0x6fab9537ul); + Round(e, f, g, h, a, b, c, d, 0x17406110ul); + Round(d, e, f, g, h, a, b, c, 0x0d8cd6f1ul); + Round(c, d, e, f, g, h, a, b, 0xcdaa3b6dul); + Round(b, c, d, e, f, g, h, a, 0xc0bbbe37ul); + Round(a, b, c, d, e, f, g, h, 0x83613bdaul); + Round(h, a, b, c, d, e, f, g, 0xdb48a363ul); + Round(g, h, a, b, c, d, e, f, 0x0b02e931ul); + Round(f, g, h, a, b, c, d, e, 0x6fd15ca7ul); + Round(e, f, g, h, a, b, c, d, 0x521afacaul); + Round(d, e, f, g, h, a, b, c, 0x31338431ul); + Round(c, d, e, f, g, h, a, b, 0x6ed41a95ul); + Round(b, c, d, e, f, g, h, a, 0x6d437890ul); + Round(a, b, c, d, e, f, g, h, 0xc39c91f2ul); + Round(h, a, b, c, d, e, f, g, 0x9eccabbdul); + Round(g, h, a, b, c, d, e, f, 0xb5c9a0e6ul); + Round(f, g, h, a, b, c, d, e, 0x532fb63cul); + Round(e, f, g, h, a, b, c, d, 0xd2c741c6ul); + Round(d, e, f, g, h, a, b, c, 0x07237ea3ul); + Round(c, d, e, f, g, h, a, b, 0xa4954b68ul); + Round(b, c, d, e, f, g, h, a, 0x4c191d76ul); + + w0 = t0 + a; + w1 = t1 + b; + w2 = t2 + c; + w3 = t3 + d; + w4 = t4 + e; + w5 = t5 + f; + w6 = t6 + g; + w7 = t7 + h; + + // Transform 3 + a = 0x6a09e667ul; + b = 0xbb67ae85ul; + c = 0x3c6ef372ul; + d = 0xa54ff53aul; + e = 0x510e527ful; + f = 0x9b05688cul; + g = 0x1f83d9abul; + h = 0x5be0cd19ul; + + Round(a, b, c, d, e, f, g, h, 0x428a2f98ul + w0); + Round(h, a, b, c, d, e, f, g, 0x71374491ul + w1); + Round(g, h, a, b, c, d, e, f, 0xb5c0fbcful + w2); + Round(f, g, h, a, b, c, d, e, 0xe9b5dba5ul + w3); + Round(e, f, g, h, a, b, c, d, 0x3956c25bul + w4); + Round(d, e, f, g, h, a, b, c, 0x59f111f1ul + w5); + Round(c, d, e, f, g, h, a, b, 0x923f82a4ul + w6); + Round(b, c, d, e, f, g, h, a, 0xab1c5ed5ul + w7); + Round(a, b, c, d, e, f, g, h, 0x5807aa98ul); + Round(h, a, b, c, d, e, f, g, 0x12835b01ul); + Round(g, h, a, b, c, d, e, f, 0x243185beul); + Round(f, g, h, a, b, c, d, e, 0x550c7dc3ul); + Round(e, f, g, h, a, b, c, d, 0x72be5d74ul); + Round(d, e, f, g, h, a, b, c, 0x80deb1feul); + Round(c, d, e, f, g, h, a, b, 0x9bdc06a7ul); + Round(b, c, d, e, f, g, h, a, 0xc19bf274ul); + Round(a, b, c, d, e, f, g, h, 0xe49b69c1ul + (w0 += sigma0(w1))); + Round(h, a, b, c, d, e, f, g, + 0xefbe4786ul + (w1 += 0xa00000ul + sigma0(w2))); + Round(g, h, a, b, c, d, e, f, + 0x0fc19dc6ul + (w2 += sigma1(w0) + sigma0(w3))); + Round(f, g, h, a, b, c, d, e, + 0x240ca1ccul + (w3 += sigma1(w1) + sigma0(w4))); + Round(e, f, g, h, a, b, c, d, + 0x2de92c6ful + (w4 += sigma1(w2) + sigma0(w5))); + Round(d, e, f, g, h, a, b, c, + 0x4a7484aaul + (w5 += sigma1(w3) + sigma0(w6))); + Round(c, d, e, f, g, h, a, b, + 0x5cb0a9dcul + (w6 += sigma1(w4) + 0x100ul + sigma0(w7))); + Round(b, c, d, e, f, g, h, a, + 0x76f988daul + (w7 += sigma1(w5) + w0 + 0x11002000ul)); + Round(a, b, c, d, e, f, g, h, + 0x983e5152ul + (w8 = 0x80000000ul + sigma1(w6) + w1)); + Round(h, a, b, c, d, e, f, g, 0xa831c66dul + (w9 = sigma1(w7) + w2)); + Round(g, h, a, b, c, d, e, f, 0xb00327c8ul + (w10 = sigma1(w8) + w3)); + Round(f, g, h, a, b, c, d, e, 0xbf597fc7ul + (w11 = sigma1(w9) + w4)); + Round(e, f, g, h, a, b, c, d, 0xc6e00bf3ul + (w12 = sigma1(w10) + w5)); + Round(d, e, f, g, h, a, b, c, 0xd5a79147ul + (w13 = sigma1(w11) + w6)); + Round(c, d, e, f, g, h, a, b, + 0x06ca6351ul + (w14 = sigma1(w12) + w7 + 0x400022ul)); + Round(b, c, d, e, f, g, h, a, + 0x14292967ul + (w15 = 0x100ul + sigma1(w13) + w8 + sigma0(w0))); + Round(a, b, c, d, e, f, g, h, + 0x27b70a85ul + (w0 += sigma1(w14) + w9 + sigma0(w1))); + Round(h, a, b, c, d, e, f, g, + 0x2e1b2138ul + (w1 += sigma1(w15) + w10 + sigma0(w2))); + Round(g, h, a, b, c, d, e, f, + 0x4d2c6dfcul + (w2 += sigma1(w0) + w11 + sigma0(w3))); + Round(f, g, h, a, b, c, d, e, + 0x53380d13ul + (w3 += sigma1(w1) + w12 + sigma0(w4))); + Round(e, f, g, h, a, b, c, d, + 0x650a7354ul + (w4 += sigma1(w2) + w13 + sigma0(w5))); + Round(d, e, f, g, h, a, b, c, + 0x766a0abbul + (w5 += sigma1(w3) + w14 + sigma0(w6))); + Round(c, d, e, f, g, h, a, b, + 0x81c2c92eul + (w6 += sigma1(w4) + w15 + sigma0(w7))); + Round(b, c, d, e, f, g, h, a, + 0x92722c85ul + (w7 += sigma1(w5) + w0 + sigma0(w8))); + Round(a, b, c, d, e, f, g, h, + 0xa2bfe8a1ul + (w8 += sigma1(w6) + w1 + sigma0(w9))); + Round(h, a, b, c, d, e, f, g, + 0xa81a664bul + (w9 += sigma1(w7) + w2 + sigma0(w10))); + Round(g, h, a, b, c, d, e, f, + 0xc24b8b70ul + (w10 += sigma1(w8) + w3 + sigma0(w11))); + Round(f, g, h, a, b, c, d, e, + 0xc76c51a3ul + (w11 += sigma1(w9) + w4 + sigma0(w12))); + Round(e, f, g, h, a, b, c, d, + 0xd192e819ul + (w12 += sigma1(w10) + w5 + sigma0(w13))); + Round(d, e, f, g, h, a, b, c, + 0xd6990624ul + (w13 += sigma1(w11) + w6 + sigma0(w14))); + Round(c, d, e, f, g, h, a, b, + 0xf40e3585ul + (w14 += sigma1(w12) + w7 + sigma0(w15))); + Round(b, c, d, e, f, g, h, a, + 0x106aa070ul + (w15 += sigma1(w13) + w8 + sigma0(w0))); + Round(a, b, c, d, e, f, g, h, + 0x19a4c116ul + (w0 += sigma1(w14) + w9 + sigma0(w1))); + Round(h, a, b, c, d, e, f, g, + 0x1e376c08ul + (w1 += sigma1(w15) + w10 + sigma0(w2))); + Round(g, h, a, b, c, d, e, f, + 0x2748774cul + (w2 += sigma1(w0) + w11 + sigma0(w3))); + Round(f, g, h, a, b, c, d, e, + 0x34b0bcb5ul + (w3 += sigma1(w1) + w12 + sigma0(w4))); + Round(e, f, g, h, a, b, c, d, + 0x391c0cb3ul + (w4 += sigma1(w2) + w13 + sigma0(w5))); + Round(d, e, f, g, h, a, b, c, + 0x4ed8aa4aul + (w5 += sigma1(w3) + w14 + sigma0(w6))); + Round(c, d, e, f, g, h, a, b, + 0x5b9cca4ful + (w6 += sigma1(w4) + w15 + sigma0(w7))); + Round(b, c, d, e, f, g, h, a, + 0x682e6ff3ul + (w7 += sigma1(w5) + w0 + sigma0(w8))); + Round(a, b, c, d, e, f, g, h, + 0x748f82eeul + (w8 += sigma1(w6) + w1 + sigma0(w9))); + Round(h, a, b, c, d, e, f, g, + 0x78a5636ful + (w9 += sigma1(w7) + w2 + sigma0(w10))); + Round(g, h, a, b, c, d, e, f, + 0x84c87814ul + (w10 += sigma1(w8) + w3 + sigma0(w11))); + Round(f, g, h, a, b, c, d, e, + 0x8cc70208ul + (w11 += sigma1(w9) + w4 + sigma0(w12))); + Round(e, f, g, h, a, b, c, d, + 0x90befffaul + (w12 += sigma1(w10) + w5 + sigma0(w13))); + Round(d, e, f, g, h, a, b, c, + 0xa4506cebul + (w13 += sigma1(w11) + w6 + sigma0(w14))); + Round(c, d, e, f, g, h, a, b, + 0xbef9a3f7ul + (w14 + sigma1(w12) + w7 + sigma0(w15))); + Round(b, c, d, e, f, g, h, a, + 0xc67178f2ul + (w15 + sigma1(w13) + w8 + sigma0(w0))); + + // Output + WriteBE32(out + 0, a + 0x6a09e667ul); + WriteBE32(out + 4, b + 0xbb67ae85ul); + WriteBE32(out + 8, c + 0x3c6ef372ul); + WriteBE32(out + 12, d + 0xa54ff53aul); + WriteBE32(out + 16, e + 0x510e527ful); + WriteBE32(out + 20, f + 0x9b05688cul); + WriteBE32(out + 24, g + 0x1f83d9abul); + WriteBE32(out + 28, h + 0x5be0cd19ul); + } + } // namespace sha256 typedef void (*TransformType)(uint32_t *, const uint8_t *, size_t); +typedef void (*TransformD64Type)(uint8_t *, const uint8_t *); + +template +void TransformD64Wrapper(uint8_t *out, const uint8_t *in) { + uint32_t s[8]; + static const uint8_t padding1[64] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0}; + uint8_t buffer2[64] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0}; + sha256::Initialize(s); + tr(s, in, 1); + tr(s, padding1, 1); + WriteBE32(buffer2 + 0, s[0]); + WriteBE32(buffer2 + 4, s[1]); + WriteBE32(buffer2 + 8, s[2]); + WriteBE32(buffer2 + 12, s[3]); + WriteBE32(buffer2 + 16, s[4]); + WriteBE32(buffer2 + 20, s[5]); + WriteBE32(buffer2 + 24, s[6]); + WriteBE32(buffer2 + 28, s[7]); + sha256::Initialize(s); + tr(s, buffer2, 1); + WriteBE32(out + 0, s[0]); + WriteBE32(out + 4, s[1]); + WriteBE32(out + 8, s[2]); + WriteBE32(out + 12, s[3]); + WriteBE32(out + 16, s[4]); + WriteBE32(out + 20, s[5]); + WriteBE32(out + 24, s[6]); + WriteBE32(out + 28, s[7]); +} bool SelfTest(TransformType tr) { static const uint8_t in1[65] = {0, 0x80}; static const uint8_t in2[129] = { 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0}; static const uint32_t init[8] = {0x6a09e667ul, 0xbb67ae85ul, 0x3c6ef372ul, 0xa54ff53aul, 0x510e527ful, 0x9b05688cul, 0x1f83d9abul, 0x5be0cd19ul}; static const uint32_t out1[8] = {0xe3b0c442ul, 0x98fc1c14ul, 0x9afbf4c8ul, 0x996fb924ul, 0x27ae41e4ul, 0x649b934cul, 0xa495991bul, 0x7852b855ul}; static const uint32_t out2[8] = {0xce4153b0ul, 0x147c2a86ul, 0x3ed4298eul, 0xe0676bc8ul, 0x79fc77a1ul, 0x2abe1f49ul, 0xb2b055dful, 0x1069523eul}; uint32_t buf[8]; memcpy(buf, init, sizeof(buf)); // Process nothing, and check we remain in the initial state. tr(buf, nullptr, 0); if (memcmp(buf, init, sizeof(buf))) return false; // Process the padded empty string (unaligned) tr(buf, in1 + 1, 1); if (memcmp(buf, out1, sizeof(buf))) return false; // Process 64 spaces (unaligned) memcpy(buf, init, sizeof(buf)); tr(buf, in2 + 1, 2); if (memcmp(buf, out2, sizeof(buf))) return false; return true; } TransformType Transform = sha256::Transform; +TransformD64Type TransformD64 = sha256::TransformD64; +TransformD64Type TransformD64_4way = nullptr; +TransformD64Type TransformD64_8way = nullptr; + +#if defined(USE_ASM) && \ + (defined(__x86_64__) || defined(__amd64__) || defined(__i386__)) +// We can't use cpuid.h's __get_cpuid as it does not support subleafs. +void inline cpuid(uint32_t leaf, uint32_t subleaf, uint32_t &a, uint32_t &b, + uint32_t &c, uint32_t &d) { + __asm__("cpuid" + : "=a"(a), "=b"(b), "=c"(c), "=d"(d) + : "0"(leaf), "2"(subleaf)); +} +/** Check whether the OS has enabled AVX registers. */ +bool AVXEnabled() { + uint32_t a, d; + __asm__("xgetbv" : "=a"(a), "=d"(d) : "c"(0)); + return (a & 6) == 6; +} +#endif } // namespace std::string SHA256AutoDetect() { -#if defined(USE_ASM) && (defined(__x86_64__) || defined(__amd64__)) + std::string ret = "standard"; +#if defined(USE_ASM) && \ + (defined(__x86_64__) || defined(__amd64__) || defined(__i386__)) + // Silence unused warning (in case ENABLE_AVX2 is not defined) + (void)AVXEnabled; uint32_t eax, ebx, ecx, edx; - if (__get_cpuid(1, &eax, &ebx, &ecx, &edx) && (ecx >> 19) & 1) { + cpuid(1, 0, eax, ebx, ecx, edx); + if ((ecx >> 19) & 1) { +#if defined(__x86_64__) || defined(__amd64__) Transform = sha256_sse4::Transform; - assert(SelfTest(Transform)); - return "sse4"; + TransformD64 = TransformD64Wrapper; +#endif +#if defined(ENABLE_SSE41) && !defined(BUILD_BITCOIN_INTERNAL) + TransformD64_4way = sha256d64_sse41::Transform_4way; + ret = "sse4(1way+4way)"; +#if defined(ENABLE_AVX2) && !defined(BUILD_BITCOIN_INTERNAL) + if (((ecx >> 27) & 1) && ((ecx >> 28) & 1)) { // XSAVE and AVX + cpuid(7, 0, eax, ebx, ecx, edx); + if ((ebx >> 5) & 1) { // AVX2 flag + if (AVXEnabled()) { // OS has enabled AVX registers + TransformD64_8way = sha256d64_avx2::Transform_8way; + ret += ",avx2(8way)"; + } + } + } +#endif +#else + ret = "sse4"; +#endif } #endif assert(SelfTest(Transform)); - return "standard"; + return ret; } ////// SHA-256 CSHA256::CSHA256() : bytes(0) { sha256::Initialize(s); } CSHA256 &CSHA256::Write(const uint8_t *data, size_t len) { const uint8_t *end = data + len; size_t bufsize = bytes % 64; if (bufsize && bufsize + len >= 64) { // Fill the buffer, and process it. memcpy(buf + bufsize, data, 64 - bufsize); bytes += 64 - bufsize; data += 64 - bufsize; Transform(s, buf, 1); bufsize = 0; } if (end - data >= 64) { size_t blocks = (end - data) / 64; Transform(s, data, blocks); data += 64 * blocks; bytes += 64 * blocks; } if (end > data) { // Fill the buffer with what remains. memcpy(buf + bufsize, data, end - data); bytes += end - data; } return *this; } void CSHA256::Finalize(uint8_t hash[OUTPUT_SIZE]) { static const uint8_t pad[64] = {0x80}; uint8_t sizedesc[8]; WriteBE64(sizedesc, bytes << 3); Write(pad, 1 + ((119 - (bytes % 64)) % 64)); Write(sizedesc, 8); WriteBE32(hash, s[0]); WriteBE32(hash + 4, s[1]); WriteBE32(hash + 8, s[2]); WriteBE32(hash + 12, s[3]); WriteBE32(hash + 16, s[4]); WriteBE32(hash + 20, s[5]); WriteBE32(hash + 24, s[6]); WriteBE32(hash + 28, s[7]); } CSHA256 &CSHA256::Reset() { bytes = 0; sha256::Initialize(s); return *this; } + +void SHA256D64(uint8_t *out, const uint8_t *in, size_t blocks) { + if (TransformD64_8way) { + while (blocks >= 8) { + TransformD64_8way(out, in); + out += 256; + in += 512; + blocks -= 8; + } + } + if (TransformD64_4way) { + while (blocks >= 4) { + TransformD64_4way(out, in); + out += 128; + in += 256; + blocks -= 4; + } + } + while (blocks) { + TransformD64(out, in); + out += 32; + in += 64; + --blocks; + } +} diff --git a/src/crypto/sha256.h b/src/crypto/sha256.h index 7c4a63988b..fc1e67dc29 100644 --- a/src/crypto/sha256.h +++ b/src/crypto/sha256.h @@ -1,34 +1,42 @@ // Copyright (c) 2014-2016 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef BITCOIN_CRYPTO_SHA256_H #define BITCOIN_CRYPTO_SHA256_H #include #include #include /** A hasher class for SHA-256. */ class CSHA256 { private: uint32_t s[8]; uint8_t buf[64]; uint64_t bytes; public: static const size_t OUTPUT_SIZE = 32; CSHA256(); CSHA256 &Write(const uint8_t *data, size_t len); void Finalize(uint8_t hash[OUTPUT_SIZE]); CSHA256 &Reset(); }; /** * Autodetect the best available SHA256 implementation. * Returns the name of the implementation. */ std::string SHA256AutoDetect(); +/** + * Compute multiple double-SHA256's of 64-byte blobs. + * output: pointer to a blocks*32 byte output buffer + * input: pointer to a blocks*64 byte input buffer + * blocks: the number of hashes to compute. + */ +void SHA256D64(uint8_t *output, const uint8_t *input, size_t blocks); + #endif // BITCOIN_CRYPTO_SHA256_H diff --git a/src/crypto/sha256_avx2.cpp b/src/crypto/sha256_avx2.cpp new file mode 100644 index 0000000000..04c980ae2a --- /dev/null +++ b/src/crypto/sha256_avx2.cpp @@ -0,0 +1,458 @@ +#ifdef ENABLE_AVX2 + +#include +#if defined(_MSC_VER) +#include +#elif defined(__GNUC__) +#include +#endif + +#include "crypto/common.h" +#include "crypto/sha256.h" + +namespace sha256d64_avx2 { +namespace { + + __m256i inline K(uint32_t x) { return _mm256_set1_epi32(x); } + + __m256i inline Add(__m256i x, __m256i y) { return _mm256_add_epi32(x, y); } + __m256i inline Add(__m256i x, __m256i y, __m256i z) { + return Add(Add(x, y), z); + } + __m256i inline Add(__m256i x, __m256i y, __m256i z, __m256i w) { + return Add(Add(x, y), Add(z, w)); + } + __m256i inline Add(__m256i x, __m256i y, __m256i z, __m256i w, __m256i v) { + return Add(Add(x, y, z), Add(w, v)); + } + __m256i inline Inc(__m256i &x, __m256i y) { + x = Add(x, y); + return x; + } + __m256i inline Inc(__m256i &x, __m256i y, __m256i z) { + x = Add(x, y, z); + return x; + } + __m256i inline Inc(__m256i &x, __m256i y, __m256i z, __m256i w) { + x = Add(x, y, z, w); + return x; + } + __m256i inline Xor(__m256i x, __m256i y) { return _mm256_xor_si256(x, y); } + __m256i inline Xor(__m256i x, __m256i y, __m256i z) { + return Xor(Xor(x, y), z); + } + __m256i inline Or(__m256i x, __m256i y) { return _mm256_or_si256(x, y); } + __m256i inline And(__m256i x, __m256i y) { return _mm256_and_si256(x, y); } + __m256i inline ShR(__m256i x, int n) { return _mm256_srli_epi32(x, n); } + __m256i inline ShL(__m256i x, int n) { return _mm256_slli_epi32(x, n); } + + __m256i inline Ch(__m256i x, __m256i y, __m256i z) { + return Xor(z, And(x, Xor(y, z))); + } + __m256i inline Maj(__m256i x, __m256i y, __m256i z) { + return Or(And(x, y), And(z, Or(x, y))); + } + __m256i inline Sigma0(__m256i x) { + return Xor(Or(ShR(x, 2), ShL(x, 30)), Or(ShR(x, 13), ShL(x, 19)), + Or(ShR(x, 22), ShL(x, 10))); + } + __m256i inline Sigma1(__m256i x) { + return Xor(Or(ShR(x, 6), ShL(x, 26)), Or(ShR(x, 11), ShL(x, 21)), + Or(ShR(x, 25), ShL(x, 7))); + } + __m256i inline sigma0(__m256i x) { + return Xor(Or(ShR(x, 7), ShL(x, 25)), Or(ShR(x, 18), ShL(x, 14)), + ShR(x, 3)); + } + __m256i inline sigma1(__m256i x) { + return Xor(Or(ShR(x, 17), ShL(x, 15)), Or(ShR(x, 19), ShL(x, 13)), + ShR(x, 10)); + } + + /** One round of SHA-256. */ + void inline __attribute__((always_inline)) + Round(__m256i a, __m256i b, __m256i c, __m256i &d, __m256i e, __m256i f, + __m256i g, __m256i &h, __m256i k) { + __m256i t1 = Add(h, Sigma1(e), Ch(e, f, g), k); + __m256i t2 = Add(Sigma0(a), Maj(a, b, c)); + d = Add(d, t1); + h = Add(t1, t2); + } + + __m256i inline Read8(const uint8_t *chunk, int offset) { + __m256i ret = _mm256_set_epi32( + ReadLE32(chunk + 0 + offset), ReadLE32(chunk + 64 + offset), + ReadLE32(chunk + 128 + offset), ReadLE32(chunk + 192 + offset), + ReadLE32(chunk + 256 + offset), ReadLE32(chunk + 320 + offset), + ReadLE32(chunk + 384 + offset), ReadLE32(chunk + 448 + offset)); + return _mm256_shuffle_epi8( + ret, _mm256_set_epi32(0x0C0D0E0FUL, 0x08090A0BUL, 0x04050607UL, + 0x00010203UL, 0x0C0D0E0FUL, 0x08090A0BUL, + 0x04050607UL, 0x00010203UL)); + } + + void inline Write8(uint8_t *out, int offset, __m256i v) { + v = _mm256_shuffle_epi8( + v, _mm256_set_epi32(0x0C0D0E0FUL, 0x08090A0BUL, 0x04050607UL, + 0x00010203UL, 0x0C0D0E0FUL, 0x08090A0BUL, + 0x04050607UL, 0x00010203UL)); + WriteLE32(out + 0 + offset, _mm256_extract_epi32(v, 7)); + WriteLE32(out + 32 + offset, _mm256_extract_epi32(v, 6)); + WriteLE32(out + 64 + offset, _mm256_extract_epi32(v, 5)); + WriteLE32(out + 96 + offset, _mm256_extract_epi32(v, 4)); + WriteLE32(out + 128 + offset, _mm256_extract_epi32(v, 3)); + WriteLE32(out + 160 + offset, _mm256_extract_epi32(v, 2)); + WriteLE32(out + 192 + offset, _mm256_extract_epi32(v, 1)); + WriteLE32(out + 224 + offset, _mm256_extract_epi32(v, 0)); + } +} + +void Transform_8way(uint8_t *out, const uint8_t *in) { + // Transform 1 + __m256i a = K(0x6a09e667ul); + __m256i b = K(0xbb67ae85ul); + __m256i c = K(0x3c6ef372ul); + __m256i d = K(0xa54ff53aul); + __m256i e = K(0x510e527ful); + __m256i f = K(0x9b05688cul); + __m256i g = K(0x1f83d9abul); + __m256i h = K(0x5be0cd19ul); + + __m256i w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, + w15; + + Round(a, b, c, d, e, f, g, h, Add(K(0x428a2f98ul), w0 = Read8(in, 0))); + Round(h, a, b, c, d, e, f, g, Add(K(0x71374491ul), w1 = Read8(in, 4))); + Round(g, h, a, b, c, d, e, f, Add(K(0xb5c0fbcful), w2 = Read8(in, 8))); + Round(f, g, h, a, b, c, d, e, Add(K(0xe9b5dba5ul), w3 = Read8(in, 12))); + Round(e, f, g, h, a, b, c, d, Add(K(0x3956c25bul), w4 = Read8(in, 16))); + Round(d, e, f, g, h, a, b, c, Add(K(0x59f111f1ul), w5 = Read8(in, 20))); + Round(c, d, e, f, g, h, a, b, Add(K(0x923f82a4ul), w6 = Read8(in, 24))); + Round(b, c, d, e, f, g, h, a, Add(K(0xab1c5ed5ul), w7 = Read8(in, 28))); + Round(a, b, c, d, e, f, g, h, Add(K(0xd807aa98ul), w8 = Read8(in, 32))); + Round(h, a, b, c, d, e, f, g, Add(K(0x12835b01ul), w9 = Read8(in, 36))); + Round(g, h, a, b, c, d, e, f, Add(K(0x243185beul), w10 = Read8(in, 40))); + Round(f, g, h, a, b, c, d, e, Add(K(0x550c7dc3ul), w11 = Read8(in, 44))); + Round(e, f, g, h, a, b, c, d, Add(K(0x72be5d74ul), w12 = Read8(in, 48))); + Round(d, e, f, g, h, a, b, c, Add(K(0x80deb1feul), w13 = Read8(in, 52))); + Round(c, d, e, f, g, h, a, b, Add(K(0x9bdc06a7ul), w14 = Read8(in, 56))); + Round(b, c, d, e, f, g, h, a, Add(K(0xc19bf174ul), w15 = Read8(in, 60))); + Round(a, b, c, d, e, f, g, h, + Add(K(0xe49b69c1ul), Inc(w0, sigma1(w14), w9, sigma0(w1)))); + Round(h, a, b, c, d, e, f, g, + Add(K(0xefbe4786ul), Inc(w1, sigma1(w15), w10, sigma0(w2)))); + Round(g, h, a, b, c, d, e, f, + Add(K(0x0fc19dc6ul), Inc(w2, sigma1(w0), w11, sigma0(w3)))); + Round(f, g, h, a, b, c, d, e, + Add(K(0x240ca1ccul), Inc(w3, sigma1(w1), w12, sigma0(w4)))); + Round(e, f, g, h, a, b, c, d, + Add(K(0x2de92c6ful), Inc(w4, sigma1(w2), w13, sigma0(w5)))); + Round(d, e, f, g, h, a, b, c, + Add(K(0x4a7484aaul), Inc(w5, sigma1(w3), w14, sigma0(w6)))); + Round(c, d, e, f, g, h, a, b, + Add(K(0x5cb0a9dcul), Inc(w6, sigma1(w4), w15, sigma0(w7)))); + Round(b, c, d, e, f, g, h, a, + Add(K(0x76f988daul), Inc(w7, sigma1(w5), w0, sigma0(w8)))); + Round(a, b, c, d, e, f, g, h, + Add(K(0x983e5152ul), Inc(w8, sigma1(w6), w1, sigma0(w9)))); + Round(h, a, b, c, d, e, f, g, + Add(K(0xa831c66dul), Inc(w9, sigma1(w7), w2, sigma0(w10)))); + Round(g, h, a, b, c, d, e, f, + Add(K(0xb00327c8ul), Inc(w10, sigma1(w8), w3, sigma0(w11)))); + Round(f, g, h, a, b, c, d, e, + Add(K(0xbf597fc7ul), Inc(w11, sigma1(w9), w4, sigma0(w12)))); + Round(e, f, g, h, a, b, c, d, + Add(K(0xc6e00bf3ul), Inc(w12, sigma1(w10), w5, sigma0(w13)))); + Round(d, e, f, g, h, a, b, c, + Add(K(0xd5a79147ul), Inc(w13, sigma1(w11), w6, sigma0(w14)))); + Round(c, d, e, f, g, h, a, b, + Add(K(0x06ca6351ul), Inc(w14, sigma1(w12), w7, sigma0(w15)))); + Round(b, c, d, e, f, g, h, a, + Add(K(0x14292967ul), Inc(w15, sigma1(w13), w8, sigma0(w0)))); + Round(a, b, c, d, e, f, g, h, + Add(K(0x27b70a85ul), Inc(w0, sigma1(w14), w9, sigma0(w1)))); + Round(h, a, b, c, d, e, f, g, + Add(K(0x2e1b2138ul), Inc(w1, sigma1(w15), w10, sigma0(w2)))); + Round(g, h, a, b, c, d, e, f, + Add(K(0x4d2c6dfcul), Inc(w2, sigma1(w0), w11, sigma0(w3)))); + Round(f, g, h, a, b, c, d, e, + Add(K(0x53380d13ul), Inc(w3, sigma1(w1), w12, sigma0(w4)))); + Round(e, f, g, h, a, b, c, d, + Add(K(0x650a7354ul), Inc(w4, sigma1(w2), w13, sigma0(w5)))); + Round(d, e, f, g, h, a, b, c, + Add(K(0x766a0abbul), Inc(w5, sigma1(w3), w14, sigma0(w6)))); + Round(c, d, e, f, g, h, a, b, + Add(K(0x81c2c92eul), Inc(w6, sigma1(w4), w15, sigma0(w7)))); + Round(b, c, d, e, f, g, h, a, + Add(K(0x92722c85ul), Inc(w7, sigma1(w5), w0, sigma0(w8)))); + Round(a, b, c, d, e, f, g, h, + Add(K(0xa2bfe8a1ul), Inc(w8, sigma1(w6), w1, sigma0(w9)))); + Round(h, a, b, c, d, e, f, g, + Add(K(0xa81a664bul), Inc(w9, sigma1(w7), w2, sigma0(w10)))); + Round(g, h, a, b, c, d, e, f, + Add(K(0xc24b8b70ul), Inc(w10, sigma1(w8), w3, sigma0(w11)))); + Round(f, g, h, a, b, c, d, e, + Add(K(0xc76c51a3ul), Inc(w11, sigma1(w9), w4, sigma0(w12)))); + Round(e, f, g, h, a, b, c, d, + Add(K(0xd192e819ul), Inc(w12, sigma1(w10), w5, sigma0(w13)))); + Round(d, e, f, g, h, a, b, c, + Add(K(0xd6990624ul), Inc(w13, sigma1(w11), w6, sigma0(w14)))); + Round(c, d, e, f, g, h, a, b, + Add(K(0xf40e3585ul), Inc(w14, sigma1(w12), w7, sigma0(w15)))); + Round(b, c, d, e, f, g, h, a, + Add(K(0x106aa070ul), Inc(w15, sigma1(w13), w8, sigma0(w0)))); + Round(a, b, c, d, e, f, g, h, + Add(K(0x19a4c116ul), Inc(w0, sigma1(w14), w9, sigma0(w1)))); + Round(h, a, b, c, d, e, f, g, + Add(K(0x1e376c08ul), Inc(w1, sigma1(w15), w10, sigma0(w2)))); + Round(g, h, a, b, c, d, e, f, + Add(K(0x2748774cul), Inc(w2, sigma1(w0), w11, sigma0(w3)))); + Round(f, g, h, a, b, c, d, e, + Add(K(0x34b0bcb5ul), Inc(w3, sigma1(w1), w12, sigma0(w4)))); + Round(e, f, g, h, a, b, c, d, + Add(K(0x391c0cb3ul), Inc(w4, sigma1(w2), w13, sigma0(w5)))); + Round(d, e, f, g, h, a, b, c, + Add(K(0x4ed8aa4aul), Inc(w5, sigma1(w3), w14, sigma0(w6)))); + Round(c, d, e, f, g, h, a, b, + Add(K(0x5b9cca4ful), Inc(w6, sigma1(w4), w15, sigma0(w7)))); + Round(b, c, d, e, f, g, h, a, + Add(K(0x682e6ff3ul), Inc(w7, sigma1(w5), w0, sigma0(w8)))); + Round(a, b, c, d, e, f, g, h, + Add(K(0x748f82eeul), Inc(w8, sigma1(w6), w1, sigma0(w9)))); + Round(h, a, b, c, d, e, f, g, + Add(K(0x78a5636ful), Inc(w9, sigma1(w7), w2, sigma0(w10)))); + Round(g, h, a, b, c, d, e, f, + Add(K(0x84c87814ul), Inc(w10, sigma1(w8), w3, sigma0(w11)))); + Round(f, g, h, a, b, c, d, e, + Add(K(0x8cc70208ul), Inc(w11, sigma1(w9), w4, sigma0(w12)))); + Round(e, f, g, h, a, b, c, d, + Add(K(0x90befffaul), Inc(w12, sigma1(w10), w5, sigma0(w13)))); + Round(d, e, f, g, h, a, b, c, + Add(K(0xa4506cebul), Inc(w13, sigma1(w11), w6, sigma0(w14)))); + Round(c, d, e, f, g, h, a, b, + Add(K(0xbef9a3f7ul), Inc(w14, sigma1(w12), w7, sigma0(w15)))); + Round(b, c, d, e, f, g, h, a, + Add(K(0xc67178f2ul), Inc(w15, sigma1(w13), w8, sigma0(w0)))); + + a = Add(a, K(0x6a09e667ul)); + b = Add(b, K(0xbb67ae85ul)); + c = Add(c, K(0x3c6ef372ul)); + d = Add(d, K(0xa54ff53aul)); + e = Add(e, K(0x510e527ful)); + f = Add(f, K(0x9b05688cul)); + g = Add(g, K(0x1f83d9abul)); + h = Add(h, K(0x5be0cd19ul)); + + __m256i t0 = a, t1 = b, t2 = c, t3 = d, t4 = e, t5 = f, t6 = g, t7 = h; + + // Transform 2 + Round(a, b, c, d, e, f, g, h, K(0xc28a2f98ul)); + Round(h, a, b, c, d, e, f, g, K(0x71374491ul)); + Round(g, h, a, b, c, d, e, f, K(0xb5c0fbcful)); + Round(f, g, h, a, b, c, d, e, K(0xe9b5dba5ul)); + Round(e, f, g, h, a, b, c, d, K(0x3956c25bul)); + Round(d, e, f, g, h, a, b, c, K(0x59f111f1ul)); + Round(c, d, e, f, g, h, a, b, K(0x923f82a4ul)); + Round(b, c, d, e, f, g, h, a, K(0xab1c5ed5ul)); + Round(a, b, c, d, e, f, g, h, K(0xd807aa98ul)); + Round(h, a, b, c, d, e, f, g, K(0x12835b01ul)); + Round(g, h, a, b, c, d, e, f, K(0x243185beul)); + Round(f, g, h, a, b, c, d, e, K(0x550c7dc3ul)); + Round(e, f, g, h, a, b, c, d, K(0x72be5d74ul)); + Round(d, e, f, g, h, a, b, c, K(0x80deb1feul)); + Round(c, d, e, f, g, h, a, b, K(0x9bdc06a7ul)); + Round(b, c, d, e, f, g, h, a, K(0xc19bf374ul)); + Round(a, b, c, d, e, f, g, h, K(0x649b69c1ul)); + Round(h, a, b, c, d, e, f, g, K(0xf0fe4786ul)); + Round(g, h, a, b, c, d, e, f, K(0x0fe1edc6ul)); + Round(f, g, h, a, b, c, d, e, K(0x240cf254ul)); + Round(e, f, g, h, a, b, c, d, K(0x4fe9346ful)); + Round(d, e, f, g, h, a, b, c, K(0x6cc984beul)); + Round(c, d, e, f, g, h, a, b, K(0x61b9411eul)); + Round(b, c, d, e, f, g, h, a, K(0x16f988faul)); + Round(a, b, c, d, e, f, g, h, K(0xf2c65152ul)); + Round(h, a, b, c, d, e, f, g, K(0xa88e5a6dul)); + Round(g, h, a, b, c, d, e, f, K(0xb019fc65ul)); + Round(f, g, h, a, b, c, d, e, K(0xb9d99ec7ul)); + Round(e, f, g, h, a, b, c, d, K(0x9a1231c3ul)); + Round(d, e, f, g, h, a, b, c, K(0xe70eeaa0ul)); + Round(c, d, e, f, g, h, a, b, K(0xfdb1232bul)); + Round(b, c, d, e, f, g, h, a, K(0xc7353eb0ul)); + Round(a, b, c, d, e, f, g, h, K(0x3069bad5ul)); + Round(h, a, b, c, d, e, f, g, K(0xcb976d5ful)); + Round(g, h, a, b, c, d, e, f, K(0x5a0f118ful)); + Round(f, g, h, a, b, c, d, e, K(0xdc1eeefdul)); + Round(e, f, g, h, a, b, c, d, K(0x0a35b689ul)); + Round(d, e, f, g, h, a, b, c, K(0xde0b7a04ul)); + Round(c, d, e, f, g, h, a, b, K(0x58f4ca9dul)); + Round(b, c, d, e, f, g, h, a, K(0xe15d5b16ul)); + Round(a, b, c, d, e, f, g, h, K(0x007f3e86ul)); + Round(h, a, b, c, d, e, f, g, K(0x37088980ul)); + Round(g, h, a, b, c, d, e, f, K(0xa507ea32ul)); + Round(f, g, h, a, b, c, d, e, K(0x6fab9537ul)); + Round(e, f, g, h, a, b, c, d, K(0x17406110ul)); + Round(d, e, f, g, h, a, b, c, K(0x0d8cd6f1ul)); + Round(c, d, e, f, g, h, a, b, K(0xcdaa3b6dul)); + Round(b, c, d, e, f, g, h, a, K(0xc0bbbe37ul)); + Round(a, b, c, d, e, f, g, h, K(0x83613bdaul)); + Round(h, a, b, c, d, e, f, g, K(0xdb48a363ul)); + Round(g, h, a, b, c, d, e, f, K(0x0b02e931ul)); + Round(f, g, h, a, b, c, d, e, K(0x6fd15ca7ul)); + Round(e, f, g, h, a, b, c, d, K(0x521afacaul)); + Round(d, e, f, g, h, a, b, c, K(0x31338431ul)); + Round(c, d, e, f, g, h, a, b, K(0x6ed41a95ul)); + Round(b, c, d, e, f, g, h, a, K(0x6d437890ul)); + Round(a, b, c, d, e, f, g, h, K(0xc39c91f2ul)); + Round(h, a, b, c, d, e, f, g, K(0x9eccabbdul)); + Round(g, h, a, b, c, d, e, f, K(0xb5c9a0e6ul)); + Round(f, g, h, a, b, c, d, e, K(0x532fb63cul)); + Round(e, f, g, h, a, b, c, d, K(0xd2c741c6ul)); + Round(d, e, f, g, h, a, b, c, K(0x07237ea3ul)); + Round(c, d, e, f, g, h, a, b, K(0xa4954b68ul)); + Round(b, c, d, e, f, g, h, a, K(0x4c191d76ul)); + + w0 = Add(t0, a); + w1 = Add(t1, b); + w2 = Add(t2, c); + w3 = Add(t3, d); + w4 = Add(t4, e); + w5 = Add(t5, f); + w6 = Add(t6, g); + w7 = Add(t7, h); + + // Transform 3 + a = K(0x6a09e667ul); + b = K(0xbb67ae85ul); + c = K(0x3c6ef372ul); + d = K(0xa54ff53aul); + e = K(0x510e527ful); + f = K(0x9b05688cul); + g = K(0x1f83d9abul); + h = K(0x5be0cd19ul); + + Round(a, b, c, d, e, f, g, h, Add(K(0x428a2f98ul), w0)); + Round(h, a, b, c, d, e, f, g, Add(K(0x71374491ul), w1)); + Round(g, h, a, b, c, d, e, f, Add(K(0xb5c0fbcful), w2)); + Round(f, g, h, a, b, c, d, e, Add(K(0xe9b5dba5ul), w3)); + Round(e, f, g, h, a, b, c, d, Add(K(0x3956c25bul), w4)); + Round(d, e, f, g, h, a, b, c, Add(K(0x59f111f1ul), w5)); + Round(c, d, e, f, g, h, a, b, Add(K(0x923f82a4ul), w6)); + Round(b, c, d, e, f, g, h, a, Add(K(0xab1c5ed5ul), w7)); + Round(a, b, c, d, e, f, g, h, K(0x5807aa98ul)); + Round(h, a, b, c, d, e, f, g, K(0x12835b01ul)); + Round(g, h, a, b, c, d, e, f, K(0x243185beul)); + Round(f, g, h, a, b, c, d, e, K(0x550c7dc3ul)); + Round(e, f, g, h, a, b, c, d, K(0x72be5d74ul)); + Round(d, e, f, g, h, a, b, c, K(0x80deb1feul)); + Round(c, d, e, f, g, h, a, b, K(0x9bdc06a7ul)); + Round(b, c, d, e, f, g, h, a, K(0xc19bf274ul)); + Round(a, b, c, d, e, f, g, h, Add(K(0xe49b69c1ul), Inc(w0, sigma0(w1)))); + Round(h, a, b, c, d, e, f, g, + Add(K(0xefbe4786ul), Inc(w1, K(0xa00000ul), sigma0(w2)))); + Round(g, h, a, b, c, d, e, f, + Add(K(0x0fc19dc6ul), Inc(w2, sigma1(w0), sigma0(w3)))); + Round(f, g, h, a, b, c, d, e, + Add(K(0x240ca1ccul), Inc(w3, sigma1(w1), sigma0(w4)))); + Round(e, f, g, h, a, b, c, d, + Add(K(0x2de92c6ful), Inc(w4, sigma1(w2), sigma0(w5)))); + Round(d, e, f, g, h, a, b, c, + Add(K(0x4a7484aaul), Inc(w5, sigma1(w3), sigma0(w6)))); + Round(c, d, e, f, g, h, a, b, + Add(K(0x5cb0a9dcul), Inc(w6, sigma1(w4), K(0x100ul), sigma0(w7)))); + Round(b, c, d, e, f, g, h, a, + Add(K(0x76f988daul), Inc(w7, sigma1(w5), w0, K(0x11002000ul)))); + Round(a, b, c, d, e, f, g, h, + Add(K(0x983e5152ul), w8 = Add(K(0x80000000ul), sigma1(w6), w1))); + Round(h, a, b, c, d, e, f, g, + Add(K(0xa831c66dul), w9 = Add(sigma1(w7), w2))); + Round(g, h, a, b, c, d, e, f, + Add(K(0xb00327c8ul), w10 = Add(sigma1(w8), w3))); + Round(f, g, h, a, b, c, d, e, + Add(K(0xbf597fc7ul), w11 = Add(sigma1(w9), w4))); + Round(e, f, g, h, a, b, c, d, + Add(K(0xc6e00bf3ul), w12 = Add(sigma1(w10), w5))); + Round(d, e, f, g, h, a, b, c, + Add(K(0xd5a79147ul), w13 = Add(sigma1(w11), w6))); + Round(c, d, e, f, g, h, a, b, + Add(K(0x06ca6351ul), w14 = Add(sigma1(w12), w7, K(0x400022ul)))); + Round(b, c, d, e, f, g, h, a, + Add(K(0x14292967ul), + w15 = Add(K(0x100ul), sigma1(w13), w8, sigma0(w0)))); + Round(a, b, c, d, e, f, g, h, + Add(K(0x27b70a85ul), Inc(w0, sigma1(w14), w9, sigma0(w1)))); + Round(h, a, b, c, d, e, f, g, + Add(K(0x2e1b2138ul), Inc(w1, sigma1(w15), w10, sigma0(w2)))); + Round(g, h, a, b, c, d, e, f, + Add(K(0x4d2c6dfcul), Inc(w2, sigma1(w0), w11, sigma0(w3)))); + Round(f, g, h, a, b, c, d, e, + Add(K(0x53380d13ul), Inc(w3, sigma1(w1), w12, sigma0(w4)))); + Round(e, f, g, h, a, b, c, d, + Add(K(0x650a7354ul), Inc(w4, sigma1(w2), w13, sigma0(w5)))); + Round(d, e, f, g, h, a, b, c, + Add(K(0x766a0abbul), Inc(w5, sigma1(w3), w14, sigma0(w6)))); + Round(c, d, e, f, g, h, a, b, + Add(K(0x81c2c92eul), Inc(w6, sigma1(w4), w15, sigma0(w7)))); + Round(b, c, d, e, f, g, h, a, + Add(K(0x92722c85ul), Inc(w7, sigma1(w5), w0, sigma0(w8)))); + Round(a, b, c, d, e, f, g, h, + Add(K(0xa2bfe8a1ul), Inc(w8, sigma1(w6), w1, sigma0(w9)))); + Round(h, a, b, c, d, e, f, g, + Add(K(0xa81a664bul), Inc(w9, sigma1(w7), w2, sigma0(w10)))); + Round(g, h, a, b, c, d, e, f, + Add(K(0xc24b8b70ul), Inc(w10, sigma1(w8), w3, sigma0(w11)))); + Round(f, g, h, a, b, c, d, e, + Add(K(0xc76c51a3ul), Inc(w11, sigma1(w9), w4, sigma0(w12)))); + Round(e, f, g, h, a, b, c, d, + Add(K(0xd192e819ul), Inc(w12, sigma1(w10), w5, sigma0(w13)))); + Round(d, e, f, g, h, a, b, c, + Add(K(0xd6990624ul), Inc(w13, sigma1(w11), w6, sigma0(w14)))); + Round(c, d, e, f, g, h, a, b, + Add(K(0xf40e3585ul), Inc(w14, sigma1(w12), w7, sigma0(w15)))); + Round(b, c, d, e, f, g, h, a, + Add(K(0x106aa070ul), Inc(w15, sigma1(w13), w8, sigma0(w0)))); + Round(a, b, c, d, e, f, g, h, + Add(K(0x19a4c116ul), Inc(w0, sigma1(w14), w9, sigma0(w1)))); + Round(h, a, b, c, d, e, f, g, + Add(K(0x1e376c08ul), Inc(w1, sigma1(w15), w10, sigma0(w2)))); + Round(g, h, a, b, c, d, e, f, + Add(K(0x2748774cul), Inc(w2, sigma1(w0), w11, sigma0(w3)))); + Round(f, g, h, a, b, c, d, e, + Add(K(0x34b0bcb5ul), Inc(w3, sigma1(w1), w12, sigma0(w4)))); + Round(e, f, g, h, a, b, c, d, + Add(K(0x391c0cb3ul), Inc(w4, sigma1(w2), w13, sigma0(w5)))); + Round(d, e, f, g, h, a, b, c, + Add(K(0x4ed8aa4aul), Inc(w5, sigma1(w3), w14, sigma0(w6)))); + Round(c, d, e, f, g, h, a, b, + Add(K(0x5b9cca4ful), Inc(w6, sigma1(w4), w15, sigma0(w7)))); + Round(b, c, d, e, f, g, h, a, + Add(K(0x682e6ff3ul), Inc(w7, sigma1(w5), w0, sigma0(w8)))); + Round(a, b, c, d, e, f, g, h, + Add(K(0x748f82eeul), Inc(w8, sigma1(w6), w1, sigma0(w9)))); + Round(h, a, b, c, d, e, f, g, + Add(K(0x78a5636ful), Inc(w9, sigma1(w7), w2, sigma0(w10)))); + Round(g, h, a, b, c, d, e, f, + Add(K(0x84c87814ul), Inc(w10, sigma1(w8), w3, sigma0(w11)))); + Round(f, g, h, a, b, c, d, e, + Add(K(0x8cc70208ul), Inc(w11, sigma1(w9), w4, sigma0(w12)))); + Round(e, f, g, h, a, b, c, d, + Add(K(0x90befffaul), Inc(w12, sigma1(w10), w5, sigma0(w13)))); + Round(d, e, f, g, h, a, b, c, + Add(K(0xa4506cebul), Inc(w13, sigma1(w11), w6, sigma0(w14)))); + Round(c, d, e, f, g, h, a, b, + Add(K(0xbef9a3f7ul), w14, sigma1(w12), w7, sigma0(w15))); + Round(b, c, d, e, f, g, h, a, + Add(K(0xc67178f2ul), w15, sigma1(w13), w8, sigma0(w0))); + + // Output + Write8(out, 0, Add(a, K(0x6a09e667ul))); + Write8(out, 4, Add(b, K(0xbb67ae85ul))); + Write8(out, 8, Add(c, K(0x3c6ef372ul))); + Write8(out, 12, Add(d, K(0xa54ff53aul))); + Write8(out, 16, Add(e, K(0x510e527ful))); + Write8(out, 20, Add(f, K(0x9b05688cul))); + Write8(out, 24, Add(g, K(0x1f83d9abul))); + Write8(out, 28, Add(h, K(0x5be0cd19ul))); +} +} + +#endif diff --git a/src/crypto/sha256_sse41.cpp b/src/crypto/sha256_sse41.cpp new file mode 100644 index 0000000000..86bacc3493 --- /dev/null +++ b/src/crypto/sha256_sse41.cpp @@ -0,0 +1,448 @@ +#ifdef ENABLE_SSE41 + +#include +#if defined(_MSC_VER) +#include +#elif defined(__GNUC__) +#include +#endif + +#include "crypto/common.h" +#include "crypto/sha256.h" + +namespace sha256d64_sse41 { +namespace { + + __m128i inline K(uint32_t x) { return _mm_set1_epi32(x); } + + __m128i inline Add(__m128i x, __m128i y) { return _mm_add_epi32(x, y); } + __m128i inline Add(__m128i x, __m128i y, __m128i z) { + return Add(Add(x, y), z); + } + __m128i inline Add(__m128i x, __m128i y, __m128i z, __m128i w) { + return Add(Add(x, y), Add(z, w)); + } + __m128i inline Add(__m128i x, __m128i y, __m128i z, __m128i w, __m128i v) { + return Add(Add(x, y, z), Add(w, v)); + } + __m128i inline Inc(__m128i &x, __m128i y) { + x = Add(x, y); + return x; + } + __m128i inline Inc(__m128i &x, __m128i y, __m128i z) { + x = Add(x, y, z); + return x; + } + __m128i inline Inc(__m128i &x, __m128i y, __m128i z, __m128i w) { + x = Add(x, y, z, w); + return x; + } + __m128i inline Xor(__m128i x, __m128i y) { return _mm_xor_si128(x, y); } + __m128i inline Xor(__m128i x, __m128i y, __m128i z) { + return Xor(Xor(x, y), z); + } + __m128i inline Or(__m128i x, __m128i y) { return _mm_or_si128(x, y); } + __m128i inline And(__m128i x, __m128i y) { return _mm_and_si128(x, y); } + __m128i inline ShR(__m128i x, int n) { return _mm_srli_epi32(x, n); } + __m128i inline ShL(__m128i x, int n) { return _mm_slli_epi32(x, n); } + + __m128i inline Ch(__m128i x, __m128i y, __m128i z) { + return Xor(z, And(x, Xor(y, z))); + } + __m128i inline Maj(__m128i x, __m128i y, __m128i z) { + return Or(And(x, y), And(z, Or(x, y))); + } + __m128i inline Sigma0(__m128i x) { + return Xor(Or(ShR(x, 2), ShL(x, 30)), Or(ShR(x, 13), ShL(x, 19)), + Or(ShR(x, 22), ShL(x, 10))); + } + __m128i inline Sigma1(__m128i x) { + return Xor(Or(ShR(x, 6), ShL(x, 26)), Or(ShR(x, 11), ShL(x, 21)), + Or(ShR(x, 25), ShL(x, 7))); + } + __m128i inline sigma0(__m128i x) { + return Xor(Or(ShR(x, 7), ShL(x, 25)), Or(ShR(x, 18), ShL(x, 14)), + ShR(x, 3)); + } + __m128i inline sigma1(__m128i x) { + return Xor(Or(ShR(x, 17), ShL(x, 15)), Or(ShR(x, 19), ShL(x, 13)), + ShR(x, 10)); + } + + /** One round of SHA-256. */ + void inline __attribute__((always_inline)) + Round(__m128i a, __m128i b, __m128i c, __m128i &d, __m128i e, __m128i f, + __m128i g, __m128i &h, __m128i k) { + __m128i t1 = Add(h, Sigma1(e), Ch(e, f, g), k); + __m128i t2 = Add(Sigma0(a), Maj(a, b, c)); + d = Add(d, t1); + h = Add(t1, t2); + } + + __m128i inline Read4(const uint8_t *chunk, int offset) { + __m128i ret = _mm_set_epi32( + ReadLE32(chunk + 0 + offset), ReadLE32(chunk + 64 + offset), + ReadLE32(chunk + 128 + offset), ReadLE32(chunk + 192 + offset)); + return _mm_shuffle_epi8(ret, _mm_set_epi32(0x0C0D0E0FUL, 0x08090A0BUL, + 0x04050607UL, 0x00010203UL)); + } + + void inline Write4(uint8_t *out, int offset, __m128i v) { + v = _mm_shuffle_epi8(v, _mm_set_epi32(0x0C0D0E0FUL, 0x08090A0BUL, + 0x04050607UL, 0x00010203UL)); + WriteLE32(out + 0 + offset, _mm_extract_epi32(v, 3)); + WriteLE32(out + 32 + offset, _mm_extract_epi32(v, 2)); + WriteLE32(out + 64 + offset, _mm_extract_epi32(v, 1)); + WriteLE32(out + 96 + offset, _mm_extract_epi32(v, 0)); + } +} + +void Transform_4way(uint8_t *out, const uint8_t *in) { + // Transform 1 + __m128i a = K(0x6a09e667ul); + __m128i b = K(0xbb67ae85ul); + __m128i c = K(0x3c6ef372ul); + __m128i d = K(0xa54ff53aul); + __m128i e = K(0x510e527ful); + __m128i f = K(0x9b05688cul); + __m128i g = K(0x1f83d9abul); + __m128i h = K(0x5be0cd19ul); + + __m128i w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, + w15; + + Round(a, b, c, d, e, f, g, h, Add(K(0x428a2f98ul), w0 = Read4(in, 0))); + Round(h, a, b, c, d, e, f, g, Add(K(0x71374491ul), w1 = Read4(in, 4))); + Round(g, h, a, b, c, d, e, f, Add(K(0xb5c0fbcful), w2 = Read4(in, 8))); + Round(f, g, h, a, b, c, d, e, Add(K(0xe9b5dba5ul), w3 = Read4(in, 12))); + Round(e, f, g, h, a, b, c, d, Add(K(0x3956c25bul), w4 = Read4(in, 16))); + Round(d, e, f, g, h, a, b, c, Add(K(0x59f111f1ul), w5 = Read4(in, 20))); + Round(c, d, e, f, g, h, a, b, Add(K(0x923f82a4ul), w6 = Read4(in, 24))); + Round(b, c, d, e, f, g, h, a, Add(K(0xab1c5ed5ul), w7 = Read4(in, 28))); + Round(a, b, c, d, e, f, g, h, Add(K(0xd807aa98ul), w8 = Read4(in, 32))); + Round(h, a, b, c, d, e, f, g, Add(K(0x12835b01ul), w9 = Read4(in, 36))); + Round(g, h, a, b, c, d, e, f, Add(K(0x243185beul), w10 = Read4(in, 40))); + Round(f, g, h, a, b, c, d, e, Add(K(0x550c7dc3ul), w11 = Read4(in, 44))); + Round(e, f, g, h, a, b, c, d, Add(K(0x72be5d74ul), w12 = Read4(in, 48))); + Round(d, e, f, g, h, a, b, c, Add(K(0x80deb1feul), w13 = Read4(in, 52))); + Round(c, d, e, f, g, h, a, b, Add(K(0x9bdc06a7ul), w14 = Read4(in, 56))); + Round(b, c, d, e, f, g, h, a, Add(K(0xc19bf174ul), w15 = Read4(in, 60))); + Round(a, b, c, d, e, f, g, h, + Add(K(0xe49b69c1ul), Inc(w0, sigma1(w14), w9, sigma0(w1)))); + Round(h, a, b, c, d, e, f, g, + Add(K(0xefbe4786ul), Inc(w1, sigma1(w15), w10, sigma0(w2)))); + Round(g, h, a, b, c, d, e, f, + Add(K(0x0fc19dc6ul), Inc(w2, sigma1(w0), w11, sigma0(w3)))); + Round(f, g, h, a, b, c, d, e, + Add(K(0x240ca1ccul), Inc(w3, sigma1(w1), w12, sigma0(w4)))); + Round(e, f, g, h, a, b, c, d, + Add(K(0x2de92c6ful), Inc(w4, sigma1(w2), w13, sigma0(w5)))); + Round(d, e, f, g, h, a, b, c, + Add(K(0x4a7484aaul), Inc(w5, sigma1(w3), w14, sigma0(w6)))); + Round(c, d, e, f, g, h, a, b, + Add(K(0x5cb0a9dcul), Inc(w6, sigma1(w4), w15, sigma0(w7)))); + Round(b, c, d, e, f, g, h, a, + Add(K(0x76f988daul), Inc(w7, sigma1(w5), w0, sigma0(w8)))); + Round(a, b, c, d, e, f, g, h, + Add(K(0x983e5152ul), Inc(w8, sigma1(w6), w1, sigma0(w9)))); + Round(h, a, b, c, d, e, f, g, + Add(K(0xa831c66dul), Inc(w9, sigma1(w7), w2, sigma0(w10)))); + Round(g, h, a, b, c, d, e, f, + Add(K(0xb00327c8ul), Inc(w10, sigma1(w8), w3, sigma0(w11)))); + Round(f, g, h, a, b, c, d, e, + Add(K(0xbf597fc7ul), Inc(w11, sigma1(w9), w4, sigma0(w12)))); + Round(e, f, g, h, a, b, c, d, + Add(K(0xc6e00bf3ul), Inc(w12, sigma1(w10), w5, sigma0(w13)))); + Round(d, e, f, g, h, a, b, c, + Add(K(0xd5a79147ul), Inc(w13, sigma1(w11), w6, sigma0(w14)))); + Round(c, d, e, f, g, h, a, b, + Add(K(0x06ca6351ul), Inc(w14, sigma1(w12), w7, sigma0(w15)))); + Round(b, c, d, e, f, g, h, a, + Add(K(0x14292967ul), Inc(w15, sigma1(w13), w8, sigma0(w0)))); + Round(a, b, c, d, e, f, g, h, + Add(K(0x27b70a85ul), Inc(w0, sigma1(w14), w9, sigma0(w1)))); + Round(h, a, b, c, d, e, f, g, + Add(K(0x2e1b2138ul), Inc(w1, sigma1(w15), w10, sigma0(w2)))); + Round(g, h, a, b, c, d, e, f, + Add(K(0x4d2c6dfcul), Inc(w2, sigma1(w0), w11, sigma0(w3)))); + Round(f, g, h, a, b, c, d, e, + Add(K(0x53380d13ul), Inc(w3, sigma1(w1), w12, sigma0(w4)))); + Round(e, f, g, h, a, b, c, d, + Add(K(0x650a7354ul), Inc(w4, sigma1(w2), w13, sigma0(w5)))); + Round(d, e, f, g, h, a, b, c, + Add(K(0x766a0abbul), Inc(w5, sigma1(w3), w14, sigma0(w6)))); + Round(c, d, e, f, g, h, a, b, + Add(K(0x81c2c92eul), Inc(w6, sigma1(w4), w15, sigma0(w7)))); + Round(b, c, d, e, f, g, h, a, + Add(K(0x92722c85ul), Inc(w7, sigma1(w5), w0, sigma0(w8)))); + Round(a, b, c, d, e, f, g, h, + Add(K(0xa2bfe8a1ul), Inc(w8, sigma1(w6), w1, sigma0(w9)))); + Round(h, a, b, c, d, e, f, g, + Add(K(0xa81a664bul), Inc(w9, sigma1(w7), w2, sigma0(w10)))); + Round(g, h, a, b, c, d, e, f, + Add(K(0xc24b8b70ul), Inc(w10, sigma1(w8), w3, sigma0(w11)))); + Round(f, g, h, a, b, c, d, e, + Add(K(0xc76c51a3ul), Inc(w11, sigma1(w9), w4, sigma0(w12)))); + Round(e, f, g, h, a, b, c, d, + Add(K(0xd192e819ul), Inc(w12, sigma1(w10), w5, sigma0(w13)))); + Round(d, e, f, g, h, a, b, c, + Add(K(0xd6990624ul), Inc(w13, sigma1(w11), w6, sigma0(w14)))); + Round(c, d, e, f, g, h, a, b, + Add(K(0xf40e3585ul), Inc(w14, sigma1(w12), w7, sigma0(w15)))); + Round(b, c, d, e, f, g, h, a, + Add(K(0x106aa070ul), Inc(w15, sigma1(w13), w8, sigma0(w0)))); + Round(a, b, c, d, e, f, g, h, + Add(K(0x19a4c116ul), Inc(w0, sigma1(w14), w9, sigma0(w1)))); + Round(h, a, b, c, d, e, f, g, + Add(K(0x1e376c08ul), Inc(w1, sigma1(w15), w10, sigma0(w2)))); + Round(g, h, a, b, c, d, e, f, + Add(K(0x2748774cul), Inc(w2, sigma1(w0), w11, sigma0(w3)))); + Round(f, g, h, a, b, c, d, e, + Add(K(0x34b0bcb5ul), Inc(w3, sigma1(w1), w12, sigma0(w4)))); + Round(e, f, g, h, a, b, c, d, + Add(K(0x391c0cb3ul), Inc(w4, sigma1(w2), w13, sigma0(w5)))); + Round(d, e, f, g, h, a, b, c, + Add(K(0x4ed8aa4aul), Inc(w5, sigma1(w3), w14, sigma0(w6)))); + Round(c, d, e, f, g, h, a, b, + Add(K(0x5b9cca4ful), Inc(w6, sigma1(w4), w15, sigma0(w7)))); + Round(b, c, d, e, f, g, h, a, + Add(K(0x682e6ff3ul), Inc(w7, sigma1(w5), w0, sigma0(w8)))); + Round(a, b, c, d, e, f, g, h, + Add(K(0x748f82eeul), Inc(w8, sigma1(w6), w1, sigma0(w9)))); + Round(h, a, b, c, d, e, f, g, + Add(K(0x78a5636ful), Inc(w9, sigma1(w7), w2, sigma0(w10)))); + Round(g, h, a, b, c, d, e, f, + Add(K(0x84c87814ul), Inc(w10, sigma1(w8), w3, sigma0(w11)))); + Round(f, g, h, a, b, c, d, e, + Add(K(0x8cc70208ul), Inc(w11, sigma1(w9), w4, sigma0(w12)))); + Round(e, f, g, h, a, b, c, d, + Add(K(0x90befffaul), Inc(w12, sigma1(w10), w5, sigma0(w13)))); + Round(d, e, f, g, h, a, b, c, + Add(K(0xa4506cebul), Inc(w13, sigma1(w11), w6, sigma0(w14)))); + Round(c, d, e, f, g, h, a, b, + Add(K(0xbef9a3f7ul), Inc(w14, sigma1(w12), w7, sigma0(w15)))); + Round(b, c, d, e, f, g, h, a, + Add(K(0xc67178f2ul), Inc(w15, sigma1(w13), w8, sigma0(w0)))); + + a = Add(a, K(0x6a09e667ul)); + b = Add(b, K(0xbb67ae85ul)); + c = Add(c, K(0x3c6ef372ul)); + d = Add(d, K(0xa54ff53aul)); + e = Add(e, K(0x510e527ful)); + f = Add(f, K(0x9b05688cul)); + g = Add(g, K(0x1f83d9abul)); + h = Add(h, K(0x5be0cd19ul)); + + __m128i t0 = a, t1 = b, t2 = c, t3 = d, t4 = e, t5 = f, t6 = g, t7 = h; + + // Transform 2 + Round(a, b, c, d, e, f, g, h, K(0xc28a2f98ul)); + Round(h, a, b, c, d, e, f, g, K(0x71374491ul)); + Round(g, h, a, b, c, d, e, f, K(0xb5c0fbcful)); + Round(f, g, h, a, b, c, d, e, K(0xe9b5dba5ul)); + Round(e, f, g, h, a, b, c, d, K(0x3956c25bul)); + Round(d, e, f, g, h, a, b, c, K(0x59f111f1ul)); + Round(c, d, e, f, g, h, a, b, K(0x923f82a4ul)); + Round(b, c, d, e, f, g, h, a, K(0xab1c5ed5ul)); + Round(a, b, c, d, e, f, g, h, K(0xd807aa98ul)); + Round(h, a, b, c, d, e, f, g, K(0x12835b01ul)); + Round(g, h, a, b, c, d, e, f, K(0x243185beul)); + Round(f, g, h, a, b, c, d, e, K(0x550c7dc3ul)); + Round(e, f, g, h, a, b, c, d, K(0x72be5d74ul)); + Round(d, e, f, g, h, a, b, c, K(0x80deb1feul)); + Round(c, d, e, f, g, h, a, b, K(0x9bdc06a7ul)); + Round(b, c, d, e, f, g, h, a, K(0xc19bf374ul)); + Round(a, b, c, d, e, f, g, h, K(0x649b69c1ul)); + Round(h, a, b, c, d, e, f, g, K(0xf0fe4786ul)); + Round(g, h, a, b, c, d, e, f, K(0x0fe1edc6ul)); + Round(f, g, h, a, b, c, d, e, K(0x240cf254ul)); + Round(e, f, g, h, a, b, c, d, K(0x4fe9346ful)); + Round(d, e, f, g, h, a, b, c, K(0x6cc984beul)); + Round(c, d, e, f, g, h, a, b, K(0x61b9411eul)); + Round(b, c, d, e, f, g, h, a, K(0x16f988faul)); + Round(a, b, c, d, e, f, g, h, K(0xf2c65152ul)); + Round(h, a, b, c, d, e, f, g, K(0xa88e5a6dul)); + Round(g, h, a, b, c, d, e, f, K(0xb019fc65ul)); + Round(f, g, h, a, b, c, d, e, K(0xb9d99ec7ul)); + Round(e, f, g, h, a, b, c, d, K(0x9a1231c3ul)); + Round(d, e, f, g, h, a, b, c, K(0xe70eeaa0ul)); + Round(c, d, e, f, g, h, a, b, K(0xfdb1232bul)); + Round(b, c, d, e, f, g, h, a, K(0xc7353eb0ul)); + Round(a, b, c, d, e, f, g, h, K(0x3069bad5ul)); + Round(h, a, b, c, d, e, f, g, K(0xcb976d5ful)); + Round(g, h, a, b, c, d, e, f, K(0x5a0f118ful)); + Round(f, g, h, a, b, c, d, e, K(0xdc1eeefdul)); + Round(e, f, g, h, a, b, c, d, K(0x0a35b689ul)); + Round(d, e, f, g, h, a, b, c, K(0xde0b7a04ul)); + Round(c, d, e, f, g, h, a, b, K(0x58f4ca9dul)); + Round(b, c, d, e, f, g, h, a, K(0xe15d5b16ul)); + Round(a, b, c, d, e, f, g, h, K(0x007f3e86ul)); + Round(h, a, b, c, d, e, f, g, K(0x37088980ul)); + Round(g, h, a, b, c, d, e, f, K(0xa507ea32ul)); + Round(f, g, h, a, b, c, d, e, K(0x6fab9537ul)); + Round(e, f, g, h, a, b, c, d, K(0x17406110ul)); + Round(d, e, f, g, h, a, b, c, K(0x0d8cd6f1ul)); + Round(c, d, e, f, g, h, a, b, K(0xcdaa3b6dul)); + Round(b, c, d, e, f, g, h, a, K(0xc0bbbe37ul)); + Round(a, b, c, d, e, f, g, h, K(0x83613bdaul)); + Round(h, a, b, c, d, e, f, g, K(0xdb48a363ul)); + Round(g, h, a, b, c, d, e, f, K(0x0b02e931ul)); + Round(f, g, h, a, b, c, d, e, K(0x6fd15ca7ul)); + Round(e, f, g, h, a, b, c, d, K(0x521afacaul)); + Round(d, e, f, g, h, a, b, c, K(0x31338431ul)); + Round(c, d, e, f, g, h, a, b, K(0x6ed41a95ul)); + Round(b, c, d, e, f, g, h, a, K(0x6d437890ul)); + Round(a, b, c, d, e, f, g, h, K(0xc39c91f2ul)); + Round(h, a, b, c, d, e, f, g, K(0x9eccabbdul)); + Round(g, h, a, b, c, d, e, f, K(0xb5c9a0e6ul)); + Round(f, g, h, a, b, c, d, e, K(0x532fb63cul)); + Round(e, f, g, h, a, b, c, d, K(0xd2c741c6ul)); + Round(d, e, f, g, h, a, b, c, K(0x07237ea3ul)); + Round(c, d, e, f, g, h, a, b, K(0xa4954b68ul)); + Round(b, c, d, e, f, g, h, a, K(0x4c191d76ul)); + + w0 = Add(t0, a); + w1 = Add(t1, b); + w2 = Add(t2, c); + w3 = Add(t3, d); + w4 = Add(t4, e); + w5 = Add(t5, f); + w6 = Add(t6, g); + w7 = Add(t7, h); + + // Transform 3 + a = K(0x6a09e667ul); + b = K(0xbb67ae85ul); + c = K(0x3c6ef372ul); + d = K(0xa54ff53aul); + e = K(0x510e527ful); + f = K(0x9b05688cul); + g = K(0x1f83d9abul); + h = K(0x5be0cd19ul); + + Round(a, b, c, d, e, f, g, h, Add(K(0x428a2f98ul), w0)); + Round(h, a, b, c, d, e, f, g, Add(K(0x71374491ul), w1)); + Round(g, h, a, b, c, d, e, f, Add(K(0xb5c0fbcful), w2)); + Round(f, g, h, a, b, c, d, e, Add(K(0xe9b5dba5ul), w3)); + Round(e, f, g, h, a, b, c, d, Add(K(0x3956c25bul), w4)); + Round(d, e, f, g, h, a, b, c, Add(K(0x59f111f1ul), w5)); + Round(c, d, e, f, g, h, a, b, Add(K(0x923f82a4ul), w6)); + Round(b, c, d, e, f, g, h, a, Add(K(0xab1c5ed5ul), w7)); + Round(a, b, c, d, e, f, g, h, K(0x5807aa98ul)); + Round(h, a, b, c, d, e, f, g, K(0x12835b01ul)); + Round(g, h, a, b, c, d, e, f, K(0x243185beul)); + Round(f, g, h, a, b, c, d, e, K(0x550c7dc3ul)); + Round(e, f, g, h, a, b, c, d, K(0x72be5d74ul)); + Round(d, e, f, g, h, a, b, c, K(0x80deb1feul)); + Round(c, d, e, f, g, h, a, b, K(0x9bdc06a7ul)); + Round(b, c, d, e, f, g, h, a, K(0xc19bf274ul)); + Round(a, b, c, d, e, f, g, h, Add(K(0xe49b69c1ul), Inc(w0, sigma0(w1)))); + Round(h, a, b, c, d, e, f, g, + Add(K(0xefbe4786ul), Inc(w1, K(0xa00000ul), sigma0(w2)))); + Round(g, h, a, b, c, d, e, f, + Add(K(0x0fc19dc6ul), Inc(w2, sigma1(w0), sigma0(w3)))); + Round(f, g, h, a, b, c, d, e, + Add(K(0x240ca1ccul), Inc(w3, sigma1(w1), sigma0(w4)))); + Round(e, f, g, h, a, b, c, d, + Add(K(0x2de92c6ful), Inc(w4, sigma1(w2), sigma0(w5)))); + Round(d, e, f, g, h, a, b, c, + Add(K(0x4a7484aaul), Inc(w5, sigma1(w3), sigma0(w6)))); + Round(c, d, e, f, g, h, a, b, + Add(K(0x5cb0a9dcul), Inc(w6, sigma1(w4), K(0x100ul), sigma0(w7)))); + Round(b, c, d, e, f, g, h, a, + Add(K(0x76f988daul), Inc(w7, sigma1(w5), w0, K(0x11002000ul)))); + Round(a, b, c, d, e, f, g, h, + Add(K(0x983e5152ul), w8 = Add(K(0x80000000ul), sigma1(w6), w1))); + Round(h, a, b, c, d, e, f, g, + Add(K(0xa831c66dul), w9 = Add(sigma1(w7), w2))); + Round(g, h, a, b, c, d, e, f, + Add(K(0xb00327c8ul), w10 = Add(sigma1(w8), w3))); + Round(f, g, h, a, b, c, d, e, + Add(K(0xbf597fc7ul), w11 = Add(sigma1(w9), w4))); + Round(e, f, g, h, a, b, c, d, + Add(K(0xc6e00bf3ul), w12 = Add(sigma1(w10), w5))); + Round(d, e, f, g, h, a, b, c, + Add(K(0xd5a79147ul), w13 = Add(sigma1(w11), w6))); + Round(c, d, e, f, g, h, a, b, + Add(K(0x06ca6351ul), w14 = Add(sigma1(w12), w7, K(0x400022ul)))); + Round(b, c, d, e, f, g, h, a, + Add(K(0x14292967ul), + w15 = Add(K(0x100ul), sigma1(w13), w8, sigma0(w0)))); + Round(a, b, c, d, e, f, g, h, + Add(K(0x27b70a85ul), Inc(w0, sigma1(w14), w9, sigma0(w1)))); + Round(h, a, b, c, d, e, f, g, + Add(K(0x2e1b2138ul), Inc(w1, sigma1(w15), w10, sigma0(w2)))); + Round(g, h, a, b, c, d, e, f, + Add(K(0x4d2c6dfcul), Inc(w2, sigma1(w0), w11, sigma0(w3)))); + Round(f, g, h, a, b, c, d, e, + Add(K(0x53380d13ul), Inc(w3, sigma1(w1), w12, sigma0(w4)))); + Round(e, f, g, h, a, b, c, d, + Add(K(0x650a7354ul), Inc(w4, sigma1(w2), w13, sigma0(w5)))); + Round(d, e, f, g, h, a, b, c, + Add(K(0x766a0abbul), Inc(w5, sigma1(w3), w14, sigma0(w6)))); + Round(c, d, e, f, g, h, a, b, + Add(K(0x81c2c92eul), Inc(w6, sigma1(w4), w15, sigma0(w7)))); + Round(b, c, d, e, f, g, h, a, + Add(K(0x92722c85ul), Inc(w7, sigma1(w5), w0, sigma0(w8)))); + Round(a, b, c, d, e, f, g, h, + Add(K(0xa2bfe8a1ul), Inc(w8, sigma1(w6), w1, sigma0(w9)))); + Round(h, a, b, c, d, e, f, g, + Add(K(0xa81a664bul), Inc(w9, sigma1(w7), w2, sigma0(w10)))); + Round(g, h, a, b, c, d, e, f, + Add(K(0xc24b8b70ul), Inc(w10, sigma1(w8), w3, sigma0(w11)))); + Round(f, g, h, a, b, c, d, e, + Add(K(0xc76c51a3ul), Inc(w11, sigma1(w9), w4, sigma0(w12)))); + Round(e, f, g, h, a, b, c, d, + Add(K(0xd192e819ul), Inc(w12, sigma1(w10), w5, sigma0(w13)))); + Round(d, e, f, g, h, a, b, c, + Add(K(0xd6990624ul), Inc(w13, sigma1(w11), w6, sigma0(w14)))); + Round(c, d, e, f, g, h, a, b, + Add(K(0xf40e3585ul), Inc(w14, sigma1(w12), w7, sigma0(w15)))); + Round(b, c, d, e, f, g, h, a, + Add(K(0x106aa070ul), Inc(w15, sigma1(w13), w8, sigma0(w0)))); + Round(a, b, c, d, e, f, g, h, + Add(K(0x19a4c116ul), Inc(w0, sigma1(w14), w9, sigma0(w1)))); + Round(h, a, b, c, d, e, f, g, + Add(K(0x1e376c08ul), Inc(w1, sigma1(w15), w10, sigma0(w2)))); + Round(g, h, a, b, c, d, e, f, + Add(K(0x2748774cul), Inc(w2, sigma1(w0), w11, sigma0(w3)))); + Round(f, g, h, a, b, c, d, e, + Add(K(0x34b0bcb5ul), Inc(w3, sigma1(w1), w12, sigma0(w4)))); + Round(e, f, g, h, a, b, c, d, + Add(K(0x391c0cb3ul), Inc(w4, sigma1(w2), w13, sigma0(w5)))); + Round(d, e, f, g, h, a, b, c, + Add(K(0x4ed8aa4aul), Inc(w5, sigma1(w3), w14, sigma0(w6)))); + Round(c, d, e, f, g, h, a, b, + Add(K(0x5b9cca4ful), Inc(w6, sigma1(w4), w15, sigma0(w7)))); + Round(b, c, d, e, f, g, h, a, + Add(K(0x682e6ff3ul), Inc(w7, sigma1(w5), w0, sigma0(w8)))); + Round(a, b, c, d, e, f, g, h, + Add(K(0x748f82eeul), Inc(w8, sigma1(w6), w1, sigma0(w9)))); + Round(h, a, b, c, d, e, f, g, + Add(K(0x78a5636ful), Inc(w9, sigma1(w7), w2, sigma0(w10)))); + Round(g, h, a, b, c, d, e, f, + Add(K(0x84c87814ul), Inc(w10, sigma1(w8), w3, sigma0(w11)))); + Round(f, g, h, a, b, c, d, e, + Add(K(0x8cc70208ul), Inc(w11, sigma1(w9), w4, sigma0(w12)))); + Round(e, f, g, h, a, b, c, d, + Add(K(0x90befffaul), Inc(w12, sigma1(w10), w5, sigma0(w13)))); + Round(d, e, f, g, h, a, b, c, + Add(K(0xa4506cebul), Inc(w13, sigma1(w11), w6, sigma0(w14)))); + Round(c, d, e, f, g, h, a, b, + Add(K(0xbef9a3f7ul), w14, sigma1(w12), w7, sigma0(w15))); + Round(b, c, d, e, f, g, h, a, + Add(K(0xc67178f2ul), w15, sigma1(w13), w8, sigma0(w0))); + + // Output + Write4(out, 0, Add(a, K(0x6a09e667ul))); + Write4(out, 4, Add(b, K(0xbb67ae85ul))); + Write4(out, 8, Add(c, K(0x3c6ef372ul))); + Write4(out, 12, Add(d, K(0xa54ff53aul))); + Write4(out, 16, Add(e, K(0x510e527ful))); + Write4(out, 20, Add(f, K(0x9b05688cul))); + Write4(out, 24, Add(g, K(0x1f83d9abul))); + Write4(out, 28, Add(h, K(0x5be0cd19ul))); +} +} + +#endif diff --git a/src/test/crypto_tests.cpp b/src/test/crypto_tests.cpp index bf51222be9..c608d08858 100644 --- a/src/test/crypto_tests.cpp +++ b/src/test/crypto_tests.cpp @@ -1,630 +1,645 @@ // Copyright (c) 2014-2016 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "crypto/aes.h" #include "crypto/chacha20.h" #include "crypto/hmac_sha256.h" #include "crypto/hmac_sha512.h" #include "crypto/ripemd160.h" #include "crypto/sha1.h" #include "crypto/sha256.h" #include "crypto/sha512.h" #include "random.h" #include "test/test_bitcoin.h" #include "utilstrencodings.h" #include #include #include #include BOOST_FIXTURE_TEST_SUITE(crypto_tests, BasicTestingSetup) template void TestVector(const Hasher &h, const In &in, const Out &out) { Out hash; BOOST_CHECK(out.size() == h.OUTPUT_SIZE); hash.resize(out.size()); { // Test that writing the whole input string at once works. Hasher(h).Write((uint8_t *)&in[0], in.size()).Finalize(&hash[0]); BOOST_CHECK(hash == out); } for (int i = 0; i < 32; i++) { // Test that writing the string broken up in random pieces works. Hasher hasher(h); size_t pos = 0; while (pos < in.size()) { size_t len = InsecureRandRange((in.size() - pos + 1) / 2 + 1); hasher.Write((uint8_t *)&in[pos], len); pos += len; if (pos > 0 && pos + 2 * out.size() > in.size() && pos < in.size()) { // Test that writing the rest at once to a copy of a hasher // works. Hasher(hasher) .Write((uint8_t *)&in[pos], in.size() - pos) .Finalize(&hash[0]); BOOST_CHECK(hash == out); } } hasher.Finalize(&hash[0]); BOOST_CHECK(hash == out); } } void TestSHA1(const std::string &in, const std::string &hexout) { TestVector(CSHA1(), in, ParseHex(hexout)); } void TestSHA256(const std::string &in, const std::string &hexout) { TestVector(CSHA256(), in, ParseHex(hexout)); } void TestSHA512(const std::string &in, const std::string &hexout) { TestVector(CSHA512(), in, ParseHex(hexout)); } void TestRIPEMD160(const std::string &in, const std::string &hexout) { TestVector(CRIPEMD160(), in, ParseHex(hexout)); } void TestHMACSHA256(const std::string &hexkey, const std::string &hexin, const std::string &hexout) { std::vector key = ParseHex(hexkey); TestVector(CHMAC_SHA256(&key[0], key.size()), ParseHex(hexin), ParseHex(hexout)); } void TestHMACSHA512(const std::string &hexkey, const std::string &hexin, const std::string &hexout) { std::vector key = ParseHex(hexkey); TestVector(CHMAC_SHA512(&key[0], key.size()), ParseHex(hexin), ParseHex(hexout)); } void TestAES128(const std::string &hexkey, const std::string &hexin, const std::string &hexout) { std::vector key = ParseHex(hexkey); std::vector in = ParseHex(hexin); std::vector correctout = ParseHex(hexout); std::vector buf, buf2; assert(key.size() == 16); assert(in.size() == 16); assert(correctout.size() == 16); AES128Encrypt enc(&key[0]); buf.resize(correctout.size()); buf2.resize(correctout.size()); enc.Encrypt(&buf[0], &in[0]); BOOST_CHECK_EQUAL(HexStr(buf), HexStr(correctout)); AES128Decrypt dec(&key[0]); dec.Decrypt(&buf2[0], &buf[0]); BOOST_CHECK_EQUAL(HexStr(buf2), HexStr(in)); } void TestAES256(const std::string &hexkey, const std::string &hexin, const std::string &hexout) { std::vector key = ParseHex(hexkey); std::vector in = ParseHex(hexin); std::vector correctout = ParseHex(hexout); std::vector buf; assert(key.size() == 32); assert(in.size() == 16); assert(correctout.size() == 16); AES256Encrypt enc(&key[0]); buf.resize(correctout.size()); enc.Encrypt(&buf[0], &in[0]); BOOST_CHECK(buf == correctout); AES256Decrypt dec(&key[0]); dec.Decrypt(&buf[0], &buf[0]); BOOST_CHECK(buf == in); } void TestAES128CBC(const std::string &hexkey, const std::string &hexiv, bool pad, const std::string &hexin, const std::string &hexout) { std::vector key = ParseHex(hexkey); std::vector iv = ParseHex(hexiv); std::vector in = ParseHex(hexin); std::vector correctout = ParseHex(hexout); std::vector realout(in.size() + AES_BLOCKSIZE); // Encrypt the plaintext and verify that it equals the cipher AES128CBCEncrypt enc(&key[0], &iv[0], pad); int size = enc.Encrypt(&in[0], in.size(), &realout[0]); realout.resize(size); BOOST_CHECK(realout.size() == correctout.size()); BOOST_CHECK_MESSAGE(realout == correctout, HexStr(realout) + std::string(" != ") + hexout); // Decrypt the cipher and verify that it equals the plaintext std::vector decrypted(correctout.size()); AES128CBCDecrypt dec(&key[0], &iv[0], pad); size = dec.Decrypt(&correctout[0], correctout.size(), &decrypted[0]); decrypted.resize(size); BOOST_CHECK(decrypted.size() == in.size()); BOOST_CHECK_MESSAGE(decrypted == in, HexStr(decrypted) + std::string(" != ") + hexin); // Encrypt and re-decrypt substrings of the plaintext and verify that they // equal each-other for (std::vector::iterator i(in.begin()); i != in.end(); ++i) { std::vector sub(i, in.end()); std::vector subout(sub.size() + AES_BLOCKSIZE); int _size = enc.Encrypt(&sub[0], sub.size(), &subout[0]); if (_size != 0) { subout.resize(_size); std::vector subdecrypted(subout.size()); _size = dec.Decrypt(&subout[0], subout.size(), &subdecrypted[0]); subdecrypted.resize(_size); BOOST_CHECK(decrypted.size() == in.size()); BOOST_CHECK_MESSAGE(subdecrypted == sub, HexStr(subdecrypted) + std::string(" != ") + HexStr(sub)); } } } void TestAES256CBC(const std::string &hexkey, const std::string &hexiv, bool pad, const std::string &hexin, const std::string &hexout) { std::vector key = ParseHex(hexkey); std::vector iv = ParseHex(hexiv); std::vector in = ParseHex(hexin); std::vector correctout = ParseHex(hexout); std::vector realout(in.size() + AES_BLOCKSIZE); // Encrypt the plaintext and verify that it equals the cipher AES256CBCEncrypt enc(&key[0], &iv[0], pad); int size = enc.Encrypt(&in[0], in.size(), &realout[0]); realout.resize(size); BOOST_CHECK(realout.size() == correctout.size()); BOOST_CHECK_MESSAGE(realout == correctout, HexStr(realout) + std::string(" != ") + hexout); // Decrypt the cipher and verify that it equals the plaintext std::vector decrypted(correctout.size()); AES256CBCDecrypt dec(&key[0], &iv[0], pad); size = dec.Decrypt(&correctout[0], correctout.size(), &decrypted[0]); decrypted.resize(size); BOOST_CHECK(decrypted.size() == in.size()); BOOST_CHECK_MESSAGE(decrypted == in, HexStr(decrypted) + std::string(" != ") + hexin); // Encrypt and re-decrypt substrings of the plaintext and verify that they // equal each-other for (std::vector::iterator i(in.begin()); i != in.end(); ++i) { std::vector sub(i, in.end()); std::vector subout(sub.size() + AES_BLOCKSIZE); int _size = enc.Encrypt(&sub[0], sub.size(), &subout[0]); if (_size != 0) { subout.resize(_size); std::vector subdecrypted(subout.size()); _size = dec.Decrypt(&subout[0], subout.size(), &subdecrypted[0]); subdecrypted.resize(_size); BOOST_CHECK(decrypted.size() == in.size()); BOOST_CHECK_MESSAGE(subdecrypted == sub, HexStr(subdecrypted) + std::string(" != ") + HexStr(sub)); } } } void TestChaCha20(const std::string &hexkey, uint64_t nonce, uint64_t seek, const std::string &hexout) { std::vector key = ParseHex(hexkey); ChaCha20 rng(key.data(), key.size()); rng.SetIV(nonce); rng.Seek(seek); std::vector out = ParseHex(hexout); std::vector outres; outres.resize(out.size()); rng.Output(outres.data(), outres.size()); BOOST_CHECK(out == outres); } std::string LongTestString(void) { std::string ret; for (int i = 0; i < 200000; i++) { ret += uint8_t(i); ret += uint8_t(i >> 4); ret += uint8_t(i >> 8); ret += uint8_t(i >> 12); ret += uint8_t(i >> 16); } return ret; } const std::string test1 = LongTestString(); BOOST_AUTO_TEST_CASE(ripemd160_testvectors) { TestRIPEMD160("", "9c1185a5c5e9fc54612808977ee8f548b2258d31"); TestRIPEMD160("abc", "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc"); TestRIPEMD160("message digest", "5d0689ef49d2fae572b881b123a85ffa21595f36"); TestRIPEMD160("secure hash algorithm", "20397528223b6a5f4cbc2808aba0464e645544f9"); TestRIPEMD160("RIPEMD160 is considered to be safe", "a7d78608c7af8a8e728778e81576870734122b66"); TestRIPEMD160("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", "12a053384a9c0c88e405a06c27dcf49ada62eb2b"); TestRIPEMD160( "For this sample, this 63-byte string will be used as input data", "de90dbfee14b63fb5abf27c2ad4a82aaa5f27a11"); TestRIPEMD160( "This is exactly 64 bytes long, not counting the terminating byte", "eda31d51d3a623b81e19eb02e24ff65d27d67b37"); TestRIPEMD160(std::string(1000000, 'a'), "52783243c1697bdbe16d37f97f68f08325dc1528"); TestRIPEMD160(test1, "464243587bd146ea835cdf57bdae582f25ec45f1"); } BOOST_AUTO_TEST_CASE(sha1_testvectors) { TestSHA1("", "da39a3ee5e6b4b0d3255bfef95601890afd80709"); TestSHA1("abc", "a9993e364706816aba3e25717850c26c9cd0d89d"); TestSHA1("message digest", "c12252ceda8be8994d5fa0290a47231c1d16aae3"); TestSHA1("secure hash algorithm", "d4d6d2f0ebe317513bbd8d967d89bac5819c2f60"); TestSHA1("SHA1 is considered to be safe", "f2b6650569ad3a8720348dd6ea6c497dee3a842a"); TestSHA1("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", "84983e441c3bd26ebaae4aa1f95129e5e54670f1"); TestSHA1("For this sample, this 63-byte string will be used as input data", "4f0ea5cd0585a23d028abdc1a6684e5a8094dc49"); TestSHA1("This is exactly 64 bytes long, not counting the terminating byte", "fb679f23e7d1ce053313e66e127ab1b444397057"); TestSHA1(std::string(1000000, 'a'), "34aa973cd4c4daa4f61eeb2bdbad27316534016f"); TestSHA1(test1, "b7755760681cbfd971451668f32af5774f4656b5"); } BOOST_AUTO_TEST_CASE(sha256_testvectors) { TestSHA256( "", "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"); TestSHA256( "abc", "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"); TestSHA256( "message digest", "f7846f55cf23e14eebeab5b4e1550cad5b509e3348fbc4efa3a1413d393cb650"); TestSHA256( "secure hash algorithm", "f30ceb2bb2829e79e4ca9753d35a8ecc00262d164cc077080295381cbd643f0d"); TestSHA256( "SHA256 is considered to be safe", "6819d915c73f4d1e77e4e1b52d1fa0f9cf9beaead3939f15874bd988e2a23630"); TestSHA256( "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1"); TestSHA256( "For this sample, this 63-byte string will be used as input data", "f08a78cbbaee082b052ae0708f32fa1e50c5c421aa772ba5dbb406a2ea6be342"); TestSHA256( "This is exactly 64 bytes long, not counting the terminating byte", "ab64eff7e88e2e46165e29f2bce41826bd4c7b3552f6b382a9e7d3af47c245f8"); TestSHA256( "As Bitcoin relies on 80 byte header hashes, we want to have an " "example for that.", "7406e8de7d6e4fffc573daef05aefb8806e7790f55eab5576f31349743cca743"); TestSHA256( std::string(1000000, 'a'), "cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0"); TestSHA256( test1, "a316d55510b49662420f49d145d42fb83f31ef8dc016aa4e32df049991a91e26"); } BOOST_AUTO_TEST_CASE(sha512_testvectors) { TestSHA512( "", "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce" "47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"); TestSHA512( "abc", "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a" "2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"); TestSHA512( "message digest", "107dbf389d9e9f71a3a95f6c055b9251bc5268c2be16d6c13492ea45b0199f33" "09e16455ab1e96118e8a905d5597b72038ddb372a89826046de66687bb420e7c"); TestSHA512( "secure hash algorithm", "7746d91f3de30c68cec0dd693120a7e8b04d8073cb699bdce1a3f64127bca7a3" "d5db502e814bb63c063a7a5043b2df87c61133395f4ad1edca7fcf4b30c3236e"); TestSHA512( "SHA512 is considered to be safe", "099e6468d889e1c79092a89ae925a9499b5408e01b66cb5b0a3bd0dfa51a9964" "6b4a3901caab1318189f74cd8cf2e941829012f2449df52067d3dd5b978456c2"); TestSHA512( "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", "204a8fc6dda82f0a0ced7beb8e08a41657c16ef468b228a8279be331a703c335" "96fd15c13b1b07f9aa1d3bea57789ca031ad85c7a71dd70354ec631238ca3445"); TestSHA512( "For this sample, this 63-byte string will be used as input data", "b3de4afbc516d2478fe9b518d063bda6c8dd65fc38402dd81d1eb7364e72fb6e" "6663cf6d2771c8f5a6da09601712fb3d2a36c6ffea3e28b0818b05b0a8660766"); TestSHA512( "This is exactly 64 bytes long, not counting the terminating byte", "70aefeaa0e7ac4f8fe17532d7185a289bee3b428d950c14fa8b713ca09814a38" "7d245870e007a80ad97c369d193e41701aa07f3221d15f0e65a1ff970cedf030"); TestSHA512( "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmno" "ijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", "8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018" "501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909"); TestSHA512( std::string(1000000, 'a'), "e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973eb" "de0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b"); TestSHA512( test1, "40cac46c147e6131c5193dd5f34e9d8bb4951395f27b08c558c65ff4ba2de594" "37de8c3ef5459d76a52cedc02dc499a3c9ed9dedbfb3281afd9653b8a112fafc"); } BOOST_AUTO_TEST_CASE(hmac_sha256_testvectors) { // test cases 1, 2, 3, 4, 6 and 7 of RFC 4231 TestHMACSHA256( "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", "4869205468657265", "b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7"); TestHMACSHA256( "4a656665", "7768617420646f2079612077616e7420666f72206e6f7468696e673f", "5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843"); TestHMACSHA256( "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd" "dddddddddddddddddddddddddddddddddddd", "773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe"); TestHMACSHA256( "0102030405060708090a0b0c0d0e0f10111213141516171819", "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd" "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd", "82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b"); TestHMACSHA256( "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaa", "54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a" "65204b6579202d2048617368204b6579204669727374", "60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54"); TestHMACSHA256( "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaa", "5468697320697320612074657374207573696e672061206c6172676572207468" "616e20626c6f636b2d73697a65206b657920616e642061206c61726765722074" "68616e20626c6f636b2d73697a6520646174612e20546865206b6579206e6565" "647320746f20626520686173686564206265666f7265206265696e6720757365" "642062792074686520484d414320616c676f726974686d2e", "9b09ffa71b942fcb27635fbcd5b0e944bfdc63644f0713938a7f51535c3a35e2"); } BOOST_AUTO_TEST_CASE(hmac_sha512_testvectors) { // test cases 1, 2, 3, 4, 6 and 7 of RFC 4231 TestHMACSHA512( "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", "4869205468657265", "87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cde" "daa833b7d6b8a702038b274eaea3f4e4be9d914eeb61f1702e696c203a126854"); TestHMACSHA512( "4a656665", "7768617420646f2079612077616e7420666f72206e6f7468696e673f", "164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea250554" "9758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737"); TestHMACSHA512( "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd" "dddddddddddddddddddddddddddddddddddd", "fa73b0089d56a284efb0f0756c890be9b1b5dbdd8ee81a3655f83e33b2279d39" "bf3e848279a722c806b485a47e67c807b946a337bee8942674278859e13292fb"); TestHMACSHA512( "0102030405060708090a0b0c0d0e0f10111213141516171819", "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd" "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd", "b0ba465637458c6990e5a8c5f61d4af7e576d97ff94b872de76f8050361ee3db" "a91ca5c11aa25eb4d679275cc5788063a5f19741120c4f2de2adebeb10a298dd"); TestHMACSHA512( "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaa", "54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a" "65204b6579202d2048617368204b6579204669727374", "80b24263c7c1a3ebb71493c1dd7be8b49b46d1f41b4aeec1121b013783f8f352" "6b56d037e05f2598bd0fd2215d6a1e5295e64f73f63f0aec8b915a985d786598"); TestHMACSHA512( "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaa", "5468697320697320612074657374207573696e672061206c6172676572207468" "616e20626c6f636b2d73697a65206b657920616e642061206c61726765722074" "68616e20626c6f636b2d73697a6520646174612e20546865206b6579206e6565" "647320746f20626520686173686564206265666f7265206265696e6720757365" "642062792074686520484d414320616c676f726974686d2e", "e37b6a775dc87dbaa4dfa9f96e5e3ffddebd71f8867289865df5a32d20cdc944" "b6022cac3c4982b10d5eeb55c3e4de15134676fb6de0446065c97440fa8c6a58"); } BOOST_AUTO_TEST_CASE(aes_testvectors) { // AES test vectors from FIPS 197. TestAES128("000102030405060708090a0b0c0d0e0f", "00112233445566778899aabbccddeeff", "69c4e0d86a7b0430d8cdb78070b4c55a"); TestAES256( "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "00112233445566778899aabbccddeeff", "8ea2b7ca516745bfeafc49904b496089"); // AES-ECB test vectors from NIST sp800-38a. TestAES128("2b7e151628aed2a6abf7158809cf4f3c", "6bc1bee22e409f96e93d7e117393172a", "3ad77bb40d7a3660a89ecaf32466ef97"); TestAES128("2b7e151628aed2a6abf7158809cf4f3c", "ae2d8a571e03ac9c9eb76fac45af8e51", "f5d3d58503b9699de785895a96fdbaaf"); TestAES128("2b7e151628aed2a6abf7158809cf4f3c", "30c81c46a35ce411e5fbc1191a0a52ef", "43b1cd7f598ece23881b00e3ed030688"); TestAES128("2b7e151628aed2a6abf7158809cf4f3c", "f69f2445df4f9b17ad2b417be66c3710", "7b0c785e27e8ad3f8223207104725dd4"); TestAES256( "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", "6bc1bee22e409f96e93d7e117393172a", "f3eed1bdb5d2a03c064b5a7e3db181f8"); TestAES256( "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", "ae2d8a571e03ac9c9eb76fac45af8e51", "591ccb10d410ed26dc5ba74a31362870"); TestAES256( "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", "30c81c46a35ce411e5fbc1191a0a52ef", "b6ed21b99ca6f4f9f153e7b1beafed1d"); TestAES256( "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", "f69f2445df4f9b17ad2b417be66c3710", "23304b7a39f9f3ff067d8d8f9e24ecc7"); } BOOST_AUTO_TEST_CASE(aes_cbc_testvectors) { // NIST AES CBC 128-bit encryption test-vectors TestAES128CBC("2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090A0B0C0D0E0F", false, "6bc1bee22e409f96e93d7e117393172a", "7649abac8119b246cee98e9b12e9197d"); TestAES128CBC("2b7e151628aed2a6abf7158809cf4f3c", "7649ABAC8119B246CEE98E9B12E9197D", false, "ae2d8a571e03ac9c9eb76fac45af8e51", "5086cb9b507219ee95db113a917678b2"); TestAES128CBC("2b7e151628aed2a6abf7158809cf4f3c", "5086cb9b507219ee95db113a917678b2", false, "30c81c46a35ce411e5fbc1191a0a52ef", "73bed6b8e3c1743b7116e69e22229516"); TestAES128CBC("2b7e151628aed2a6abf7158809cf4f3c", "73bed6b8e3c1743b7116e69e22229516", false, "f69f2445df4f9b17ad2b417be66c3710", "3ff1caa1681fac09120eca307586e1a7"); // The same vectors with padding enabled TestAES128CBC( "2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090A0B0C0D0E0F", true, "6bc1bee22e409f96e93d7e117393172a", "7649abac8119b246cee98e9b12e9197d8964e0b149c10b7b682e6e39aaeb731c"); TestAES128CBC( "2b7e151628aed2a6abf7158809cf4f3c", "7649ABAC8119B246CEE98E9B12E9197D", true, "ae2d8a571e03ac9c9eb76fac45af8e51", "5086cb9b507219ee95db113a917678b255e21d7100b988ffec32feeafaf23538"); TestAES128CBC( "2b7e151628aed2a6abf7158809cf4f3c", "5086cb9b507219ee95db113a917678b2", true, "30c81c46a35ce411e5fbc1191a0a52ef", "73bed6b8e3c1743b7116e69e22229516f6eccda327bf8e5ec43718b0039adceb"); TestAES128CBC( "2b7e151628aed2a6abf7158809cf4f3c", "73bed6b8e3c1743b7116e69e22229516", true, "f69f2445df4f9b17ad2b417be66c3710", "3ff1caa1681fac09120eca307586e1a78cb82807230e1321d3fae00d18cc2012"); // NIST AES CBC 256-bit encryption test-vectors TestAES256CBC( "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", "000102030405060708090A0B0C0D0E0F", false, "6bc1bee22e409f96e93d7e117393172a", "f58c4c04d6e5f1ba779eabfb5f7bfbd6"); TestAES256CBC( "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", "F58C4C04D6E5F1BA779EABFB5F7BFBD6", false, "ae2d8a571e03ac9c9eb76fac45af8e51", "9cfc4e967edb808d679f777bc6702c7d"); TestAES256CBC( "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", "9CFC4E967EDB808D679F777BC6702C7D", false, "30c81c46a35ce411e5fbc1191a0a52ef", "39f23369a9d9bacfa530e26304231461"); TestAES256CBC( "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", "39F23369A9D9BACFA530E26304231461", false, "f69f2445df4f9b17ad2b417be66c3710", "b2eb05e2c39be9fcda6c19078c6a9d1b"); // The same vectors with padding enabled TestAES256CBC( "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", "000102030405060708090A0B0C0D0E0F", true, "6bc1bee22e409f96e93d7e117393172a", "f58c4c04d6e5f1ba779eabfb5f7bfbd6485a5c81519cf378fa36d42b8547edc0"); TestAES256CBC( "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", "F58C4C04D6E5F1BA779EABFB5F7BFBD6", true, "ae2d8a571e03ac9c9eb76fac45af8e51", "9cfc4e967edb808d679f777bc6702c7d3a3aa5e0213db1a9901f9036cf5102d2"); TestAES256CBC( "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", "9CFC4E967EDB808D679F777BC6702C7D", true, "30c81c46a35ce411e5fbc1191a0a52ef", "39f23369a9d9bacfa530e263042314612f8da707643c90a6f732b3de1d3f5cee"); TestAES256CBC( "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", "39F23369A9D9BACFA530E26304231461", true, "f69f2445df4f9b17ad2b417be66c3710", "b2eb05e2c39be9fcda6c19078c6a9d1b3f461796d6b0d6b2e0c2a72b4d80e644"); } BOOST_AUTO_TEST_CASE(chacha20_testvector) { // Test vector from RFC 7539 TestChaCha20( "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", 0x4a000000UL, 1, "224f51f3401bd9e12fde276fb8631ded8c131f823d2c06e27e4fc" "aec9ef3cf788a3b0aa372600a92b57974cded2b9334794cba40c6" "3e34cdea212c4cf07d41b769a6749f3f630f4122cafe28ec4dc47" "e26d4346d70b98c73f3e9c53ac40c5945398b6eda1a832c89c167" "eacd901d7e2bf363"); // Test vectors from // https://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04#section-7 TestChaCha20( "0000000000000000000000000000000000000000000000000000000000000000", 0, 0, "76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc8b770dc7da4" "1597c5157488d7724e03fb8d84a376a43b8f41518a11cc387b669b2ee6586"); TestChaCha20( "0000000000000000000000000000000000000000000000000000000000000001", 0, 0, "4540f05a9f1fb296d7736e7b208e3c96eb4fe1834688d2604f450952ed432d41bbe" "2a0b6ea7566d2a5d1e7e20d42af2c53d792b1c43fea817e9ad275ae546963"); TestChaCha20( "0000000000000000000000000000000000000000000000000000000000000000", 0x0100000000000000ULL, 0, "de9cba7bf3d69ef5e786dc63973f653a0b49e015adbf" "f7134fcb7df137821031e85a050278a7084527214f73" "efc7fa5b5277062eb7a0433e445f41e3"); TestChaCha20( "0000000000000000000000000000000000000000000000000000000000000000", 1, 0, "ef3fdfd6c61578fbf5cf35bd3dd33b8009631634d21e42ac33960bd138e50d32111" "e4caf237ee53ca8ad6426194a88545ddc497a0b466e7d6bbdb0041b2f586b"); TestChaCha20( "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", 0x0706050403020100ULL, 0, "f798a189f195e66982105ffb640bb7757f579da31602fc93ec01ac56f85ac3c134a454" "7b733b46413042c9440049176905d3be59ea1c53f15916155c2be8241a38008b9a26bc" "35941e2444177c8ade6689de95264986d95889fb60e84629c9bd9a5acb1cc118be563e" "b9b3a4a472f82e09a7e778492b562ef7130e88dfe031c79db9d4f7c7a899151b9a4750" "32b63fc385245fe054e3dd5a97a5f576fe064025d3ce042c566ab2c507b138db853e3d" "6959660996546cc9c4a6eafdc777c040d70eaf46f76dad3979e5c5360c3317166a1c89" "4c94a371876a94df7628fe4eaaf2ccb27d5aaae0ad7ad0f9d4b6ad3b54098746d4524d" "38407a6deb3ab78fab78c9"); } BOOST_AUTO_TEST_CASE(countbits_tests) { FastRandomContext ctx; for (int i = 0; i <= 64; ++i) { if (i == 0) { // Check handling of zero. BOOST_CHECK_EQUAL(CountBits(0), 0); } else if (i < 10) { for (uint64_t j = 1 << (i - 1); (j >> i) == 0; ++j) { // Exhaustively test up to 10 bits BOOST_CHECK_EQUAL(CountBits(j), i); } } else { for (int k = 0; k < 1000; k++) { // Randomly test 1000 samples of each length above 10 bits. uint64_t j = uint64_t(1) << (i - 1) | ctx.randbits(i - 1); BOOST_CHECK_EQUAL(CountBits(j), i); } } } } +BOOST_AUTO_TEST_CASE(sha256d64) { + for (int i = 0; i <= 32; ++i) { + uint8_t in[64 * 32]; + uint8_t out1[32 * 32], out2[32 * 32]; + for (int j = 0; j < 64 * i; ++j) { + in[j] = InsecureRandBits(8); + } + for (int j = 0; j < i; ++j) { + CHash256().Write(in + 64 * j, 64).Finalize(out1 + 32 * j); + } + SHA256D64(out2, in, i); + BOOST_CHECK(memcmp(out1, out2, 32 * i) == 0); + } +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/merkle_tests.cpp b/src/test/merkle_tests.cpp index 205ce69ca9..dcfd532e57 100644 --- a/src/test/merkle_tests.cpp +++ b/src/test/merkle_tests.cpp @@ -1,155 +1,292 @@ // Copyright (c) 2015-2016 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "consensus/merkle.h" #include "test/test_bitcoin.h" #include BOOST_FIXTURE_TEST_SUITE(merkle_tests, TestingSetup) +static uint256 +ComputeMerkleRootFromBranch(const uint256 &leaf, + const std::vector &vMerkleBranch, + uint32_t nIndex) { + uint256 hash = leaf; + for (std::vector::const_iterator it = vMerkleBranch.begin(); + it != vMerkleBranch.end(); ++it) { + if (nIndex & 1) { + hash = Hash(BEGIN(*it), END(*it), BEGIN(hash), END(hash)); + } else { + hash = Hash(BEGIN(hash), END(hash), BEGIN(*it), END(*it)); + } + nIndex >>= 1; + } + return hash; +} + +/** + * This implements a constant-space merkle root/path calculator, limited to 2^32 + * leaves. + */ +static void MerkleComputation(const std::vector &leaves, + uint256 *proot, bool *pmutated, + uint32_t branchpos, + std::vector *pbranch) { + if (pbranch) pbranch->clear(); + if (leaves.size() == 0) { + if (pmutated) *pmutated = false; + if (proot) *proot = uint256(); + return; + } + bool mutated = false; + // count is the number of leaves processed so far. + uint32_t count = 0; + // inner is an array of eagerly computed subtree hashes, indexed by tree + // level (0 being the leaves). + // For example, when count is 25 (11001 in binary), inner[4] is the hash of + // the first 16 leaves, inner[3] of the next 8 leaves, and inner[0] equal to + // the last leaf. The other inner entries are undefined. + uint256 inner[32]; + // Which position in inner is a hash that depends on the matching leaf. + int matchlevel = -1; + // First process all leaves into 'inner' values. + while (count < leaves.size()) { + uint256 h = leaves[count]; + bool matchh = count == branchpos; + count++; + int level; + // For each of the lower bits in count that are 0, do 1 step. Each + // corresponds to an inner value that existed before processing the + // current leaf, and each needs a hash to combine it. + for (level = 0; !(count & (((uint32_t)1) << level)); level++) { + if (pbranch) { + if (matchh) { + pbranch->push_back(inner[level]); + } else if (matchlevel == level) { + pbranch->push_back(h); + matchh = true; + } + } + mutated |= (inner[level] == h); + CHash256() + .Write(inner[level].begin(), 32) + .Write(h.begin(), 32) + .Finalize(h.begin()); + } + // Store the resulting hash at inner position level. + inner[level] = h; + if (matchh) { + matchlevel = level; + } + } + // Do a final 'sweep' over the rightmost branch of the tree to process + // odd levels, and reduce everything to a single top value. + // Level is the level (counted from the bottom) up to which we've sweeped. + int level = 0; + // As long as bit number level in count is zero, skip it. It means there + // is nothing left at this level. + while (!(count & (((uint32_t)1) << level))) { + level++; + } + uint256 h = inner[level]; + bool matchh = matchlevel == level; + while (count != (((uint32_t)1) << level)) { + // If we reach this point, h is an inner value that is not the top. + // We combine it with itself (Bitcoin's special rule for odd levels in + // the tree) to produce a higher level one. + if (pbranch && matchh) { + pbranch->push_back(h); + } + CHash256() + .Write(h.begin(), 32) + .Write(h.begin(), 32) + .Finalize(h.begin()); + // Increment count to the value it would have if two entries at this + // level had existed. + count += (((uint32_t)1) << level); + level++; + // And propagate the result upwards accordingly. + while (!(count & (((uint32_t)1) << level))) { + if (pbranch) { + if (matchh) { + pbranch->push_back(inner[level]); + } else if (matchlevel == level) { + pbranch->push_back(h); + matchh = true; + } + } + CHash256() + .Write(inner[level].begin(), 32) + .Write(h.begin(), 32) + .Finalize(h.begin()); + level++; + } + } + // Return result. + if (pmutated) *pmutated = mutated; + if (proot) *proot = h; +} + +static std::vector +ComputeMerkleBranch(const std::vector &leaves, uint32_t position) { + std::vector ret; + MerkleComputation(leaves, nullptr, nullptr, position, &ret); + return ret; +} + +static std::vector BlockMerkleBranch(const CBlock &block, + uint32_t position) { + std::vector leaves; + leaves.resize(block.vtx.size()); + for (size_t s = 0; s < block.vtx.size(); s++) { + leaves[s] = block.vtx[s]->GetHash(); + } + return ComputeMerkleBranch(leaves, position); +} + // Older version of the merkle root computation code, for comparison. static uint256 BlockBuildMerkleTree(const CBlock &block, bool *fMutated, std::vector &vMerkleTree) { vMerkleTree.clear(); // Safe upper bound for the number of total nodes. vMerkleTree.reserve(block.vtx.size() * 2 + 16); for (std::vector::const_iterator it(block.vtx.begin()); it != block.vtx.end(); ++it) vMerkleTree.push_back((*it)->GetId()); int j = 0; bool mutated = false; for (int nSize = block.vtx.size(); nSize > 1; nSize = (nSize + 1) / 2) { for (int i = 0; i < nSize; i += 2) { int i2 = std::min(i + 1, nSize - 1); if (i2 == i + 1 && i2 + 1 == nSize && vMerkleTree[j + i] == vMerkleTree[j + i2]) { // Two identical hashes at the end of the list at a particular // level. mutated = true; } vMerkleTree.push_back( Hash(vMerkleTree[j + i].begin(), vMerkleTree[j + i].end(), vMerkleTree[j + i2].begin(), vMerkleTree[j + i2].end())); } j += nSize; } if (fMutated) { *fMutated = mutated; } return (vMerkleTree.empty() ? uint256() : vMerkleTree.back()); } // Older version of the merkle branch computation code, for comparison. static std::vector BlockGetMerkleBranch(const CBlock &block, const std::vector &vMerkleTree, int nIndex) { std::vector vMerkleBranch; int j = 0; for (int nSize = block.vtx.size(); nSize > 1; nSize = (nSize + 1) / 2) { int i = std::min(nIndex ^ 1, nSize - 1); vMerkleBranch.push_back(vMerkleTree[j + i]); nIndex >>= 1; j += nSize; } return vMerkleBranch; } static inline int ctz(uint32_t i) { if (i == 0) return 0; int j = 0; while (!(i & 1)) { j++; i >>= 1; } return j; } BOOST_AUTO_TEST_CASE(merkle_test) { for (int i = 0; i < 32; i++) { // Try 32 block sizes: all sizes from 0 to 16 inclusive, and then 15 // random sizes. int ntx = (i <= 16) ? i : 17 + (InsecureRandRange(4000)); // Try up to 3 mutations. for (int mutate = 0; mutate <= 3; mutate++) { // The last how many transactions to duplicate first. int duplicate1 = mutate >= 1 ? 1 << ctz(ntx) : 0; if (duplicate1 >= ntx) { // Duplication of the entire tree results in a different root // (it adds a level). break; } // The resulting number of transactions after the first duplication. int ntx1 = ntx + duplicate1; // Likewise for the second mutation. int duplicate2 = mutate >= 2 ? 1 << ctz(ntx1) : 0; if (duplicate2 >= ntx1) break; int ntx2 = ntx1 + duplicate2; // And for the third mutation. int duplicate3 = mutate >= 3 ? 1 << ctz(ntx2) : 0; if (duplicate3 >= ntx2) break; int ntx3 = ntx2 + duplicate3; // Build a block with ntx different transactions. CBlock block; block.vtx.resize(ntx); for (int j = 0; j < ntx; j++) { CMutableTransaction mtx; mtx.nLockTime = j; block.vtx[j] = MakeTransactionRef(std::move(mtx)); } // Compute the root of the block before mutating it. bool unmutatedMutated = false; uint256 unmutatedRoot = BlockMerkleRoot(block, &unmutatedMutated); BOOST_CHECK(unmutatedMutated == false); // Optionally mutate by duplicating the last transactions, resulting // in the same merkle root. block.vtx.resize(ntx3); for (int j = 0; j < duplicate1; j++) { block.vtx[ntx + j] = block.vtx[ntx + j - duplicate1]; } for (int j = 0; j < duplicate2; j++) { block.vtx[ntx1 + j] = block.vtx[ntx1 + j - duplicate2]; } for (int j = 0; j < duplicate3; j++) { block.vtx[ntx2 + j] = block.vtx[ntx2 + j - duplicate3]; } // Compute the merkle root and merkle tree using the old mechanism. bool oldMutated = false; std::vector merkleTree; uint256 oldRoot = BlockBuildMerkleTree(block, &oldMutated, merkleTree); // Compute the merkle root using the new mechanism. bool newMutated = false; uint256 newRoot = BlockMerkleRoot(block, &newMutated); BOOST_CHECK(oldRoot == newRoot); BOOST_CHECK(newRoot == unmutatedRoot); BOOST_CHECK((newRoot == uint256()) == (ntx == 0)); BOOST_CHECK(oldMutated == newMutated); BOOST_CHECK(newMutated == !!mutate); // If no mutation was done (once for every ntx value), try up to 16 // branches. if (mutate == 0) { for (int loop = 0; loop < std::min(ntx, 16); loop++) { // If ntx <= 16, try all branches. Otherise, try 16 random // ones. int mtx = loop; if (ntx > 16) { mtx = InsecureRandRange(ntx); } std::vector newBranch = BlockMerkleBranch(block, mtx); std::vector oldBranch = BlockGetMerkleBranch(block, merkleTree, mtx); BOOST_CHECK(oldBranch == newBranch); BOOST_CHECK( ComputeMerkleRootFromBranch(block.vtx[mtx]->GetId(), newBranch, mtx) == oldRoot); } } } } } BOOST_AUTO_TEST_SUITE_END()