diff -uNr a/bitcoin/manifest b/bitcoin/manifest --- a/bitcoin/manifest 4771feddc73ba3a542b7a93dbd95942d742205b3ee99e0a651a16698b3dc6e3bea6e746fd806667e4e77603473f8a938b6caa9c532100a6360b26bd64f49393f +++ b/bitcoin/manifest 1ca5d6f60d54f98cc03d8ea821a2fcdc0feaea96c0bc25bcdc8a31310fbc14509b1366074baca17e558a6b0cb31205730c5e32c68351f86f1535674fd6bb81e2 @@ -55,3 +55,4 @@ 835694 bitcoin_drop_bdb_locking jfw Turn off BDB's page-level locking subsystem, with some tweaks to firm up the already largely single-threaded pattern of database use. This allows removing the magic-number limits on locks, lockers and lock objects; the numbers were reported by past authority to be sufficient for any 1MB block, but have proven insufficient for large reorganizations, because BDB accumulates locks for the duration of a transaction. It also saves nearly 2GB of preallocations in the database environment (__db.00[1-5] files) to support the large limits. 835698 bitcoin_easy_warning_fixes jfw Quiet the vast majority of compiler warning spew so any actual trouble stands a chance of being spotted. Continue incremental conversion from CRITICAL_BLOCK to SCOPED_LOCK, as that and BOOST_FOREACH are the main sources of spurious -Wparentheses due to the macros' internal if-statements. Besides the more cosmetic changes, this cures a reckless stack buffer allocation (200k, when truncating the debug log) and a potential integer overflow (in string formatting code). Related string handling routines still need attention though. 835709 bitcoin_reorg_bounded_space jfw Remove linear heap allocation by Reorganize, at the "cost" of rereading the affected blocks from disk after database commit to update the mempool. As usual, even the smallest of fixes uncovers other landmines: resurrected transactions were not checked for minimum relay fee; TxnAbort was doubly invoked in the case of ConnectBlock failure; invalid blocks were not distinguished from db failure - and still aren't, but the warning text is finessed (again) so as not to lie outright. The mempool itself remains unbounded, though at least now the minimum fee upholds a cost for entering it. +918943 bitcoin_peer_debug_etc jfw Reveal peer state info by implementing 'getpeerinfo' RPC; likewise simple global state info in new 'getinfo' fields and a 'getbestblockhash'. Remove keypool fields from getinfo because they're somewhat heavy, in a small start toward removing the integrated wallet code. Mitigate recent debug.log explosion by trimming or gating some of the more verbose messages on -debug=1, while making -debug=0 usable and even a good default by removing the weird log semi-truncation, which never made much sense as it only ran at startup. diff -uNr a/bitcoin/src/bitcoinrpc.cpp b/bitcoin/src/bitcoinrpc.cpp --- a/bitcoin/src/bitcoinrpc.cpp 0ceb473bfc2901e66d569de7d3ea054697f43e39066621169400171c9a99adf81cffe34d414c2c97a640b0c5fe6120f4f615fd33fc1c591ca8f6f35c2c703dfc +++ b/bitcoin/src/bitcoinrpc.cpp 53a0436b8fc61e7aa838ae637d754d05c2ae0b3da0a50a2489685a9f48ba23de7c70485b6a1495d34bafcaecf94dda533478637c06c23d161870500a51d27c90 @@ -187,6 +187,17 @@ } +Value getbestblockhash(const Array ¶ms, bool fHelp) +{ + if (fHelp || params.size() != 0) + throw runtime_error( + "getbestblockhash\n" + "Returns the latest block hash in the current best chain."); + + return hashBestChain.GetHex(); +} + + Value getconnectioncount(const Array& params, bool fHelp) { if (fHelp || params.size() != 0) @@ -307,16 +318,70 @@ obj.push_back(Pair("genproclimit", (int)(fLimitProcessors ? nLimitProcessors : -1))); obj.push_back(Pair("difficulty", (double)GetDifficulty())); obj.push_back(Pair("hashespersec", gethashespersec(params, false))); - obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime())); - obj.push_back(Pair("keypoolsize", pwalletMain->GetKeyPoolSize())); obj.push_back(Pair("paytxfee", ValueFromAmount(GetTransactionFee()))); obj.push_back(Pair("minrelaytxfee", ValueFromAmount(GetMinRelayTxFee()))); if (pwalletMain->IsCrypted()) obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime / 1000)); obj.push_back(Pair("errors", GetWarnings("statusbar"))); + // main.cpp global containers + obj.push_back(Pair("mempoolsize", GetMempoolSize())); + obj.push_back(Pair("mapNextTx_size", mapNextTx.size())); + obj.push_back(Pair("mapBlockIndex_size", mapBlockIndex.size())); + // net.cpp global containers (besides vNodes) + obj.push_back(Pair("mapAddresses_size", mapAddresses.size())); + obj.push_back(Pair("mapRelay_size", mapRelay.size())); + obj.push_back(Pair("vRelayExpiration_size", vRelayExpiration.size())); + obj.push_back(Pair("mapAlreadyAskedFor_size", mapAlreadyAskedFor.size())); return obj; } +Value getpeerinfo(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 0) + throw runtime_error( + "getpeerinfo\n" + "Returns an array of objects containing state info for each connected peer (subject to change with the networking code)."); + + Array ret; + SCOPED_LOCK(cs_vNodes); + BOOST_FOREACH(CNode* pnode, vNodes) + { + Object obj; + + // these fields PRB-compatible + obj.push_back(Pair("addr", pnode->addr.ToString())); + obj.push_back(Pair("services", strprintf("%016"PRI64x, pnode->nServices))); + obj.push_back(Pair("lastsend", (boost::int64_t)pnode->nLastSend)); + obj.push_back(Pair("lastrecv", (boost::int64_t)pnode->nLastRecv)); + obj.push_back(Pair("conntime", (boost::int64_t)pnode->nTimeConnected)); + obj.push_back(Pair("version", pnode->nVersion)); + // Confirmed strSubVer doesn't need to be sanitized here as control characters are backslash-encoded in the JSON output (albeit in some strange unicodey way). Printing to console or log file might be another story. -jfw + obj.push_back(Pair("subver", pnode->strSubVer)); + obj.push_back(Pair("inbound", pnode->fInbound)); + obj.push_back(Pair("startingheight", pnode->nStartingHeight)); + + // these more likely to change, following internal names + obj.push_back(Pair("fClient", pnode->fClient)); + obj.push_back(Pair("fNetworkNode", pnode->fNetworkNode)); + obj.push_back(Pair("fSuccessfullyConnected", pnode->fSuccessfullyConnected)); // bool + obj.push_back(Pair("fDisconnect", pnode->fDisconnect)); + obj.push_back(Pair("vSend_size", pnode->vSend.size())); + obj.push_back(Pair("vRecv_size", pnode->vRecv.size())); + obj.push_back(Pair("nLastSendEmpty", (boost::int64_t)pnode->nLastSendEmpty)); + obj.push_back(Pair("nMisbehavior", pnode->nMisbehavior)); + obj.push_back(Pair("nReleaseTime", (boost::int64_t)pnode->nReleaseTime)); + obj.push_back(Pair("hashContinue", pnode->hashContinue.GetHex())); + obj.push_back(Pair("vAddrToSend_size", pnode->vAddrToSend.size())); + obj.push_back(Pair("setAddrKnown_size", pnode->setAddrKnown.size())); + obj.push_back(Pair("fGetAddr", pnode->fGetAddr)); + obj.push_back(Pair("setKnown_size", pnode->setKnown.size())); + obj.push_back(Pair("setInventoryKnown_size", pnode->setInventoryKnown.size())); + obj.push_back(Pair("vInventoryToSend_size", pnode->vInventoryToSend.size())); + obj.push_back(Pair("mapAskFor_size", pnode->mapAskFor.size())); + ret.push_back(obj); + } + return ret; +} Value getnewaddress(const Array& params, bool fHelp) { @@ -2005,12 +2070,14 @@ make_pair("stop", &stop), make_pair("getblockcount", &getblockcount), make_pair("getblocknumber", &getblocknumber), + make_pair("getbestblockhash", &getbestblockhash), make_pair("getconnectioncount", &getconnectioncount), make_pair("getdifficulty", &getdifficulty), make_pair("getgenerate", &getgenerate), make_pair("setgenerate", &setgenerate), make_pair("gethashespersec", &gethashespersec), make_pair("getinfo", &getinfo), + make_pair("getpeerinfo", &getpeerinfo), make_pair("getnewaddress", &getnewaddress), make_pair("getaccountaddress", &getaccountaddress), make_pair("setaccount", &setaccount), @@ -2058,12 +2125,14 @@ "stop", "getblockcount", "getblocknumber", // deprecated + "getbestblockhash", "getconnectioncount", "getdifficulty", "getgenerate", "setgenerate", "gethashespersec", "getinfo", + "getpeerinfo", "getnewaddress", "getaccountaddress", "getaccount", diff -uNr a/bitcoin/src/init.cpp b/bitcoin/src/init.cpp --- a/bitcoin/src/init.cpp 3b26dcbfbf59ff4bacbb62b11d0f1acad77a94d66fcf37a30703257b0e00511b7c63942bbe09056fe811af6539ec9ea97d71c4e2577a82cdc40b0f5abb2693d1 +++ b/bitcoin/src/init.cpp 10ca23faf53499a34c255131522c26e14a74c7724f7172b8238246dea26cee28b0edb73ff8e581f750b7b874cecc3bce6d592082a1401bed4257f9e6414e5639 @@ -288,8 +288,6 @@ fprintf(stderr, "Error: setsid(): %s\n", StringError(errno).c_str()); } - if (!fDebug && !pszSetDataDir[0]) - ShrinkDebugFile(); printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); printf("Bitcoin version %s\n", FormatFullVersion().c_str()); printf("Default data directory %s\n", GetDefaultDataDir().c_str()); diff -uNr a/bitcoin/src/main.cpp b/bitcoin/src/main.cpp --- a/bitcoin/src/main.cpp 5d2369099187febaa86bd7e760543be6d6b8846123285646407f03a22a068d0b205b988bfdd146b80b7752edef00f7416fd804bd0d7c0bbb4c39bcd4a1a09941 +++ b/bitcoin/src/main.cpp 81c88cc34c2a35a06e1856f831e42e83cca6cdbb9e5ab003433308fc211843abc0529b80b733cf642e81f8888ca9af4828cfa807506a183ac4f0ebd967818505 @@ -115,6 +115,12 @@ return mapTransactions.count(hash) != 0; } +size_t GetMempoolSize() +{ + SCOPED_LOCK(cs_mapTransactions); + return mapTransactions.size(); +} + ////////////////////////////////////////////////////////////////////////////// // // dispatching functions @@ -2426,7 +2432,8 @@ const CInv& inv = (*pto->mapAskFor.begin()).second; if (!AlreadyHave(txdb, inv)) { - printf("sending getdata: %s\n", inv.ToString().c_str()); + if (fDebug) + printf("sending getdata: %s\n", inv.ToString().c_str()); vGetData.push_back(inv); if (vGetData.size() >= 1000) { @@ -2434,6 +2441,7 @@ vGetData.clear(); } } + // XXX redundant with the insertion in CNode::AskFor? mapAlreadyAskedFor[inv] = nNow; pto->mapAskFor.erase(pto->mapAskFor.begin()); } diff -uNr a/bitcoin/src/main.h b/bitcoin/src/main.h --- a/bitcoin/src/main.h f2d586abd98cb8b61ddcd5c63e6f627b58f1e8d5fa1be70e249347ff96e017afaace0b7d586715cc8d855c732f776c1f7e3f60cea8bdf4c2314c6cfb838560af +++ b/bitcoin/src/main.h 32aa17511399aa79da73052a641d9b84c9e2817f9a0e4d8649591bf39395cc871a0b136e82cb8a55b9252c3a72d9b7b01594dd78c86a96e60a0c7d9dcdc25d06 @@ -25,6 +25,8 @@ class CInv; class CNode; class CBlockIndex; +class CInPoint; +class COutPoint; static const unsigned int MAX_BLOCK_SIZE = 1000000; static const unsigned int MAX_BLOCK_SIZE_GEN = MAX_BLOCK_SIZE/2; @@ -43,6 +45,7 @@ extern CCriticalSection cs_main; +extern std::map mapNextTx; extern std::map mapBlockIndex; extern uint256 hashGenesisBlock; extern CBlockIndex* pindexGenesisBlock; @@ -86,6 +89,7 @@ bool GetMempoolTx(const uint256 &hash, CTransaction &tx); bool MempoolContainsTx(const uint256 &hash); +size_t GetMempoolSize(); void RegisterWallet(CWallet* pwalletIn); void UnregisterWallet(CWallet* pwalletIn); void SyncWithWallets(const CTransaction& tx, const CBlock* pblock = NULL, bool fUpdate = false); diff -uNr a/bitcoin/src/net.cpp b/bitcoin/src/net.cpp --- a/bitcoin/src/net.cpp d84be0a2d4aa69a293ded8e4cb97db0bc033fa36bd592ecb4f3fede7279bf7d4eb5070e34924509f2b6a6d7a30dea2b75db5bafae4d462e9fd41fafbcd26b658 +++ b/bitcoin/src/net.cpp d09f0c1415b5d92fdbe812069e46afec06bfd94432d6f05df299b747f5539e08d786b587101fe00cc8cfb05d51f995a94907f2e551a133d89058b94138b2c8ce @@ -253,7 +253,8 @@ if (it == mapAddresses.end()) { // New address - printf("AddAddress(%s)\n", addr.ToString().c_str()); + if (fDebug) + printf("AddAddress(%s)\n", addr.ToString().c_str()); mapAddresses.insert(make_pair(addr.GetKey(), addr)); fUpdated = true; fNew = true; diff -uNr a/bitcoin/src/net.h b/bitcoin/src/net.h --- a/bitcoin/src/net.h 535c36b1f7607ab818f9df2c020c583756542fe6dfa6a7fbd5aa0c5a4736106a0a8ea1e80a3dbc0dc2d666479793bf84c662a91b0c489db361baf6dc8c8cf727 +++ b/bitcoin/src/net.h 517f957058f9344024155603c69301ea6c19c2a719de92aff09861f1df114311e16ba8c94edaf4d601eb90a66fc0f2a70c2d8f81d38bb2ea4e8cade4c28ee69e @@ -97,6 +97,7 @@ bool fNetworkNode; bool fSuccessfullyConnected; bool fDisconnect; + int nMisbehavior; protected: int nRefCount; @@ -104,7 +105,6 @@ // Key is ip address, value is banned-until-time static std::map setBanned; static CCriticalSection cs_setBanned; - int nMisbehavior; public: int64 nReleaseTime; @@ -232,7 +232,7 @@ // We're using mapAskFor as a priority queue, // the key is the earliest time the request can be sent int64& nRequestTime = mapAlreadyAskedFor[inv]; - printf("askfor %s %"PRI64d"\n", inv.ToString().c_str(), nRequestTime); + // XXX inv isn't always cleaned out from mapAlreadyAskedFor after this insertion, see http://jfxpt.com/2025/a-thorny-memory-leak-in-bitcoind-and-a-way-forward/ // Make sure not to reuse time indexes to keep things in the same order int64 nNow = (GetTime() - 1) * 1000000; diff -uNr a/bitcoin/src/util.cpp b/bitcoin/src/util.cpp --- a/bitcoin/src/util.cpp 04b7c3d690e97fdc8bae2b9fbf978f6f7ef4e4be95e98babd993754590b2c23bbbd800b53a5c404b26814ea2a20b0fa0bcd218272e2fa3974ad3eebd29d0e87a +++ b/bitcoin/src/util.cpp 7a23f133253df5d0769c201b22e1a6606420e6a03f69a27333d70c3cfabd36ae64153c2d2e1c49145ae2cfae75ff764e5f42681e3ba6a4884af111c37b9f5317 @@ -755,45 +755,6 @@ } } -int GetFilesize(FILE* file) -{ - int nSavePos = ftell(file); - int nFilesize = -1; - if (fseek(file, 0, SEEK_END) == 0) - nFilesize = ftell(file); - fseek(file, nSavePos, SEEK_SET); - return nFilesize; -} - -void ShrinkDebugFile() -{ - // Scroll debug.log if it's getting too big - string strFile = GetDataDir() + "/debug.log"; - FILE* file = fopen(strFile.c_str(), "r"); - if (file && GetFilesize(file) > 10 * 1000000) - { - // Restart the file with some of the end - vector vch(200*1000); - fseek(file, -vch.size(), SEEK_END); - int nBytes = fread(vch.data(), 1, vch.size(), file); - fclose(file); - - file = fopen(strFile.c_str(), "w"); - if (file) - { - fwrite(vch.data(), 1, nBytes, file); - fclose(file); - } - } -} - - - - - - - - // // "Never go to sea with two chronometers; take one or three." // Our three time sources are: diff -uNr a/bitcoin/src/util.h b/bitcoin/src/util.h --- a/bitcoin/src/util.h 69eabb88785ef1d9be04a591fc11fd8055f2e805ca93a8f9c37768101b3b548a3034c7606207215e6d508747f6a6528b09632e2dd22c2f399e14d02c4ee8885f +++ b/bitcoin/src/util.h eae832be1978fc0d23ba469371dc5935a8d9c5bb1a9daa1d7589c5a0e81596f9f628ceaf7de8489cb717d22dfd06a35fcedd2b5a47f92eb314b888b4113a7b7f @@ -137,7 +137,6 @@ const char* wxGetTranslation(const char* psz); bool WildcardMatch(const char* psz, const char* mask); bool WildcardMatch(const std::string& str, const std::string& mask); -int GetFilesize(FILE* file); void GetDataDir(char* pszDirRet); std::string GetConfigFile(); std::string GetPidFile(); @@ -145,7 +144,6 @@ void ReadConfigFile(std::map& mapSettingsRet, std::map >& mapMultiSettingsRet); std::string GetDefaultDataDir(); std::string GetDataDir(); -void ShrinkDebugFile(); int GetRandInt(int nMax); uint64 GetRand(uint64 nMax); int64 GetTime();