diff options
Diffstat (limited to 'src')
51 files changed, 343 insertions, 225 deletions
diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp index 8e8ac47455..cb863bda19 100644 --- a/src/bitcoin-tx.cpp +++ b/src/bitcoin-tx.cpp @@ -395,10 +395,8 @@ static void MutateTxSign(CMutableTransaction& tx, const string& flagStr) if (!registers.count("privatekeys")) throw runtime_error("privatekeys register variable must be set."); - bool fGivenKeys = false; CBasicKeyStore tempKeystore; UniValue keysObj = registers["privatekeys"]; - fGivenKeys = true; for (unsigned int kidx = 0; kidx < keysObj.size(); kidx++) { if (!keysObj[kidx].isStr()) @@ -454,7 +452,7 @@ static void MutateTxSign(CMutableTransaction& tx, const string& flagStr) // if redeemScript given and private keys given, // add redeemScript to the tempKeystore so it can be signed: - if (fGivenKeys && (scriptPubKey.IsPayToScriptHash() || scriptPubKey.IsPayToWitnessScriptHash()) && + if ((scriptPubKey.IsPayToScriptHash() || scriptPubKey.IsPayToWitnessScriptHash()) && prevOut.exists("redeemScript")) { UniValue v = prevOut["redeemScript"]; vector<unsigned char> rsData(ParseHexUV(v, "redeemScript")); @@ -517,7 +515,7 @@ public: static void MutateTx(CMutableTransaction& tx, const string& command, const string& commandVal) { - boost::scoped_ptr<Secp256k1Init> ecc; + std::unique_ptr<Secp256k1Init> ecc; if (command == "nversion") MutateTxVersion(tx, commandVal); diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp index 28bc374acc..322298d1b3 100644 --- a/src/bitcoind.cpp +++ b/src/bitcoind.cpp @@ -40,8 +40,6 @@ * Use the buttons <code>Namespaces</code>, <code>Classes</code> or <code>Files</code> at the top of the page to start navigating the code. */ -static bool fDaemon; - void WaitForShutdown(boost::thread_group* threadGroup) { bool fShutdown = ShutdownRequested(); @@ -130,8 +128,7 @@ bool AppInit(int argc, char* argv[]) exit(1); } #ifndef WIN32 - fDaemon = GetBoolArg("-daemon", false); - if (fDaemon) + if (GetBoolArg("-daemon", false)) { fprintf(stdout, "Bitcoin server starting\n"); diff --git a/src/blockencodings.h b/src/blockencodings.h index b980e9e286..349fcbd50f 100644 --- a/src/blockencodings.h +++ b/src/blockencodings.h @@ -53,11 +53,11 @@ public: } uint16_t offset = 0; - for (size_t i = 0; i < indexes.size(); i++) { - if (uint64_t(indexes[i]) + uint64_t(offset) > std::numeric_limits<uint16_t>::max()) + for (size_t j = 0; j < indexes.size(); j++) { + if (uint64_t(indexes[j]) + uint64_t(offset) > std::numeric_limits<uint16_t>::max()) throw std::ios_base::failure("indexes overflowed 16 bits"); - indexes[i] = indexes[i] + offset; - offset = indexes[i] + 1; + indexes[j] = indexes[j] + offset; + offset = indexes[j] + 1; } } else { for (size_t i = 0; i < indexes.size(); i++) { diff --git a/src/chain.h b/src/chain.h index 76a774c123..6588e8f57d 100644 --- a/src/chain.h +++ b/src/chain.h @@ -137,15 +137,15 @@ enum BlockStatus: uint32_t { BLOCK_VALID_MASK = BLOCK_VALID_HEADER | BLOCK_VALID_TREE | BLOCK_VALID_TRANSACTIONS | BLOCK_VALID_CHAIN | BLOCK_VALID_SCRIPTS, - BLOCK_HAVE_DATA = 8, //! full block available in blk*.dat - BLOCK_HAVE_UNDO = 16, //! undo data available in rev*.dat + BLOCK_HAVE_DATA = 8, //!< full block available in blk*.dat + BLOCK_HAVE_UNDO = 16, //!< undo data available in rev*.dat BLOCK_HAVE_MASK = BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO, - BLOCK_FAILED_VALID = 32, //! stage after last reached validness failed - BLOCK_FAILED_CHILD = 64, //! descends from failed block + BLOCK_FAILED_VALID = 32, //!< stage after last reached validness failed + BLOCK_FAILED_CHILD = 64, //!< descends from failed block BLOCK_FAILED_MASK = BLOCK_FAILED_VALID | BLOCK_FAILED_CHILD, - BLOCK_OPT_WITNESS = 128, //! block data in blk*.data was received with a witness-enforcing client + BLOCK_OPT_WITNESS = 128, //!< block data in blk*.data was received with a witness-enforcing client }; /** The block chain is a tree shaped structure starting with the diff --git a/src/chainparams.cpp b/src/chainparams.cpp index ea6e3aada2..e6be1b5d5b 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -118,7 +118,7 @@ public: vSeeds.push_back(CDNSSeedData("dashjr.org", "dnsseed.bitcoin.dashjr.org")); // Luke Dashjr vSeeds.push_back(CDNSSeedData("bitcoinstats.com", "seed.bitcoinstats.com")); // Christian Decker vSeeds.push_back(CDNSSeedData("xf2.org", "bitseed.xf2.org")); // Jeff Garzik - vSeeds.push_back(CDNSSeedData("bitcoin.jonasschnelli.ch", "seed.bitcoin.jonasschnelli.ch")); // Jonas Schnelli + vSeeds.push_back(CDNSSeedData("bitcoin.jonasschnelli.ch", "seed.bitcoin.jonasschnelli.ch", true)); // Jonas Schnelli base58Prefixes[PUBKEY_ADDRESS] = std::vector<unsigned char>(1,0); base58Prefixes[SCRIPT_ADDRESS] = std::vector<unsigned char>(1,5); diff --git a/src/consensus/validation.h b/src/consensus/validation.h index 000b197270..3e24294a64 100644 --- a/src/consensus/validation.h +++ b/src/consensus/validation.h @@ -22,9 +22,9 @@ static const unsigned char REJECT_CHECKPOINT = 0x43; class CValidationState { private: enum mode_state { - MODE_VALID, //! everything ok - MODE_INVALID, //! network rule violation (DoS value may be set) - MODE_ERROR, //! run-time error + MODE_VALID, //!< everything ok + MODE_INVALID, //!< network rule violation (DoS value may be set) + MODE_ERROR, //!< run-time error } mode; int nDoS; std::string strRejectReason; diff --git a/src/dbwrapper.cpp b/src/dbwrapper.cpp index 09c68fbe55..4fa06135d2 100644 --- a/src/dbwrapper.cpp +++ b/src/dbwrapper.cpp @@ -117,7 +117,7 @@ std::vector<unsigned char> CDBWrapper::CreateObfuscateKey() const bool CDBWrapper::IsEmpty() { - boost::scoped_ptr<CDBIterator> it(NewIterator()); + std::unique_ptr<CDBIterator> it(NewIterator()); it->SeekToFirst(); return !(it->Valid()); } diff --git a/src/httprpc.cpp b/src/httprpc.cpp index 04d3386e9a..6a6c5276cc 100644 --- a/src/httprpc.cpp +++ b/src/httprpc.cpp @@ -45,7 +45,7 @@ private: class HTTPRPCTimerInterface : public RPCTimerInterface { public: - HTTPRPCTimerInterface(struct event_base* base) : base(base) + HTTPRPCTimerInterface(struct event_base* _base) : base(_base) { } const char* Name() diff --git a/src/httpserver.cpp b/src/httpserver.cpp index f921305fcc..b296b28503 100644 --- a/src/httpserver.cpp +++ b/src/httpserver.cpp @@ -42,8 +42,8 @@ static const size_t MAX_HEADERS_SIZE = 8192; class HTTPWorkItem : public HTTPClosure { public: - HTTPWorkItem(std::unique_ptr<HTTPRequest> req, const std::string &path, const HTTPRequestHandler& func): - req(std::move(req)), path(path), func(func) + HTTPWorkItem(std::unique_ptr<HTTPRequest> _req, const std::string &_path, const HTTPRequestHandler& _func): + req(std::move(_req)), path(_path), func(_func) { } void operator()() @@ -92,8 +92,8 @@ private: }; public: - WorkQueue(size_t maxDepth) : running(true), - maxDepth(maxDepth), + WorkQueue(size_t _maxDepth) : running(true), + maxDepth(_maxDepth), numThreads(0) { } @@ -158,8 +158,8 @@ public: struct HTTPPathHandler { HTTPPathHandler() {} - HTTPPathHandler(std::string prefix, bool exactMatch, HTTPRequestHandler handler): - prefix(prefix), exactMatch(exactMatch), handler(handler) + HTTPPathHandler(std::string _prefix, bool _exactMatch, HTTPRequestHandler _handler): + prefix(_prefix), exactMatch(_exactMatch), handler(_handler) { } std::string prefix; @@ -522,8 +522,8 @@ static void httpevent_callback_fn(evutil_socket_t, short, void* data) delete self; } -HTTPEvent::HTTPEvent(struct event_base* base, bool deleteWhenTriggered, const std::function<void(void)>& handler): - deleteWhenTriggered(deleteWhenTriggered), handler(handler) +HTTPEvent::HTTPEvent(struct event_base* base, bool _deleteWhenTriggered, const std::function<void(void)>& _handler): + deleteWhenTriggered(_deleteWhenTriggered), handler(_handler) { ev = event_new(base, -1, 0, httpevent_callback_fn, this); assert(ev); @@ -539,7 +539,7 @@ void HTTPEvent::trigger(struct timeval* tv) else evtimer_add(ev, tv); // trigger after timeval passed } -HTTPRequest::HTTPRequest(struct evhttp_request* req) : req(req), +HTTPRequest::HTTPRequest(struct evhttp_request* _req) : req(_req), replySent(false) { } diff --git a/src/init.cpp b/src/init.cpp index 13c68e512a..27843fa882 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -162,7 +162,7 @@ public: static CCoinsViewDB *pcoinsdbview = NULL; static CCoinsViewErrorCatcher *pcoinscatcher = NULL; -static boost::scoped_ptr<ECCVerifyHandle> globalVerifyHandle; +static std::unique_ptr<ECCVerifyHandle> globalVerifyHandle; void Interrupt(boost::thread_group& threadGroup) { @@ -380,7 +380,7 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-whitelist=<netmask>", _("Whitelist peers connecting from the given netmask or IP address. Can be specified multiple times.") + " " + _("Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway")); strUsage += HelpMessageOpt("-whitelistrelay", strprintf(_("Accept relayed transactions received from whitelisted peers even when not relaying transactions (default: %d)"), DEFAULT_WHITELISTRELAY)); - strUsage += HelpMessageOpt("-whitelistforcerelay", strprintf(_("Force relay of transactions from whitelisted peers even they violate local relay policy (default: %d)"), DEFAULT_WHITELISTFORCERELAY)); + strUsage += HelpMessageOpt("-whitelistforcerelay", strprintf(_("Force relay of transactions from whitelisted peers even if they violate local relay policy (default: %d)"), DEFAULT_WHITELISTFORCERELAY)); strUsage += HelpMessageOpt("-maxuploadtarget=<n>", strprintf(_("Tries to keep outbound traffic under the given target (in MiB per 24h), 0 = no limit (default: %d)"), DEFAULT_MAX_UPLOAD_TARGET)); #ifdef ENABLE_WALLET @@ -1183,8 +1183,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) fNameLookup = GetBoolArg("-dns", DEFAULT_NAME_LOOKUP); fRelayTxes = !GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY); - bool fBound = false; if (fListen) { + bool fBound = false; if (mapArgs.count("-bind") || mapArgs.count("-whitebind")) { BOOST_FOREACH(const std::string& strBind, mapMultiArgs["-bind"]) { CService addrBind; diff --git a/src/main.cpp b/src/main.cpp index ddd0541101..4b42afb561 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -196,7 +196,7 @@ namespace { * * Memory used: 1.3 MB */ - boost::scoped_ptr<CRollingBloomFilter> recentRejects; + std::unique_ptr<CRollingBloomFilter> recentRejects; uint256 hashRecentRejectsChainTip; /** Blocks that are in flight, and that are in the queue to be downloaded. Protected by cs_main. */ @@ -532,7 +532,7 @@ CBlockIndex* LastCommonAncestor(CBlockIndex* pa, CBlockIndex* pb) { /** Update pindexLastCommonBlock and add not-in-flight missing successors to vBlocks, until it has * at most count entries. */ -void FindNextBlocksToDownload(NodeId nodeid, unsigned int count, std::vector<CBlockIndex*>& vBlocks, NodeId& nodeStaller) { +void FindNextBlocksToDownload(NodeId nodeid, unsigned int count, std::vector<CBlockIndex*>& vBlocks, NodeId& nodeStaller, const Consensus::Params& consensusParams) { if (count == 0) return; @@ -589,6 +589,10 @@ void FindNextBlocksToDownload(NodeId nodeid, unsigned int count, std::vector<CBl // We consider the chain that this peer is on invalid. return; } + if (!State(nodeid)->fHaveWitness && IsWitnessEnabled(pindex->pprev, consensusParams)) { + // We wouldn't download this block or its descendants from this peer. + return; + } if (pindex->nStatus & BLOCK_HAVE_DATA || chainActive.Contains(pindex)) { if (pindex->nChainTx) state->pindexLastCommonBlock = pindex; @@ -1492,12 +1496,13 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C // Check against previous transactions // This is done last to help prevent CPU exhaustion denial-of-service attacks. - if (!CheckInputs(tx, state, view, true, scriptVerifyFlags, true)) { + PrecomputedTransactionData txdata(tx); + if (!CheckInputs(tx, state, view, true, scriptVerifyFlags, true, txdata)) { // SCRIPT_VERIFY_CLEANSTACK requires SCRIPT_VERIFY_WITNESS, so we // need to turn both off, and compare against just turning off CLEANSTACK // to see if the failure is specifically due to witness validation. - if (CheckInputs(tx, state, view, true, scriptVerifyFlags & ~(SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_CLEANSTACK), true) && - !CheckInputs(tx, state, view, true, scriptVerifyFlags & ~SCRIPT_VERIFY_CLEANSTACK, true)) { + if (CheckInputs(tx, state, view, true, scriptVerifyFlags & ~(SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_CLEANSTACK), true, txdata) && + !CheckInputs(tx, state, view, true, scriptVerifyFlags & ~SCRIPT_VERIFY_CLEANSTACK, true, txdata)) { // Only the witness is wrong, so the transaction itself may be fine. state.SetCorruptionPossible(); } @@ -1513,7 +1518,7 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C // There is a similar check in CreateNewBlock() to prevent creating // invalid blocks, however allowing such transactions into the mempool // can be exploited as a DoS attack. - if (!CheckInputs(tx, state, view, true, MANDATORY_SCRIPT_VERIFY_FLAGS, true)) + if (!CheckInputs(tx, state, view, true, MANDATORY_SCRIPT_VERIFY_FLAGS, true, txdata)) { return error("%s: BUG! PLEASE REPORT THIS! ConnectInputs failed against MANDATORY but not STANDARD flags %s, %s", __func__, hash.ToString(), FormatStateMessage(state)); @@ -1910,7 +1915,7 @@ void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, int nHeight) bool CScriptCheck::operator()() { const CScript &scriptSig = ptxTo->vin[nIn].scriptSig; const CScriptWitness *witness = (nIn < ptxTo->wit.vtxinwit.size()) ? &ptxTo->wit.vtxinwit[nIn].scriptWitness : NULL; - if (!VerifyScript(scriptSig, scriptPubKey, witness, nFlags, CachingTransactionSignatureChecker(ptxTo, nIn, amount, cacheStore), &error)) { + if (!VerifyScript(scriptSig, scriptPubKey, witness, nFlags, CachingTransactionSignatureChecker(ptxTo, nIn, amount, cacheStore, *txdata), &error)) { return false; } return true; @@ -1969,7 +1974,7 @@ bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoins } }// namespace Consensus -bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &inputs, bool fScriptChecks, unsigned int flags, bool cacheStore, std::vector<CScriptCheck> *pvChecks) +bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &inputs, bool fScriptChecks, unsigned int flags, bool cacheStore, PrecomputedTransactionData& txdata, std::vector<CScriptCheck> *pvChecks) { if (!tx.IsCoinBase()) { @@ -1996,7 +2001,7 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi assert(coins); // Verify signature - CScriptCheck check(*coins, tx, i, flags, cacheStore); + CScriptCheck check(*coins, tx, i, flags, cacheStore, &txdata); if (pvChecks) { pvChecks->push_back(CScriptCheck()); check.swap(pvChecks->back()); @@ -2009,7 +2014,7 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi // avoid splitting the network between upgraded and // non-upgraded nodes. CScriptCheck check2(*coins, tx, i, - flags & ~STANDARD_NOT_MANDATORY_VERIFY_FLAGS, cacheStore); + flags & ~STANDARD_NOT_MANDATORY_VERIFY_FLAGS, cacheStore, &txdata); if (check2()) return state.Invalid(false, REJECT_NONSTANDARD, strprintf("non-mandatory-script-verify-flag (%s)", ScriptErrorString(check.GetScriptError()))); } @@ -2405,6 +2410,8 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin std::vector<std::pair<uint256, CDiskTxPos> > vPos; vPos.reserve(block.vtx.size()); blockundo.vtxundo.reserve(block.vtx.size() - 1); + std::vector<PrecomputedTransactionData> txdata; + txdata.reserve(block.vtx.size()); // Required so that pointers to individual PrecomputedTransactionData don't get invalidated for (unsigned int i = 0; i < block.vtx.size(); i++) { const CTransaction &tx = block.vtx[i]; @@ -2451,13 +2458,14 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin return state.DoS(100, error("ConnectBlock(): too many sigops"), REJECT_INVALID, "bad-blk-sigops"); + txdata.emplace_back(tx); if (!tx.IsCoinBase()) { nFees += view.GetValueIn(tx)-tx.GetValueOut(); std::vector<CScriptCheck> vChecks; bool fCacheResults = fJustCheck; /* Don't cache results if we're actually connecting blocks (still consult the cache, though) */ - if (!CheckInputs(tx, state, view, fScriptChecks, flags, fCacheResults, nScriptCheckThreads ? &vChecks : NULL)) + if (!CheckInputs(tx, state, view, fScriptChecks, flags, fCacheResults, txdata[i], nScriptCheckThreads ? &vChecks : NULL)) return error("ConnectBlock(): CheckInputs on %s failed with %s", tx.GetHash().ToString(), FormatStateMessage(state)); control.Add(vChecks); @@ -4781,10 +4789,16 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam pfrom->PushMessage(NetMsgType::BLOCK, block); else if (inv.type == MSG_FILTERED_BLOCK) { - LOCK(pfrom->cs_filter); - if (pfrom->pfilter) + bool send = false; + CMerkleBlock merkleBlock; { - CMerkleBlock merkleBlock(block, *pfrom->pfilter); + LOCK(pfrom->cs_filter); + if (pfrom->pfilter) { + send = true; + merkleBlock = CMerkleBlock(block, *pfrom->pfilter); + } + } + if (send) { pfrom->PushMessage(NetMsgType::MERKLEBLOCK, merkleBlock); // CMerkleBlock just contains hashes, so also push any transactions in the block the client did not see // This avoids hurting performance by pointlessly requiring a round-trip @@ -5389,7 +5403,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, // we must use CBlocks, as CBlockHeaders won't include the 0x00 nTx count at the end vector<CBlock> vHeaders; int nLimit = MAX_HEADERS_RESULTS; - LogPrint("net", "getheaders %d to %s from peer=%d\n", (pindex ? pindex->nHeight : -1), hashStop.ToString(), pfrom->id); + LogPrint("net", "getheaders %d to %s from peer=%d\n", (pindex ? pindex->nHeight : -1), hashStop.IsNull() ? "end" : hashStop.ToString(), pfrom->id); for (; pindex; pindex = chainActive.Next(pindex)) { vHeaders.push_back(pindex->GetBlockHeader()); @@ -6046,8 +6060,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, CBloomFilter filter; vRecv >> filter; - LOCK(pfrom->cs_filter); - if (!filter.IsWithinSizeConstraints()) { // There is no excuse for sending a too-large filter @@ -6056,11 +6068,12 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, } else { + LOCK(pfrom->cs_filter); delete pfrom->pfilter; pfrom->pfilter = new CBloomFilter(filter); pfrom->pfilter->UpdateEmptyFull(); + pfrom->fRelayTxes = true; } - pfrom->fRelayTxes = true; } @@ -6071,20 +6084,21 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, // Nodes must NEVER send a data item > 520 bytes (the max size for a script data object, // and thus, the maximum size any matched object can have) in a filteradd message - if (vData.size() > MAX_SCRIPT_ELEMENT_SIZE) - { - LOCK(cs_main); - Misbehaving(pfrom->GetId(), 100); + bool bad = false; + if (vData.size() > MAX_SCRIPT_ELEMENT_SIZE) { + bad = true; } else { LOCK(pfrom->cs_filter); - if (pfrom->pfilter) + if (pfrom->pfilter) { pfrom->pfilter->insert(vData); - else - { - LOCK(cs_main); - Misbehaving(pfrom->GetId(), 100); + } else { + bad = true; } } + if (bad) { + LOCK(cs_main); + Misbehaving(pfrom->GetId(), 100); + } } @@ -6707,15 +6721,13 @@ bool SendMessages(CNode* pto) if (!pto->fDisconnect && !pto->fClient && (fFetch || !IsInitialBlockDownload()) && state.nBlocksInFlight < MAX_BLOCKS_IN_TRANSIT_PER_PEER) { vector<CBlockIndex*> vToDownload; NodeId staller = -1; - FindNextBlocksToDownload(pto->GetId(), MAX_BLOCKS_IN_TRANSIT_PER_PEER - state.nBlocksInFlight, vToDownload, staller); + FindNextBlocksToDownload(pto->GetId(), MAX_BLOCKS_IN_TRANSIT_PER_PEER - state.nBlocksInFlight, vToDownload, staller, consensusParams); BOOST_FOREACH(CBlockIndex *pindex, vToDownload) { - if (State(pto->GetId())->fHaveWitness || !IsWitnessEnabled(pindex->pprev, consensusParams)) { - uint32_t nFetchFlags = GetFetchFlags(pto, pindex->pprev, consensusParams); - vGetData.push_back(CInv(MSG_BLOCK | nFetchFlags, pindex->GetBlockHash())); - MarkBlockAsInFlight(pto->GetId(), pindex->GetBlockHash(), consensusParams, pindex); - LogPrint("net", "Requesting block %s (%d) peer=%d\n", pindex->GetBlockHash().ToString(), - pindex->nHeight, pto->id); - } + uint32_t nFetchFlags = GetFetchFlags(pto, pindex->pprev, consensusParams); + vGetData.push_back(CInv(MSG_BLOCK | nFetchFlags, pindex->GetBlockHash())); + MarkBlockAsInFlight(pto->GetId(), pindex->GetBlockHash(), consensusParams, pindex); + LogPrint("net", "Requesting block %s (%d) peer=%d\n", pindex->GetBlockHash().ToString(), + pindex->nHeight, pto->id); } if (state.nBlocksInFlight == 0 && staller != -1) { if (State(staller)->nStallingSince == 0) { diff --git a/src/main.h b/src/main.h index e9106fccf7..18d674612f 100644 --- a/src/main.h +++ b/src/main.h @@ -39,6 +39,7 @@ class CTxMemPool; class CValidationInterface; class CValidationState; +struct PrecomputedTransactionData; struct CNodeStateStats; struct LockPoints; @@ -191,7 +192,7 @@ extern uint64_t nPruneTarget; /** Block files containing a block-height within MIN_BLOCKS_TO_KEEP of chainActive.Tip() will not be pruned. */ static const unsigned int MIN_BLOCKS_TO_KEEP = 288; -static const signed int DEFAULT_CHECKBLOCKS = MIN_BLOCKS_TO_KEEP; +static const signed int DEFAULT_CHECKBLOCKS = 6; static const unsigned int DEFAULT_CHECKLEVEL = 3; // Require that user allocate at least 550MB for block & undo files (blk???.dat and rev???.dat) @@ -347,7 +348,7 @@ int64_t GetTransactionSigOpCost(const CTransaction& tx, const CCoinsViewCache& i * instead of being performed inline. */ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &view, bool fScriptChecks, - unsigned int flags, bool cacheStore, std::vector<CScriptCheck> *pvChecks = NULL); + unsigned int flags, bool cacheStore, PrecomputedTransactionData& txdata, std::vector<CScriptCheck> *pvChecks = NULL); /** Apply the effects of this transaction on the UTXO set represented by view */ void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, int nHeight); @@ -421,12 +422,13 @@ private: unsigned int nFlags; bool cacheStore; ScriptError error; + PrecomputedTransactionData *txdata; public: CScriptCheck(): amount(0), ptxTo(0), nIn(0), nFlags(0), cacheStore(false), error(SCRIPT_ERR_UNKNOWN_ERROR) {} - CScriptCheck(const CCoins& txFromIn, const CTransaction& txToIn, unsigned int nInIn, unsigned int nFlagsIn, bool cacheIn) : + CScriptCheck(const CCoins& txFromIn, const CTransaction& txToIn, unsigned int nInIn, unsigned int nFlagsIn, bool cacheIn, PrecomputedTransactionData* txdataIn) : scriptPubKey(txFromIn.vout[txToIn.vin[nInIn].prevout.n].scriptPubKey), amount(txFromIn.vout[txToIn.vin[nInIn].prevout.n].nValue), - ptxTo(&txToIn), nIn(nInIn), nFlags(nFlagsIn), cacheStore(cacheIn), error(SCRIPT_ERR_UNKNOWN_ERROR) { } + ptxTo(&txToIn), nIn(nInIn), nFlags(nFlagsIn), cacheStore(cacheIn), error(SCRIPT_ERR_UNKNOWN_ERROR), txdata(txdataIn) { } bool operator()(); @@ -438,6 +440,7 @@ public: std::swap(nFlags, check.nFlags); std::swap(cacheStore, check.cacheStore); std::swap(error, check.error); + std::swap(txdata, check.txdata); } ScriptError GetScriptError() const { return error; } diff --git a/src/net.cpp b/src/net.cpp index 957388b8fd..c5b080f794 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -70,7 +70,7 @@ namespace { SOCKET socket; bool whitelisted; - ListenSocket(SOCKET socket, bool whitelisted) : socket(socket), whitelisted(whitelisted) {} + ListenSocket(SOCKET _socket, bool _whitelisted) : socket(_socket), whitelisted(_whitelisted) {} }; } @@ -512,21 +512,21 @@ public: - void AddAddressKnown(const CAddress& addr) + void AddAddressKnown(const CAddress& _addr) { - addrKnown.insert(addr.GetKey()); + addrKnown.insert(_addr.GetKey()); } - void PushAddress(const CAddress& addr) + void PushAddress(const CAddress& _addr) { // Known checking here is only to save space from duplicates. // SendMessages will filter it again for knowns that were added // after addresses were pushed. - if (addr.IsValid() && !addrKnown.contains(addr.GetKey())) { + if (_addr.IsValid() && !addrKnown.contains(_addr.GetKey())) { if (vAddrToSend.size() >= MAX_ADDR_TO_SEND) { - vAddrToSend[insecure_rand() % vAddrToSend.size()] = addr; + vAddrToSend[insecure_rand() % vAddrToSend.size()] = _addr; } else { - vAddrToSend.push_back(addr); + vAddrToSend.push_back(_addr); } } } diff --git a/src/netaddress.cpp b/src/netaddress.cpp index 7000ce3f0a..db5cc3bc20 100644 --- a/src/netaddress.cpp +++ b/src/netaddress.cpp @@ -197,8 +197,8 @@ bool CNetAddr::IsValid() const return false; // unspecified IPv6 address (::/128) - unsigned char ipNone[16] = {}; - if (memcmp(ip, ipNone, 16) == 0) + unsigned char ipNone6[16] = {}; + if (memcmp(ip, ipNone6, 16) == 0) return false; // documentation IPv6 address diff --git a/src/netbase.cpp b/src/netbase.cpp index 4f243ec6f5..7d7f1b6788 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -631,8 +631,8 @@ bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest SplitHostPort(std::string(pszDest), port, strDest); - proxyType nameProxy; - GetNameProxy(nameProxy); + proxyType proxy; + GetNameProxy(proxy); std::vector<CService> addrResolved; if (Lookup(strDest.c_str(), addrResolved, port, fNameLookup && !HaveNameProxy(), 256)) { @@ -646,7 +646,7 @@ bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest if (!HaveNameProxy()) return false; - return ConnectThroughProxy(nameProxy, strDest, port, hSocketRet, nTimeout, outProxyConnectionFailed); + return ConnectThroughProxy(proxy, strDest, port, hSocketRet, nTimeout, outProxyConnectionFailed); } bool LookupSubNet(const char* pszName, CSubNet& ret) diff --git a/src/netbase.h b/src/netbase.h index bb12019a82..eb39d16578 100644 --- a/src/netbase.h +++ b/src/netbase.h @@ -29,7 +29,7 @@ class proxyType { public: proxyType(): randomize_credentials(false) {} - proxyType(const CService &proxy, bool randomize_credentials=false): proxy(proxy), randomize_credentials(randomize_credentials) {} + proxyType(const CService &_proxy, bool _randomize_credentials=false): proxy(_proxy), randomize_credentials(_randomize_credentials) {} bool IsValid() const { return proxy.IsValid(); } diff --git a/src/protocol.h b/src/protocol.h index 015215b2a6..9b474ec79c 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -267,6 +267,9 @@ enum ServiceFlags : uint64_t { // Indicates that a node can be asked for blocks and transactions including // witness data. NODE_WITNESS = (1 << 3), + // NODE_XTHIN means the node supports Xtreme Thinblocks + // If this is turned off then the node will not service nor make xthin requests + NODE_XTHIN = (1 << 4), // Bits 24-31 are reserved for temporary experiments. Just pick a bit that // isn't getting used, or one not being used much, and notify the diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index 947a4c6821..c00f5e8591 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -930,6 +930,9 @@ QString formatServicesStr(quint64 mask) case NODE_WITNESS: strList.append("WITNESS"); break; + case NODE_XTHIN: + strList.append("XTHIN"); + break; default: strList.append(QString("%1[%2]").arg("UNKNOWN").arg(check)); } diff --git a/src/rest.cpp b/src/rest.cpp index 2dff8d7dad..c815592124 100644 --- a/src/rest.cpp +++ b/src/rest.cpp @@ -420,7 +420,7 @@ static bool rest_getutxos(HTTPRequest* req, const std::string& strURIPart) // throw exception in case of a empty request std::string strRequestMutable = req->ReadBody(); if (strRequestMutable.length() == 0 && uriParts.size() == 0) - return RESTERR(req, HTTP_INTERNAL_SERVER_ERROR, "Error: empty request"); + return RESTERR(req, HTTP_BAD_REQUEST, "Error: empty request"); bool fInputParsed = false; bool fCheckMemPool = false; @@ -444,7 +444,7 @@ static bool rest_getutxos(HTTPRequest* req, const std::string& strURIPart) std::string strOutput = uriParts[i].substr(uriParts[i].find("-")+1); if (!ParseInt32(strOutput, &nOutput) || !IsHex(strTxid)) - return RESTERR(req, HTTP_INTERNAL_SERVER_ERROR, "Parse error"); + return RESTERR(req, HTTP_BAD_REQUEST, "Parse error"); txid.SetHex(strTxid); vOutPoints.push_back(COutPoint(txid, (uint32_t)nOutput)); @@ -453,7 +453,7 @@ static bool rest_getutxos(HTTPRequest* req, const std::string& strURIPart) if (vOutPoints.size() > 0) fInputParsed = true; else - return RESTERR(req, HTTP_INTERNAL_SERVER_ERROR, "Error: empty request"); + return RESTERR(req, HTTP_BAD_REQUEST, "Error: empty request"); } switch (rf) { @@ -469,7 +469,7 @@ static bool rest_getutxos(HTTPRequest* req, const std::string& strURIPart) if (strRequestMutable.size() > 0) { if (fInputParsed) //don't allow sending input over URI and HTTP RAW DATA - return RESTERR(req, HTTP_INTERNAL_SERVER_ERROR, "Combination of URI scheme inputs and raw post data is not allowed"); + return RESTERR(req, HTTP_BAD_REQUEST, "Combination of URI scheme inputs and raw post data is not allowed"); CDataStream oss(SER_NETWORK, PROTOCOL_VERSION); oss << strRequestMutable; @@ -478,14 +478,14 @@ static bool rest_getutxos(HTTPRequest* req, const std::string& strURIPart) } } catch (const std::ios_base::failure& e) { // abort in case of unreadable binary data - return RESTERR(req, HTTP_INTERNAL_SERVER_ERROR, "Parse error"); + return RESTERR(req, HTTP_BAD_REQUEST, "Parse error"); } break; } case RF_JSON: { if (!fInputParsed) - return RESTERR(req, HTTP_INTERNAL_SERVER_ERROR, "Error: empty request"); + return RESTERR(req, HTTP_BAD_REQUEST, "Error: empty request"); break; } default: { @@ -495,7 +495,7 @@ static bool rest_getutxos(HTTPRequest* req, const std::string& strURIPart) // limit max outpoints if (vOutPoints.size() > MAX_GETUTXOS_OUTPOINTS) - return RESTERR(req, HTTP_INTERNAL_SERVER_ERROR, strprintf("Error: max outpoints exceeded (max: %d, tried: %d)", MAX_GETUTXOS_OUTPOINTS, vOutPoints.size())); + return RESTERR(req, HTTP_BAD_REQUEST, strprintf("Error: max outpoints exceeded (max: %d, tried: %d)", MAX_GETUTXOS_OUTPOINTS, vOutPoints.size())); // check spentness and form a bitmap (as well as a JSON capable human-readable string representation) vector<unsigned char> bitmap; diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index e3c32d905a..b90410017b 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -632,7 +632,7 @@ struct CCoinsStats //! Calculate statistics about the unspent transaction output set static bool GetUTXOStats(CCoinsView *view, CCoinsStats &stats) { - boost::scoped_ptr<CCoinsViewCursor> pcursor(view->Cursor()); + std::unique_ptr<CCoinsViewCursor> pcursor(view->Cursor()); CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION); stats.hashBlock = pcursor->GetBestBlock(); @@ -1205,8 +1205,8 @@ static const CRPCCommand commands[] = { "hidden", "reconsiderblock", &reconsiderblock, true }, }; -void RegisterBlockchainRPCCommands(CRPCTable &tableRPC) +void RegisterBlockchainRPCCommands(CRPCTable &t) { for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++) - tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]); + t.appendCommand(commands[vcidx].name, &commands[vcidx]); } diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index d0675fdb49..3003ea3452 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -26,7 +26,6 @@ static const CRPCConvertParam vRPCConvertParams[] = { { "stop", 0 }, { "setmocktime", 0 }, - { "getaddednodeinfo", 0 }, { "generate", 0 }, { "generate", 1 }, { "generatetoaddress", 0 }, diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index a26340f3e4..14183c8e82 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -919,8 +919,8 @@ static const CRPCCommand commands[] = { "util", "estimatesmartpriority", &estimatesmartpriority, true }, }; -void RegisterMiningRPCCommands(CRPCTable &tableRPC) +void RegisterMiningRPCCommands(CRPCTable &t) { for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++) - tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]); + t.appendCommand(commands[vcidx].name, &commands[vcidx]); } diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index a8c5bcd177..e96feaa864 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -498,8 +498,8 @@ static const CRPCCommand commands[] = { "hidden", "setmocktime", &setmocktime, true }, }; -void RegisterMiscRPCCommands(CRPCTable &tableRPC) +void RegisterMiscRPCCommands(CRPCTable &t) { for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++) - tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]); + t.appendCommand(commands[vcidx].name, &commands[vcidx]); } diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index 4ce122648b..840bfd5a24 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -269,14 +269,13 @@ UniValue disconnectnode(const UniValue& params, bool fHelp) UniValue getaddednodeinfo(const UniValue& params, bool fHelp) { - if (fHelp || params.size() < 1 || params.size() > 2) + if (fHelp || params.size() > 1) throw runtime_error( - "getaddednodeinfo dummy ( \"node\" )\n" + "getaddednodeinfo ( \"node\" )\n" "\nReturns information about the given added node, or all added nodes\n" "(note that onetry addnodes are not listed here)\n" "\nArguments:\n" - "1. dummy (boolean, required) Kept for historical purposes but ignored\n" - "2. \"node\" (string, optional) If provided, return information about this specific node, otherwise all nodes are returned.\n" + "1. \"node\" (string, optional) If provided, return information about this specific node, otherwise all nodes are returned.\n" "\nResult:\n" "[\n" " {\n" @@ -299,10 +298,10 @@ UniValue getaddednodeinfo(const UniValue& params, bool fHelp) std::vector<AddedNodeInfo> vInfo = GetAddedNodeInfo(); - if (params.size() == 2) { + if (params.size() == 1) { bool found = false; for (const AddedNodeInfo& info : vInfo) { - if (info.strAddedNode == params[1].get_str()) { + if (info.strAddedNode == params[0].get_str()) { vInfo.assign(1, info); found = true; break; @@ -590,8 +589,8 @@ static const CRPCCommand commands[] = { "network", "clearbanned", &clearbanned, true }, }; -void RegisterNetRPCCommands(CRPCTable &tableRPC) +void RegisterNetRPCCommands(CRPCTable &t) { for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++) - tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]); + t.appendCommand(commands[vcidx].name, &commands[vcidx]); } diff --git a/src/rpc/protocol.h b/src/rpc/protocol.h index 55d0aac68b..988e0fc5fa 100644 --- a/src/rpc/protocol.h +++ b/src/rpc/protocol.h @@ -38,18 +38,18 @@ enum RPCErrorCode RPC_PARSE_ERROR = -32700, //! General application defined errors - RPC_MISC_ERROR = -1, //! std::exception thrown in command handling - RPC_FORBIDDEN_BY_SAFE_MODE = -2, //! Server is in safe mode, and command is not allowed in safe mode - RPC_TYPE_ERROR = -3, //! Unexpected type was passed as parameter - RPC_INVALID_ADDRESS_OR_KEY = -5, //! Invalid address or key - RPC_OUT_OF_MEMORY = -7, //! Ran out of memory during operation - RPC_INVALID_PARAMETER = -8, //! Invalid, missing or duplicate parameter - RPC_DATABASE_ERROR = -20, //! Database error - RPC_DESERIALIZATION_ERROR = -22, //! Error parsing or validating structure in raw format - RPC_VERIFY_ERROR = -25, //! General error during transaction or block submission - RPC_VERIFY_REJECTED = -26, //! Transaction or block was rejected by network rules - RPC_VERIFY_ALREADY_IN_CHAIN = -27, //! Transaction already in chain - RPC_IN_WARMUP = -28, //! Client still warming up + RPC_MISC_ERROR = -1, //!< std::exception thrown in command handling + RPC_FORBIDDEN_BY_SAFE_MODE = -2, //!< Server is in safe mode, and command is not allowed in safe mode + RPC_TYPE_ERROR = -3, //!< Unexpected type was passed as parameter + RPC_INVALID_ADDRESS_OR_KEY = -5, //!< Invalid address or key + RPC_OUT_OF_MEMORY = -7, //!< Ran out of memory during operation + RPC_INVALID_PARAMETER = -8, //!< Invalid, missing or duplicate parameter + RPC_DATABASE_ERROR = -20, //!< Database error + RPC_DESERIALIZATION_ERROR = -22, //!< Error parsing or validating structure in raw format + RPC_VERIFY_ERROR = -25, //!< General error during transaction or block submission + RPC_VERIFY_REJECTED = -26, //!< Transaction or block was rejected by network rules + RPC_VERIFY_ALREADY_IN_CHAIN = -27, //!< Transaction already in chain + RPC_IN_WARMUP = -28, //!< Client still warming up //! Aliases for backward compatibility RPC_TRANSACTION_ERROR = RPC_VERIFY_ERROR, @@ -57,23 +57,23 @@ enum RPCErrorCode RPC_TRANSACTION_ALREADY_IN_CHAIN= RPC_VERIFY_ALREADY_IN_CHAIN, //! P2P client errors - RPC_CLIENT_NOT_CONNECTED = -9, //! Bitcoin is not connected - RPC_CLIENT_IN_INITIAL_DOWNLOAD = -10, //! Still downloading initial blocks - RPC_CLIENT_NODE_ALREADY_ADDED = -23, //! Node is already added - RPC_CLIENT_NODE_NOT_ADDED = -24, //! Node has not been added before - RPC_CLIENT_NODE_NOT_CONNECTED = -29, //! Node to disconnect not found in connected nodes - RPC_CLIENT_INVALID_IP_OR_SUBNET = -30, //! Invalid IP/Subnet + RPC_CLIENT_NOT_CONNECTED = -9, //!< Bitcoin is not connected + RPC_CLIENT_IN_INITIAL_DOWNLOAD = -10, //!< Still downloading initial blocks + RPC_CLIENT_NODE_ALREADY_ADDED = -23, //!< Node is already added + RPC_CLIENT_NODE_NOT_ADDED = -24, //!< Node has not been added before + RPC_CLIENT_NODE_NOT_CONNECTED = -29, //!< Node to disconnect not found in connected nodes + RPC_CLIENT_INVALID_IP_OR_SUBNET = -30, //!< Invalid IP/Subnet //! Wallet errors - RPC_WALLET_ERROR = -4, //! Unspecified problem with wallet (key not found etc.) - RPC_WALLET_INSUFFICIENT_FUNDS = -6, //! Not enough funds in wallet or account - RPC_WALLET_INVALID_ACCOUNT_NAME = -11, //! Invalid account name - RPC_WALLET_KEYPOOL_RAN_OUT = -12, //! Keypool ran out, call keypoolrefill first - RPC_WALLET_UNLOCK_NEEDED = -13, //! Enter the wallet passphrase with walletpassphrase first - RPC_WALLET_PASSPHRASE_INCORRECT = -14, //! The wallet passphrase entered was incorrect - RPC_WALLET_WRONG_ENC_STATE = -15, //! Command given in wrong wallet encryption state (encrypting an encrypted wallet etc.) - RPC_WALLET_ENCRYPTION_FAILED = -16, //! Failed to encrypt the wallet - RPC_WALLET_ALREADY_UNLOCKED = -17, //! Wallet is already unlocked + RPC_WALLET_ERROR = -4, //!< Unspecified problem with wallet (key not found etc.) + RPC_WALLET_INSUFFICIENT_FUNDS = -6, //!< Not enough funds in wallet or account + RPC_WALLET_INVALID_ACCOUNT_NAME = -11, //!< Invalid account name + RPC_WALLET_KEYPOOL_RAN_OUT = -12, //!< Keypool ran out, call keypoolrefill first + RPC_WALLET_UNLOCK_NEEDED = -13, //!< Enter the wallet passphrase with walletpassphrase first + RPC_WALLET_PASSPHRASE_INCORRECT = -14, //!< The wallet passphrase entered was incorrect + RPC_WALLET_WRONG_ENC_STATE = -15, //!< Command given in wrong wallet encryption state (encrypting an encrypted wallet etc.) + RPC_WALLET_ENCRYPTION_FAILED = -16, //!< Failed to encrypt the wallet + RPC_WALLET_ALREADY_UNLOCKED = -17, //!< Wallet is already unlocked }; std::string JSONRPCRequest(const std::string& strMethod, const UniValue& params, const UniValue& id); diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index 3270cd384f..9461a7280c 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -910,8 +910,8 @@ static const CRPCCommand commands[] = { "blockchain", "verifytxoutproof", &verifytxoutproof, true }, }; -void RegisterRawTransactionRPCCommands(CRPCTable &tableRPC) +void RegisterRawTransactionRPCCommands(CRPCTable &t) { for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++) - tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]); + t.appendCommand(commands[vcidx].name, &commands[vcidx]); } diff --git a/src/rpc/register.h b/src/rpc/register.h index 01aa58a25d..49aee2365f 100644 --- a/src/rpc/register.h +++ b/src/rpc/register.h @@ -20,13 +20,13 @@ void RegisterMiningRPCCommands(CRPCTable &tableRPC); /** Register raw transaction RPC commands */ void RegisterRawTransactionRPCCommands(CRPCTable &tableRPC); -static inline void RegisterAllCoreRPCCommands(CRPCTable &tableRPC) +static inline void RegisterAllCoreRPCCommands(CRPCTable &t) { - RegisterBlockchainRPCCommands(tableRPC); - RegisterNetRPCCommands(tableRPC); - RegisterMiscRPCCommands(tableRPC); - RegisterMiningRPCCommands(tableRPC); - RegisterRawTransactionRPCCommands(tableRPC); + RegisterBlockchainRPCCommands(t); + RegisterNetRPCCommands(t); + RegisterMiscRPCCommands(t); + RegisterMiningRPCCommands(t); + RegisterRawTransactionRPCCommands(t); } #endif diff --git a/src/script/bitcoinconsensus.cpp b/src/script/bitcoinconsensus.cpp index 62fd9031f8..b629f4278b 100644 --- a/src/script/bitcoinconsensus.cpp +++ b/src/script/bitcoinconsensus.cpp @@ -84,8 +84,8 @@ static int verify_script(const unsigned char *scriptPubKey, unsigned int scriptP // Regardless of the verification result, the tx did not error. set_error(err, bitcoinconsensus_ERR_OK); - - return VerifyScript(tx.vin[nIn].scriptSig, CScript(scriptPubKey, scriptPubKey + scriptPubKeyLen), nIn < tx.wit.vtxinwit.size() ? &tx.wit.vtxinwit[nIn].scriptWitness : NULL, flags, TransactionSignatureChecker(&tx, nIn, amount), NULL); + PrecomputedTransactionData txdata(tx); + return VerifyScript(tx.vin[nIn].scriptSig, CScript(scriptPubKey, scriptPubKey + scriptPubKeyLen), nIn < tx.wit.vtxinwit.size() ? &tx.wit.vtxinwit[nIn].scriptWitness : NULL, flags, TransactionSignatureChecker(&tx, nIn, amount, txdata), NULL); } catch (const std::exception&) { return set_error(err, bitcoinconsensus_ERR_TX_DESERIALIZE); // Error deserializing } diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index bc027e9f0c..47ea261e31 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -1108,9 +1108,40 @@ public: } }; +uint256 GetPrevoutHash(const CTransaction& txTo) { + CHashWriter ss(SER_GETHASH, 0); + for (unsigned int n = 0; n < txTo.vin.size(); n++) { + ss << txTo.vin[n].prevout; + } + return ss.GetHash(); +} + +uint256 GetSequenceHash(const CTransaction& txTo) { + CHashWriter ss(SER_GETHASH, 0); + for (unsigned int n = 0; n < txTo.vin.size(); n++) { + ss << txTo.vin[n].nSequence; + } + return ss.GetHash(); +} + +uint256 GetOutputsHash(const CTransaction& txTo) { + CHashWriter ss(SER_GETHASH, 0); + for (unsigned int n = 0; n < txTo.vout.size(); n++) { + ss << txTo.vout[n]; + } + return ss.GetHash(); +} + } // anon namespace -uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, const CAmount& amount, SigVersion sigversion) +PrecomputedTransactionData::PrecomputedTransactionData(const CTransaction& txTo) +{ + hashPrevouts = GetPrevoutHash(txTo); + hashSequence = GetSequenceHash(txTo); + hashOutputs = GetOutputsHash(txTo); +} + +uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, const CAmount& amount, SigVersion sigversion, const PrecomputedTransactionData* cache) { if (sigversion == SIGVERSION_WITNESS_V0) { uint256 hashPrevouts; @@ -1118,27 +1149,16 @@ uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsig uint256 hashOutputs; if (!(nHashType & SIGHASH_ANYONECANPAY)) { - CHashWriter ss(SER_GETHASH, 0); - for (unsigned int n = 0; n < txTo.vin.size(); n++) { - ss << txTo.vin[n].prevout; - } - hashPrevouts = ss.GetHash(); // TODO: cache this value for all signatures in a transaction + hashPrevouts = cache ? cache->hashPrevouts : GetPrevoutHash(txTo); } if (!(nHashType & SIGHASH_ANYONECANPAY) && (nHashType & 0x1f) != SIGHASH_SINGLE && (nHashType & 0x1f) != SIGHASH_NONE) { - CHashWriter ss(SER_GETHASH, 0); - for (unsigned int n = 0; n < txTo.vin.size(); n++) { - ss << txTo.vin[n].nSequence; - } - hashSequence = ss.GetHash(); // TODO: cache this value for all signatures in a transaction + hashSequence = cache ? cache->hashSequence : GetSequenceHash(txTo); } + if ((nHashType & 0x1f) != SIGHASH_SINGLE && (nHashType & 0x1f) != SIGHASH_NONE) { - CHashWriter ss(SER_GETHASH, 0); - for (unsigned int n = 0; n < txTo.vout.size(); n++) { - ss << txTo.vout[n]; - } - hashOutputs = ss.GetHash(); // TODO: cache this value for all signatures in a transaction + hashOutputs = cache ? cache->hashOutputs : GetOutputsHash(txTo); } else if ((nHashType & 0x1f) == SIGHASH_SINGLE && nIn < txTo.vout.size()) { CHashWriter ss(SER_GETHASH, 0); ss << txTo.vout[nIn]; @@ -1209,7 +1229,7 @@ bool TransactionSignatureChecker::CheckSig(const vector<unsigned char>& vchSigIn int nHashType = vchSig.back(); vchSig.pop_back(); - uint256 sighash = SignatureHash(scriptCode, *txTo, nIn, nHashType, amount, sigversion); + uint256 sighash = SignatureHash(scriptCode, *txTo, nIn, nHashType, amount, sigversion, this->txdata); if (!VerifySignature(vchSig, pubkey, sighash)) return false; diff --git a/src/script/interpreter.h b/src/script/interpreter.h index bd2f211663..e5d7865cd3 100644 --- a/src/script/interpreter.h +++ b/src/script/interpreter.h @@ -98,13 +98,20 @@ enum bool CheckSignatureEncoding(const std::vector<unsigned char> &vchSig, unsigned int flags, ScriptError* serror); +struct PrecomputedTransactionData +{ + uint256 hashPrevouts, hashSequence, hashOutputs; + + PrecomputedTransactionData(const CTransaction& tx); +}; + enum SigVersion { SIGVERSION_BASE = 0, SIGVERSION_WITNESS_V0 = 1, }; -uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, const CAmount& amount, SigVersion sigversion); +uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, const CAmount& amount, SigVersion sigversion, const PrecomputedTransactionData* cache = NULL); class BaseSignatureChecker { @@ -133,12 +140,14 @@ private: const CTransaction* txTo; unsigned int nIn; const CAmount amount; + const PrecomputedTransactionData* txdata; protected: virtual bool VerifySignature(const std::vector<unsigned char>& vchSig, const CPubKey& vchPubKey, const uint256& sighash) const; public: - TransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn) : txTo(txToIn), nIn(nInIn), amount(amountIn) {} + TransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn) : txTo(txToIn), nIn(nInIn), amount(amountIn), txdata(NULL) {} + TransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn, const PrecomputedTransactionData& txdataIn) : txTo(txToIn), nIn(nInIn), amount(amountIn), txdata(&txdataIn) {} bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const; bool CheckLockTime(const CScriptNum& nLockTime) const; bool CheckSequence(const CScriptNum& nSequence) const; diff --git a/src/script/sigcache.h b/src/script/sigcache.h index 050bf8cc42..44551ec2bc 100644 --- a/src/script/sigcache.h +++ b/src/script/sigcache.h @@ -22,7 +22,7 @@ private: bool store; public: - CachingTransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CAmount& amount, bool storeIn) : TransactionSignatureChecker(txToIn, nInIn, amount), store(storeIn) {} + CachingTransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CAmount& amount, bool storeIn, PrecomputedTransactionData& txdataIn) : TransactionSignatureChecker(txToIn, nInIn, amount, txdataIn), store(storeIn) {} bool VerifySignature(const std::vector<unsigned char>& vchSig, const CPubKey& vchPubKey, const uint256& sighash) const; }; diff --git a/src/script/sign.h b/src/script/sign.h index 6404b4523e..f9aa6fca27 100644 --- a/src/script/sign.h +++ b/src/script/sign.h @@ -51,7 +51,7 @@ public: MutableTransactionSignatureCreator(const CKeyStore* keystoreIn, const CMutableTransaction* txToIn, unsigned int nInIn, const CAmount& amount, int nHashTypeIn) : TransactionSignatureCreator(keystoreIn, &tx, nInIn, amount, nHashTypeIn), tx(*txToIn) {} }; -/** A signature creator that just produces 72-byte empty signatyres. */ +/** A signature creator that just produces 72-byte empty signatures. */ class DummySignatureCreator : public BaseSignatureCreator { public: DummySignatureCreator(const CKeyStore* keystoreIn) : BaseSignatureCreator(keystoreIn) {} diff --git a/src/sync.h b/src/sync.h index 0c58fb6b4e..7733910749 100644 --- a/src/sync.h +++ b/src/sync.h @@ -171,7 +171,10 @@ public: typedef CMutexLock<CCriticalSection> CCriticalBlock; -#define LOCK(cs) CCriticalBlock criticalblock(cs, #cs, __FILE__, __LINE__) +#define PASTE(x, y) x ## y +#define PASTE2(x, y) PASTE(x, y) + +#define LOCK(cs) CCriticalBlock PASTE2(criticalblock, __COUNTER__)(cs, #cs, __FILE__, __LINE__) #define LOCK2(cs1, cs2) CCriticalBlock criticalblock1(cs1, #cs1, __FILE__, __LINE__), criticalblock2(cs2, #cs2, __FILE__, __LINE__) #define TRY_LOCK(cs, name) CCriticalBlock name(cs, #cs, __FILE__, __LINE__, true) diff --git a/src/test/blockencodings_tests.cpp b/src/test/blockencodings_tests.cpp index 3884bf3fe3..d2392cfb22 100644 --- a/src/test/blockencodings_tests.cpp +++ b/src/test/blockencodings_tests.cpp @@ -283,7 +283,6 @@ BOOST_AUTO_TEST_CASE(EmptyBlockRoundTripTest) std::vector<CTransaction> vtx_missing; BOOST_CHECK(partialBlock.FillBlock(block2, vtx_missing) == READ_STATUS_OK); BOOST_CHECK_EQUAL(block.GetHash().ToString(), block2.GetHash().ToString()); - bool mutated; BOOST_CHECK_EQUAL(block.hashMerkleRoot.ToString(), BlockMerkleRoot(block2, &mutated).ToString()); BOOST_CHECK(!mutated); } diff --git a/src/test/dbwrapper_tests.cpp b/src/test/dbwrapper_tests.cpp index a0bdcf4afb..d4d825d199 100644 --- a/src/test/dbwrapper_tests.cpp +++ b/src/test/dbwrapper_tests.cpp @@ -101,7 +101,7 @@ BOOST_AUTO_TEST_CASE(dbwrapper_iterator) uint256 in2 = GetRandHash(); BOOST_CHECK(dbw.Write(key2, in2)); - boost::scoped_ptr<CDBIterator> it(const_cast<CDBWrapper*>(&dbw)->NewIterator()); + std::unique_ptr<CDBIterator> it(const_cast<CDBWrapper*>(&dbw)->NewIterator()); // Be sure to seek past the obfuscation key (if it exists) it->Seek(key); @@ -214,7 +214,7 @@ BOOST_AUTO_TEST_CASE(iterator_ordering) BOOST_CHECK(dbw.Write(key, value)); } - boost::scoped_ptr<CDBIterator> it(const_cast<CDBWrapper*>(&dbw)->NewIterator()); + std::unique_ptr<CDBIterator> it(const_cast<CDBWrapper*>(&dbw)->NewIterator()); for (int c=0; c<2; ++c) { int seek_start; if (c == 0) @@ -290,7 +290,7 @@ BOOST_AUTO_TEST_CASE(iterator_string_ordering) } } - boost::scoped_ptr<CDBIterator> it(const_cast<CDBWrapper*>(&dbw)->NewIterator()); + std::unique_ptr<CDBIterator> it(const_cast<CDBWrapper*>(&dbw)->NewIterator()); for (int c=0; c<2; ++c) { int seek_start; if (c == 0) diff --git a/src/test/script_P2SH_tests.cpp b/src/test/script_P2SH_tests.cpp index 5224b57ca4..1a01593a8e 100644 --- a/src/test/script_P2SH_tests.cpp +++ b/src/test/script_P2SH_tests.cpp @@ -107,18 +107,20 @@ BOOST_AUTO_TEST_CASE(sign) } // All of the above should be OK, and the txTos have valid signatures // Check to make sure signature verification fails if we use the wrong ScriptSig: - for (int i = 0; i < 8; i++) + for (int i = 0; i < 8; i++) { + PrecomputedTransactionData txdata(txTo[i]); for (int j = 0; j < 8; j++) { CScript sigSave = txTo[i].vin[0].scriptSig; txTo[i].vin[0].scriptSig = txTo[j].vin[0].scriptSig; - bool sigOK = CScriptCheck(CCoins(txFrom, 0), txTo[i], 0, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC, false)(); + bool sigOK = CScriptCheck(CCoins(txFrom, 0), txTo[i], 0, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC, false, &txdata)(); if (i == j) BOOST_CHECK_MESSAGE(sigOK, strprintf("VerifySignature %d %d", i, j)); else BOOST_CHECK_MESSAGE(!sigOK, strprintf("VerifySignature %d %d", i, j)); txTo[i].vin[0].scriptSig = sigSave; } + } } BOOST_AUTO_TEST_CASE(norecurse) diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp index fd4f174b40..b5af400bc5 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -7,6 +7,7 @@ #include "test/test_bitcoin.h" #include "clientversion.h" +#include "checkqueue.h" #include "consensus/validation.h" #include "core_io.h" #include "key.h" @@ -153,6 +154,7 @@ BOOST_AUTO_TEST_CASE(tx_valid) BOOST_CHECK_MESSAGE(CheckTransaction(tx, state), strTest); BOOST_CHECK(state.IsValid()); + PrecomputedTransactionData txdata(tx); for (unsigned int i = 0; i < tx.vin.size(); i++) { if (!mapprevOutScriptPubKeys.count(tx.vin[i].prevout)) @@ -168,7 +170,7 @@ BOOST_AUTO_TEST_CASE(tx_valid) unsigned int verify_flags = ParseScriptFlags(test[2].get_str()); const CScriptWitness *witness = (i < tx.wit.vtxinwit.size()) ? &tx.wit.vtxinwit[i].scriptWitness : NULL; BOOST_CHECK_MESSAGE(VerifyScript(tx.vin[i].scriptSig, mapprevOutScriptPubKeys[tx.vin[i].prevout], - witness, verify_flags, TransactionSignatureChecker(&tx, i, amount), &err), + witness, verify_flags, TransactionSignatureChecker(&tx, i, amount, txdata), &err), strTest); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); } @@ -237,6 +239,7 @@ BOOST_AUTO_TEST_CASE(tx_invalid) CValidationState state; fValid = CheckTransaction(tx, state) && state.IsValid(); + PrecomputedTransactionData txdata(tx); for (unsigned int i = 0; i < tx.vin.size() && fValid; i++) { if (!mapprevOutScriptPubKeys.count(tx.vin[i].prevout)) @@ -252,7 +255,7 @@ BOOST_AUTO_TEST_CASE(tx_invalid) } const CScriptWitness *witness = (i < tx.wit.vtxinwit.size()) ? &tx.wit.vtxinwit[i].scriptWitness : NULL; fValid = VerifyScript(tx.vin[i].scriptSig, mapprevOutScriptPubKeys[tx.vin[i].prevout], - witness, verify_flags, TransactionSignatureChecker(&tx, i, amount), &err); + witness, verify_flags, TransactionSignatureChecker(&tx, i, amount, txdata), &err); } BOOST_CHECK_MESSAGE(!fValid, strTest); BOOST_CHECK_MESSAGE(err != SCRIPT_ERR_OK, ScriptErrorString(err)); @@ -419,6 +422,86 @@ void ReplaceRedeemScript(CScript& script, const CScript& redeemScript) script = PushAll(stack); } +BOOST_AUTO_TEST_CASE(test_big_witness_transaction) { + CMutableTransaction mtx; + mtx.nVersion = 1; + + CKey key; + key.MakeNewKey(false); + CBasicKeyStore keystore; + keystore.AddKeyPubKey(key, key.GetPubKey()); + CKeyID hash = key.GetPubKey().GetID(); + CScript scriptPubKey = CScript() << OP_0 << std::vector<unsigned char>(hash.begin(), hash.end()); + + vector<int> sigHashes; + sigHashes.push_back(SIGHASH_NONE | SIGHASH_ANYONECANPAY); + sigHashes.push_back(SIGHASH_SINGLE | SIGHASH_ANYONECANPAY); + sigHashes.push_back(SIGHASH_ALL | SIGHASH_ANYONECANPAY); + sigHashes.push_back(SIGHASH_NONE); + sigHashes.push_back(SIGHASH_SINGLE); + sigHashes.push_back(SIGHASH_ALL); + + // create a big transaction of 4500 inputs signed by the same key + for(uint32_t ij = 0; ij < 4500; ij++) { + uint32_t i = mtx.vin.size(); + uint256 prevId; + prevId.SetHex("0000000000000000000000000000000000000000000000000000000000000100"); + COutPoint outpoint(prevId, i); + + mtx.vin.resize(mtx.vin.size() + 1); + mtx.vin[i].prevout = outpoint; + mtx.vin[i].scriptSig = CScript(); + + mtx.vout.resize(mtx.vout.size() + 1); + mtx.vout[i].nValue = 1000; + mtx.vout[i].scriptPubKey = CScript() << OP_1; + } + + // sign all inputs + for(uint32_t i = 0; i < mtx.vin.size(); i++) { + bool hashSigned = SignSignature(keystore, scriptPubKey, mtx, i, 1000, sigHashes.at(i % sigHashes.size())); + assert(hashSigned); + } + + CTransaction tx; + CDataStream ssout(SER_NETWORK, PROTOCOL_VERSION); + WithOrVersion(&ssout, 0) << mtx; + WithOrVersion(&ssout, 0) >> tx; + + // check all inputs concurrently, with the cache + PrecomputedTransactionData txdata(tx); + boost::thread_group threadGroup; + CCheckQueue<CScriptCheck> scriptcheckqueue(128); + CCheckQueueControl<CScriptCheck> control(&scriptcheckqueue); + + for (int i=0; i<20; i++) + threadGroup.create_thread(boost::bind(&CCheckQueue<CScriptCheck>::Thread, boost::ref(scriptcheckqueue))); + + CCoins coins; + coins.nVersion = 1; + coins.fCoinBase = false; + for(uint32_t i = 0; i < mtx.vin.size(); i++) { + CTxOut txout; + txout.nValue = 1000; + txout.scriptPubKey = scriptPubKey; + coins.vout.push_back(txout); + } + + for(uint32_t i = 0; i < mtx.vin.size(); i++) { + std::vector<CScriptCheck> vChecks; + CScriptCheck check(coins, tx, i, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, false, &txdata); + vChecks.push_back(CScriptCheck()); + check.swap(vChecks.back()); + control.Add(vChecks); + } + + bool controlCheck = control.Wait(); + assert(controlCheck); + + threadGroup.interrupt_all(); + threadGroup.join_all(); +} + BOOST_AUTO_TEST_CASE(test_witness) { CBasicKeyStore keystore, keystore2; diff --git a/src/txdb.cpp b/src/txdb.cpp index 078c29def3..4f11c7b951 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -173,7 +173,7 @@ bool CBlockTreeDB::ReadFlag(const std::string &name, bool &fValue) { bool CBlockTreeDB::LoadBlockIndexGuts(boost::function<CBlockIndex*(const uint256&)> insertBlockIndex) { - boost::scoped_ptr<CDBIterator> pcursor(NewIterator()); + std::unique_ptr<CDBIterator> pcursor(NewIterator()); pcursor->Seek(make_pair(DB_BLOCK_INDEX, uint256())); diff --git a/src/txdb.h b/src/txdb.h index 5b98d2792c..adb3f66327 100644 --- a/src/txdb.h +++ b/src/txdb.h @@ -92,7 +92,7 @@ public: private: CCoinsViewDBCursor(CDBIterator* pcursorIn, const uint256 &hashBlockIn): CCoinsViewCursor(hashBlockIn), pcursor(pcursorIn) {} - boost::scoped_ptr<CDBIterator> pcursor; + std::unique_ptr<CDBIterator> pcursor; std::pair<char, uint256> keyTmp; friend class CCoinsViewDB; diff --git a/src/txmempool.cpp b/src/txmempool.cpp index b631c48484..0a00d757a2 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -576,7 +576,6 @@ void CTxMemPool::removeForReorg(const CCoinsViewCache *pcoins, unsigned int nMem void CTxMemPool::removeConflicts(const CTransaction &tx, std::list<CTransaction>& removed) { // Remove transactions which depend on inputs of tx, recursively - list<CTransaction> result; LOCK(cs); BOOST_FOREACH(const CTxIn &txin, tx.vin) { auto it = mapNextTx.find(txin.prevout); diff --git a/src/util.cpp b/src/util.cpp index 9a9209c621..c7d147a11e 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -107,7 +107,6 @@ map<string, vector<string> > mapMultiArgs; bool fDebug = false; bool fPrintToConsole = false; bool fPrintToDebugLog = true; -bool fDaemon = false; bool fServer = false; string strMiscWarning; bool fLogTimestamps = DEFAULT_LOGTIMESTAMPS; @@ -801,11 +800,10 @@ int GetNumCores() std::string CopyrightHolders(const std::string& strPrefix) { - std::string strCopyrightHolders = strPrefix + _(COPYRIGHT_HOLDERS); - if (strCopyrightHolders.find("%s") != strCopyrightHolders.npos) { - strCopyrightHolders = strprintf(strCopyrightHolders, _(COPYRIGHT_HOLDERS_SUBSTITUTION)); - } - if (strCopyrightHolders.find("Bitcoin Core developers") == strCopyrightHolders.npos) { + std::string strCopyrightHolders = strPrefix + strprintf(_(COPYRIGHT_HOLDERS), _(COPYRIGHT_HOLDERS_SUBSTITUTION)); + + // Check for untranslated substitution to make sure Bitcoin Core copyright is not removed by accident + if (strprintf(COPYRIGHT_HOLDERS, COPYRIGHT_HOLDERS_SUBSTITUTION).find("Bitcoin Core") == std::string::npos) { strCopyrightHolders += "\n" + strPrefix + "The Bitcoin Core developers"; } return strCopyrightHolders; diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp index cfd007ca1c..a809c9ad64 100644 --- a/src/wallet/db.cpp +++ b/src/wallet/db.cpp @@ -43,7 +43,7 @@ void CDBEnv::EnvShutdown() if (ret != 0) LogPrintf("CDBEnv::EnvShutdown: Error %d shutting down database environment: %s\n", ret, DbEnv::strerror(ret)); if (!fMockDb) - DbEnv(0).remove(strPath.c_str(), 0); + DbEnv((u_int32_t)0).remove(strPath.c_str(), 0); } void CDBEnv::Reset() @@ -387,11 +387,11 @@ bool CDB::Rewrite(const string& strFile, const char* pszSkip) while (fSuccess) { CDataStream ssKey(SER_DISK, CLIENT_VERSION); CDataStream ssValue(SER_DISK, CLIENT_VERSION); - int ret = db.ReadAtCursor(pcursor, ssKey, ssValue, DB_NEXT); - if (ret == DB_NOTFOUND) { + int ret1 = db.ReadAtCursor(pcursor, ssKey, ssValue); + if (ret1 == DB_NOTFOUND) { pcursor->close(); break; - } else if (ret != 0) { + } else if (ret1 != 0) { pcursor->close(); fSuccess = false; break; diff --git a/src/wallet/db.h b/src/wallet/db.h index 01b8c71a04..a0f673ecfc 100644 --- a/src/wallet/db.h +++ b/src/wallet/db.h @@ -228,19 +228,17 @@ protected: return pcursor; } - int ReadAtCursor(Dbc* pcursor, CDataStream& ssKey, CDataStream& ssValue, unsigned int fFlags = DB_NEXT) + int ReadAtCursor(Dbc* pcursor, CDataStream& ssKey, CDataStream& ssValue, bool setRange = false) { // Read at cursor Dbt datKey; - if (fFlags == DB_SET || fFlags == DB_SET_RANGE || fFlags == DB_GET_BOTH || fFlags == DB_GET_BOTH_RANGE) { + unsigned int fFlags = DB_NEXT; + if (setRange) { datKey.set_data(&ssKey[0]); datKey.set_size(ssKey.size()); + fFlags = DB_SET_RANGE; } Dbt datValue; - if (fFlags == DB_GET_BOTH || fFlags == DB_GET_BOTH_RANGE) { - datValue.set_data(&ssValue[0]); - datValue.set_size(ssValue.size()); - } datKey.set_flags(DB_DBT_MALLOC); datValue.set_flags(DB_DBT_MALLOC); int ret = pcursor->get(&datKey, &datValue, fFlags); diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index fe8b53ceb0..42ebdb9b9b 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -257,14 +257,13 @@ UniValue importprunedfunds(const UniValue& params, bool fHelp) if (!EnsureWalletIsAvailable(fHelp)) return NullUniValue; - if (fHelp || params.size() < 2 || params.size() > 3) + if (fHelp || params.size() != 2) throw runtime_error( "importprunedfunds\n" "\nImports funds without rescan. Corresponding address or script must previously be included in wallet. Aimed towards pruned wallets. The end-user is responsible to import additional transactions that subsequently spend the imported outputs or rescan after the point in the blockchain the transaction is included.\n" "\nArguments:\n" "1. \"rawtransaction\" (string, required) A raw transaction in hex funding an already-existing address in wallet\n" "2. \"txoutproof\" (string, required) The hex output from gettxoutproof that contains the transaction\n" - "3. \"label\" (string, optional) An optional label\n" ); CTransaction tx; @@ -277,10 +276,6 @@ UniValue importprunedfunds(const UniValue& params, bool fHelp) CMerkleBlock merkleBlock; ssMB >> merkleBlock; - string strLabel = ""; - if (params.size() == 3) - strLabel = params[2].get_str(); - //Search partial merkle tree in proof for our transaction and index in valid block vector<uint256> vMatch; vector<unsigned int> vIndex; diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index aa0a9374c1..0ba6706baf 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -1176,10 +1176,10 @@ UniValue ListReceived(const UniValue& params, bool fByAccounts) if (fByAccounts) { - tallyitem& item = mapAccountTally[strAccount]; - item.nAmount += nAmount; - item.nConf = min(item.nConf, nConf); - item.fIsWatchonly = fIsWatchonly; + tallyitem& _item = mapAccountTally[strAccount]; + _item.nAmount += nAmount; + _item.nConf = min(_item.nConf, nConf); + _item.fIsWatchonly = fIsWatchonly; } else { @@ -1195,9 +1195,9 @@ UniValue ListReceived(const UniValue& params, bool fByAccounts) UniValue transactions(UniValue::VARR); if (it != mapTally.end()) { - BOOST_FOREACH(const uint256& item, (*it).second.txids) + BOOST_FOREACH(const uint256& _item, (*it).second.txids) { - transactions.push_back(item.GetHex()); + transactions.push_back(_item.GetHex()); } } obj.push_back(Pair("txids", transactions)); @@ -2617,8 +2617,8 @@ static const CRPCCommand commands[] = { "wallet", "removeprunedfunds", &removeprunedfunds, true }, }; -void RegisterWalletRPCCommands(CRPCTable &tableRPC) +void RegisterWalletRPCCommands(CRPCTable &t) { for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++) - tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]); + t.appendCommand(commands[vcidx].name, &commands[vcidx]); } diff --git a/src/wallet/rpcwallet.h b/src/wallet/rpcwallet.h index a5de7e2de1..3a68ccf1b2 100644 --- a/src/wallet/rpcwallet.h +++ b/src/wallet/rpcwallet.h @@ -7,6 +7,6 @@ class CRPCTable; -void RegisterWalletRPCCommands(CRPCTable &tableRPC); +void RegisterWalletRPCCommands(CRPCTable &t); #endif //BITCOIN_WALLET_RPCWALLET_H diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp index c6c5058984..acf980c784 100644 --- a/src/wallet/test/wallet_tests.cpp +++ b/src/wallet/test/wallet_tests.cpp @@ -217,7 +217,7 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests) // run the 'mtgox' test (see http://blockexplorer.com/tx/29a3efd3ef04f9153d47a990bd7b048a4b2d213daaa5fb8ed670fb85f13bdbcf) // they tried to consolidate 10 50k coins into one 500k coin, and ended up with 50k in change empty_wallet(); - for (int i = 0; i < 20; i++) + for (int j = 0; j < 20; j++) add_coin(50000 * COIN); BOOST_CHECK( wallet.SelectCoinsMinConf(500000 * COIN, 1, 1, vCoins, setCoinsRet, nValueRet)); @@ -296,7 +296,7 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests) BOOST_CHECK(!equal_sets(setCoinsRet, setCoinsRet2)); int fails = 0; - for (int i = 0; i < RANDOM_REPEATS; i++) + for (int j = 0; j < RANDOM_REPEATS; j++) { // selecting 1 from 100 identical coins depends on the shuffle; this test will fail 1% of the time // run the test RANDOM_REPEATS times and only complain if all of them fail @@ -317,7 +317,7 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests) add_coin(25 * CENT); fails = 0; - for (int i = 0; i < RANDOM_REPEATS; i++) + for (int j = 0; j < RANDOM_REPEATS; j++) { // selecting 1 from 100 identical coins depends on the shuffle; this test will fail 1% of the time // run the test RANDOM_REPEATS times and only complain if all of them fail diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 769322969d..10aca2e499 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2461,7 +2461,6 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey) AddToWallet(wtxNew); // Notify that old coins are spent - set<CWalletTx*> setCoins; BOOST_FOREACH(const CTxIn& txin, wtxNew.vin) { CWalletTx &coin = mapWallet[txin.prevout.hash]; diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index e6e9fc484b..80bfe8255d 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -18,7 +18,6 @@ #include <boost/version.hpp> #include <boost/filesystem.hpp> #include <boost/foreach.hpp> -#include <boost/scoped_ptr.hpp> #include <boost/thread.hpp> using namespace std; @@ -216,16 +215,16 @@ void CWalletDB::ListAccountCreditDebit(const string& strAccount, list<CAccountin Dbc* pcursor = GetCursor(); if (!pcursor) throw runtime_error(std::string(__func__) + ": cannot create DB cursor"); - unsigned int fFlags = DB_SET_RANGE; + bool setRange = true; while (true) { // Read next record CDataStream ssKey(SER_DISK, CLIENT_VERSION); - if (fFlags == DB_SET_RANGE) + if (setRange) ssKey << std::make_pair(std::string("acentry"), std::make_pair((fAllAccounts ? string("") : strAccount), uint64_t(0))); CDataStream ssValue(SER_DISK, CLIENT_VERSION); - int ret = ReadAtCursor(pcursor, ssKey, ssValue, fFlags); - fFlags = DB_NEXT; + int ret = ReadAtCursor(pcursor, ssKey, ssValue, setRange); + setRange = false; if (ret == DB_NOTFOUND) break; else if (ret != 0) @@ -887,8 +886,8 @@ void ThreadFlushWalletDB(const string& strFile) if (nRefCount == 0) { boost::this_thread::interruption_point(); - map<string, int>::iterator mi = bitdb.mapFileUseCount.find(strFile); - if (mi != bitdb.mapFileUseCount.end()) + map<string, int>::iterator _mi = bitdb.mapFileUseCount.find(strFile); + if (_mi != bitdb.mapFileUseCount.end()) { LogPrint("db", "Flushing %s\n", strFile); nLastFlushed = nWalletDBUpdated; @@ -898,7 +897,7 @@ void ThreadFlushWalletDB(const string& strFile) bitdb.CloseDb(strFile); bitdb.CheckpointLSN(strFile); - bitdb.mapFileUseCount.erase(mi++); + bitdb.mapFileUseCount.erase(_mi++); LogPrint("db", "Flushed %s %dms\n", strFile, GetTimeMillis() - nStart); } } @@ -941,7 +940,7 @@ bool CWalletDB::Recover(CDBEnv& dbenv, const std::string& filename, bool fOnlyKe } LogPrintf("Salvage(aggressive) found %u records\n", salvagedData.size()); - boost::scoped_ptr<Db> pdbCopy(new Db(dbenv.dbenv, 0)); + std::unique_ptr<Db> pdbCopy(new Db(dbenv.dbenv, 0)); int ret = pdbCopy->open(NULL, // Txn pointer filename.c_str(), // Filename "main", // Logical db name diff --git a/src/zmq/zmqpublishnotifier.h b/src/zmq/zmqpublishnotifier.h index 22f02a3d0d..751ded3957 100644 --- a/src/zmq/zmqpublishnotifier.h +++ b/src/zmq/zmqpublishnotifier.h @@ -12,7 +12,7 @@ class CBlockIndex; class CZMQAbstractPublishNotifier : public CZMQAbstractNotifier { private: - uint32_t nSequence; //! upcounting per message sequence number + uint32_t nSequence; //!< upcounting per message sequence number public: |