diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 5809cf58fe69..07da17c23c0a 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -95,6 +95,7 @@ BITCOIN_TESTS =\ test/timedata_tests.cpp \ test/torcontrol_tests.cpp \ test/transaction_tests.cpp \ + test/txvalidation_tests.cpp \ test/txvalidationcache_tests.cpp \ test/versionbits_tests.cpp \ test/uint256_tests.cpp \ diff --git a/src/dash-cli.cpp b/src/dash-cli.cpp index f161162c4200..b8d0b62919b8 100644 --- a/src/dash-cli.cpp +++ b/src/dash-cli.cpp @@ -226,6 +226,9 @@ class GetinfoRequestHandler: public BaseRequestHandler /** Create a simulated `getinfo` request. */ UniValue PrepareRequest(const std::string& method, const std::vector& args) override { + if (!args.empty()) { + throw std::runtime_error("-getinfo takes no arguments"); + } UniValue result(UniValue::VARR); result.push_back(JSONRPCRequestObj("getnetworkinfo", NullUniValue, ID_NETWORKINFO)); result.push_back(JSONRPCRequestObj("getblockchaininfo", NullUniValue, ID_BLOCKCHAININFO)); diff --git a/src/init.cpp b/src/init.cpp index e84a166a4744..c59f57dd3304 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -553,8 +553,6 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-debug=", strprintf(_("Output debugging information (default: %u, supplying is optional)"), 0) + ". " + _("If is not supplied or if = 1, output all debugging information.") + " " + _(" can be:") + " " + ListLogCategories() + "."); strUsage += HelpMessageOpt("-debugexclude=", strprintf(_("Exclude debugging information for a category. Can be used in conjunction with -debug=1 to output debug logs for all categories except one or more specified categories."))); - if (showDebug) - strUsage += HelpMessageOpt("-nodebug", "Turn off debugging messages, same as -debug=0"); strUsage += HelpMessageOpt("-help-debug", _("Show all debugging options (usage: --help -help-debug)")); strUsage += HelpMessageOpt("-logips", strprintf(_("Include IP addresses in debug output (default: %u)"), DEFAULT_LOGIPS)); strUsage += HelpMessageOpt("-logtimestamps", strprintf(_("Prepend debug output with timestamp (default: %u)"), DEFAULT_LOGTIMESTAMPS)); @@ -800,11 +798,13 @@ void ThreadImport(std::vector vImportFiles) if (!ActivateBestChain(state, chainparams)) { LogPrintf("Failed to connect best block (%s)\n", FormatStateMessage(state)); StartShutdown(); + return; } if (gArgs.GetBoolArg("-stopafterblockimport", DEFAULT_STOPAFTERBLOCKIMPORT)) { LogPrintf("Stopping after block import\n"); StartShutdown(); + return; } } // End scope of CImportingNow @@ -1110,12 +1110,12 @@ bool AppInitParameterInteraction() InitWarning(strprintf(_("Reducing -maxconnections from %d to %d, because of system limitations."), nUserMaxConnections, nMaxConnections)); // ********************************************************* Step 3: parameter-to-internal-flags - if (gArgs.IsArgSet("-debug")) { // Special-case: if -debug=0/-nodebug is set, turn off debugging messages const std::vector categories = gArgs.GetArgs("-debug"); - if (!(gArgs.GetBoolArg("-nodebug", false) || find(categories.begin(), categories.end(), std::string("0")) != categories.end())) { + if (std::none_of(categories.begin(), categories.end(), + [](std::string cat){return cat == "0" || cat == "none";})) { for (const auto& cat : categories) { uint64_t flag; if (!GetLogCategory(&flag, &cat)) { @@ -1807,9 +1807,15 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) pcoinsTip.reset(); pcoinsdbview.reset(); pcoinscatcher.reset(); + // new CBlockTreeDB tries to delete the existing file, which + // fails if it's still open from the previous loop. Close it first: + pblocktree.reset(); pblocktree.reset(new CBlockTreeDB(nBlockTreeDBCache, false, fReset)); llmq::DestroyLLMQSystem(); + // Same logic as above with pblocktree + evoDb.reset(); evoDb.reset(new CEvoDB(nEvoDbCache, false, fReset || fReindexChainState)); + deterministicMNManager.reset(); deterministicMNManager.reset(new CDeterministicMNManager(*evoDb)); llmq::InitLLMQSystem(*evoDb, &scheduler, false, fReset || fReindexChainState); @@ -2193,16 +2199,18 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) // Wait for genesis block to be processed { WaitableLock lock(cs_GenesisWait); - while (!fHaveGenesis) { - condvar_GenesisWait.wait(lock); + // We previously could hang here if StartShutdown() is called prior to + // ThreadImport getting started, so instead we just wait on a timer to + // check ShutdownRequested() regularly. + while (!fHaveGenesis && !ShutdownRequested()) { + condvar_GenesisWait.wait_for(lock, std::chrono::milliseconds(500)); } uiInterface.NotifyBlockTip.disconnect(BlockNotifyGenesisWait); } // As importing blocks can take several minutes, it's possible the user // requested to kill the GUI during one of the last operations. If so, exit. - if (fRequestShutdown) - { + if (ShutdownRequested()) { LogPrintf("Shutdown requested. Exiting.\n"); return false; } diff --git a/src/llmq/quorums_debug.h b/src/llmq/quorums_debug.h index d6721914edb5..3ba4422fe790 100644 --- a/src/llmq/quorums_debug.h +++ b/src/llmq/quorums_debug.h @@ -9,6 +9,7 @@ #include "sync.h" #include "univalue.h" +#include #include class CDataStream; diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 97e7b9af730d..ab9af5c2d4d1 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -1711,7 +1711,8 @@ void static ProcessOrphanTx(CConnman* connman, std::set& orphan_work_se CValidationState stateDummy; if (setMisbehaving.count(fromPeer)) continue; - if (AcceptToMemoryPool(mempool, stateDummy, porphanTx, true, &fMissingInputs2)) { + if (AcceptToMemoryPool(mempool, stateDummy, porphanTx, &fMissingInputs2 /* pfMissingInputs */, + false /* bypass_limits */, 0 /* nAbsurdFee */)) { LogPrint(BCLog::MEMPOOL, " accepted orphan tx %s\n", orphanHash.ToString()); connman->RelayTransaction(orphanTx); for (unsigned int i = 0; i < orphanTx.vout.size(); i++) { @@ -2516,16 +2517,18 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr bool fMissingInputs = false; CValidationState state; - if (!AlreadyHave(inv) && AcceptToMemoryPool(mempool, state, ptx, true, &fMissingInputs)) { + if (!AlreadyHave(inv) && AcceptToMemoryPool(mempool, state, ptx, &fMissingInputs /* pfMissingInputs */, + false /* bypass_limits */, 0 /* nAbsurdFee */)) { // Process custom txes, this changes AlreadyHave to "true" if (nInvType == MSG_DSTX) { LogPrint(BCLog::PRIVATESEND, "DSTX -- Masternode transaction accepted, txid=%s, peer=%d\n", - tx.GetHash().ToString(), pfrom->GetId()); + tx.GetHash().ToString(), pfrom->GetId()); CPrivateSend::AddDSTX(dstx); } mempool.check(pcoinsTip.get()); connman->RelayTransaction(tx); + for (unsigned int i = 0; i < tx.vout.size(); i++) { auto it_by_prev = mapOrphanTransactionsByPrev.find(COutPoint(inv.hash, i)); if (it_by_prev != mapOrphanTransactionsByPrev.end()) { @@ -2538,9 +2541,9 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr pfrom->nLastTXTime = GetTime(); LogPrint(BCLog::MEMPOOL, "AcceptToMemoryPool: peer=%d: accepted %s (poolsz %u txn, %u kB)\n", - pfrom->GetId(), - tx.GetHash().ToString(), - mempool.size(), mempool.DynamicMemoryUsage() / 1000); + pfrom->GetId(), + tx.GetHash().ToString(), + mempool.size(), mempool.DynamicMemoryUsage() / 1000); // Recursively process any orphan transactions that depended on this one ProcessOrphanTx(connman, pfrom->orphan_work_set); diff --git a/src/privatesend/privatesend-server.cpp b/src/privatesend/privatesend-server.cpp index aa2bfc922f5e..4c3f66d588e9 100644 --- a/src/privatesend/privatesend-server.cpp +++ b/src/privatesend/privatesend-server.cpp @@ -303,7 +303,7 @@ void CPrivateSendServer::CommitFinalTransaction(CConnman& connman) TRY_LOCK(cs_main, lockMain); CValidationState validationState; mempool.PrioritiseTransaction(hashTx, 0.1 * COIN); - if (!lockMain || !AcceptToMemoryPool(mempool, validationState, finalTransaction, false, nullptr, false, maxTxFee)) { + if (!lockMain || !AcceptToMemoryPool(mempool, validationState, finalTransaction, nullptr /* pfMissingInputs */, false /* bypass_limits */, maxTxFee /* nAbsurdFee */)) { LogPrint(BCLog::PRIVATESEND, "CPrivateSendServer::CommitFinalTransaction -- AcceptToMemoryPool() error: Transaction not valid\n"); SetNull(); // not much we can do in this case, just notify clients @@ -434,7 +434,7 @@ void CPrivateSendServer::ConsumeCollateral(CConnman& connman, const CTransaction { LOCK(cs_main); CValidationState validationState; - if (!AcceptToMemoryPool(mempool, validationState, txref, false, nullptr)) { + if (!AcceptToMemoryPool(mempool, validationState, txref, nullptr /* pfMissingInputs */, false /* bypass_limits */, 0 /* nAbsurdFee */)) { LogPrint(BCLog::PRIVATESEND, "%s -- AcceptToMemoryPool failed\n", __func__); } else { connman.RelayTransaction(*txref); diff --git a/src/privatesend/privatesend.cpp b/src/privatesend/privatesend.cpp index 482c46d75305..2a3c02487675 100644 --- a/src/privatesend/privatesend.cpp +++ b/src/privatesend/privatesend.cpp @@ -383,7 +383,7 @@ bool CPrivateSend::IsCollateralValid(const CTransaction& txCollateral) { LOCK(cs_main); CValidationState validationState; - if (!AcceptToMemoryPool(mempool, validationState, MakeTransactionRef(txCollateral), false, nullptr, false, maxTxFee, true)) { + if (!AcceptToMemoryPool(mempool, validationState, MakeTransactionRef(txCollateral), nullptr /* pfMissingInputs */, false /* bypass_limits */, maxTxFee /* nAbsurdFee */, true /* fDryRun */)) { LogPrint(BCLog::PRIVATESEND, "CPrivateSend::IsCollateralValid -- didn't pass AcceptToMemoryPool()\n"); return false; } diff --git a/src/qt/dash.cpp b/src/qt/dash.cpp index 41be48a1cf61..6ed863b5861e 100644 --- a/src/qt/dash.cpp +++ b/src/qt/dash.cpp @@ -424,7 +424,6 @@ void BitcoinApplication::createWindow(const NetworkStyle *networkStyle) pollShutdownTimer = new QTimer(window); connect(pollShutdownTimer, SIGNAL(timeout()), window, SLOT(detectShutdown())); - pollShutdownTimer->start(200); } void BitcoinApplication::createSplashScreen(const NetworkStyle *networkStyle) @@ -552,14 +551,16 @@ void BitcoinApplication::initializeResult(bool success) window, SLOT(message(QString,QString,unsigned int))); QTimer::singleShot(100, paymentServer, SLOT(uiReady())); #endif + pollShutdownTimer->start(200); } else { - quit(); // Exit main loop + Q_EMIT splashFinished(window); // Make sure splash screen doesn't stick around during shutdown + quit(); // Exit first main loop invocation } } void BitcoinApplication::shutdownResult() { - quit(); // Exit main loop after shutdown finished + quit(); // Exit second main loop invocation after shutdown finished } void BitcoinApplication::handleRunawayException(const QString &message) diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index 7e5a2e2847b7..723c410360f1 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -1133,6 +1133,9 @@ uint64_t getCategoryMask(UniValue cats) { if (!GetLogCategory(&flag, &cat)) { throw JSONRPCError(RPC_INVALID_PARAMETER, "unknown logging category " + cat); } + if (flag == BCLog::NONE) { + return 0; + } mask |= flag; } return mask; @@ -1142,20 +1145,34 @@ UniValue logging(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() > 2) { throw std::runtime_error( - "logging [include,...] \n" + "logging ( )\n" "Gets and sets the logging configuration.\n" - "When called without an argument, returns the list of categories that are currently being debug logged.\n" - "When called with arguments, adds or removes categories from debug logging.\n" - "The valid logging categories are: " + ListLogCategories() + ".\n" - "libevent logging is configured on startup and cannot be modified by this RPC during runtime.\n" - "There are also a few meta-categories:\n" - " - \"all\", \"1\" and \"\" activate all categories at once;\n" - " - \"dash\" activates all Dash-specific categories at once.\n" + "When called without an argument, returns the list of categories with status that are currently being debug logged or not.\n" + "When called with arguments, adds or removes categories from debug logging and return the lists above.\n" + "The arguments are evaluated in order \"include\", \"exclude\".\n" + "If an item is both included and excluded, it will thus end up being excluded.\n" + "The valid logging categories are: " + ListLogCategories() + "\n" + "In addition, the following are available as category names with special meanings:\n" + " - \"all\", \"1\" : represent all logging categories.\n" + " - \"dash\" activates all Dash-specific categories at once.\n" "To deactivate all categories at once you can specify \"all\" in .\n" + " - \"none\", \"0\" : even if other logging categories are specified, ignore all of them.\n" "\nArguments:\n" - "1. \"include\" (array of strings) add debug logging for these categories.\n" - "2. \"exclude\" (array of strings) remove debug logging for these categories.\n" - "\nResult: (string): a list of the logging categories that are active.\n" + "1. \"include\" (array of strings, optional) A json array of categories to add debug logging\n" + " [\n" + " \"category\" (string) the valid logging category\n" + " ,...\n" + " ]\n" + "2. \"exclude\" (array of strings, optional) A json array of categories to remove debug logging\n" + " [\n" + " \"category\" (string) the valid logging category\n" + " ,...\n" + " ]\n" + "\nResult:\n" + "{ (json object where keys are the logging categories, and values indicates its status\n" + " \"category\": 0|1, (numeric) if being debug logged or not. 0:inactive, 1:active\n" + " ...\n" + "}\n" "\nExamples:\n" + HelpExampleCli("logging", "\"[\\\"all\\\"]\" \"[\\\"http\\\"]\"") + HelpExampleRpc("logging", "[\"all\"], \"[libevent]\"") diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index ee02571170c3..b1ffadc6e27b 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -93,7 +93,7 @@ UniValue getpeerinfo(const JSONRPCRequest& request) " \"pingtime\": n, (numeric) ping time (if available)\n" " \"minping\": n, (numeric) minimum observed ping time (if any at all)\n" " \"pingwait\": n, (numeric) ping wait (if non-zero)\n" - " \"version\": v, (numeric) The peer version, such as 7001\n" + " \"version\": v, (numeric) The peer version, such as 70001\n" " \"subver\": \"/Dash Core:x.x.x/\", (string) The string version\n" " \"inbound\": true|false, (boolean) Inbound (true) or Outbound (false)\n" " \"addnode\": true|false, (boolean) Whether connection was due to addnode/-connect or if it was an automatic/inbound connection\n" diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index 9a3b15bab203..b552e805dbd7 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -1010,7 +1010,8 @@ UniValue sendrawtransaction(const JSONRPCRequest& request) // push to local node and sync with wallets CValidationState state; bool fMissingInputs; - if (!AcceptToMemoryPool(mempool, state, std::move(tx), !fBypassLimits, &fMissingInputs, false, nMaxRawTxFee)) { + if (!AcceptToMemoryPool(mempool, state, std::move(tx), &fMissingInputs, + fBypassLimits /* bypass_limits */, nMaxRawTxFee)) { if (state.IsInvalid()) { throw JSONRPCError(RPC_TRANSACTION_REJECTED, strprintf("%i: %s", state.GetRejectCode(), state.GetRejectReason())); } else { diff --git a/src/test/txvalidation_tests.cpp b/src/test/txvalidation_tests.cpp new file mode 100644 index 000000000000..1a6a7e3acf34 --- /dev/null +++ b/src/test/txvalidation_tests.cpp @@ -0,0 +1,60 @@ +// Copyright (c) 2017 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 +#include +#include +#include +#include