diff --git a/.vscode.template/c_cpp_properties.json b/.vscode.template/c_cpp_properties.json new file mode 100644 index 00000000..fdf270fb --- /dev/null +++ b/.vscode.template/c_cpp_properties.json @@ -0,0 +1,16 @@ +{ + "configurations": [ + { + "name": "Linux", + "includePath": [ + "${workspaceFolder}/**" + ], + "defines": ["ENABLE_MINING","ENABLE_WALLET","USE_ASM"], + "compilerPath": "/usr/bin/g++", + "cStandard": "c11", + "cppStandard": "c++11", + "intelliSenseMode": "gcc-x64" + } + ], + "version": 4 +} \ No newline at end of file diff --git a/.vscode.template/launch.json b/.vscode.template/launch.json new file mode 100644 index 00000000..4b172a3f --- /dev/null +++ b/.vscode.template/launch.json @@ -0,0 +1,45 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "(gdb) Launch (komodo-qt)", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceFolder}/src/qt/komodo-qt", + "args": ["-minrelaytxfee=0.000035", "-opretmintxfee=0.004","-debug=mempool","-listen=0","-server=1"], + "stopAtEntry": false, + "cwd": "${workspaceFolder}", + "environment": [], + "externalConsole": true, + "MIMode": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ] + }, + { + "name": "(gdb) Launch (komodo-test)", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceFolder}/src/komodo-test", + "stopAtEntry": false, + "cwd": "${workspaceFolder}", + "environment": [], + "externalConsole": true, + "MIMode": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ] + } + ] +} \ No newline at end of file diff --git a/.vscode.template/settings.json b/.vscode.template/settings.json new file mode 100644 index 00000000..d93381f9 --- /dev/null +++ b/.vscode.template/settings.json @@ -0,0 +1,81 @@ +{ + "files.associations": { + "iostream": "cpp", + "array": "cpp", + "cctype": "cpp", + "cmath": "cpp", + "csignal": "cpp", + "cstdarg": "cpp", + "cstddef": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "atomic": "cpp", + "hash_map": "cpp", + "strstream": "cpp", + "*.tcc": "cpp", + "bitset": "cpp", + "chrono": "cpp", + "clocale": "cpp", + "complex": "cpp", + "condition_variable": "cpp", + "cstdint": "cpp", + "deque": "cpp", + "list": "cpp", + "unordered_map": "cpp", + "vector": "cpp", + "exception": "cpp", + "fstream": "cpp", + "functional": "cpp", + "future": "cpp", + "initializer_list": "cpp", + "iomanip": "cpp", + "iosfwd": "cpp", + "istream": "cpp", + "limits": "cpp", + "memory": "cpp", + "mutex": "cpp", + "new": "cpp", + "ostream": "cpp", + "numeric": "cpp", + "ratio": "cpp", + "sstream": "cpp", + "stdexcept": "cpp", + "streambuf": "cpp", + "system_error": "cpp", + "thread": "cpp", + "cinttypes": "cpp", + "type_traits": "cpp", + "tuple": "cpp", + "typeindex": "cpp", + "typeinfo": "cpp", + "utility": "cpp", + "optional": "cpp", + "string_view": "cpp", + "*.ipp": "cpp", + "csetjmp": "cpp", + "codecvt": "cpp", + "forward_list": "cpp", + "unordered_set": "cpp", + "algorithm": "cpp", + "filesystem": "cpp", + "rope": "cpp", + "slist": "cpp", + "scoped_allocator": "cpp", + "shared_mutex": "cpp", + "cfenv": "cpp", + "regex": "cpp", + "valarray": "cpp", + "string": "cpp", + "*.cuh": "cpp" + }, + // The following will hide unneeded files in the editor + "files.exclude": { + "**/*.o": true, + "**/*.a": true, + "**/*.lo": true + } +} \ No newline at end of file diff --git a/build-aux/m4/bitcoin_qt.m4 b/build-aux/m4/bitcoin_qt.m4 index 1a7c5d5f..43bf3a22 100644 --- a/build-aux/m4/bitcoin_qt.m4 +++ b/build-aux/m4/bitcoin_qt.m4 @@ -116,8 +116,10 @@ AC_DEFUN([BITCOIN_QT_CONFIGURE],[ if test "x$bitcoin_cv_static_qt" = xyes; then _BITCOIN_QT_FIND_STATIC_PLUGINS AC_DEFINE(QT_STATICPLUGIN, 1, [Define this symbol if qt plugins are static]) + if test "x$TARGET_OS" != xandroid; then _BITCOIN_QT_CHECK_STATIC_PLUGINS([Q_IMPORT_PLUGIN(QMinimalIntegrationPlugin)],[-lqminimal]) AC_DEFINE(QT_QPA_PLATFORM_MINIMAL, 1, [Define this symbol if the minimal qt platform exists]) + fi if test "x$TARGET_OS" = xwindows; then _BITCOIN_QT_CHECK_STATIC_PLUGINS([Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin)],[-lqwindows]) AC_DEFINE(QT_QPA_PLATFORM_WINDOWS, 1, [Define this symbol if the qt platform is windows]) @@ -128,6 +130,9 @@ AC_DEFUN([BITCOIN_QT_CONFIGURE],[ AX_CHECK_LINK_FLAG([[-framework IOKit]],[QT_LIBS="$QT_LIBS -framework IOKit"],[AC_MSG_ERROR(could not iokit framework)]) _BITCOIN_QT_CHECK_STATIC_PLUGINS([Q_IMPORT_PLUGIN(QCocoaIntegrationPlugin)],[-lqcocoa]) AC_DEFINE(QT_QPA_PLATFORM_COCOA, 1, [Define this symbol if the qt platform is cocoa]) + elif test "x$TARGET_OS" = xandroid; then + QT_LIBS="-Wl,--export-dynamic,--undefined=JNI_OnLoad -lqtforandroid -ljnigraphics -landroid -lqtfreetype -lQt5EglSupport $QT_LIBS" + AC_DEFINE(QT_QPA_PLATFORM_ANDROID, 1, [Define this symbol if the qt platform is android]) fi fi CPPFLAGS=$TEMP_CPPFLAGS @@ -228,7 +233,11 @@ AC_DEFUN([BITCOIN_QT_CONFIGURE],[ ],[ bitcoin_enable_qt=no ]) - AC_MSG_RESULT([$bitcoin_enable_qt (Qt5)]) + if test x$bitcoin_enable_qt = xyes; then + AC_MSG_RESULT([$bitcoin_enable_qt ($QT_LIB_PREFIX)]) + else + AC_MSG_RESULT([$bitcoin_enable_qt]) + fi AC_SUBST(QT_PIE_FLAGS) AC_SUBST(QT_INCLUDES) @@ -268,7 +277,7 @@ AC_DEFUN([_BITCOIN_QT_CHECK_QT5],[ dnl Internal. Check if the included version of Qt is greater than Qt58. dnl Requires: INCLUDES must be populated as necessary. -dnl Output: bitcoin_cv_qt5=yes|no +dnl Output: bitcoin_cv_qt58=yes|no AC_DEFUN([_BITCOIN_QT_CHECK_QT58],[ AC_CACHE_CHECK(for > Qt 5.7, bitcoin_cv_qt58,[ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ @@ -341,6 +350,9 @@ AC_DEFUN([_BITCOIN_QT_FIND_STATIC_PLUGINS],[ if test -d "$qt_plugin_path/accessible"; then QT_LIBS="$QT_LIBS -L$qt_plugin_path/accessible" fi + if test -d "$qt_plugin_path/platforms/android"; then + QT_LIBS="$QT_LIBS -L$qt_plugin_path/platforms/android -lqtfreetype -lEGL" + fi if test "x$use_pkgconfig" = xyes; then : dnl m4_ifdef([PKG_CHECK_MODULES],[ @@ -355,7 +367,6 @@ AC_DEFUN([_BITCOIN_QT_FIND_STATIC_PLUGINS],[ PKG_CHECK_MODULES([QTFB], [Qt5FbSupport], [QT_LIBS="-lQt5FbSupport $QT_LIBS"]) fi if test "x$TARGET_OS" = xlinux; then - PKG_CHECK_MODULES([X11XCB], [x11-xcb], [QT_LIBS="$X11XCB_LIBS $QT_LIBS"]) PKG_CHECK_MODULES([QTXCBQPA], [Qt5XcbQpa], [QT_LIBS="$QTXCBQPA_LIBS $QT_LIBS"]) elif test "x$TARGET_OS" = xdarwin; then PKG_CHECK_MODULES([QTCLIPBOARD], [Qt5ClipboardSupport], [QT_LIBS="-lQt5ClipboardSupport $QT_LIBS"]) @@ -469,7 +480,6 @@ AC_DEFUN([_BITCOIN_QT_FIND_LIBS_WITHOUT_PKGCONFIG],[ ]) BITCOIN_QT_CHECK(AC_CHECK_LIB([z] ,[main],,AC_MSG_WARN([zlib not found. Assuming qt has it built-in]))) - BITCOIN_QT_CHECK(AC_SEARCH_LIBS([jpeg_create_decompress] ,[qtjpeg jpeg],,AC_MSG_WARN([libjpeg not found. Assuming qt has it built-in]))) if test x$bitcoin_cv_qt58 = xno; then BITCOIN_QT_CHECK(AC_SEARCH_LIBS([png_error] ,[qtpng png],,AC_MSG_WARN([libpng not found. Assuming qt has it built-in]))) BITCOIN_QT_CHECK(AC_SEARCH_LIBS([pcre16_exec], [qtpcre pcre16],,AC_MSG_WARN([libpcre16 not found. Assuming qt has it built-in]))) diff --git a/configure.ac b/configure.ac index 672bf382..05fb7fd4 100644 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 3) define(_CLIENT_VERSION_MINOR, 0) define(_CLIENT_VERSION_REVISION, 1) -define(_CLIENT_VERSION_BUILD, 1) +define(_CLIENT_VERSION_BUILD, 2) define(_ZC_BUILD_VAL, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, m4_incr(_CLIENT_VERSION_BUILD), m4_eval(_CLIENT_VERSION_BUILD < 50), 1, m4_eval(_CLIENT_VERSION_BUILD - 24), m4_eval(_CLIENT_VERSION_BUILD == 50), 1, , m4_eval(_CLIENT_VERSION_BUILD - 50))) define(_CLIENT_VERSION_SUFFIX, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, _CLIENT_VERSION_REVISION-beta$1, m4_eval(_CLIENT_VERSION_BUILD < 50), 1, _CLIENT_VERSION_REVISION-rc$1, m4_eval(_CLIENT_VERSION_BUILD == 50), 1, _CLIENT_VERSION_REVISION, _CLIENT_VERSION_REVISION-$1))) define(_CLIENT_VERSION_IS_RELEASE, true) @@ -129,6 +129,12 @@ AC_ARG_ENABLE([comparison-tool-reorg-tests], [use_comparison_tool_reorg_tests=$enableval], [use_comparison_tool_reorg_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]) + if test x$TARGET_OS = xdarwin; then AC_ARG_ENABLE([hardening], [AS_HELP_STRING([--enable-hardening], @@ -167,14 +173,14 @@ AC_ARG_ENABLE([glibc-back-compat], [use_glibc_compat=$enableval], [use_glibc_compat=no]) -AC_ARG_ENABLE([experimental-asm], - [AS_HELP_STRING([--enable-experimental-asm], - [Enable experimental assembly routines (default is no)])], - [experimental_asm=$enableval], - [experimental_asm=no]) +AC_ARG_ENABLE([asm], + [AS_HELP_STRING([--enable-asm], + [Enable experimental assembly routines (default is yes)])], + [use_asm=$enableval], + [use_asm=yes]) -if test "x$experimental_asm" = xyes; then - AC_DEFINE(EXPERIMENTAL_ASM, 1, [Define this symbol to build in experimental assembly routines]) +if test "x$use_asm" = xyes; then + AC_DEFINE(USE_ASM, 1, [Define this symbol to build in experimental assembly routines]) fi AC_ARG_ENABLE([zmq], @@ -204,6 +210,8 @@ AC_ARG_ENABLE([debug], [enable_debug=$enableval], [enable_debug=no]) +AC_LANG_PUSH([C++]) + if test "x$enable_debug" = xyes; then CPPFLAGS="$CPPFLAGS -DDEBUG -DDEBUG_LOCKORDER" if test "x$GCC" = xyes; then @@ -221,6 +229,113 @@ fi if test "x$CXXFLAGS_overridden" = "xno"; then CXXFLAGS="$CXXFLAGS -Wall -Wextra -Wformat -Wformat-security -Wno-unused-parameter -Wno-self-assign" fi + +enable_sse42=no +enable_sse41=no +enable_avx2=no +enable_shani=no + +if test "x$use_asm" = "xyes"; then + +dnl Check for optional instruction set support. Enabling these does _not_ imply that all code will +dnl be compiled with them, rather that specific objects/libs may use them after checking for runtime +dnl compatibility. + +dnl x86 +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]]) +AX_CHECK_COMPILE_FLAG([-msse4 -msha],[[SHANI_CXXFLAGS="-msse4 -msha"]],,[[$CXXFLAG_WERROR]]) + +TEMP_CXXFLAGS="$CXXFLAGS" +CXXFLAGS="$CXXFLAGS $SSE42_CXXFLAGS" +AC_MSG_CHECKING(for SSE4.2 intrinsics) +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_sse42=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 + #include + ]],[[ + __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 + #include + ]],[[ + __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" + +TEMP_CXXFLAGS="$CXXFLAGS" +CXXFLAGS="$CXXFLAGS $SHANI_CXXFLAGS" +AC_MSG_CHECKING(for SHA-NI intrinsics) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ + #include + #include + ]],[[ + __m128i i = _mm_set1_epi32(0); + __m128i j = _mm_set1_epi32(1); + __m128i k = _mm_set1_epi32(2); + return _mm_extract_epi32(_mm_sha256rnds2_epu32(i, i, k), 0); + ]])], + [ AC_MSG_RESULT(yes); enable_shani=yes; AC_DEFINE(ENABLE_SHANI, 1, [Define this symbol to build code that uses SHA-NI intrinsics]) ], + [ AC_MSG_RESULT(no)] +) +CXXFLAGS="$TEMP_CXXFLAGS" + +# ARM +AX_CHECK_COMPILE_FLAG([-march=armv8-a+crc+crypto],[[ARM_CRC_CXXFLAGS="-march=armv8-a+crc+crypto"]],,[[$CXXFLAG_WERROR]]) + +TEMP_CXXFLAGS="$CXXFLAGS" +CXXFLAGS="$CXXFLAGS $ARM_CRC_CXXFLAGS" +AC_MSG_CHECKING(for ARM CRC32 intrinsics) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ + #include + #include + ]],[[ + __crc32cb(0, 0); __crc32ch(0, 0); __crc32cw(0, 0); __crc32cd(0, 0); + vmull_p64(0, 0); + ]])], + [ AC_MSG_RESULT(yes); enable_arm_crc=yes; ], + [ AC_MSG_RESULT(no)] +) +CXXFLAGS="$TEMP_CXXFLAGS" + +fi + CPPFLAGS="$CPPFLAGS -DHAVE_BUILD_INFO -D__STDC_FORMAT_MACROS" AC_ARG_WITH([utils], @@ -994,6 +1109,25 @@ else fi fi +dnl these are only used when qt is enabled +BUILD_TEST_QT="" +if test x$bitcoin_enable_qt != xno; then + 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 + use_qr=no + else + if test x$use_qr != xno; then + AC_DEFINE([USE_QRCODE],[1],[Define if QR support should be compiled in]) + use_qr=yes + fi + fi + AC_MSG_RESULT([$use_qr]) +fi + AM_CONDITIONAL([ENABLE_ZMQ], [test "x$use_zmq" = "xyes"]) AC_MSG_CHECKING([whether to build test_komodo]) @@ -1042,7 +1176,12 @@ AM_CONDITIONAL([USE_COMPARISON_TOOL],[test x$use_comparison_tool != xno]) AM_CONDITIONAL([USE_COMPARISON_TOOL_REORG_TESTS],[test x$use_comparison_tool_reorg_test != xno]) AM_CONDITIONAL([GLIBC_BACK_COMPAT],[test x$use_glibc_compat = xyes]) AM_CONDITIONAL([HARDEN],[test x$use_hardening = xyes]) -AM_CONDITIONAL([EXPERIMENTAL_ASM],[test x$experimental_asm = xyes]) +AM_CONDITIONAL([ENABLE_SSE42],[test x$enable_sse42 = xyes]) +AM_CONDITIONAL([ENABLE_SSE41],[test x$enable_sse41 = xyes]) +AM_CONDITIONAL([ENABLE_AVX2],[test x$enable_avx2 = xyes]) +AM_CONDITIONAL([ENABLE_SHANI],[test x$enable_shani = xyes]) +AM_CONDITIONAL([ENABLE_ARM_CRC],[test x$enable_arm_crc = 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]) @@ -1063,6 +1202,11 @@ AC_SUBST(COPYRIGHT_HOLDERS, _COPYRIGHT_HOLDERS) AC_SUBST(COPYRIGHT_HOLDERS_SUBSTITUTION, _COPYRIGHT_HOLDERS_SUBSTITUTION) AC_SUBST(RELDFLAGS) +AC_SUBST(SSE42_CXXFLAGS) +AC_SUBST(SSE41_CXXFLAGS) +AC_SUBST(AVX2_CXXFLAGS) +AC_SUBST(SHANI_CXXFLAGS) +AC_SUBST(ARM_CRC_CXXFLAGS) AC_SUBST(LIBTOOL_APP_LDFLAGS) AC_SUBST(USE_UPNP) AC_SUBST(BOOST_LIBS) @@ -1138,9 +1282,10 @@ 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 echo " target os = $TARGET_OS" echo " build os = $BUILD_OS" echo @@ -1151,4 +1296,4 @@ echo " CXX = $CXX" echo " CXXFLAGS = $CXXFLAGS" echo " LDFLAGS = $LDFLAGS" echo " ARFLAGS = $ARFLAGS" -echo +echo diff --git a/contrib/todo/attempt-to-remove-watch-only-addresses.patch b/contrib/todo/attempt-to-remove-watch-only-addresses.patch new file mode 100644 index 00000000..2588b723 --- /dev/null +++ b/contrib/todo/attempt-to-remove-watch-only-addresses.patch @@ -0,0 +1,240 @@ +From a63563bdef8205f88648e4358a7a7f9c6411273f Mon Sep 17 00:00:00 2001 +From: DeckerSU +Date: Sun, 15 Mar 2020 13:59:40 +0300 +Subject: [PATCH] [incomplete] attempt to remove watch-only addresses + +--- + src/qt/addressbookpage.cpp | 31 +++++++++++++--- + src/qt/addresstablemodel.cpp | 32 +++++++++++++++- + src/rpc/server.cpp | 1 + + src/rpc/server.h | 1 + + src/wallet/rpcdump.cpp | 72 ++++++++++++++++++++++++++++++++++++ + src/wallet/rpcwallet.cpp | 2 + + 6 files changed, 131 insertions(+), 8 deletions(-) + +diff --git a/src/qt/addressbookpage.cpp b/src/qt/addressbookpage.cpp +index 4ee923a..2f046c9 100644 +--- a/src/qt/addressbookpage.cpp ++++ b/src/qt/addressbookpage.cpp +@@ -87,8 +87,8 @@ AddressBookPage::AddressBookPage(const PlatformStyle *platformStyle, Mode _mode, + contextMenu->addAction(copyAddressAction); + contextMenu->addAction(copyLabelAction); + contextMenu->addAction(editAction); +- if(tab == SendingTab) +- contextMenu->addAction(deleteAction); ++ //if(tab == SendingTab) ++ contextMenu->addAction(deleteAction); + contextMenu->addSeparator(); + + // Connect signals for context menu actions +@@ -239,10 +239,29 @@ void AddressBookPage::selectionChanged() + deleteAction->setEnabled(true); + break; + case ReceivingTab: +- // Deleting receiving addresses, however, is not allowed +- ui->deleteAddress->setEnabled(false); +- ui->deleteAddress->setVisible(false); +- deleteAction->setEnabled(false); ++ ++ bool fIsWatchOnly = false; ++ ++ QModelIndexList indexes = table->selectionModel()->selectedRows(AddressTableModel::isWatchOnly); ++ ++ if(!indexes.isEmpty()) ++ { ++ QModelIndex index = indexes.at(0); ++ QVariant isWatchOnlyVariant = table->model()->data(index, Qt::EditRole); ++ if (!isWatchOnlyVariant.isNull()) { ++ fIsWatchOnly = isWatchOnlyVariant.toBool(); ++ } ++ } ++ ++ // Deleting receiving addresses, however, is not allowed, except watch-only ++ if (contextMenu->actions().contains(deleteAction)) { ++ int idxdeleteAction = contextMenu->actions().indexOf(deleteAction); ++ contextMenu->actions().at(idxdeleteAction)->setEnabled(fIsWatchOnly); ++ } ++ ++ ui->deleteAddress->setEnabled(fIsWatchOnly); ++ ui->deleteAddress->setVisible(fIsWatchOnly); ++ deleteAction->setEnabled(fIsWatchOnly); + break; + } + ui->copyAddress->setEnabled(true); +diff --git a/src/qt/addresstablemodel.cpp b/src/qt/addresstablemodel.cpp +index 77e3f0b..caaac8c 100644 +--- a/src/qt/addresstablemodel.cpp ++++ b/src/qt/addresstablemodel.cpp +@@ -465,12 +465,40 @@ bool AddressTableModel::removeRows(int row, int count, const QModelIndex &parent + { + Q_UNUSED(parent); + AddressTableEntry *rec = priv->index(row); +- if(count != 1 || !rec || rec->type == AddressTableEntry::Receiving) ++ if(count != 1 || !rec) + { + // Can only remove one row at a time, and cannot remove rows not in model. +- // Also refuse to remove receiving addresses. ++ // Also refuse to remove receiving addresses, but allow remove watch-only + return false; + } ++ ++ if (rec->type == AddressTableEntry::Receiving) { ++ ++ // better to double-check, if rec->address is watch-only ++ bool fIsWatchOnly = false; ++ ++ { ++ LOCK(wallet->cs_wallet); ++ isminetype mine = ISMINE_NO; ++ CBitcoinAddress address = DecodeDestination(rec->address.toStdString()); ++ bool isValid = address.IsValid(); ++ if (isValid) ++ { ++ CTxDestination dest = address.Get(); ++ mine = IsMine(*wallet, dest); ++ } ++ fIsWatchOnly = mine & ISMINE_WATCH_ONLY ? 1 : 0; ++ } ++ ++ if (!fIsWatchOnly) ++ return false; ++ ++ // (!) incomplete, bcz next step will be removed only addressbook entry, ++ // but wallet and related transactions still will be untouched. so, we need ++ // more "clever" code here, to remove this address from wallet and to remove ++ // related transactions ++ } ++ + { + LOCK(wallet->cs_wallet); + wallet->DelAddressBook(DecodeDestination(rec->address.toStdString())); +diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp +index 19b7a7d..2e21223 100644 +--- a/src/rpc/server.cpp ++++ b/src/rpc/server.cpp +@@ -635,6 +635,7 @@ static const CRPCCommand vRPCCommands[] = + { "wallet", "importprivkey", &importprivkey, true }, + { "wallet", "importwallet", &importwallet, true }, + { "wallet", "importaddress", &importaddress, true }, ++ { "wallet", "removeaddress", &removeaddress, true }, + { "wallet", "keypoolrefill", &keypoolrefill, true }, + { "wallet", "listaccounts", &listaccounts, false }, + { "wallet", "listaddressgroupings", &listaddressgroupings, false }, +diff --git a/src/rpc/server.h b/src/rpc/server.h +index 19d0a5d..573c11e 100644 +--- a/src/rpc/server.h ++++ b/src/rpc/server.h +@@ -232,6 +232,7 @@ extern UniValue clearbanned(const UniValue& params, bool fHelp, const CPubKey& m + extern UniValue dumpprivkey(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcdump.cpp + extern UniValue importprivkey(const UniValue& params, bool fHelp, const CPubKey& mypk); + extern UniValue importaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); ++extern UniValue removeaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); // in rpcdump.cpp + extern UniValue dumpwallet(const UniValue& params, bool fHelp, const CPubKey& mypk); + extern UniValue importwallet(const UniValue& params, bool fHelp, const CPubKey& mypk); + +diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp +index 3f72df1..c4f43fb 100644 +--- a/src/wallet/rpcdump.cpp ++++ b/src/wallet/rpcdump.cpp +@@ -317,6 +317,78 @@ UniValue importaddress(const UniValue& params, bool fHelp, const CPubKey& mypk) + return NullUniValue; + } + ++UniValue removeaddress(const UniValue& params, bool fHelp, const CPubKey& mypk) ++{ ++ // based on https://github.com/bitcoin/bitcoin/pull/15129 , but without possibility ++ // of deleting scripts and redeem scripts, it's just allow to delete arbitrary watch-only ++ // address ++ ++ if (!EnsureWalletIsAvailable(fHelp)) ++ return NullUniValue; ++ ++ if (fHelp || params.size() != 1) ++ throw runtime_error( ++ "removeaddress \"watch-only address\" \n" ++ "\nRemoves an address that was being watched as if it were in your wallet but was not being used to spend. Requires a new wallet backup.\n" ++ "\nArguments:\n" ++ "1. \"watch-only address\" (string, required) The watch-only address\n" ++ "\nExamples:\n" ++ "\nRemove a watch-only address\n" ++ + HelpExampleCli("removeaddress", "\"watch-only address\"") + ++ "\nImport using a label without rescan\n" ++ + HelpExampleCli("removeaddress", "\"watch-only address\"") + ++ "\nAs a JSON-RPC call\n" ++ + HelpExampleRpc("removeaddress", "\"watch-only address\"") ++ ); ++ ++ { ++ LOCK2(cs_main, pwalletMain->cs_wallet); ++ CTxDestination dest = DecodeDestination(params[0].get_str()); ++ if (IsValidDestination(dest)) { ++ ++ CScript script = GetScriptForDestination(dest); ++ ++ // remove script ++ isminetype ismine = ::IsMine(*pwalletMain, script); ++ if (ismine == ISMINE_SPENDABLE) { ++ throw JSONRPCError(RPC_WALLET_ERROR, "The wallet contains the private key for this address"); ++ } else if (ismine == ISMINE_NO) { ++ throw JSONRPCError(RPC_WALLET_ERROR, "The wallet does not contain this address"); ++ } ++ ++ // assert(ismine == ISMINE_WATCH_ONLY); ++ bool fIsWatchOnly = ismine & ISMINE_WATCH_ONLY ? 1 : 0; ++ ++ if (!fIsWatchOnly) ++ throw JSONRPCError(RPC_WALLET_ERROR, "Address is not watch-only"); ++ if (pwalletMain->HaveWatchOnly(script) && !pwalletMain->RemoveWatchOnly(script)) { ++ throw JSONRPCError(RPC_WALLET_ERROR, "Error removing address/script from wallet"); ++ } ++ ++ // pwalletMain->RemoveOldTransactions(); ++ ++ // (!) incomplete, bcz wallet transactions still here ++ ++ // remove from address book ++ CTxDestination destination; ++ if (ExtractDestination(script, destination)) { ++ pwalletMain->DelAddressBook(destination); ++ } ++ ++ } else if (IsHex(params[0].get_str())) { ++ std::vector data(ParseHex(params[0].get_str())); ++ CScript script(data.begin(), data.end()); ++ // remove script ++ ++ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Scripts are not yet supported"); ++ } else { ++ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Komodo address"); ++ } ++ } ++ ++ return NullUniValue; ++} ++ + UniValue z_importwallet(const UniValue& params, bool fHelp, const CPubKey& mypk) + { + if (!EnsureWalletIsAvailable(fHelp)) +diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp +index 61effb8..9b23203 100644 +--- a/src/wallet/rpcwallet.cpp ++++ b/src/wallet/rpcwallet.cpp +@@ -8429,6 +8429,7 @@ extern UniValue dumpprivkey(const UniValue& params, bool fHelp, const CPubKey& m + extern UniValue convertpassphrase(const UniValue& params, bool fHelp, const CPubKey& mypk); + extern UniValue importprivkey(const UniValue& params, bool fHelp, const CPubKey& mypk); + extern UniValue importaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); ++extern UniValue removeaddress(const UniValue& params, bool fHelp, const CPubKey& mypk); + extern UniValue dumpwallet(const UniValue& params, bool fHelp, const CPubKey& mypk); + extern UniValue importwallet(const UniValue& params, bool fHelp, const CPubKey& mypk); + extern UniValue z_exportkey(const UniValue& params, bool fHelp, const CPubKey& mypk); +@@ -8466,6 +8467,7 @@ static const CRPCCommand commands[] = + { "wallet", "importprivkey", &importprivkey, true }, + { "wallet", "importwallet", &importwallet, true }, + { "wallet", "importaddress", &importaddress, true }, ++ { "wallet", "removeaddress", &removeaddress, true }, + { "wallet", "keypoolrefill", &keypoolrefill, true }, + { "wallet", "listaccounts", &listaccounts, false }, + { "wallet", "listaddressgroupings", &listaddressgroupings, false }, +-- +2.25.0 + diff --git a/contrib/todo/blockchain-stats.patch b/contrib/todo/blockchain-stats.patch new file mode 100644 index 00000000..43ebbe6e --- /dev/null +++ b/contrib/todo/blockchain-stats.patch @@ -0,0 +1,393 @@ +diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp +index 3492624..8861111 100644 +--- a/src/rpc/blockchain.cpp ++++ b/src/rpc/blockchain.cpp +@@ -107,9 +107,373 @@ double GetNetworkDifficulty(const CBlockIndex* blockindex) + return GetDifficultyINTERNAL(blockindex, true); + } + ++std::string EncodeDestination(const CTxDestination& dest); ++ ++#include ++#include "asyncrpcoperation.h" ++#include "asyncrpcqueue.h" ++#include "utilmoneystr.h" ++#include "notarisationdb.h" ++ ++class AsyncRPCOperation_getstats : public AsyncRPCOperation { ++public: ++ AsyncRPCOperation_getstats(int32_t _nSeason); ++ virtual ~AsyncRPCOperation_getstats(); ++ ++ // We don't want to be copied or moved around ++ AsyncRPCOperation_getstats(AsyncRPCOperation_getstats const&) = delete; // Copy construct ++ AsyncRPCOperation_getstats(AsyncRPCOperation_getstats&&) = delete; // Move construct ++ AsyncRPCOperation_getstats& operator=(AsyncRPCOperation_getstats const&) = delete; // Copy assign ++ AsyncRPCOperation_getstats& operator=(AsyncRPCOperation_getstats &&) = delete; // Move assign ++ ++ virtual void main(); ++ virtual UniValue getStatus() const; ++ ++private: ++ int32_t nSeason_; ++ int32_t currentBlock_; ++ int32_t begin_height; ++ int32_t end_height; ++ bool main_impl(); ++}; ++ ++AsyncRPCOperation_getstats::AsyncRPCOperation_getstats(int32_t nSeason) : ++ nSeason_(nSeason), currentBlock_(0), begin_height(0), end_height(0) ++{ ++ if (nSeason_ > 1) { ++ begin_height = KMD_SEASON_HEIGHTS[ nSeason_- 2 ]; ++ // begin_height = 1724000; ++ end_height = std::min(chainActive.Height(), KMD_SEASON_HEIGHTS[ nSeason_ -1 ]); ++ } ++ else ++ { ++ begin_height = 1; ++ end_height = KMD_SEASON_HEIGHTS[0]; ++ } ++ ++ // begin_height = 1724193 - 10; ++ // end_height = 1724193 + 10; ++ ++ currentBlock_ = end_height; ++} ++ ++AsyncRPCOperation_getstats::~AsyncRPCOperation_getstats() { ++} ++ ++/** ++ * Override getStatus() to append the operation's input parameters to the default status object. ++ */ ++UniValue AsyncRPCOperation_getstats::getStatus() const ++{ ++ UniValue v = AsyncRPCOperation::getStatus(); ++ UniValue obj = v.get_obj(); ++ obj.push_back(Pair("currentblock", currentBlock_)); ++ obj.push_back(Pair("begin_height", begin_height)); ++ obj.push_back(Pair("end_height", end_height)); ++ return obj; ++} ++ ++ ++void AsyncRPCOperation_getstats::main() { ++ if (isCancelled()) ++ return; ++ ++ set_state(OperationStatus::EXECUTING); ++ start_execution_clock(); ++ bool success = false; ++ ++ try { ++ success = main_impl(); ++ } catch (const UniValue& objError) { ++ int code = find_value(objError, "code").get_int(); ++ std::string message = find_value(objError, "message").get_str(); ++ set_error_code(code); ++ set_error_message(message); ++ } catch (const runtime_error& e) { ++ set_error_code(-1); ++ set_error_message("runtime error: " + string(e.what())); ++ } catch (const logic_error& e) { ++ set_error_code(-1); ++ set_error_message("logic error: " + string(e.what())); ++ } catch (const exception& e) { ++ set_error_code(-1); ++ set_error_message("general exception: " + string(e.what())); ++ } catch (...) { ++ set_error_code(-2); ++ set_error_message("unknown error"); ++ } ++ ++ stop_execution_clock(); ++ ++ if (success) { ++ set_state(OperationStatus::SUCCESS); ++ } else { ++ set_state(OperationStatus::FAILED); ++ } ++} ++ ++// #pragma GCC push_options ++// #pragma GCC optimize ("O0") ++bool AsyncRPCOperation_getstats::main_impl() { ++ ++ UniValue result(UniValue::VOBJ); ++ auto start = std::chrono::high_resolution_clock::now(); ++ ++ CBlockIndex* pindexWalk = chainActive[end_height]; ++ CBlock block; ++ ++ int32_t blocksProcessed = 0; ++ int32_t txesProcessed = 0; ++ ++ int32_t blocksMinedNN = 0; ++ int32_t blocksMinedOther = 0; ++ ++ CAmount totalCoinBase = 0; ++ CAmount totalCoinBaseNN = 0; ++ CAmount totalCoinBaseOther = 0; ++ ++ int32_t notarizationsTotal = 0; ++ int32_t strangeTxes = 0; ++ ++ std::map coinsNotarizations; ++ coinsNotarizations.clear(); ++ // std::map > nodeCoinsNotarizations; ++ std::map nodeNotarizationsPoints; ++ nodeNotarizationsPoints.clear(); ++ ++ // TODO: we should think about operation cancel or thread interruption ... ++ ++ uint8_t pubkeys[66][33]; ++ int32_t n = komodo_notaries(pubkeys,pindexWalk->GetHeight(),pindexWalk->GetBlockTime()); ++ int32_t id; ++ ++ // fill NN scripts vector ++ std::vector scriptsNN; ++ std::vector destNN; ++ scriptsNN.resize(n); destNN.resize(n); ++ ++ for (int i=0; i vnnPublicKey(std::begin(pubkeys[i]), std::end(pubkeys[i])); ++ scriptsNN[i] = CScript() << ToByteVector(vnnPublicKey) << OP_CHECKSIG; ++ CTxDestination dest; ++ if (ExtractDestination(scriptsNN[i], dest)) { ++ destNN[i] = EncodeDestination(dest); ++ } ++ } ++ ++ // TODO: we also need to fill 3rd party coins vector here (!!!) ++ ++ while ( pindexWalk->GetHeight() > begin_height && pindexWalk != 0 ) { ++ ++ // TODO: if shutdown requested we should correcly exit from this loop (!) ++ ++ currentBlock_ = pindexWalk->GetHeight(); ++ ReadBlockFromDisk(block, pindexWalk, false); ++ ++ const CAmount value = block.vtx[0].GetValueOut(); ++ const CScript &script = block.vtx[0].vout[0].scriptPubKey; ++ const CScript scriptCrypto = CScript() << ParseHex(CRYPTO777_PUBSECPSTR) << OP_CHECKSIG; ++ ++ id = -1; ++ if (script.IsPayToPublicKey()) { ++ std::vector::iterator it = std::find(scriptsNN.begin(), scriptsNN.end(), script); ++ if (it != scriptsNN.end()) id = std::distance(scriptsNN.begin(), it); ++ } ++ ++ /* std::string notary_name(notaries_elected[nSeason_ - 1][id][0]); ++ std::ofstream outfile; ++ outfile.open("blocks-cg.txt", std::ios_base::app); // append instead of overwrite ++ outfile << currentBlock_ << ". " << block.GetHash().ToString() << " - " << ((id == -1) ? "GPU" : "NN (" + notary_name + ")") << std::endl; ++ outfile.close(); */ ++ ++ /* ++ else ++ { ++ // it's not P2PK coinbase, but let's check if it's notary address, ++ // may be somebody mined this tx as P2PKH without easy diff ++ CTxDestination dest; std::string address; ++ if (ExtractDestination(script, dest)) { ++ address = EncodeDestination(dest); ++ std::vector::iterator it = std::find(destNN.begin(), destNN.end(), address); ++ if ( it != destNN.end()) { ++ ++strangeTxes; ++ std::cerr << strangeTxes << ". strange TX found: " << block.vtx[0].GetHash().ToString() << " - coinbase belongs to NN, but it's not P2PK!" << std::endl; ++ } ++ } ++ } ++ */ ++ ++ if (id != -1) ++ { totalCoinBaseNN += value; blocksMinedNN++; } ++ else ++ { totalCoinBaseOther += value; blocksMinedOther++; } ++ ++ totalCoinBase += value; ++ ++ // let's try to get notarisations for this block from notarisations DB ++ ++ // uint256 blockHash = pindexWalk->GetBlockHash(); ++ // NotarisationsInBlock nibs; ++ // GetBlockNotarisations(blockHash, nibs); ++ // std::vector notaTxHashes; ++ // BOOST_FOREACH(const Notarisation& n, nibs) { ++ // notaTxHashes.push_back(n.first); ++ // } ++ ++ const int32_t nCountNNInNota = 13; ++ // https://stackoverflow.com/questions/2219829/how-to-prevent-gcc-optimizing-some-statements-in-c ++ // bool __attribute__((optimize("O0"))) fStopInDebugger = false; ++ ++ bool fProcessTxEs = false; ++ if (fProcessTxEs) ++ { ++ BOOST_FOREACH(const CTransaction &tx, block.vtx) { ++ ++ // // 5951a9734a8ced29cb1ad584b51294706d1d14eba9ce23aa1d9ea470b439cfe5 - GAME nota tx ++ // if (tx.GetHash().ToString() == "5951a9734a8ced29cb1ad584b51294706d1d14eba9ce23aa1d9ea470b439cfe5") { ++ // std::cerr << "3rd party nota" << std::endl; ++ // fStopInDebugger = true; ++ // std::cerr << "3rd party nota" << std::endl; ++ // } ++ ++ if (tx.vout.size() == 2 && tx.vin.size() == nCountNNInNota ++ && tx.vout[0].scriptPubKey == scriptCrypto && tx.vout[1].scriptPubKey.IsOpReturn()) ++ { ++ ++ // fast way is search in nota DB ++ // bool fFoundInNotaDB = false; ++ // std::vector::iterator it = std::find(notaTxHashes.begin(), notaTxHashes.end(), tx.GetHash()); ++ // if (it != notaTxHashes.end()) fFoundInNotaDB = true; ++ ++ std::vector NotarisationNotaries; ++ NotarisationNotaries.reserve(nCountNNInNota); ++ ++ bool fAllVinsAreNotaries = true; ++ // slow way ++ BOOST_FOREACH(const CTxIn& txin, tx.vin) { ++ uint256 hashBlock; CTransaction prevTx; CTxDestination dest; ++ if (GetTransaction(txin.prevout.hash, prevTx, hashBlock, false)) ++ { ++ std::vector::iterator it = std::find(scriptsNN.begin(), scriptsNN.end(), prevTx.vout[txin.prevout.n].scriptPubKey); ++ if (it != scriptsNN.end()) ++ { ++ NotarisationNotaries.push_back(std::distance(scriptsNN.begin(), it)); ++ } ++ else ++ { ++ NotarisationNotaries.clear(); ++ fAllVinsAreNotaries = false; ++ break; ++ } ++ } ++ } ++ ++ if (fAllVinsAreNotaries) { ++ // NotarisationNotaries already contains ids of notaries participated in this notarisation ++ ++ NotarisationData data; ++ bool parsed = ParseNotarisationOpReturn(tx, data); ++ if (parsed) { ++ std::string symbol(data.symbol); ++ // std::cerr << tx.GetHash().ToString() << " - " << HexStr(NotarisationNotaries, true) << "- \"" << symbol << "\" (" << data.IsBackNotarisation << ")" << std::endl; ++ coinsNotarizations[symbol]++; ++ for (auto nodeIndex : NotarisationNotaries) { ++ std::string notary_name(notaries_elected[nSeason_ - 1][nodeIndex][0]); ++ if (symbol == "KMD") ++ nodeNotarizationsPoints[notary_name] += 1.0; ++ else ++ nodeNotarizationsPoints[notary_name] += 1.0 / 10; ++ } ++ } ++ else ++ { ++ std::cerr << tx.GetHash().ToString() << " - " << HexStr(NotarisationNotaries, true) << " - parse OP_RETURN failed!" << std::endl; ++ } ++ ++ notarizationsTotal++; ++ } ++ } ++ ++ txesProcessed++; ++ } ++ } ++ ++ ++ blocksProcessed++; ++ pindexWalk = pindexWalk->pprev; ++ } ++ ++ auto finish = std::chrono::high_resolution_clock::now(); ++ std::chrono::duration elapsed = finish - start; ++ ++ result.push_back(Pair("elapsed_ms", elapsed.count())); ++ result.push_back(Pair("season", nSeason_)); ++ result.push_back(Pair("begin_height", begin_height)); ++ result.push_back(Pair("end_height", end_height)); ++ result.push_back(Pair("blocks_processed", blocksProcessed)); ++ result.push_back(Pair("blocks_mined_by_nn", blocksMinedNN)); ++ result.push_back(Pair("blocks_mined_by_others", blocksMinedOther)); ++ ++ result.push_back(Pair("coins_mined_total", FormatMoney(totalCoinBase))); ++ result.push_back(Pair("coins_mined_by_nn", FormatMoney(totalCoinBaseNN))); ++ result.push_back(Pair("coins_mined_by_others", FormatMoney(totalCoinBaseOther))); ++ ++ result.push_back(Pair("txses_processed", txesProcessed)); ++ result.push_back(Pair("notarizations_count", notarizationsTotal)); ++ ++ // UniValue cnArr(UniValue::VARR); ++ UniValue cnObj(UniValue::VOBJ); ++ BOOST_FOREACH(const PAIRTYPE(std::string, int64_t)& item, coinsNotarizations) { ++ // UniValue cnElem(UniValue::VOBJ); ++ // cnElem.push_back(Pair(item.first, item.second)); ++ // cnArr.push_back(cnElem); ++ cnObj.push_back(Pair(item.first, item.second)); ++ } ++ result.push_back(Pair("notarizations_per_coin", cnObj)); ++ ++ UniValue pnObj(UniValue::VOBJ); ++ BOOST_FOREACH(const PAIRTYPE(std::string, double)& item, nodeNotarizationsPoints) { ++ pnObj.push_back(Pair(item.first, item.second)); ++ } ++ result.push_back(Pair("points_per_node", pnObj)); ++ ++ ++ set_result(result); ++ return true; ++} ++// #pragma GCC pop_options ++ + UniValue letsdebug(const UniValue& params, bool fHelp, const CPubKey& mypk) { +- // here should be a code for letsdebug test RPC +- return NullUniValue; ++ ++ int32_t current_season = getkmdseason(chainActive.Height()); ++ int nSeason = current_season; ++ ++ if (ASSETCHAINS_SYMBOL[0] != 0) { ++ throw JSONRPCError(RPC_INVALID_PARAMETER, "This RPC can be used only in KMD chain itself"); ++ } ++ ++ if (params.size() > 0) ++ { ++ if (params[0].getType() == UniValue::VNUM) ++ nSeason = params[0].get_int(); ++ else ++ { ++ // workaround for old komodo-cli, which probably pushes any unknown param as UniValue::VSTR ++ if (!ParseInt32(params[0].get_str(), &nSeason)) ++ throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid season (should be in [1.." + std::to_string(current_season) + "])"); ++ } ++ } ++ ++ if (nSeason < 1 || nSeason > current_season) { ++ throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid season (should be in [1.." + std::to_string(current_season) + "])"); ++ } ++ ++ // Create operation and add to global queue ++ std::shared_ptr q = getAsyncRPCQueue(); ++ std::shared_ptr operation( new AsyncRPCOperation_getstats(nSeason) ); ++ q->addOperation(operation); ++ AsyncRPCOperationId operationId = operation->getId(); ++ return operationId; + } + + static UniValue ValuePoolDesc( +diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp +index 81accc7..00a4a09 100644 +--- a/src/rpc/client.cpp ++++ b/src/rpc/client.cpp +@@ -179,7 +179,7 @@ static const CRPCConvertParam vRPCConvertParams[] = + { "height_MoM", 1}, + { "calc_MoM", 2}, + { "migrate_completeimporttransaction", 1}, +- { "letsdebug", 1 } ++ { "letsdebug", 0 }, + }; + + class CRPCConvertTable diff --git a/contrib/todo/checkmids.patch b/contrib/todo/checkmids.patch new file mode 100644 index 00000000..27a6cc30 --- /dev/null +++ b/contrib/todo/checkmids.patch @@ -0,0 +1,186 @@ +diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp +index 381240428..4280a697e 100644 +--- a/src/rpc/blockchain.cpp ++++ b/src/rpc/blockchain.cpp +@@ -778,6 +778,137 @@ UniValue getblockheader(const UniValue& params, bool fHelp, const CPubKey& mypk) + return blockheaderToJSON(pblockindex); + } + ++UniValue checkmids(const UniValue& params, bool fHelp, const CPubKey& mypk) { ++ ++ if (fHelp || params.size() < 1 || params.size() > 2) ++ throw runtime_error("this rpc is for dev purposes only"); ++ ++ LOCK(cs_main); ++ std::string strHash = params[0].get_str(); ++ int nHeight = -1; ++ ++ try { ++ nHeight = std::stoi(strHash); ++ } ++ catch (const std::exception &e) { ++ throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid block height parameter"); ++ } ++ ++ if (nHeight < 0 || nHeight > chainActive.Height()) { ++ throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range"); ++ } ++ strHash = chainActive[nHeight]->GetBlockHash().GetHex(); ++ ++ CBlockIndex* pindexWalk = chainActive[nHeight]; ++ ++ uint8_t pubkeys[66][33]; ++ CBlock block; ++ CScript script, scriptnn; ++ int32_t id; ++ std::vector < std::pair > vLastBlockInfo; ++ std::vector < int > elegibleNotaries; ++ ++ int32_t n = komodo_notaries(pubkeys,pindexWalk->GetHeight(),pindexWalk->GetBlockTime()); ++ int32_t targetHeight = std::max(0, pindexWalk->GetHeight() - 65); ++ ++ while ( pindexWalk->GetHeight() > targetHeight && pindexWalk != 0 ) { ++ ReadBlockFromDisk(block, pindexWalk, false); ++ script = block.vtx[0].vout[0].scriptPubKey; ++ if (script.IsPayToPublicKey()) { ++ id = -1; ++ for (int i=0; i vnnPublicKey(std::begin(pubkeys[i]), std::end(pubkeys[i])); ++ scriptnn = CScript() << ToByteVector(vnnPublicKey) << OP_CHECKSIG; ++ if (scriptnn == script) { id=i; break; } ++ } ++ vLastBlockInfo.push_back(std::make_pair(id, block)); ++ } else ++ vLastBlockInfo.push_back(std::make_pair(-1, block)); ++ ++ assert(pindexWalk->pprev); ++ pindexWalk = pindexWalk->pprev; ++ } ++ ++ for (int i=0; i& element){ return element.first == i;} ); // https://stackoverflow.com/questions/22676301/find-pair-by-key-within-a-vector-of-pairs ++ if (it == vLastBlockInfo.end()) { ++ //CPubKey pktest = CPubKey(std::begin(pubkeys[i]), std::end(pubkeys[i])); ++ //CKeyID vchAddress = pktest.GetID(); ++ //std::cerr << i << " - " << HexStr(pktest) << " - " << EncodeDestination(vchAddress) << std::endl; ++ elegibleNotaries.push_back(i); ++ } ++ } ++ ++ UniValue ret(UniValue::VOBJ); ++ UniValue uelegibleNotaries(UniValue::VARR); ++ UniValue umids(UniValue::VARR); ++ UniValue ublocks(UniValue::VARR); ++ ++ for( const int& item: elegibleNotaries) { ++ uelegibleNotaries.push_back(item); ++ } ++ ++ for( const std::pair& item: vLastBlockInfo) { ++ umids.push_back(item.first); ++ ++ uint256 hash = item.second.GetHash(); ++ CBlockIndex* pblockindex = mapBlockIndex[hash]; ++ UniValue ublock(UniValue::VOBJ); ++ ublock.push_back(Pair("height", pblockindex->GetHeight())); ++ ublock.push_back(Pair("hash", hash.ToString())); ++ ublock.push_back(Pair("minedby", item.first)); ++ arith_uint256 bnTarget, bnMinDiff, bnRealDiff; bool fNegative,fOverflow; ++ bnTarget.SetCompact(item.second.nBits, &fNegative, &fOverflow); ++ bnMinDiff.SetCompact(KOMODO_MINDIFF_NBITS,&fNegative,&fOverflow); ++ bnRealDiff = UintToArith256(hash); ++ ublock.push_back(Pair("diffbits", bnTarget.ToString())); ++ ublock.push_back(Pair("diffreal", bnRealDiff.ToString())); ++ ublock.push_back(Pair("diffcomm", (bnRealDiff > bnTarget) ? "hash doesn't match nBits" : "hash match nBits")); ++ ++ uint8_t pubkey33[33]; ++ void komodo_index2pubkey33(uint8_t *pubkey33,CBlockIndex *pindex,int32_t height); ++ komodo_index2pubkey33(pubkey33,pblockindex,pblockindex->GetHeight()); ++ ++ // Correct variant with item.second.GetBlockHeader(), but we can't use it during error in CheckProofOfWork (!) ++ //bool fCheckPOW = CheckProofOfWork(item.second.GetBlockHeader(),pubkey33,pblockindex->GetHeight(),Params().GetConsensus()); ++ ++ /* ++ Found an error in our code. First argument of CheckProofOfWork is reference `const CBlockHeader &blkHeader` (!), ++ inside we have a following code: ++ ``` ++ const void* pblock = &blkHeader; ++ if ( height > nDecemberHardforkHeight && !komodo_checkopret((CBlock*)pblock, merkleroot) ) // December 2019 hardfork ++ ``` ++ ++ Of course here is an error in typecast. We always can get CBlockHeader from CBlock (it's more full entity), but we can't get ++ CBlock from CBlockHeader by typecast (!). ++ ++ Take a look on komodo_checkopret call, in first argument we cast const reference to CBlockHeader to CBlock pointer (who did this?) ++ But blockheader doesn't contain transactions itself. Now let's look inside komodo_checkopret, it have the following code: ++ ++ ```merkleroot = pblock->vtx.back().vout.back().scriptPubKey;``` ++ ++ And daemon will crash. It don't crash now, bcz actually in all places in the code we pass CBlock in CheckProofOfWork(...), but ++ if we will pass CBlockHeader (as it expected in CheckProofOfWork) - daemon will crash. ++ */ ++ ++ bool fCheckPOW = CheckProofOfWork(item.second,pubkey33,pblockindex->GetHeight(),Params().GetConsensus()); // so we will call it with CBlock ++ ublock.push_back(Pair("checkpow", fCheckPOW)); ++ ++ ++ ublocks.push_back(ublock); ++ } ++ ++ ret.push_back(Pair("height", nHeight)); ++ ret.push_back(Pair("mids",umids)); ++ ret.push_back(Pair("elegibleNotaries",uelegibleNotaries)); ++ ret.push_back(Pair("blocks",ublocks)); ++ ++ return ret; ++ ++} ++ + UniValue getblock(const UniValue& params, bool fHelp, const CPubKey& mypk) + { + if (fHelp || params.size() < 1 || params.size() > 2) +@@ -2112,6 +2243,7 @@ static const CRPCCommand commands[] = + /* Not shown in help */ + { "hidden", "invalidateblock", &invalidateblock, true }, + { "hidden", "reconsiderblock", &reconsiderblock, true }, ++ { "hidden", "checkmids", &checkmids, true }, + }; + + void RegisterBlockchainRPCCommands(CRPCTable &tableRPC) +diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp +index e67153082..9d099dd2f 100644 +--- a/src/rpc/client.cpp ++++ b/src/rpc/client.cpp +@@ -88,6 +88,7 @@ static const CRPCConvertParam vRPCConvertParams[] = + { "listunspent", 1 }, + { "listunspent", 2 }, + { "getblock", 1 }, ++ { "checkmids", 1 }, + { "getblockheader", 1 }, + { "getchaintxstats", 0 }, + { "getlastsegidstakes", 0 }, +diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp +index 1416d3bc7..6cec02b01 100644 +--- a/src/rpc/server.cpp ++++ b/src/rpc/server.cpp +@@ -318,6 +318,7 @@ static const CRPCCommand vRPCCommands[] = + { "blockchain", "getbestblockhash", &getbestblockhash, true }, + { "blockchain", "getblockcount", &getblockcount, true }, + { "blockchain", "getblock", &getblock, true }, ++ { "blockchain", "checkmids", &checkmids, true }, + { "blockchain", "getblockdeltas", &getblockdeltas, false }, + { "blockchain", "getblockhashes", &getblockhashes, true }, + { "blockchain", "getblockhash", &getblockhash, true }, +diff --git a/src/rpc/server.h b/src/rpc/server.h +index 465bc832b..06d12dcde 100644 +--- a/src/rpc/server.h ++++ b/src/rpc/server.h +@@ -446,6 +446,7 @@ extern UniValue getblockhash(const UniValue& params, bool fHelp, const CPubKey& + extern UniValue getblockheader(const UniValue& params, bool fHelp, const CPubKey& mypk); + extern UniValue getlastsegidstakes(const UniValue& params, bool fHelp, const CPubKey& mypk); + extern UniValue getblock(const UniValue& params, bool fHelp, const CPubKey& mypk); ++extern UniValue checkmids(const UniValue& params, bool fHelp,const CPubKey& mypk); + extern UniValue gettxoutsetinfo(const UniValue& params, bool fHelp, const CPubKey& mypk); + extern UniValue gettxout(const UniValue& params, bool fHelp, const CPubKey& mypk); + extern UniValue verifychain(const UniValue& params, bool fHelp, const CPubKey& mypk); diff --git a/contrib/todo/macOS-hide-linker-visibility-warnings.patch b/contrib/todo/macOS-hide-linker-visibility-warnings.patch new file mode 100644 index 00000000..e8ee9012 --- /dev/null +++ b/contrib/todo/macOS-hide-linker-visibility-warnings.patch @@ -0,0 +1,21 @@ +From a41021777eeb8fc06c9f8deb910468e4b5c65bbc Mon Sep 17 00:00:00 2001 +From: Dimitris Apostolou +Date: Thu, 12 Dec 2019 00:11:12 +0200 +Subject: depends macOS: hide linker visibility warnings + + +diff --git a/depends/builders/darwin.mk b/depends/builders/darwin.mk +index 7990b872f..f8ff4e23a 100644 +--- a/depends/builders/darwin.mk ++++ b/depends/builders/darwin.mk +@@ -10,8 +10,8 @@ build_darwin_SHA256SUM = shasum -a 256 + build_darwin_DOWNLOAD = curl --location --fail --connect-timeout $(DOWNLOAD_CONNECT_TIMEOUT) --retry $(DOWNLOAD_RETRIES) -o + + #darwin host on darwin builder. overrides darwin host preferences. +-darwin_CC=$(shell xcrun -f clang) -mmacosx-version-min=$(OSX_MIN_VERSION) --sysroot $(shell xcrun --show-sdk-path) +-darwin_CXX:=$(shell xcrun -f clang++) -mmacosx-version-min=$(OSX_MIN_VERSION) -stdlib=libc++ --sysroot $(shell xcrun --show-sdk-path) ++darwin_CC=$(shell xcrun -f clang) -mmacosx-version-min=$(OSX_MIN_VERSION) -fvisibility=hidden -fvisibility-inlines-hidden --sysroot $(shell xcrun --show-sdk-path) ++darwin_CXX:=$(shell xcrun -f clang++) -mmacosx-version-min=$(OSX_MIN_VERSION) -fvisibility=hidden -fvisibility-inlines-hidden -stdlib=libc++ --sysroot $(shell xcrun --show-sdk-path) + darwin_AR:=$(shell xcrun -f ar) + darwin_RANLIB:=$(shell xcrun -f ranlib) + darwin_STRIP:=$(shell xcrun -f strip) diff --git a/contrib/todo/txexpirynotify.patch b/contrib/todo/txexpirynotify.patch new file mode 100644 index 00000000..84a632a2 --- /dev/null +++ b/contrib/todo/txexpirynotify.patch @@ -0,0 +1,115 @@ +From e992825e0a486d4de4066d521eea14586e9e8ad9 Mon Sep 17 00:00:00 2001 +From: Alfredo Garcia +Date: Mon, 10 Feb 2020 19:44:20 -0300 +Subject: add txexpirynotify + + +diff --git a/src/init.cpp b/src/init.cpp +index 2c4727a56..03afa83c9 100644 +--- a/src/init.cpp ++++ b/src/init.cpp +@@ -368,6 +368,7 @@ std::string HelpMessage(HelpMessageMode mode) + #ifndef WIN32 + strUsage += HelpMessageOpt("-sysperms", _("Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)")); + #endif ++ strUsage += HelpMessageOpt("-txexpirynotify=", _("Execute command when transaction expires (%s in cmd is replaced by transaction id)")); + strUsage += HelpMessageOpt("-txindex", strprintf(_("Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)"), DEFAULT_TXINDEX)); + + strUsage += HelpMessageGroup(_("Connection options:")); +@@ -528,6 +529,14 @@ static void BlockNotifyCallback(const uint256& hashNewTip) + boost::thread t(runCommand, strCmd); // thread runs free + } + ++static void TxExpiryNotifyCallback(const uint256& txid) ++{ ++ std::string strCmd = GetArg("-txexpirynotify", ""); ++ ++ boost::replace_all(strCmd, "%s", txid.GetHex()); ++ boost::thread t(runCommand, strCmd); // thread runs free ++} ++ + struct CImportingNow + { + CImportingNow() { +@@ -1557,6 +1566,9 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) + if (mapArgs.count("-blocknotify")) + uiInterface.NotifyBlockTip.connect(BlockNotifyCallback); + ++ if (mapArgs.count("-txexpirynotify")) ++ uiInterface.NotifyTxExpiration.connect(TxExpiryNotifyCallback); ++ + uiInterface.InitMessage(_("Activating best chain...")); + // scan for better chains in the block chain database, that are not yet connected in the active best chain + CValidationState state; +diff --git a/src/main.cpp b/src/main.cpp +index bcf652693..82c9b6402 100644 +--- a/src/main.cpp ++++ b/src/main.cpp +@@ -3075,7 +3075,11 @@ bool static ConnectTip(CValidationState& state, const CChainParams& chainparams, + mempool.removeForBlock(pblock->vtx, pindexNew->nHeight, txConflicted, !IsInitialBlockDownload(chainparams)); + + // Remove transactions that expire at new block height from mempool +- mempool.removeExpired(pindexNew->nHeight); ++ auto ids = mempool.removeExpired(pindexNew->nHeight); ++ ++ for (auto id : ids) { ++ uiInterface.NotifyTxExpiration(id); ++ } + + // Update chainActive & related variables. + UpdateTip(pindexNew, chainparams); +diff --git a/src/txmempool.cpp b/src/txmempool.cpp +index 568d437fc..eb9eca11f 100644 +--- a/src/txmempool.cpp ++++ b/src/txmempool.cpp +@@ -406,7 +406,7 @@ void CTxMemPool::removeConflicts(const CTransaction &tx, std::list + } + } + +-void CTxMemPool::removeExpired(unsigned int nBlockHeight) ++std::vector CTxMemPool::removeExpired(unsigned int nBlockHeight) + { + // Remove expired txs from the mempool + LOCK(cs); +@@ -418,11 +418,14 @@ void CTxMemPool::removeExpired(unsigned int nBlockHeight) + transactionsToRemove.push_back(tx); + } + } ++ std::vector ids; + for (const CTransaction& tx : transactionsToRemove) { + list removed; + remove(tx, removed, true); ++ ids.push_back(tx.GetHash()); + LogPrint("mempool", "Removing expired txid: %s\n", tx.GetHash().ToString()); + } ++ return ids; + } + + /** +diff --git a/src/txmempool.h b/src/txmempool.h +index d66176436..e0f382ccf 100644 +--- a/src/txmempool.h ++++ b/src/txmempool.h +@@ -202,7 +202,7 @@ public: + void removeWithAnchor(const uint256 &invalidRoot, ShieldedType type); + void removeForReorg(const CCoinsViewCache *pcoins, unsigned int nMemPoolHeight, int flags); + void removeConflicts(const CTransaction &tx, std::list& removed); +- void removeExpired(unsigned int nBlockHeight); ++ std::vector removeExpired(unsigned int nBlockHeight); + void removeForBlock(const std::vector& vtx, unsigned int nBlockHeight, + std::list& conflicts, bool fCurrentEstimate = true); + void removeWithoutBranchId(uint32_t nMemPoolBranchId); +diff --git a/src/ui_interface.h b/src/ui_interface.h +index 3bcd57648..d7524db40 100644 +--- a/src/ui_interface.h ++++ b/src/ui_interface.h +@@ -98,6 +98,9 @@ public: + + /** New block has been accepted */ + boost::signals2::signal NotifyBlockTip; ++ ++ /** Transaction expired */ ++ boost::signals2::signal NotifyTxExpiration; + }; + + extern CClientUIInterface uiInterface; diff --git a/depends/hosts/linux.mk b/depends/hosts/linux.mk index 31748d66..b13a0f1a 100644 --- a/depends/hosts/linux.mk +++ b/depends/hosts/linux.mk @@ -1,7 +1,7 @@ linux_CFLAGS=-pipe linux_CXXFLAGS=$(linux_CFLAGS) -linux_release_CFLAGS=-O1 +linux_release_CFLAGS=-O2 linux_release_CXXFLAGS=$(linux_release_CFLAGS) linux_debug_CFLAGS=-O1 diff --git a/depends/packages/dbus.mk b/depends/packages/dbus.mk deleted file mode 100644 index bbe03754..00000000 --- a/depends/packages/dbus.mk +++ /dev/null @@ -1,23 +0,0 @@ -package=dbus -$(package)_version=1.10.18 -$(package)_download_path=https://dbus.freedesktop.org/releases/dbus -$(package)_file_name=$(package)-$($(package)_version).tar.gz -$(package)_sha256_hash=6049ddd5f3f3e2618f615f1faeda0a115104423a7996b7aa73e2f36e38cc514a -$(package)_dependencies=expat - -define $(package)_set_vars - $(package)_config_opts=--disable-tests --disable-doxygen-docs --disable-xml-docs --disable-static --without-x -endef - -define $(package)_config_cmds - $($(package)_autoconf) -endef - -define $(package)_build_cmds - $(MAKE) -C dbus libdbus-1.la -endef - -define $(package)_stage_cmds - $(MAKE) -C dbus DESTDIR=$($(package)_staging_dir) install-libLTLIBRARIES install-dbusincludeHEADERS install-nodist_dbusarchincludeHEADERS && \ - $(MAKE) DESTDIR=$($(package)_staging_dir) install-pkgconfigDATA -endef diff --git a/depends/packages/expat.mk b/depends/packages/expat.mk index 8d06882c..902fe43b 100644 --- a/depends/packages/expat.mk +++ b/depends/packages/expat.mk @@ -1,11 +1,13 @@ package=expat -$(package)_version=2.2.6 -$(package)_download_path=https://github.com/libexpat/libexpat/releases/download/R_2_2_6/ +$(package)_version=2.2.7 +$(package)_download_path=https://github.com/libexpat/libexpat/releases/download/R_2_2_7/ $(package)_file_name=$(package)-$($(package)_version).tar.bz2 -$(package)_sha256_hash=17b43c2716d521369f82fc2dc70f359860e90fa440bea65b3b85f0b246ea81f2 +$(package)_sha256_hash=cbc9102f4a31a8dafd42d642e9a3aa31e79a0aedaa1f6efd2795ebc83174ec18 define $(package)_set_vars -$(package)_config_opts=--disable-static --without-docbook + $(package)_config_opts=--disable-shared --without-docbook --without-tests --without-examples + $(package)_config_opts += --disable-dependency-tracking --enable-option-checking + $(package)_config_opts_linux=--with-pic endef define $(package)_config_cmds @@ -19,3 +21,7 @@ endef define $(package)_stage_cmds $(MAKE) DESTDIR=$($(package)_staging_dir) install endef + +define $(package)_postprocess_cmds + rm lib/*.la +endef diff --git a/depends/packages/fontconfig.mk b/depends/packages/fontconfig.mk index 12695db4..128599ba 100644 --- a/depends/packages/fontconfig.mk +++ b/depends/packages/fontconfig.mk @@ -1,12 +1,13 @@ package=fontconfig $(package)_version=2.12.1 -$(package)_download_path=http://www.freedesktop.org/software/fontconfig/release/ +$(package)_download_path=https://www.freedesktop.org/software/fontconfig/release/ $(package)_file_name=$(package)-$($(package)_version).tar.bz2 $(package)_sha256_hash=b449a3e10c47e1d1c7a6ec6e2016cca73d3bd68fbbd4f0ae5cc6b573f7d6c7f3 $(package)_dependencies=freetype expat define $(package)_set_vars - $(package)_config_opts=--disable-docs --disable-static + $(package)_config_opts=--disable-docs --disable-static --disable-libxml2 --disable-iconv + $(package)_config_opts += --disable-dependency-tracking --enable-option-checking endef define $(package)_config_cmds @@ -26,3 +27,7 @@ endef define $(package)_stage_cmds $(MAKE) DESTDIR=$($(package)_staging_dir) install endef + +define $(package)_postprocess_cmds + rm lib/*.la +endef diff --git a/depends/packages/freetype.mk b/depends/packages/freetype.mk index 41e02e20..a1584608 100644 --- a/depends/packages/freetype.mk +++ b/depends/packages/freetype.mk @@ -1,11 +1,12 @@ package=freetype $(package)_version=2.7.1 -$(package)_download_path=http://download.savannah.gnu.org/releases/$(package) +$(package)_download_path=https://download.savannah.gnu.org/releases/$(package) $(package)_file_name=$(package)-$($(package)_version).tar.bz2 $(package)_sha256_hash=3a3bb2c4e15ffb433f2032f50a5b5a92558206822e22bfe8cbe339af4aa82f88 define $(package)_set_vars $(package)_config_opts=--without-zlib --without-png --without-harfbuzz --without-bzip2 --disable-static + $(package)_config_opts += --enable-option-checking $(package)_config_opts_linux=--with-pic endef @@ -20,3 +21,7 @@ endef define $(package)_stage_cmds $(MAKE) DESTDIR=$($(package)_staging_dir) install endef + +define $(package)_postprocess_cmds + rm lib/*.la +endef diff --git a/depends/packages/libX11.mk b/depends/packages/libX11.mk deleted file mode 100644 index 298616be..00000000 --- a/depends/packages/libX11.mk +++ /dev/null @@ -1,27 +0,0 @@ -package=libX11 -$(package)_version=1.6.2 -$(package)_download_path=http://xorg.freedesktop.org/releases/individual/lib/ -$(package)_file_name=$(package)-$($(package)_version).tar.bz2 -$(package)_sha256_hash=2aa027e837231d2eeea90f3a4afe19948a6eb4c8b2bec0241eba7dbc8106bd16 -$(package)_dependencies=libxcb xtrans xextproto xproto - -define $(package)_set_vars -$(package)_config_opts=--disable-xkb --disable-static -$(package)_config_opts_linux=--with-pic -endef - -define $(package)_preprocess_cmds - cp -f $(BASEDIR)/config.guess $(BASEDIR)/config.sub . -endef - -define $(package)_config_cmds - $($(package)_autoconf) -endef - -define $(package)_build_cmds - $(MAKE) -endef - -define $(package)_stage_cmds - $(MAKE) DESTDIR=$($(package)_staging_dir) install -endef diff --git a/depends/packages/libXau.mk b/depends/packages/libXau.mk index 304494e3..4c55c2df 100644 --- a/depends/packages/libXau.mk +++ b/depends/packages/libXau.mk @@ -1,12 +1,15 @@ package=libXau $(package)_version=1.0.8 -$(package)_download_path=http://xorg.freedesktop.org/releases/individual/lib/ +$(package)_download_path=https://xorg.freedesktop.org/releases/individual/lib/ $(package)_file_name=$(package)-$($(package)_version).tar.bz2 $(package)_sha256_hash=fdd477320aeb5cdd67272838722d6b7d544887dfe7de46e1e7cc0c27c2bea4f2 $(package)_dependencies=xproto +# When updating this package, check the default value of +# --disable-xthreads. It is currently enabled. define $(package)_set_vars - $(package)_config_opts=--disable-shared + $(package)_config_opts=--disable-shared --disable-lint-library --without-lint + $(package)_config_opts += --disable-dependency-tracking --enable-option-checking $(package)_config_opts_linux=--with-pic endef @@ -25,3 +28,7 @@ endef define $(package)_stage_cmds $(MAKE) DESTDIR=$($(package)_staging_dir) install endef + +define $(package)_postprocess_cmds + rm lib/*.la +endef diff --git a/depends/packages/libXext.mk b/depends/packages/libXext.mk deleted file mode 100644 index c0565dd6..00000000 --- a/depends/packages/libXext.mk +++ /dev/null @@ -1,26 +0,0 @@ -package=libXext -$(package)_version=1.3.2 -$(package)_download_path=http://xorg.freedesktop.org/releases/individual/lib/ -$(package)_file_name=$(package)-$($(package)_version).tar.bz2 -$(package)_sha256_hash=f829075bc646cdc085fa25d98d5885d83b1759ceb355933127c257e8e50432e0 -$(package)_dependencies=xproto xextproto libX11 libXau - -define $(package)_set_vars - $(package)_config_opts=--disable-static -endef - -define $(package)_preprocess_cmds - cp -f $(BASEDIR)/config.guess $(BASEDIR)/config.sub . -endef - -define $(package)_config_cmds - $($(package)_autoconf) -endef - -define $(package)_build_cmds - $(MAKE) -endef - -define $(package)_stage_cmds - $(MAKE) DESTDIR=$($(package)_staging_dir) install -endef diff --git a/depends/packages/libxcb.mk b/depends/packages/libxcb.mk index 3f346d97..2204b381 100644 --- a/depends/packages/libxcb.mk +++ b/depends/packages/libxcb.mk @@ -1,12 +1,25 @@ package=libxcb $(package)_version=1.10 -$(package)_download_path=http://xcb.freedesktop.org/dist +$(package)_download_path=https://xcb.freedesktop.org/dist $(package)_file_name=$(package)-$($(package)_version).tar.bz2 $(package)_sha256_hash=98d9ab05b636dd088603b64229dd1ab2d2cc02ab807892e107d674f9c3f2d5b5 -$(package)_dependencies=xcb_proto libXau xproto +$(package)_dependencies=xcb_proto libXau define $(package)_set_vars -$(package)_config_opts=--disable-static +$(package)_config_opts=--disable-static --disable-build-docs --without-doxygen --without-launchd +$(package)_config_opts += --disable-dependency-tracking --enable-option-checking +# Because we pass -qt-xcb to Qt, it will compile in a set of xcb helper libraries and extensions, +# so we skip building all of the extensions here. +# More info is available from: https://doc.qt.io/qt-5.9/linux-requirements.html +$(package)_config_opts += --disable-composite --disable-damage --disable-dpms +$(package)_config_opts += --disable-dri2 --disable-dri3 --disable-glx +$(package)_config_opts += --disable-present --disable-randr --disable-record +$(package)_config_opts += --disable-render --disable-resource --disable-screensaver +$(package)_config_opts += --disable-shape --disable-shm --disable-sync +$(package)_config_opts += --disable-xevie --disable-xfixes --disable-xfree86-dri +$(package)_config_opts += --disable-xinerama --disable-xinput --disable-xkb +$(package)_config_opts += --disable-xprint --disable-selinux --disable-xtest +$(package)_config_opts += --disable-xv --disable-xvmc endef define $(package)_preprocess_cmds @@ -32,5 +45,5 @@ define $(package)_stage_cmds endef define $(package)_postprocess_cmds - rm -rf share/man share/doc + rm -rf share/man share/doc lib/*.la endef diff --git a/depends/packages/packages.mk b/depends/packages/packages.mk index 80f157e3..e64f1d82 100644 --- a/depends/packages/packages.mk +++ b/depends/packages/packages.mk @@ -9,7 +9,8 @@ endif qt_native_packages = native_protobuf qt_packages = qrencode protobuf zlib -qt_linux_packages:=qt expat dbus libxcb xcb_proto libXau xproto freetype fontconfig libX11 xextproto libXext xtrans +qt_linux_packages:=qt expat libxcb xcb_proto libXau xproto freetype fontconfig +qt_android_packages=qt qt_darwin_packages=qt qt_mingw32_packages=qt diff --git a/depends/packages/qrencode.mk b/depends/packages/qrencode.mk index 313e4adf..d1687883 100644 --- a/depends/packages/qrencode.mk +++ b/depends/packages/qrencode.mk @@ -5,8 +5,11 @@ $(package)_file_name=$(package)-$($(package)_version).tar.bz2 $(package)_sha256_hash=efe5188b1ddbcbf98763b819b146be6a90481aac30cfc8d858ab78a19cde1fa5 define $(package)_set_vars -$(package)_config_opts=--disable-shared -without-tools --disable-sdltest +$(package)_config_opts=--disable-shared --without-tools --without-tests --disable-sdltest +$(package)_config_opts += --disable-gprof --disable-gcov --disable-mudflap +$(package)_config_opts += --disable-dependency-tracking --enable-option-checking $(package)_config_opts_linux=--with-pic +$(package)_config_opts_android=--with-pic endef define $(package)_preprocess_cmds @@ -24,3 +27,7 @@ endef define $(package)_stage_cmds $(MAKE) DESTDIR=$($(package)_staging_dir) install endef + +define $(package)_postprocess_cmds + rm lib/*.la +endef diff --git a/depends/packages/qt.mk b/depends/packages/qt.mk index 379632ea..d1e62723 100644 --- a/depends/packages/qt.mk +++ b/depends/packages/qt.mk @@ -1,20 +1,20 @@ PACKAGE=qt -$(package)_version=5.9.7 +$(package)_version=5.9.8 $(package)_download_path=https://download.qt.io/official_releases/qt/5.9/$($(package)_version)/submodules $(package)_suffix=opensource-src-$($(package)_version).tar.xz $(package)_file_name=qtbase-$($(package)_suffix) -$(package)_sha256_hash=36dd9574f006eaa1e5af780e4b33d11fe39d09fd7c12f3b9d83294174bd28f00 -$(package)_dependencies=openssl zlib -$(package)_linux_dependencies=freetype fontconfig libxcb libX11 xproto libXext +$(package)_sha256_hash=9b9dec1f67df1f94bce2955c5604de992d529dde72050239154c56352da0907d +$(package)_dependencies=zlib +$(package)_linux_dependencies=freetype fontconfig libxcb $(package)_build_subdir=qtbase $(package)_qt_libs=corelib network widgets gui plugins testlib -$(package)_patches=fix_qt_pkgconfig.patch mac-qmake.conf fix_configure_mac.patch fix_no_printer.patch fix_rcc_determinism.patch fix_riscv64_arch.patch xkb-default.patch +$(package)_patches=fix_qt_pkgconfig.patch mac-qmake.conf fix_configure_mac.patch fix_no_printer.patch fix_rcc_determinism.patch fix_riscv64_arch.patch xkb-default.patch no-xlib.patch fix_android_qmake_conf.patch fix_android_jni_static.patch $(package)_qttranslations_file_name=qttranslations-$($(package)_suffix) -$(package)_qttranslations_sha256_hash=b36da7d93c3ab6fca56b32053bb73bc619c8b192bb89b74e3bcde2705f1c2a14 +$(package)_qttranslations_sha256_hash=fb5a47799754af73d3bf501fe513342cfe2fc37f64e80df5533f6110e804220c $(package)_qttools_file_name=qttools-$($(package)_suffix) -$(package)_qttools_sha256_hash=d62e0f70d99645d6704dbb8976fb2222443061743689943d40970c52c49367a1 +$(package)_qttools_sha256_hash=a97556eb7b2f30252cdd8a598c396cfce2b2f79d2bae883af6d3b26a2cdcc63c $(package)_extra_sources = $($(package)_qttranslations_file_name) $(package)_extra_sources += $($(package)_qttools_file_name) @@ -25,7 +25,6 @@ $(package)_config_opts_debug = -debug $(package)_config_opts += -bindir $(build_prefix)/bin $(package)_config_opts += -c++std c++11 $(package)_config_opts += -confirm-license -$(package)_config_opts += -dbus-runtime $(package)_config_opts += -hostprefix $(build_prefix) $(package)_config_opts += -no-compile-examples $(package)_config_opts += -no-cups @@ -35,14 +34,20 @@ $(package)_config_opts += -no-freetype $(package)_config_opts += -no-gif $(package)_config_opts += -no-glib $(package)_config_opts += -no-icu +$(package)_config_opts += -no-ico $(package)_config_opts += -no-iconv $(package)_config_opts += -no-kms $(package)_config_opts += -no-linuxfb +$(package)_config_opts += -no-libjpeg +$(package)_config_opts += -no-libproxy $(package)_config_opts += -no-libudev $(package)_config_opts += -no-mtdev +$(package)_config_opts += -no-openssl $(package)_config_opts += -no-openvg $(package)_config_opts += -no-reduce-relocations $(package)_config_opts += -no-qml-debug +$(package)_config_opts += -no-sctp +$(package)_config_opts += -no-securetransport $(package)_config_opts += -no-sql-db2 $(package)_config_opts += -no-sql-ibase $(package)_config_opts += -no-sql-oci @@ -52,62 +57,114 @@ $(package)_config_opts += -no-sql-odbc $(package)_config_opts += -no-sql-psql $(package)_config_opts += -no-sql-sqlite $(package)_config_opts += -no-sql-sqlite2 +$(package)_config_opts += -no-system-proxies $(package)_config_opts += -no-use-gold-linker $(package)_config_opts += -no-xinput2 $(package)_config_opts += -nomake examples $(package)_config_opts += -nomake tests $(package)_config_opts += -opensource -$(package)_config_opts += -no-openssl -$(package)_config_opts += -optimized-qmake +$(package)_config_opts += -optimized-tools $(package)_config_opts += -pch $(package)_config_opts += -pkg-config $(package)_config_opts += -prefix $(host_prefix) $(package)_config_opts += -qt-libpng -$(package)_config_opts += -qt-libjpeg $(package)_config_opts += -qt-pcre $(package)_config_opts += -qt-harfbuzz $(package)_config_opts += -system-zlib $(package)_config_opts += -static $(package)_config_opts += -silent $(package)_config_opts += -v +$(package)_config_opts += -no-feature-bearermanagement +$(package)_config_opts += -no-feature-colordialog +$(package)_config_opts += -no-feature-commandlineparser +$(package)_config_opts += -no-feature-concurrent $(package)_config_opts += -no-feature-dial +$(package)_config_opts += -no-feature-filesystemwatcher +$(package)_config_opts += -no-feature-fontcombobox $(package)_config_opts += -no-feature-ftp +$(package)_config_opts += -no-feature-http +$(package)_config_opts += -no-feature-image_heuristic_mask +$(package)_config_opts += -no-feature-keysequenceedit $(package)_config_opts += -no-feature-lcdnumber +$(package)_config_opts += -no-feature-networkdiskcache +$(package)_config_opts += -no-feature-networkproxy $(package)_config_opts += -no-feature-pdf -$(package)_config_opts += -no-feature-printer $(package)_config_opts += -no-feature-printdialog -$(package)_config_opts += -no-feature-concurrent +$(package)_config_opts += -no-feature-printer +$(package)_config_opts += -no-feature-printpreviewdialog +$(package)_config_opts += -no-feature-printpreviewwidget +$(package)_config_opts += -no-feature-regularexpression +$(package)_config_opts += -no-feature-sessionmanager +$(package)_config_opts += -no-feature-socks5 $(package)_config_opts += -no-feature-sql $(package)_config_opts += -no-feature-statemachine $(package)_config_opts += -no-feature-syntaxhighlighter $(package)_config_opts += -no-feature-textbrowser $(package)_config_opts += -no-feature-textodfwriter +$(package)_config_opts += -no-feature-topleveldomain $(package)_config_opts += -no-feature-udpsocket +$(package)_config_opts += -no-feature-undocommand +$(package)_config_opts += -no-feature-undogroup +$(package)_config_opts += -no-feature-undostack +$(package)_config_opts += -no-feature-undoview +$(package)_config_opts += -no-feature-vnc $(package)_config_opts += -no-feature-wizard $(package)_config_opts += -no-feature-xml +$(package)_config_opts_darwin = -no-dbus +$(package)_config_opts_darwin += -no-opengl + ifneq ($(build_os),darwin) -$(package)_config_opts_darwin = -xplatform macx-clang-linux +$(package)_config_opts_darwin += -xplatform macx-clang-linux $(package)_config_opts_darwin += -device-option MAC_SDK_PATH=$(OSX_SDK) $(package)_config_opts_darwin += -device-option MAC_SDK_VERSION=$(OSX_SDK_VERSION) $(package)_config_opts_darwin += -device-option CROSS_COMPILE="$(host)-" $(package)_config_opts_darwin += -device-option MAC_MIN_VERSION=$(OSX_MIN_VERSION) $(package)_config_opts_darwin += -device-option MAC_TARGET=$(host) -$(package)_config_opts_darwin += -device-option MAC_LD64_VERSION=$(LD64_VERSION) endif $(package)_config_opts_linux = -qt-xkbcommon-x11 $(package)_config_opts_linux += -qt-xcb +$(package)_config_opts_linux += -no-xcb-xlib +$(package)_config_opts_linux += -no-feature-xlib $(package)_config_opts_linux += -system-freetype -$(package)_config_opts_linux += -no-feature-sessionmanager $(package)_config_opts_linux += -fontconfig $(package)_config_opts_linux += -no-opengl +$(package)_config_opts_linux += -dbus-runtime $(package)_config_opts_arm_linux += -platform linux-g++ -xplatform bitcoin-linux-g++ $(package)_config_opts_i686_linux = -xplatform linux-g++-32 $(package)_config_opts_x86_64_linux = -xplatform linux-g++-64 $(package)_config_opts_aarch64_linux = -xplatform linux-aarch64-gnu-g++ +$(package)_config_opts_powerpc64_linux = -platform linux-g++ -xplatform bitcoin-linux-g++ +$(package)_config_opts_powerpc64le_linux = -platform linux-g++ -xplatform bitcoin-linux-g++ $(package)_config_opts_riscv64_linux = -platform linux-g++ -xplatform bitcoin-linux-g++ -$(package)_config_opts_mingw32 = -no-opengl -xplatform win32-g++ -device-option CROSS_COMPILE="$(host)-" +$(package)_config_opts_s390x_linux = -platform linux-g++ -xplatform bitcoin-linux-g++ + +$(package)_config_opts_mingw32 = -no-opengl +$(package)_config_opts_mingw32 += -no-dbus +$(package)_config_opts_mingw32 += -xplatform win32-g++ +$(package)_config_opts_mingw32 += -device-option CROSS_COMPILE="$(host)-" + +$(package)_config_opts_android = -xplatform android-clang +$(package)_config_opts_android += -android-sdk $(ANDROID_SDK) +$(package)_config_opts_android += -android-ndk $(ANDROID_NDK) +$(package)_config_opts_android += -android-ndk-platform android-$(ANDROID_API_LEVEL) +$(package)_config_opts_android += -device-option CROSS_COMPILE="$(host)-" +$(package)_config_opts_android += -egl +$(package)_config_opts_android += -qpa xcb +$(package)_config_opts_android += -no-eglfs +$(package)_config_opts_android += -no-dbus +$(package)_config_opts_android += -opengl es2 +$(package)_config_opts_android += -qt-freetype +$(package)_config_opts_android += -no-fontconfig +$(package)_config_opts_android += -L $(host_prefix)/lib +$(package)_config_opts_android += -I $(host_prefix)/include + +$(package)_config_opts_aarch64_android += -android-arch arm64-v8a +$(package)_config_opts_armv7a_android += -android-arch armeabi-v7a +$(package)_config_opts_x86_64_android += -android-arch x86_64 +$(package)_config_opts_i686_android += -android-arch i686 + $(package)_build_env = QT_RCC_TEST=1 $(package)_build_env += QT_RCC_SOURCE_DATE_OVERRIDE=1 endef @@ -137,9 +194,7 @@ define $(package)_preprocess_cmds sed -i.old "s|updateqm.commands = \$$$$\$$$$LRELEASE|updateqm.commands = $($(package)_extract_dir)/qttools/bin/lrelease|" qttranslations/translations/translations.pro && \ sed -i.old "/updateqm.depends =/d" qttranslations/translations/translations.pro && \ sed -i.old "s/src_plugins.depends = src_sql src_network/src_plugins.depends = src_network/" qtbase/src/src.pro && \ - sed -i.old "s|X11/extensions/XIproto.h|X11/X.h|" qtbase/src/plugins/platforms/xcb/qxcbxsettings.cpp && \ sed -i.old -e 's/if \[ "$$$$XPLATFORM_MAC" = "yes" \]; then xspecvals=$$$$(macSDKify/if \[ "$$$$BUILD_ON_MAC" = "yes" \]; then xspecvals=$$$$(macSDKify/' -e 's|/bin/pwd|pwd|' qtbase/configure && \ - sed -i.old 's/CGEventCreateMouseEvent(0, kCGEventMouseMoved, pos, 0)/CGEventCreateMouseEvent(0, kCGEventMouseMoved, pos, kCGMouseButtonLeft)/' qtbase/src/plugins/platforms/cocoa/qcocoacursor.mm && \ mkdir -p qtbase/mkspecs/macx-clang-linux &&\ cp -f qtbase/mkspecs/macx-clang/Info.plist.lib qtbase/mkspecs/macx-clang-linux/ &&\ cp -f qtbase/mkspecs/macx-clang/Info.plist.app qtbase/mkspecs/macx-clang-linux/ &&\ @@ -152,15 +207,19 @@ define $(package)_preprocess_cmds patch -p1 -i $($(package)_patch_dir)/fix_no_printer.patch &&\ patch -p1 -i $($(package)_patch_dir)/fix_rcc_determinism.patch &&\ patch -p1 -i $($(package)_patch_dir)/xkb-default.patch &&\ + patch -p1 -i $($(package)_patch_dir)/fix_android_qmake_conf.patch &&\ + patch -p1 -i $($(package)_patch_dir)/fix_android_jni_static.patch &&\ echo "!host_build: QMAKE_CFLAGS += $($(package)_cflags) $($(package)_cppflags)" >> qtbase/mkspecs/common/gcc-base.conf && \ echo "!host_build: QMAKE_CXXFLAGS += $($(package)_cxxflags) $($(package)_cppflags)" >> qtbase/mkspecs/common/gcc-base.conf && \ echo "!host_build: QMAKE_LFLAGS += $($(package)_ldflags)" >> qtbase/mkspecs/common/gcc-base.conf && \ patch -p1 -i $($(package)_patch_dir)/fix_riscv64_arch.patch &&\ + patch -p1 -i $($(package)_patch_dir)/no-xlib.patch &&\ echo "QMAKE_LINK_OBJECT_MAX = 10" >> qtbase/mkspecs/win32-g++/qmake.conf &&\ echo "QMAKE_LINK_OBJECT_SCRIPT = object_script" >> qtbase/mkspecs/win32-g++/qmake.conf &&\ - sed -i.old "s|QMAKE_CFLAGS = |!host_build: QMAKE_CFLAGS = $($(package)_cflags) $($(package)_cppflags) |" qtbase/mkspecs/win32-g++/qmake.conf && \ - sed -i.old "s|QMAKE_LFLAGS = |!host_build: QMAKE_LFLAGS = $($(package)_ldflags) |" qtbase/mkspecs/win32-g++/qmake.conf && \ - sed -i.old "s|QMAKE_CXXFLAGS = |!host_build: QMAKE_CXXFLAGS = $($(package)_cxxflags) $($(package)_cppflags) |" qtbase/mkspecs/win32-g++/qmake.conf + sed -i.old "s|QMAKE_CFLAGS += |!host_build: QMAKE_CFLAGS = $($(package)_cflags) $($(package)_cppflags) |" qtbase/mkspecs/win32-g++/qmake.conf && \ + sed -i.old "s|QMAKE_CXXFLAGS += |!host_build: QMAKE_CXXFLAGS = $($(package)_cxxflags) $($(package)_cppflags) |" qtbase/mkspecs/win32-g++/qmake.conf && \ + sed -i.old "0,/^QMAKE_LFLAGS_/s|^QMAKE_LFLAGS_|!host_build: QMAKE_LFLAGS = $($(package)_ldflags)\n&|" qtbase/mkspecs/win32-g++/qmake.conf && \ + sed -i.old "s/LIBRARY_PATH/(CROSS_)?\0/g" qtbase/mkspecs/features/toolchain.prf endef define $(package)_config_cmds diff --git a/depends/packages/xcb_proto.mk b/depends/packages/xcb_proto.mk index 0c7c958d..01203a07 100644 --- a/depends/packages/xcb_proto.mk +++ b/depends/packages/xcb_proto.mk @@ -1,14 +1,9 @@ package=xcb_proto $(package)_version=1.10 -$(package)_download_path=http://xcb.freedesktop.org/dist +$(package)_download_path=https://xcb.freedesktop.org/dist $(package)_file_name=xcb-proto-$($(package)_version).tar.bz2 $(package)_sha256_hash=7ef40ddd855b750bc597d2a435da21e55e502a0fefa85b274f2c922800baaf05 -define $(package)_set_vars - $(package)_config_opts=--disable-shared - $(package)_config_opts_linux=--with-pic -endef - define $(package)_config_cmds $($(package)_autoconf) endef diff --git a/depends/packages/xextproto.mk b/depends/packages/xextproto.mk deleted file mode 100644 index 7065237b..00000000 --- a/depends/packages/xextproto.mk +++ /dev/null @@ -1,25 +0,0 @@ -package=xextproto -$(package)_version=7.3.0 -$(package)_download_path=http://xorg.freedesktop.org/releases/individual/proto -$(package)_file_name=$(package)-$($(package)_version).tar.bz2 -$(package)_sha256_hash=f3f4b23ac8db9c3a9e0d8edb591713f3d70ef9c3b175970dd8823dfc92aa5bb0 - -define $(package)_preprocess_cmds - cp -f $(BASEDIR)/config.guess $(BASEDIR)/config.sub . -endef - -define $(package)_set_vars -$(package)_config_opts=--disable-shared -endef - -define $(package)_config_cmds - $($(package)_autoconf) -endef - -define $(package)_build_cmds - $(MAKE) -endef - -define $(package)_stage_cmds - $(MAKE) DESTDIR=$($(package)_staging_dir) install -endef diff --git a/depends/packages/xproto.mk b/depends/packages/xproto.mk index 5328ec84..6bd867d0 100644 --- a/depends/packages/xproto.mk +++ b/depends/packages/xproto.mk @@ -1,11 +1,12 @@ package=xproto $(package)_version=7.0.26 -$(package)_download_path=http://xorg.freedesktop.org/releases/individual/proto +$(package)_download_path=https://xorg.freedesktop.org/releases/individual/proto $(package)_file_name=$(package)-$($(package)_version).tar.bz2 $(package)_sha256_hash=636162c1759805a5a0114a369dffdeccb8af8c859ef6e1445f26a4e6e046514f define $(package)_set_vars -$(package)_config_opts=--disable-shared +$(package)_config_opts=--without-fop --without-xmlto --without-xsltproc --disable-specs +$(package)_config_opts += --disable-dependency-tracking --enable-option-checking endef define $(package)_preprocess_cmds diff --git a/depends/packages/xtrans.mk b/depends/packages/xtrans.mk deleted file mode 100644 index c313b1f6..00000000 --- a/depends/packages/xtrans.mk +++ /dev/null @@ -1,26 +0,0 @@ -package=xtrans -$(package)_version=1.3.4 -$(package)_download_path=http://xorg.freedesktop.org/releases/individual/lib/ -$(package)_file_name=$(package)-$($(package)_version).tar.bz2 -$(package)_sha256_hash=054d4ee3efd52508c753e9f7bc655ef185a29bd2850dd9e2fc2ccc33544f583a -$(package)_dependencies= - -define $(package)_set_vars -$(package)_config_opts_linux=--with-pic --disable-static -endef - -define $(package)_preprocess_cmds - cp -f $(BASEDIR)/config.guess $(BASEDIR)/config.sub . -endef - -define $(package)_config_cmds - $($(package)_autoconf) -endef - -define $(package)_build_cmds - $(MAKE) -endef - -define $(package)_stage_cmds - $(MAKE) DESTDIR=$($(package)_staging_dir) install -endef diff --git a/depends/packages/zlib.mk b/depends/packages/zlib.mk index 58949080..acb02020 100644 --- a/depends/packages/zlib.mk +++ b/depends/packages/zlib.mk @@ -1,27 +1,31 @@ package=zlib $(package)_version=1.2.11 -$(package)_download_path=http://www.zlib.net +$(package)_download_path=https://www.zlib.net $(package)_file_name=$(package)-$($(package)_version).tar.gz $(package)_sha256_hash=c3e5e9fdd5004dcb542feda5ee4f0ff0744628baf8ed2dd5d66f8ca1197cb1a1 define $(package)_set_vars -$(package)_build_opts= CC="$($(package)_cc)" -$(package)_build_opts+=CFLAGS="$($(package)_cflags) $($(package)_cppflags) -fPIC" -$(package)_build_opts+=RANLIB="$($(package)_ranlib)" -$(package)_build_opts+=AR="$($(package)_ar)" -$(package)_build_opts_darwin+=AR="$($(package)_libtool)" -$(package)_build_opts_darwin+=ARFLAGS="-o" +$(package)_config_opts= CC="$($(package)_cc)" +$(package)_config_opts+=CFLAGS="$($(package)_cflags) $($(package)_cppflags) -fPIC" +$(package)_config_opts+=RANLIB="$($(package)_ranlib)" +$(package)_config_opts+=AR="$($(package)_ar)" +$(package)_config_opts_darwin+=AR="$($(package)_libtool)" +$(package)_config_opts_darwin+=ARFLAGS="-o" +$(package)_config_opts_android+=CHOST=$(host) endef +# zlib has its own custom configure script that takes in options like CC, +# CFLAGS, RANLIB, AR, and ARFLAGS from the environment rather than from +# command-line arguments. define $(package)_config_cmds - ./configure --static --prefix=$(host_prefix) + env $($(package)_config_opts) ./configure --static --prefix=$(host_prefix) endef define $(package)_build_cmds - $(MAKE) $($(package)_build_opts) libz.a + $(MAKE) libz.a endef define $(package)_stage_cmds - $(MAKE) DESTDIR=$($(package)_staging_dir) install $($(package)_build_opts) + $(MAKE) DESTDIR=$($(package)_staging_dir) install endef diff --git a/depends/patches/qt/fix_android_jni_static.patch b/depends/patches/qt/fix_android_jni_static.patch new file mode 100644 index 00000000..2f6ff00f --- /dev/null +++ b/depends/patches/qt/fix_android_jni_static.patch @@ -0,0 +1,18 @@ +--- old/qtbase/src/plugins/platforms/android/androidjnimain.cpp ++++ new/qtbase/src/plugins/platforms/android/androidjnimain.cpp +@@ -890,6 +890,14 @@ + __android_log_print(ANDROID_LOG_FATAL, "Qt", "registerNatives failed"); + return -1; + } ++ ++ const jint ret = QT_PREPEND_NAMESPACE(QtAndroidPrivate::initJNI(vm, env)); ++ if (ret != 0) ++ { ++ __android_log_print(ANDROID_LOG_FATAL, "Qt", "initJNI failed"); ++ return ret; ++ } ++ + QWindowSystemInterfacePrivate::TabletEvent::setPlatformSynthesizesMouse(false); + + m_javaVM = vm; + diff --git a/depends/patches/qt/fix_android_qmake_conf.patch b/depends/patches/qt/fix_android_qmake_conf.patch new file mode 100644 index 00000000..13bfff97 --- /dev/null +++ b/depends/patches/qt/fix_android_qmake_conf.patch @@ -0,0 +1,20 @@ +--- old/qtbase/mkspecs/android-clang/qmake.conf ++++ new/qtbase/mkspecs/android-clang/qmake.conf +@@ -30,7 +30,7 @@ + QMAKE_CFLAGS += -target mips64el-none-linux-android + + QMAKE_CFLAGS += -gcc-toolchain $$NDK_TOOLCHAIN_PATH +-QMAKE_LINK = $$QMAKE_CXX $$QMAKE_CFLAGS -Wl,--exclude-libs,libgcc.a ++QMAKE_LINK = $$QMAKE_CXX $$QMAKE_CFLAGS -Wl,--exclude-libs,libgcc.a -nostdlib++ + QMAKE_CFLAGS += -DANDROID_HAS_WSTRING --sysroot=$$NDK_ROOT/sysroot \ + -isystem $$NDK_ROOT/sysroot/usr/include/$$NDK_TOOLS_PREFIX \ + -isystem $$NDK_ROOT/sources/cxx-stl/llvm-libc++/include \ +@@ -40,7 +40,7 @@ + ANDROID_SOURCES_CXX_STL_LIBDIR = $$NDK_ROOT/sources/cxx-stl/llvm-libc++/libs/$$ANDROID_TARGET_ARCH + + ANDROID_STDCPP_PATH = $$ANDROID_SOURCES_CXX_STL_LIBDIR/libc++_shared.so +-ANDROID_CXX_STL_LIBS = -lc++ ++ANDROID_CXX_STL_LIBS = -lc++_shared + + QMAKE_ARM_CFLAGS_RELEASE = -Oz + QMAKE_ARM_CFLAGS_RELEASE_WITH_DEBUGINFO = -g -Oz diff --git a/depends/patches/qt/mac-qmake.conf b/depends/patches/qt/mac-qmake.conf index 337d0eb9..4cd96df2 100644 --- a/depends/patches/qt/mac-qmake.conf +++ b/depends/patches/qt/mac-qmake.conf @@ -18,7 +18,7 @@ QMAKE_APPLE_DEVICE_ARCHS=x86_64 !host_build: QMAKE_CFLAGS += -target $${MAC_TARGET} !host_build: QMAKE_OBJECTIVE_CFLAGS += $$QMAKE_CFLAGS !host_build: QMAKE_CXXFLAGS += $$QMAKE_CFLAGS -!host_build: QMAKE_LFLAGS += -target $${MAC_TARGET} -mlinker-version=$${MAC_LD64_VERSION} +!host_build: QMAKE_LFLAGS += -target $${MAC_TARGET} QMAKE_AR = $${CROSS_COMPILE}ar cq QMAKE_RANLIB=$${CROSS_COMPILE}ranlib QMAKE_LIBTOOL=$${CROSS_COMPILE}libtool diff --git a/depends/patches/qt/no-xlib.patch b/depends/patches/qt/no-xlib.patch new file mode 100644 index 00000000..fe82c2c7 --- /dev/null +++ b/depends/patches/qt/no-xlib.patch @@ -0,0 +1,69 @@ +From 9563cef873ae82e06f60708d706d054717e801ce Mon Sep 17 00:00:00 2001 +From: Carl Dong +Date: Thu, 18 Jul 2019 17:22:05 -0400 +Subject: [PATCH] Wrap xlib related code blocks in #if's + +They are not necessary to compile QT. +--- + qtbase/src/plugins/platforms/xcb/qxcbcursor.cpp | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/qtbase/src/plugins/platforms/xcb/qxcbcursor.cpp b/qtbase/src/plugins/platforms/xcb/qxcbcursor.cpp +index 7c62c2e2b3..c05c6c0a07 100644 +--- a/qtbase/src/plugins/platforms/xcb/qxcbcursor.cpp ++++ b/qtbase/src/plugins/platforms/xcb/qxcbcursor.cpp +@@ -49,7 +49,9 @@ + #include + #include + #include ++#if QT_CONFIG(xcb_xlib) && QT_CONFIG(library) + #include ++#endif + #include + #include + +@@ -384,6 +386,7 @@ void QXcbCursor::changeCursor(QCursor *cursor, QWindow *widget) + w->setCursor(c, isBitmapCursor); + } + ++#if QT_CONFIG(xcb_xlib) && QT_CONFIG(library) + static int cursorIdForShape(int cshape) + { + int cursorId = 0; +@@ -437,6 +440,7 @@ static int cursorIdForShape(int cshape) + } + return cursorId; + } ++#endif + + xcb_cursor_t QXcbCursor::createNonStandardCursor(int cshape) + { +@@ -558,7 +562,9 @@ static xcb_cursor_t loadCursor(void *dpy, int cshape) + xcb_cursor_t QXcbCursor::createFontCursor(int cshape) + { + xcb_connection_t *conn = xcb_connection(); ++#if QT_CONFIG(xcb_xlib) && QT_CONFIG(library) + int cursorId = cursorIdForShape(cshape); ++#endif + xcb_cursor_t cursor = XCB_NONE; + + // Try Xcursor first +@@ -589,6 +595,7 @@ xcb_cursor_t QXcbCursor::createFontCursor(int cshape) + // Non-standard X11 cursors are created from bitmaps + cursor = createNonStandardCursor(cshape); + ++#if QT_CONFIG(xcb_xlib) && QT_CONFIG(library) + // Create a glpyh cursor if everything else failed + if (!cursor && cursorId) { + cursor = xcb_generate_id(conn); +@@ -596,6 +603,7 @@ xcb_cursor_t QXcbCursor::createFontCursor(int cshape) + cursorId, cursorId + 1, + 0xFFFF, 0xFFFF, 0xFFFF, 0, 0, 0); + } ++#endif + + if (cursor && cshape >= 0 && cshape < Qt::LastCursor && connection()->hasXFixes()) { + const char *name = cursorNames[cshape]; +-- +2.22.0 + diff --git a/src/Makefile.am b/src/Makefile.am index b7745b11..8e25d840 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -48,6 +48,18 @@ LIBBITCOIN_UTIL=libbitcoin_util.a LIBBITCOIN_CRYPTO=crypto/libbitcoin_crypto.a LIBBITCOINQT=qt/libkomodoqt.a LIBVERUS_CRYPTO=crypto/libverus_crypto.a +if ENABLE_SSE41 +LIBBITCOIN_CRYPTO_SSE41 = crypto/libbitcoin_crypto_sse41.a +LIBBITCOIN_CRYPTO += $(LIBBITCOIN_CRYPTO_SSE41) +endif +if ENABLE_AVX2 +LIBBITCOIN_CRYPTO_AVX2 = crypto/libbitcoin_crypto_avx2.a +LIBBITCOIN_CRYPTO += $(LIBBITCOIN_CRYPTO_AVX2) +endif +if ENABLE_SHANI +LIBBITCOIN_CRYPTO_SHANI = crypto/libbitcoin_crypto_shani.a +LIBBITCOIN_CRYPTO += $(LIBBITCOIN_CRYPTO_SHANI) +endif LIBVERUS_PORTABLE_CRYPTO=crypto/libverus_portable_crypto.a LIBSECP256K1=secp256k1/libsecp256k1.la LIBCRYPTOCONDITIONS=cryptoconditions/libcryptoconditions_core.la @@ -79,20 +91,20 @@ $(LIBCRYPTOCONDITIONS): $(wildcard cryptoconditions/src/*) $(wildcard cryptocond # 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 = \ - crypto/libbitcoin_crypto.a \ + $(LIBBITCOIN_CRYPTO) \ $(LIBVERUS_CRYPTO) \ $(LIBVERUS_PORTABLE_CRYPTO) \ - libbitcoin_util.a \ - libbitcoin_common.a \ - libbitcoin_server.a \ - libbitcoin_cli.a \ - libzcash.a + $(LIBBITCOIN_UTIL) \ + $(LIBBITCOIN_COMMON) \ + $(LIBBITCOIN_SERVER) \ + $(LIBBITCOIN_CLI) \ + $(LIBZCASH) if ENABLE_WALLET BITCOIN_INCLUDES += $(BDB_CPPFLAGS) -EXTRA_LIBRARIES += libbitcoin_wallet.a +EXTRA_LIBRARIES += $(LIBBITCOIN_WALLET) endif if ENABLE_ZMQ -EXTRA_LIBRARIES += libbitcoin_zmq.a +EXTRA_LIBRARIES += $(LIBBITCOIN_ZMQ) endif if BUILD_KOMODO_LIBS @@ -112,8 +124,8 @@ if BUILD_KOMODOD endif if BUILD_KOMODO_UTILS -# bin_PROGRAMS += komodo-cli komodo-tx - + bin_PROGRAMS += komodo-cli +# bin_PROGRAMS += komodo-cli komodo-tx endif LIBZCASH_H = \ @@ -164,6 +176,7 @@ BITCOIN_CORE_H = \ compat/sanity.h \ compressor.h \ consensus/consensus.h \ + consensus/merkle.h \ consensus/params.h \ consensus/upgrades.h \ consensus/validation.h \ @@ -410,10 +423,28 @@ crypto_libbitcoin_crypto_a_SOURCES = \ crypto/verus_hash.h \ crypto/verus_hash.cpp -if EXPERIMENTAL_ASM +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) +crypto_libbitcoin_crypto_sse41_a_CXXFLAGS += $(SSE41_CXXFLAGS) +crypto_libbitcoin_crypto_sse41_a_CPPFLAGS += -DENABLE_SSE41 +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) +crypto_libbitcoin_crypto_avx2_a_CXXFLAGS += $(AVX2_CXXFLAGS) +crypto_libbitcoin_crypto_avx2_a_CPPFLAGS += -DENABLE_AVX2 +crypto_libbitcoin_crypto_avx2_a_SOURCES = crypto/sha256_avx2.cpp + +crypto_libbitcoin_crypto_shani_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) +crypto_libbitcoin_crypto_shani_a_CPPFLAGS = $(AM_CPPFLAGS) +crypto_libbitcoin_crypto_shani_a_CXXFLAGS += $(SHANI_CXXFLAGS) +crypto_libbitcoin_crypto_shani_a_CPPFLAGS += -DENABLE_SHANI +crypto_libbitcoin_crypto_shani_a_SOURCES = crypto/sha256_shani.cpp + if ENABLE_MINING EQUIHASH_TROMP_SOURCES = \ pow/tromp/equi_miner.h \ @@ -450,6 +481,7 @@ libbitcoin_common_a_SOURCES = \ chainparams.cpp \ coins.cpp \ compressor.cpp \ + consensus/merkle.cpp \ consensus/upgrades.cpp \ core_read.cpp \ core_write.cpp \ @@ -549,7 +581,7 @@ komodod_LDADD += $(LIBBITCOIN_ZMQ) $(ZMQ_LIBS) endif if ENABLE_WALLET -komodod_LDADD += libbitcoin_wallet.a +komodod_LDADD += $(LIBBITCOIN_WALLET) endif komodod_LDADD += \ @@ -564,9 +596,10 @@ komodod_LDADD += \ $(LIBBITCOIN_CRYPTO) \ $(LIBVERUS_CRYPTO) \ $(LIBVERUS_PORTABLE_CRYPTO) \ + $(LIBSNARK) \ $(LIBZCASH_LIBS) -komodod_LDADD += libcc.a $(LIBSECP256K1) +komodod_LDADD += $(LIBSECP256K1) # bitcoin-cli binary # komodo_cli_SOURCES = bitcoin-cli.cpp @@ -716,10 +749,11 @@ if ENABLE_BIP70 $(AM_V_GEN) $(PROTOC) --cpp_out=$(@D) --proto_path=$(abspath $( // needed for VERSIONINFO +#include "clientversion.h" // holds the needed client version information + +#define VER_PRODUCTVERSION CLIENT_VERSION_MAJOR,CLIENT_VERSION_MINOR,CLIENT_VERSION_REVISION,CLIENT_VERSION_BUILD +#define VER_PRODUCTVERSION_STR STRINGIZE(CLIENT_VERSION_MAJOR) "." STRINGIZE(CLIENT_VERSION_MINOR) "." STRINGIZE(CLIENT_VERSION_REVISION) "." STRINGIZE(CLIENT_VERSION_BUILD) +#define VER_FILEVERSION VER_PRODUCTVERSION +#define VER_FILEVERSION_STR VER_PRODUCTVERSION_STR + +VS_VERSION_INFO VERSIONINFO +FILEVERSION VER_FILEVERSION +PRODUCTVERSION VER_PRODUCTVERSION +FILEOS VOS_NT_WINDOWS32 +FILETYPE VFT_APP +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904E4" // U.S. English - multilingual (hex) + BEGIN + VALUE "CompanyName", "Komodo" + VALUE "FileDescription", "komodo-cli (JSON-RPC client for Komodo)" + VALUE "FileVersion", VER_FILEVERSION_STR + VALUE "InternalName", "komodo-cli" + VALUE "LegalCopyright", COPYRIGHT_STR + VALUE "LegalTrademarks1", "Distributed under the MIT software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php." + VALUE "OriginalFilename", "komodo-cli.exe" + VALUE "ProductName", "komodo-cli" + VALUE "ProductVersion", VER_PRODUCTVERSION_STR + END + END + + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0, 1252 // language neutral - multilingual (decimal) + END +END diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp new file mode 100644 index 00000000..54497258 --- /dev/null +++ b/src/bitcoin-cli.cpp @@ -0,0 +1,404 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2013 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +/****************************************************************************** + * Copyright © 2014-2019 The SuperNET Developers. * + * * + * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * + * the top-level directory of this distribution for the individual copyright * + * holder information and the developer policies on copyright and licensing. * + * * + * Unless otherwise agreed in a custom licensing agreement, no part of the * + * SuperNET software, including this file may be copied, modified, propagated * + * or distributed except according to the terms contained in the LICENSE file * + * * + * Removal or modification of this copyright notice is prohibited. * + * * + ******************************************************************************/ + +#include "chainparamsbase.h" +#include "clientversion.h" +#include "rpc/client.h" +#include "rpc/protocol.h" +#include "util.h" +#include "utilstrencodings.h" + +#include +#include + +#include +#include +#include "support/events.h" +uint16_t BITCOIND_RPCPORT = 7771; +char ASSETCHAINS_SYMBOL[65]; + +#include + +using namespace std; + +static const int DEFAULT_HTTP_CLIENT_TIMEOUT=900; +static const int CONTINUE_EXECUTION=-1; + +std::string HelpMessageCli() +{ + std::string strUsage; + strUsage += HelpMessageGroup(_("Options:")); + strUsage += HelpMessageOpt("-?", _("This help message")); + strUsage += HelpMessageOpt("-conf=", strprintf(_("Specify configuration file (default: %s)"), "komodo.conf")); + strUsage += HelpMessageOpt("-datadir=", _("Specify data directory")); + strUsage += HelpMessageOpt("-testnet", _("Use the test network")); + strUsage += HelpMessageOpt("-regtest", _("Enter regression test mode, which uses a special chain in which blocks can be " + "solved instantly. This is intended for regression testing tools and app development.")); + strUsage += HelpMessageOpt("-rpcconnect=", strprintf(_("Send commands to node running on (default: %s)"), "127.0.0.1")); + strUsage += HelpMessageOpt("-rpcport=", strprintf(_("Connect to JSON-RPC on (default: %u or testnet: %u)"), 8232, 18232)); + strUsage += HelpMessageOpt("-rpcwait", _("Wait for RPC server to start")); + strUsage += HelpMessageOpt("-rpcuser=", _("Username for JSON-RPC connections")); + strUsage += HelpMessageOpt("-rpcpassword=", _("Password for JSON-RPC connections")); + strUsage += HelpMessageOpt("-rpcclienttimeout=", strprintf(_("Timeout in seconds during HTTP requests, or 0 for no timeout. (default: %d)"), DEFAULT_HTTP_CLIENT_TIMEOUT)); + strUsage += HelpMessageOpt("-stdin", _("Read extra arguments from standard input, one per line until EOF/Ctrl-D (recommended for sensitive information such as passphrases)")); + + return strUsage; +} + +////////////////////////////////////////////////////////////////////////////// +// +// Start +// + +// +// Exception thrown on connection error. This error is used to determine +// when to wait if -rpcwait is given. +// +class CConnectionFailed : public std::runtime_error +{ +public: + + explicit inline CConnectionFailed(const std::string& msg) : + std::runtime_error(msg) + {} + +}; + +// +// This function returns either one of EXIT_ codes when it's expected to stop the process or +// CONTINUE_EXECUTION when it's expected to continue further. +// +static int AppInitRPC(int argc, char* argv[]) +{ + static_assert(CONTINUE_EXECUTION != EXIT_FAILURE, + "CONTINUE_EXECUTION should be different from EXIT_FAILURE"); + static_assert(CONTINUE_EXECUTION != EXIT_SUCCESS, + "CONTINUE_EXECUTION should be different from EXIT_SUCCESS"); + // + // Parameters + // + ParseParameters(argc, argv); + std:string name; + name = GetArg("-ac_name",""); + if ( !name.empty() ) + strncpy(ASSETCHAINS_SYMBOL,name.c_str(),sizeof(ASSETCHAINS_SYMBOL)-1); + + if (argc<2 || mapArgs.count("-?") || mapArgs.count("-h") || mapArgs.count("-help") || mapArgs.count("-version")) { + std::string strUsage = _("Komodo RPC client version") + " " + FormatFullVersion() + "\n" + PrivacyInfo(); + if (!mapArgs.count("-version")) { + strUsage += "\n" + _("Usage:") + "\n" + + " komodo-cli [options] [params] " + _("Send command to Komodo") + "\n" + + " komodo-cli [options] help " + _("List commands") + "\n" + + " komodo-cli [options] help " + _("Get help for a command") + "\n"; + + strUsage += "\n" + HelpMessageCli(); + } else { + strUsage += LicenseInfo(); + } + + fprintf(stdout, "%s", strUsage.c_str()); + if (argc < 2) { + fprintf(stderr, "Error: too few parameters\n"); + return EXIT_FAILURE; + } + return EXIT_SUCCESS; + } + if (!boost::filesystem::is_directory(GetDataDir(false))) { + fprintf(stderr, "Error: Specified data directory \"%s\" does not exist.\n", mapArgs["-datadir"].c_str()); + return EXIT_FAILURE; + } + try { + ReadConfigFile(mapArgs, mapMultiArgs); + } catch (const std::exception& e) { + fprintf(stderr,"Error reading configuration file: %s\n", e.what()); + return EXIT_FAILURE; + } + // Check for -testnet or -regtest parameter (BaseParams() calls are only valid after this clause) + if (!SelectBaseParamsFromCommandLine()) { + fprintf(stderr, "Error: Invalid combination of -regtest and -testnet.\n"); + return EXIT_FAILURE; + } + if (GetBoolArg("-rpcssl", false)) + { + fprintf(stderr, "Error: SSL mode for RPC (-rpcssl) is no longer supported.\n"); + return EXIT_FAILURE; + } + return CONTINUE_EXECUTION; +} + + +/** Reply structure for request_done to fill in */ +struct HTTPReply +{ + HTTPReply(): status(0), error(-1) {} + + int status; + int error; + std::string body; +}; + +const char *http_errorstring(int code) +{ + switch(code) { +#if LIBEVENT_VERSION_NUMBER >= 0x02010300 + case EVREQ_HTTP_TIMEOUT: + return "timeout reached"; + case EVREQ_HTTP_EOF: + return "EOF reached"; + case EVREQ_HTTP_INVALID_HEADER: + return "error while reading header, or invalid header"; + case EVREQ_HTTP_BUFFER_ERROR: + return "error encountered while reading or writing"; + case EVREQ_HTTP_REQUEST_CANCEL: + return "request was canceled"; + case EVREQ_HTTP_DATA_TOO_LONG: + return "response body is larger than allowed"; +#endif + default: + return "unknown"; + } +} + +static void http_request_done(struct evhttp_request *req, void *ctx) +{ + HTTPReply *reply = static_cast(ctx); + + if (req == NULL) { + /* If req is NULL, it means an error occurred while connecting: the + * error code will have been passed to http_error_cb. + */ + reply->status = 0; + return; + } + + reply->status = evhttp_request_get_response_code(req); + + struct evbuffer *buf = evhttp_request_get_input_buffer(req); + if (buf) + { + size_t size = evbuffer_get_length(buf); + const char *data = (const char*)evbuffer_pullup(buf, size); + if (data) + reply->body = std::string(data, size); + evbuffer_drain(buf, size); + } +} + +#if LIBEVENT_VERSION_NUMBER >= 0x02010300 +static void http_error_cb(enum evhttp_request_error err, void *ctx) +{ + HTTPReply *reply = static_cast(ctx); + reply->error = err; +} +#endif + +UniValue CallRPC(const std::string& strMethod, const UniValue& params) +{ + std::string host = GetArg("-rpcconnect", "127.0.0.1"); + int port = GetArg("-rpcport", BaseParams().RPCPort()); + BITCOIND_RPCPORT = port; + // Obtain event base + raii_event_base base = obtain_event_base(); + + // Synchronously look up hostname + raii_evhttp_connection evcon = obtain_evhttp_connection_base(base.get(), host, port); + evhttp_connection_set_timeout(evcon.get(), GetArg("-rpcclienttimeout", DEFAULT_HTTP_CLIENT_TIMEOUT)); + + HTTPReply response; + raii_evhttp_request req = obtain_evhttp_request(http_request_done, (void*)&response); + if (req == NULL) + throw std::runtime_error("create http request failed"); +#if LIBEVENT_VERSION_NUMBER >= 0x02010300 + evhttp_request_set_error_cb(req.get(), http_error_cb); +#endif + + // Get credentials + std::string strRPCUserColonPass; + if (mapArgs["-rpcpassword"] == "") { + // Try fall back to cookie-based authentication if no password is provided + if (!GetAuthCookie(&strRPCUserColonPass)) { + throw std::runtime_error(strprintf( + _("Could not locate RPC credentials. No authentication cookie could be found,\n" + "and no rpcpassword is set in the configuration file (%s)."), + GetConfigFile().string().c_str())); + + } + } else { + strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]; + } + + struct evkeyvalq* output_headers = evhttp_request_get_output_headers(req.get()); + assert(output_headers); + evhttp_add_header(output_headers, "Host", host.c_str()); + evhttp_add_header(output_headers, "Connection", "close"); + evhttp_add_header(output_headers, "Authorization", (std::string("Basic ") + EncodeBase64(strRPCUserColonPass)).c_str()); + + // Attach request data + std::string strRequest = JSONRPCRequest(strMethod, params, 1); + struct evbuffer* output_buffer = evhttp_request_get_output_buffer(req.get()); + assert(output_buffer); + evbuffer_add(output_buffer, strRequest.data(), strRequest.size()); + + int r = evhttp_make_request(evcon.get(), req.get(), EVHTTP_REQ_POST, "/"); + req.release(); // ownership moved to evcon in above call + if (r != 0) { + throw CConnectionFailed("send http request failed"); + } + + event_base_dispatch(base.get()); + + if (response.status == 0) + throw CConnectionFailed(strprintf("couldn't connect to server: %s (code %d)\n(make sure server is running and you are connecting to the correct RPC port)", http_errorstring(response.error), response.error)); + else if (response.status == HTTP_UNAUTHORIZED) + throw std::runtime_error("incorrect rpcuser or rpcpassword (authorization failed)"); + else if (response.status >= 400 && response.status != HTTP_BAD_REQUEST && response.status != HTTP_NOT_FOUND && response.status != HTTP_INTERNAL_SERVER_ERROR) + throw std::runtime_error(strprintf("server returned HTTP error %d", response.status)); + else if (response.body.empty()) + throw std::runtime_error("no response from server"); + + // Parse reply + UniValue valReply(UniValue::VSTR); + if (!valReply.read(response.body)) + throw std::runtime_error("couldn't parse reply from server"); + const UniValue& reply = valReply.get_obj(); + if (reply.empty()) + throw std::runtime_error("expected reply to have result, error and id properties"); + + return reply; +} + +int CommandLineRPC(int argc, char *argv[]) +{ + std::string strPrint; + int nRet = 0; + try { + // Skip switches + while (argc > 1 && IsSwitchChar(argv[1][0])) { + argc--; + argv++; + } + std::vector args = std::vector(&argv[1], &argv[argc]); + if (GetBoolArg("-stdin", false)) { + // Read one arg per line from stdin and append + std::string line; + while (std::getline(std::cin,line)) + args.push_back(line); + } + if (args.size() < 1) + throw std::runtime_error("too few parameters (need at least command)"); + std::string strMethod = args[0]; + UniValue params = RPCConvertValues(strMethod, std::vector(args.begin()+1, args.end())); + + // Execute and handle connection failures with -rpcwait + const bool fWait = GetBoolArg("-rpcwait", false); + do { + try { + const UniValue reply = CallRPC(strMethod, params); + + // Parse reply + const UniValue& result = find_value(reply, "result"); + const UniValue& error = find_value(reply, "error"); + + if (!error.isNull()) { + // Error + int code = error["code"].get_int(); + if (fWait && code == RPC_IN_WARMUP) + throw CConnectionFailed("server in warmup"); + strPrint = "error: " + error.write(); + nRet = abs(code); + if (error.isObject()) + { + UniValue errCode = find_value(error, "code"); + UniValue errMsg = find_value(error, "message"); + strPrint = errCode.isNull() ? "" : "error code: "+errCode.getValStr()+"\n"; + + if (errMsg.isStr()) + strPrint += "error message:\n"+errMsg.get_str(); + } + } else { + // Result + if (result.isNull()) + strPrint = ""; + else if (result.isStr()) + strPrint = result.get_str(); + else + strPrint = result.write(2); + } + // Connection succeeded, no need to retry. + break; + } + catch (const CConnectionFailed&) { + if (fWait) + MilliSleep(1000); + else + throw; + } + } while (fWait); + } + catch (const boost::thread_interrupted&) { + throw; + } + catch (const std::exception& e) { + strPrint = std::string("error: ") + e.what(); + nRet = EXIT_FAILURE; + } + catch (...) { + PrintExceptionContinue(NULL, "CommandLineRPC()"); + throw; + } + + if (strPrint != "") { + fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str()); + } + return nRet; +} + +int main(int argc, char* argv[]) +{ + SetupEnvironment(); + if (!SetupNetworking()) { + fprintf(stderr, "Error: Initializing networking failed\n"); + return EXIT_FAILURE; + } + + try { + int ret = AppInitRPC(argc, argv); + if (ret != CONTINUE_EXECUTION) + return ret; + } + catch (const std::exception& e) { + PrintExceptionContinue(&e, "AppInitRPC()"); + return EXIT_FAILURE; + } catch (...) { + PrintExceptionContinue(NULL, "AppInitRPC()"); + return EXIT_FAILURE; + } + + int ret = EXIT_FAILURE; + try { + ret = CommandLineRPC(argc, argv); + } + catch (const std::exception& e) { + PrintExceptionContinue(&e, "CommandLineRPC()"); + } catch (...) { + PrintExceptionContinue(NULL, "CommandLineRPC()"); + } + return ret; +} diff --git a/src/cc/eval.cpp b/src/cc/eval.cpp index e9b4fa7a..c4ee629a 100644 --- a/src/cc/eval.cpp +++ b/src/cc/eval.cpp @@ -26,6 +26,7 @@ #include "chain.h" #include "core_io.h" #include "crosschain.h" +#include "consensus/merkle.h" bool CClib_Dispatch(const CC *cond,Eval *eval,std::vector paramsNull,const CTransaction &txTo,unsigned int nIn); char *CClib_name(); @@ -256,6 +257,7 @@ uint256 SafeCheckMerkleBranch(uint256 hash, const std::vector& vMerkleB uint256 GetMerkleRoot(const std::vector& vLeaves) { bool fMutated; - std::vector vMerkleTree; - return BuildMerkleTree(&fMutated, vLeaves, vMerkleTree); + /* std::vector vMerkleTree; + return BuildMerkleTree(&fMutated, vLeaves, vMerkleTree); */ + return ComputeMerkleRoot(vLeaves, &fMutated); } diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 72734093..543d75c1 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -30,6 +30,7 @@ #include #include "chainparamsseeds.h" +#include "consensus/merkle.h" static CBlock CreateGenesisBlock(const char* pszTimestamp, const CScript& genesisOutputScript, uint32_t nTime, const uint256& nNonce, const std::vector& nSolution, uint32_t nBits, int32_t nVersion, const CAmount& genesisReward) { @@ -54,7 +55,7 @@ static CBlock CreateGenesisBlock(const char* pszTimestamp, const CScript& genesi genesis.nVersion = nVersion; genesis.vtx.push_back(txNew); genesis.hashPrevBlock.SetNull(); - genesis.hashMerkleRoot = genesis.BuildMerkleTree(); + genesis.hashMerkleRoot = BlockMerkleRoot(genesis); return genesis; } @@ -163,7 +164,7 @@ class CMainParams : public CChainParams { txNew.vout[0].scriptPubKey = CScript() << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f") << OP_CHECKSIG; genesis.vtx.push_back(txNew); genesis.hashPrevBlock.SetNull(); - genesis.hashMerkleRoot = genesis.BuildMerkleTree(); + genesis.hashMerkleRoot = BlockMerkleRoot(genesis); genesis.nVersion = 1; genesis.nTime = 1231006505; genesis.nBits = KOMODO_MINDIFF_NBITS; @@ -550,14 +551,14 @@ void komodo_setactivation(int32_t height) pCurrentParams->consensus.vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight = height; pCurrentParams->consensus.vUpgrades[Consensus::UPGRADE_OVERWINTER].nActivationHeight = height; ASSETCHAINS_SAPLING = height; - fprintf(stderr,"SET SAPLING ACTIVATION height.%d\n",height); + LogPrintf("SET SAPLING ACTIVATION height.%d\n",height); } void *chainparams_commandline() { - fprintf(stderr,"chainparams_commandline called\n"); + LogPrintf("chainparams_commandline called\n"); CChainParams::CCheckpointData checkpointData; - //fprintf(stderr,">>>>>>>> port.%u\n",ASSETCHAINS_P2PPORT); + //LogPrintf(">>>>>>>> port.%u\n",ASSETCHAINS_P2PPORT); if ( ASSETCHAINS_SYMBOL[0] != 0 ) { if ( ASSETCHAINS_BLOCKTIME != 60 ) @@ -580,7 +581,7 @@ void *chainparams_commandline() pCurrentParams->pchMessageStart[1] = (ASSETCHAINS_MAGIC >> 8) & 0xff; pCurrentParams->pchMessageStart[2] = (ASSETCHAINS_MAGIC >> 16) & 0xff; pCurrentParams->pchMessageStart[3] = (ASSETCHAINS_MAGIC >> 24) & 0xff; - fprintf(stderr,">>>>>>>>>> %s: p2p.%u rpc.%u magic.%08x %u %u coins\n",ASSETCHAINS_SYMBOL,ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT,ASSETCHAINS_MAGIC,ASSETCHAINS_MAGIC,(uint32_t)ASSETCHAINS_SUPPLY); + LogPrintf(">>>>>>>>>> %s: p2p.%u rpc.%u magic.%08x %u %u coins\n",ASSETCHAINS_SYMBOL,ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT,ASSETCHAINS_MAGIC,ASSETCHAINS_MAGIC,(uint32_t)ASSETCHAINS_SUPPLY); if (ASSETCHAINS_ALGO == ASSETCHAINS_VERUSHASH) { // this is only good for 60 second blocks with an averaging window of 45. for other parameters, use: diff --git a/src/clientversion.h b/src/clientversion.h index 7a4c376d..5e73fa8f 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -33,7 +33,7 @@ #define CLIENT_VERSION_MAJOR 3 #define CLIENT_VERSION_MINOR 0 #define CLIENT_VERSION_REVISION 1 -#define CLIENT_VERSION_BUILD 1 +#define CLIENT_VERSION_BUILD 2 //! Set to true for release, false for prerelease or test build #define CLIENT_VERSION_IS_RELEASE true diff --git a/src/consensus/merkle.cpp b/src/consensus/merkle.cpp new file mode 100644 index 00000000..38dc0ab0 --- /dev/null +++ b/src/consensus/merkle.cpp @@ -0,0 +1,74 @@ +// Copyright (c) 2015-2019 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 + +/* 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. +*/ + + +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; + } + } + if (hashes.size() & 1) { + hashes.push_back(hashes.back()); + } + SHA256D64(hashes[0].begin(), hashes[0].begin(), hashes.size() / 2); + hashes.resize(hashes.size() / 2); + } + 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]->GetHash(); + leaves[s] = block.vtx[s].GetHash(); + } + return ComputeMerkleRoot(std::move(leaves), mutated); +} diff --git a/src/consensus/merkle.h b/src/consensus/merkle.h new file mode 100644 index 00000000..a1f91bb0 --- /dev/null +++ b/src/consensus/merkle.h @@ -0,0 +1,21 @@ +// Copyright (c) 2015-2019 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_CONSENSUS_MERKLE_H +#define BITCOIN_CONSENSUS_MERKLE_H + +#include + +#include +#include + +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); + +#endif // BITCOIN_CONSENSUS_MERKLE_H diff --git a/src/crypto/sha256.cpp b/src/crypto/sha256.cpp index 0718d2d2..a23b91e6 100644 --- a/src/crypto/sha256.cpp +++ b/src/crypto/sha256.cpp @@ -9,8 +9,10 @@ #include #include -#if defined(__x86_64__) || defined(__amd64__) -#if defined(EXPERIMENTAL_ASM) + + +#if defined(__x86_64__) || defined(__amd64__) || defined(__i386__) +#if defined(USE_ASM) #include namespace sha256_sse4 { @@ -19,6 +21,26 @@ void Transform(uint32_t* s, const unsigned char* chunk, size_t blocks); #endif #endif +namespace sha256d64_sse41 +{ +void Transform_4way(unsigned char* out, const unsigned char* in); +} + +namespace sha256d64_avx2 +{ +void Transform_8way(unsigned char* out, const unsigned char* in); +} + +namespace sha256d64_shani +{ +void Transform_2way(unsigned char* out, const unsigned char* in); +} + +namespace sha256_shani +{ +void Transform(uint32_t* s, const unsigned char* chunk, size_t blocks); +} + // Internal implementation code. namespace { @@ -33,9 +55,9 @@ uint32_t inline sigma0(uint32_t x) { return (x >> 7 | x << 25) ^ (x >> 18 | x << uint32_t inline sigma1(uint32_t x) { return (x >> 17 | x << 15) ^ (x >> 19 | x << 13) ^ (x >> 10); } /** One round of SHA-256. */ -void inline 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) +void inline 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 t1 = h + Sigma1(e) + Ch(e, f, g) + k + w; + 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; @@ -61,73 +83,73 @@ void Transform(uint32_t* s, const unsigned char* chunk, size_t 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; @@ -141,54 +163,490 @@ void Transform(uint32_t* s, const unsigned char* chunk, size_t blocks) } } +/** Specialized double sha256 for 64 byte inputs */ +void TransformD64(unsigned char* out, const unsigned char* 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 unsigned char*, size_t); +typedef void (*TransformD64Type)(unsigned char*, const unsigned char*); -bool SelfTest(TransformType tr) { - static const unsigned char in1[65] = {0, 0x80}; - static const unsigned char 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 +template +void TransformD64Wrapper(unsigned char* out, const unsigned char* in) +{ + uint32_t s[8]; + static const unsigned char 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 }; - 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; + unsigned char 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]); } TransformType Transform = sha256::Transform; +TransformD64Type TransformD64 = sha256::TransformD64; +TransformD64Type TransformD64_2way = nullptr; +TransformD64Type TransformD64_4way = nullptr; +TransformD64Type TransformD64_8way = nullptr; + +bool SelfTest() { + // Input state (equal to the initial SHA256 state) + static const uint32_t init[8] = { + 0x6a09e667ul, 0xbb67ae85ul, 0x3c6ef372ul, 0xa54ff53aul, 0x510e527ful, 0x9b05688cul, 0x1f83d9abul, 0x5be0cd19ul + }; + // Some random input data to test with + static const unsigned char data[641] = "-" // Intentionally not aligned + "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do " + "eiusmod tempor incididunt ut labore et dolore magna aliqua. Et m" + "olestie ac feugiat sed lectus vestibulum mattis ullamcorper. Mor" + "bi blandit cursus risus at ultrices mi tempus imperdiet nulla. N" + "unc congue nisi vita suscipit tellus mauris. Imperdiet proin fer" + "mentum leo vel orci. Massa tempor nec feugiat nisl pretium fusce" + " id velit. Telus in metus vulputate eu scelerisque felis. Mi tem" + "pus imperdiet nulla malesuada pellentesque. Tristique magna sit."; + // Expected output state for hashing the i*64 first input bytes above (excluding SHA256 padding). + static const uint32_t result[9][8] = { + {0x6a09e667ul, 0xbb67ae85ul, 0x3c6ef372ul, 0xa54ff53aul, 0x510e527ful, 0x9b05688cul, 0x1f83d9abul, 0x5be0cd19ul}, + {0x91f8ec6bul, 0x4da10fe3ul, 0x1c9c292cul, 0x45e18185ul, 0x435cc111ul, 0x3ca26f09ul, 0xeb954caeul, 0x402a7069ul}, + {0xcabea5acul, 0x374fb97cul, 0x182ad996ul, 0x7bd69cbful, 0x450ff900ul, 0xc1d2be8aul, 0x6a41d505ul, 0xe6212dc3ul}, + {0xbcff09d6ul, 0x3e76f36eul, 0x3ecb2501ul, 0x78866e97ul, 0xe1c1e2fdul, 0x32f4eafful, 0x8aa6c4e5ul, 0xdfc024bcul}, + {0xa08c5d94ul, 0x0a862f93ul, 0x6b7f2f40ul, 0x8f9fae76ul, 0x6d40439ful, 0x79dcee0cul, 0x3e39ff3aul, 0xdc3bdbb1ul}, + {0x216a0895ul, 0x9f1a3662ul, 0xe99946f9ul, 0x87ba4364ul, 0x0fb5db2cul, 0x12bed3d3ul, 0x6689c0c7ul, 0x292f1b04ul}, + {0xca3067f8ul, 0xbc8c2656ul, 0x37cb7e0dul, 0x9b6b8b0ful, 0x46dc380bul, 0xf1287f57ul, 0xc42e4b23ul, 0x3fefe94dul}, + {0x3e4c4039ul, 0xbb6fca8cul, 0x6f27d2f7ul, 0x301e44a4ul, 0x8352ba14ul, 0x5769ce37ul, 0x48a1155ful, 0xc0e1c4c6ul}, + {0xfe2fa9ddul, 0x69d0862bul, 0x1ae0db23ul, 0x471f9244ul, 0xf55c0145ul, 0xc30f9c3bul, 0x40a84ea0ul, 0x5b8a266cul}, + }; + // Expected output for each of the individual 8 64-byte messages under full double SHA256 (including padding). + static const unsigned char result_d64[256] = { + 0x09, 0x3a, 0xc4, 0xd0, 0x0f, 0xf7, 0x57, 0xe1, 0x72, 0x85, 0x79, 0x42, 0xfe, 0xe7, 0xe0, 0xa0, + 0xfc, 0x52, 0xd7, 0xdb, 0x07, 0x63, 0x45, 0xfb, 0x53, 0x14, 0x7d, 0x17, 0x22, 0x86, 0xf0, 0x52, + 0x48, 0xb6, 0x11, 0x9e, 0x6e, 0x48, 0x81, 0x6d, 0xcc, 0x57, 0x1f, 0xb2, 0x97, 0xa8, 0xd5, 0x25, + 0x9b, 0x82, 0xaa, 0x89, 0xe2, 0xfd, 0x2d, 0x56, 0xe8, 0x28, 0x83, 0x0b, 0xe2, 0xfa, 0x53, 0xb7, + 0xd6, 0x6b, 0x07, 0x85, 0x83, 0xb0, 0x10, 0xa2, 0xf5, 0x51, 0x3c, 0xf9, 0x60, 0x03, 0xab, 0x45, + 0x6c, 0x15, 0x6e, 0xef, 0xb5, 0xac, 0x3e, 0x6c, 0xdf, 0xb4, 0x92, 0x22, 0x2d, 0xce, 0xbf, 0x3e, + 0xe9, 0xe5, 0xf6, 0x29, 0x0e, 0x01, 0x4f, 0xd2, 0xd4, 0x45, 0x65, 0xb3, 0xbb, 0xf2, 0x4c, 0x16, + 0x37, 0x50, 0x3c, 0x6e, 0x49, 0x8c, 0x5a, 0x89, 0x2b, 0x1b, 0xab, 0xc4, 0x37, 0xd1, 0x46, 0xe9, + 0x3d, 0x0e, 0x85, 0xa2, 0x50, 0x73, 0xa1, 0x5e, 0x54, 0x37, 0xd7, 0x94, 0x17, 0x56, 0xc2, 0xd8, + 0xe5, 0x9f, 0xed, 0x4e, 0xae, 0x15, 0x42, 0x06, 0x0d, 0x74, 0x74, 0x5e, 0x24, 0x30, 0xce, 0xd1, + 0x9e, 0x50, 0xa3, 0x9a, 0xb8, 0xf0, 0x4a, 0x57, 0x69, 0x78, 0x67, 0x12, 0x84, 0x58, 0xbe, 0xc7, + 0x36, 0xaa, 0xee, 0x7c, 0x64, 0xa3, 0x76, 0xec, 0xff, 0x55, 0x41, 0x00, 0x2a, 0x44, 0x68, 0x4d, + 0xb6, 0x53, 0x9e, 0x1c, 0x95, 0xb7, 0xca, 0xdc, 0x7f, 0x7d, 0x74, 0x27, 0x5c, 0x8e, 0xa6, 0x84, + 0xb5, 0xac, 0x87, 0xa9, 0xf3, 0xff, 0x75, 0xf2, 0x34, 0xcd, 0x1a, 0x3b, 0x82, 0x2c, 0x2b, 0x4e, + 0x6a, 0x46, 0x30, 0xa6, 0x89, 0x86, 0x23, 0xac, 0xf8, 0xa5, 0x15, 0xe9, 0x0a, 0xaa, 0x1e, 0x9a, + 0xd7, 0x93, 0x6b, 0x28, 0xe4, 0x3b, 0xfd, 0x59, 0xc6, 0xed, 0x7c, 0x5f, 0xa5, 0x41, 0xcb, 0x51 + }; + + + // Test Transform() for 0 through 8 transformations. + for (size_t i = 0; i <= 8; ++i) { + uint32_t state[8]; + std::copy(init, init + 8, state); + Transform(state, data + 1, i); + if (!std::equal(state, state + 8, result[i])) return false; + } + + // Test TransformD64 + unsigned char out[32]; + TransformD64(out, data + 1); + if (!std::equal(out, out + 32, result_d64)) return false; + + // Test TransformD64_2way, if available. + if (TransformD64_2way) { + unsigned char out[64]; + TransformD64_2way(out, data + 1); + if (!std::equal(out, out + 64, result_d64)) return false; + } + + // Test TransformD64_4way, if available. + if (TransformD64_4way) { + unsigned char out[128]; + TransformD64_4way(out, data + 1); + if (!std::equal(out, out + 128, result_d64)) return false; + } + + // Test TransformD64_8way, if available. + if (TransformD64_8way) { + unsigned char out[256]; + TransformD64_8way(out, data + 1); + if (!std::equal(out, out + 256, result_d64)) return false; + } + + return true; +} + +/* TODO: move this to compat/cpuid.h */ +#if defined(USE_ASM) && (defined(__x86_64__) || defined(__amd64__) || defined(__i386__)) +/** 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 + +#if defined(__x86_64__) || defined(__amd64__) || defined(__i386__) +#define HAVE_GETCPUID + +#include + +// We can't use cpuid.h's __get_cpuid as it does not support subleafs. +void static inline GetCPUID(uint32_t leaf, uint32_t subleaf, uint32_t& a, uint32_t& b, uint32_t& c, uint32_t& d) +{ +#ifdef __GNUC__ + __cpuid_count(leaf, subleaf, a, b, c, d); +#else + __asm__ ("cpuid" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "0"(leaf), "2"(subleaf)); +#endif +} + +#endif // defined(__x86_64__) || defined(__amd64__) || defined(__i386__) } // namespace + std::string SHA256AutoDetect() { -#if defined(EXPERIMENTAL_ASM) && (defined(__x86_64__) || defined(__amd64__)) + std::string ret = "standard"; +#if defined(USE_ASM) && defined(HAVE_GETCPUID) + bool have_sse4 = false; + bool have_xsave = false; + bool have_avx = false; + bool have_avx2 = false; + bool have_shani = false; + bool enabled_avx = false; + + (void)AVXEnabled; + (void)have_sse4; + (void)have_avx; + (void)have_xsave; + (void)have_avx2; + (void)have_shani; + (void)enabled_avx; + uint32_t eax, ebx, ecx, edx; - if (__get_cpuid(1, &eax, &ebx, &ecx, &edx) && (ecx >> 19) & 1) { + GetCPUID(1, 0, eax, ebx, ecx, edx); + have_sse4 = (ecx >> 19) & 1; + have_xsave = (ecx >> 27) & 1; + have_avx = (ecx >> 28) & 1; + if (have_xsave && have_avx) { + enabled_avx = AVXEnabled(); + } + if (have_sse4) { + GetCPUID(7, 0, eax, ebx, ecx, edx); + have_avx2 = (ebx >> 5) & 1; + have_shani = (ebx >> 29) & 1; + } + +#if defined(ENABLE_SHANI) && !defined(BUILD_BITCOIN_INTERNAL) + if (have_shani) { + Transform = sha256_shani::Transform; + TransformD64 = TransformD64Wrapper; + TransformD64_2way = sha256d64_shani::Transform_2way; + ret = "shani(1way,2way)"; + have_sse4 = false; // Disable SSE4/AVX2; + have_avx2 = false; + } +#endif + + if (have_sse4) { +#if defined(__x86_64__) || defined(__amd64__) Transform = sha256_sse4::Transform; - assert(SelfTest(Transform)); - return "sse4"; + TransformD64 = TransformD64Wrapper; + ret = "sse4(1way)"; +#endif +#if defined(ENABLE_SSE41) && !defined(BUILD_BITCOIN_INTERNAL) + TransformD64_4way = sha256d64_sse41::Transform_4way; + ret += ",sse41(4way)"; +#endif + } + +#if defined(ENABLE_AVX2) && !defined(BUILD_BITCOIN_INTERNAL) + if (have_avx2 && have_avx && enabled_avx) { + TransformD64_8way = sha256d64_avx2::Transform_8way; + ret += ",avx2(8way)"; } +#endif #endif - assert(SelfTest(Transform)); - return "standard"; + assert(SelfTest()); + return ret; } ////// SHA-256 @@ -256,3 +714,37 @@ CSHA256& CSHA256::Reset() sha256::Initialize(s); return *this; } + +void SHA256D64(unsigned char* out, const unsigned char* 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; + } + } + if (TransformD64_2way) { + while (blocks >= 2) { + TransformD64_2way(out, in); + out += 64; + in += 128; + blocks -= 2; + } + } + while (blocks) { + TransformD64(out, in); + out += 32; + in += 64; + --blocks; + } +} diff --git a/src/crypto/sha256.h b/src/crypto/sha256.h index 24c9c666..d38125fe 100644 --- a/src/crypto/sha256.h +++ b/src/crypto/sha256.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2016 The Bitcoin Core developers +// Copyright (c) 2014-2018 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -34,4 +34,11 @@ class CSHA256 */ 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(unsigned char* output, const unsigned char* 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 00000000..624bdb42 --- /dev/null +++ b/src/crypto/sha256_avx2.cpp @@ -0,0 +1,328 @@ +// Copyright (c) 2017-2019 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifdef ENABLE_AVX2 + +#include +#include + +#include + +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 unsigned char* 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(unsigned char* 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(unsigned char* out, const unsigned char* 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_shani.cpp b/src/crypto/sha256_shani.cpp new file mode 100644 index 00000000..92f67710 --- /dev/null +++ b/src/crypto/sha256_shani.cpp @@ -0,0 +1,358 @@ +// Copyright (c) 2018-2019 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// +// Based on https://github.com/noloader/SHA-Intrinsics/blob/master/sha256-x86.c, +// Written and placed in public domain by Jeffrey Walton. +// Based on code from Intel, and by Sean Gulley for the miTLS project. + +#ifdef ENABLE_SHANI + +#include +#include + + + +namespace { + +const __m128i MASK = _mm_set_epi64x(0x0c0d0e0f08090a0bULL, 0x0405060700010203ULL); +const __m128i INIT0 = _mm_set_epi64x(0x6a09e667bb67ae85ull, 0x510e527f9b05688cull); +const __m128i INIT1 = _mm_set_epi64x(0x3c6ef372a54ff53aull, 0x1f83d9ab5be0cd19ull); + +void inline __attribute__((always_inline)) QuadRound(__m128i& state0, __m128i& state1, uint64_t k1, uint64_t k0) +{ + const __m128i msg = _mm_set_epi64x(k1, k0); + state1 = _mm_sha256rnds2_epu32(state1, state0, msg); + state0 = _mm_sha256rnds2_epu32(state0, state1, _mm_shuffle_epi32(msg, 0x0e)); +} + +void inline __attribute__((always_inline)) QuadRound(__m128i& state0, __m128i& state1, __m128i m, uint64_t k1, uint64_t k0) +{ + const __m128i msg = _mm_add_epi32(m, _mm_set_epi64x(k1, k0)); + state1 = _mm_sha256rnds2_epu32(state1, state0, msg); + state0 = _mm_sha256rnds2_epu32(state0, state1, _mm_shuffle_epi32(msg, 0x0e)); +} + +void inline __attribute__((always_inline)) ShiftMessageA(__m128i& m0, __m128i m1) +{ + m0 = _mm_sha256msg1_epu32(m0, m1); +} + +void inline __attribute__((always_inline)) ShiftMessageC(__m128i& m0, __m128i m1, __m128i& m2) +{ + m2 = _mm_sha256msg2_epu32(_mm_add_epi32(m2, _mm_alignr_epi8(m1, m0, 4)), m1); +} + +void inline __attribute__((always_inline)) ShiftMessageB(__m128i& m0, __m128i m1, __m128i& m2) +{ + ShiftMessageC(m0, m1, m2); + ShiftMessageA(m0, m1); +} + +void inline __attribute__((always_inline)) Shuffle(__m128i& s0, __m128i& s1) +{ + const __m128i t1 = _mm_shuffle_epi32(s0, 0xB1); + const __m128i t2 = _mm_shuffle_epi32(s1, 0x1B); + s0 = _mm_alignr_epi8(t1, t2, 0x08); + s1 = _mm_blend_epi16(t2, t1, 0xF0); +} + +void inline __attribute__((always_inline)) Unshuffle(__m128i& s0, __m128i& s1) +{ + const __m128i t1 = _mm_shuffle_epi32(s0, 0x1B); + const __m128i t2 = _mm_shuffle_epi32(s1, 0xB1); + s0 = _mm_blend_epi16(t1, t2, 0xF0); + s1 = _mm_alignr_epi8(t2, t1, 0x08); +} + +__m128i inline __attribute__((always_inline)) Load(const unsigned char* in) +{ + return _mm_shuffle_epi8(_mm_loadu_si128((const __m128i*)in), MASK); +} + +void inline __attribute__((always_inline)) Save(unsigned char* out, __m128i s) +{ + _mm_storeu_si128((__m128i*)out, _mm_shuffle_epi8(s, MASK)); +} +} + +namespace sha256_shani { +void Transform(uint32_t* s, const unsigned char* chunk, size_t blocks) +{ + __m128i m0, m1, m2, m3, s0, s1, so0, so1; + + /* Load state */ + s0 = _mm_loadu_si128((const __m128i*)s); + s1 = _mm_loadu_si128((const __m128i*)(s + 4)); + Shuffle(s0, s1); + + while (blocks--) { + /* Remember old state */ + so0 = s0; + so1 = s1; + + /* Load data and transform */ + m0 = Load(chunk); + QuadRound(s0, s1, m0, 0xe9b5dba5b5c0fbcfull, 0x71374491428a2f98ull); + m1 = Load(chunk + 16); + QuadRound(s0, s1, m1, 0xab1c5ed5923f82a4ull, 0x59f111f13956c25bull); + ShiftMessageA(m0, m1); + m2 = Load(chunk + 32); + QuadRound(s0, s1, m2, 0x550c7dc3243185beull, 0x12835b01d807aa98ull); + ShiftMessageA(m1, m2); + m3 = Load(chunk + 48); + QuadRound(s0, s1, m3, 0xc19bf1749bdc06a7ull, 0x80deb1fe72be5d74ull); + ShiftMessageB(m2, m3, m0); + QuadRound(s0, s1, m0, 0x240ca1cc0fc19dc6ull, 0xefbe4786E49b69c1ull); + ShiftMessageB(m3, m0, m1); + QuadRound(s0, s1, m1, 0x76f988da5cb0a9dcull, 0x4a7484aa2de92c6full); + ShiftMessageB(m0, m1, m2); + QuadRound(s0, s1, m2, 0xbf597fc7b00327c8ull, 0xa831c66d983e5152ull); + ShiftMessageB(m1, m2, m3); + QuadRound(s0, s1, m3, 0x1429296706ca6351ull, 0xd5a79147c6e00bf3ull); + ShiftMessageB(m2, m3, m0); + QuadRound(s0, s1, m0, 0x53380d134d2c6dfcull, 0x2e1b213827b70a85ull); + ShiftMessageB(m3, m0, m1); + QuadRound(s0, s1, m1, 0x92722c8581c2c92eull, 0x766a0abb650a7354ull); + ShiftMessageB(m0, m1, m2); + QuadRound(s0, s1, m2, 0xc76c51A3c24b8b70ull, 0xa81a664ba2bfe8a1ull); + ShiftMessageB(m1, m2, m3); + QuadRound(s0, s1, m3, 0x106aa070f40e3585ull, 0xd6990624d192e819ull); + ShiftMessageB(m2, m3, m0); + QuadRound(s0, s1, m0, 0x34b0bcb52748774cull, 0x1e376c0819a4c116ull); + ShiftMessageB(m3, m0, m1); + QuadRound(s0, s1, m1, 0x682e6ff35b9cca4full, 0x4ed8aa4a391c0cb3ull); + ShiftMessageC(m0, m1, m2); + QuadRound(s0, s1, m2, 0x8cc7020884c87814ull, 0x78a5636f748f82eeull); + ShiftMessageC(m1, m2, m3); + QuadRound(s0, s1, m3, 0xc67178f2bef9A3f7ull, 0xa4506ceb90befffaull); + + /* Combine with old state */ + s0 = _mm_add_epi32(s0, so0); + s1 = _mm_add_epi32(s1, so1); + + /* Advance */ + chunk += 64; + } + + Unshuffle(s0, s1); + _mm_storeu_si128((__m128i*)s, s0); + _mm_storeu_si128((__m128i*)(s + 4), s1); +} +} + +namespace sha256d64_shani { + +void Transform_2way(unsigned char* out, const unsigned char* in) +{ + __m128i am0, am1, am2, am3, as0, as1, aso0, aso1; + __m128i bm0, bm1, bm2, bm3, bs0, bs1, bso0, bso1; + + /* Transform 1 */ + bs0 = as0 = INIT0; + bs1 = as1 = INIT1; + am0 = Load(in); + bm0 = Load(in + 64); + QuadRound(as0, as1, am0, 0xe9b5dba5b5c0fbcfull, 0x71374491428a2f98ull); + QuadRound(bs0, bs1, bm0, 0xe9b5dba5b5c0fbcfull, 0x71374491428a2f98ull); + am1 = Load(in + 16); + bm1 = Load(in + 80); + QuadRound(as0, as1, am1, 0xab1c5ed5923f82a4ull, 0x59f111f13956c25bull); + QuadRound(bs0, bs1, bm1, 0xab1c5ed5923f82a4ull, 0x59f111f13956c25bull); + ShiftMessageA(am0, am1); + ShiftMessageA(bm0, bm1); + am2 = Load(in + 32); + bm2 = Load(in + 96); + QuadRound(as0, as1, am2, 0x550c7dc3243185beull, 0x12835b01d807aa98ull); + QuadRound(bs0, bs1, bm2, 0x550c7dc3243185beull, 0x12835b01d807aa98ull); + ShiftMessageA(am1, am2); + ShiftMessageA(bm1, bm2); + am3 = Load(in + 48); + bm3 = Load(in + 112); + QuadRound(as0, as1, am3, 0xc19bf1749bdc06a7ull, 0x80deb1fe72be5d74ull); + QuadRound(bs0, bs1, bm3, 0xc19bf1749bdc06a7ull, 0x80deb1fe72be5d74ull); + ShiftMessageB(am2, am3, am0); + ShiftMessageB(bm2, bm3, bm0); + QuadRound(as0, as1, am0, 0x240ca1cc0fc19dc6ull, 0xefbe4786E49b69c1ull); + QuadRound(bs0, bs1, bm0, 0x240ca1cc0fc19dc6ull, 0xefbe4786E49b69c1ull); + ShiftMessageB(am3, am0, am1); + ShiftMessageB(bm3, bm0, bm1); + QuadRound(as0, as1, am1, 0x76f988da5cb0a9dcull, 0x4a7484aa2de92c6full); + QuadRound(bs0, bs1, bm1, 0x76f988da5cb0a9dcull, 0x4a7484aa2de92c6full); + ShiftMessageB(am0, am1, am2); + ShiftMessageB(bm0, bm1, bm2); + QuadRound(as0, as1, am2, 0xbf597fc7b00327c8ull, 0xa831c66d983e5152ull); + QuadRound(bs0, bs1, bm2, 0xbf597fc7b00327c8ull, 0xa831c66d983e5152ull); + ShiftMessageB(am1, am2, am3); + ShiftMessageB(bm1, bm2, bm3); + QuadRound(as0, as1, am3, 0x1429296706ca6351ull, 0xd5a79147c6e00bf3ull); + QuadRound(bs0, bs1, bm3, 0x1429296706ca6351ull, 0xd5a79147c6e00bf3ull); + ShiftMessageB(am2, am3, am0); + ShiftMessageB(bm2, bm3, bm0); + QuadRound(as0, as1, am0, 0x53380d134d2c6dfcull, 0x2e1b213827b70a85ull); + QuadRound(bs0, bs1, bm0, 0x53380d134d2c6dfcull, 0x2e1b213827b70a85ull); + ShiftMessageB(am3, am0, am1); + ShiftMessageB(bm3, bm0, bm1); + QuadRound(as0, as1, am1, 0x92722c8581c2c92eull, 0x766a0abb650a7354ull); + QuadRound(bs0, bs1, bm1, 0x92722c8581c2c92eull, 0x766a0abb650a7354ull); + ShiftMessageB(am0, am1, am2); + ShiftMessageB(bm0, bm1, bm2); + QuadRound(as0, as1, am2, 0xc76c51A3c24b8b70ull, 0xa81a664ba2bfe8a1ull); + QuadRound(bs0, bs1, bm2, 0xc76c51A3c24b8b70ull, 0xa81a664ba2bfe8a1ull); + ShiftMessageB(am1, am2, am3); + ShiftMessageB(bm1, bm2, bm3); + QuadRound(as0, as1, am3, 0x106aa070f40e3585ull, 0xd6990624d192e819ull); + QuadRound(bs0, bs1, bm3, 0x106aa070f40e3585ull, 0xd6990624d192e819ull); + ShiftMessageB(am2, am3, am0); + ShiftMessageB(bm2, bm3, bm0); + QuadRound(as0, as1, am0, 0x34b0bcb52748774cull, 0x1e376c0819a4c116ull); + QuadRound(bs0, bs1, bm0, 0x34b0bcb52748774cull, 0x1e376c0819a4c116ull); + ShiftMessageB(am3, am0, am1); + ShiftMessageB(bm3, bm0, bm1); + QuadRound(as0, as1, am1, 0x682e6ff35b9cca4full, 0x4ed8aa4a391c0cb3ull); + QuadRound(bs0, bs1, bm1, 0x682e6ff35b9cca4full, 0x4ed8aa4a391c0cb3ull); + ShiftMessageC(am0, am1, am2); + ShiftMessageC(bm0, bm1, bm2); + QuadRound(as0, as1, am2, 0x8cc7020884c87814ull, 0x78a5636f748f82eeull); + QuadRound(bs0, bs1, bm2, 0x8cc7020884c87814ull, 0x78a5636f748f82eeull); + ShiftMessageC(am1, am2, am3); + ShiftMessageC(bm1, bm2, bm3); + QuadRound(as0, as1, am3, 0xc67178f2bef9A3f7ull, 0xa4506ceb90befffaull); + QuadRound(bs0, bs1, bm3, 0xc67178f2bef9A3f7ull, 0xa4506ceb90befffaull); + as0 = _mm_add_epi32(as0, INIT0); + bs0 = _mm_add_epi32(bs0, INIT0); + as1 = _mm_add_epi32(as1, INIT1); + bs1 = _mm_add_epi32(bs1, INIT1); + + /* Transform 2 */ + aso0 = as0; + bso0 = bs0; + aso1 = as1; + bso1 = bs1; + QuadRound(as0, as1, 0xe9b5dba5b5c0fbcfull, 0x71374491c28a2f98ull); + QuadRound(bs0, bs1, 0xe9b5dba5b5c0fbcfull, 0x71374491c28a2f98ull); + QuadRound(as0, as1, 0xab1c5ed5923f82a4ull, 0x59f111f13956c25bull); + QuadRound(bs0, bs1, 0xab1c5ed5923f82a4ull, 0x59f111f13956c25bull); + QuadRound(as0, as1, 0x550c7dc3243185beull, 0x12835b01d807aa98ull); + QuadRound(bs0, bs1, 0x550c7dc3243185beull, 0x12835b01d807aa98ull); + QuadRound(as0, as1, 0xc19bf3749bdc06a7ull, 0x80deb1fe72be5d74ull); + QuadRound(bs0, bs1, 0xc19bf3749bdc06a7ull, 0x80deb1fe72be5d74ull); + QuadRound(as0, as1, 0x240cf2540fe1edc6ull, 0xf0fe4786649b69c1ull); + QuadRound(bs0, bs1, 0x240cf2540fe1edc6ull, 0xf0fe4786649b69c1ull); + QuadRound(as0, as1, 0x16f988fa61b9411eull, 0x6cc984be4fe9346full); + QuadRound(bs0, bs1, 0x16f988fa61b9411eull, 0x6cc984be4fe9346full); + QuadRound(as0, as1, 0xb9d99ec7b019fc65ull, 0xa88e5a6df2c65152ull); + QuadRound(bs0, bs1, 0xb9d99ec7b019fc65ull, 0xa88e5a6df2c65152ull); + QuadRound(as0, as1, 0xc7353eb0fdb1232bull, 0xe70eeaa09a1231c3ull); + QuadRound(bs0, bs1, 0xc7353eb0fdb1232bull, 0xe70eeaa09a1231c3ull); + QuadRound(as0, as1, 0xdc1eeefd5a0f118full, 0xcb976d5f3069bad5ull); + QuadRound(bs0, bs1, 0xdc1eeefd5a0f118full, 0xcb976d5f3069bad5ull); + QuadRound(as0, as1, 0xe15d5b1658f4ca9dull, 0xde0b7a040a35b689ull); + QuadRound(bs0, bs1, 0xe15d5b1658f4ca9dull, 0xde0b7a040a35b689ull); + QuadRound(as0, as1, 0x6fab9537a507ea32ull, 0x37088980007f3e86ull); + QuadRound(bs0, bs1, 0x6fab9537a507ea32ull, 0x37088980007f3e86ull); + QuadRound(as0, as1, 0xc0bbbe37cdaa3b6dull, 0x0d8cd6f117406110ull); + QuadRound(bs0, bs1, 0xc0bbbe37cdaa3b6dull, 0x0d8cd6f117406110ull); + QuadRound(as0, as1, 0x6fd15ca70b02e931ull, 0xdb48a36383613bdaull); + QuadRound(bs0, bs1, 0x6fd15ca70b02e931ull, 0xdb48a36383613bdaull); + QuadRound(as0, as1, 0x6d4378906ed41a95ull, 0x31338431521afacaull); + QuadRound(bs0, bs1, 0x6d4378906ed41a95ull, 0x31338431521afacaull); + QuadRound(as0, as1, 0x532fb63cb5c9a0e6ull, 0x9eccabbdc39c91f2ull); + QuadRound(bs0, bs1, 0x532fb63cb5c9a0e6ull, 0x9eccabbdc39c91f2ull); + QuadRound(as0, as1, 0x4c191d76a4954b68ull, 0x07237ea3d2c741c6ull); + QuadRound(bs0, bs1, 0x4c191d76a4954b68ull, 0x07237ea3d2c741c6ull); + as0 = _mm_add_epi32(as0, aso0); + bs0 = _mm_add_epi32(bs0, bso0); + as1 = _mm_add_epi32(as1, aso1); + bs1 = _mm_add_epi32(bs1, bso1); + + /* Extract hash */ + Unshuffle(as0, as1); + Unshuffle(bs0, bs1); + am0 = as0; + bm0 = bs0; + am1 = as1; + bm1 = bs1; + + /* Transform 3 */ + bs0 = as0 = INIT0; + bs1 = as1 = INIT1; + QuadRound(as0, as1, am0, 0xe9b5dba5B5c0fbcfull, 0x71374491428a2f98ull); + QuadRound(bs0, bs1, bm0, 0xe9b5dba5B5c0fbcfull, 0x71374491428a2f98ull); + QuadRound(as0, as1, am1, 0xab1c5ed5923f82a4ull, 0x59f111f13956c25bull); + QuadRound(bs0, bs1, bm1, 0xab1c5ed5923f82a4ull, 0x59f111f13956c25bull); + ShiftMessageA(am0, am1); + ShiftMessageA(bm0, bm1); + bm2 = am2 = _mm_set_epi64x(0x0ull, 0x80000000ull); + QuadRound(as0, as1, 0x550c7dc3243185beull, 0x12835b015807aa98ull); + QuadRound(bs0, bs1, 0x550c7dc3243185beull, 0x12835b015807aa98ull); + ShiftMessageA(am1, am2); + ShiftMessageA(bm1, bm2); + bm3 = am3 = _mm_set_epi64x(0x10000000000ull, 0x0ull); + QuadRound(as0, as1, 0xc19bf2749bdc06a7ull, 0x80deb1fe72be5d74ull); + QuadRound(bs0, bs1, 0xc19bf2749bdc06a7ull, 0x80deb1fe72be5d74ull); + ShiftMessageB(am2, am3, am0); + ShiftMessageB(bm2, bm3, bm0); + QuadRound(as0, as1, am0, 0x240ca1cc0fc19dc6ull, 0xefbe4786e49b69c1ull); + QuadRound(bs0, bs1, bm0, 0x240ca1cc0fc19dc6ull, 0xefbe4786e49b69c1ull); + ShiftMessageB(am3, am0, am1); + ShiftMessageB(bm3, bm0, bm1); + QuadRound(as0, as1, am1, 0x76f988da5cb0a9dcull, 0x4a7484aa2de92c6full); + QuadRound(bs0, bs1, bm1, 0x76f988da5cb0a9dcull, 0x4a7484aa2de92c6full); + ShiftMessageB(am0, am1, am2); + ShiftMessageB(bm0, bm1, bm2); + QuadRound(as0, as1, am2, 0xbf597fc7b00327c8ull, 0xa831c66d983e5152ull); + QuadRound(bs0, bs1, bm2, 0xbf597fc7b00327c8ull, 0xa831c66d983e5152ull); + ShiftMessageB(am1, am2, am3); + ShiftMessageB(bm1, bm2, bm3); + QuadRound(as0, as1, am3, 0x1429296706ca6351ull, 0xd5a79147c6e00bf3ull); + QuadRound(bs0, bs1, bm3, 0x1429296706ca6351ull, 0xd5a79147c6e00bf3ull); + ShiftMessageB(am2, am3, am0); + ShiftMessageB(bm2, bm3, bm0); + QuadRound(as0, as1, am0, 0x53380d134d2c6dfcull, 0x2e1b213827b70a85ull); + QuadRound(bs0, bs1, bm0, 0x53380d134d2c6dfcull, 0x2e1b213827b70a85ull); + ShiftMessageB(am3, am0, am1); + ShiftMessageB(bm3, bm0, bm1); + QuadRound(as0, as1, am1, 0x92722c8581c2c92eull, 0x766a0abb650a7354ull); + QuadRound(bs0, bs1, bm1, 0x92722c8581c2c92eull, 0x766a0abb650a7354ull); + ShiftMessageB(am0, am1, am2); + ShiftMessageB(bm0, bm1, bm2); + QuadRound(as0, as1, am2, 0xc76c51a3c24b8b70ull, 0xa81a664ba2bfe8A1ull); + QuadRound(bs0, bs1, bm2, 0xc76c51a3c24b8b70ull, 0xa81a664ba2bfe8A1ull); + ShiftMessageB(am1, am2, am3); + ShiftMessageB(bm1, bm2, bm3); + QuadRound(as0, as1, am3, 0x106aa070f40e3585ull, 0xd6990624d192e819ull); + QuadRound(bs0, bs1, bm3, 0x106aa070f40e3585ull, 0xd6990624d192e819ull); + ShiftMessageB(am2, am3, am0); + ShiftMessageB(bm2, bm3, bm0); + QuadRound(as0, as1, am0, 0x34b0bcb52748774cull, 0x1e376c0819a4c116ull); + QuadRound(bs0, bs1, bm0, 0x34b0bcb52748774cull, 0x1e376c0819a4c116ull); + ShiftMessageB(am3, am0, am1); + ShiftMessageB(bm3, bm0, bm1); + QuadRound(as0, as1, am1, 0x682e6ff35b9cca4full, 0x4ed8aa4a391c0cb3ull); + QuadRound(bs0, bs1, bm1, 0x682e6ff35b9cca4full, 0x4ed8aa4a391c0cb3ull); + ShiftMessageC(am0, am1, am2); + ShiftMessageC(bm0, bm1, bm2); + QuadRound(as0, as1, am2, 0x8cc7020884c87814ull, 0x78a5636f748f82eeull); + QuadRound(bs0, bs1, bm2, 0x8cc7020884c87814ull, 0x78a5636f748f82eeull); + ShiftMessageC(am1, am2, am3); + ShiftMessageC(bm1, bm2, bm3); + QuadRound(as0, as1, am3, 0xc67178f2bef9a3f7ull, 0xa4506ceb90befffaull); + QuadRound(bs0, bs1, bm3, 0xc67178f2bef9a3f7ull, 0xa4506ceb90befffaull); + as0 = _mm_add_epi32(as0, INIT0); + bs0 = _mm_add_epi32(bs0, INIT0); + as1 = _mm_add_epi32(as1, INIT1); + bs1 = _mm_add_epi32(bs1, INIT1); + + /* Extract hash into out */ + Unshuffle(as0, as1); + Unshuffle(bs0, bs1); + Save(out, as0); + Save(out + 16, as1); + Save(out + 32, bs0); + Save(out + 48, bs1); +} + +} + +#endif diff --git a/src/crypto/sha256_sse41.cpp b/src/crypto/sha256_sse41.cpp new file mode 100644 index 00000000..4eaf7d7b --- /dev/null +++ b/src/crypto/sha256_sse41.cpp @@ -0,0 +1,320 @@ +// Copyright (c) 2018-2019 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifdef ENABLE_SSE41 + +#include +#include + +#include + +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 unsigned char* 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(unsigned char* 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(unsigned char* out, const unsigned char* 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/init.cpp b/src/init.cpp index 69d6a0df..8a635865 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -505,7 +505,7 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-logtimestamps", strprintf(_("Prepend debug output with timestamp (default: %u)"), 1)); if (showDebug) { - strUsage += HelpMessageOpt("-limitfreerelay=", strprintf("Continuously rate-limit free transactions to *1000 bytes per minute (default: %u)", 15)); + strUsage += HelpMessageOpt("-limitfreerelay=", strprintf("Continuously rate-limit free transactions to *1000 bytes per minute (default: %u)", DEFAULT_LIMITFREERELAY)); strUsage += HelpMessageOpt("-relaypriority", strprintf("Require high priority for relaying free or low-fee transactions (default: %u)", 0)); strUsage += HelpMessageOpt("-maxsigcachesize=", strprintf("Limit size of signature cache to entries (default: %u)", 50000)); strUsage += HelpMessageOpt("-maxtipage=", strprintf("Maximum tip age in seconds to consider node in initial block download (default: %u)", DEFAULT_MAX_TIP_AGE)); @@ -1935,7 +1935,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) nLocalServices |= NODE_ADDRINDEX; if ( GetBoolArg("-spentindex", DEFAULT_SPENTINDEX) != 0 ) nLocalServices |= NODE_SPENTINDEX; - fprintf(stderr,"nLocalServices %llx %d, %d\n",(long long)nLocalServices,GetBoolArg("-addressindex", DEFAULT_ADDRESSINDEX),GetBoolArg("-spentindex", DEFAULT_SPENTINDEX)); + LogPrintf("nLocalServices %llx %d, %d\n",(long long)nLocalServices,GetBoolArg("-addressindex", DEFAULT_ADDRESSINDEX),GetBoolArg("-spentindex", DEFAULT_SPENTINDEX)); } // ********************************************************* Step 10: import blocks diff --git a/src/komodo_bitcoind.h b/src/komodo_bitcoind.h index cae0acc0..d518a693 100644 --- a/src/komodo_bitcoind.h +++ b/src/komodo_bitcoind.h @@ -906,20 +906,6 @@ int32_t komodo_blockload(CBlock& block,CBlockIndex *pindex) return(0); } -int32_t komodo_blockload(CBlock& block,CBlockIndex *pindex,CBufferedFile *buffered_file) -{ - block.SetNull(); - - if (pindex->GetBlockPos().IsNull()) return(-1); - - buffered_file->SetAnyPos(pindex->GetBlockPos().nPos); - - // Read block - *buffered_file >> block; - - return(0); -} - uint32_t komodo_chainactive_timestamp() { if ( chainActive.LastTip() != 0 ) @@ -1000,17 +986,6 @@ void komodo_index2pubkey33(uint8_t *pubkey33,CBlockIndex *pindex,int32_t height) } } -void komodo_index2pubkey33(uint8_t *pubkey33,CBlockIndex *pindex,int32_t height,CBufferedFile *buffered_file) -{ - int32_t num,i; CBlock block; - memset(pubkey33,0,33); - if ( pindex != 0 ) - { - if ( komodo_blockload(block,pindex,buffered_file) == 0 ) - komodo_block2pubkey33(pubkey33,&block); - } -} - /*int8_t komodo_minerid(int32_t height,uint8_t *destpubkey33) { int32_t num,i,numnotaries; CBlockIndex *pindex; uint32_t timestamp=0; uint8_t pubkey33[33],pubkeys[64][33]; diff --git a/src/komodo_ccdata.h b/src/komodo_ccdata.h index 8deeec6b..545b27af 100644 --- a/src/komodo_ccdata.h +++ b/src/komodo_ccdata.h @@ -20,6 +20,7 @@ struct komodo_ccdata *CC_data; int32_t CC_firstheight; uint256 BuildMerkleTree(bool* fMutated, const std::vector leaves, std::vector &vMerkleTree); +uint256 ComputeMerkleRoot(std::vector hashes, bool* mutated ); uint256 komodo_calcMoM(int32_t height,int32_t MoMdepth) { @@ -35,7 +36,8 @@ uint256 komodo_calcMoM(int32_t height,int32_t MoMdepth) else return(zero); } - return BuildMerkleTree(&fMutated, leaves, tree); + // return BuildMerkleTree(&fMutated, leaves, tree); + return ComputeMerkleRoot(leaves, &fMutated); } struct komodo_ccdata_entry *komodo_allMoMs(int32_t *nump,uint256 *MoMoMp,int32_t kmdstarti,int32_t kmdendi) @@ -68,7 +70,8 @@ struct komodo_ccdata_entry *komodo_allMoMs(int32_t *nump,uint256 *MoMoMp,int32_t { for (i=0; i> 3) * 2 + 1],uint8_t hash[256 >> 3],uint8_t *src,int32_t len) { - struct sha256_vstate md; + /* struct sha256_vstate md; sha256_vinit(&md); sha256_vprocess(&md,src,len); - sha256_vdone(&md,hash); + sha256_vdone(&md,hash); */ + + // we will use CSHA256 class instead of above implementation, + // in case if daemon compiled with USE_ASM enabled it will use + // hardware (SSE4) implementation, otherwise standart + + CSHA256().Write((const unsigned char *)src, len).Finalize(hash); } bits256 bits256_doublesha256(char *deprecated,uint8_t *data,int32_t datalen) @@ -2476,6 +2482,7 @@ struct komodo_state *komodo_stateptr(char *symbol,char *dest) return(komodo_stateptrget(symbol)); } +/* void komodo_prefetch(FILE *fp) { long fsize,fpos; int32_t incr = 16*1024*1024; @@ -2489,9 +2496,12 @@ void komodo_prefetch(FILE *fp) { rewind(fp); while ( fread(ignore,1,incr,fp) == incr ) // prefetch - LogPrintf("."); + { + // LogPrintf("."); + } free(ignore); } } fseek(fp,fpos,SEEK_SET); } +*/ \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 44e0fd41..0aa4c72f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -20,6 +20,7 @@ #include "main.h" #include "sodium.h" +#include "consensus/merkle.h" #include "addrman.h" #include "alert.h" @@ -1264,9 +1265,9 @@ bool ContextualCheckTransaction(int32_t slowflag,const CBlock *block, CBlockInde if (IsExpiredTx(tx, nHeight)) { // Don't increase banscore if the transaction only just expired int expiredDosLevel = IsExpiredTx(tx, nHeight - 1) ? (dosLevel > 10 ? dosLevel : 10) : 0; - string strHex = EncodeHexTx(tx); + //string strHex = EncodeHexTx(tx); //LogPrintf( "transaction exipred.%s\n",strHex.c_str()); - return state.DoS(expiredDosLevel, error("ContextualCheckTransaction(): transaction %s is expired, expiry block %i vs current block %i\n txhex.%s",tx.GetHash().ToString(),tx.nExpiryHeight,nHeight,strHex), REJECT_INVALID, "tx-overwinter-expired"); + return state.DoS(expiredDosLevel, error("ContextualCheckTransaction(): transaction %s is expired, expiry block %i vs current block %i\n",tx.GetHash().ToString(),tx.nExpiryHeight,nHeight), REJECT_INVALID, "tx-overwinter-expired"); } } @@ -2039,7 +2040,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa nLastTime = nNow; // -limitfreerelay unit is thousand-bytes-per-minute // At default rate it would take over a month to fill 1GB - if (dFreeCount >= GetArg("-limitfreerelay", 15)*10*1000) + if (dFreeCount >= GetArg("-limitfreerelay", DEFAULT_LIMITFREERELAY)*10*1000) { LogPrintf("accept failure.7\n"); //return state.DoS(0, error("AcceptToMemoryPool: free transaction rejected by rate limiter"), REJECT_INSUFFICIENTFEE, "rate limited free transaction"); @@ -5214,7 +5215,7 @@ bool CheckBlock(int32_t *futureblockp,int32_t height,CBlockIndex *pindex,const C // Check the merkle root. if (fCheckMerkleRoot) { bool mutated; - uint256 hashMerkleRoot2 = block.BuildMerkleTree(&mutated); + uint256 hashMerkleRoot2 = BlockMerkleRoot(block,&mutated); if (block.hashMerkleRoot != hashMerkleRoot2) return state.DoS(100, error("CheckBlock: hashMerkleRoot mismatch"), REJECT_INVALID, "bad-txnmrklroot", true); @@ -6048,7 +6049,7 @@ bool CheckDiskSpace(uint64_t nAdditionalBytes) FILE* OpenDiskFile(const CDiskBlockPos &pos, const char *prefix, bool fReadOnly) { - static int32_t didinit[256]; + //static int32_t didinit[256]; if (pos.IsNull()) return NULL; boost::filesystem::path path = GetBlockPosFilename(pos, prefix); @@ -6060,11 +6061,13 @@ FILE* OpenDiskFile(const CDiskBlockPos &pos, const char *prefix, bool fReadOnly) LogPrintf("Unable to open file %s\n", path.string()); return NULL; } + /* if ( pos.nFile < sizeof(didinit)/sizeof(*didinit) && didinit[pos.nFile] == 0 && strcmp(prefix,(char *)"blk") == 0 ) { komodo_prefetch(file); didinit[pos.nFile] = 1; } + */ if (pos.nPos) { if (fseek(file, pos.nPos, SEEK_SET)) { LogPrintf("Unable to seek to position %u of %s\n", pos.nPos, path.string()); @@ -6232,13 +6235,26 @@ bool static LoadBlockIndexDB() } } //LogPrintf("load blockindexDB %u\n",(uint32_t)time(NULL)); + + int64_t count = 0; int reportDone = 0; + uiInterface.ShowProgress(_("Checking all blk files are present..."), 0, false); for (std::set::iterator it = setBlkDataFiles.begin(); it != setBlkDataFiles.end(); it++) { CDiskBlockPos pos(*it, 0); if (CAutoFile(OpenBlockFile(pos, true), SER_DISK, CLIENT_VERSION).IsNull()) { return false; } + count++; + int percentageDone = (int)(count * 100.0 / setBlkDataFiles.size() + 0.5); + if (reportDone < percentageDone/10) { + // report max. every 10% step + LogPrintf("[%d%%]...", percentageDone); /* Continued */ + uiInterface.ShowProgress(_("Checking all blk files are present..."), percentageDone, false); + reportDone = percentageDone/10; + } } + LogPrintf("[%s].\n", "DONE"); + uiInterface.ShowProgress("", 100, false); // Check whether we have ever pruned block & undo files pblocktree->ReadFlag("prunedblockfiles", fHavePruned); diff --git a/src/main.h b/src/main.h index d633d19d..f08340ad 100644 --- a/src/main.h +++ b/src/main.h @@ -4,7 +4,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. /****************************************************************************** - * Copyright © 2014-2019 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -118,6 +118,7 @@ static const unsigned int DATABASE_WRITE_INTERVAL = 60 * 60; static const unsigned int DATABASE_FLUSH_INTERVAL = 24 * 60 * 60; /** Maximum length of reject messages. */ static const unsigned int MAX_REJECT_MESSAGE_LENGTH = 111; +static const unsigned int DEFAULT_LIMITFREERELAY = 15; static const int64_t DEFAULT_MAX_TIP_AGE = 24 * 60 * 60; //static const bool DEFAULT_ADDRESSINDEX = false; diff --git a/src/miner.cpp b/src/miner.cpp index 103651c5..cec94fcc 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -28,6 +28,7 @@ #include "chainparams.h" #include "importcoin.h" #include "consensus/consensus.h" +#include "consensus/merkle.h" #include "consensus/upgrades.h" #include "consensus/validation.h" #ifdef ENABLE_MINING @@ -997,7 +998,7 @@ void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& assert(txCoinbase.vin[0].scriptSig.size() <= 100); pblock->vtx[0] = txCoinbase; - pblock->hashMerkleRoot = pblock->BuildMerkleTree(); + pblock->hashMerkleRoot = BlockMerkleRoot(*pblock); } #ifdef ENABLE_WALLET diff --git a/src/pubkey.h b/src/pubkey.h index 6d66a225..7a0a6dfe 100644 --- a/src/pubkey.h +++ b/src/pubkey.h @@ -5,7 +5,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. /****************************************************************************** - * Copyright © 2014-2019 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -48,10 +48,10 @@ class CPubKey /** * secp256k1: */ - static const unsigned int PUBLIC_KEY_SIZE = 65; - static const unsigned int COMPRESSED_PUBLIC_KEY_SIZE = 33; - static const unsigned int SIGNATURE_SIZE = 72; - static const unsigned int COMPACT_SIGNATURE_SIZE = 65; + static constexpr unsigned int PUBLIC_KEY_SIZE = 65; + static constexpr unsigned int COMPRESSED_PUBLIC_KEY_SIZE = 33; + static constexpr unsigned int SIGNATURE_SIZE = 72; + static constexpr unsigned int COMPACT_SIGNATURE_SIZE = 65; /** * see www.keylength.com * script supports up to 75 for single byte push @@ -85,6 +85,11 @@ class CPubKey } public: + + bool static ValidSize(const std::vector &vch) { + return vch.size() > 0 && GetLen(vch[0]) == vch.size(); + } + //! Construct an invalid public key. CPubKey() { diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp index 4b66ca01..1ec795d0 100644 --- a/src/qt/optionsmodel.cpp +++ b/src/qt/optionsmodel.cpp @@ -24,7 +24,10 @@ #include "wallet/walletdb.h" #endif +#ifdef ENABLE_BIP70 #include +#endif +#include #include #include @@ -430,6 +433,7 @@ void OptionsModel::setDisplayUnit(const QVariant &value) } } +#ifdef ENABLE_BIP70 bool OptionsModel::getProxySettings(QNetworkProxy& proxy) const { // Directly query current base proxy, because @@ -447,6 +451,7 @@ bool OptionsModel::getProxySettings(QNetworkProxy& proxy) const return false; } +#endif void OptionsModel::setRestartRequired(bool fRequired) { diff --git a/src/qt/optionsmodel.h b/src/qt/optionsmodel.h index 339eae2f..af675dd6 100644 --- a/src/qt/optionsmodel.h +++ b/src/qt/optionsmodel.h @@ -10,7 +10,9 @@ #include QT_BEGIN_NAMESPACE +#ifdef ENABLE_BIP70 class QNetworkProxy; +#endif QT_END_NAMESPACE /** Interface from Qt to configuration data structure for Komodo client. @@ -64,7 +66,9 @@ class OptionsModel : public QAbstractListModel bool getMinimizeOnClose() const { return fMinimizeOnClose; } int getDisplayUnit() const { return nDisplayUnit; } QString getThirdPartyTxUrls() const { return strThirdPartyTxUrls; } + #ifdef ENABLE_BIP70 bool getProxySettings(QNetworkProxy& proxy) const; + #endif bool getCoinControlFeatures() const { return fCoinControlFeatures; } const QString& getOverriddenByCommandLine() { return strOverriddenByCommandLine; } diff --git a/src/script/script.cpp b/src/script/script.cpp index 1b6bb1eb..c93f9206 100644 --- a/src/script/script.cpp +++ b/src/script/script.cpp @@ -4,7 +4,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. /****************************************************************************** - * Copyright © 2014-2019 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -174,11 +174,6 @@ const char* GetOpName(opcodetype opcode) case OP_INVALIDOPCODE : return "OP_INVALIDOPCODE"; - // Note: - // The template matching params OP_SMALLDATA/etc are defined in opcodetype enum - // as kind of implementation hack, they are *NOT* real opcodes. If found in real - // Script, just let the default: case deal with them. - default: return "OP_UNKNOWN"; } @@ -419,6 +414,23 @@ bool CScript::IsCoinImport() const return false; } +bool CScript::IsPushOnly(const_iterator pc) const +{ + while (pc < end()) + { + opcodetype opcode; + if (!GetOp(pc, opcode)) + return false; + // Note that IsPushOnly() *does* consider OP_RESERVED to be a + // push-type opcode, however execution of OP_RESERVED fails, so + // it's not relevant to P2SH/BIP62 as the scriptSig would fail prior to + // the P2SH special validation code being executed. + if (opcode > OP_16) + return false; + } + return true; +} + // A witness program is any valid CScript that consists of a 1-byte push opcode // followed by a data push between 2 and 40 bytes. bool CScript::IsWitnessProgram(int& version, std::vector& program) const diff --git a/src/script/script.h b/src/script/script.h index 9617666e..417c3969 100644 --- a/src/script/script.h +++ b/src/script/script.h @@ -4,7 +4,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. /****************************************************************************** - * Copyright © 2014-2019 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -195,10 +195,6 @@ enum opcodetype // template matching params OP_SMALLDATA = 0xf9, - OP_SMALLINTEGER = 0xfa, - OP_PUBKEYS = 0xfb, - OP_PUBKEYHASH = 0xfd, - OP_PUBKEY = 0xfe, OP_CRYPTOCONDITION = 0xfc, OP_INVALIDOPCODE = 0xff, @@ -605,6 +601,7 @@ class CScript : public CScriptBase bool IsWitnessProgram(int& version, std::vector& program) const; /** Called by IsStandardTx and P2SH/BIP62 VerifyScript (which makes it consensus-critical). */ + bool IsPushOnly(const_iterator pc) const; bool IsPushOnly() const; /** if the front of the script has check lock time verify. this is a fairly simple check. diff --git a/src/script/standard.cpp b/src/script/standard.cpp index 0e41455c..4cb3dd84 100644 --- a/src/script/standard.cpp +++ b/src/script/standard.cpp @@ -4,7 +4,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. /****************************************************************************** - * Copyright © 2014-2019 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -155,26 +155,57 @@ const char* GetTxnOutputType(txnouttype t) /** * Return public keys or hashes from scriptPubKey, for 'standard' transaction types. */ -bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, vector >& vSolutionsRet) +static bool MatchPayToPubkey(const CScript& script, valtype& pubkey) { - // Templates - static multimap mTemplates; - if (mTemplates.empty()) - { - // Standard tx, sender provides pubkey, receiver adds signature - mTemplates.insert(make_pair(TX_PUBKEY, CScript() << OP_PUBKEY << OP_CHECKSIG)); + if (script.size() == CPubKey::PUBLIC_KEY_SIZE + 2 && script[0] == CPubKey::PUBLIC_KEY_SIZE && script.back() == OP_CHECKSIG) { + pubkey = valtype(script.begin() + 1, script.begin() + CPubKey::PUBLIC_KEY_SIZE + 1); + return CPubKey::ValidSize(pubkey); + } + if (script.size() == CPubKey::COMPRESSED_PUBLIC_KEY_SIZE + 2 && script[0] == CPubKey::COMPRESSED_PUBLIC_KEY_SIZE && script.back() == OP_CHECKSIG) { + pubkey = valtype(script.begin() + 1, script.begin() + CPubKey::COMPRESSED_PUBLIC_KEY_SIZE + 1); + return CPubKey::ValidSize(pubkey); + } + return false; +} - // Bitcoin address tx, sender provides hash of pubkey, receiver provides signature and pubkey - mTemplates.insert(make_pair(TX_PUBKEYHASH, CScript() << OP_DUP << OP_HASH160 << OP_PUBKEYHASH << OP_EQUALVERIFY << OP_CHECKSIG)); +static bool MatchPayToPubkeyHash(const CScript& script, valtype& pubkeyhash) + { + if (script.size() == 25 && script[0] == OP_DUP && script[1] == OP_HASH160 && script[2] == 20 && script[23] == OP_EQUALVERIFY && script[24] == OP_CHECKSIG) { + pubkeyhash = valtype(script.begin () + 3, script.begin() + 23); + return true; + } + return false; +} - // Sender provides N pubkeys, receivers provides M signatures - mTemplates.insert(make_pair(TX_MULTISIG, CScript() << OP_SMALLINTEGER << OP_PUBKEYS << OP_SMALLINTEGER << OP_CHECKMULTISIG)); +/** Test for "small positive integer" script opcodes - OP_1 through OP_16. */ +static constexpr bool IsSmallInteger(opcodetype opcode) +{ + return opcode >= OP_1 && opcode <= OP_16; +} - // Empty, provably prunable, data-carrying output - if (GetBoolArg("-datacarrier", true)) - mTemplates.insert(make_pair(TX_NULL_DATA, CScript() << OP_RETURN << OP_SMALLDATA)); - mTemplates.insert(make_pair(TX_NULL_DATA, CScript() << OP_RETURN)); +static bool MatchMultisig(const CScript& script, unsigned int& required, std::vector& pubkeys) +{ + opcodetype opcode; + valtype data; + CScript::const_iterator it = script.begin(); + if (script.size() < 1 || script.back() != OP_CHECKMULTISIG) return false; + + if (!script.GetOp(it, opcode, data) || !IsSmallInteger(opcode)) return false; + required = CScript::DecodeOP_N(opcode); + while (script.GetOp(it, opcode, data) && CPubKey::ValidSize(data)) { + pubkeys.emplace_back(std::move(data)); } + + if (!IsSmallInteger(opcode)) return false; + unsigned int keys = CScript::DecodeOP_N(opcode); + if (pubkeys.size() != keys || keys < required) return false; + return (it + 1 == script.end()); +} + + +bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, std::vector >& vSolutionsRet) +{ + vSolutionsRet.clear(); // Shortcut for pay-to-script-hash, which are more constrained than the other types: // it is always OP_HASH160 20 [20 byte hash] OP_EQUAL @@ -186,6 +217,16 @@ bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, vector= 1 && scriptPubKey[0] == OP_RETURN && scriptPubKey.IsPushOnly(scriptPubKey.begin()+1)) { + typeRet = TX_NULL_DATA; + return true; + } + if (IsCryptoConditionsEnabled()) { // Shortcut for pay-to-crypto-condition CScript ccSubScript = CScript(); @@ -220,93 +261,27 @@ bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, vector vch1, vch2; - - // Compare - CScript::const_iterator pc1 = script1.begin(); - CScript::const_iterator pc2 = script2.begin(); - while (true) - { - if (pc1 == script1.end() && pc2 == script2.end()) - { - // Found a match - typeRet = tplate.first; - if (typeRet == TX_MULTISIG) - { - // Additional checks for TX_MULTISIG: - unsigned char m = vSolutionsRet.front()[0]; - unsigned char n = vSolutionsRet.back()[0]; - if (m < 1 || n < 1 || m > n || vSolutionsRet.size()-2 != n) - return false; - } + std::vector data; + if (MatchPayToPubkey(scriptPubKey, data)) { + typeRet = TX_PUBKEY; + vSolutionsRet.push_back(std::move(data)); return true; } - if (!script1.GetOp(pc1, opcode1, vch1)) - break; - if (!script2.GetOp(pc2, opcode2, vch2)) - break; - // Template matching opcodes: - if (opcode2 == OP_PUBKEYS) - { - while (vch1.size() >= 33 && vch1.size() <= 65) - { - vSolutionsRet.push_back(vch1); - if (!script1.GetOp(pc1, opcode1, vch1)) - break; - } - if (!script2.GetOp(pc2, opcode2, vch2)) - break; - // Normal situation is to fall through - // to other if/else statements + if (MatchPayToPubkeyHash(scriptPubKey, data)) { + typeRet = TX_PUBKEYHASH; + vSolutionsRet.push_back(std::move(data)); + return true; } - if (opcode2 == OP_PUBKEY) - { - if (vch1.size() < 33 || vch1.size() > 65) - break; - vSolutionsRet.push_back(vch1); - } - else if (opcode2 == OP_PUBKEYHASH) - { - if (vch1.size() != sizeof(uint160)) - break; - vSolutionsRet.push_back(vch1); - } - else if (opcode2 == OP_SMALLINTEGER) - { // Single-byte small integer pushed onto vSolutions - if (opcode1 == OP_0 || - (opcode1 >= OP_1 && opcode1 <= OP_16)) - { - char n = (char)CScript::DecodeOP_N(opcode1); - vSolutionsRet.push_back(valtype(1, n)); - } - else - break; - } - else if (opcode2 == OP_SMALLDATA) - { - // small pushdata, <= nMaxDatacarrierBytes - if (vch1.size() > nMaxDatacarrierBytes) - { - //LogPrintf("size.%d > nMaxDatacarrier.%d\n",(int32_t)vch1.size(),(int32_t)nMaxDatacarrierBytes); - break; - } - } - else if (opcode1 != opcode2 || vch1 != vch2) - { - // Others must match exactly - break; - } - } + unsigned int required; + std::vector> keys; + if (MatchMultisig(scriptPubKey, required, keys)) { + typeRet = TX_MULTISIG; + vSolutionsRet.push_back({static_cast(required)}); // safe as required is in range 1..16 + vSolutionsRet.insert(vSolutionsRet.end(), keys.begin(), keys.end()); + vSolutionsRet.push_back({static_cast(keys.size())}); // safe as size is in range 1..16 + return true; } vSolutionsRet.clear(); diff --git a/src/script/standard.h b/src/script/standard.h index fe748b32..fbe0f3a1 100644 --- a/src/script/standard.h +++ b/src/script/standard.h @@ -4,7 +4,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. /****************************************************************************** - * Copyright © 2014-2019 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -36,7 +36,7 @@ class CScriptID : public uint160 { public: CScriptID() : uint160() {} - CScriptID(const CScript& in); + explicit CScriptID(const CScript& in); CScriptID(const uint160& in) : uint160(in) {} }; diff --git a/src/streams.h b/src/streams.h index 6170e584..e8958900 100644 --- a/src/streams.h +++ b/src/streams.h @@ -1,10 +1,10 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2013 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// file COPYING or https://www.opensource.org/licenses/mit-license.php . /****************************************************************************** - * Copyright © 2014-2019 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -546,19 +546,20 @@ class CBufferedFile readNow = nAvail; if (readNow == 0) return false; - size_t read = fread((void*)&vchBuf[pos], 1, readNow, src); - if (read == 0) { + size_t nBytes = fread((void*)&vchBuf[pos], 1, readNow, src); + if (nBytes == 0) { throw std::ios_base::failure(feof(src) ? "CBufferedFile::Fill: end of file" : "CBufferedFile::Fill: fread failed"); - } else { - nSrcPos += read; - return true; } + nSrcPos += nBytes; + return true; } public: CBufferedFile(FILE *fileIn, uint64_t nBufSize, uint64_t nRewindIn, int nTypeIn, int nVersionIn) : nType(nTypeIn), nVersion(nVersionIn), nSrcPos(0), nReadPos(0), nReadLimit((uint64_t)(-1)), nRewind(nRewindIn), vchBuf(nBufSize, 0) { + if (nRewindIn >= nBufSize) + throw std::ios_base::failure("Rewind limit must be less than buffer size"); src = fileIn; } @@ -593,8 +594,6 @@ class CBufferedFile if (nSize + nReadPos > nReadLimit) throw std::ios_base::failure("Read attempted past buffer limit"); - if (nSize + nRewind > vchBuf.size()) - throw std::ios_base::failure("Read larger than buffer size"); while (nSize > 0) { if (nReadPos == nSrcPos) Fill(); @@ -618,22 +617,18 @@ class CBufferedFile // rewind to a given reading position bool SetPos(uint64_t nPos) { - nReadPos = nPos; - if (nReadPos + nRewind < nSrcPos) { - nReadPos = nSrcPos - nRewind; + size_t bufsize = vchBuf.size(); + if (nPos + bufsize < nSrcPos) { + // rewinding too far, rewind as far as possible + nReadPos = nSrcPos - bufsize; return false; - } else if (nReadPos > nSrcPos) { + } + if (nPos > nSrcPos) { + // can't go this far forward, go as far as possible nReadPos = nSrcPos; return false; - } else { - return true; } - } - - // set any reading position - bool SetAnyPos(uint64_t nPos) { nReadPos = nPos; - nSrcPos = (unsigned int)(vchBuf.size()); return true; } diff --git a/src/test-komodo/test_buffered_file.cpp b/src/test-komodo/test_buffered_file.cpp new file mode 100644 index 00000000..7d5cfee1 --- /dev/null +++ b/src/test-komodo/test_buffered_file.cpp @@ -0,0 +1,449 @@ +#include +#include "testutils.h" +#include "streams.h" +#include +#include "clientversion.h" + +namespace TestBufferedFile { + + class TestBufferedFile : public ::testing::Test {}; + + TEST(TestBufferedFile, streams_buffered_file) + { + FILE* file = fopen("streams_test_tmp", "w+b"); + // The value at each offset is the offset. + for (uint8_t j = 0; j < 40; ++j) { + fwrite(&j, 1, 1, file); + } + rewind(file); + + // The buffer size (second arg) must be greater than the rewind + // amount (third arg). + + try { + CBufferedFile bfbad(file, 25, 25, 222, 333); + ASSERT_TRUE(false); + } catch (const std::exception& e) { + ASSERT_TRUE(strstr(e.what(), + "Rewind limit must be less than buffer size") != nullptr); + } + + // The buffer is 25 bytes, allow rewinding 10 bytes. + CBufferedFile bf(file, 25, 10, 222, 333); + ASSERT_TRUE(!bf.eof()); + + // These two members have no functional effect. + ASSERT_EQ(bf.GetType(), 222); + ASSERT_EQ(bf.GetVersion(), 333); + + uint8_t i; + bf >> i; // bf.nSrcPos = 15, bf.nReadPos = 1 + ASSERT_EQ(i, 0); + bf >> i; // bf.nSrcPos = 15, bf.nReadPos = 2 + ASSERT_EQ(i, 1); + + // After reading bytes 0 and 1, we're positioned at 2. + ASSERT_EQ(bf.GetPos(), 2); + + // Rewind to offset 0, ok (within the 10 byte window). + ASSERT_TRUE(bf.SetPos(0)); // bf.nSrcPos = 15, bf.nReadPos = 0 + bf >> i; // bf.nSrcPos = 15, bf.nReadPos = 1 + ASSERT_EQ(i, 0); + + // We can go forward to where we've been, but beyond may fail. + ASSERT_TRUE(bf.SetPos(2)); // bf.nSrcPos = 15, bf.nReadPos = 2 + bf >> i; // bf.nSrcPos = 15, bf.nReadPos = 3 + ASSERT_EQ(i, 2); + + // If you know the maximum number of bytes that should be + // read to deserialize the variable, you can limit the read + // extent. The current file offset is 3, so the following + // SetLimit() allows zero bytes to be read. + ASSERT_TRUE(bf.SetLimit(3)); + try { + bf >> i; + ASSERT_TRUE(false); + } catch (const std::exception& e) { + ASSERT_TRUE(strstr(e.what(), + "Read attempted past buffer limit") != nullptr); + } + // The default argument removes the limit completely. + ASSERT_TRUE(bf.SetLimit()); + // The read position should still be at 3 (no change). + ASSERT_EQ(bf.GetPos(), 3); + + // Read from current offset, 3, forward until position 10. + for (uint8_t j = 3; j < 10; ++j) { + bf >> i; + ASSERT_EQ(i, j); + } + ASSERT_EQ(bf.GetPos(), 10); + + // We're guaranteed (just barely) to be able to rewind to zero. + ASSERT_TRUE(bf.SetPos(0)); + ASSERT_EQ(bf.GetPos(), 0); + bf >> i; + ASSERT_EQ(i, 0); + + // We can set the position forward again up to the farthest + // into the stream we've been, but no farther. (Attempting + // to go farther may succeed, but it's not guaranteed.) + ASSERT_TRUE(bf.SetPos(10)); + bf >> i; + ASSERT_EQ(i, 10); + ASSERT_EQ(bf.GetPos(), 11); + + // Now it's only guaranteed that we can rewind to offset 1 + // (current read position, 11, minus rewind amount, 10). + ASSERT_TRUE(bf.SetPos(1)); + ASSERT_EQ(bf.GetPos(), 1); + bf >> i; + ASSERT_EQ(i, 1); + + // We can stream into large variables, even larger than + // the buffer size. + ASSERT_TRUE(bf.SetPos(11)); + { + uint8_t a[40 - 11]; + bf >> FLATDATA(a); + for (uint8_t j = 0; j < sizeof(a); ++j) { + ASSERT_EQ(a[j], 11 + j); + } + } + ASSERT_EQ(bf.GetPos(), 40); + + // We've read the entire file, the next read should throw. + try { + bf >> i; + ASSERT_TRUE(false); + } catch (const std::exception& e) { + ASSERT_TRUE(strstr(e.what(), + "CBufferedFile::Fill: end of file") != nullptr); + } + // Attempting to read beyond the end sets the EOF indicator. + ASSERT_TRUE(bf.eof()); + + // Still at offset 40, we can go back 10, to 30. + ASSERT_EQ(bf.GetPos(), 40); + ASSERT_TRUE(bf.SetPos(30)); + bf >> i; + ASSERT_EQ(i, 30); + ASSERT_EQ(bf.GetPos(), 31); + + // We're too far to rewind to position zero. + ASSERT_TRUE(!bf.SetPos(0)); + // But we should now be positioned at least as far back as allowed + // by the rewind window (relative to our farthest read position, 40). + ASSERT_TRUE(bf.GetPos() <= 30); + + // We can explicitly close the file, or the destructor will do it. + bf.fclose(); + + boost::filesystem::remove("streams_test_tmp"); + } + + TEST(TestBufferedFile, streams_buffered_file_rand) + { + + // Make this test deterministic. + seed_insecure_rand(true); + + for (int rep = 0; rep < 500; ++rep) { + FILE* file = fopen("streams_test_tmp", "w+b"); + size_t fileSize = GetRandInt(256); + for (uint8_t i = 0; i < fileSize; ++i) { + fwrite(&i, 1, 1, file); + } + rewind(file); + + size_t bufSize = GetRandInt(300) + 1; + size_t rewindSize = GetRandInt(bufSize); + CBufferedFile bf(file, bufSize, rewindSize, 222, 333); + size_t currentPos = 0; + size_t maxPos = 0; + for (int step = 0; step < 100; ++step) { + if (currentPos >= fileSize) + break; + + // We haven't read to the end of the file yet. + ASSERT_TRUE(!bf.eof()); + ASSERT_EQ(bf.GetPos(), currentPos); + + // Pretend the file consists of a series of objects of varying + // sizes; the boundaries of the objects can interact arbitrarily + // with the CBufferFile's internal buffer. These first three + // cases simulate objects of various sizes (1, 2, 5 bytes). + switch (GetRandInt(5)) { + case 0: { + uint8_t a[1]; + if (currentPos + 1 > fileSize) + continue; + bf.SetLimit(currentPos + 1); + bf >> FLATDATA(a); + for (uint8_t i = 0; i < 1; ++i) { + ASSERT_EQ(a[i], currentPos); + currentPos++; + } + break; + } + case 1: { + uint8_t a[2]; + if (currentPos + 2 > fileSize) + continue; + bf.SetLimit(currentPos + 2); + bf >> FLATDATA(a); + for (uint8_t i = 0; i < 2; ++i) { + ASSERT_EQ(a[i], currentPos); + currentPos++; + } + break; + } + case 2: { + uint8_t a[5]; + if (currentPos + 5 > fileSize) + continue; + bf.SetLimit(currentPos + 5); + bf >> FLATDATA(a); + for (uint8_t i = 0; i < 5; ++i) { + ASSERT_EQ(a[i], currentPos); + currentPos++; + } + break; + } + case 3: { + // Find a byte value (that is at or ahead of the current position). + size_t find = currentPos + GetRandInt(8); + if (find >= fileSize) + find = fileSize - 1; + bf.FindByte(static_cast(find)); + // The value at each offset is the offset. + ASSERT_EQ(bf.GetPos(), find); + currentPos = find; + + bf.SetLimit(currentPos + 1); + uint8_t i; + bf >> i; + ASSERT_EQ(i, currentPos); + currentPos++; + break; + } + case 4: { + size_t requestPos = GetRandInt(maxPos + 4); + bool okay = bf.SetPos(requestPos); + // The new position may differ from the requested position + // because we may not be able to rewind beyond the rewind + // window, and we may not be able to move forward beyond the + // farthest position we've reached so far. + currentPos = bf.GetPos(); + ASSERT_EQ(okay, currentPos == requestPos); + // Check that we can position within the rewind window. + if (requestPos <= maxPos && + maxPos > rewindSize && + requestPos >= maxPos - rewindSize) { + // We requested a position within the rewind window. + ASSERT_TRUE(okay); + } + break; + } + } + if (maxPos < currentPos) + maxPos = currentPos; + } + } + boost::filesystem::remove("streams_test_tmp"); + + } + + TEST(TestBufferedFile, komodo_block_load) { + + CBlock block; + block.SetNull(); + + FILE* fileIn = fopen("komodo_block_load_tmp", "w+b"); + + // dd if=blk00000.dat bs=1 count=1700 2>/dev/null | xxd -i + const uint8_t blockOnDisk[] = { + 0xf9, 0xee, 0xe4, 0x8d, 0x9c, 0x06, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3b, 0xa3, 0xed, 0xfd, + 0x7a, 0x7b, 0x12, 0xb2, 0x7a, 0xc7, 0x2c, 0x3e, 0x67, 0x76, 0x8f, 0x61, + 0x7f, 0xc8, 0x1b, 0xc3, 0x88, 0x8a, 0x51, 0x32, 0x3a, 0x9f, 0xb8, 0xaa, + 0x4b, 0x1e, 0x5e, 0x4a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x29, 0xab, 0x5f, 0x49, 0x0f, 0x0f, 0x0f, 0x20, 0x0b, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfd, 0x40, 0x05, 0x00, 0x0d, 0x5b, 0xa7, 0xcd, + 0xa5, 0xd4, 0x73, 0x94, 0x72, 0x63, 0xbf, 0x19, 0x42, 0x85, 0x31, 0x71, + 0x79, 0xd2, 0xb0, 0xd3, 0x07, 0x11, 0x9c, 0x2e, 0x7c, 0xc4, 0xbd, 0x8a, + 0xc4, 0x56, 0xf0, 0x77, 0x4b, 0xd5, 0x2b, 0x0c, 0xd9, 0x24, 0x9b, 0xe9, + 0xd4, 0x07, 0x18, 0xb6, 0x39, 0x7a, 0x4c, 0x7b, 0xbd, 0x8f, 0x2b, 0x32, + 0x72, 0xfe, 0xd2, 0x82, 0x3c, 0xd2, 0xaf, 0x4b, 0xd1, 0x63, 0x22, 0x00, + 0xba, 0x4b, 0xf7, 0x96, 0x72, 0x7d, 0x63, 0x47, 0xb2, 0x25, 0xf6, 0x70, + 0xf2, 0x92, 0x34, 0x32, 0x74, 0xcc, 0x35, 0x09, 0x94, 0x66, 0xf5, 0xfb, + 0x5f, 0x0c, 0xd1, 0xc1, 0x05, 0x12, 0x1b, 0x28, 0x21, 0x3d, 0x15, 0xdb, + 0x2e, 0xd7, 0xbd, 0xba, 0x49, 0x0b, 0x4c, 0xed, 0xc6, 0x97, 0x42, 0xa5, + 0x7b, 0x7c, 0x25, 0xaf, 0x24, 0x48, 0x5e, 0x52, 0x3a, 0xad, 0xbb, 0x77, + 0xa0, 0x14, 0x4f, 0xc7, 0x6f, 0x79, 0xef, 0x73, 0xbd, 0x85, 0x30, 0xd4, + 0x2b, 0x9f, 0x3b, 0x9b, 0xed, 0x1c, 0x13, 0x5a, 0xd1, 0xfe, 0x15, 0x29, + 0x23, 0xfa, 0xfe, 0x98, 0xf9, 0x5f, 0x76, 0xf1, 0x61, 0x5e, 0x64, 0xc4, + 0xab, 0xb1, 0x13, 0x7f, 0x4c, 0x31, 0xb2, 0x18, 0xba, 0x27, 0x82, 0xbc, + 0x15, 0x53, 0x47, 0x88, 0xdd, 0xa2, 0xcc, 0x08, 0xa0, 0xee, 0x29, 0x87, + 0xc8, 0xb2, 0x7f, 0xf4, 0x1b, 0xd4, 0xe3, 0x1c, 0xd5, 0xfb, 0x56, 0x43, + 0xdf, 0xe8, 0x62, 0xc9, 0xa0, 0x2c, 0xa9, 0xf9, 0x0c, 0x8c, 0x51, 0xa6, + 0x67, 0x1d, 0x68, 0x1d, 0x04, 0xad, 0x47, 0xe4, 0xb5, 0x3b, 0x15, 0x18, + 0xd4, 0xbe, 0xfa, 0xfe, 0xfe, 0x8c, 0xad, 0xfb, 0x91, 0x2f, 0x3d, 0x03, + 0x05, 0x1b, 0x1e, 0xfb, 0xf1, 0xdf, 0xe3, 0x7b, 0x56, 0xe9, 0x3a, 0x74, + 0x1d, 0x8d, 0xfd, 0x80, 0xd5, 0x76, 0xca, 0x25, 0x0b, 0xee, 0x55, 0xfa, + 0xb1, 0x31, 0x1f, 0xc7, 0xb3, 0x25, 0x59, 0x77, 0x55, 0x8c, 0xdd, 0xa6, + 0xf7, 0xd6, 0xf8, 0x75, 0x30, 0x6e, 0x43, 0xa1, 0x44, 0x13, 0xfa, 0xcd, + 0xae, 0xd2, 0xf4, 0x60, 0x93, 0xe0, 0xef, 0x1e, 0x8f, 0x8a, 0x96, 0x3e, + 0x16, 0x32, 0xdc, 0xbe, 0xeb, 0xd8, 0xe4, 0x9f, 0xd1, 0x6b, 0x57, 0xd4, + 0x9b, 0x08, 0xf9, 0x76, 0x2d, 0xe8, 0x91, 0x57, 0xc6, 0x52, 0x33, 0xf6, + 0x0c, 0x8e, 0x38, 0xa1, 0xf5, 0x03, 0xa4, 0x8c, 0x55, 0x5f, 0x8e, 0xc4, + 0x5d, 0xed, 0xec, 0xd5, 0x74, 0xa3, 0x76, 0x01, 0x32, 0x3c, 0x27, 0xbe, + 0x59, 0x7b, 0x95, 0x63, 0x43, 0x10, 0x7f, 0x8b, 0xd8, 0x0f, 0x3a, 0x92, + 0x5a, 0xfa, 0xf3, 0x08, 0x11, 0xdf, 0x83, 0xc4, 0x02, 0x11, 0x6b, 0xb9, + 0xc1, 0xe5, 0x23, 0x1c, 0x70, 0xff, 0xf8, 0x99, 0xa7, 0xc8, 0x2f, 0x73, + 0xc9, 0x02, 0xba, 0x54, 0xda, 0x53, 0xcc, 0x45, 0x9b, 0x7b, 0xf1, 0x11, + 0x3d, 0xb6, 0x5c, 0xc8, 0xf6, 0x91, 0x4d, 0x36, 0x18, 0x56, 0x0e, 0xa6, + 0x9a, 0xbd, 0x13, 0x65, 0x8f, 0xa7, 0xb6, 0xaf, 0x92, 0xd3, 0x74, 0xd6, + 0xec, 0xa9, 0x52, 0x9f, 0x8b, 0xd5, 0x65, 0x16, 0x6e, 0x4f, 0xcb, 0xf2, + 0xa8, 0xdf, 0xb3, 0xc9, 0xb6, 0x95, 0x39, 0xd4, 0xd2, 0xee, 0x2e, 0x93, + 0x21, 0xb8, 0x5b, 0x33, 0x19, 0x25, 0xdf, 0x19, 0x59, 0x15, 0xf2, 0x75, + 0x76, 0x37, 0xc2, 0x80, 0x5e, 0x1d, 0x41, 0x31, 0xe1, 0xad, 0x9e, 0xf9, + 0xbc, 0x1b, 0xb1, 0xc7, 0x32, 0xd8, 0xdb, 0xa4, 0x73, 0x87, 0x16, 0xd3, + 0x51, 0xab, 0x30, 0xc9, 0x96, 0xc8, 0x65, 0x7b, 0xab, 0x39, 0x56, 0x7e, + 0xe3, 0xb2, 0x9c, 0x6d, 0x05, 0x4b, 0x71, 0x14, 0x95, 0xc0, 0xd5, 0x2e, + 0x1c, 0xd5, 0xd8, 0xe5, 0x5b, 0x4f, 0x0f, 0x03, 0x25, 0xb9, 0x73, 0x69, + 0x28, 0x07, 0x55, 0xb4, 0x6a, 0x02, 0xaf, 0xd5, 0x4b, 0xe4, 0xdd, 0xd9, + 0xf7, 0x7c, 0x22, 0x27, 0x2b, 0x8b, 0xbb, 0x17, 0xff, 0x51, 0x18, 0xfe, + 0xdb, 0xae, 0x25, 0x64, 0x52, 0x4e, 0x79, 0x7b, 0xd2, 0x8b, 0x5f, 0x74, + 0xf7, 0x07, 0x9d, 0x53, 0x2c, 0xcc, 0x05, 0x98, 0x07, 0x98, 0x9f, 0x94, + 0xd2, 0x67, 0xf4, 0x7e, 0x72, 0x4b, 0x3f, 0x1e, 0xcf, 0xe0, 0x0e, 0xc9, + 0xe6, 0x54, 0x1c, 0x96, 0x10, 0x80, 0xd8, 0x89, 0x12, 0x51, 0xb8, 0x4b, + 0x44, 0x80, 0xbc, 0x29, 0x2f, 0x6a, 0x18, 0x0b, 0xea, 0x08, 0x9f, 0xef, + 0x5b, 0xbd, 0xa5, 0x6e, 0x1e, 0x41, 0x39, 0x0d, 0x7c, 0x0e, 0x85, 0xba, + 0x0e, 0xf5, 0x30, 0xf7, 0x17, 0x74, 0x13, 0x48, 0x1a, 0x22, 0x64, 0x65, + 0xa3, 0x6e, 0xf6, 0xaf, 0xe1, 0xe2, 0xbc, 0xa6, 0x9d, 0x20, 0x78, 0x71, + 0x2b, 0x39, 0x12, 0xbb, 0xa1, 0xa9, 0x9b, 0x1f, 0xbf, 0xf0, 0xd3, 0x55, + 0xd6, 0xff, 0xe7, 0x26, 0xd2, 0xbb, 0x6f, 0xbc, 0x10, 0x3c, 0x4a, 0xc5, + 0x75, 0x6e, 0x5b, 0xee, 0x6e, 0x47, 0xe1, 0x74, 0x24, 0xeb, 0xcb, 0xf1, + 0xb6, 0x3d, 0x8c, 0xb9, 0x0c, 0xe2, 0xe4, 0x01, 0x98, 0xb4, 0xf4, 0x19, + 0x86, 0x89, 0xda, 0xea, 0x25, 0x43, 0x07, 0xe5, 0x2a, 0x25, 0x56, 0x2f, + 0x4c, 0x14, 0x55, 0x34, 0x0f, 0x0f, 0xfe, 0xb1, 0x0f, 0x9d, 0x8e, 0x91, + 0x47, 0x75, 0xe3, 0x7d, 0x0e, 0xdc, 0xa0, 0x19, 0xfb, 0x1b, 0x9c, 0x6e, + 0xf8, 0x12, 0x55, 0xed, 0x86, 0xbc, 0x51, 0xc5, 0x39, 0x1e, 0x05, 0x91, + 0x48, 0x0f, 0x66, 0xe2, 0xd8, 0x8c, 0x5f, 0x4f, 0xd7, 0x27, 0x76, 0x97, + 0x96, 0x86, 0x56, 0xa9, 0xb1, 0x13, 0xab, 0x97, 0xf8, 0x74, 0xfd, 0xd5, + 0xf2, 0x46, 0x5e, 0x55, 0x59, 0x53, 0x3e, 0x01, 0xba, 0x13, 0xef, 0x4a, + 0x8f, 0x7a, 0x21, 0xd0, 0x2c, 0x30, 0xc8, 0xde, 0xd6, 0x8e, 0x8c, 0x54, + 0x60, 0x3a, 0xb9, 0xc8, 0x08, 0x4e, 0xf6, 0xd9, 0xeb, 0x4e, 0x92, 0xc7, + 0x5b, 0x07, 0x85, 0x39, 0xe2, 0xae, 0x78, 0x6e, 0xba, 0xb6, 0xda, 0xb7, + 0x3a, 0x09, 0xe0, 0xaa, 0x9a, 0xc5, 0x75, 0xbc, 0xef, 0xb2, 0x9e, 0x93, + 0x0a, 0xe6, 0x56, 0xe5, 0x8b, 0xcb, 0x51, 0x3f, 0x7e, 0x3c, 0x17, 0xe0, + 0x79, 0xdc, 0xe4, 0xf0, 0x5b, 0x5d, 0xbc, 0x18, 0xc2, 0xa8, 0x72, 0xb2, + 0x25, 0x09, 0x74, 0x0e, 0xbe, 0x6a, 0x39, 0x03, 0xe0, 0x0a, 0xd1, 0xab, + 0xc5, 0x50, 0x76, 0x44, 0x18, 0x62, 0x64, 0x3f, 0x93, 0x60, 0x6e, 0x3d, + 0xc3, 0x5e, 0x8d, 0x9f, 0x2c, 0xae, 0xf3, 0xee, 0x6b, 0xe1, 0x4d, 0x51, + 0x3b, 0x2e, 0x06, 0x2b, 0x21, 0xd0, 0x06, 0x1d, 0xe3, 0xbd, 0x56, 0x88, + 0x17, 0x13, 0xa1, 0xa5, 0xc1, 0x7f, 0x5a, 0xce, 0x05, 0xe1, 0xec, 0x09, + 0xda, 0x53, 0xf9, 0x94, 0x42, 0xdf, 0x17, 0x5a, 0x49, 0xbd, 0x15, 0x4a, + 0xa9, 0x6e, 0x49, 0x49, 0xde, 0xcd, 0x52, 0xfe, 0xd7, 0x9c, 0xcf, 0x7c, + 0xcb, 0xce, 0x32, 0x94, 0x14, 0x19, 0xc3, 0x14, 0xe3, 0x74, 0xe4, 0xa3, + 0x96, 0xac, 0x55, 0x3e, 0x17, 0xb5, 0x34, 0x03, 0x36, 0xa1, 0xa2, 0x5c, + 0x22, 0xf9, 0xe4, 0x2a, 0x24, 0x3b, 0xa5, 0x40, 0x44, 0x50, 0xb6, 0x50, + 0xac, 0xfc, 0x82, 0x6a, 0x6e, 0x43, 0x29, 0x71, 0xac, 0xe7, 0x76, 0xe1, + 0x57, 0x19, 0x51, 0x5e, 0x16, 0x34, 0xce, 0xb9, 0xa4, 0xa3, 0x50, 0x61, + 0xb6, 0x68, 0xc7, 0x49, 0x98, 0xd3, 0xdf, 0xb5, 0x82, 0x7f, 0x62, 0x38, + 0xec, 0x01, 0x53, 0x77, 0xe6, 0xf9, 0xc9, 0x4f, 0x38, 0x10, 0x87, 0x68, + 0xcf, 0x6e, 0x5c, 0x8b, 0x13, 0x2e, 0x03, 0x03, 0xfb, 0x5a, 0x20, 0x03, + 0x68, 0xf8, 0x45, 0xad, 0x9d, 0x46, 0x34, 0x30, 0x35, 0xa6, 0xff, 0x94, + 0x03, 0x1d, 0xf8, 0xd8, 0x30, 0x94, 0x15, 0xbb, 0x3f, 0x6c, 0xd5, 0xed, + 0xe9, 0xc1, 0x35, 0xfd, 0xab, 0xcc, 0x03, 0x05, 0x99, 0x85, 0x8d, 0x80, + 0x3c, 0x0f, 0x85, 0xbe, 0x76, 0x61, 0xc8, 0x89, 0x84, 0xd8, 0x8f, 0xaa, + 0x3d, 0x26, 0xfb, 0x0e, 0x9a, 0xac, 0x00, 0x56, 0xa5, 0x3f, 0x1b, 0x5d, + 0x0b, 0xae, 0xd7, 0x13, 0xc8, 0x53, 0xc4, 0xa2, 0x72, 0x68, 0x69, 0xa0, + 0xa1, 0x24, 0xa8, 0xa5, 0xbb, 0xc0, 0xfc, 0x0e, 0xf8, 0x0c, 0x8a, 0xe4, + 0xcb, 0x53, 0x63, 0x6a, 0xa0, 0x25, 0x03, 0xb8, 0x6a, 0x1e, 0xb9, 0x83, + 0x6f, 0xcc, 0x25, 0x98, 0x23, 0xe2, 0x69, 0x2d, 0x92, 0x1d, 0x88, 0xe1, + 0xff, 0xc1, 0xe6, 0xcb, 0x2b, 0xde, 0x43, 0x93, 0x9c, 0xeb, 0x3f, 0x32, + 0xa6, 0x11, 0x68, 0x6f, 0x53, 0x9f, 0x8f, 0x7c, 0x9f, 0x0b, 0xf0, 0x03, + 0x81, 0xf7, 0x43, 0x60, 0x7d, 0x40, 0x96, 0x0f, 0x06, 0xd3, 0x47, 0xd1, + 0xcd, 0x8a, 0xc8, 0xa5, 0x19, 0x69, 0xc2, 0x5e, 0x37, 0x15, 0x0e, 0xfd, + 0xf7, 0xaa, 0x4c, 0x20, 0x37, 0xa2, 0xfd, 0x05, 0x16, 0xfb, 0x44, 0x45, + 0x25, 0xab, 0x15, 0x7a, 0x0e, 0xd0, 0xa7, 0x41, 0x2b, 0x2f, 0xa6, 0x9b, + 0x21, 0x7f, 0xe3, 0x97, 0x26, 0x31, 0x53, 0x78, 0x2c, 0x0f, 0x64, 0x35, + 0x1f, 0xbd, 0xf2, 0x67, 0x8f, 0xa0, 0xdc, 0x85, 0x69, 0x91, 0x2d, 0xcd, + 0x8e, 0x3c, 0xca, 0xd3, 0x8f, 0x34, 0xf2, 0x3b, 0xbb, 0xce, 0x14, 0xc6, + 0xa2, 0x6a, 0xc2, 0x49, 0x11, 0xb3, 0x08, 0xb8, 0x2c, 0x7e, 0x43, 0x06, + 0x2d, 0x18, 0x0b, 0xae, 0xac, 0x4b, 0xa7, 0x15, 0x38, 0x58, 0x36, 0x5c, + 0x72, 0xc6, 0x3d, 0xcf, 0x5f, 0x6a, 0x5b, 0x08, 0x07, 0x0b, 0x73, 0x0a, + 0xdb, 0x01, 0x7a, 0xea, 0xe9, 0x25, 0xb7, 0xd0, 0x43, 0x99, 0x79, 0xe2, + 0x67, 0x9f, 0x45, 0xed, 0x2f, 0x25, 0xa7, 0xed, 0xcf, 0xd2, 0xfb, 0x77, + 0xa8, 0x79, 0x46, 0x30, 0x28, 0x5c, 0xcb, 0x0a, 0x07, 0x1f, 0x5c, 0xce, + 0x41, 0x0b, 0x46, 0xdb, 0xf9, 0x75, 0x0b, 0x03, 0x54, 0xaa, 0xe8, 0xb6, + 0x55, 0x74, 0x50, 0x1c, 0xc6, 0x9e, 0xfb, 0x5b, 0x6a, 0x43, 0x44, 0x40, + 0x74, 0xfe, 0xe1, 0x16, 0x64, 0x1b, 0xb2, 0x9d, 0xa5, 0x6c, 0x2b, 0x4a, + 0x7f, 0x45, 0x69, 0x91, 0xfc, 0x92, 0xb2, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, + 0xff, 0x4d, 0x04, 0xff, 0xff, 0x00, 0x1d, 0x01, 0x04, 0x45, 0x54, 0x68, + 0x65, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x20, 0x30, 0x33, 0x2f, 0x4a, + 0x61, 0x6e, 0x2f, 0x32, 0x30, 0x30, 0x39, 0x20, 0x43, 0x68, 0x61, 0x6e, + 0x63, 0x65, 0x6c, 0x6c, 0x6f, 0x72, 0x20, 0x6f, 0x6e, 0x20, 0x62, 0x72, + 0x69, 0x6e, 0x6b, 0x20, 0x6f, 0x66, 0x20, 0x73, 0x65, 0x63, 0x6f, 0x6e, + 0x64, 0x20, 0x62, 0x61, 0x69, 0x6c, 0x6f, 0x75, 0x74, 0x20, 0x66, 0x6f, + 0x72, 0x20, 0x62, 0x61, 0x6e, 0x6b, 0x73, 0xff, 0xff, 0xff, 0xff, 0x01, + 0x00, 0xf2, 0x05, 0x2a, 0x01, 0x00, 0x00, 0x00, 0x43, 0x41, 0x04, 0x67, + 0x8a, 0xfd, 0xb0, 0xfe, 0x55, 0x48, 0x27, 0x19, 0x67, 0xf1, 0xa6, 0x71, + 0x30, 0xb7, 0x10, 0x5c, 0xd6, 0xa8, 0x28, 0xe0, 0x39, 0x09, 0xa6, 0x79, + 0x62, 0xe0, 0xea, 0x1f, 0x61, 0xde, 0xb6, 0x49, 0xf6, 0xbc, 0x3f, 0x4c, + 0xef, 0x38, 0xc4, 0xf3, 0x55, 0x04, 0xe5, 0x1e, 0xc1, 0x12, 0xde, 0x5c, + 0x38, 0x4d, 0xf7, 0xba, 0x0b, 0x8d, 0x57, 0x8a, 0x4c, 0x70, 0x2b, 0x6b, + 0xf1, 0x1d, 0x5f, 0xac, 0x00, 0x00, 0x00, 0x00 + }; + + // make blk.dat consists from 2 genesis blocks + for (uint32_t i = 0; i < 2; ++i) + for (uint32_t j = 0; j < sizeof(blockOnDisk); ++j) { + fwrite(&blockOnDisk[j], 1, 1, fileIn); + } + rewind(fileIn); + + CBufferedFile blkdat(fileIn, 2*MAX_BLOCK_SIZE(10000000), MAX_BLOCK_SIZE(10000000)+8, SER_DISK, CLIENT_VERSION); + blkdat.SetLimit(); // remove former limit + + blkdat.SetPos(0); + for (uint32_t i = 0; i < 2; ++i) { + unsigned int nSize = 0; + try { + // locate a header + unsigned char buf[MESSAGE_START_SIZE]; + blkdat >> FLATDATA(buf); + ASSERT_TRUE(*(uint32_t *)buf == 0x8DE4EEF9); + // read size + blkdat >> nSize; + ASSERT_FALSE(nSize < 80 || nSize > MAX_BLOCK_SIZE(10000000)); + } catch (const std::exception&) { + ASSERT_TRUE(false); + } + // Read block + blkdat >> block; + ASSERT_TRUE(block.GetHash().ToString() == "027e3758c3a65b12aa1046462b486d0a63bfa1beae327897f56c5cfb7daaae71"); + } + + block.SetNull(); + blkdat.SetPos(8); + blkdat >> block; + ASSERT_TRUE(block.GetHash().ToString() == "027e3758c3a65b12aa1046462b486d0a63bfa1beae327897f56c5cfb7daaae71"); + + blkdat.fclose(); + boost::filesystem::remove("komodo_block_load_tmp"); + + } + +} \ No newline at end of file diff --git a/src/test-komodo/test_coinimport.cpp b/src/test-komodo/test_coinimport.cpp index fda62c30..05c709eb 100644 --- a/src/test-komodo/test_coinimport.cpp +++ b/src/test-komodo/test_coinimport.cpp @@ -79,7 +79,7 @@ class TestCoinImport : public ::testing::Test, public Eval { }; -TEST_F(TestCoinImport, testProcessImportThroughPipeline) +TEST_F(TestCoinImport, DISABLED_testProcessImportThroughPipeline) { CValidationState mainstate; CTransaction tx(importTx); @@ -110,7 +110,7 @@ TEST_F(TestCoinImport, testProcessImportThroughPipeline) } -TEST_F(TestCoinImport, testImportTombstone) +TEST_F(TestCoinImport, DISABLED_testImportTombstone) { CValidationState mainstate; // By setting an unspendable output, there will be no addition to UTXO @@ -188,7 +188,7 @@ TEST_F(TestCoinImport, testInvalidBurnParams) } -TEST_F(TestCoinImport, testWrongChainId) +TEST_F(TestCoinImport, DISABLED_testWrongChainId) { testCcid = 0; TestRunCCEval(importTx); @@ -206,7 +206,7 @@ TEST_F(TestCoinImport, testInvalidBurnAmount) } -TEST_F(TestCoinImport, testPayoutTooHigh) +TEST_F(TestCoinImport, DISABLED_testPayoutTooHigh) { importTx.vout[1].nValue = 101; TestRunCCEval(importTx); @@ -214,7 +214,7 @@ TEST_F(TestCoinImport, testPayoutTooHigh) } -TEST_F(TestCoinImport, testAmountInOpret) +TEST_F(TestCoinImport, DISABLED_testAmountInOpret) { importTx.vout[0].nValue = 1; TestRunCCEval(importTx); @@ -223,7 +223,7 @@ TEST_F(TestCoinImport, testAmountInOpret) -TEST_F(TestCoinImport, testInvalidPayouts) +TEST_F(TestCoinImport, DISABLED_testInvalidPayouts) { importTx.vout[1].nValue = 40; importTx.vout.push_back(importTx.vout[0]); @@ -232,7 +232,7 @@ TEST_F(TestCoinImport, testInvalidPayouts) } -TEST_F(TestCoinImport, testCouldntLoadMomom) +TEST_F(TestCoinImport, DISABLED_testCouldntLoadMomom) { MoMoM.SetNull(); TestRunCCEval(importTx); @@ -240,7 +240,7 @@ TEST_F(TestCoinImport, testCouldntLoadMomom) } -TEST_F(TestCoinImport, testMomomCheckFail) +TEST_F(TestCoinImport, DISABLED_testMomomCheckFail) { MoMoM.SetNull(); MoMoM.begin()[0] = 1; diff --git a/src/test-komodo/test_eval_notarisation.cpp b/src/test-komodo/test_eval_notarisation.cpp index f0c48f95..2256f476 100644 --- a/src/test-komodo/test_eval_notarisation.cpp +++ b/src/test-komodo/test_eval_notarisation.cpp @@ -130,6 +130,7 @@ TEST(TestEvalNotarisation, testInvalidNotaryPubkey) TEST(TestEvalNotarisation, testInvalidNotarisationBadOpReturn) { EvalMock eval; + EVAL_TEST = &eval; CMutableTransaction notary(notaryTx); notary.vout[1].scriptPubKey = CScript() << OP_RETURN << 0; @@ -143,6 +144,7 @@ TEST(TestEvalNotarisation, testInvalidNotarisationBadOpReturn) TEST(TestEvalNotarisation, testInvalidNotarisationTxNotEnoughSigs) { EvalMock eval; + EVAL_TEST = &eval; CMutableTransaction notary(notaryTx); SetupEval(eval, notary, [](CMutableTransaction &tx) { @@ -157,6 +159,7 @@ TEST(TestEvalNotarisation, testInvalidNotarisationTxNotEnoughSigs) TEST(TestEvalNotarisation, testInvalidNotarisationTxDoesntExist) { EvalMock eval; + EVAL_TEST = &eval; CMutableTransaction notary(notaryTx); SetupEval(eval, notary, noop); @@ -169,6 +172,7 @@ TEST(TestEvalNotarisation, testInvalidNotarisationTxDoesntExist) TEST(TestEvalNotarisation, testInvalidNotarisationDupeNotary) { EvalMock eval; + EVAL_TEST = &eval; CMutableTransaction notary(notaryTx); SetupEval(eval, notary, [](CMutableTransaction &tx) { @@ -183,6 +187,7 @@ TEST(TestEvalNotarisation, testInvalidNotarisationDupeNotary) TEST(TestEvalNotarisation, testInvalidNotarisationInputNotCheckSig) { EvalMock eval; + EVAL_TEST = &eval; CMutableTransaction notary(notaryTx); SetupEval(eval, notary, [&](CMutableTransaction &tx) { diff --git a/src/test-komodo/test_merkle_tests.cpp b/src/test-komodo/test_merkle_tests.cpp new file mode 100644 index 00000000..05bcaf66 --- /dev/null +++ b/src/test-komodo/test_merkle_tests.cpp @@ -0,0 +1,315 @@ +#include + +// #include "chainparamsbase.h" +// #include "fs.h" +// #include "key.h" +// #include "pubkey.h" +// #include "random.h" +// #include "scheduler.h" +// #include "txdb.h" +// #include "txmempool.h" + +// #include +// #include + +#include "uint256.h" +#include "hash.h" +#include "primitives/block.h" +#include "consensus/merkle.h" +#include "random.h" +#include "core_io.h" + +namespace TestMerkleTests { + + class TestMerkleTests : public ::testing::Test {}; + + 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(it->begin(), it->end(), hash.begin(), hash.end()); + } else { + hash = Hash(hash.begin(), hash.end(), it->begin(), it->end()); + } + 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(); + 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(); + vMerkleTree.reserve(block.vtx.size() * 2 + 16); // Safe upper bound for the number of total nodes. + //for (std::vector::const_iterator it(block.vtx.begin()); it != block.vtx.end(); ++it) + for (std::vector::const_iterator it(block.vtx.begin()); it != block.vtx.end(); ++it) { + // vMerkleTree.push_back((*it)->GetHash()); + vMerkleTree.push_back((*it).GetHash()); + } + + 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; + } + + TEST(TestMerkleTests, merkle_test) { + // standart bitcoin test from merkle_tests.cpp + + 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 + ( GetRand(4000) ); // InsecureRandRange(4000) + // Try up to 3 mutations. + for (int mutate = 0; mutate <= 3; mutate++) { + int duplicate1 = mutate >= 1 ? 1 << ctz(ntx) : 0; // The last how many transactions to duplicate first. + if (duplicate1 >= ntx) break; // Duplication of the entire tree results in a different root (it adds a level). + int ntx1 = ntx + duplicate1; // The resulting number of transactions after the first duplication. + int duplicate2 = mutate >= 2 ? 1 << ctz(ntx1) : 0; // Likewise for the second mutation. + if (duplicate2 >= ntx1) break; + int ntx2 = ntx1 + duplicate2; + int duplicate3 = mutate >= 3 ? 1 << ctz(ntx2) : 0; // And for the third mutation. + 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)); + block.vtx[j] = mtx; + } + + // Compute the root of the block before mutating it. + bool unmutatedMutated = false; + uint256 unmutatedRoot = BlockMerkleRoot(block, &unmutatedMutated); + ASSERT_TRUE(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); + ASSERT_TRUE(oldRoot == newRoot); + ASSERT_TRUE(newRoot == unmutatedRoot); + ASSERT_TRUE((newRoot == uint256()) == (ntx == 0)); + ASSERT_TRUE(oldMutated == newMutated); + ASSERT_TRUE(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. Otherwise, try 16 random ones. + int mtx = loop; + if (ntx > 16) { + mtx = GetRand(mtx); // InsecureRandRange(ntx) + } + std::vector newBranch = BlockMerkleBranch(block, mtx); + std::vector oldBranch = BlockGetMerkleBranch(block, merkleTree, mtx); + ASSERT_TRUE(oldBranch == newBranch); + //BOOST_CHECK(ComputeMerkleRootFromBranch(block.vtx[mtx]->GetHash(), newBranch, mtx) == oldRoot); + ASSERT_TRUE(ComputeMerkleRootFromBranch(block.vtx[mtx].GetHash(), newBranch, mtx) == oldRoot); + } + } + } + } + } + + TEST(TestMerkleTests, merkle_real_one) { + CBlock b; + // Block #1795885 + std::string strHexBlock = "040000009db54b2301a7a2c3cc9ba11595f38bc72c635c2b10ea3e1d88170de7c65bec06c4214e1c5767ab99d69c50581b0edb506c5c3ca2b95ebb9e6c8e4147d9ec630ba2d8a734eb73a4dc734072dbfd12406f1e7121bfe0e3d6c10922495c44e5cc1c2422725ea8f7001d0a00f67390367e032efd0eb7ac9a410d4f4bea82cf759e5b02ef85bd714c0000fd40050014d0c2e1c56c7522655035ed399ef8b11577fbe00b03077d075779fcdfc6428240e2bc314ff897c82c0ab1518b5e04c219ff8b920185ef2ae51fcbd1c4c8463617f97fa89cb34d0c27a5b6e0870e41d27de7820474b2f826dc5f85374f005cc7e3b53429ae0359f350cac4d204d9126fa0f3979502da9d1209249e1e452f581aa749e24a9948c9384996e08aceb4af9efab28f7e24af056acc0dfd756a92205b0e1b0a01fcace40132d20ab675e7f9d01e22f247d53b5e68c1def058306a14522812e82cb2cf24dbc0b851d953095adfba014e819b5cca96594ccdd049a19631ba0590f9d672071203fe735208f51dcf43bf857188620a95bb1d0d0769024ec072a187a22ac2b73445274e155e17cbc1186a5ac9890b4d90ff5a658373be55070ad03fb24a0ec88b5be890bfa1dc896689b7bb3a1db3a66e6f1b681ca53de75c7904f295b7ed4cd0804eac5b59e378009c3f7680501d1ae52b046dbe46b7cd3e8a3f8d490ad0a687eb9918b153f160c9deb1371500096b2bc007ddd2b365644529315e00c1b793372274ff5ad68e2584c5075792cb3d1e49077cc349f5fe961379a2f602696a8e451310e3b01e3345b6cad1d1b357f7caea077a0d3f72591027e749027a52f912462a3f7231f1054f38d8ec9ff8c9352772a6aea1928515bf1b801e1c7909e0cc26e46f46753a048deabaa384397e187d00cc2d7678a2b1dbb5e232bc66c2ea6cd0e852b18a1596cbc2e988607519dab2ea437797f6180c9546f203b1256d06e36d9d5388b1d2bc1ef54d150c1acbfc1ccc47ab81fa0adbd8e3340094f8c782a0e17c8359021b284ff2c373ac1c0e31541511b53263be54c9c621a4a2aec9a4f01da52ae2ac1f95b2ef46fefdb1290cdb8c470035e363bc9eb33ca9aefc61dbf07f268735b703577f900221894b95303c422181e5fdef401b001cef9e9b1df991de14230371fea7ad5082f885901c4dba0dd896f37ec38a323f9a62fcf60b9ade79541024b3b285ded1a54695513b71924690741d3f4bda2cb86691aa691abbd201144294d5656a8266571177041a56a1b602d3af648890f71934e508c617e98ff72636beda5d29c73776c965358be503d6d84d976d0b0b4a267c554e5b9dabbab0df14589f44544fb6c7194a325eb6a7192c23efc785041d4f4776141d72525e023833e3654e85b1521253fc49b6a60b693cffa3d204819acdcce29689c92742acbcbf0908e0d4e982a3076fd0593810e88dbc7275313a563b1726a6df3bd22126dfe1f36fb6ebc91a955808ccbe63d01afedac11dee75316228c081b2811471a357f1d6c0275956be306a6d55032b6539e95805032973ead9e5f0feb7031fefd77cef91a85ee200720051f5b4148ef58b75a1317fc7de495b48d8fd1c6a5e39d49872d9827f3f1b00c574e59307008f8d2540efb326ae81f5439d924f1fb187189ed6d5cf886762c21bfb1950e17cdace422aa5448cf48cce7514ae341ab9ecf9c1aa291912f632c7ebf55d93ba51747f338cb5da2b89e4425704c10d8c70b4f00ea741bbf7e5b9ebb012d27c68770353340401c62f326bcb9a0ca5dc89d74ac9bf8d78b6a2196f916a3f12cab2b2783524c2bd9bee22adffc18e1ace3c5edbb155ffec51190b8b731eb67aefba1d1f03a0ef35a20ed34f6bbe7364aca8118708f1dffed807381304691708796609a18f8dbe4a7cb6957bfde023ae662e83d23cf3d4c1428b94ed781aa07e7b3def50a2ded3b2eefe13f7e1b718445ec72a415fba507b090bcf8d74dec46d7970f143abf116fddc4c581fe50af58d0ac12b1f2b811843df5a54c5b2e21c3a618c1edd2c4499d0da1ad69c6630fcc7946665187808c431b0ace7c624036da2ec53878b7d7bccfb0aeca54a040400008085202f89010000000000000000000000000000000000000000000000000000000000000000ffffffff06032d671b0101ffffffff015034e21100000000232103ffdf1a116300a78729608d9930742cd349f11a9d64fcc336b8f18592dd9c91bcace721725e0000000000000000000000000000000400008085202f89011564d4cca16e344f52d12990586f27be394a1a96e353eaa44630de23b6d82bf4010000006a47304402204f5ddd47966b572f84ebc9c83b67355c5337eb6d9f11b7d0a0e0d26d3c954f7602201c9518d5859a51eb7c7ee588d5dc8f1fe60e6b23a63f16a528b71b978f531cda0121023e7363600c74eab77f6049339767660988936f55aac603d8f9a424d61089e012ffffffff025bda0600000000001976a914ca1e04745e8ca0c60d8c5881531d51bec470743f88ac0c07d004000000001976a914dbdfc4cefcf7fa0fa0c40270eb95ad6abb2ee35c88ace519725e0000000000000000000000000000000400008085202f890d27f51e72e562595212f9a92e9cfe5904b02f2d30bf16a006a55f8f595cf8fc2207000000494830450221009df689a80276a165bdddda3c10bc159b73f2b7fbe43b356fb36399e40121cbf0022032021d3c0e29ad562f33be3ccc2db1a7a9bfa214d69a0d0933bc43bb7fb5628901ffffffff0bda2bf0036db1367a0e03200a013d7487ed3f0f9b97f6a01ad56230b89526c61900000049483045022100c31d8504468aef7def59bfb58f5cd41c9261b7dd5cce4fc3687553bd183fb32c02207001e0883d6f0e73b2fd662c822ad21139bd5b19681cad27f2f48ceab67e78af01ffffffff632a9fb8a154e8e6019aad2367ddf03151659f844325b3eae7f4cc60f55c30810e00000049483045022100ffd197a2e05ae73f2073762d9530de765927e32af3697af0ce493b561737ba1102204d2b190d222dfd0e93689047e0e220f48a5a5e44f3a2762b56bab337b7f50c4f01fffffffff6800e723bba635aeaa4d3111bd4ae6ef8d01d98a95c4e2a1aaae8c2b11846ec3400000049483045022100e5f2a94e10c2f6d92b3ff48ae1582f0c0244e4ab4d141672c9d25bc86d2e8ad0022071d850fdb13816546e26c5f672fb9af4b4aa6a158a62a9a7ccf986b61096c5d601ffffffff638f262670789a20f561926bf1af50939dc1772af0f97c8be606e1dd5889105e0a000000494830450221008ae752a726cc1cf0fcb7127d73b87da31d02bf637cf943600a70c6d9a6983eb3022058c71a9219cfd4e5dcf644f3d22c7ad2cdee9863adcf1019338c2312fb2564ff01ffffffffcdd6056065b5f1764c0b7152432a7cac431b06be5ea530478469c865733f55f10a0000004847304402202ae8b2112c61c08d2739f1ff706cabbf93a10e563de9e229e75d699c95697fad02203be2568a811ffaa569d2469a2ed623dea3a0e45494733c38c90ed2b3179cc6de01ffffffff0ada9ffbbf628f1086ea873b004c0caea793aafa2d0959bc1ffa5f8b0e6eb493160000004847304402206c25273b9a6ddc386bc45fa045d3ddefe3dd582756183a1f3949597c8d5b24a602203b1247be908c717e9b0e7ce5add789fd27769de7482f95656bcb791188ad84d201ffffffff399bd17a83e419b5cd3f9685b7c768eea6483142d99f684d2572f2c32c9ea7d30000000049483045022100a0c744090ea03ad8b49e1aa7bc117eb88ddeb3cc357b47120cbf0a63bcefc934022074e60140c2704c62b6e23b3640a58567cdb48c169df82215646789fc5fcfcbbd01ffffffffee20f6d4c372ac04de49e9e91a12bf4ae2039b80c70e9c2351276908bc1f30761700000049483045022100e928f5c15fbf691b8b85aef0b322578701aafa5c8e88ba6273d139f46c31fbe302203e87797d1c9ff013ffadf174e27107ba584cfd10d5d7a52a3d5fe37b9ae800c001ffffffff9dbab35ce824b1cda10fd42ca2039970ff1c521ee0640b1b88d48811c19cecd82c00000049483045022100e00ed0eeaeef2df20aa6818efcc936af83514416e41ca0cf9631b1e4502e68190220711e0529190ddec4a51593446ec0f6496ce1bf7a43b09dccb71ab32e731b9c3401ffffffff6ea9427838bf315dd359925dcbddb57762a114e95ad7d2ff24a1985ccb16cedb1300000049483045022100daec766e4a578944d5e0df4f25767671cb5ade2b7b8d58346367d2da22f70f31022049b167ef75a9fe034efb0f09e9504147fc8482fedcc92c1a006869ec4c21bab301ffffffff4382e822aa22a632f252b08ab4723d739d01f79b40191cc314d9487efbd56d7a1d00000049483045022100fdda851870b0008fe1f45a9f6754a16320d825363075e21cde6a81410a6c44be02207accaa8ad8ed5a250646c0b50859247e0755acfc161b00d90b3f73904d64411201ffffffffa3d918bde33d20be628bfaaf8c5c354633b5d0dfed637f0f6160e95d9d6d19301b00000049483045022100f1493d37f036bed1d7fbdbb8c82d07a8bae296abaef718736221181b46932ef80220496ffc0a5c68f37d35b115a0db242de55a759100acbf5051ebe7b5317d799b2701ffffffff02f0810100000000002321020e46e79a2a8d12b9b5d12c7a91adb4e454edfae43c0a0cb805427d2ac7613fd9ac00000000000000004f6a4c4cbf2febf989888339fd19cc326553bfa506d6d97eeb4f678c95042d292b3c7e0e68710500544843006e99f983dc132bb584ef77ecbccc012b8b398b6209f1dfdca5098b7668fde98008000200000000000000000000000000000000000000000400008085202f89015b742fe720038fb5d4ffa67d712074f8f06027e635dcfd28593c3927f6f8a22a0c00000049483045022100c9ba5302eff4dc788eeaf56410cb111fe2b1a1287bab330cbdcf77a582f468e202205f84ba5db019de8c1b80e0e0b3ce15e6143123454240e261c663ba668c5c4a9501ffffffff0288130000000000002321020e46e79a2a8d12b9b5d12c7a91adb4e454edfae43c0a0cb805427d2ac7613fd9ac0000000000000000226a20afd3070729dad0191ff74b26e072eacd2382248047f8f4428cda690a67389c802422725ef5671b000000000000000000000000"; + std::string strHashMerkleRoot = "0b63ecd947418e6c9ebb5eb9a23c5c6c50db0e1b58509cd699ab67571c4e21c4"; + + if (!DecodeHexBlk(b, strHexBlock)) { + ASSERT_TRUE(false); + } + + uint256 hashMerkleRoot, hashMerkleRoot1, hashMerkleRoot2, hashMerkleRoot3, hashMerkleRoot4; + bool mutated; + + // using old implementation directly from primitives/block.h + hashMerkleRoot1 = b.BuildMerkleTree(&mutated); + // using new implementation in consensus/merkle.h + hashMerkleRoot2 = BlockMerkleRoot(b, &mutated); + + // old version of merkleroot computation code from this + std::vector leaves; + std::vector vMerkleTree; + for (int i=0; i::const_iterator it(leaves.begin()); it != leaves.end(); ++it) + vMerkleTree.push_back(*it); + hashMerkleRoot3 = BlockBuildMerkleTree(b, &mutated, vMerkleTree); + + hashMerkleRoot = uint256S(strHashMerkleRoot); + + /* std::cerr << hashMerkleRoot.ToString() << std::endl; + std::cerr << hashMerkleRoot1.ToString() << std::endl; + std::cerr << hashMerkleRoot2.ToString() << std::endl; + std::cerr << hashMerkleRoot3.ToString() << std::endl; */ + + ASSERT_EQ(hashMerkleRoot, hashMerkleRoot1); + ASSERT_EQ(hashMerkleRoot, hashMerkleRoot2); + ASSERT_EQ(hashMerkleRoot, hashMerkleRoot3); + + } +} \ No newline at end of file diff --git a/src/test-komodo/test_multisig_tests.cpp b/src/test-komodo/test_multisig_tests.cpp new file mode 100644 index 00000000..71da430b --- /dev/null +++ b/src/test-komodo/test_multisig_tests.cpp @@ -0,0 +1,239 @@ +#include +#include "consensus/upgrades.h" +#include "key.h" +#include "keystore.h" +#include "policy/policy.h" +#include "script/script.h" +#include "script/script_error.h" +#include "script/interpreter.h" +#include "script/sign.h" +#include "wallet/wallet_ismine.h" +#include "uint256.h" + + +namespace TestMultiSigTests { + + CScript sign_multisig(CScript scriptPubKey, std::vector keys, CTransaction transaction, int whichIn, uint32_t consensusBranchId) + { + uint256 hash = SignatureHash(scriptPubKey, transaction, whichIn, SIGHASH_ALL, 0, consensusBranchId); + + CScript result; + result << OP_0; // CHECKMULTISIG bug workaround + for(const CKey &key : keys) + { + std::vector vchSig; + EXPECT_TRUE(key.Sign(hash, vchSig)); + vchSig.push_back((unsigned char)SIGHASH_ALL); + result << vchSig; + } + return result; + } + + TEST(TestMultiSigTests , multisig_IsStandard) { + + CKey key[10]; + for (int i = 0; i < 10; i++) + key[i].MakeNewKey(true); + + txnouttype whichType; + + CScript a_and_b; + a_and_b << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG; + ASSERT_TRUE(::IsStandard(a_and_b, whichType)); + + CScript a_or_b; + a_or_b << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG; + ASSERT_TRUE(::IsStandard(a_or_b, whichType)); + + CScript escrow; + escrow << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << ToByteVector(key[2].GetPubKey()) << OP_3 << OP_CHECKMULTISIG; + ASSERT_TRUE(::IsStandard(escrow, whichType)); + + // Komodo supported up to x-of-9 multisig txns as standard (ZCash only x-of-3) + + CScript one_of_four; + one_of_four << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << ToByteVector(key[2].GetPubKey()) << ToByteVector(key[3].GetPubKey()) << OP_4 << OP_CHECKMULTISIG; + ASSERT_TRUE(::IsStandard(one_of_four, whichType)); + + CScript one_of_nine; + one_of_nine << OP_1; + for (int i = 0; i < 9; i++) one_of_nine << ToByteVector(key[i].GetPubKey()); + one_of_nine << OP_9 << OP_CHECKMULTISIG; + ASSERT_TRUE(::IsStandard(one_of_nine, whichType)); + + CScript one_of_ten; + one_of_ten << OP_1; + for (int i = 0; i < 9; i++) one_of_ten << ToByteVector(key[i].GetPubKey()); + one_of_nine << OP_10 << OP_CHECKMULTISIG; + ASSERT_TRUE(!::IsStandard(one_of_ten, whichType)); + + CScript malformed[6]; + malformed[0] << OP_3 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG; + malformed[1] << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_3 << OP_CHECKMULTISIG; + malformed[2] << OP_0 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG; + malformed[3] << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_0 << OP_CHECKMULTISIG; + malformed[4] << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_CHECKMULTISIG; + malformed[5] << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()); + + for (int i = 0; i < 6; i++) + ASSERT_TRUE(!::IsStandard(malformed[i], whichType)); + + } + + TEST(TestMultiSigTests , multisig_verify) { + // Parameterized testing over consensus branch ids + for ( int idx = Consensus::BASE_SPROUT; idx != Consensus::MAX_NETWORK_UPGRADES; idx++ ) { + + Consensus::UpgradeIndex sample = static_cast(idx); + uint32_t consensusBranchId = NetworkUpgradeInfo[sample].nBranchId; + unsigned int flags = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC; + + ScriptError err; + CKey key[4]; + CAmount amount = 0; + for (int i = 0; i < 4; i++) + key[i].MakeNewKey(true); + + CScript a_and_b; + a_and_b << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG; + + CScript a_or_b; + a_or_b << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG; + + CScript escrow; + escrow << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << ToByteVector(key[2].GetPubKey()) << OP_3 << OP_CHECKMULTISIG; + + CMutableTransaction txFrom; // Funding transaction + txFrom.vout.resize(3); + txFrom.vout[0].scriptPubKey = a_and_b; + txFrom.vout[1].scriptPubKey = a_or_b; + txFrom.vout[2].scriptPubKey = escrow; + + CMutableTransaction txTo[3]; // Spending transaction + for (int i = 0; i < 3; i++) + { + txTo[i].vin.resize(1); + txTo[i].vout.resize(1); + txTo[i].vin[0].prevout.n = i; + txTo[i].vin[0].prevout.hash = txFrom.GetHash(); + txTo[i].vout[0].nValue = 1; + } + + std::vector keys; + CScript s; + + // Test a AND b: + keys.assign(1,key[0]); + keys.push_back(key[1]); + s = sign_multisig(a_and_b, keys, txTo[0], 0, consensusBranchId); + ASSERT_TRUE(VerifyScript(s, a_and_b, flags, MutableTransactionSignatureChecker(&txTo[0], 0, amount), consensusBranchId, &err)); + ASSERT_TRUE(err == SCRIPT_ERR_OK) << ScriptErrorString(err); + + for (int i = 0; i < 4; i++) + { + keys.assign(1,key[i]); + s = sign_multisig(a_and_b, keys, txTo[0], 0, consensusBranchId); + ASSERT_TRUE(!VerifyScript(s, a_and_b, flags, MutableTransactionSignatureChecker(&txTo[0], 0, amount), consensusBranchId, &err)) << strprintf("a&b 1: %d", i); + ASSERT_TRUE(err == SCRIPT_ERR_INVALID_STACK_OPERATION) << ScriptErrorString(err); + + keys.assign(1,key[1]); + keys.push_back(key[i]); + s = sign_multisig(a_and_b, keys, txTo[0], 0, consensusBranchId); + ASSERT_TRUE(!VerifyScript(s, a_and_b, flags, MutableTransactionSignatureChecker(&txTo[0], 0, amount), consensusBranchId, &err)) << strprintf("a&b 2: %d", i); + ASSERT_TRUE(err == SCRIPT_ERR_EVAL_FALSE) << ScriptErrorString(err); + } + + // Test a OR b: + for (int i = 0; i < 4; i++) + { + keys.assign(1,key[i]); + s = sign_multisig(a_or_b, keys, txTo[1], 0, consensusBranchId); + if (i == 0 || i == 1) + { + ASSERT_TRUE(VerifyScript(s, a_or_b, flags, MutableTransactionSignatureChecker(&txTo[1], 0, amount), consensusBranchId, &err)) << strprintf("a|b: %d", i); + ASSERT_TRUE(err == SCRIPT_ERR_OK) << ScriptErrorString(err); + } + else + { + ASSERT_TRUE(!VerifyScript(s, a_or_b, flags, MutableTransactionSignatureChecker(&txTo[1], 0, amount), consensusBranchId, &err)) << strprintf("a|b: %d", i); + ASSERT_TRUE(err == SCRIPT_ERR_EVAL_FALSE) << ScriptErrorString(err); + } + } + s.clear(); + s << OP_0 << OP_1; + ASSERT_TRUE(!VerifyScript(s, a_or_b, flags, MutableTransactionSignatureChecker(&txTo[1], 0, amount), consensusBranchId, &err)); + ASSERT_TRUE(err == SCRIPT_ERR_SIG_DER) << ScriptErrorString(err); + + + for (int i = 0; i < 4; i++) + for (int j = 0; j < 4; j++) + { + keys.assign(1,key[i]); + keys.push_back(key[j]); + s = sign_multisig(escrow, keys, txTo[2], 0, consensusBranchId); + if (i < j && i < 3 && j < 3) + { + ASSERT_TRUE(VerifyScript(s, escrow, flags, MutableTransactionSignatureChecker(&txTo[2], 0, amount), consensusBranchId, &err)) << strprintf("escrow 1: %d %d", i, j); + ASSERT_TRUE(err == SCRIPT_ERR_OK) << ScriptErrorString(err); + } + else + { + ASSERT_TRUE(!VerifyScript(s, escrow, flags, MutableTransactionSignatureChecker(&txTo[2], 0, amount), consensusBranchId, &err)) << strprintf("escrow 2: %d %d", i, j); + ASSERT_TRUE(err == SCRIPT_ERR_EVAL_FALSE) << ScriptErrorString(err); + } + } + + + } + } + + TEST(TestMultiSigTests , multisig_Sign) { + // Parameterized testing over consensus branch ids + for ( int idx = Consensus::BASE_SPROUT; idx != Consensus::MAX_NETWORK_UPGRADES; idx++ ) { + + Consensus::UpgradeIndex sample = static_cast(idx); + uint32_t consensusBranchId = NetworkUpgradeInfo[sample].nBranchId; + + // Test SignSignature() (and therefore the version of Solver() that signs transactions) + CBasicKeyStore keystore; + CKey key[4]; + for (int i = 0; i < 4; i++) + { + key[i].MakeNewKey(true); + keystore.AddKey(key[i]); + } + + CScript a_and_b; + a_and_b << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG; + + CScript a_or_b; + a_or_b << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG; + + CScript escrow; + escrow << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << ToByteVector(key[2].GetPubKey()) << OP_3 << OP_CHECKMULTISIG; + + CMutableTransaction txFrom; // Funding transaction + txFrom.vout.resize(3); + txFrom.vout[0].scriptPubKey = a_and_b; + txFrom.vout[1].scriptPubKey = a_or_b; + txFrom.vout[2].scriptPubKey = escrow; + + CMutableTransaction txTo[3]; // Spending transaction + for (int i = 0; i < 3; i++) + { + txTo[i].vin.resize(1); + txTo[i].vout.resize(1); + txTo[i].vin[0].prevout.n = i; + txTo[i].vin[0].prevout.hash = txFrom.GetHash(); + txTo[i].vout[0].nValue = 1; + } + + for (int i = 0; i < 3; i++) + { + ASSERT_TRUE(SignSignature(keystore, txFrom, txTo[i], 0, SIGHASH_ALL, consensusBranchId)) << strprintf("SignSignature %d", i); + } + + } + } + +} \ No newline at end of file diff --git a/src/test-komodo/test_script_standard_tests.cpp b/src/test-komodo/test_script_standard_tests.cpp new file mode 100644 index 00000000..ea08e017 --- /dev/null +++ b/src/test-komodo/test_script_standard_tests.cpp @@ -0,0 +1,626 @@ +#include +#include "key.h" +#include "keystore.h" +#include "wallet/wallet_ismine.h" +#include "script/script.h" +#include "script/script_error.h" +#include "script/standard.h" +#include "utilstrencodings.h" + +namespace TestScriptStandartTests { + + class TestScriptStandartTests : public ::testing::Test {}; + + inline std::string txnouttypeToString(txnouttype t) + { + std::string res ; + + switch (t) + { + case TX_NONSTANDARD: + res = "TX_NONSTANDARD"; + break; + case TX_NULL_DATA: + res = "TX_NULL_DATA"; + break; + case TX_PUBKEY: + res = "TX_PUBKEY"; + break; + case TX_PUBKEYHASH: + res = "TX_PUBKEYHASH"; + break; + case TX_MULTISIG: + res = "TX_MULTISIG"; + break; + case TX_SCRIPTHASH: + res = "TX_SCRIPTHASH"; + break; + case TX_CRYPTOCONDITION: + res = "TX_CRYPTOCONDITION"; + break; + default: + res = "UNKNOWN"; + } + + return res; + } + + TEST(TestScriptStandartTests, script_standard_Solver_success) { + + CKey keys[3]; + CPubKey pubkeys[3]; + for (int i = 0; i < 3; i++) { + keys[i].MakeNewKey(true); + pubkeys[i] = keys[i].GetPubKey(); + } + + CScript s; + txnouttype whichType; + std::vector > solutions; + + // TX_PUBKEY + s.clear(); + s << ToByteVector(pubkeys[0]) << OP_CHECKSIG; + ASSERT_TRUE(Solver(s, whichType, solutions)); + ASSERT_EQ(whichType, TX_PUBKEY); + ASSERT_EQ(solutions.size(), 1); + ASSERT_TRUE(solutions[0] == ToByteVector(pubkeys[0])); + + // TX_PUBKEYHASH + s.clear(); + s << OP_DUP << OP_HASH160 << ToByteVector(pubkeys[0].GetID()) << OP_EQUALVERIFY << OP_CHECKSIG; + ASSERT_TRUE(Solver(s, whichType, solutions)); + ASSERT_EQ(whichType, TX_PUBKEYHASH); + ASSERT_EQ(solutions.size(), 1); + ASSERT_TRUE(solutions[0] == ToByteVector(pubkeys[0].GetID())); + + // solutions.clear(); + + // TX_SCRIPTHASH + CScript redeemScript(s); // initialize with leftover P2PKH script + s.clear(); + s << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL; + ASSERT_TRUE(Solver(s, whichType, solutions)); + ASSERT_EQ(whichType, TX_SCRIPTHASH); + ASSERT_EQ(solutions.size(), 1); + ASSERT_TRUE(solutions[0] == ToByteVector(CScriptID(redeemScript))); + + // TX_MULTISIG + s.clear(); + s << OP_1 << + ToByteVector(pubkeys[0]) << + ToByteVector(pubkeys[1]) << + OP_2 << OP_CHECKMULTISIG; + ASSERT_TRUE(Solver(s, whichType, solutions)); + ASSERT_EQ(whichType, TX_MULTISIG); + ASSERT_EQ(solutions.size(), 4); + ASSERT_TRUE(solutions[0] == std::vector({1})); + ASSERT_TRUE(solutions[1] == ToByteVector(pubkeys[0])); + ASSERT_TRUE(solutions[2] == ToByteVector(pubkeys[1])); + ASSERT_TRUE(solutions[3] == std::vector({2})); + + s.clear(); + s << OP_2 << + ToByteVector(pubkeys[0]) << + ToByteVector(pubkeys[1]) << + ToByteVector(pubkeys[2]) << + OP_3 << OP_CHECKMULTISIG; + ASSERT_TRUE(Solver(s, whichType, solutions)); + ASSERT_EQ(whichType, TX_MULTISIG); + ASSERT_EQ(solutions.size(), 5); + ASSERT_TRUE(solutions[0] == std::vector({2})); + ASSERT_TRUE(solutions[1] == ToByteVector(pubkeys[0])); + ASSERT_TRUE(solutions[2] == ToByteVector(pubkeys[1])); + ASSERT_TRUE(solutions[3] == ToByteVector(pubkeys[2])); + ASSERT_TRUE(solutions[4] == std::vector({3})); + + // TX_NULL_DATA + s.clear(); + s << OP_RETURN << + std::vector({0}) << + std::vector({75}) << + std::vector({255}); + ASSERT_TRUE(Solver(s, whichType, solutions)); + ASSERT_EQ(whichType, TX_NULL_DATA); + ASSERT_EQ(solutions.size(), 0); + + // TX_NONSTANDARD + s.clear(); + s << OP_9 << OP_ADD << OP_11 << OP_EQUAL; + ASSERT_TRUE(!Solver(s, whichType, solutions)); + ASSERT_EQ(whichType, TX_NONSTANDARD); + + } + + TEST(TestScriptStandartTests, script_standard_Solver_failure) { + CKey key; + CPubKey pubkey; + key.MakeNewKey(true); + pubkey = key.GetPubKey(); + + CScript s; + txnouttype whichType; + std::vector > solutions; + + // TX_PUBKEY with incorrectly sized pubkey + s.clear(); + s << std::vector(30, 0x01) << OP_CHECKSIG; + ASSERT_TRUE(!Solver(s, whichType, solutions)); + + // TX_PUBKEYHASH with incorrectly sized key hash + s.clear(); + s << OP_DUP << OP_HASH160 << ToByteVector(pubkey) << OP_EQUALVERIFY << OP_CHECKSIG; + ASSERT_TRUE(!Solver(s, whichType, solutions)); + + // TX_SCRIPTHASH with incorrectly sized script hash + s.clear(); + s << OP_HASH160 << std::vector(21, 0x01) << OP_EQUAL; + ASSERT_TRUE(!Solver(s, whichType, solutions)); + + // TX_MULTISIG 0/2 + s.clear(); + s << OP_0 << ToByteVector(pubkey) << OP_1 << OP_CHECKMULTISIG; + ASSERT_TRUE(!Solver(s, whichType, solutions)); + + // TX_MULTISIG 2/1 + s.clear(); + s << OP_2 << ToByteVector(pubkey) << OP_1 << OP_CHECKMULTISIG; + ASSERT_TRUE(!Solver(s, whichType, solutions)); + + // TX_MULTISIG n = 2 with 1 pubkey + s.clear(); + s << OP_1 << ToByteVector(pubkey) << OP_2 << OP_CHECKMULTISIG; + ASSERT_TRUE(!Solver(s, whichType, solutions)); + + // TX_MULTISIG n = 1 with 0 pubkeys + s.clear(); + s << OP_1 << OP_1 << OP_CHECKMULTISIG; + ASSERT_TRUE(!Solver(s, whichType, solutions)); + + // TX_NULL_DATA with other opcodes + s.clear(); + s << OP_RETURN << std::vector({75}) << OP_ADD; + ASSERT_TRUE(!Solver(s, whichType, solutions)); + + /* witness tests are absent, bcz Komodo doesn't support witness */ + } + + TEST(TestScriptStandartTests, script_standard_ExtractDestination) { + + CKey key; + CPubKey pubkey; + key.MakeNewKey(true); + pubkey = key.GetPubKey(); + + CScript s; + CTxDestination address; + + // TX_PUBKEY + s.clear(); + s << ToByteVector(pubkey) << OP_CHECKSIG; + ASSERT_TRUE(ExtractDestination(s, address)); + ASSERT_TRUE(boost::get(&address) && + *boost::get(&address) == pubkey.GetID()); + + // TX_PUBKEYHASH + s.clear(); + s << OP_DUP << OP_HASH160 << ToByteVector(pubkey.GetID()) << OP_EQUALVERIFY << OP_CHECKSIG; + ASSERT_TRUE(ExtractDestination(s, address)); + ASSERT_TRUE(boost::get(&address) && + *boost::get(&address) == pubkey.GetID()); + + // TX_SCRIPTHASH + CScript redeemScript(s); // initialize with leftover P2PKH script + s.clear(); + s << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL; + ASSERT_TRUE(ExtractDestination(s, address)); + ASSERT_TRUE(boost::get(&address) && + *boost::get(&address) == CScriptID(redeemScript)); + + // TX_MULTISIG + s.clear(); + s << OP_1 << ToByteVector(pubkey) << OP_1 << OP_CHECKMULTISIG; + ASSERT_TRUE(!ExtractDestination(s, address)); + + // TX_NULL_DATA + s.clear(); + s << OP_RETURN << std::vector({75}); + ASSERT_TRUE(!ExtractDestination(s, address)); + } + + TEST(TestScriptStandartTests, script_standard_ExtractDestinations) { + + CKey keys[3]; + CPubKey pubkeys[3]; + for (int i = 0; i < 3; i++) { + keys[i].MakeNewKey(true); + pubkeys[i] = keys[i].GetPubKey(); + } + + CScript s; + txnouttype whichType; + std::vector addresses; + int nRequired; + + // TX_PUBKEY + s.clear(); + s << ToByteVector(pubkeys[0]) << OP_CHECKSIG; + ASSERT_TRUE(ExtractDestinations(s, whichType, addresses, nRequired)); + ASSERT_EQ(whichType, TX_PUBKEY); + ASSERT_EQ(addresses.size(), 1); + ASSERT_EQ(nRequired, 1); + ASSERT_TRUE(boost::get(&addresses[0]) && + *boost::get(&addresses[0]) == pubkeys[0].GetID()); + + // TX_PUBKEYHASH + s.clear(); + s << OP_DUP << OP_HASH160 << ToByteVector(pubkeys[0].GetID()) << OP_EQUALVERIFY << OP_CHECKSIG; + ASSERT_TRUE(ExtractDestinations(s, whichType, addresses, nRequired)); + ASSERT_EQ(whichType, TX_PUBKEYHASH); + ASSERT_EQ(addresses.size(), 1); + ASSERT_EQ(nRequired, 1); + ASSERT_TRUE(boost::get(&addresses[0]) && + *boost::get(&addresses[0]) == pubkeys[0].GetID()); + + // TX_SCRIPTHASH + CScript redeemScript(s); // initialize with leftover P2PKH script + s.clear(); + s << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL; + ASSERT_TRUE(ExtractDestinations(s, whichType, addresses, nRequired)); + ASSERT_EQ(whichType, TX_SCRIPTHASH); + ASSERT_EQ(addresses.size(), 1); + ASSERT_EQ(nRequired, 1); + ASSERT_TRUE(boost::get(&addresses[0]) && + *boost::get(&addresses[0]) == CScriptID(redeemScript)); + + // TX_MULTISIG + s.clear(); + s << OP_2 << + ToByteVector(pubkeys[0]) << + ToByteVector(pubkeys[1]) << + OP_2 << OP_CHECKMULTISIG; + ASSERT_TRUE(ExtractDestinations(s, whichType, addresses, nRequired)); + ASSERT_EQ(whichType, TX_MULTISIG); + ASSERT_EQ(addresses.size(), 2); + ASSERT_EQ(nRequired, 2); + ASSERT_TRUE(boost::get(&addresses[0]) && + *boost::get(&addresses[0]) == pubkeys[0].GetID()); + ASSERT_TRUE(boost::get(&addresses[1]) && + *boost::get(&addresses[1]) == pubkeys[1].GetID()); + + // TX_NULL_DATA + s.clear(); + s << OP_RETURN << std::vector({75}); + ASSERT_TRUE(!ExtractDestinations(s, whichType, addresses, nRequired)); + + } + + TEST(TestScriptStandartTests, script_standard_GetScriptFor_) { + + CKey keys[3]; + CPubKey pubkeys[3]; + for (int i = 0; i < 3; i++) { + keys[i].MakeNewKey(true); + pubkeys[i] = keys[i].GetPubKey(); + } + + CScript expected, result; + + // CKeyID + expected.clear(); + expected << OP_DUP << OP_HASH160 << ToByteVector(pubkeys[0].GetID()) << OP_EQUALVERIFY << OP_CHECKSIG; + result = GetScriptForDestination(pubkeys[0].GetID()); + ASSERT_TRUE(result == expected); + + // CScriptID + CScript redeemScript(result); + expected.clear(); + expected << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL; + result = GetScriptForDestination(CScriptID(redeemScript)); + ASSERT_TRUE(result == expected); + + // CNoDestination + expected.clear(); + result = GetScriptForDestination(CNoDestination()); + ASSERT_TRUE(result == expected); + + // GetScriptForRawPubKey + // expected.clear(); + // expected << ToByteVector(pubkeys[0]) << OP_CHECKSIG; + // result = GetScriptForRawPubKey(pubkeys[0]); + // ASSERT_TRUE(result == expected); + + // GetScriptForMultisig + expected.clear(); + expected << OP_2 << + ToByteVector(pubkeys[0]) << + ToByteVector(pubkeys[1]) << + ToByteVector(pubkeys[2]) << + OP_3 << OP_CHECKMULTISIG; + result = GetScriptForMultisig(2, std::vector(pubkeys, pubkeys + 3)); + ASSERT_TRUE(result == expected); + } + + TEST(TestScriptStandartTests, script_standard_IsMine) { + + CKey keys[2]; + CPubKey pubkeys[2]; + for (int i = 0; i < 2; i++) { + keys[i].MakeNewKey(true); + pubkeys[i] = keys[i].GetPubKey(); + } + + CKey uncompressedKey; + uncompressedKey.MakeNewKey(false); + CPubKey uncompressedPubkey = uncompressedKey.GetPubKey(); + + CScript scriptPubKey; + isminetype result; + + // P2PK compressed + { + CBasicKeyStore keystore; + scriptPubKey.clear(); + scriptPubKey << ToByteVector(pubkeys[0]) << OP_CHECKSIG; + + // Keystore does not have key + result = IsMine(keystore, scriptPubKey); + ASSERT_EQ(result, ISMINE_NO); + + // Keystore has key + keystore.AddKey(keys[0]); + result = IsMine(keystore, scriptPubKey); + ASSERT_EQ(result, ISMINE_SPENDABLE); + } + + // P2PK uncompressed + { + CBasicKeyStore keystore; + scriptPubKey.clear(); + scriptPubKey << ToByteVector(uncompressedPubkey) << OP_CHECKSIG; + + // Keystore does not have key + result = IsMine(keystore, scriptPubKey); + ASSERT_EQ(result, ISMINE_NO); + + // Keystore has key + keystore.AddKey(uncompressedKey); + result = IsMine(keystore, scriptPubKey); + ASSERT_EQ(result, ISMINE_SPENDABLE); + } + + // P2PKH compressed + { + CBasicKeyStore keystore; + scriptPubKey.clear(); + scriptPubKey << OP_DUP << OP_HASH160 << ToByteVector(pubkeys[0].GetID()) << OP_EQUALVERIFY << OP_CHECKSIG; + + // Keystore does not have key + result = IsMine(keystore, scriptPubKey); + ASSERT_EQ(result, ISMINE_NO); + + // Keystore has key + keystore.AddKey(keys[0]); + result = IsMine(keystore, scriptPubKey); + ASSERT_EQ(result, ISMINE_SPENDABLE); + } + + // P2PKH uncompressed + { + CBasicKeyStore keystore; + scriptPubKey.clear(); + scriptPubKey << OP_DUP << OP_HASH160 << ToByteVector(uncompressedPubkey.GetID()) << OP_EQUALVERIFY << OP_CHECKSIG; + + // Keystore does not have key + result = IsMine(keystore, scriptPubKey); + ASSERT_EQ(result, ISMINE_NO); + + // Keystore has key + keystore.AddKey(uncompressedKey); + result = IsMine(keystore, scriptPubKey); + ASSERT_EQ(result, ISMINE_SPENDABLE); + } + + // P2SH + { + CBasicKeyStore keystore; + + CScript redeemScript; + redeemScript << OP_DUP << OP_HASH160 << ToByteVector(pubkeys[0].GetID()) << OP_EQUALVERIFY << OP_CHECKSIG; + + scriptPubKey.clear(); + scriptPubKey << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL; + + // Keystore does not have redeemScript or key + result = IsMine(keystore, scriptPubKey); + ASSERT_EQ(result, ISMINE_NO); + + // Keystore has redeemScript but no key + keystore.AddCScript(redeemScript); + result = IsMine(keystore, scriptPubKey); + ASSERT_EQ(result, ISMINE_NO); + + // Keystore has redeemScript and key + keystore.AddKey(keys[0]); + result = IsMine(keystore, scriptPubKey); + ASSERT_EQ(result, ISMINE_SPENDABLE); + } + + // scriptPubKey multisig + { + CBasicKeyStore keystore; + + scriptPubKey.clear(); + scriptPubKey << OP_2 << + ToByteVector(uncompressedPubkey) << + ToByteVector(pubkeys[1]) << + OP_2 << OP_CHECKMULTISIG; + + // Keystore does not have any keys + result = IsMine(keystore, scriptPubKey); + ASSERT_EQ(result, ISMINE_NO); + + // Keystore has 1/2 keys + keystore.AddKey(uncompressedKey); + + result = IsMine(keystore, scriptPubKey); + ASSERT_EQ(result, ISMINE_NO); + + // Keystore has 2/2 keys + keystore.AddKey(keys[1]); + + result = IsMine(keystore, scriptPubKey); + ASSERT_EQ(result, ISMINE_NO); + + // Keystore has 2/2 keys and the script + keystore.AddCScript(scriptPubKey); + + result = IsMine(keystore, scriptPubKey); + ASSERT_EQ(result, ISMINE_NO); + } + + // P2SH multisig + { + CBasicKeyStore keystore; + keystore.AddKey(uncompressedKey); + keystore.AddKey(keys[1]); + + CScript redeemScript; + redeemScript << OP_2 << + ToByteVector(uncompressedPubkey) << + ToByteVector(pubkeys[1]) << + OP_2 << OP_CHECKMULTISIG; + + scriptPubKey.clear(); + scriptPubKey << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL; + + // Keystore has no redeemScript + result = IsMine(keystore, scriptPubKey); + ASSERT_EQ(result, ISMINE_NO); + + // Keystore has redeemScript + keystore.AddCScript(redeemScript); + result = IsMine(keystore, scriptPubKey); + ASSERT_EQ(result, ISMINE_SPENDABLE); + } + + // OP_RETURN + { + CBasicKeyStore keystore; + keystore.AddKey(keys[0]); + + scriptPubKey.clear(); + scriptPubKey << OP_RETURN << ToByteVector(pubkeys[0]); + + result = IsMine(keystore, scriptPubKey); + ASSERT_EQ(result, ISMINE_NO); + } + + // Nonstandard + { + CBasicKeyStore keystore; + keystore.AddKey(keys[0]); + + scriptPubKey.clear(); + scriptPubKey << OP_9 << OP_ADD << OP_11 << OP_EQUAL; + + result = IsMine(keystore, scriptPubKey); + ASSERT_EQ(result, ISMINE_NO); + } + + } + + TEST(TestScriptStandartTests, script_standard_Malpill) { + + static const std::string log_tab = " "; + + /* testing against non-minimal forms of PUSHDATA in P2PK/P2PKH (by Decker) */ + + CKey key; CPubKey pubkey; + txnouttype whichType; + std::vector > solutions; + + key.MakeNewKey(true); // true - compressed pubkey, false - uncompressed + pubkey = key.GetPubKey(); + + ASSERT_TRUE(pubkey.size() == 0x21 || pubkey.size() == 0x41); + + std::vector vScriptPubKeys = { + CScript() << ToByteVector(pubkey) << OP_CHECKSIG, // 0x21 pubkey OP_CHECKSIG (the shortest form, typical) + CScript() << OP_DUP << OP_HASH160 << ToByteVector(pubkey.GetID()) << OP_EQUALVERIFY << OP_CHECKSIG, + }; + + CScript modifiedScript; std::vector modData; + + // PUSHDATA1(0x21) pubkey OP_CHECKSIG (one byte longer) + modifiedScript = vScriptPubKeys[0]; + modData = {OP_PUSHDATA1, (unsigned char )pubkey.size()}; + modifiedScript.erase(modifiedScript.begin()); modifiedScript.insert(modifiedScript.begin(), modData.begin(), modData.end()); + vScriptPubKeys.push_back(modifiedScript); + + // PUSHDATA2(0x21) pubkey OP_CHECKSIG (two bytes longer) + modifiedScript = vScriptPubKeys[0]; + modData = {OP_PUSHDATA2, (unsigned char )pubkey.size(), 0x00}; + modifiedScript.erase(modifiedScript.begin()); modifiedScript.insert(modifiedScript.begin(), modData.begin(), modData.end()); + vScriptPubKeys.push_back(modifiedScript); + + // PUSHDATA4(0x21) pubkey OP_CHECKSIG (four bytes longer) + modifiedScript = vScriptPubKeys[0]; + modData = {OP_PUSHDATA4, (unsigned char )pubkey.size(), 0x00, 0x00, 0x00}; + modifiedScript.erase(modifiedScript.begin()); modifiedScript.insert(modifiedScript.begin(), modData.begin(), modData.end()); + vScriptPubKeys.push_back(modifiedScript); + + // same forms for p2kh + + modifiedScript = vScriptPubKeys[1]; + modData = {OP_PUSHDATA1, 0x14}; + modifiedScript.erase(modifiedScript.begin() + 2); modifiedScript.insert(modifiedScript.begin() + 2, modData.begin(), modData.end()); + vScriptPubKeys.push_back(modifiedScript); + + modifiedScript = vScriptPubKeys[1]; + modData = {OP_PUSHDATA2, 0x14, 0x00}; + modifiedScript.erase(modifiedScript.begin() + 2); modifiedScript.insert(modifiedScript.begin() + 2, modData.begin(), modData.end()); + vScriptPubKeys.push_back(modifiedScript); + + modifiedScript = vScriptPubKeys[1]; + modData = {OP_PUSHDATA4, 0x14, 0x00, 0x00, 0x00}; + modifiedScript.erase(modifiedScript.begin() + 2); modifiedScript.insert(modifiedScript.begin() + 2, modData.begin(), modData.end()); + vScriptPubKeys.push_back(modifiedScript); + + int test_count = 0; + for(const auto &s : vScriptPubKeys) { + solutions.clear(); + if (test_count < 2) + EXPECT_TRUE(Solver(s, whichType, solutions)) << "Failed on Test #" << test_count; + else + EXPECT_FALSE(Solver(s, whichType, solutions)) << "Failed on Test #" << test_count; + + /* std::cerr << log_tab << "Test #" << test_count << ":" << std::endl; + std::cerr << log_tab << "scriptPubKey [asm]: " << s.ToString() << std::endl; + std::cerr << log_tab << "scriptPubKey [hex]: " << HexStr(s.begin(), s.end()) << std::endl; + std::cerr << log_tab << "solutions.size(): " << solutions.size() << std::endl; + std::cerr << log_tab << "whichType: " << txnouttypeToString(whichType) << std::endl; */ + + switch (test_count) + { + case 0: + ASSERT_EQ(whichType, TX_PUBKEY); + ASSERT_EQ(solutions.size(), 1); + ASSERT_TRUE(solutions[0] == ToByteVector(pubkey)); + break; + case 1: + ASSERT_EQ(whichType, TX_PUBKEYHASH); + ASSERT_EQ(solutions.size(), 1); + ASSERT_TRUE(solutions[0] == ToByteVector(pubkey.GetID())); + break; + default: + EXPECT_EQ(solutions.size(), 0); + EXPECT_EQ(whichType, TX_NONSTANDARD); + break; + } + + test_count++; + } + } + +} \ No newline at end of file diff --git a/src/test-komodo/test_sha256_crypto.cpp b/src/test-komodo/test_sha256_crypto.cpp new file mode 100644 index 00000000..5424c3fe --- /dev/null +++ b/src/test-komodo/test_sha256_crypto.cpp @@ -0,0 +1,175 @@ +#include +#include "crypto/sha256.h" +#include "uint256.h" +#include +#include "random.h" +#include "utilstrencodings.h" +#include "hash.h" + +namespace TestSHA256Crypto { + + class TestSHA256Crypto : public ::testing::Test {}; + static const std::string log_tab = " "; + + template + void TestVector(const Hasher &h, const In &in, const Out &out) { + Out hash; + ASSERT_TRUE(out.size() == h.OUTPUT_SIZE); + hash.resize(out.size()); + { + // Test that writing the whole input string at once works. + Hasher(h).Write((unsigned char*)&in[0], in.size()).Finalize(&hash[0]); + ASSERT_TRUE(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 = insecure_rand() % ((in.size() - pos + 1) / 2 + 1); + hasher.Write((unsigned char*)&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((unsigned char*)&in[pos], in.size() - pos).Finalize(&hash[0]); + ASSERT_TRUE(hash == out); + } + } + hasher.Finalize(&hash[0]); + ASSERT_TRUE(hash == out); + } + } + + void TestSHA256(const std::string &in, const std::string &hexout) { TestVector(CSHA256(), in, ParseHex(hexout));} + + std::string LongTestString(void) { + std::string ret; + for (int i=0; i<200000; i++) { + ret += (unsigned char)(i); + ret += (unsigned char)(i >> 4); + ret += (unsigned char)(i >> 8); + ret += (unsigned char)(i >> 12); + ret += (unsigned char)(i >> 16); + } + return ret; + } + + const std::string test1 = LongTestString(); + + TEST(TestSHA256Crypto, compression) // sha256compress_tests.cpp + { + { + std::cerr << log_tab << "Using \"" << SHA256AutoDetect() << "\" SHA256 implementation ..." << std::endl; + + unsigned char preimage[64] = {}; + CSHA256 hasher; + hasher.Write(&preimage[0], 64); + + uint256 digest; + + hasher.FinalizeNoPadding(digest.begin()); + + ASSERT_TRUE(digest == uint256S("d8a93718eaf9feba4362d2c091d4e58ccabe9f779957336269b4b917be9856da")) << digest.GetHex(); + } + + { + unsigned char preimage[63] = {}; + CSHA256 hasher; + hasher.Write(&preimage[0], 63); + uint256 digest; + ASSERT_THROW(hasher.FinalizeNoPadding(digest.begin()), std::length_error); + } + + { + unsigned char preimage[65] = {}; + CSHA256 hasher; + hasher.Write(&preimage[0], 65); + uint256 digest; + ASSERT_THROW(hasher.FinalizeNoPadding(digest.begin()), std::length_error); + } + + { + unsigned char n = 0x00; + CSHA256 hasher; + for (size_t i = 0; i < 64; i++) { + hasher.Write(&n, 1); + } + uint256 digest; + + hasher.FinalizeNoPadding(digest.begin()); + + ASSERT_TRUE(digest == uint256S("d8a93718eaf9feba4362d2c091d4e58ccabe9f779957336269b4b917be9856da")) << digest.GetHex(); + } + + { + unsigned char preimage[64] = { 'a', 'b', 'c', 'd', + 'a', 'b', 'c', 'd', + 'a', 'b', 'c', 'd', + 'a', 'b', 'c', 'd', + 'a', 'b', 'c', 'd', + 'a', 'b', 'c', 'd', + 'a', 'b', 'c', 'd', + 'a', 'b', 'c', 'd', + 'a', 'b', 'c', 'd', + 'a', 'b', 'c', 'd', + 'a', 'b', 'c', 'd', + 'a', 'b', 'c', 'd', + 'a', 'b', 'c', 'd', + 'a', 'b', 'c', 'd', + 'a', 'b', 'c', 'd', + 'a', 'b', 'c', 'd' + }; + CSHA256 hasher; + hasher.Write(&preimage[0], 64); + + uint256 digest; + + hasher.FinalizeNoPadding(digest.begin()); + + ASSERT_TRUE(digest == uint256S("da70ec41879e36b000281733d4deb27ddf41e8e343a38f2fabbd2d8611987d86")) << digest.GetHex(); + + } + } + + TEST(TestSHA256Crypto, sha256_testvectors) // crypto_tests.cpp + { + 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"); + TestSHA256("The quick brown fox jumps over the lazy dog", + "d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592"); + } + + TEST(TestSHA256Crypto, sha256d64) + { + for (int i = 0; i <= 32; ++i) { + unsigned char in[64 * 32]; + unsigned char out1[32 * 32], out2[32 * 32]; + for (int j = 0; j < 64 * i; ++j) { + in[j] = (unsigned char) insecure_rand(); // InsecureRandBits(8); + } + for (int j = 0; j < i; ++j) { + CHash256().Write(in + 64 * j, 64).Finalize(out1 + 32 * j); // hasher class for Bitcoin's 256-bit hash (double SHA-256) + } + SHA256D64(out2, in, i); + ASSERT_TRUE(memcmp(out1, out2, 32 * i) == 0); + } + } + +} \ No newline at end of file diff --git a/src/txdb.cpp b/src/txdb.cpp index 6032e941..c606d966 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -4,7 +4,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. /****************************************************************************** - * Copyright © 2014-2019 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -28,6 +28,9 @@ #include "uint256.h" #include "core_io.h" +#include "ui_interface.h" +#include "init.h" + #include #include @@ -693,12 +696,29 @@ bool CBlockTreeDB::LoadBlockIndexGuts() boost::scoped_ptr pcursor(NewIterator()); pcursor->Seek(make_pair(DB_BLOCK_INDEX, uint256())); + int64_t count = 0; int reportDone = 0; + uiInterface.ShowProgress(_("Loading guts..."), 0, false); // Load mapBlockIndex while (pcursor->Valid()) { boost::this_thread::interruption_point(); + if (ShutdownRequested()) return false; + std::pair key; + if (pcursor->GetKey(key) && key.first == DB_BLOCK_INDEX) { + + if (count++ % 256 == 0) { + uint32_t high = 0x100 * *key.second.begin() + *(key.second.begin() + 1); + int percentageDone = (int)(high * 100.0 / 65536.0 + 0.5); + uiInterface.ShowProgress(_("Loading guts..."), percentageDone, false); + if (reportDone < percentageDone/10) { + // report max. every 10% step + LogPrintf("[%d%%]...", percentageDone); /* Continued */ + reportDone = percentageDone/10; + } + } + CDiskBlockIndex diskindex; if (pcursor->GetValue(diskindex)) { // Construct block index object @@ -745,5 +765,8 @@ bool CBlockTreeDB::LoadBlockIndexGuts() } } + uiInterface.ShowProgress("", 100, false); + LogPrintf("[%s].\n", ShutdownRequested() ? "CANCELLED" : "DONE"); + return true; } diff --git a/src/txmempool.cpp b/src/txmempool.cpp index f1e43c56..a1294fb8 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -4,7 +4,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. /****************************************************************************** - * Copyright © 2014-2019 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -521,8 +521,20 @@ void CTxMemPool::removeExpired(unsigned int nBlockHeight) { const CTransaction& tx = it->GetTx(); tipindex = chainActive.LastTip(); - if (IsExpiredTx(tx, nBlockHeight) || (ASSETCHAINS_SYMBOL[0] == 0 && tipindex != 0 && komodo_validate_interest(tx,tipindex->GetHeight()+1,tipindex->GetMedianTimePast() + 777,0)) < 0) + + /* cmptime = chainActive.LastTip()->GetMedianTimePast() + 777 - here for interest validation, inside + CTxMemPool::removeExpired. need to test, may be here better to validate against pindexNew->nTime. + In ConnectBlock we have a condition for each tx like komodo_validate_interest(..., block.nTime), so + blocks mined with such txes will be valid. Mean, may be chainActive.LastTip()->GetMedianTimePast() + 777 + is "too earlier" condition. [nBlockHeight should be equal tipindex->GetHeight()+1 here] + */ + + // if (IsExpiredTx(tx, nBlockHeight) || (ASSETCHAINS_SYMBOL[0] == 0 && tipindex != 0 && komodo_validate_interest(tx,tipindex->GetHeight()+1,tipindex->GetMedianTimePast() + 777,0)) < 0) + bool fInterestNotValidated = ASSETCHAINS_SYMBOL[0] == 0 && tipindex != 0 && komodo_validate_interest(tx,tipindex->GetHeight()+1,tipindex->GetMedianTimePast() + 777,0) < 0; + if (IsExpiredTx(tx, nBlockHeight) || fInterestNotValidated) { + if (fInterestNotValidated && tipindex != 0) + LogPrintf("Removing interest violate txid.%s nHeight.%d nTime.%u vs locktime.%u\n",tx.GetHash().ToString(),tipindex->GetHeight()+1,tipindex->GetMedianTimePast() + 777,tx.nLockTime); transactionsToRemove.push_back(tx); } } diff --git a/src/txmempool.h b/src/txmempool.h index b37e668a..b73ff4b3 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -4,7 +4,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. /****************************************************************************** - * Copyright © 2014-2019 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 4b502c77..61effb84 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -4524,7 +4524,7 @@ UniValue z_sendmany(const UniValue& params, bool fHelp, const CPubKey& mypk) LOCK2(cs_main, pwalletMain->cs_wallet); - THROW_IF_SYNCING(KOMODO_INSYNC); + //THROW_IF_SYNCING(KOMODO_INSYNC); // Check that the from address is valid. auto fromaddress = params[0].get_str(); @@ -4836,7 +4836,7 @@ UniValue z_shieldcoinbase(const UniValue& params, bool fHelp, const CPubKey& myp LOCK2(cs_main, pwalletMain->cs_wallet); - THROW_IF_SYNCING(KOMODO_INSYNC); + //THROW_IF_SYNCING(KOMODO_INSYNC); // Validate the from address auto fromaddress = params[0].get_str(); @@ -5098,7 +5098,7 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp, const CPubKey& myp LOCK2(cs_main, pwalletMain->cs_wallet); - THROW_IF_SYNCING(KOMODO_INSYNC); + //THROW_IF_SYNCING(KOMODO_INSYNC); bool useAnyUTXO = false; bool useAnySprout = false; diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 6ca417a1..49006fef 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -4311,13 +4311,14 @@ CAmount CWallet::GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarge } */ -void komodo_prefetch(FILE *fp); +//void komodo_prefetch(FILE *fp); DBErrors CWallet::LoadWallet(bool& fFirstRunRet) { if (!fFileBacked) return DB_LOAD_OK; fFirstRunRet = false; + /* if ( 0 ) // doesnt help { LogPrintf("loading wallet %s %u\n",strWalletFile.c_str(),(uint32_t)time(NULL)); @@ -4328,6 +4329,7 @@ DBErrors CWallet::LoadWallet(bool& fFirstRunRet) fclose(fp); } } + */ //LogPrintf("prefetched wallet %s %u\n",strWalletFile.c_str(),(uint32_t)time(NULL)); DBErrors nLoadWalletRet = CWalletDB(strWalletFile,"cr+").LoadWallet(this); //LogPrintf("loaded wallet %s %u\n",strWalletFile.c_str(),(uint32_t)time(NULL)); diff --git a/src/wallet/wallet_ismine.cpp b/src/wallet/wallet_ismine.cpp index 14c63e93..3a1513cb 100644 --- a/src/wallet/wallet_ismine.cpp +++ b/src/wallet/wallet_ismine.cpp @@ -4,7 +4,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. /****************************************************************************** - * Copyright © 2014-2019 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * @@ -44,13 +44,28 @@ unsigned int HaveKeys(const vector& pubkeys, const CKeyStore& keystore) return nResult; } -isminetype IsMine(const CKeyStore &keystore, const CTxDestination& dest) +namespace { + +/** + * This is an enum that tracks the execution context of a script, similar to + * SigVersion in script/interpreter. It is separate however because we want to + * distinguish between top-level scriptPubKey execution and P2SH redeemScript + * execution (a distinction that has no impact on consensus rules). + */ +enum class IsMineSigVersion { - CScript script = GetScriptForDestination(dest); - return IsMine(keystore, script); + TOP = 0, //! scriptPubKey execution + P2SH = 1, //! P2SH redeemScript +}; + +bool PermitsUncompressed(IsMineSigVersion sigversion) +{ + return sigversion == IsMineSigVersion::TOP || sigversion == IsMineSigVersion::P2SH; } -isminetype IsMine(const CKeyStore &keystore, const CScript& _scriptPubKey) +typedef vector valtype; + +isminetype IsMineInner(const CKeyStore& keystore, const CScript& _scriptPubKey, IsMineSigVersion sigversion) { vector vSolutions; txnouttype whichType; @@ -102,7 +117,7 @@ isminetype IsMine(const CKeyStore &keystore, const CScript& _scriptPubKey) CScriptID scriptID = CScriptID(uint160(vSolutions[0])); CScript subscript; if (keystore.GetCScript(scriptID, subscript)) { - isminetype ret = IsMine(keystore, subscript); + isminetype ret = IsMineInner(keystore, subscript, IsMineSigVersion::P2SH); if (ret == ISMINE_SPENDABLE) return ret; } @@ -110,6 +125,8 @@ isminetype IsMine(const CKeyStore &keystore, const CScript& _scriptPubKey) } case TX_MULTISIG: { + // Never treat bare multisig outputs as ours (they can still be made watchonly-though) + if (sigversion == IsMineSigVersion::TOP) break; // Only consider transactions "mine" if we own ALL the // keys involved. Multi-signature transactions that are // partially owned (somebody else has a key that can spend @@ -126,3 +143,17 @@ isminetype IsMine(const CKeyStore &keystore, const CScript& _scriptPubKey) return ISMINE_WATCH_ONLY; return ISMINE_NO; } + + +} // namespace + +isminetype IsMine(const CKeyStore& keystore, const CScript& scriptPubKey) +{ + return IsMineInner(keystore, scriptPubKey, IsMineSigVersion::TOP); +} + +isminetype IsMine(const CKeyStore& keystore, const CTxDestination& dest) +{ + CScript script = GetScriptForDestination(dest); + return IsMine(keystore, script); +} \ No newline at end of file diff --git a/src/wallet/wallet_ismine.h b/src/wallet/wallet_ismine.h index 8d6d2b90..409def1e 100644 --- a/src/wallet/wallet_ismine.h +++ b/src/wallet/wallet_ismine.h @@ -4,7 +4,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. /****************************************************************************** - * Copyright © 2014-2019 The SuperNET Developers. * + * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * diff --git a/zcutil/build-mac.sh b/zcutil/build-mac.sh index f2de05dc..a4199bd0 100755 --- a/zcutil/build-mac.sh +++ b/zcutil/build-mac.sh @@ -59,7 +59,7 @@ CPPFLAGS="-I$PREFIX/include -arch x86_64" LDFLAGS="-L$PREFIX/lib -arch x86_64 -W # step will cause an error and static Qt plugins will not be linked. CXXFLAGS='-arch x86_64 -I/usr/local/Cellar/gcc@6/6.5.0_2/include/c++/6.5.0 '"-I${PREFIX}/include"' -fwrapv -fno-strict-aliasing -g0 -O2 -Wl,-undefined -Wl,dynamic_lookup' \ -./configure --prefix="${PREFIX}" --disable-bip70 --with-gui=qt5 "$HARDENING_ARG" "$LCOV_ARG" +./configure --prefix="${PREFIX}" --disable-bip70 --with-gui=qt5 --enable-tests=no "$HARDENING_ARG" "$LCOV_ARG" # here we need a small hacks, bcz QT_QPA_PLATFORM_COCOA and QT_STATICPLUGIN still have # incorect values after configure (TODO: fix it) diff --git a/zcutil/build-win.sh b/zcutil/build-win.sh index cb81b53a..55930bf3 100755 --- a/zcutil/build-win.sh +++ b/zcutil/build-win.sh @@ -11,15 +11,13 @@ cd "$(dirname "$(readlink -f "$0")")/.." cd depends/ && make HOST=$HOST V=1 -j$(nproc) && cd ../ -### don't used here, bcz we have cclib static built-in in libbitcoin_server_a -#WD=$PWD -#cd src/cc -#echo $PWD -#./makecustom -#cd $WD - ./autogen.sh -CONFIG_SITE=$PWD/depends/x86_64-w64-mingw32/share/config.site CXXFLAGS="-DPTW32_STATIC_LIB -DCURL_STATICLIB -DCURVE_ALT_BN128 -fopenmp -pthread -g0 -O2" ./configure --prefix="${PREFIX}" --host=x86_64-w64-mingw32 --enable-static --disable-shared --with-gui=qt5 --disable-bip70 + +CONFIG_SITE=$PWD/depends/x86_64-w64-mingw32/share/config.site \ + CXXFLAGS="-DPTW32_STATIC_LIB -DCURL_STATICLIB -DCURVE_ALT_BN128 -fopenmp -pthread -g0 -O2" \ + ./configure --prefix="${PREFIX}" --host=x86_64-w64-mingw32 --enable-static --disable-shared \ + --with-gui=qt5 --disable-bip70 --enable-tests=no + sed -i 's/-lboost_system-mt /-lboost_system-mt-s /' configure cd src/ -CC="${CC}" CXX="${CXX}" make V=1 -j$(nproc) +CC="${CC}" CXX="${CXX}" make "$@" V=1