diff --git a/configure.ac b/configure.ac index c44ffdbab5..046a7dcec4 100644 --- a/configure.ac +++ b/configure.ac @@ -307,6 +307,7 @@ if test "x$CXXFLAGS_overridden" = "xno"; then AX_CHECK_COMPILE_FLAG([-Wvla],[CXXFLAGS="$CXXFLAGS -Wvla"],,[[$CXXFLAG_WERROR]]) AX_CHECK_COMPILE_FLAG([-Wformat-security],[CXXFLAGS="$CXXFLAGS -Wformat-security"],,[[$CXXFLAG_WERROR]]) AX_CHECK_COMPILE_FLAG([-Wthread-safety-analysis],[CXXFLAGS="$CXXFLAGS -Wthread-safety-analysis"],,[[$CXXFLAG_WERROR]]) + AX_CHECK_COMPILE_FLAG([-Wrange-loop-analysis],[WARN_CXXFLAGS="$WARN_CXXFLAGS -Wrange-loop-analysis"],,[[$CXXFLAG_WERROR]]) ## Some compilers (gcc) ignore unknown -Wno-* options, but warn about all ## unknown options if any other warning is produced. Test the -Wfoo case, and @@ -844,6 +845,14 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include [ AC_MSG_RESULT(no)] ) +AC_MSG_CHECKING(for if type char equals int8_t) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include + #include ]], + [[ static_assert(std::is_same::value, ""); ]])], + [ AC_MSG_RESULT(yes); AC_DEFINE(CHAR_EQUALS_INT8, 1,[Define this symbol if type char equals int8_t]) ], + [ AC_MSG_RESULT(no)] +) + # ensure backtrace() is found, check -lexecinfo if necessary if test x$TARGET_OS != xwindows; then AC_SEARCH_LIBS([backtrace], [execinfo], [], [ diff --git a/doc/translation_strings_policy.md b/doc/translation_strings_policy.md index 7b3fe8a549..e0f792ac64 100644 --- a/doc/translation_strings_policy.md +++ b/doc/translation_strings_policy.md @@ -21,21 +21,11 @@ On a high level, these strings are to be translated: - GUI strings, anything that appears in a dialog or window -- Command-line option documentation - ### GUI strings Anything that appears to the user in the GUI is to be translated. This includes labels, menu items, button texts, tooltips and window titles. This includes messages passed to the GUI through the UI interface through `InitMessage`, `ThreadSafeMessageBox` or `ShowProgress`. -### Command-line options - -Documentation for the command line options in the output of `--help` should be translated as well. - -Make sure that default values do not end up in the string, but use string formatting like `strprintf(_("Threshold for disconnecting misbehaving peers (default: %u)"), 100)`. Putting default values in strings has led to accidental translations in the past, and forces the string to be retranslated every time the value changes. - -Do not translate messages that are only shown to developers, such as those that only appear when `--help-debug` is used. - General recommendations ------------------------ diff --git a/src/Makefile.am b/src/Makefile.am index 1b8c062784..bb1d2b1724 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -345,6 +345,7 @@ libdash_server_a_SOURCES = \ rpc/rpcquorums.cpp \ rpc/server.cpp \ rpc/privatesend.cpp \ + rpc/util.cpp \ script/sigcache.cpp \ script/ismine.cpp \ spork.cpp \ @@ -545,7 +546,6 @@ libdash_util_a_SOURCES = \ fs.cpp \ random.cpp \ rpc/protocol.cpp \ - rpc/util.cpp \ stacktraces.cpp \ support/cleanse.cpp \ sync.cpp \ diff --git a/src/init.cpp b/src/init.cpp index 8ef7237044..07acb49d39 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -505,12 +505,12 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-spentindex", strprintf(_("Maintain a full spent index, used to query the spending txid and input index for an outpoint (default: %u)"), DEFAULT_SPENTINDEX)); strUsage += HelpMessageGroup(_("Connection options:")); - strUsage += HelpMessageOpt("-addnode=", _("Add a node to connect to and attempt to keep the connection open (see the `addnode` RPC command help for more info)")); + strUsage += HelpMessageOpt("-addnode=", _("Add a node to connect to and attempt to keep the connection open (see the `addnode` RPC command help for more info). This option can be specified multiple times to add multiple nodes.")); strUsage += HelpMessageOpt("-allowprivatenet", strprintf(_("Allow RFC1918 addresses to be relayed and connected to (default: %u)"), DEFAULT_ALLOWPRIVATENET)); strUsage += HelpMessageOpt("-banscore=", strprintf(_("Threshold for disconnecting misbehaving peers (default: %u)"), DEFAULT_BANSCORE_THRESHOLD)); strUsage += HelpMessageOpt("-bantime=", strprintf(_("Number of seconds to keep misbehaving peers from reconnecting (default: %u)"), DEFAULT_MISBEHAVING_BANTIME)); strUsage += HelpMessageOpt("-bind=", _("Bind to given address and always listen on it. Use [host]:port notation for IPv6")); - strUsage += HelpMessageOpt("-connect=", _("Connect only to the specified node(s); -connect=0 disables automatic connections (the rules for this peer are the same as for -addnode)")); + strUsage += HelpMessageOpt("-connect=", _("Connect only to the specified node; -connect=0 disables automatic connections (the rules for this peer are the same as for -addnode). This option can be specified multiple times to connect to multiple nodes.")); strUsage += HelpMessageOpt("-discover", _("Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)")); strUsage += HelpMessageOpt("-dns", _("Allow DNS lookups for -addnode, -seednode and -connect") + " " + strprintf(_("(default: %u)"), DEFAULT_NAME_LOOKUP)); strUsage += HelpMessageOpt("-dnsseed", _("Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless -connect used)")); @@ -524,13 +524,13 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-maxsendbuffer=", strprintf(_("Maximum per-connection send buffer, *1000 bytes (default: %u)"), DEFAULT_MAXSENDBUFFER)); strUsage += HelpMessageOpt("-maxtimeadjustment", strprintf(_("Maximum allowed median peer time offset adjustment. Local perspective of time may be influenced by peers forward or backward by this amount. (default: %u seconds)"), DEFAULT_MAX_TIME_ADJUSTMENT)); strUsage += HelpMessageOpt("-onion=", strprintf(_("Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)"), "-proxy")); - strUsage += HelpMessageOpt("-onlynet=", _("Only connect to nodes in network (ipv4, ipv6 or onion)")); + strUsage += HelpMessageOpt("-onlynet=", _("Make outgoing connections only through network (ipv4, ipv6 or onion). Incoming connections are not affected by this option. This option can be specified multiple times to allow multiple networks.")); strUsage += HelpMessageOpt("-permitbaremultisig", strprintf(_("Relay non-P2SH multisig (default: %u)"), DEFAULT_PERMIT_BAREMULTISIG)); strUsage += HelpMessageOpt("-peerbloomfilters", strprintf(_("Support filtering of blocks and transaction with bloom filters (default: %u)"), DEFAULT_PEERBLOOMFILTERS)); strUsage += HelpMessageOpt("-port=", strprintf(_("Listen for connections on (default: %u or testnet: %u)"), defaultChainParams->GetDefaultPort(), testnetChainParams->GetDefaultPort())); strUsage += HelpMessageOpt("-proxy=", _("Connect through SOCKS5 proxy")); strUsage += HelpMessageOpt("-proxyrandomize", strprintf(_("Randomize credentials for every proxy connection. This enables Tor stream isolation (default: %u)"), DEFAULT_PROXYRANDOMIZE)); - strUsage += HelpMessageOpt("-seednode=", _("Connect to a node to retrieve peer addresses, and disconnect")); + strUsage += HelpMessageOpt("-seednode=", _("Connect to a node to retrieve peer addresses, and disconnect. This option can be specified multiple times to connect to multiple nodes.")); strUsage += HelpMessageOpt("-socketevents=", strprintf(_("Socket events mode, which must be one of: %s (default: %s)"), GetSupportedSocketEventsStr(), DEFAULT_SOCKETEVENTS)); strUsage += HelpMessageOpt("-timeout=", strprintf(_("Specify connection timeout in milliseconds (minimum: 1, default: %d)"), DEFAULT_CONNECT_TIMEOUT)); strUsage += HelpMessageOpt("-peertimeout=", strprintf("Specify p2p connection timeout in seconds. This option determines the amount of time a peer may be inactive before the connection to it is dropped. (minimum: 1, default: %d)", DEFAULT_PEER_CONNECT_TIMEOUT)); diff --git a/src/miner.cpp b/src/miner.cpp index b5919711e5..6de45f9d00 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -267,7 +267,7 @@ bool BlockAssembler::TestPackage(uint64_t packageSize, unsigned int packageSigOp // - safe TXs in regard to ChainLocks bool BlockAssembler::TestPackageTransactions(const CTxMemPool::setEntries& package) { - for (const CTxMemPool::txiter it : package) { + for (CTxMemPool::txiter it : package) { if (!IsFinalTx(it->GetTx(), nHeight, nLockTimeCutoff)) return false; if (!llmq::chainLocksHandler->IsTxSafeForMining(it->GetTx().GetHash())) { @@ -300,7 +300,7 @@ int BlockAssembler::UpdatePackagesForAdded(const CTxMemPool::setEntries& already indexed_modified_transaction_set &mapModifiedTx) { int nDescendantsUpdated = 0; - for (const CTxMemPool::txiter it : alreadyAdded) { + for (CTxMemPool::txiter it : alreadyAdded) { CTxMemPool::setEntries descendants; mempool.CalculateDescendants(it, descendants); // Insert all descendants (not yet in block) into the modified set diff --git a/src/net_processing.h b/src/net_processing.h index cdc578b34a..a5aa48130a 100644 --- a/src/net_processing.h +++ b/src/net_processing.h @@ -58,7 +58,7 @@ public: * @param[in] interrupt Interrupt condition for processing threads * @return True if there is more work to be done */ - bool SendMessages(CNode* pto, std::atomic& interrupt) override; + bool SendMessages(CNode* pto, std::atomic& interrupt) override EXCLUSIVE_LOCKS_REQUIRED(pto->cs_sendProcessing); /** Consider evicting an outbound peer based on the amount of time they've been behind our tip */ void ConsiderEviction(CNode *pto, int64_t time_in_seconds); diff --git a/src/qt/platformstyle.cpp b/src/qt/platformstyle.cpp index 419263d981..810d788054 100644 --- a/src/qt/platformstyle.cpp +++ b/src/qt/platformstyle.cpp @@ -46,7 +46,7 @@ void MakeSingleColorImage(QImage& img, const QColor& colorbase) QIcon ColorizeIcon(const QIcon& ico, const QColor& colorbase) { QIcon new_ico; - for (const QSize sz : ico.availableSizes()) + for (const QSize& sz : ico.availableSizes()) { QImage img(ico.pixmap(sz).toImage()); MakeSingleColorImage(img, colorbase); diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 8d33a2c38b..821e03c255 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -1097,7 +1097,7 @@ static void ApplyStats(CCoinsStats &stats, CHashWriter& ss, const uint256& hash, ss << hash; ss << VARINT(outputs.begin()->second.nHeight * 2 + outputs.begin()->second.fCoinBase); stats.nTransactions++; - for (const auto output : outputs) { + for (const auto& output : outputs) { ss << VARINT(output.first + 1); ss << output.second.out.scriptPubKey; ss << VARINT(output.second.out.nValue); diff --git a/src/serialize.h b/src/serialize.h index 1c266c6582..26bc5b319b 100644 --- a/src/serialize.h +++ b/src/serialize.h @@ -186,7 +186,9 @@ template const X& ReadWriteAsHelper(const X& x) { return x; } SerializationOp(s, CSerActionUnserialize()); \ } +#ifndef CHAR_EQUALS_INT8 template inline void Serialize(Stream& s, char a ) { ser_writedata8(s, a); } // TODO Get rid of bare char +#endif template inline void Serialize(Stream& s, int8_t a ) { ser_writedata8(s, a); } template inline void Serialize(Stream& s, uint8_t a ) { ser_writedata8(s, a); } template inline void Serialize(Stream& s, int16_t a ) { ser_writedata16(s, a); } @@ -198,7 +200,9 @@ template inline void Serialize(Stream& s, uint64_t a) { ser_wri template inline void Serialize(Stream& s, float a ) { ser_writedata32(s, ser_float_to_uint32(a)); } template inline void Serialize(Stream& s, double a ) { ser_writedata64(s, ser_double_to_uint64(a)); } +#ifndef CHAR_EQUALS_INT8 template inline void Unserialize(Stream& s, char& a ) { a = ser_readdata8(s); } // TODO Get rid of bare char +#endif template inline void Unserialize(Stream& s, int8_t& a ) { a = ser_readdata8(s); } template inline void Unserialize(Stream& s, uint8_t& a ) { a = ser_readdata8(s); } template inline void Unserialize(Stream& s, int16_t& a ) { a = ser_readdata16(s); } diff --git a/src/test/cuckoocache_tests.cpp b/src/test/cuckoocache_tests.cpp index 260162b1a3..bd27ae4f3d 100644 --- a/src/test/cuckoocache_tests.cpp +++ b/src/test/cuckoocache_tests.cpp @@ -114,7 +114,7 @@ double normalize_hit_rate(double hits, double load) return hits * std::max(load, 1.0); } -/** Check the hit rate on loads ranging from 0.1 to 2.0 */ +/** Check the hit rate on loads ranging from 0.1 to 1.6 */ BOOST_AUTO_TEST_CASE(cuckoocache_hit_rate_ok) { /** Arbitrarily selected Hit Rate threshold that happens to work for this test diff --git a/src/test/denialofservice_tests.cpp b/src/test/denialofservice_tests.cpp index aa8cbf448b..ee0493dcce 100644 --- a/src/test/denialofservice_tests.cpp +++ b/src/test/denialofservice_tests.cpp @@ -69,26 +69,41 @@ BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction) dummyNode1.fSuccessfullyConnected = true; // This test requires that we have a chain with non-zero work. - LOCK(cs_main); - BOOST_CHECK(chainActive.Tip() != nullptr); - BOOST_CHECK(chainActive.Tip()->nChainWork > 0); + { + LOCK(cs_main); + BOOST_CHECK(chainActive.Tip() != nullptr); + BOOST_CHECK(chainActive.Tip()->nChainWork > 0); + } // Test starts here - LOCK(dummyNode1.cs_sendProcessing); - peerLogic->SendMessages(&dummyNode1, interruptDummy); // should result in getheaders - LOCK(dummyNode1.cs_vSend); - BOOST_CHECK(dummyNode1.vSendMsg.size() > 0); - dummyNode1.vSendMsg.clear(); - dummyNode1.nSendMsgSize = 0; + { + LOCK2(cs_main, dummyNode1.cs_sendProcessing); + peerLogic->SendMessages(&dummyNode1, interruptDummy); // should result in getheaders + } + { + LOCK2(cs_main, dummyNode1.cs_vSend); + BOOST_CHECK(dummyNode1.vSendMsg.size() > 0); + dummyNode1.vSendMsg.clear(); + dummyNode1.nSendMsgSize = 0; + } int64_t nStartTime = GetTime(); // Wait 21 minutes SetMockTime(nStartTime+21*60); - peerLogic->SendMessages(&dummyNode1, interruptDummy); // should result in getheaders - BOOST_CHECK(dummyNode1.vSendMsg.size() > 0); + { + LOCK2(cs_main, dummyNode1.cs_sendProcessing); + peerLogic->SendMessages(&dummyNode1, interruptDummy); // should result in getheaders + } + { + LOCK2(cs_main, dummyNode1.cs_vSend); + BOOST_CHECK(dummyNode1.vSendMsg.size() > 0); + } // Wait 3 more minutes SetMockTime(nStartTime+24*60); - peerLogic->SendMessages(&dummyNode1, interruptDummy); // should result in disconnect + { + LOCK2(cs_main, dummyNode1.cs_sendProcessing); + peerLogic->SendMessages(&dummyNode1, interruptDummy); // should result in disconnect + } BOOST_CHECK(dummyNode1.fDisconnect == true); SetMockTime(0); @@ -194,8 +209,10 @@ BOOST_AUTO_TEST_CASE(DoS_banning) LOCK(cs_main); Misbehaving(dummyNode1.GetId(), 100); // Should get banned } - LOCK(dummyNode1.cs_sendProcessing); - peerLogic->SendMessages(&dummyNode1, interruptDummy); + { + LOCK2(cs_main, dummyNode1.cs_sendProcessing); + peerLogic->SendMessages(&dummyNode1, interruptDummy); + } BOOST_CHECK(connman->IsBanned(addr1)); BOOST_CHECK(!connman->IsBanned(ip(0xa0b0c001|0x0000ff00))); // Different IP, not banned @@ -209,15 +226,20 @@ BOOST_AUTO_TEST_CASE(DoS_banning) LOCK(cs_main); Misbehaving(dummyNode2.GetId(), 50); } - LOCK(dummyNode2.cs_sendProcessing); - peerLogic->SendMessages(&dummyNode2, interruptDummy); + { + LOCK2(cs_main, dummyNode2.cs_sendProcessing); + peerLogic->SendMessages(&dummyNode2, interruptDummy); + } BOOST_CHECK(!connman->IsBanned(addr2)); // 2 not banned yet... BOOST_CHECK(connman->IsBanned(addr1)); // ... but 1 still should be { LOCK(cs_main); Misbehaving(dummyNode2.GetId(), 50); } - peerLogic->SendMessages(&dummyNode2, interruptDummy); + { + LOCK2(cs_main, dummyNode2.cs_sendProcessing); + peerLogic->SendMessages(&dummyNode2, interruptDummy); + } BOOST_CHECK(connman->IsBanned(addr2)); bool dummy; @@ -241,20 +263,28 @@ BOOST_AUTO_TEST_CASE(DoS_banscore) LOCK(cs_main); Misbehaving(dummyNode1.GetId(), 100); } - LOCK(dummyNode1.cs_sendProcessing); - peerLogic->SendMessages(&dummyNode1, interruptDummy); + { + LOCK2(cs_main, dummyNode1.cs_sendProcessing); + peerLogic->SendMessages(&dummyNode1, interruptDummy); + } BOOST_CHECK(!connman->IsBanned(addr1)); { LOCK(cs_main); Misbehaving(dummyNode1.GetId(), 10); } - peerLogic->SendMessages(&dummyNode1, interruptDummy); + { + LOCK2(cs_main, dummyNode1.cs_sendProcessing); + peerLogic->SendMessages(&dummyNode1, interruptDummy); + } BOOST_CHECK(!connman->IsBanned(addr1)); { LOCK(cs_main); Misbehaving(dummyNode1.GetId(), 1); } - peerLogic->SendMessages(&dummyNode1, interruptDummy); + { + LOCK2(cs_main, dummyNode1.cs_sendProcessing); + peerLogic->SendMessages(&dummyNode1, interruptDummy); + } BOOST_CHECK(connman->IsBanned(addr1)); gArgs.ForceSetArg("-banscore", std::to_string(DEFAULT_BANSCORE_THRESHOLD)); @@ -281,8 +311,10 @@ BOOST_AUTO_TEST_CASE(DoS_bantime) LOCK(cs_main); Misbehaving(dummyNode.GetId(), 100); } - LOCK(dummyNode.cs_sendProcessing); - peerLogic->SendMessages(&dummyNode, interruptDummy); + { + LOCK2(cs_main, dummyNode.cs_sendProcessing); + peerLogic->SendMessages(&dummyNode, interruptDummy); + } BOOST_CHECK(connman->IsBanned(addr)); SetMockTime(nStartTime+60*60); diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 3a6aba4f61..f38290fb77 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -70,12 +70,12 @@ void CTxMemPool::UpdateForDescendants(txiter updateIt, cacheMap &cachedDescendan setAllDescendants.insert(cit); stageEntries.erase(cit); const setEntries &setChildren = GetMemPoolChildren(cit); - for (const txiter childEntry : setChildren) { + for (txiter childEntry : setChildren) { cacheMap::iterator cacheIt = cachedDescendants.find(childEntry); if (cacheIt != cachedDescendants.end()) { // We've already calculated this one, just add the entries for this set // but don't traverse again. - for (const txiter cacheEntry : cacheIt->second) { + for (txiter cacheEntry : cacheIt->second) { setAllDescendants.insert(cacheEntry); } } else if (!setAllDescendants.count(childEntry)) { diff --git a/src/txmempool.h b/src/txmempool.h index 57cf7df81e..0d257228c3 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -488,7 +488,7 @@ public: mutable CCriticalSection cs; indexed_transaction_set mapTx GUARDED_BY(cs); - typedef indexed_transaction_set::nth_index<0>::type::iterator txiter; + using txiter = indexed_transaction_set::nth_index<0>::type::const_iterator; std::vector > vTxHashes; //!< All tx hashes/entries in mapTx, in random order struct CompareIteratorByHash { diff --git a/src/validation.cpp b/src/validation.cpp index fb2840539d..a64024ffc4 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -202,7 +202,7 @@ private: void InvalidBlockFound(CBlockIndex *pindex, const CValidationState &state); CBlockIndex* FindMostWorkChain(); - bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBlockIndex *pindexNew, const CDiskBlockPos& pos); + void ReceivedBlockTransactions(const CBlock& block, CBlockIndex* pindexNew, const CDiskBlockPos& pos); bool RollforwardBlock(const CBlockIndex* pindex, CCoinsViewCache& inputs, const CChainParams& params); @@ -695,7 +695,7 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool view.SetBackend(viewMemPool); // do all inputs exist? - for (const CTxIn txin : tx.vin) { + for (const CTxIn& txin : tx.vin) { if (!pcoinsTip->HaveCoinInCache(txin.prevout)) { coins_to_uncache.push_back(txin.prevout); } @@ -3227,7 +3227,7 @@ CBlockIndex* CChainState::AddToBlockIndex(const CBlockHeader& block, enum BlockS } /** Mark a block as having its data received and checked (up to BLOCK_VALID_TRANSACTIONS). */ -bool CChainState::ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBlockIndex *pindexNew, const CDiskBlockPos& pos) +void CChainState::ReceivedBlockTransactions(const CBlock& block, CBlockIndex* pindexNew, const CDiskBlockPos& pos) { pindexNew->nTx = block.vtx.size(); pindexNew->nChainTx = 0; @@ -3268,8 +3268,6 @@ bool CChainState::ReceivedBlockTransactions(const CBlock &block, CValidationStat mapBlocksUnlinked.insert(std::make_pair(pindexNew->pprev, pindexNew)); } } - - return true; } static bool FindBlockPos(CDiskBlockPos &pos, unsigned int nAddSize, unsigned int nHeight, uint64_t nTime, bool fKnown = false) @@ -3749,8 +3747,7 @@ bool CChainState::AcceptBlock(const std::shared_ptr& pblock, CVali state.Error(strprintf("%s: Failed to find position to write new block to disk", __func__)); return false; } - if (!ReceivedBlockTransactions(block, state, pindex, blockPos)) - return error("AcceptBlock(): ReceivedBlockTransactions failed"); + ReceivedBlockTransactions(block, pindex, blockPos); } catch (const std::runtime_error& e) { return AbortNode(state, std::string("System error: ") + e.what()); } @@ -4230,14 +4227,13 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview, nCheckLevel = std::max(0, std::min(4, nCheckLevel)); LogPrintf("Verifying last %i blocks at level %i\n", nCheckDepth, nCheckLevel); CCoinsViewCache coins(coinsview); - CBlockIndex* pindexState = chainActive.Tip(); + CBlockIndex* pindex; CBlockIndex* pindexFailure = nullptr; int nGoodTransactions = 0; CValidationState state; int reportDone = 0; LogPrintf("[0%%]..."); /* Continued */ - for (CBlockIndex* pindex = chainActive.Tip(); pindex && pindex->pprev; pindex = pindex->pprev) - { + for (pindex = chainActive.Tip(); pindex && pindex->pprev; pindex = pindex->pprev) { boost::this_thread::interruption_point(); int percentageDone = std::max(1, std::min(99, (int)(((double)(chainActive.Height() - pindex->nHeight)) / (double)nCheckDepth * (nCheckLevel >= 4 ? 50 : 100)))); if (reportDone < percentageDone/10) { @@ -4271,13 +4267,12 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview, } } // check level 3: check for inconsistencies during memory-only disconnect of tip blocks - if (nCheckLevel >= 3 && pindex == pindexState && (coins.DynamicMemoryUsage() + pcoinsTip->DynamicMemoryUsage()) <= nCoinCacheUsage) { + if (nCheckLevel >= 3 && (coins.DynamicMemoryUsage() + pcoinsTip->DynamicMemoryUsage()) <= nCoinCacheUsage) { assert(coins.GetBestBlock() == pindex->GetBlockHash()); DisconnectResult res = g_chainstate.DisconnectBlock(block, pindex, coins); if (res == DISCONNECT_FAILED) { return error("VerifyDB(): *** irrecoverable inconsistency in block data at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString()); } - pindexState = pindex->pprev; if (res == DISCONNECT_UNCLEAN) { nGoodTransactions = 0; pindexFailure = pindex; @@ -4291,9 +4286,11 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview, if (pindexFailure) return error("VerifyDB(): *** coin database inconsistencies found (last %i blocks, %i good transactions before that)\n", chainActive.Height() - pindexFailure->nHeight + 1, nGoodTransactions); + // store block count as we move pindex at check level >= 4 + int block_count = chainActive.Height() - pindex->nHeight; + // check level 4: try reconnecting blocks if (nCheckLevel >= 4) { - CBlockIndex *pindex = pindexState; while (pindex != chainActive.Tip()) { boost::this_thread::interruption_point(); uiInterface.ShowProgress(_("Verifying blocks..."), std::max(1, std::min(99, 100 - (int)(((double)(chainActive.Height() - pindex->nHeight)) / (double)nCheckDepth * 50))), false); @@ -4307,7 +4304,7 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview, } LogPrintf("[DONE].\n"); - LogPrintf("No coin database inconsistencies in last %i blocks (%i transactions)\n", chainActive.Height() - pindexState->nHeight, nGoodTransactions); + LogPrintf("No coin database inconsistencies in last %i blocks (%i transactions)\n", block_count, nGoodTransactions); return true; } @@ -4495,8 +4492,7 @@ bool CChainState::AddGenesisBlock(const CChainParams& chainparams, const CBlock& if (blockPos.IsNull()) return error("%s: writing genesis block to disk failed", __func__); CBlockIndex *pindex = AddToBlockIndex(block); - if (!ReceivedBlockTransactions(block, state, pindex, blockPos)) - return error("%s: genesis block not accepted", __func__); + ReceivedBlockTransactions(block, pindex, blockPos); return true; } diff --git a/src/wallet/init.cpp b/src/wallet/init.cpp index 5be1b67969..8d96744ba6 100644 --- a/src/wallet/init.cpp +++ b/src/wallet/init.cpp @@ -319,7 +319,7 @@ bool WalletInit::Verify() // Keep track of each wallet absolute path to detect duplicates. std::set wallet_paths; - for (const auto wallet_file : wallet_files) { + for (const auto& wallet_file : wallet_files) { fs::path wallet_path = fs::absolute(wallet_file, GetWalletDir()); if (!wallet_paths.insert(wallet_path).second) { diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index ea52ee6cad..cc73572ced 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -717,7 +717,7 @@ void CWallet::SyncMetaData(std::pair ran for (TxSpends::iterator it = range.first; it != range.second; ++it) { const CWalletTx* wtx = &mapWallet[it->second]; if (wtx->nOrderPos < nMinOrderPos) { - nMinOrderPos = wtx->nOrderPos;; + nMinOrderPos = wtx->nOrderPos; copyFrom = wtx; } } @@ -774,6 +774,8 @@ void CWallet::AddToSpends(const COutPoint& outpoint, const uint256& wtxid) mapTxSpends.insert(std::make_pair(outpoint, wtxid)); setWalletUTXO.erase(outpoint); + setLockedCoins.erase(outpoint); + std::pair range; range = mapTxSpends.equal_range(outpoint); SyncMetaData(range); diff --git a/test/functional/wallet.py b/test/functional/wallet.py index e092619c92..9420b94135 100755 --- a/test/functional/wallet.py +++ b/test/functional/wallet.py @@ -66,7 +66,7 @@ class WalletTest(BitcoinTestFramework): assert_equal(txout['value'], 500) txout = self.nodes[0].gettxout(txid=confirmed_txid, n=confirmed_index, include_mempool=True) assert_equal(txout['value'], 500) - + # Send 210 DASH from 0 to 2 using sendtoaddress call. # Second transaction will be child of first, and will require a fee self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 110) @@ -114,6 +114,15 @@ class WalletTest(BitcoinTestFramework): self.nodes[2].lockunspent, False, [{"txid": unspent_0["txid"], "vout": 999}]) + # An output should be unlocked when spent + unspent_0 = self.nodes[1].listunspent()[0] + self.nodes[1].lockunspent(False, [unspent_0]) + tx = self.nodes[1].createrawtransaction([unspent_0], { self.nodes[1].getnewaddress() : 1 }) + tx = self.nodes[1].fundrawtransaction(tx)['hex'] + tx = self.nodes[1].signrawtransaction(tx)["hex"] + self.nodes[1].sendrawtransaction(tx) + assert_equal(len(self.nodes[1].listlockunspent()), 0) + # Have node1 generate 100 blocks (so node0 can recover the fee) self.nodes[1].generate(100) self.sync_all(self.nodes[0:3]) @@ -219,8 +228,8 @@ class WalletTest(BitcoinTestFramework): #2. hex-changed one output to 0.0 #3. sign and send #4. check if recipient (node0) can list the zero value tx - usp = self.nodes[1].listunspent() - inputs = [{"txid":usp[0]['txid'], "vout":usp[0]['vout']}] + usp = self.nodes[1].listunspent(query_options={'minimumAmount': '499.998'})[0] + inputs = [{"txid":usp['txid'], "vout":usp['vout']}] outputs = {self.nodes[1].getnewaddress(): 499.998, self.nodes[0].getnewaddress(): 11.11} rawTx = self.nodes[1].createrawtransaction(inputs, outputs).replace("c0833842", "00000000") #replace 11.11 with 0.0 (int32) diff --git a/test/lint/lint-filenames.sh b/test/lint/lint-filenames.sh index 61e978fe79..9020567e6f 100755 --- a/test/lint/lint-filenames.sh +++ b/test/lint/lint-filenames.sh @@ -10,7 +10,10 @@ export LC_ALL=C EXIT_CODE=0 -OUTPUT=$(git ls-files -- "*.cpp" "*.h" "*.py" "*.sh" | grep -vE '^[a-z0-9_./-]+$' | grep -vE 'src/(secp256k1|univalue)/') +OUTPUT=$(git ls-files --full-name -- "*.[cC][pP][pP]" "*.[hH]" "*.[pP][yY]" "*.[sS][hH]" | \ + grep -vE '^[a-z0-9_./-]+$' | \ + grep -vE '^src/(secp256k1|univalue)/') + if [[ ${OUTPUT} != "" ]]; then echo "Use only lowercase alphanumerics (a-z0-9), underscores (_), hyphens (-) and dots (.)" echo "in source code filenames:"