From 5e478618e6d03af98774626a14081587af850e5b Mon Sep 17 00:00:00 2001 From: Peter Todd Date: Wed, 27 May 2015 21:02:04 -0400 Subject: [PATCH 01/19] Improve comment explaining purpose of MAX_MONEY constant --- src/amount.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/amount.h b/src/amount.h index 9212244a8..7dc62edac 100644 --- a/src/amount.h +++ b/src/amount.h @@ -16,7 +16,15 @@ typedef int64_t CAmount; static const CAmount COIN = 100000000; static const CAmount CENT = 1000000; -/** No amount larger than this (in satoshi) is valid */ +/** No amount larger than this (in satoshi) is valid. + * + * Note that this constant is *not* the total money supply, which in Bitcoin + * currently happens to be less than 21,000,000 BTC for various reasons, but + * rather a sanity check. As this sanity check is used by consensus-critical + * validation code, the exact value of the MAX_MONEY constant is consensus + * critical; in unusual circumstances like a(nother) overflow bug that allowed + * for the creation of coins out of thin air modification could lead to a fork. + * */ static const CAmount MAX_MONEY = 21000000 * COIN; inline bool MoneyRange(const CAmount& nValue) { return (nValue >= 0 && nValue <= MAX_MONEY); } From db954a65ac01df85e8f53bf2f2b72b2644443a4a Mon Sep 17 00:00:00 2001 From: Philip Kaufmann Date: Sun, 31 May 2015 15:36:44 +0200 Subject: [PATCH 02/19] use const references where appropriate --- src/alert.cpp | 4 ++-- src/alert.h | 2 +- src/consensus/validation.h | 2 +- src/core_io.h | 2 +- src/core_read.cpp | 2 +- src/init.cpp | 20 ++++++++++---------- src/main.cpp | 6 +++--- src/main.h | 2 +- src/net.cpp | 21 ++++++++++----------- src/net.h | 4 ++-- src/rpcmining.cpp | 3 +-- src/rpcnet.cpp | 17 ++++++++--------- src/rpcserver.cpp | 10 ++++++---- src/rpcserver.h | 10 +++++----- src/util.cpp | 2 +- src/util.h | 2 +- src/utilstrencodings.cpp | 2 +- src/utilstrencodings.h | 4 ++-- src/wallet/wallet.cpp | 2 +- src/wallet/wallet.h | 4 ++-- 20 files changed, 60 insertions(+), 61 deletions(-) diff --git a/src/alert.cpp b/src/alert.cpp index 6e41b11a2..ea9cbad21 100644 --- a/src/alert.cpp +++ b/src/alert.cpp @@ -50,7 +50,7 @@ std::string CUnsignedAlert::ToString() const BOOST_FOREACH(int n, setCancel) strSetCancel += strprintf("%d ", n); std::string strSetSubVer; - BOOST_FOREACH(std::string str, setSubVer) + BOOST_FOREACH(const std::string& str, setSubVer) strSetSubVer += "\"" + str + "\" "; return strprintf( "CAlert(\n" @@ -112,7 +112,7 @@ bool CAlert::Cancels(const CAlert& alert) const return (alert.nID <= nCancel || setCancel.count(alert.nID)); } -bool CAlert::AppliesTo(int nVersion, std::string strSubVerIn) const +bool CAlert::AppliesTo(int nVersion, const std::string& strSubVerIn) const { // TODO: rework for client-version-embedded-in-strSubVer ? return (IsInEffect() && diff --git a/src/alert.h b/src/alert.h index b5e1cd110..76d8d916e 100644 --- a/src/alert.h +++ b/src/alert.h @@ -97,7 +97,7 @@ public: uint256 GetHash() const; bool IsInEffect() const; bool Cancels(const CAlert& alert) const; - bool AppliesTo(int nVersion, std::string strSubVerIn) const; + bool AppliesTo(int nVersion, const std::string& strSubVerIn) const; bool AppliesToMe() const; bool RelayTo(CNode* pnode) const; bool CheckSignature(const std::vector& alertKey) const; diff --git a/src/consensus/validation.h b/src/consensus/validation.h index d0ea30bf4..c62adcd8f 100644 --- a/src/consensus/validation.h +++ b/src/consensus/validation.h @@ -48,7 +48,7 @@ public: unsigned char _chRejectCode=0, std::string _strRejectReason="") { return DoS(0, ret, _chRejectCode, _strRejectReason); } - virtual bool Error(std::string strRejectReasonIn="") { + virtual bool Error(const std::string& strRejectReasonIn) { if (mode == MODE_VALID) strRejectReason = strRejectReasonIn; mode = MODE_ERROR; diff --git a/src/core_io.h b/src/core_io.h index 0989cf743..115e3199d 100644 --- a/src/core_io.h +++ b/src/core_io.h @@ -15,7 +15,7 @@ class uint256; class UniValue; // core_read.cpp -extern CScript ParseScript(std::string s); +extern CScript ParseScript(const std::string& s); extern bool DecodeHexTx(CTransaction& tx, const std::string& strHexTx); extern bool DecodeHexBlk(CBlock&, const std::string& strHexBlk); extern uint256 ParseHashUV(const UniValue& v, const std::string& strName); diff --git a/src/core_read.cpp b/src/core_read.cpp index 1b3e9025d..4be24f8e0 100644 --- a/src/core_read.cpp +++ b/src/core_read.cpp @@ -22,7 +22,7 @@ using namespace std; -CScript ParseScript(std::string s) +CScript ParseScript(const std::string& s) { CScript result; diff --git a/src/init.cpp b/src/init.cpp index cff7bfd90..934feef09 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -612,7 +612,7 @@ void ThreadImport(std::vector vImportFiles) } // -loadblock= - BOOST_FOREACH(boost::filesystem::path &path, vImportFiles) { + BOOST_FOREACH(const boost::filesystem::path& path, vImportFiles) { FILE *file = fopen(path.string().c_str(), "rb"); if (file) { CImportingNow imp; @@ -1096,15 +1096,15 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) std::string warningString; std::string errorString; - + if (!CWallet::Verify(strWalletFile, warningString, errorString)) return false; - + if (!warningString.empty()) InitWarning(warningString); if (!errorString.empty()) return InitError(warningString); - + } // (!fDisableWallet) #endif // ENABLE_WALLET // ********************************************************* Step 6: network initialization @@ -1113,7 +1113,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) if (mapArgs.count("-onlynet")) { std::set nets; - BOOST_FOREACH(std::string snet, mapMultiArgs["-onlynet"]) { + BOOST_FOREACH(const std::string& snet, mapMultiArgs["-onlynet"]) { enum Network net = ParseNetwork(snet); if (net == NET_UNROUTABLE) return InitError(strprintf(_("Unknown network specified in -onlynet: '%s'"), snet)); @@ -1170,13 +1170,13 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) bool fBound = false; if (fListen) { if (mapArgs.count("-bind") || mapArgs.count("-whitebind")) { - BOOST_FOREACH(std::string strBind, mapMultiArgs["-bind"]) { + BOOST_FOREACH(const std::string& strBind, mapMultiArgs["-bind"]) { CService addrBind; if (!Lookup(strBind.c_str(), addrBind, GetListenPort(), false)) return InitError(strprintf(_("Cannot resolve -bind address: '%s'"), strBind)); fBound |= Bind(addrBind, (BF_EXPLICIT | BF_REPORT_ERROR)); } - BOOST_FOREACH(std::string strBind, mapMultiArgs["-whitebind"]) { + BOOST_FOREACH(const std::string& strBind, mapMultiArgs["-whitebind"]) { CService addrBind; if (!Lookup(strBind.c_str(), addrBind, 0, false)) return InitError(strprintf(_("Cannot resolve -whitebind address: '%s'"), strBind)); @@ -1196,7 +1196,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) } if (mapArgs.count("-externalip")) { - BOOST_FOREACH(string strAddr, mapMultiArgs["-externalip"]) { + BOOST_FOREACH(const std::string& strAddr, mapMultiArgs["-externalip"]) { CService addrLocal(strAddr, GetListenPort(), fNameLookup); if (!addrLocal.IsValid()) return InitError(strprintf(_("Cannot resolve -externalip address: '%s'"), strAddr)); @@ -1204,7 +1204,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) } } - BOOST_FOREACH(string strDest, mapMultiArgs["-seednode"]) + BOOST_FOREACH(const std::string& strDest, mapMultiArgs["-seednode"]) AddOneShot(strDest); #if ENABLE_ZMQ @@ -1572,7 +1572,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) std::vector vImportFiles; if (mapArgs.count("-loadblock")) { - BOOST_FOREACH(string strFile, mapMultiArgs["-loadblock"]) + BOOST_FOREACH(const std::string& strFile, mapMultiArgs["-loadblock"]) vImportFiles.push_back(strFile); } threadGroup.create_thread(boost::bind(&ThreadImport, vImportFiles)); diff --git a/src/main.cpp b/src/main.cpp index 207c0d458..d1ec9ca41 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -740,7 +740,7 @@ bool CheckFinalTx(const CTransaction &tx, int flags) /** * Check transaction inputs to mitigate two * potential denial-of-service attacks: - * + * * 1. scriptSigs with extra data stuffed into them, * not consumed by scriptPubKey (or P2SH script) * 2. P2SH scripts with a crazy number of expensive @@ -2457,7 +2457,7 @@ static int64_t nTimeFlush = 0; static int64_t nTimeChainState = 0; static int64_t nTimePostConnect = 0; -/** +/** * Connect a new block to chainActive. pblock is either NULL or a pointer to a CBlock * corresponding to pindexNew, to bypass loading it again from disk. */ @@ -4072,7 +4072,7 @@ void static CheckBlockIndex() // CAlert // -string GetWarnings(string strFor) +std::string GetWarnings(const std::string& strFor) { int nPriority = 0; string strStatusBar; diff --git a/src/main.h b/src/main.h index 289e908d2..30f67b4fb 100644 --- a/src/main.h +++ b/src/main.h @@ -207,7 +207,7 @@ void PartitionCheck(bool (*initialDownloadCheck)(), CCriticalSection& cs, const /** Check whether we are doing an initial block download (synchronizing from disk or network) */ bool IsInitialBlockDownload(); /** Format a string that describes several potential problems detected by the core */ -std::string GetWarnings(std::string strFor); +std::string GetWarnings(const std::string& strFor); /** Retrieve a transaction (from memory pool, or from disk, if possible) */ bool GetTransaction(const uint256 &hash, CTransaction &tx, uint256 &hashBlock, bool fAllowSlow = false); /** Find the best known block, and make it the tip of the block chain */ diff --git a/src/net.cpp b/src/net.cpp index 0a96d01f2..4ae5a6b2c 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -107,7 +107,7 @@ boost::condition_variable messageHandlerCondition; static CNodeSignals g_signals; CNodeSignals& GetNodeSignals() { return g_signals; } -void AddOneShot(string strDest) +void AddOneShot(const std::string& strDest) { LOCK(cs_vOneShots); vOneShots.push_back(strDest); @@ -1316,7 +1316,7 @@ void ThreadDNSAddressSeed() vector vAdd; if (LookupHost(seed.host.c_str(), vIPs)) { - BOOST_FOREACH(CNetAddr& ip, vIPs) + BOOST_FOREACH(const CNetAddr& ip, vIPs) { int nOneDay = 24*3600; CAddress addr = CAddress(CService(ip, Params().GetDefaultPort())); @@ -1380,7 +1380,7 @@ void ThreadOpenConnections() for (int64_t nLoop = 0;; nLoop++) { ProcessOneShot(); - BOOST_FOREACH(string strAddr, mapMultiArgs["-connect"]) + BOOST_FOREACH(const std::string& strAddr, mapMultiArgs["-connect"]) { CAddress addr; OpenNetworkConnection(addr, NULL, strAddr.c_str()); @@ -1483,10 +1483,10 @@ void ThreadOpenAddedConnections() list lAddresses(0); { LOCK(cs_vAddedNodes); - BOOST_FOREACH(string& strAddNode, vAddedNodes) + BOOST_FOREACH(const std::string& strAddNode, vAddedNodes) lAddresses.push_back(strAddNode); } - BOOST_FOREACH(string& strAddNode, lAddresses) { + BOOST_FOREACH(const std::string& strAddNode, lAddresses) { CAddress addr; CSemaphoreGrant grant(*semOutbound); OpenNetworkConnection(addr, &grant, strAddNode.c_str()); @@ -1501,20 +1501,19 @@ void ThreadOpenAddedConnections() list lAddresses(0); { LOCK(cs_vAddedNodes); - BOOST_FOREACH(string& strAddNode, vAddedNodes) + BOOST_FOREACH(const std::string& strAddNode, vAddedNodes) lAddresses.push_back(strAddNode); } list > lservAddressesToAdd(0); - BOOST_FOREACH(string& strAddNode, lAddresses) - { + BOOST_FOREACH(const std::string& strAddNode, lAddresses) { vector vservNode(0); if(Lookup(strAddNode.c_str(), vservNode, Params().GetDefaultPort(), fNameLookup, 0)) { lservAddressesToAdd.push_back(vservNode); { LOCK(cs_setservAddNodeAddresses); - BOOST_FOREACH(CService& serv, vservNode) + BOOST_FOREACH(const CService& serv, vservNode) setservAddNodeAddresses.insert(serv); } } @@ -1525,7 +1524,7 @@ void ThreadOpenAddedConnections() LOCK(cs_vNodes); BOOST_FOREACH(CNode* pnode, vNodes) for (list >::iterator it = lservAddressesToAdd.begin(); it != lservAddressesToAdd.end(); it++) - BOOST_FOREACH(CService& addrNode, *(it)) + BOOST_FOREACH(const CService& addrNode, *(it)) if (pnode->addr == addrNode) { it = lservAddressesToAdd.erase(it); @@ -2110,7 +2109,7 @@ bool CAddrDB::Read(CAddrMan& addr) unsigned int ReceiveFloodSize() { return 1000*GetArg("-maxreceivebuffer", 5*1000); } unsigned int SendBufferSize() { return 1000*GetArg("-maxsendbuffer", 1*1000); } -CNode::CNode(SOCKET hSocketIn, CAddress addrIn, std::string addrNameIn, bool fInboundIn) : +CNode::CNode(SOCKET hSocketIn, const CAddress& addrIn, const std::string& addrNameIn, bool fInboundIn) : ssSend(SER_NETWORK, INIT_PROTO_VERSION), addrKnown(5000, 0.001), setInventoryKnown(SendBufferSize() / 1000) diff --git a/src/net.h b/src/net.h index 50fb90dca..bf152b832 100644 --- a/src/net.h +++ b/src/net.h @@ -65,7 +65,7 @@ static const size_t SETASKFOR_MAX_SZ = 2 * MAX_INV_SZ; unsigned int ReceiveFloodSize(); unsigned int SendBufferSize(); -void AddOneShot(std::string strDest); +void AddOneShot(const std::string& strDest); void AddressCurrentlyConnected(const CService& addr); CNode* FindNode(const CNetAddr& ip); CNode* FindNode(const std::string& addrName); @@ -328,7 +328,7 @@ public: // Whether a ping is requested. bool fPingQueued; - CNode(SOCKET hSocketIn, CAddress addrIn, std::string addrNameIn = "", bool fInboundIn=false); + CNode(SOCKET hSocketIn, const CAddress &addrIn, const std::string &addrNameIn = "", bool fInboundIn = false); ~CNode(); private: diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp index dd622444e..b46c939c1 100644 --- a/src/rpcmining.cpp +++ b/src/rpcmining.cpp @@ -651,8 +651,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp) UniValue transactions(UniValue::VARR); map setTxIndex; int i = 0; - BOOST_FOREACH (CTransaction& tx, pblock->vtx) - { + BOOST_FOREACH (const CTransaction& tx, pblock->vtx) { uint256 txHash = tx.GetHash(); setTxIndex[txHash] = i++; diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp index 522edc741..d1c7c1051 100644 --- a/src/rpcnet.cpp +++ b/src/rpcnet.cpp @@ -253,19 +253,20 @@ UniValue getaddednodeinfo(const UniValue& params, bool fHelp) if (params.size() == 1) { LOCK(cs_vAddedNodes); - BOOST_FOREACH(string& strAddNode, vAddedNodes) + BOOST_FOREACH(const std::string& strAddNode, vAddedNodes) laddedNodes.push_back(strAddNode); } else { string strNode = params[1].get_str(); LOCK(cs_vAddedNodes); - BOOST_FOREACH(string& strAddNode, vAddedNodes) + BOOST_FOREACH(const std::string& strAddNode, vAddedNodes) { if (strAddNode == strNode) { laddedNodes.push_back(strAddNode); break; } + } if (laddedNodes.size() == 0) throw JSONRPCError(RPC_CLIENT_NODE_NOT_ADDED, "Error: Node has not been added."); } @@ -273,8 +274,7 @@ UniValue getaddednodeinfo(const UniValue& params, bool fHelp) UniValue ret(UniValue::VARR); if (!fDns) { - BOOST_FOREACH(string& strAddNode, laddedNodes) - { + BOOST_FOREACH (const std::string& strAddNode, laddedNodes) { UniValue obj(UniValue::VOBJ); obj.push_back(Pair("addednode", strAddNode)); ret.push_back(obj); @@ -283,8 +283,7 @@ UniValue getaddednodeinfo(const UniValue& params, bool fHelp) } list > > laddedAddreses(0); - BOOST_FOREACH(string& strAddNode, laddedNodes) - { + BOOST_FOREACH(const std::string& strAddNode, laddedNodes) { vector vservNode(0); if(Lookup(strAddNode.c_str(), vservNode, Params().GetDefaultPort(), fNameLookup, 0)) laddedAddreses.push_back(make_pair(strAddNode, vservNode)); @@ -306,12 +305,11 @@ UniValue getaddednodeinfo(const UniValue& params, bool fHelp) UniValue addresses(UniValue::VARR); bool fConnected = false; - BOOST_FOREACH(CService& addrNode, it->second) - { + BOOST_FOREACH(const CService& addrNode, it->second) { bool fFound = false; UniValue node(UniValue::VOBJ); node.push_back(Pair("address", addrNode.ToString())); - BOOST_FOREACH(CNode* pnode, vNodes) + BOOST_FOREACH(CNode* pnode, vNodes) { if (pnode->addr == addrNode) { fFound = true; @@ -319,6 +317,7 @@ UniValue getaddednodeinfo(const UniValue& params, bool fHelp) node.push_back(Pair("connected", pnode->fInbound ? "inbound" : "outbound")); break; } + } if (!fFound) node.push_back(Pair("connected", "false")); addresses.push_back(node); diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index 7414ec128..17c7cbf01 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -177,7 +177,7 @@ vector ParseHexO(const UniValue& o, string strKey) * Note: This interface may still be subject to change. */ -string CRPCTable::help(string strCommand) const +std::string CRPCTable::help(const std::string& strCommand) const { string strRet; string category; @@ -419,7 +419,7 @@ CRPCTable::CRPCTable() } } -const CRPCCommand *CRPCTable::operator[](string name) const +const CRPCCommand *CRPCTable::operator[](const std::string& name) const { map::const_iterator it = mapCommands.find(name); if (it == mapCommands.end()) @@ -1071,11 +1071,13 @@ UniValue CRPCTable::execute(const std::string &strMethod, const UniValue ¶ms g_rpcSignals.PostCommand(*pcmd); } -std::string HelpExampleCli(string methodname, string args){ +std::string HelpExampleCli(const std::string& methodname, const std::string& args) +{ return "> zcash-cli " + methodname + " " + args + "\n"; } -std::string HelpExampleRpc(string methodname, string args){ +std::string HelpExampleRpc(const std::string& methodname, const std::string& args) +{ return "> curl --user myusername --data-binary '{\"jsonrpc\": \"1.0\", \"id\":\"curltest\", " "\"method\": \"" + methodname + "\", \"params\": [" + args + "] }' -H 'content-type: text/plain;' http://127.0.0.1:8232/\n"; } diff --git a/src/rpcserver.h b/src/rpcserver.h index 6ee17da68..59154954c 100644 --- a/src/rpcserver.h +++ b/src/rpcserver.h @@ -61,7 +61,7 @@ bool IsRPCRunning(); std::shared_ptr getAsyncRPCQueue(); -/** +/** * Set the RPC warmup status. When this is done, all RPC calls will error out * immediately with RPC_IN_WARMUP. */ @@ -116,8 +116,8 @@ private: std::map mapCommands; public: CRPCTable(); - const CRPCCommand* operator[](std::string name) const; - std::string help(std::string name) const; + const CRPCCommand* operator[](const std::string& name) const; + std::string help(const std::string& name) const; /** * Execute a method. @@ -149,8 +149,8 @@ extern UniValue ValueFromAmount(const CAmount& amount); extern double GetDifficulty(const CBlockIndex* blockindex = NULL); extern double GetNetworkDifficulty(const CBlockIndex* blockindex = NULL); extern std::string HelpRequiringPassphrase(); -extern std::string HelpExampleCli(std::string methodname, std::string args); -extern std::string HelpExampleRpc(std::string methodname, std::string args); +extern std::string HelpExampleCli(const std::string& methodname, const std::string& args); +extern std::string HelpExampleRpc(const std::string& methodname, const std::string& args); extern void EnsureWalletIsUnlocked(); diff --git a/src/util.cpp b/src/util.cpp index 0023cd380..ed495202c 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -770,7 +770,7 @@ boost::filesystem::path GetTempPath() { #endif } -void runCommand(std::string strCommand) +void runCommand(const std::string& strCommand) { int nErr = ::system(strCommand.c_str()); if (nErr) diff --git a/src/util.h b/src/util.h index 3e4113164..fc1ba8277 100644 --- a/src/util.h +++ b/src/util.h @@ -137,7 +137,7 @@ boost::filesystem::path GetSpecialFolderPath(int nFolder, bool fCreate = true); #endif boost::filesystem::path GetTempPath(); void ShrinkDebugFile(); -void runCommand(std::string strCommand); +void runCommand(const std::string& strCommand); const boost::filesystem::path GetExportDir(); /** Returns licensing information (for -version) */ diff --git a/src/utilstrencodings.cpp b/src/utilstrencodings.cpp index 142d5a4eb..054992cfb 100644 --- a/src/utilstrencodings.cpp +++ b/src/utilstrencodings.cpp @@ -488,7 +488,7 @@ bool ParseDouble(const std::string& str, double *out) return text.eof() && !text.fail(); } -std::string FormatParagraph(const std::string in, size_t width, size_t indent) +std::string FormatParagraph(const std::string& in, size_t width, size_t indent) { std::stringstream out; size_t col = 0; diff --git a/src/utilstrencodings.h b/src/utilstrencodings.h index 08d337727..d6973a130 100644 --- a/src/utilstrencodings.h +++ b/src/utilstrencodings.h @@ -89,11 +89,11 @@ inline std::string HexStr(const T& vch, bool fSpaces=false) return HexStr(vch.begin(), vch.end(), fSpaces); } -/** +/** * Format a paragraph of text to a fixed width, adding spaces for * indentation to any added line. */ -std::string FormatParagraph(const std::string in, size_t width=79, size_t indent=0); +std::string FormatParagraph(const std::string& in, size_t width = 79, size_t indent = 0); /** * Timing-attack-resistant comparison. diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 154adca60..b8c983b3a 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -3148,7 +3148,7 @@ set< set > CWallet::GetAddressGroupings() return ret; } -set CWallet::GetAccountAddresses(string strAccount) const +std::set CWallet::GetAccountAddresses(const std::string& strAccount) const { LOCK(cs_wallet); set result; diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 222c8cea9..07d0f1f91 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -708,7 +708,7 @@ public: SetNull(); } - CWallet(std::string strWalletFileIn) + CWallet(const std::string& strWalletFileIn) { SetNull(); @@ -931,7 +931,7 @@ public: std::set< std::set > GetAddressGroupings(); std::map GetAddressBalances(); - std::set GetAccountAddresses(std::string strAccount) const; + std::set GetAccountAddresses(const std::string& strAccount) const; boost::optional GetNoteNullifier( const JSDescription& jsdesc, From bfa832c7ed528701859903aba99b90eebec41bdc Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Thu, 19 Mar 2015 05:34:06 -0700 Subject: [PATCH 03/19] Reduce checkpoints' effect on consensus. Instead of only checking height to decide whether to disable script checks, actually check whether a block is an ancestor of a checkpoint, up to which headers have been validated. This means that we don't have to prevent accepting a side branch anymore - it will be safe, just less fast to do. We still need to prevent being fed a multitude of low-difficulty headers filling up our memory. The mechanism for that is unchanged for now: once a checkpoint is reached with headers, no headers chain branching off before that point are allowed anymore. --- src/chain.cpp | 7 ++++--- src/checkpoints.cpp | 9 --------- src/checkpoints.h | 3 --- src/init.cpp | 2 +- src/main.cpp | 17 ++++++++++------- src/test/Checkpoints_tests.cpp | 16 +--------------- 6 files changed, 16 insertions(+), 38 deletions(-) diff --git a/src/chain.cpp b/src/chain.cpp index 719256106..5b8ce076c 100644 --- a/src/chain.cpp +++ b/src/chain.cpp @@ -82,9 +82,10 @@ CBlockIndex* CBlockIndex::GetAncestor(int height) while (heightWalk > height) { int heightSkip = GetSkipHeight(heightWalk); int heightSkipPrev = GetSkipHeight(heightWalk - 1); - if (heightSkip == height || - (heightSkip > height && !(heightSkipPrev < heightSkip - 2 && - heightSkipPrev >= height))) { + if (pindexWalk->pskip != NULL && + (heightSkip == height || + (heightSkip > height && !(heightSkipPrev < heightSkip - 2 && + heightSkipPrev >= height)))) { // Only follow pskip if pprev->pskip isn't better than pskip->pprev. pindexWalk = pindexWalk->pskip; heightWalk = heightSkip; diff --git a/src/checkpoints.cpp b/src/checkpoints.cpp index 202448613..87f4ad7f2 100644 --- a/src/checkpoints.cpp +++ b/src/checkpoints.cpp @@ -24,15 +24,6 @@ namespace Checkpoints { */ static const double SIGCHECK_VERIFICATION_FACTOR = 5.0; - bool CheckBlock(const CCheckpointData& data, int nHeight, const uint256& hash) - { - const MapCheckpoints& checkpoints = data.mapCheckpoints; - - MapCheckpoints::const_iterator i = checkpoints.find(nHeight); - if (i == checkpoints.end()) return true; - return hash == i->second; - } - //! Guess how far we are in the verification process at the given block index double GuessVerificationProgress(const CCheckpointData& data, CBlockIndex *pindex, bool fSigchecks) { if (pindex==NULL) diff --git a/src/checkpoints.h b/src/checkpoints.h index a720f096c..001e3cc80 100644 --- a/src/checkpoints.h +++ b/src/checkpoints.h @@ -26,9 +26,6 @@ struct CCheckpointData { double fTransactionsPerDay; }; -//! Returns true if block passes checkpoint checks -bool CheckBlock(const CCheckpointData& data, int nHeight, const uint256& hash); - //! Return conservative estimate of total number of blocks, 0 if unknown int GetTotalBlocksEstimate(const CCheckpointData& data); diff --git a/src/init.cpp b/src/init.cpp index 934feef09..c69a4fe69 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -401,7 +401,7 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageGroup(_("Debugging/Testing options:")); if (showDebug) { - strUsage += HelpMessageOpt("-checkpoints", strprintf("Only accept block chain matching built-in checkpoints (default: %u)", 1)); + strUsage += HelpMessageOpt("-checkpoints", strprintf("Disable expensive verification for known chain history (default: %u)", 1)); strUsage += HelpMessageOpt("-dblogsize=", strprintf("Flush database activity from memory pool to disk log every megabytes (default: %u)", 100)); strUsage += HelpMessageOpt("-disablesafemode", strprintf("Disable safemode, override a real safe mode event (default: %u)", 0)); strUsage += HelpMessageOpt("-testsafemode", strprintf("Force safe mode (default: %u)", 0)); diff --git a/src/main.cpp b/src/main.cpp index d1ec9ca41..5cb65bbf5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2044,7 +2044,15 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin const CChainParams& chainparams = Params(); AssertLockHeld(cs_main); - bool fExpensiveChecks = (!fCheckpointsEnabled || pindex->nHeight >= Checkpoints::GetTotalBlocksEstimate(chainparams.Checkpoints())); + bool fExpensiveChecks = true; + if (fCheckpointsEnabled) { + CBlockIndex *pindexLastCheckpoint = Checkpoints::GetLastCheckpoint(chainparams.Checkpoints()); + if (pindexLastCheckpoint && pindexLastCheckpoint->GetAncestor(pindex->nHeight) == pindex) { + // This block is an ancestor of a checkpoint: disable script checks + fExpensiveChecks = false; + } + } + auto verifier = libzcash::ProofVerifier::Strict(); auto disabledVerifier = libzcash::ProofVerifier::Disabled(); @@ -3066,13 +3074,8 @@ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& sta return state.Invalid(error("%s: block's timestamp is too early", __func__), REJECT_INVALID, "time-too-old"); - if(fCheckpointsEnabled) + if (fCheckpointsEnabled) { - // Check that the block chain matches the known block chain up to a checkpoint - if (!Checkpoints::CheckBlock(chainParams.Checkpoints(), nHeight, hash)) - return state.DoS(100, error("%s: rejected by checkpoint lock-in at %d", __func__, nHeight), - REJECT_CHECKPOINT, "checkpoint mismatch"); - // Don't accept any forks from the main chain prior to last checkpoint CBlockIndex* pcheckpoint = Checkpoints::GetLastCheckpoint(chainParams.Checkpoints()); if (pcheckpoint && nHeight < pcheckpoint->nHeight) diff --git a/src/test/Checkpoints_tests.cpp b/src/test/Checkpoints_tests.cpp index c32a424f1..d15203945 100644 --- a/src/test/Checkpoints_tests.cpp +++ b/src/test/Checkpoints_tests.cpp @@ -23,21 +23,7 @@ BOOST_FIXTURE_TEST_SUITE(Checkpoints_tests, BasicTestingSetup) BOOST_AUTO_TEST_CASE(sanity) { const Checkpoints::CCheckpointData& checkpoints = Params(CBaseChainParams::MAIN).Checkpoints(); - uint256 p11111 = uint256S("0x0000000069e244f73d78e8fd29ba2fd2ed618bd6fa2ee92559f542fdb26e7c1d"); - uint256 p134444 = uint256S("0x00000000000005b12ffd4cd315cd34ffd4a594f430ac814c91184a0d42d2b0fe"); - BOOST_CHECK(Checkpoints::CheckBlock(checkpoints, 11111, p11111)); - BOOST_CHECK(Checkpoints::CheckBlock(checkpoints, 134444, p134444)); - - - // Wrong hashes at checkpoints should fail: - BOOST_CHECK(!Checkpoints::CheckBlock(checkpoints, 11111, p134444)); - BOOST_CHECK(!Checkpoints::CheckBlock(checkpoints, 134444, p11111)); - - // ... but any hash not at a checkpoint should succeed: - BOOST_CHECK(Checkpoints::CheckBlock(checkpoints, 11111+1, p134444)); - BOOST_CHECK(Checkpoints::CheckBlock(checkpoints, 134444+1, p11111)); - BOOST_CHECK(Checkpoints::GetTotalBlocksEstimate(checkpoints) >= 134444); -} +} */ BOOST_AUTO_TEST_SUITE_END() From fbbd3cc638cf668f5013e5c77907ce57a6405b2b Mon Sep 17 00:00:00 2001 From: Philip Kaufmann Date: Mon, 1 Jun 2015 14:37:21 +0200 Subject: [PATCH 04/19] [init] add -blockversion help and extend -upnp help --- src/init.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index c69a4fe69..ca97900fc 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -357,7 +357,7 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-timeout=", strprintf(_("Specify connection timeout in milliseconds (minimum: 1, default: %d)"), DEFAULT_CONNECT_TIMEOUT)); #ifdef USE_UPNP #if USE_UPNP - strUsage += HelpMessageOpt("-upnp", _("Use UPnP to map the listening port (default: 1 when listening)")); + strUsage += HelpMessageOpt("-upnp", _("Use UPnP to map the listening port (default: 1 when listening and no -proxy)")); #else strUsage += HelpMessageOpt("-upnp", strprintf(_("Use UPnP to map the listening port (default: %u)"), 0)); #endif @@ -387,7 +387,6 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-walletnotify=", _("Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)")); strUsage += HelpMessageOpt("-zapwallettxes=", _("Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup") + " " + _("(1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)")); - #endif #if ENABLE_ZMQ @@ -446,6 +445,8 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-blockminsize=", strprintf(_("Set minimum block size in bytes (default: %u)"), 0)); strUsage += HelpMessageOpt("-blockmaxsize=", strprintf(_("Set maximum block size in bytes (default: %d)"), DEFAULT_BLOCK_MAX_SIZE)); strUsage += HelpMessageOpt("-blockprioritysize=", strprintf(_("Set maximum size of high-priority/low-fee transactions in bytes (default: %d)"), DEFAULT_BLOCK_PRIORITY_SIZE)); + if (GetBoolArg("-help-debug", false)) + strUsage += HelpMessageOpt("-blockversion=", strprintf("Override block version to test forking scenarios (default: %d)", (int)CBlock::CURRENT_VERSION)); #ifdef ENABLE_MINING strUsage += HelpMessageGroup(_("Mining options:")); From e079f010bfcad6392704744b65b9c960efab4863 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Tim=C3=B3n?= Date: Fri, 24 Apr 2015 16:45:16 +0200 Subject: [PATCH 05/19] Consensus: Refactor: Separate Consensus::CheckTxInputs and GetSpendHeight in CheckInputs Zcash: - Replaces some of the refactoring performed in #1017 - Exposed Consensus::CheckTxInputs for testing --- src/main.cpp | 67 +++++++++++++++++----------------------- src/main.h | 15 ++++++--- src/test/coins_tests.cpp | 4 +-- 3 files changed, 41 insertions(+), 45 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 5cb65bbf5..27c43fb18 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1607,13 +1607,16 @@ bool CScriptCheck::operator()() { return true; } -bool NonContextualCheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &inputs, bool fScriptChecks, unsigned int flags, bool cacheStore, const Consensus::Params& consensusParams, std::vector *pvChecks) +int GetSpendHeight(const CCoinsViewCache& inputs) { - if (!tx.IsCoinBase()) - { - if (pvChecks) - pvChecks->reserve(tx.vin.size()); + LOCK(cs_main); + CBlockIndex* pindexPrev = mapBlockIndex.find(inputs.GetBestBlock())->second; + return pindexPrev->nHeight + 1; +} +namespace Consensus { +bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight, const Consensus::Params& consensusParams) +{ // This doesn't trigger the DoS code on purpose; if it did, it would make it easier // for an attacker to attempt to split the network. if (!inputs.HaveInputs(tx)) @@ -1632,6 +1635,13 @@ bool NonContextualCheckInputs(const CTransaction& tx, CValidationState &state, c assert(coins); if (coins->IsCoinBase()) { + // Ensure that coinbases are matured + if (nSpendHeight - coins->nHeight < COINBASE_MATURITY) { + return state.Invalid( + error("CheckInputs(): tried to spend coinbase at depth %d", nSpendHeight - coins->nHeight), + REJECT_INVALID, "bad-txns-premature-spend-of-coinbase"); + } + // Ensure that coinbases cannot be spent to transparent outputs // Disabled on regtest if (fCoinbaseEnforcedProtectionEnabled && @@ -1670,6 +1680,19 @@ bool NonContextualCheckInputs(const CTransaction& tx, CValidationState &state, c if (!MoneyRange(nFees)) return state.DoS(100, error("CheckInputs(): nFees out of range"), REJECT_INVALID, "bad-txns-fee-outofrange"); + return true; +} +}// namespace Consensus + +bool ContextualCheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &inputs, bool fScriptChecks, unsigned int flags, bool cacheStore, const Consensus::Params& consensusParams, std::vector *pvChecks) +{ + if (!Consensus::CheckTxInputs(tx, state, inputs, GetSpendHeight(inputs), consensusParams)) + return false; + + if (!tx.IsCoinBase()) + { + if (pvChecks) + pvChecks->reserve(tx.vin.size()); // The first loop above does all the inexpensive checks. // Only if ALL inputs pass do we perform expensive ECDSA signature checks. @@ -1718,40 +1741,6 @@ bool NonContextualCheckInputs(const CTransaction& tx, CValidationState &state, c return true; } -bool ContextualCheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &inputs, bool fScriptChecks, unsigned int flags, bool cacheStore, const Consensus::Params& consensusParams, std::vector *pvChecks) -{ - if (!NonContextualCheckInputs(tx, state, inputs, fScriptChecks, flags, cacheStore, consensusParams, pvChecks)) { - return false; - } - - if (!tx.IsCoinBase()) - { - // While checking, GetBestBlock() refers to the parent block. - // This is also true for mempool checks. - CBlockIndex *pindexPrev = mapBlockIndex.find(inputs.GetBestBlock())->second; - int nSpendHeight = pindexPrev->nHeight + 1; - for (unsigned int i = 0; i < tx.vin.size(); i++) - { - const COutPoint &prevout = tx.vin[i].prevout; - const CCoins *coins = inputs.AccessCoins(prevout.hash); - // Assertion is okay because NonContextualCheckInputs ensures the inputs - // are available. - assert(coins); - - // If prev is coinbase, check that it's matured - if (coins->IsCoinBase()) { - if (nSpendHeight - coins->nHeight < COINBASE_MATURITY) { - return state.Invalid( - error("CheckInputs(): tried to spend coinbase at depth %d", nSpendHeight - coins->nHeight), - REJECT_INVALID, "bad-txns-premature-spend-of-coinbase"); - } - } - } - } - - return true; -} - namespace { bool UndoWriteToDisk(const CBlockUndo& blockundo, CDiskBlockPos& pos, const uint256& hashBlock, const CMessageHeader::MessageStartChars& messageStart) diff --git a/src/main.h b/src/main.h index 30f67b4fb..12f3734cc 100644 --- a/src/main.h +++ b/src/main.h @@ -332,10 +332,6 @@ bool ContextualCheckInputs(const CTransaction& tx, CValidationState &state, cons unsigned int flags, bool cacheStore, const Consensus::Params& consensusParams, std::vector *pvChecks = NULL); -bool NonContextualCheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &view, bool fScriptChecks, - unsigned int flags, bool cacheStore, const Consensus::Params& consensusParams, - std::vector *pvChecks = NULL); - /** Apply the effects of this transaction on the UTXO set represented by view */ void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCache &inputs, int nHeight); @@ -520,4 +516,15 @@ extern CCoinsViewCache *pcoinsTip; /** Global variable that points to the active block tree (protected by cs_main) */ extern CBlockTreeDB *pblocktree; +/** + * Return the spend height, which is one more than the inputs.GetBestBlock(). + * While checking, GetBestBlock() refers to the parent block. (protected by cs_main) + * This is also true for mempool checks. + */ +int GetSpendHeight(const CCoinsViewCache& inputs); + +namespace Consensus { +bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight, const Consensus::Params& consensusParams); +} + #endif // BITCOIN_MAIN_H diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp index ea7e81851..67b97a0ba 100644 --- a/src/test/coins_tests.cpp +++ b/src/test/coins_tests.cpp @@ -756,7 +756,7 @@ BOOST_AUTO_TEST_CASE(coins_coinbase_spends) { CTransaction tx2(mtx2); - BOOST_CHECK(NonContextualCheckInputs(tx2, state, cache, false, SCRIPT_VERIFY_NONE, false, Params().GetConsensus())); + BOOST_CHECK(Consensus::CheckTxInputs(tx2, state, cache, 100+COINBASE_MATURITY, Params().GetConsensus())); } mtx2.vout.resize(1); @@ -765,7 +765,7 @@ BOOST_AUTO_TEST_CASE(coins_coinbase_spends) { CTransaction tx2(mtx2); - BOOST_CHECK(!NonContextualCheckInputs(tx2, state, cache, false, SCRIPT_VERIFY_NONE, false, Params().GetConsensus())); + BOOST_CHECK(!Consensus::CheckTxInputs(tx2, state, cache, 100+COINBASE_MATURITY, Params().GetConsensus())); BOOST_CHECK(state.GetRejectReason() == "bad-txns-coinbase-spend-has-transparent-outputs"); } } From da7579184e741709e7864adfcef1fd8ef37881db Mon Sep 17 00:00:00 2001 From: Philip Kaufmann Date: Mon, 15 Jun 2015 14:43:31 +0200 Subject: [PATCH 06/19] make CAddrMan::size() return the correct type of size_t --- src/addrman.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/addrman.h b/src/addrman.h index cde9430ae..2a08076b7 100644 --- a/src/addrman.h +++ b/src/addrman.h @@ -470,7 +470,7 @@ public: } //! Return the number of (unique) addresses in all tables. - int size() + size_t size() const { return vRandom.size(); } From 8d9719e0ef6a3f9cb725a3cac2267c87f13c6df1 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 10 Jun 2015 09:19:13 +0200 Subject: [PATCH 07/19] Improve proxy initialization Simplify and make the code in AppInit2 more clear. This provides a straightforward flow, gets rid of .count() (which makes it possible to override an earlier provided proxy option to nothing), as well as comments the different cases. --- src/init.cpp | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index ca97900fc..46a20abda 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1136,31 +1136,36 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) } } - proxyType addrProxy; - bool fProxy = false; - if (mapArgs.count("-proxy")) { - addrProxy = proxyType(CService(mapArgs["-proxy"], 9050), GetBoolArg("-proxyrandomize", true)); + bool proxyRandomize = GetBoolArg("-proxyrandomize", true); + // -proxy sets a proxy for all outgoing network traffic + // -noproxy (or -proxy=0) as well as the empty string can be used to not set a proxy, this is the default + std::string proxyArg = GetArg("-proxy", ""); + if (proxyArg != "" && proxyArg != "0") { + proxyType addrProxy = proxyType(CService(proxyArg, 9050), proxyRandomize); if (!addrProxy.IsValid()) - return InitError(strprintf(_("Invalid -proxy address: '%s'"), mapArgs["-proxy"])); + return InitError(strprintf(_("Invalid -proxy address: '%s'"), proxyArg)); SetProxy(NET_IPV4, addrProxy); SetProxy(NET_IPV6, addrProxy); + SetProxy(NET_TOR, addrProxy); SetNameProxy(addrProxy); - fProxy = true; + SetReachable(NET_TOR); // by default, -proxy sets onion as reachable, unless -noonion later } - // -onion can override normal proxy, -noonion disables connecting to .onion entirely - if (!(mapArgs.count("-onion") && mapArgs["-onion"] == "0") && - (fProxy || mapArgs.count("-onion"))) { - proxyType addrOnion; - if (!mapArgs.count("-onion")) - addrOnion = addrProxy; - else - addrOnion = proxyType(CService(mapArgs["-onion"], 9050), GetBoolArg("-proxyrandomize", true)); - if (!addrOnion.IsValid()) - return InitError(strprintf(_("Invalid -onion address: '%s'"), mapArgs["-onion"])); - SetProxy(NET_TOR, addrOnion); - SetReachable(NET_TOR); + // -onion can be used to set only a proxy for .onion, or override normal proxy for .onion addresses + // -noonion (or -onion=0) disables connecting to .onion entirely + // An empty string is used to not override the onion proxy (in which case it defaults to -proxy set above, or none) + std::string onionArg = GetArg("-onion", ""); + if (onionArg != "") { + if (onionArg == "0") { // Handle -noonion/-onion=0 + SetReachable(NET_TOR, false); // set onions as unreachable + } else { + proxyType addrOnion = proxyType(CService(onionArg, 9050), proxyRandomize); + if (!addrOnion.IsValid()) + return InitError(strprintf(_("Invalid -onion address: '%s'"), onionArg)); + SetProxy(NET_TOR, addrOnion); + SetReachable(NET_TOR); + } } // see Step 2: parameter interactions for more information about these From 7cc6648341d44c409a69ddadc12323612f60c602 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 15 Jun 2015 12:44:56 +0200 Subject: [PATCH 08/19] tests: Extend RPC proxy tests Also test -noonion --- qa/rpc-tests/proxy_test.py | 62 +++++++++++++++++++++++++++++--------- 1 file changed, 48 insertions(+), 14 deletions(-) diff --git a/qa/rpc-tests/proxy_test.py b/qa/rpc-tests/proxy_test.py index 9a9b2f530..3623c1616 100755 --- a/qa/rpc-tests/proxy_test.py +++ b/qa/rpc-tests/proxy_test.py @@ -68,10 +68,10 @@ class ProxyTest(BitcoinTestFramework): ['-listen', '-debug=net', '-debug=proxy', '-proxy=%s:%i' % (self.conf1.addr),'-proxyrandomize=1'], ['-listen', '-debug=net', '-debug=proxy', '-proxy=%s:%i' % (self.conf1.addr),'-onion=%s:%i' % (self.conf2.addr),'-proxyrandomize=0'], ['-listen', '-debug=net', '-debug=proxy', '-proxy=%s:%i' % (self.conf2.addr),'-proxyrandomize=1'], - ['-listen', '-debug=net', '-debug=proxy', '-proxy=[%s]:%i' % (self.conf3.addr),'-proxyrandomize=0'] + ['-listen', '-debug=net', '-debug=proxy', '-proxy=[%s]:%i' % (self.conf3.addr),'-proxyrandomize=0', '-noonion'] ]) - def node_test(self, node, proxies, auth): + def node_test(self, node, proxies, auth, test_onion=True): rv = [] # Test: outgoing IPv4 connection through node node.addnode("15.61.23.23:1234", "onetry") @@ -99,17 +99,18 @@ class ProxyTest(BitcoinTestFramework): assert_equal(cmd.password, None) rv.append(cmd) - # Test: outgoing onion connection through node - node.addnode("bitcoinostk4e4re.onion:8333", "onetry") - cmd = proxies[2].queue.get() - assert(isinstance(cmd, Socks5Command)) - assert_equal(cmd.atyp, AddressType.DOMAINNAME) - assert_equal(cmd.addr, "bitcoinostk4e4re.onion") - assert_equal(cmd.port, 8333) - if not auth: - assert_equal(cmd.username, None) - assert_equal(cmd.password, None) - rv.append(cmd) + if test_onion: + # Test: outgoing onion connection through node + node.addnode("bitcoinostk4e4re.onion:8333", "onetry") + cmd = proxies[2].queue.get() + assert(isinstance(cmd, Socks5Command)) + assert_equal(cmd.atyp, AddressType.DOMAINNAME) + assert_equal(cmd.addr, "bitcoinostk4e4re.onion") + assert_equal(cmd.port, 8333) + if not auth: + assert_equal(cmd.username, None) + assert_equal(cmd.password, None) + rv.append(cmd) # Test: outgoing DNS name connection through node node.addnode("node.noumenon:8333", "onetry") @@ -139,8 +140,41 @@ class ProxyTest(BitcoinTestFramework): assert_equal(len(credentials), 4) # proxy on IPv6 localhost - self.node_test(self.nodes[3], [self.serv3, self.serv3, self.serv3, self.serv3], False) + self.node_test(self.nodes[3], [self.serv3, self.serv3, self.serv3, self.serv3], False, False) + + def networks_dict(d): + r = {} + for x in d['networks']: + r[x['name']] = x + return r + + # test RPC getnetworkinfo + n0 = networks_dict(self.nodes[0].getnetworkinfo()) + for net in ['ipv4','ipv6','onion']: + assert_equal(n0[net]['proxy'], '%s:%i' % (self.conf1.addr)) + assert_equal(n0[net]['proxy_randomize_credentials'], True) + assert_equal(n0['onion']['reachable'], True) + + n1 = networks_dict(self.nodes[1].getnetworkinfo()) + for net in ['ipv4','ipv6']: + assert_equal(n1[net]['proxy'], '%s:%i' % (self.conf1.addr)) + assert_equal(n1[net]['proxy_randomize_credentials'], False) + assert_equal(n1['onion']['proxy'], '%s:%i' % (self.conf2.addr)) + assert_equal(n1['onion']['proxy_randomize_credentials'], False) + assert_equal(n1['onion']['reachable'], True) + n2 = networks_dict(self.nodes[2].getnetworkinfo()) + for net in ['ipv4','ipv6','onion']: + assert_equal(n2[net]['proxy'], '%s:%i' % (self.conf2.addr)) + assert_equal(n2[net]['proxy_randomize_credentials'], True) + assert_equal(n2['onion']['reachable'], True) + + n3 = networks_dict(self.nodes[3].getnetworkinfo()) + for net in ['ipv4','ipv6']: + assert_equal(n3[net]['proxy'], '[%s]:%i' % (self.conf3.addr)) + assert_equal(n3[net]['proxy_randomize_credentials'], False) + assert_equal(n3['onion']['reachable'], False) + if __name__ == '__main__': ProxyTest().main() From 55fca515d8d212869acd0f625bde0474ee249b97 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Sun, 21 Jun 2015 08:22:31 +0200 Subject: [PATCH 09/19] build: Remove -DBOOST_SPIRIT_THREADSAFE Now that boost spirit is no longer used, `-DBOOST_SPIRIT_THREADSAFE` doesn't need to be passed to the compiler anymore. --- configure.ac | 2 +- src/rpcprotocol.cpp | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index e7fb4a927..54d92c238 100644 --- a/configure.ac +++ b/configure.ac @@ -193,7 +193,7 @@ fi if test "x$CXXFLAGS_overridden" = "xno"; then CXXFLAGS="$CXXFLAGS -Wall -Wextra -Wformat -Wformat-security -Wno-unused-parameter -Wno-self-assign" fi -CPPFLAGS="$CPPFLAGS -DBOOST_SPIRIT_THREADSAFE -DHAVE_BUILD_INFO -D__STDC_FORMAT_MACROS" +CPPFLAGS="$CPPFLAGS -DHAVE_BUILD_INFO -D__STDC_FORMAT_MACROS" AC_ARG_WITH([utils], [AS_HELP_STRING([--with-utils], diff --git a/src/rpcprotocol.cpp b/src/rpcprotocol.cpp index 684feb823..ecc1d952a 100644 --- a/src/rpcprotocol.cpp +++ b/src/rpcprotocol.cpp @@ -253,7 +253,6 @@ int ReadHTTPMessage(std::basic_istream& stream, map Date: Wed, 13 May 2015 20:04:39 +0000 Subject: [PATCH 10/19] Fix various warnings Found while building on Debian 7 --- src/main.h | 4 ++-- src/rest.cpp | 2 +- src/txmempool.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main.h b/src/main.h index 12f3734cc..886542db7 100644 --- a/src/main.h +++ b/src/main.h @@ -145,7 +145,7 @@ extern bool fPruneMode; /** Number of MiB of block files that we're trying to stay below. */ extern uint64_t nPruneTarget; /** Block files containing a block-height within MIN_BLOCKS_TO_KEEP of chainActive.Tip() will not be pruned. */ -static const signed int MIN_BLOCKS_TO_KEEP = 288; +static const unsigned int MIN_BLOCKS_TO_KEEP = 288; // Require that user allocate at least 550MB for block & undo files (blk???.dat and rev???.dat) // At 1MB per block, 288 blocks = 288MB. @@ -155,7 +155,7 @@ static const signed int MIN_BLOCKS_TO_KEEP = 288; // full block file chunks, we need the high water mark which triggers the prune to be // one 128MB block file + added 15% undo data = 147MB greater for a total of 545MB // Setting the target to > than 550MB will make it likely we can respect the target. -static const signed int MIN_DISK_SPACE_FOR_BLOCK_FILES = 550 * 1024 * 1024; +static const uint64_t MIN_DISK_SPACE_FOR_BLOCK_FILES = 550 * 1024 * 1024; /** Register with a network node to receive its signals */ void RegisterNodeSignals(CNodeSignals& nodeSignals); diff --git a/src/rest.cpp b/src/rest.cpp index 82155bab1..52d766b3d 100644 --- a/src/rest.cpp +++ b/src/rest.cpp @@ -20,7 +20,7 @@ using namespace std; -static const int MAX_GETUTXOS_OUTPOINTS = 15; //allow a max of 15 outpoints to be queried at once +static const size_t MAX_GETUTXOS_OUTPOINTS = 15; //allow a max of 15 outpoints to be queried at once enum RetFormat { RF_UNDEF, diff --git a/src/txmempool.cpp b/src/txmempool.cpp index e9c846485..3f0e3938a 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -176,7 +176,7 @@ void CTxMemPool::removeCoinbaseSpends(const CCoinsViewCache *pcoins, unsigned in continue; const CCoins *coins = pcoins->AccessCoins(txin.prevout.hash); if (fSanityCheck) assert(coins); - if (!coins || (coins->IsCoinBase() && nMemPoolHeight - coins->nHeight < COINBASE_MATURITY)) { + if (!coins || (coins->IsCoinBase() && ((signed long)nMemPoolHeight) - coins->nHeight < COINBASE_MATURITY)) { transactionsToRemove.push_back(tx); break; } From f061578b8f0e3c882a4a55c31fa307f92350218a Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Tue, 7 Jul 2015 12:15:44 +0200 Subject: [PATCH 11/19] [bitcoin-cli] improve error output --- src/bitcoin-cli.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp index 6e54cd97a..0e692622b 100644 --- a/src/bitcoin-cli.cpp +++ b/src/bitcoin-cli.cpp @@ -200,6 +200,15 @@ int CommandLineRPC(int argc, char *argv[]) throw CConnectionFailed("server in warmup"); strPrint = "error: " + error.write(); nRet = abs(code); + if (error.isObject()) + { + UniValue errCode = find_value(error, "code"); + UniValue errMsg = find_value(error, "message"); + strPrint = errCode.isNull() ? "" : "error code: "+errCode.getValStr()+"\n"; + + if (errMsg.isStr()) + strPrint += "error message:\n"+errMsg.get_str(); + } } else { // Result if (result.isNull()) From 70b3d9e3ac26bd4b6c4292876fa77a6e3a960087 Mon Sep 17 00:00:00 2001 From: Florian Schmaus Date: Wed, 8 Jul 2015 22:35:29 +0200 Subject: [PATCH 12/19] Add BITCOIND_SIGTERM_TIMEOUT to OpenRC init scripts This allows users to specify, e.g. raise, the default timeout of 60 seconds. Some bitcoind instances, especially long running ones on slow hardware, require a higher timeout for a clean shut down. Also add a comment to bitcoind.openrc's 'retry=', since it is not obvious from the variable name what it does. --- contrib/init/bitcoind.openrc | 6 +++++- contrib/init/bitcoind.openrcconf | 6 ++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/contrib/init/bitcoind.openrc b/contrib/init/bitcoind.openrc index a94f03680..eda1a96fb 100644 --- a/contrib/init/bitcoind.openrc +++ b/contrib/init/bitcoind.openrc @@ -32,7 +32,11 @@ required_files="${BITCOIND_CONFIGFILE}" start_stop_daemon_args="-u ${BITCOIND_USER} \ -N ${BITCOIND_NICE} -w 2000" pidfile="${BITCOIND_PIDFILE}" -retry=60 + +# The retry schedule to use when stopping the daemon. Could be either +# a timeout in seconds or multiple signal/timeout pairs (like +# "SIGKILL/180 SIGTERM/300") +retry="${BITCOIND_SIGTERM_TIMEOUT}" depend() { need localmount net diff --git a/contrib/init/bitcoind.openrcconf b/contrib/init/bitcoind.openrcconf index d8d7f5833..0cbff6d30 100644 --- a/contrib/init/bitcoind.openrcconf +++ b/contrib/init/bitcoind.openrcconf @@ -25,3 +25,9 @@ # Additional options (avoid -conf and -datadir, use flags above) BITCOIND_OPTS="-disablewallet" +# The timeout in seconds OpenRC will wait for bitcoind to terminate +# after a SIGTERM has been raised. +# Note that this will be mapped as argument to start-stop-daemon's +# '--retry' option, which means you can specify a retry schedule +# here. For more information see man 8 start-stop-daemon. +BITCOIND_SIGTERM_TIMEOUT=60 From ae1565b52f9d1c48a6e754bae8fd9839ce90df6b Mon Sep 17 00:00:00 2001 From: Gavin Andresen Date: Mon, 13 Jul 2015 14:28:03 -0400 Subject: [PATCH 13/19] configure --enable-debug changes Three changes to how configure --enable-debug behaves: 1. Preserve user-passed CXXFLAGS/CFLAGS 2. Compile with -DDEBUG_LOCKORDER 3. Add -DDEBUG -DDEBUG_LOCKORDER to CPPFLAGS (since they are preprocessor options) --- configure.ac | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 54d92c238..84c66624b 100644 --- a/configure.ac +++ b/configure.ac @@ -178,12 +178,13 @@ AC_ARG_ENABLE([debug], [enable_debug=no]) if test "x$enable_debug" = xyes; then + CPPFLAGS="$CPPFLAGS -DDEBUG -DDEBUG_LOCKORDER" if test "x$GCC" = xyes; then - CFLAGS="-g3 -O0 -DDEBUG" + CFLAGS="$CFLAGS -g3 -O0" fi if test "x$GXX" = xyes; then - CXXFLAGS="-g3 -O0 -DDEBUG" + CXXFLAGS="$CXXFLAGS -g3 -O0" fi fi From 0eac70954c94b868f9e131df602ac948a6139598 Mon Sep 17 00:00:00 2001 From: Paul Georgiou Date: Fri, 10 Jul 2015 19:21:21 +0300 Subject: [PATCH 14/19] Update Linearize tool to support Windows paths --- contrib/linearize/README.md | 6 +++--- contrib/linearize/linearize-data.py | 12 +++++++----- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/contrib/linearize/README.md b/contrib/linearize/README.md index 157586e4d..06f278f3b 100644 --- a/contrib/linearize/README.md +++ b/contrib/linearize/README.md @@ -3,7 +3,7 @@ Construct a linear, no-fork, best version of the blockchain. ## Step 1: Download hash list - $ ./linearize-hashes.py linearize.cfg > hashlist.txt + $ ./linearize-hashes.py linearize.cfg > hashlist.txt Required configuration file settings for linearize-hashes: * RPC: rpcuser, rpcpassword @@ -14,7 +14,7 @@ Optional config file setting for linearize-hashes: ## Step 2: Copy local block data - $ ./linearize-data.py linearize.cfg + $ ./linearize-data.py linearize.cfg Required configuration file settings: * "input": bitcoind blocks/ directory containing blkNNNNN.dat @@ -26,7 +26,7 @@ output. Optional config file setting for linearize-data: * "netmagic": network magic number -* "max_out_sz": maximum output file size (default 1000*1000*1000) +* "max_out_sz": maximum output file size (default `1000*1000*1000`) * "split_timestamp": Split files when a new month is first seen, in addition to reaching a maximum file size. * "file_timestamp": Set each file's last-modified time to that of the diff --git a/contrib/linearize/linearize-data.py b/contrib/linearize/linearize-data.py index 7947c6bf7..0f6fde2a6 100755 --- a/contrib/linearize/linearize-data.py +++ b/contrib/linearize/linearize-data.py @@ -12,6 +12,7 @@ import json import struct import re import os +import os.path import base64 import httplib import sys @@ -115,19 +116,20 @@ class BlockDataCopier: self.setFileTime = True if settings['split_timestamp'] != 0: self.timestampSplit = True - # Extents and cache for out-of-order blocks + # Extents and cache for out-of-order blocks self.blockExtents = {} self.outOfOrderData = {} self.outOfOrderSize = 0 # running total size for items in outOfOrderData def writeBlock(self, inhdr, blk_hdr, rawblock): - if not self.fileOutput and ((self.outsz + self.inLen) > self.maxOutSz): + blockSizeOnDisk = len(inhdr) + len(blk_hdr) + len(rawblock) + if not self.fileOutput and ((self.outsz + blockSizeOnDisk) > self.maxOutSz): self.outF.close() if self.setFileTime: os.utime(outFname, (int(time.time()), highTS)) self.outF = None self.outFname = None - self.outFn = outFn + 1 + self.outFn = self.outFn + 1 self.outsz = 0 (blkDate, blkTS) = get_blk_dt(blk_hdr) @@ -147,7 +149,7 @@ class BlockDataCopier: if self.fileOutput: outFname = self.settings['output_file'] else: - outFname = "%s/blk%05d.dat" % (self.settings['output'], outFn) + outFname = os.path.join(self.settings['output'], "blk%05d.dat" % self.outFn) print("Output file " + outFname) self.outF = open(outFname, "wb") @@ -165,7 +167,7 @@ class BlockDataCopier: (self.blkCountIn, self.blkCountOut, len(self.blkindex), 100.0 * self.blkCountOut / len(self.blkindex))) def inFileName(self, fn): - return "%s/blk%05d.dat" % (self.settings['input'], fn) + return os.path.join(self.settings['input'], "blk%05d.dat" % fn) def fetchBlock(self, extent): '''Fetch block contents from disk given extents''' From 2af5a65066a416ff5a817813bf611d9e374b7d7b Mon Sep 17 00:00:00 2001 From: Pavel Vasin Date: Tue, 30 Jun 2015 23:10:27 +0300 Subject: [PATCH 15/19] remove unused inv from ConnectTip() --- src/main.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 27c43fb18..4e9230c51 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2478,7 +2478,6 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock * LogPrint("bench", " - Load block from disk: %.2fms [%.2fs]\n", (nTime2 - nTime1) * 0.001, nTimeReadFromDisk * 0.000001); { CCoinsViewCache view(pcoinsTip); - CInv inv(MSG_BLOCK, pindexNew->GetBlockHash()); bool rv = ConnectBlock(*pblock, state, pindexNew, view); GetMainSignals().BlockChecked(*pblock, state); if (!rv) { @@ -2486,7 +2485,7 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock * InvalidBlockFound(pindexNew, state); return error("ConnectTip(): ConnectBlock %s failed", pindexNew->GetBlockHash().ToString()); } - mapBlockSource.erase(inv.hash); + mapBlockSource.erase(pindexNew->GetBlockHash()); nTime3 = GetTimeMicros(); nTimeConnectTotal += nTime3 - nTime2; LogPrint("bench", " - Connect total: %.2fms [%.2fs]\n", (nTime3 - nTime2) * 0.001, nTimeConnectTotal * 0.000001); assert(view.Flush()); From 8550bcfecae27ff4728e10dd166764d9f1280439 Mon Sep 17 00:00:00 2001 From: Adam Weiss Date: Fri, 15 May 2015 15:31:14 -0400 Subject: [PATCH 16/19] Buffer log messages and explicitly open logs Prevents stomping on debug logs in datadirs that are locked by other instances and lost parameter interaction messages that can get wiped by ShrinkDebugFile(). The log is now opened explicitly and all emitted messages are buffered until this open occurs. The version message and log cut have also been moved to the earliest possible sensible location. --- src/init.cpp | 9 ++++- src/util.cpp | 101 ++++++++++++++++++++++++++++++++++++++------------- src/util.h | 1 + 3 files changed, 84 insertions(+), 27 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 46a20abda..5d7f4d3f1 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -767,6 +767,9 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) fLogTimestamps = GetBoolArg("-logtimestamps", true); fLogIPs = GetBoolArg("-logips", false); + LogPrintf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); + LogPrintf("Zcash version %s (%s)\n", FormatFullVersion(), CLIENT_DATE); + // when specifying an explicit binding address, you want to listen on it // even when -connect or -proxy is specified if (mapArgs.count("-bind")) { @@ -1031,8 +1034,10 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) #endif if (GetBoolArg("-shrinkdebugfile", !fDebug)) ShrinkDebugFile(); - LogPrintf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); - LogPrintf("Zcash version %s (%s)\n", FormatFullVersion(), CLIENT_DATE); + + if (fPrintToDebugLog) + OpenDebugLog(); + LogPrintf("Using OpenSSL version %s\n", SSLeay_version(SSLEAY_VERSION)); #ifdef ENABLE_WALLET LogPrintf("Using BerkeleyDB version %s\n", DbEnv::version(0, 0, 0)); diff --git a/src/util.cpp b/src/util.cpp index ed495202c..8ce727609 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -165,23 +165,51 @@ instance_of_cinit; */ static boost::once_flag debugPrintInitFlag = BOOST_ONCE_INIT; + /** - * We use boost::call_once() to make sure these are initialized - * in a thread-safe manner the first time called: + * We use boost::call_once() to make sure mutexDebugLog and + * vMsgsBeforeOpenLog are initialized in a thread-safe manner. + * + * NOTE: fileout, mutexDebugLog and sometimes vMsgsBeforeOpenLog + * are leaked on exit. This is ugly, but will be cleaned up by + * the OS/libc. When the shutdown sequence is fully audited and + * tested, explicit destruction of these objects can be implemented. */ static FILE* fileout = NULL; static boost::mutex* mutexDebugLog = NULL; +static list *vMsgsBeforeOpenLog; + +static int FileWriteStr(const std::string &str, FILE *fp) +{ + return fwrite(str.data(), 1, str.size(), fp); +} static void DebugPrintInit() { - assert(fileout == NULL); assert(mutexDebugLog == NULL); + mutexDebugLog = new boost::mutex(); + vMsgsBeforeOpenLog = new list; +} +void OpenDebugLog() +{ + boost::call_once(&DebugPrintInit, debugPrintInitFlag); + boost::mutex::scoped_lock scoped_lock(*mutexDebugLog); + + assert(fileout == NULL); + assert(vMsgsBeforeOpenLog); boost::filesystem::path pathDebug = GetDataDir() / "debug.log"; fileout = fopen(pathDebug.string().c_str(), "a"); if (fileout) setbuf(fileout, NULL); // unbuffered - mutexDebugLog = new boost::mutex(); + // dump buffered messages from before we opened the log + while (!vMsgsBeforeOpenLog->empty()) { + FileWriteStr(vMsgsBeforeOpenLog->front(), fileout); + vMsgsBeforeOpenLog->pop_front(); + } + + delete vMsgsBeforeOpenLog; + vMsgsBeforeOpenLog = NULL; } bool LogAcceptCategory(const char* category) @@ -213,44 +241,67 @@ bool LogAcceptCategory(const char* category) return true; } +/** + * fStartedNewLine is a state variable held by the calling context that will + * suppress printing of the timestamp when multiple calls are made that don't + * end in a newline. Initialize it to true, and hold it, in the calling context. + */ +static std::string LogTimestampStr(const std::string &str, bool *fStartedNewLine) +{ + string strStamped; + + if (!fLogTimestamps) + return str; + + if (*fStartedNewLine) + strStamped = DateTimeStrFormat("%Y-%m-%d %H:%M:%S", GetTime()) + ' ' + str; + else + strStamped = str; + + if (!str.empty() && str[str.size()-1] == '\n') + *fStartedNewLine = true; + else + *fStartedNewLine = false; + + return strStamped; +} + int LogPrintStr(const std::string &str) { int ret = 0; // Returns total number of characters written + static bool fStartedNewLine = true; if (fPrintToConsole) { // print to console ret = fwrite(str.data(), 1, str.size(), stdout); fflush(stdout); } - else if (fPrintToDebugLog && AreBaseParamsConfigured()) + else if (fPrintToDebugLog) { - static bool fStartedNewLine = true; boost::call_once(&DebugPrintInit, debugPrintInitFlag); - - if (fileout == NULL) - return ret; - boost::mutex::scoped_lock scoped_lock(*mutexDebugLog); - // reopen the log file, if requested - if (fReopenDebugLog) { - fReopenDebugLog = false; - boost::filesystem::path pathDebug = GetDataDir() / "debug.log"; - if (freopen(pathDebug.string().c_str(),"a",fileout) != NULL) - setbuf(fileout, NULL); // unbuffered + string strTimestamped = LogTimestampStr(str, &fStartedNewLine); + + // buffer if we haven't opened the log yet + if (fileout == NULL) { + assert(vMsgsBeforeOpenLog); + ret = strTimestamped.length(); + vMsgsBeforeOpenLog->push_back(strTimestamped); } - - // Debug print useful for profiling - if (fLogTimestamps && fStartedNewLine) - ret += fprintf(fileout, "%s ", DateTimeStrFormat("%Y-%m-%d %H:%M:%S", GetTime()).c_str()); - if (!str.empty() && str[str.size()-1] == '\n') - fStartedNewLine = true; else - fStartedNewLine = false; + { + // reopen the log file, if requested + if (fReopenDebugLog) { + fReopenDebugLog = false; + boost::filesystem::path pathDebug = GetDataDir() / "debug.log"; + if (freopen(pathDebug.string().c_str(),"a",fileout) != NULL) + setbuf(fileout, NULL); // unbuffered + } - ret = fwrite(str.data(), 1, str.size(), fileout); + ret = FileWriteStr(strTimestamped, fileout); + } } - return ret; } diff --git a/src/util.h b/src/util.h index fc1ba8277..e4eea2ba1 100644 --- a/src/util.h +++ b/src/util.h @@ -136,6 +136,7 @@ void ReadConfigFile(std::map& mapSettingsRet, std::map boost::filesystem::path GetSpecialFolderPath(int nFolder, bool fCreate = true); #endif boost::filesystem::path GetTempPath(); +void OpenDebugLog(); void ShrinkDebugFile(); void runCommand(const std::string& strCommand); const boost::filesystem::path GetExportDir(); From 53bcf8379a1279efb2904607f0e16419dd38a756 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Thu, 23 Jul 2015 16:14:17 +0200 Subject: [PATCH 17/19] fix and extend CBitcoinExtKeyBase template - fix Decode call (req. only one param) - add constructor for base58c->CExtKey --- src/base58.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/base58.h b/src/base58.h index d3967ec4e..9c6b54943 100644 --- a/src/base58.h +++ b/src/base58.h @@ -171,7 +171,7 @@ public: K GetKey() { K ret; - ret.Decode(&vchData[0], &vchData[Size]); + ret.Decode(&vchData[0]); return ret; } @@ -179,6 +179,10 @@ public: SetKey(key); } + CBitcoinExtKeyBase(const std::string& strBase58c) { + SetString(strBase58c.c_str(), Params().Base58Prefix(Type).size()); + } + CBitcoinExtKeyBase() {} }; From 51878774bf0846f22fbdc2365ba512a8ceb9d151 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Thu, 23 Jul 2015 16:22:37 +0200 Subject: [PATCH 18/19] extend bip32 tests to cover Base58c/CExtKey decode --- src/test/bip32_tests.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/test/bip32_tests.cpp b/src/test/bip32_tests.cpp index 0d815c27f..69084213a 100644 --- a/src/test/bip32_tests.cpp +++ b/src/test/bip32_tests.cpp @@ -88,12 +88,23 @@ void RunTest(const TestVector &test) { unsigned char data[74]; key.Encode(data); pubkey.Encode(data); + // Test private key CBitcoinExtKey b58key; b58key.SetKey(key); BOOST_CHECK(b58key.ToString() == derive.prv); + + CBitcoinExtKey b58keyDecodeCheck(derive.prv); + CExtKey checkKey = b58keyDecodeCheck.GetKey(); + assert(checkKey == key); //ensure a base58 decoded key also matches + // Test public key CBitcoinExtPubKey b58pubkey; b58pubkey.SetKey(pubkey); BOOST_CHECK(b58pubkey.ToString() == derive.pub); + + CBitcoinExtPubKey b58PubkeyDecodeCheck(derive.pub); + CExtPubKey checkPubKey = b58PubkeyDecodeCheck.GetKey(); + assert(checkPubKey == pubkey); //ensure a base58 decoded pubkey also matches + // Derive new keys CExtKey keyNew; BOOST_CHECK(key.Derive(keyNew, derive.nChild)); From 4d1d95310f1b03c19ae2725fadfbbeb238476a86 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Thu, 23 Jul 2015 21:05:00 +0200 Subject: [PATCH 19/19] don't try to decode invalid encoded ext keys --- src/base58.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/base58.h b/src/base58.h index 9c6b54943..88efadbd6 100644 --- a/src/base58.h +++ b/src/base58.h @@ -171,7 +171,10 @@ public: K GetKey() { K ret; - ret.Decode(&vchData[0]); + if (vchData.size() == Size) { + //if base58 encouded data not holds a ext key, return a !IsValid() key + ret.Decode(&vchData[0]); + } return ret; }