From 29575044675b2c1fd5d1309a4d55bbead8b8c494 Mon Sep 17 00:00:00 2001 From: DeckerSU Date: Thu, 12 Mar 2020 02:16:24 +0300 Subject: [PATCH 01/40] prevent spamming in debug.log with big hex txes in case of expire --- src/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 44e0fd41..cb550a42 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1264,9 +1264,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"); } } From 1fbf1c449ae321162e61f76fd7d5786e7383a682 Mon Sep 17 00:00:00 2001 From: DeckerSU Date: Thu, 12 Mar 2020 05:09:09 +0300 Subject: [PATCH 02/40] [test] proper removing of txes that violates interest validation from mempool In CreateNewBlock of miner https://github.com/KomodoPlatform/komodo/blob/master/src/miner.cpp#L331 we have a condition that prevents miners to include certain txes in block if tx violates komodo_validate_interest check. so, if such txes will exist in mempool and in some reason they was not miner earlier, if they have nExpiryHeight = 0 - they NEVER will be included in block by miners. Also, code in CTxMemPool::removeExpired that should remove such txes from mempool didn't do it due to mistake. As a result these txes stucks in mempool. No one can mine it, bcz no one can include it in block, and no one get success to remove it from mempool. Look on old code: ``` (ASSETCHAINS_SYMBOL[0] == 0 && tipindex != 0 && komodo_validate_interest(...) ) < 0 ``` But should be: ``` (ASSETCHAINS_SYMBOL[0] == 0 && tipindex != 0 && komodo_validate_interest(...) < 0 ) ``` Bcz we should compare with 0 result of komodo_validate_interest, but we had different behaviour, due to typo. --- src/main.cpp | 9 ++++++++- src/txmempool.cpp | 12 +++++++----- src/txmempool.h | 4 ++-- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index cb550a42..d8f4373d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4321,7 +4321,14 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock * mempool.removeForBlock(pblock->vtx, pindexNew->GetHeight(), txConflicted, !IsInitialBlockDownload()); // Remove transactions that expire at new block height from mempool - mempool.removeExpired(pindexNew->GetHeight()); + mempool.removeExpired(pindexNew->GetHeight(), chainActive.LastTip()->GetMedianTimePast() + 777); + + /* 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. + */ // Update chainActive & related variables. UpdateTip(pindexNew); diff --git a/src/txmempool.cpp b/src/txmempool.cpp index f1e43c56..19a749c6 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 * @@ -511,21 +511,23 @@ void CTxMemPool::removeConflicts(const CTransaction &tx, std::list int32_t komodo_validate_interest(const CTransaction &tx,int32_t txheight,uint32_t nTime,int32_t dispflag); extern char ASSETCHAINS_SYMBOL[]; -void CTxMemPool::removeExpired(unsigned int nBlockHeight) +void CTxMemPool::removeExpired(unsigned int nBlockHeight, unsigned int cmpTime) { - CBlockIndex *tipindex; // Remove expired txs from the mempool LOCK(cs); list transactionsToRemove; for (indexed_transaction_set::const_iterator it = mapTx.begin(); it != mapTx.end(); it++) { 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) + bool fInterestNotValidated = ASSETCHAINS_SYMBOL[0] == 0 && komodo_validate_interest(tx,nBlockHeight,cmpTime,0) < 0; + if (IsExpiredTx(tx, nBlockHeight) || fInterestNotValidated) { + if (fInterestNotValidated) + LogPrint("mempool","Removing interest violate txid.%s nHeight.%d nTime.%u vs locktime.%u\n",tx.GetHash().ToString(),nBlockHeight,cmpTime,tx.nLockTime); transactionsToRemove.push_back(tx); } } + for (const CTransaction& tx : transactionsToRemove) { list removed; remove(tx, removed, true); diff --git a/src/txmempool.h b/src/txmempool.h index b37e668a..89425e9f 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 * @@ -216,7 +216,7 @@ class CTxMemPool 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); + void removeExpired(unsigned int nBlockHeight, unsigned int cmpTime); void removeForBlock(const std::vector& vtx, unsigned int nBlockHeight, std::list& conflicts, bool fCurrentEstimate = true); void removeWithoutBranchId(uint32_t nMemPoolBranchId); From b9ed1d1df67e38e16538d95ac624145dbe99173c Mon Sep 17 00:00:00 2001 From: DeckerSU Date: Thu, 12 Mar 2020 06:55:18 +0300 Subject: [PATCH 03/40] DEFAULT_LIMITFREERELAY: move constant values to a single location in code part of https://github.com/bitcoin/bitcoin/commit/b966aa836a3bc5bfa1314248258308f0026d41bb --- src/init.cpp | 2 +- src/main.cpp | 2 +- src/main.h | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 69d6a0df..ff9aa800 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)); diff --git a/src/main.cpp b/src/main.cpp index d8f4373d..ef8744e4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2039,7 +2039,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"); 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; From 6b1aa27adcb025377432838df0edd436d050ee8a Mon Sep 17 00:00:00 2001 From: DeckerSU Date: Thu, 12 Mar 2020 12:39:24 +0300 Subject: [PATCH 04/40] move few printouts from stderr to debug.log --- src/chainparams.cpp | 8 ++++---- src/init.cpp | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 72734093..0e6de6fd 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -550,14 +550,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 +580,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/init.cpp b/src/init.cpp index ff9aa800..8a635865 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -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 From 71ca44a9b8596a27c5e4eaade3b62f0fc297de61 Mon Sep 17 00:00:00 2001 From: DeckerSU Date: Thu, 12 Mar 2020 19:00:56 +0300 Subject: [PATCH 05/40] vcalc_sha256 -> CSHA256(): to use hardware acceleration, if available --- src/komodo_utils.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/komodo_utils.h b/src/komodo_utils.h index 7417a996..a62a0d63 100644 --- a/src/komodo_utils.h +++ b/src/komodo_utils.h @@ -279,10 +279,16 @@ static inline int32_t sha256_vdone(struct sha256_vstate *md,uint8_t *out) void vcalc_sha256(char deprecated[(256 >> 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 EXPERIMENTAL_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) From 10187591076f5c04cd58ad2271c67b9dacf50f07 Mon Sep 17 00:00:00 2001 From: DeckerSU Date: Sat, 14 Mar 2020 23:17:51 +0300 Subject: [PATCH 06/40] enable build of komodo-cli binary --- src/Makefile.am | 4 +- src/bitcoin-cli-res.rc | 35 ++++ src/bitcoin-cli.cpp | 404 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 441 insertions(+), 2 deletions(-) create mode 100644 src/bitcoin-cli-res.rc create mode 100644 src/bitcoin-cli.cpp diff --git a/src/Makefile.am b/src/Makefile.am index b7745b11..94655ee3 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -112,8 +112,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 = \ diff --git a/src/bitcoin-cli-res.rc b/src/bitcoin-cli-res.rc new file mode 100644 index 00000000..3e46f5a1 --- /dev/null +++ b/src/bitcoin-cli-res.rc @@ -0,0 +1,35 @@ +#include // 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; +} From 885d759bb23f8606d2c914c10e548f56c9a2cb7c Mon Sep 17 00:00:00 2001 From: DeckerSU Date: Sun, 15 Mar 2020 00:47:16 +0300 Subject: [PATCH 07/40] disable THROW_IF_SYNCING to allow z-rpcs anyway method of determination is chain in sync (KOMODO_INSYNC), based on KOMODO_LONGESTCHAIN (https://github.com/DeckerSU/KomodoOcean/blob/27f2631e84c013ad03b24c2cf0b1381d032c39ad/src/main.cpp#L4348) is far away from best solution. bcz KOMODO_LONGESTCHAIN filled from nodes stats - https://github.com/DeckerSU/KomodoOcean/blob/27f2631e84c013ad03b24c2cf0b1381d032c39ad/src/rpc/net.cpp#L211 and not intended for this. --- src/wallet/rpcwallet.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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; From 85d5837b84098386ba62bcdadb9a4a4e1495634a Mon Sep 17 00:00:00 2001 From: DeckerSU Date: Sun, 15 Mar 2020 14:39:57 +0300 Subject: [PATCH 08/40] TODO: few uncomplete RPCs / patches / fixes to implement --- ...tempt-to-remove-watch-only-addresses.patch | 240 +++++++++++ contrib/todo/blockchain-stats.patch | 393 ++++++++++++++++++ contrib/todo/checkmids.patch | 186 +++++++++ ...acOS-hide-linker-visibility-warnings.patch | 21 + contrib/todo/txexpirynotify.patch | 115 +++++ 5 files changed, 955 insertions(+) create mode 100644 contrib/todo/attempt-to-remove-watch-only-addresses.patch create mode 100644 contrib/todo/blockchain-stats.patch create mode 100644 contrib/todo/checkmids.patch create mode 100644 contrib/todo/macOS-hide-linker-visibility-warnings.patch create mode 100644 contrib/todo/txexpirynotify.patch 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; From 0a322a0d1bca61fb9a1b4fe2b292a51b667bf7ba Mon Sep 17 00:00:00 2001 From: DeckerSU Date: Sun, 15 Mar 2020 22:24:53 +0300 Subject: [PATCH 09/40] add komodo unit tests + Makefile.am fixes TODO: refactor Makefile.am --- src/Makefile.am | 12 ++++--- src/Makefile.ktest.include | 67 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+), 5 deletions(-) create mode 100644 src/Makefile.ktest.include diff --git a/src/Makefile.am b/src/Makefile.am index 94655ee3..4efc987f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -89,7 +89,7 @@ EXTRA_LIBRARIES = \ libzcash.a 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 @@ -549,7 +549,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 +564,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 +717,11 @@ if ENABLE_BIP70 $(AM_V_GEN) $(PROTOC) --cpp_out=$(@D) --proto_path=$(abspath $( Date: Sun, 15 Mar 2020 22:27:07 +0300 Subject: [PATCH 10/40] fix notarization test segfault (komodo-test) --- src/test-komodo/test_eval_notarisation.cpp | 5 +++++ 1 file changed, 5 insertions(+) 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) { From 9700247d313e6af3286851ddfbf34f8d6abc996f Mon Sep 17 00:00:00 2001 From: DeckerSU Date: Mon, 16 Mar 2020 03:38:54 +0300 Subject: [PATCH 11/40] util: CBufferedFile fixes https://github.com/bitcoin/bitcoin/pull/16577 https://github.com/zcash/zcash/pull/4265 - added CBufferedFile fix (thx LarryRuane) - added unit test (streams_tests.cpp rewritten for Google C++ Testing Framework - additional komodo_block_load test (read 2 blocks from binary file) - removed CBufferedFile::SetAnyPos method (had incorrect logic) - removed komodo_index2pubkey33, komodo_blockload (as not-used and related to SetAnyPos) - --- src/Makefile.ktest.include | 15 +- src/komodo_bitcoind.h | 25 -- src/streams.h | 35 +- src/test-komodo/test_buffered_file.cpp | 449 +++++++++++++++++++++++++ 4 files changed, 472 insertions(+), 52 deletions(-) create mode 100644 src/test-komodo/test_buffered_file.cpp diff --git a/src/Makefile.ktest.include b/src/Makefile.ktest.include index 57d46469..f0222c47 100644 --- a/src/Makefile.ktest.include +++ b/src/Makefile.ktest.include @@ -3,13 +3,14 @@ bin_PROGRAMS += komodo-test # tool for generating our public parameters komodo_test_SOURCES = \ - test-komodo/main.cpp \ - test-komodo/testutils.cpp \ - test-komodo/test_cryptoconditions.cpp \ - test-komodo/test_coinimport.cpp \ - test-komodo/test_eval_bet.cpp \ - test-komodo/test_eval_notarisation.cpp \ - test-komodo/test_parse_notarisation.cpp + test-komodo/main.cpp \ + test-komodo/testutils.cpp \ + test-komodo/test_cryptoconditions.cpp \ + test-komodo/test_coinimport.cpp \ + test-komodo/test_eval_bet.cpp \ + test-komodo/test_eval_notarisation.cpp \ + test-komodo/test_parse_notarisation.cpp \ + test-komodo/test_buffered_file.cpp komodo_test_CPPFLAGS = $(komodod_CPPFLAGS) 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/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 From ab2a60bb237f6abcb96d7074924c560c7a5a72af Mon Sep 17 00:00:00 2001 From: DeckerSU Date: Mon, 16 Mar 2020 10:31:35 +0300 Subject: [PATCH 12/40] disable building unit test by default on Windows and Mac TODO: fix unit test build on Windows fail --- zcutil/build-mac.sh | 2 +- zcutil/build-win.sh | 16 +++++++--------- 2 files changed, 8 insertions(+), 10 deletions(-) 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 From 49d3283b99c20b04307c16e85d3b6e852b2f85fc Mon Sep 17 00:00:00 2001 From: DeckerSU Date: Mon, 16 Mar 2020 19:24:50 +0300 Subject: [PATCH 13/40] added sha256 crypto unit test --- src/Makefile.ktest.include | 3 +- src/test-komodo/test_sha256_crypto.cpp | 158 +++++++++++++++++++++++++ 2 files changed, 160 insertions(+), 1 deletion(-) create mode 100644 src/test-komodo/test_sha256_crypto.cpp diff --git a/src/Makefile.ktest.include b/src/Makefile.ktest.include index f0222c47..46adc9a1 100644 --- a/src/Makefile.ktest.include +++ b/src/Makefile.ktest.include @@ -10,7 +10,8 @@ komodo_test_SOURCES = \ test-komodo/test_eval_bet.cpp \ test-komodo/test_eval_notarisation.cpp \ test-komodo/test_parse_notarisation.cpp \ - test-komodo/test_buffered_file.cpp + test-komodo/test_buffered_file.cpp \ + test-komodo/test_sha256_crypto.cpp komodo_test_CPPFLAGS = $(komodod_CPPFLAGS) diff --git a/src/test-komodo/test_sha256_crypto.cpp b/src/test-komodo/test_sha256_crypto.cpp new file mode 100644 index 00000000..6aa94e59 --- /dev/null +++ b/src/test-komodo/test_sha256_crypto.cpp @@ -0,0 +1,158 @@ +#include +#include "crypto/sha256.h" +#include "uint256.h" +#include +#include "random.h" +#include "utilstrencodings.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"); + } + +} \ No newline at end of file From f650848687ef6f0c765047ab2ac2c231a0486385 Mon Sep 17 00:00:00 2001 From: DeckerSU Date: Tue, 17 Mar 2020 11:52:53 +0300 Subject: [PATCH 14/40] temp disable non-working coin import tests --- src/test-komodo/test_coinimport.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) 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; From 337442edc1bc3f1bd649ecc613ce82acb61e4ebe Mon Sep 17 00:00:00 2001 From: DeckerSU Date: Tue, 17 Mar 2020 15:33:23 +0300 Subject: [PATCH 15/40] Remove template matching and pseudo opcodes https://github.com/bitcoin/bitcoin/pull/13194 https://github.com/zcash/zcash/commit/2cb14d79b15447ab180ad1ab0d79f3f57535e95e https://github.com/KomodoPlatform/komodo/pull/298 --- src/pubkey.h | 15 ++-- src/script/script.cpp | 24 ++++-- src/script/script.h | 7 +- src/script/standard.cpp | 171 +++++++++++++++++----------------------- 4 files changed, 103 insertions(+), 114 deletions(-) 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/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(); From 22817d383ef0d06a6b2661dae55573422714d18c Mon Sep 17 00:00:00 2001 From: DeckerSU Date: Tue, 17 Mar 2020 17:12:24 +0300 Subject: [PATCH 16/40] Do not treat bare multisig outputs as IsMine unless watched https://github.com/bitcoin/bitcoin/pull/13002/files https://github.com/KomodoPlatform/komodo/pull/298 --- src/script/standard.h | 4 ++-- src/wallet/wallet_ismine.cpp | 43 +++++++++++++++++++++++++++++++----- src/wallet/wallet_ismine.h | 2 +- 3 files changed, 40 insertions(+), 9 deletions(-) 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/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 * From c0b917b1809a235181973313e28fcb92d7e9bda2 Mon Sep 17 00:00:00 2001 From: DeckerSU Date: Tue, 17 Mar 2020 17:20:55 +0300 Subject: [PATCH 17/40] added unit test for standart scripts included script_standard_Malpill test for non-minimal forms of P2PK / P2PKH scripts --- src/Makefile.ktest.include | 3 +- .../test_script_standard_tests.cpp | 626 ++++++++++++++++++ 2 files changed, 628 insertions(+), 1 deletion(-) create mode 100644 src/test-komodo/test_script_standard_tests.cpp diff --git a/src/Makefile.ktest.include b/src/Makefile.ktest.include index 46adc9a1..dc3b5a06 100644 --- a/src/Makefile.ktest.include +++ b/src/Makefile.ktest.include @@ -11,7 +11,8 @@ komodo_test_SOURCES = \ test-komodo/test_eval_notarisation.cpp \ test-komodo/test_parse_notarisation.cpp \ test-komodo/test_buffered_file.cpp \ - test-komodo/test_sha256_crypto.cpp + test-komodo/test_sha256_crypto.cpp \ + test-komodo/test_script_standard_tests.cpp komodo_test_CPPFLAGS = $(komodod_CPPFLAGS) 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 From 01096328aac1d232f6c7d083a63c5d145df8c338 Mon Sep 17 00:00:00 2001 From: DeckerSU Date: Wed, 18 Mar 2020 00:27:43 +0300 Subject: [PATCH 18/40] added multisig tests (gtest) --- src/Makefile.ktest.include | 3 +- src/test-komodo/test_multisig_tests.cpp | 239 ++++++++++++++++++++++++ 2 files changed, 241 insertions(+), 1 deletion(-) create mode 100644 src/test-komodo/test_multisig_tests.cpp diff --git a/src/Makefile.ktest.include b/src/Makefile.ktest.include index dc3b5a06..beaa3ee4 100644 --- a/src/Makefile.ktest.include +++ b/src/Makefile.ktest.include @@ -12,7 +12,8 @@ komodo_test_SOURCES = \ test-komodo/test_parse_notarisation.cpp \ test-komodo/test_buffered_file.cpp \ test-komodo/test_sha256_crypto.cpp \ - test-komodo/test_script_standard_tests.cpp + test-komodo/test_script_standard_tests.cpp \ + test-komodo/test_multisig_tests.cpp komodo_test_CPPFLAGS = $(komodod_CPPFLAGS) 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 From a4256ad7fa31f69c8f1ec6bd4a2824d5076919cf Mon Sep 17 00:00:00 2001 From: DeckerSU Date: Wed, 18 Mar 2020 03:24:02 +0300 Subject: [PATCH 19/40] Refactor SHA256 code https://github.com/bitcoin/bitcoin/commit/57f34630fb6c3e218bd19535ac607008cb894173 --- src/crypto/sha256.cpp | 132 +++++++++++++++++++++--------------------- 1 file changed, 66 insertions(+), 66 deletions(-) diff --git a/src/crypto/sha256.cpp b/src/crypto/sha256.cpp index 0718d2d2..bc7999b1 100644 --- a/src/crypto/sha256.cpp +++ b/src/crypto/sha256.cpp @@ -33,9 +33,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 +61,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, 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, 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, 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, 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; From 852312948bb6e13a504a77fc6aef3a7feaaeba3d Mon Sep 17 00:00:00 2001 From: DeckerSU Date: Wed, 18 Mar 2020 04:04:43 +0300 Subject: [PATCH 20/40] Specialized double sha256 for 64 byte inputs https://github.com/bitcoin/bitcoin/commit/d0c96328833127284574bfef26f96aa2e4afc91a TODO: Use it in MerkleRoot Calculations, bits256_doublesha256 (komodo_utils.h) and analyse komodo specific code which possible can use this new SHA256D64. --- src/crypto/sha256.cpp | 304 +++++++++++++++++++++++++ src/crypto/sha256.h | 7 + src/test-komodo/test_sha256_crypto.cpp | 17 ++ 3 files changed, 328 insertions(+) diff --git a/src/crypto/sha256.cpp b/src/crypto/sha256.cpp index bc7999b1..5ff61795 100644 --- a/src/crypto/sha256.cpp +++ b/src/crypto/sha256.cpp @@ -141,9 +141,301 @@ 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*); + +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 + }; + 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]); +} bool SelfTest(TransformType tr) { static const unsigned char in1[65] = {0, 0x80}; @@ -173,6 +465,7 @@ bool SelfTest(TransformType tr) { } TransformType Transform = sha256::Transform; +TransformD64Type TransformD64 = sha256::TransformD64; } // namespace @@ -182,6 +475,7 @@ std::string SHA256AutoDetect() uint32_t eax, ebx, ecx, edx; if (__get_cpuid(1, &eax, &ebx, &ecx, &edx) && (ecx >> 19) & 1) { Transform = sha256_sse4::Transform; + TransformD64 = TransformD64Wrapper; assert(SelfTest(Transform)); return "sse4"; } @@ -256,3 +550,13 @@ CSHA256& CSHA256::Reset() sha256::Initialize(s); return *this; } + +void SHA256D64(unsigned char* out, const unsigned char* in, size_t blocks) +{ + while (blocks) { + TransformD64(out, in); + out += 32; + in += 64; + --blocks; + } +} \ No newline at end of file diff --git a/src/crypto/sha256.h b/src/crypto/sha256.h index 24c9c666..4469fd06 100644 --- a/src/crypto/sha256.h +++ b/src/crypto/sha256.h @@ -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/test-komodo/test_sha256_crypto.cpp b/src/test-komodo/test_sha256_crypto.cpp index 6aa94e59..5424c3fe 100644 --- a/src/test-komodo/test_sha256_crypto.cpp +++ b/src/test-komodo/test_sha256_crypto.cpp @@ -4,6 +4,7 @@ #include #include "random.h" #include "utilstrencodings.h" +#include "hash.h" namespace TestSHA256Crypto { @@ -155,4 +156,20 @@ namespace TestSHA256Crypto { "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 From 7b8d0fb929a54cee0166c79086e89336ec973fb3 Mon Sep 17 00:00:00 2001 From: DeckerSU Date: Wed, 18 Mar 2020 05:33:40 +0300 Subject: [PATCH 21/40] Add merkle.{h,cpp}, generic merkle root/branch algorithm https://github.com/bitcoin/bitcoin/commit/ee60e5625bf8a11c8e5509b9cea8b6465056c448 https://github.com/bitcoin/bitcoin/pull/13191/commits/1f0e7ca09c9d7c5787c218156fa5096a1bdf2ea8 --- src/Makefile.am | 2 ++ src/consensus/merkle.cpp | 74 ++++++++++++++++++++++++++++++++++++++++ src/consensus/merkle.h | 21 ++++++++++++ 3 files changed, 97 insertions(+) create mode 100644 src/consensus/merkle.cpp create mode 100644 src/consensus/merkle.h diff --git a/src/Makefile.am b/src/Makefile.am index 4efc987f..70fcf588 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -164,6 +164,7 @@ BITCOIN_CORE_H = \ compat/sanity.h \ compressor.h \ consensus/consensus.h \ + consensus/merkle.h \ consensus/params.h \ consensus/upgrades.h \ consensus/validation.h \ @@ -450,6 +451,7 @@ libbitcoin_common_a_SOURCES = \ chainparams.cpp \ coins.cpp \ compressor.cpp \ + consensus/merkle.cpp \ consensus/upgrades.cpp \ core_read.cpp \ core_write.cpp \ 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 From 51a2c4ed42e85b982c15ba0bd7674004b4f0a02c Mon Sep 17 00:00:00 2001 From: DeckerSU Date: Wed, 18 Mar 2020 12:31:06 +0300 Subject: [PATCH 22/40] build: Rename --enable-experimental-asm to --enable-asm and enable by default https://github.com/bitcoin/bitcoin/commit/ce5381e7fe6702a950a9a81693ca678d87912125 --- configure.ac | 18 +++++++++--------- src/Makefile.am | 2 +- src/crypto/sha256.cpp | 4 ++-- src/komodo_utils.h | 2 +- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/configure.ac b/configure.ac index 672bf382..3ce9002c 100644 --- a/configure.ac +++ b/configure.ac @@ -167,14 +167,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]) - -if test "x$experimental_asm" = xyes; then - AC_DEFINE(EXPERIMENTAL_ASM, 1, [Define this symbol to build in experimental assembly routines]) +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$use_asm" = xyes; then + AC_DEFINE(USE_ASM, 1, [Define this symbol to build in experimental assembly routines]) fi AC_ARG_ENABLE([zmq], @@ -1042,7 +1042,7 @@ 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([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]) diff --git a/src/Makefile.am b/src/Makefile.am index 70fcf588..4e53871a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -411,7 +411,7 @@ 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 diff --git a/src/crypto/sha256.cpp b/src/crypto/sha256.cpp index 5ff61795..e24276c6 100644 --- a/src/crypto/sha256.cpp +++ b/src/crypto/sha256.cpp @@ -10,7 +10,7 @@ #include #if defined(__x86_64__) || defined(__amd64__) -#if defined(EXPERIMENTAL_ASM) +#if defined(USE_ASM) #include namespace sha256_sse4 { @@ -471,7 +471,7 @@ TransformD64Type TransformD64 = sha256::TransformD64; std::string SHA256AutoDetect() { -#if defined(EXPERIMENTAL_ASM) && (defined(__x86_64__) || defined(__amd64__)) +#if defined(USE_ASM) && (defined(__x86_64__) || defined(__amd64__)) uint32_t eax, ebx, ecx, edx; if (__get_cpuid(1, &eax, &ebx, &ecx, &edx) && (ecx >> 19) & 1) { Transform = sha256_sse4::Transform; diff --git a/src/komodo_utils.h b/src/komodo_utils.h index a62a0d63..064cf408 100644 --- a/src/komodo_utils.h +++ b/src/komodo_utils.h @@ -285,7 +285,7 @@ void vcalc_sha256(char deprecated[(256 >> 3) * 2 + 1],uint8_t hash[256 >> 3],uin sha256_vdone(&md,hash); */ // we will use CSHA256 class instead of above implementation, - // in case if daemon compiled with EXPERIMENTAL_ASM enabled it will use + // 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); From aad9cfb4822448dac95fb8e1e096bb9bfd5d1c51 Mon Sep 17 00:00:00 2001 From: DeckerSU Date: Wed, 18 Mar 2020 13:35:56 +0300 Subject: [PATCH 23/40] __get_cpuid -> GetCPUID TODO: move it in src/compat/cpuid.h as in Bitcoin 0.19.x (see commit 723c79666770b30cce9f962bed5ece8cc7d74580), also analyse changes in src/random.cpp to use this implementation of GetCPUID there. --- src/crypto/sha256.cpp | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/crypto/sha256.cpp b/src/crypto/sha256.cpp index e24276c6..f1186133 100644 --- a/src/crypto/sha256.cpp +++ b/src/crypto/sha256.cpp @@ -467,13 +467,31 @@ bool SelfTest(TransformType tr) { TransformType Transform = sha256::Transform; TransformD64Type TransformD64 = sha256::TransformD64; +#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(USE_ASM) && (defined(__x86_64__) || defined(__amd64__)) uint32_t eax, ebx, ecx, edx; - if (__get_cpuid(1, &eax, &ebx, &ecx, &edx) && (ecx >> 19) & 1) { + GetCPUID(1, 0, eax, ebx, ecx, edx); + if ((ecx >> 19) & 1) { Transform = sha256_sse4::Transform; TransformD64 = TransformD64Wrapper; assert(SelfTest(Transform)); From 0b074662151546558e9242f206f2bcc85854a531 Mon Sep 17 00:00:00 2001 From: DeckerSU Date: Wed, 18 Mar 2020 15:08:38 +0300 Subject: [PATCH 24/40] [test] Add hardware SHA256D64 implementations (from BTC 0.19.x) - sha256d64_sse41 - sha256d64_avx2 - sha256d64_shani - sha256_shani NB: now build subsystem have few mistakes and checking for SSE4.2 intrinsics, checking for SSE4.1 intrinsics never passed. TODO: fix it. --- configure.ac | 122 +++++++++++- src/Makefile.am | 30 +++ src/crypto/sha256.cpp | 238 ++++++++++++++++++++---- src/crypto/sha256.h | 2 +- src/crypto/sha256_avx2.cpp | 328 +++++++++++++++++++++++++++++++++ src/crypto/sha256_shani.cpp | 358 ++++++++++++++++++++++++++++++++++++ src/crypto/sha256_sse41.cpp | 320 ++++++++++++++++++++++++++++++++ 7 files changed, 1361 insertions(+), 37 deletions(-) create mode 100644 src/crypto/sha256_avx2.cpp create mode 100644 src/crypto/sha256_shani.cpp create mode 100644 src/crypto/sha256_sse41.cpp diff --git a/configure.ac b/configure.ac index 3ce9002c..e664fb72 100644 --- a/configure.ac +++ b/configure.ac @@ -221,6 +221,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], @@ -1042,6 +1149,11 @@ 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([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]) @@ -1063,6 +1175,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 +1255,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 +1269,4 @@ echo " CXX = $CXX" echo " CXXFLAGS = $CXXFLAGS" echo " LDFLAGS = $LDFLAGS" echo " ARFLAGS = $ARFLAGS" -echo +echo diff --git a/src/Makefile.am b/src/Makefile.am index 4e53871a..563b9604 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 @@ -415,6 +427,24 @@ 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 \ diff --git a/src/crypto/sha256.cpp b/src/crypto/sha256.cpp index f1186133..a23b91e6 100644 --- a/src/crypto/sha256.cpp +++ b/src/crypto/sha256.cpp @@ -9,7 +9,9 @@ #include #include -#if defined(__x86_64__) || defined(__amd64__) + + +#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 { @@ -437,35 +459,107 @@ void TransformD64Wrapper(unsigned char* out, const unsigned char* in) WriteBE32(out + 28, s[7]); } -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 +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 }; - 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; + + + // 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; } -TransformType Transform = sha256::Transform; -TransformD64Type TransformD64 = sha256::TransformD64; +/* 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 @@ -477,7 +571,7 @@ void static inline GetCPUID(uint32_t leaf, uint32_t subleaf, uint32_t& a, uint32 { #ifdef __GNUC__ __cpuid_count(leaf, subleaf, a, b, c, d); -#else +#else __asm__ ("cpuid" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "0"(leaf), "2"(subleaf)); #endif } @@ -486,21 +580,73 @@ void static inline GetCPUID(uint32_t leaf, uint32_t subleaf, uint32_t& a, uint32 } // namespace + std::string SHA256AutoDetect() { -#if defined(USE_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; GetCPUID(1, 0, eax, ebx, ecx, edx); - if ((ecx >> 19) & 1) { + 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; TransformD64 = TransformD64Wrapper; - assert(SelfTest(Transform)); - return "sse4"; + 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 @@ -571,10 +717,34 @@ CSHA256& CSHA256::Reset() 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; } -} \ No newline at end of file +} diff --git a/src/crypto/sha256.h b/src/crypto/sha256.h index 4469fd06..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. 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 From 405f44d15761bf64f8aa3e93d437f38e540f2fc7 Mon Sep 17 00:00:00 2001 From: DeckerSU Date: Wed, 18 Mar 2020 15:32:46 +0300 Subject: [PATCH 25/40] Add AC_LANG_PUSH([C++]) in configure.ac This fixed prev commit https://github.com/DeckerSU/KomodoOcean/commit/0b074662151546558e9242f206f2bcc85854a531 error, when checking for SSE4.2 intrinsics, checking for SSE4.1 intrinsics never passed, bcz of choice gcc, instead of g++. - https://www.gnu.org/software/autoconf/manual/autoconf-2.67/html_node/Language-Choice.html#Language-Choice - https://www.gnu.org/software/autoconf/manual/autoconf-2.61/html_node/Generating-Sources.html --- configure.ac | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configure.ac b/configure.ac index e664fb72..94406b66 100644 --- a/configure.ac +++ b/configure.ac @@ -204,6 +204,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 From 53ca762b9bcc2bcfe64c0cc40b0f4cb3cf7de40f Mon Sep 17 00:00:00 2001 From: DeckerSU Date: Wed, 18 Mar 2020 15:55:02 +0300 Subject: [PATCH 26/40] Fix Makefile.am TODO: find and fix similar errors --- src/Makefile.am | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 563b9604..8e25d840 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -91,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) endif if ENABLE_ZMQ -EXTRA_LIBRARIES += libbitcoin_zmq.a +EXTRA_LIBRARIES += $(LIBBITCOIN_ZMQ) endif if BUILD_KOMODO_LIBS From 7b26e16b5c0129fc5c5b43069501faf2b3f256a6 Mon Sep 17 00:00:00 2001 From: DeckerSU Date: Wed, 18 Mar 2020 19:47:12 +0300 Subject: [PATCH 27/40] add merkle root unit test (old and new mechanism) old: use block.BuildMerkleTree from CBlock (primitives/block.cpp) new: use BlockMerkleRoot from consensus/merkle.cpp (using SHA256D64 hardware) TODO: switch all places in code to new (!) --- src/Makefile.ktest.include | 3 +- src/test-komodo/test_merkle_tests.cpp | 315 ++++++++++++++++++++++++++ 2 files changed, 317 insertions(+), 1 deletion(-) create mode 100644 src/test-komodo/test_merkle_tests.cpp diff --git a/src/Makefile.ktest.include b/src/Makefile.ktest.include index beaa3ee4..c3efeb99 100644 --- a/src/Makefile.ktest.include +++ b/src/Makefile.ktest.include @@ -13,7 +13,8 @@ komodo_test_SOURCES = \ test-komodo/test_buffered_file.cpp \ test-komodo/test_sha256_crypto.cpp \ test-komodo/test_script_standard_tests.cpp \ - test-komodo/test_multisig_tests.cpp + test-komodo/test_multisig_tests.cpp \ + test-komodo/test_merkle_tests.cpp komodo_test_CPPFLAGS = $(komodod_CPPFLAGS) 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 From 956fb59044b002c07ff270af85099358c80e8db8 Mon Sep 17 00:00:00 2001 From: DeckerSU Date: Wed, 18 Mar 2020 23:33:17 +0300 Subject: [PATCH 28/40] BuildMerkleTree -> { BlockMerkleRoot, ComputeMerkleRoot } merkle.cpp Switch to new mechanism of Merkle Root calc: old: use block.BuildMerkleTree from CBlock (primitives/block.cpp) new: use BlockMerkleRoot from consensus/merkle.cpp (using SHA256D64 hardware) TODO: crosschain.cpp logic remains with old mechanism --- src/cc/eval.cpp | 6 ++++-- src/chainparams.cpp | 5 +++-- src/komodo_ccdata.h | 7 +++++-- src/main.cpp | 3 ++- src/miner.cpp | 3 ++- 5 files changed, 16 insertions(+), 8 deletions(-) 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 0e6de6fd..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; 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; ivtx[0] = txCoinbase; - pblock->hashMerkleRoot = pblock->BuildMerkleTree(); + pblock->hashMerkleRoot = BlockMerkleRoot(*pblock); } #ifdef ENABLE_WALLET From 511b27aba1c53b05acdc2a169eb374017b7b9145 Mon Sep 17 00:00:00 2001 From: DeckerSU Date: Wed, 18 Mar 2020 23:34:00 +0300 Subject: [PATCH 29/40] linux_release_CFLAGS: -O1 -> -O2 --- depends/hosts/linux.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 From 8070fb99c4b9f66e91e8265fd4200797c421311b Mon Sep 17 00:00:00 2001 From: DeckerSU Date: Thu, 19 Mar 2020 00:28:40 +0300 Subject: [PATCH 30/40] [dev] VSCode params template Copy into ${workspaceFolder}/.vscode --- .vscode.template/c_cpp_properties.json | 16 +++++ .vscode.template/launch.json | 45 ++++++++++++++ .vscode.template/settings.json | 81 ++++++++++++++++++++++++++ 3 files changed, 142 insertions(+) create mode 100644 .vscode.template/c_cpp_properties.json create mode 100644 .vscode.template/launch.json create mode 100644 .vscode.template/settings.json 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 From 632b9d04c565a491ee181750db8856f3bb870c8b Mon Sep 17 00:00:00 2001 From: DeckerSU Date: Thu, 19 Mar 2020 01:18:33 +0300 Subject: [PATCH 31/40] fix removeExpired crash when syncing from scratch previous fix for deleting txes which violates interest rules contain an error (call of GetMedianTimePast() method when chainActive.LastTip() could be NULL), this commit fixed it. --- src/main.cpp | 9 +-------- src/txmempool.cpp | 20 +++++++++++++++----- src/txmempool.h | 2 +- 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index bef989ad..1791d505 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4322,14 +4322,7 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock * mempool.removeForBlock(pblock->vtx, pindexNew->GetHeight(), txConflicted, !IsInitialBlockDownload()); // Remove transactions that expire at new block height from mempool - mempool.removeExpired(pindexNew->GetHeight(), chainActive.LastTip()->GetMedianTimePast() + 777); - - /* 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. - */ + mempool.removeExpired(pindexNew->GetHeight()); // Update chainActive & related variables. UpdateTip(pindexNew); diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 19a749c6..a1294fb8 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -511,23 +511,33 @@ void CTxMemPool::removeConflicts(const CTransaction &tx, std::list int32_t komodo_validate_interest(const CTransaction &tx,int32_t txheight,uint32_t nTime,int32_t dispflag); extern char ASSETCHAINS_SYMBOL[]; -void CTxMemPool::removeExpired(unsigned int nBlockHeight, unsigned int cmpTime) +void CTxMemPool::removeExpired(unsigned int nBlockHeight) { + CBlockIndex *tipindex; // Remove expired txs from the mempool LOCK(cs); list transactionsToRemove; for (indexed_transaction_set::const_iterator it = mapTx.begin(); it != mapTx.end(); it++) { const CTransaction& tx = it->GetTx(); - bool fInterestNotValidated = ASSETCHAINS_SYMBOL[0] == 0 && komodo_validate_interest(tx,nBlockHeight,cmpTime,0) < 0; + tipindex = chainActive.LastTip(); + + /* 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) - LogPrint("mempool","Removing interest violate txid.%s nHeight.%d nTime.%u vs locktime.%u\n",tx.GetHash().ToString(),nBlockHeight,cmpTime,tx.nLockTime); + 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); } } - for (const CTransaction& tx : transactionsToRemove) { list removed; remove(tx, removed, true); diff --git a/src/txmempool.h b/src/txmempool.h index 89425e9f..b73ff4b3 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -216,7 +216,7 @@ class CTxMemPool 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, unsigned int cmpTime); + void removeExpired(unsigned int nBlockHeight); void removeForBlock(const std::vector& vtx, unsigned int nBlockHeight, std::list& conflicts, bool fCurrentEstimate = true); void removeWithoutBranchId(uint32_t nMemPoolBranchId); From 90d2ac8ebb4ffd9e14f1eb79f8539ecf0b423fa9 Mon Sep 17 00:00:00 2001 From: DeckerSU Date: Thu, 19 Mar 2020 03:07:35 +0300 Subject: [PATCH 32/40] add missed QR code support --- configure.ac | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/configure.ac b/configure.ac index 94406b66..bc1f4e6b 100644 --- a/configure.ac +++ b/configure.ac @@ -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], @@ -1103,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]) From 35c137443e69217a9bc3b4d7b85b3ae83c0d088e Mon Sep 17 00:00:00 2001 From: DeckerSU Date: Thu, 19 Mar 2020 03:20:07 +0300 Subject: [PATCH 33/40] bump version to 3.0.1.2 (v3.0.1-beta3) --- configure.ac | 2 +- src/clientversion.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index bc1f4e6b..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) 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 From 286eec9228b2b249a4d9ea3d8e76f17bd31ffeda Mon Sep 17 00:00:00 2001 From: DeckerSU Date: Thu, 19 Mar 2020 04:36:43 +0300 Subject: [PATCH 34/40] add loading guts progress on init --- src/txdb.cpp | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/txdb.cpp b/src/txdb.cpp index 6032e941..c127f2fa 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,28 @@ 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 + reportDone = percentageDone/10; + } + } + CDiskBlockIndex diskindex; if (pcursor->GetValue(diskindex)) { // Construct block index object From 9b9c011bbb22a438617e303f722a00767d540d2b Mon Sep 17 00:00:00 2001 From: DeckerSU Date: Fri, 20 Mar 2020 01:16:14 +0300 Subject: [PATCH 35/40] add loading guts progress logging in debug.log LoadBlockIndexDB: start loading guts [10%]...[20%]...[30%]...[40%]...[50%]...[60%]...[70%]...[80%]...[90%]...[100%]...[DONE]. LoadBlockIndexDB: loaded guts --- src/txdb.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/txdb.cpp b/src/txdb.cpp index c127f2fa..c606d966 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -697,7 +697,7 @@ bool CBlockTreeDB::LoadBlockIndexGuts() pcursor->Seek(make_pair(DB_BLOCK_INDEX, uint256())); int64_t count = 0; int reportDone = 0; - uiInterface.ShowProgress(_("Loading guts"), 0, false); + uiInterface.ShowProgress(_("Loading guts..."), 0, false); // Load mapBlockIndex while (pcursor->Valid()) { @@ -711,9 +711,10 @@ bool CBlockTreeDB::LoadBlockIndexGuts() 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); + uiInterface.ShowProgress(_("Loading guts..."), percentageDone, false); if (reportDone < percentageDone/10) { // report max. every 10% step + LogPrintf("[%d%%]...", percentageDone); /* Continued */ reportDone = percentageDone/10; } } @@ -764,5 +765,8 @@ bool CBlockTreeDB::LoadBlockIndexGuts() } } + uiInterface.ShowProgress("", 100, false); + LogPrintf("[%s].\n", ShutdownRequested() ? "CANCELLED" : "DONE"); + return true; } From 12eb60849c69ea3c264629262adf8bdb451c2be7 Mon Sep 17 00:00:00 2001 From: DeckerSU Date: Fri, 20 Mar 2020 01:52:28 +0300 Subject: [PATCH 36/40] better logging for checking all blk files + show percentage in ui --- src/komodo_utils.h | 4 +++- src/main.cpp | 13 +++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/komodo_utils.h b/src/komodo_utils.h index 064cf408..5f13d1e3 100644 --- a/src/komodo_utils.h +++ b/src/komodo_utils.h @@ -2495,7 +2495,9 @@ void komodo_prefetch(FILE *fp) { rewind(fp); while ( fread(ignore,1,incr,fp) == incr ) // prefetch - LogPrintf("."); + { + // LogPrintf("."); + } free(ignore); } } diff --git a/src/main.cpp b/src/main.cpp index 1791d505..973dfdf9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6233,13 +6233,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); From ef39b390e0f69b4b215624af33a85cdc34e6919f Mon Sep 17 00:00:00 2001 From: DeckerSU Date: Sun, 22 Mar 2020 00:06:07 +0300 Subject: [PATCH 37/40] port Qt build changes from Bitcoin upstream - Qt 5.9.8 - Build flags - Packages add / remove --- build-aux/m4/bitcoin_qt.m4 | 18 ++- depends/packages/dbus.mk | 23 ---- depends/packages/expat.mk | 14 ++- depends/packages/fontconfig.mk | 9 +- depends/packages/freetype.mk | 7 +- depends/packages/libX11.mk | 27 ----- depends/packages/libXau.mk | 11 +- depends/packages/libXext.mk | 26 ----- depends/packages/libxcb.mk | 21 +++- depends/packages/packages.mk | 3 +- depends/packages/qrencode.mk | 9 +- depends/packages/qt.mk | 105 ++++++++++++++---- depends/packages/xcb_proto.mk | 7 +- depends/packages/xextproto.mk | 25 ----- depends/packages/xproto.mk | 5 +- depends/packages/xtrans.mk | 26 ----- depends/packages/zlib.mk | 24 ++-- .../patches/qt/fix_android_jni_static.patch | 18 +++ .../patches/qt/fix_android_qmake_conf.patch | 20 ++++ depends/patches/qt/mac-qmake.conf | 2 +- depends/patches/qt/no-xlib.patch | 69 ++++++++++++ 21 files changed, 282 insertions(+), 187 deletions(-) delete mode 100644 depends/packages/dbus.mk delete mode 100644 depends/packages/libX11.mk delete mode 100644 depends/packages/libXext.mk delete mode 100644 depends/packages/xextproto.mk delete mode 100644 depends/packages/xtrans.mk create mode 100644 depends/patches/qt/fix_android_jni_static.patch create mode 100644 depends/patches/qt/fix_android_qmake_conf.patch create mode 100644 depends/patches/qt/no-xlib.patch 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/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..366b1d0c 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,21 @@ 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|QMAKE_CC = clang|QMAKE_CC = $($(package)_cc)|" qtbase/mkspecs/common/clang.conf && \ + sed -i.old "s|QMAKE_CXX = clang++|QMAKE_CXX = $($(package)_cxx)|" qtbase/mkspecs/common/clang.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 + From ce404267cb4671c4002c7586f393a080bb6767a4 Mon Sep 17 00:00:00 2001 From: DeckerSU Date: Sun, 22 Mar 2020 00:33:59 +0300 Subject: [PATCH 38/40] QNetworkProxy can't be used anymore, since we changed Qt build flags This is part of: https://github.com/bitcoin/bitcoin/commit/d91af4768c1cbc1a6ec0f69a3a6d17f69c0cee07 TODO: complete remove of BIP70 support --- src/qt/optionsmodel.cpp | 5 +++++ src/qt/optionsmodel.h | 4 ++++ 2 files changed, 9 insertions(+) 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; } From 45efe1ad78eb028b27723d6c396437d1736f35a8 Mon Sep 17 00:00:00 2001 From: DeckerSU Date: Sun, 22 Mar 2020 01:56:57 +0300 Subject: [PATCH 39/40] disable (comment) komodo_prefetch usage --- src/komodo_globals.h | 2 +- src/komodo_utils.h | 2 ++ src/main.cpp | 4 +++- src/wallet/wallet.cpp | 4 +++- 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/komodo_globals.h b/src/komodo_globals.h index bf9d42ad..767c1e59 100644 --- a/src/komodo_globals.h +++ b/src/komodo_globals.h @@ -15,7 +15,7 @@ #include "komodo_defs.h" -void komodo_prefetch(FILE *fp); +//void komodo_prefetch(FILE *fp); uint32_t komodo_heightstamp(int32_t height); void komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotaries,uint8_t notaryid,uint256 txhash,uint64_t voutmask,uint8_t numvouts,uint32_t *pvals,uint8_t numpvals,int32_t kheight,uint32_t ktime,uint64_t opretvalue,uint8_t *opretbuf,uint16_t opretlen,uint16_t vout,uint256 MoM,int32_t MoMdepth); void komodo_init(int32_t height); diff --git a/src/komodo_utils.h b/src/komodo_utils.h index 5f13d1e3..79952dde 100644 --- a/src/komodo_utils.h +++ b/src/komodo_utils.h @@ -2482,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; @@ -2503,3 +2504,4 @@ void komodo_prefetch(FILE *fp) } fseek(fp,fpos,SEEK_SET); } +*/ \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 973dfdf9..0aa4c72f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6049,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); @@ -6061,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()); 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)); From 7b131231ffc50c2364504109bdcd22d64aa1a1df Mon Sep 17 00:00:00 2001 From: DeckerSU Date: Sun, 22 Mar 2020 04:46:19 +0300 Subject: [PATCH 40/40] fix macos build (#1) revert the https://github.com/bitcoin/bitcoin/commit/bc728d12a975934a1ef21e8d06612e157faaff6a commit. i know, it's kind of a hack and Qt on MacOS should be build with compiler specified in depends/builders/darwin.mk in darwin_CC and darwin_CXX variables. but here we need default clang/clang++ especially for Qt. previous build subsystem (before transition to Qt 5.9.8) had "error", but according to that, it using clang/clang++ and build fine. $($(package)_cc) here equal to darwin_CC $($(package)_cxx) equal to darwin_CXX (from depends/builders/darwin.mk) --- depends/packages/qt.mk | 2 -- 1 file changed, 2 deletions(-) diff --git a/depends/packages/qt.mk b/depends/packages/qt.mk index 366b1d0c..d1e62723 100644 --- a/depends/packages/qt.mk +++ b/depends/packages/qt.mk @@ -219,8 +219,6 @@ define $(package)_preprocess_cmds 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|QMAKE_CC = clang|QMAKE_CC = $($(package)_cc)|" qtbase/mkspecs/common/clang.conf && \ - sed -i.old "s|QMAKE_CXX = clang++|QMAKE_CXX = $($(package)_cxx)|" qtbase/mkspecs/common/clang.conf && \ sed -i.old "s/LIBRARY_PATH/(CROSS_)?\0/g" qtbase/mkspecs/features/toolchain.prf endef