diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/httpserver.cpp | 4 | ||||
-rw-r--r-- | src/main.cpp | 33 | ||||
-rw-r--r-- | src/net.cpp | 1 | ||||
-rw-r--r-- | src/net.h | 1 | ||||
-rw-r--r-- | src/qt/clientmodel.cpp | 12 | ||||
-rw-r--r-- | src/qt/clientmodel.h | 6 | ||||
-rw-r--r-- | src/qt/forms/debugwindow.ui | 148 | ||||
-rw-r--r-- | src/qt/guiutil.cpp | 5 | ||||
-rw-r--r-- | src/qt/rpcconsole.cpp | 12 | ||||
-rw-r--r-- | src/qt/rpcconsole.h | 2 | ||||
-rw-r--r-- | src/rpcblockchain.cpp | 6 | ||||
-rw-r--r-- | src/rpcnet.cpp | 2 | ||||
-rw-r--r-- | src/test/accounting_tests.cpp | 8 | ||||
-rw-r--r-- | src/wallet/rpcwallet.cpp | 12 | ||||
-rw-r--r-- | src/wallet/wallet.cpp | 47 | ||||
-rw-r--r-- | src/wallet/wallet.h | 17 | ||||
-rw-r--r-- | src/wallet/walletdb.cpp | 8 | ||||
-rw-r--r-- | src/wallet/walletdb.h | 4 |
18 files changed, 224 insertions, 104 deletions
diff --git a/src/httpserver.cpp b/src/httpserver.cpp index 52f5675e85..91518d7c5f 100644 --- a/src/httpserver.cpp +++ b/src/httpserver.cpp @@ -487,7 +487,11 @@ void StopHTTPServer() // master that appears to be solved, so in the future that solution // could be used again (if desirable). // (see discussion in https://github.com/bitcoin/bitcoin/pull/6990) +#if BOOST_VERSION >= 105000 if (!threadHTTP.try_join_for(boost::chrono::milliseconds(2000))) { +#else + if (!threadHTTP.timed_join(boost::posix_time::milliseconds(2000))) { +#endif LogPrintf("HTTP event loop did not exit within allotted time, sending loopbreak\n"); event_base_loopbreak(eventBase); threadHTTP.join(); diff --git a/src/main.cpp b/src/main.cpp index 8fb121c00d..2579b642b8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -670,10 +670,11 @@ bool CheckFinalTx(const CTransaction &tx, int flags) // IsFinalTx() with one more than chainActive.Height(). const int nBlockHeight = chainActive.Height() + 1; - // Timestamps on the other hand don't get any special treatment, - // because we can't know what timestamp the next block will have, - // and there aren't timestamp applications where it matters. - // However this changes once median past time-locks are enforced: + // BIP113 will require that time-locked transactions have nLockTime set to + // less than the median time of the previous block they're contained in. + // When the next block is created its previous block will be the current + // chain tip, so we use that to calculate the median time passed to + // IsFinalTx() if LOCKTIME_MEDIAN_TIME_PAST is set. const int64_t nBlockTime = (flags & LOCKTIME_MEDIAN_TIME_PAST) ? chainActive.Tip()->GetMedianTimePast() : GetAdjustedTime(); @@ -4210,6 +4211,12 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, return error("message inv size() = %u", vInv.size()); } + bool fBlocksOnly = GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY); + + // Allow whitelisted peers to send data other than blocks in blocks only mode if whitelistalwaysrelay is true + if (pfrom->fWhitelisted && GetBoolArg("-whitelistalwaysrelay", DEFAULT_WHITELISTALWAYSRELAY)) + fBlocksOnly = false; + LOCK(cs_main); std::vector<CInv> vToFetch; @@ -4224,9 +4231,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, bool fAlreadyHave = AlreadyHave(inv); LogPrint("net", "got inv: %s %s peer=%d\n", inv.ToString(), fAlreadyHave ? "have" : "new", pfrom->id); - if (!fAlreadyHave && !fImporting && !fReindex && inv.type != MSG_BLOCK && !GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY)) - pfrom->AskFor(inv); - if (inv.type == MSG_BLOCK) { UpdateBlockAvailability(pfrom->GetId(), inv.hash); if (!fAlreadyHave && !fImporting && !fReindex && !mapBlocksInFlight.count(inv.hash)) { @@ -4250,6 +4254,13 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, LogPrint("net", "getheaders (%d) %s to peer=%d\n", pindexBestHeader->nHeight, inv.hash.ToString(), pfrom->id); } } + else + { + if (fBlocksOnly) + LogPrint("net", "transaction (%s) inv sent in violation of protocol peer=%d\n", inv.hash.ToString(), pfrom->id); + else if (!fAlreadyHave && !fImporting && !fReindex) + pfrom->AskFor(inv); + } // Track requests for our stuff GetMainSignals().Inventory(inv.hash); @@ -4374,6 +4385,14 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, else if (strCommand == "tx") { + // Stop processing the transaction early if + // We are in blocks only mode and peer is either not whitelisted or whitelistalwaysrelay is off + if (GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY) && (!pfrom->fWhitelisted || !GetBoolArg("-whitelistalwaysrelay", DEFAULT_WHITELISTALWAYSRELAY))) + { + LogPrint("net", "transaction sent in violation of protocol peer=%d\n", pfrom->id); + return true; + } + vector<uint256> vWorkQueue; vector<uint256> vEraseQueue; CTransaction tx; diff --git a/src/net.cpp b/src/net.cpp index 000eefc858..cff4c54505 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -617,6 +617,7 @@ void CNode::copyStats(CNodeStats &stats) { stats.nodeid = this->GetId(); X(nServices); + X(fRelayTxes); X(nLastSend); X(nLastRecv); X(nTimeConnected); @@ -180,6 +180,7 @@ class CNodeStats public: NodeId nodeid; uint64_t nServices; + bool fRelayTxes; int64_t nLastSend; int64_t nLastRecv; int64_t nTimeConnected; diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index 0900a35cc4..566e8fa62d 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -13,6 +13,7 @@ #include "checkpoints.h" #include "clientversion.h" #include "net.h" +#include "txmempool.h" #include "ui_interface.h" #include "util.h" @@ -88,6 +89,16 @@ QDateTime ClientModel::getLastBlockDate() const return QDateTime::fromTime_t(Params().GenesisBlock().GetBlockTime()); // Genesis block's time of current network } +long ClientModel::getMempoolSize() const +{ + return mempool.size(); +} + +size_t ClientModel::getMempoolDynamicUsage() const +{ + return mempool.DynamicMemoryUsage(); +} + double ClientModel::getVerificationProgress() const { LOCK(cs_main); @@ -122,6 +133,7 @@ void ClientModel::updateTimer() Q_EMIT numBlocksChanged(newNumBlocks, newBlockDate); } + Q_EMIT mempoolSizeChanged(getMempoolSize(), getMempoolDynamicUsage()); Q_EMIT bytesChanged(getTotalBytesRecv(), getTotalBytesSent()); } diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h index 627bdf862d..493a759331 100644 --- a/src/qt/clientmodel.h +++ b/src/qt/clientmodel.h @@ -51,6 +51,11 @@ public: int getNumConnections(unsigned int flags = CONNECTIONS_ALL) const; int getNumBlocks() const; + //! Return number of transactions in the mempool + long getMempoolSize() const; + //! Return the dynamic memory usage of the mempool + size_t getMempoolDynamicUsage() const; + quint64 getTotalBytesRecv() const; quint64 getTotalBytesSent() const; @@ -89,6 +94,7 @@ private: Q_SIGNALS: void numConnectionsChanged(int count); void numBlocksChanged(int count, const QDateTime& blockDate); + void mempoolSizeChanged(long count, size_t mempoolSizeInBytes); void alertsChanged(const QString &warnings); void bytesChanged(quint64 totalBytesIn, quint64 totalBytesOut); diff --git a/src/qt/forms/debugwindow.ui b/src/qt/forms/debugwindow.ui index eb02dd80ff..2471470363 100644 --- a/src/qt/forms/debugwindow.ui +++ b/src/qt/forms/debugwindow.ui @@ -23,7 +23,7 @@ <attribute name="title"> <string>&Information</string> </attribute> - <layout class="QGridLayout" name="gridLayout" columnstretch="0,1"> + <layout class="QGridLayout" name="gridLayout" columnstretch="0,1,0"> <property name="horizontalSpacing"> <number>12</number> </property> @@ -47,7 +47,7 @@ </property> </widget> </item> - <item row="1" column="1"> + <item row="1" column="1" colspan="2"> <widget class="QLabel" name="clientName"> <property name="cursor"> <cursorShape>IBeamCursor</cursorShape> @@ -70,7 +70,7 @@ </property> </widget> </item> - <item row="2" column="1"> + <item row="2" column="1" colspan="2"> <widget class="QLabel" name="clientVersion"> <property name="cursor"> <cursorShape>IBeamCursor</cursorShape> @@ -96,7 +96,7 @@ </property> </widget> </item> - <item row="3" column="1"> + <item row="3" column="1" colspan="2"> <widget class="QLabel" name="clientUserAgent"> <property name="cursor"> <cursorShape>IBeamCursor</cursorShape> @@ -122,7 +122,7 @@ </property> </widget> </item> - <item row="4" column="1"> + <item row="4" column="1" colspan="2"> <widget class="QLabel" name="openSSLVersion"> <property name="cursor"> <cursorShape>IBeamCursor</cursorShape> @@ -148,7 +148,7 @@ </property> </widget> </item> - <item row="5" column="1"> + <item row="5" column="1" colspan="2"> <widget class="QLabel" name="berkeleyDBVersion"> <property name="cursor"> <cursorShape>IBeamCursor</cursorShape> @@ -171,7 +171,7 @@ </property> </widget> </item> - <item row="6" column="1"> + <item row="6" column="1" colspan="2"> <widget class="QLabel" name="buildDate"> <property name="cursor"> <cursorShape>IBeamCursor</cursorShape> @@ -194,7 +194,7 @@ </property> </widget> </item> - <item row="7" column="1"> + <item row="7" column="1" colspan="2"> <widget class="QLabel" name="startupTime"> <property name="cursor"> <cursorShape>IBeamCursor</cursorShape> @@ -210,19 +210,6 @@ </property> </widget> </item> - <item row="8" column="0"> - <widget class="QLabel" name="label_11"> - <property name="font"> - <font> - <weight>75</weight> - <bold>true</bold> - </font> - </property> - <property name="text"> - <string>Network</string> - </property> - </widget> - </item> <item row="9" column="0"> <widget class="QLabel" name="label_8"> <property name="text"> @@ -230,7 +217,7 @@ </property> </widget> </item> - <item row="9" column="1"> + <item row="9" column="1" colspan="2"> <widget class="QLabel" name="networkName"> <property name="cursor"> <cursorShape>IBeamCursor</cursorShape> @@ -253,7 +240,7 @@ </property> </widget> </item> - <item row="10" column="1"> + <item row="10" column="1" colspan="2"> <widget class="QLabel" name="numberOfConnections"> <property name="cursor"> <cursorShape>IBeamCursor</cursorShape> @@ -289,7 +276,7 @@ </property> </widget> </item> - <item row="12" column="1"> + <item row="12" column="1" colspan="2"> <widget class="QLabel" name="numberOfBlocks"> <property name="cursor"> <cursorShape>IBeamCursor</cursorShape> @@ -306,13 +293,13 @@ </widget> </item> <item row="13" column="0"> - <widget class="QLabel" name="label_2"> + <widget class="QLabel" name="labelLastBlockTime"> <property name="text"> <string>Last block time</string> </property> </widget> </item> - <item row="13" column="1"> + <item row="13" column="1" colspan="2"> <widget class="QLabel" name="lastBlockTime"> <property name="cursor"> <cursorShape>IBeamCursor</cursorShape> @@ -329,20 +316,43 @@ </widget> </item> <item row="14" column="0"> - <spacer name="verticalSpacer_2"> - <property name="orientation"> - <enum>Qt::Vertical</enum> + <widget class="QLabel" name="labelMempoolTitle"> + <property name="font"> + <font> + <weight>75</weight> + <bold>true</bold> + </font> </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>20</height> - </size> + <property name="text"> + <string>Memory Pool</string> </property> - </spacer> + </widget> </item> <item row="15" column="0"> - <widget class="QLabel" name="labelDebugLogfile"> + <widget class="QLabel" name="labelNumberOfTransactions"> + <property name="text"> + <string>Current number of transactions</string> + </property> + </widget> + </item> + <item row="15" column="1"> + <widget class="QLabel" name="mempoolNumberTxs"> + <property name="cursor"> + <cursorShape>IBeamCursor</cursorShape> + </property> + <property name="text"> + <string>N/A</string> + </property> + <property name="textFormat"> + <enum>Qt::PlainText</enum> + </property> + <property name="textInteractionFlags"> + <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> + </property> + </widget> + </item> + <item row="8" column="0"> + <widget class="QLabel" name="labelNetwork"> <property name="font"> <font> <weight>75</weight> @@ -350,24 +360,74 @@ </font> </property> <property name="text"> - <string>Debug log file</string> + <string>Network</string> </property> </widget> </item> <item row="16" column="0"> - <widget class="QPushButton" name="openDebugLogfileButton"> - <property name="toolTip"> - <string>Open the Bitcoin Core debug log file from the current data directory. This can take a few seconds for large log files.</string> + <widget class="QLabel" name="labelMemoryUsage"> + <property name="text"> + <string>Memory usage</string> + </property> + </widget> + </item> + <item row="16" column="1"> + <widget class="QLabel" name="mempoolSize"> + <property name="cursor"> + <cursorShape>IBeamCursor</cursorShape> </property> <property name="text"> - <string>&Open</string> + <string>N/A</string> </property> - <property name="autoDefault"> - <bool>false</bool> + <property name="textFormat"> + <enum>Qt::PlainText</enum> + </property> + <property name="textInteractionFlags"> + <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set> </property> </widget> </item> - <item row="17" column="0"> + <item row="14" column="2" rowspan="3"> + <layout class="QVBoxLayout" name="verticalLayoutDebugButton"> + <property name="spacing"> + <number>3</number> + </property> + <item> + <spacer name="verticalSpacer_2"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>10</width> + <height>5</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="labelDebugLogfile"> + <property name="text"> + <string>Debug log file</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="openDebugLogfileButton"> + <property name="toolTip"> + <string>Open the Bitcoin Core debug log file from the current data directory. This can take a few seconds for large log files.</string> + </property> + <property name="text"> + <string>&Open</string> + </property> + <property name="autoDefault"> + <bool>false</bool> + </property> + </widget> + </item> + </layout> + </item> + <item row="18" column="0"> <spacer name="verticalSpacer"> <property name="orientation"> <enum>Qt::Vertical</enum> diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index 845459b76a..6dce9370d7 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -681,7 +681,10 @@ boost::filesystem::path static GetAutostartDir() boost::filesystem::path static GetAutostartFilePath() { - return GetAutostartDir() / "bitcoin.desktop"; + std::string chain = ChainNameFromCommandLine(); + if (chain == CBaseChainParams::MAIN) + return GetAutostartDir() / "bitcoin.desktop"; + return GetAutostartDir() / strprintf("bitcoin-%s.lnk", chain); } bool GetStartOnSystemStartup() diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index 4554281e0f..619c8631ae 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -343,6 +343,8 @@ void RPCConsole::setClientModel(ClientModel *model) updateTrafficStats(model->getTotalBytesRecv(), model->getTotalBytesSent()); connect(model, SIGNAL(bytesChanged(quint64,quint64)), this, SLOT(updateTrafficStats(quint64, quint64))); + connect(model, SIGNAL(mempoolSizeChanged(long,size_t)), this, SLOT(setMempoolSize(long,size_t))); + // set up peer table ui->peerWidget->setModel(model->getPeerTableModel()); ui->peerWidget->verticalHeader()->hide(); @@ -523,6 +525,16 @@ void RPCConsole::setNumBlocks(int count, const QDateTime& blockDate) ui->lastBlockTime->setText(blockDate.toString()); } +void RPCConsole::setMempoolSize(long numberOfTxs, size_t dynUsage) +{ + ui->mempoolNumberTxs->setText(QString::number(numberOfTxs)); + + if (dynUsage < 1000000) + ui->mempoolSize->setText(QString::number(dynUsage/1000.0, 'f', 2) + " KB"); + else + ui->mempoolSize->setText(QString::number(dynUsage/1000000.0, 'f', 2) + " MB"); +} + void RPCConsole::on_lineEdit_returnPressed() { QString cmd = ui->lineEdit->text(); diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h index 0914612c3e..4b242affcd 100644 --- a/src/qt/rpcconsole.h +++ b/src/qt/rpcconsole.h @@ -84,6 +84,8 @@ public Q_SLOTS: void setNumConnections(int count); /** Set number of blocks and last block date shown in the UI */ void setNumBlocks(int count, const QDateTime& blockDate); + /** Set size (number of transactions and memory usage) of the mempool in the UI */ + void setMempoolSize(long numberOfTxs, size_t dynUsage); /** Go forward or back in history */ void browseHistory(int offset); /** Scroll console view to end */ diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp index 9c0e78f772..012370ed10 100644 --- a/src/rpcblockchain.cpp +++ b/src/rpcblockchain.cpp @@ -71,6 +71,7 @@ UniValue blockheaderToJSON(const CBlockIndex* blockindex) result.push_back(Pair("version", blockindex->nVersion)); result.push_back(Pair("merkleroot", blockindex->hashMerkleRoot.GetHex())); result.push_back(Pair("time", (int64_t)blockindex->nTime)); + result.push_back(Pair("mediantime", (int64_t)blockindex->GetMedianTimePast())); result.push_back(Pair("nonce", (uint64_t)blockindex->nNonce)); result.push_back(Pair("bits", strprintf("%08x", blockindex->nBits))); result.push_back(Pair("difficulty", GetDifficulty(blockindex))); @@ -111,6 +112,7 @@ UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool tx } result.push_back(Pair("tx", txs)); result.push_back(Pair("time", block.GetBlockTime())); + result.push_back(Pair("mediantime", (int64_t)blockindex->GetMedianTimePast())); result.push_back(Pair("nonce", (uint64_t)block.nNonce)); result.push_back(Pair("bits", strprintf("%08x", block.nBits))); result.push_back(Pair("difficulty", GetDifficulty(blockindex))); @@ -313,6 +315,7 @@ UniValue getblockheader(const UniValue& params, bool fHelp) " \"version\" : n, (numeric) The block version\n" " \"merkleroot\" : \"xxxx\", (string) The merkle root\n" " \"time\" : ttt, (numeric) The block time in seconds since epoch (Jan 1 1970 GMT)\n" + " \"mediantime\" : ttt, (numeric) The median block time in seconds since epoch (Jan 1 1970 GMT)\n" " \"nonce\" : n, (numeric) The nonce\n" " \"bits\" : \"1d00ffff\", (string) The bits\n" " \"difficulty\" : x.xxx, (numeric) The difficulty\n" @@ -374,6 +377,7 @@ UniValue getblock(const UniValue& params, bool fHelp) " ,...\n" " ],\n" " \"time\" : ttt, (numeric) The block time in seconds since epoch (Jan 1 1970 GMT)\n" + " \"mediantime\" : ttt, (numeric) The median block time in seconds since epoch (Jan 1 1970 GMT)\n" " \"nonce\" : n, (numeric) The nonce\n" " \"bits\" : \"1d00ffff\", (string) The bits\n" " \"difficulty\" : x.xxx, (numeric) The difficulty\n" @@ -608,6 +612,7 @@ UniValue getblockchaininfo(const UniValue& params, bool fHelp) " \"headers\": xxxxxx, (numeric) the current number of headers we have validated\n" " \"bestblockhash\": \"...\", (string) the hash of the currently best block\n" " \"difficulty\": xxxxxx, (numeric) the current difficulty\n" + " \"mediantime\": xxxxxx, (numeric) median time for the current best block\n" " \"verificationprogress\": xxxx, (numeric) estimate of verification progress [0..1]\n" " \"chainwork\": \"xxxx\" (string) total amount of work in active chain, in hexadecimal\n" " \"pruned\": xx, (boolean) if the blocks are subject to pruning\n" @@ -639,6 +644,7 @@ UniValue getblockchaininfo(const UniValue& params, bool fHelp) obj.push_back(Pair("headers", pindexBestHeader ? pindexBestHeader->nHeight : -1)); obj.push_back(Pair("bestblockhash", chainActive.Tip()->GetBlockHash().GetHex())); obj.push_back(Pair("difficulty", (double)GetDifficulty())); + obj.push_back(Pair("mediantime", (int64_t)chainActive.Tip()->GetMedianTimePast())); obj.push_back(Pair("verificationprogress", Checkpoints::GuessVerificationProgress(Params().Checkpoints(), chainActive.Tip()))); obj.push_back(Pair("chainwork", chainActive.Tip()->nChainWork.GetHex())); obj.push_back(Pair("pruned", fPruneMode)); diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp index 8915010649..2578848891 100644 --- a/src/rpcnet.cpp +++ b/src/rpcnet.cpp @@ -90,6 +90,7 @@ UniValue getpeerinfo(const UniValue& params, bool fHelp) " \"addr\":\"host:port\", (string) The ip address and port of the peer\n" " \"addrlocal\":\"ip:port\", (string) local address\n" " \"services\":\"xxxxxxxxxxxxxxxx\", (string) The services offered\n" + " \"relaytxes\":true|false, (boolean) Whether peer has asked us to relay transactions to it\n" " \"lastsend\": ttt, (numeric) The time in seconds since epoch (Jan 1 1970 GMT) of the last send\n" " \"lastrecv\": ttt, (numeric) The time in seconds since epoch (Jan 1 1970 GMT) of the last receive\n" " \"bytessent\": n, (numeric) The total bytes sent\n" @@ -134,6 +135,7 @@ UniValue getpeerinfo(const UniValue& params, bool fHelp) if (!(stats.addrLocal.empty())) obj.push_back(Pair("addrlocal", stats.addrLocal)); obj.push_back(Pair("services", strprintf("%016x", stats.nServices))); + obj.push_back(Pair("relaytxes", stats.fRelayTxes)); obj.push_back(Pair("lastsend", stats.nLastSend)); obj.push_back(Pair("lastrecv", stats.nLastRecv)); obj.push_back(Pair("bytessent", stats.nSendBytes)); diff --git a/src/test/accounting_tests.cpp b/src/test/accounting_tests.cpp index 0c2ade48d6..4a294c6712 100644 --- a/src/test/accounting_tests.cpp +++ b/src/test/accounting_tests.cpp @@ -45,7 +45,7 @@ BOOST_AUTO_TEST_CASE(acc_orderupgrade) ae.nTime = 1333333333; ae.strOtherAccount = "b"; ae.strComment = ""; - walletdb.WriteAccountingEntry(ae); + pwalletMain->AddAccountingEntry(ae, walletdb); wtx.mapValue["comment"] = "z"; pwalletMain->AddToWallet(wtx, false, &walletdb); @@ -55,7 +55,7 @@ BOOST_AUTO_TEST_CASE(acc_orderupgrade) ae.nTime = 1333333336; ae.strOtherAccount = "c"; - walletdb.WriteAccountingEntry(ae); + pwalletMain->AddAccountingEntry(ae, walletdb); GetResults(walletdb, results); @@ -71,7 +71,7 @@ BOOST_AUTO_TEST_CASE(acc_orderupgrade) ae.nTime = 1333333330; ae.strOtherAccount = "d"; ae.nOrderPos = pwalletMain->IncOrderPosNext(); - walletdb.WriteAccountingEntry(ae); + pwalletMain->AddAccountingEntry(ae, walletdb); GetResults(walletdb, results); @@ -121,7 +121,7 @@ BOOST_AUTO_TEST_CASE(acc_orderupgrade) ae.nTime = 1333333334; ae.strOtherAccount = "e"; ae.nOrderPos = -1; - walletdb.WriteAccountingEntry(ae); + pwalletMain->AddAccountingEntry(ae, walletdb); GetResults(walletdb, results); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 63d45d9709..b6eaca80b3 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -835,7 +835,7 @@ UniValue movecmd(const UniValue& params, bool fHelp) debit.nTime = nNow; debit.strOtherAccount = strTo; debit.strComment = strComment; - walletdb.WriteAccountingEntry(debit); + pwalletMain->AddAccountingEntry(debit, walletdb); // Credit CAccountingEntry credit; @@ -845,7 +845,7 @@ UniValue movecmd(const UniValue& params, bool fHelp) credit.nTime = nNow; credit.strOtherAccount = strFrom; credit.strComment = strComment; - walletdb.WriteAccountingEntry(credit); + pwalletMain->AddAccountingEntry(credit, walletdb); if (!walletdb.TxnCommit()) throw JSONRPCError(RPC_DATABASE_ERROR, "database error"); @@ -1471,11 +1471,10 @@ UniValue listtransactions(const UniValue& params, bool fHelp) UniValue ret(UniValue::VARR); - std::list<CAccountingEntry> acentries; - CWallet::TxItems txOrdered = pwalletMain->OrderedTxItems(acentries, strAccount); + const CWallet::TxItems & txOrdered = pwalletMain->wtxOrdered; // iterate backwards until we have nCount items to return: - for (CWallet::TxItems::reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it) + for (CWallet::TxItems::const_reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it) { CWalletTx *const pwtx = (*it).second.first; if (pwtx != 0) @@ -1580,8 +1579,7 @@ UniValue listaccounts(const UniValue& params, bool fHelp) } } - list<CAccountingEntry> acentries; - CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries); + const list<CAccountingEntry> & acentries = pwalletMain->laccentries; BOOST_FOREACH(const CAccountingEntry& entry, acentries) mapAccountBalances[entry.strAccount] += entry.nCreditDebit; diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index d51b8ddaef..1b152f4192 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -588,31 +588,6 @@ int64_t CWallet::IncOrderPosNext(CWalletDB *pwalletdb) return nRet; } -CWallet::TxItems CWallet::OrderedTxItems(std::list<CAccountingEntry>& acentries, std::string strAccount) -{ - AssertLockHeld(cs_wallet); // mapWallet - CWalletDB walletdb(strWalletFile); - - // First: get all CWalletTx and CAccountingEntry into a sorted-by-order multimap. - TxItems txOrdered; - - // Note: maintaining indices in the database of (account,time) --> txid and (account, time) --> acentry - // would make this much faster for applications that do this a lot. - for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) - { - CWalletTx* wtx = &((*it).second); - txOrdered.insert(make_pair(wtx->nOrderPos, TxPair(wtx, (CAccountingEntry*)0))); - } - acentries.clear(); - walletdb.ListAccountCreditDebit(strAccount, acentries); - BOOST_FOREACH(CAccountingEntry& entry, acentries) - { - txOrdered.insert(make_pair(entry.nOrderPos, TxPair((CWalletTx*)0, &entry))); - } - - return txOrdered; -} - void CWallet::MarkDirty() { { @@ -629,7 +604,9 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet, CWalletD if (fFromLoadWallet) { mapWallet[hash] = wtxIn; - mapWallet[hash].BindWallet(this); + CWalletTx& wtx = mapWallet[hash]; + wtx.BindWallet(this); + wtxOrdered.insert(make_pair(wtx.nOrderPos, TxPair(&wtx, (CAccountingEntry*)0))); AddToSpends(hash); } else @@ -644,6 +621,7 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet, CWalletD { wtx.nTimeReceived = GetAdjustedTime(); wtx.nOrderPos = IncOrderPosNext(pwalletdb); + wtxOrdered.insert(make_pair(wtx.nOrderPos, TxPair(&wtx, (CAccountingEntry*)0))); wtx.nTimeSmart = wtx.nTimeReceived; if (!wtxIn.hashBlock.IsNull()) @@ -655,9 +633,8 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet, CWalletD { // Tolerate times up to the last timestamp in the wallet not more than 5 minutes into the future int64_t latestTolerated = latestNow + 300; - std::list<CAccountingEntry> acentries; - TxItems txOrdered = OrderedTxItems(acentries); - for (TxItems::reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it) + const TxItems & txOrdered = wtxOrdered; + for (TxItems::const_reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it) { CWalletTx *const pwtx = (*it).second.first; if (pwtx == &wtx) @@ -2118,6 +2095,18 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey) return true; } +bool CWallet::AddAccountingEntry(const CAccountingEntry& acentry, CWalletDB & pwalletdb) +{ + if (!pwalletdb.WriteAccountingEntry_Backend(acentry)) + return false; + + laccentries.push_back(acentry); + CAccountingEntry & entry = laccentries.back(); + wtxOrdered.insert(make_pair(entry.nOrderPos, TxPair((CWalletTx*)0, &entry))); + + return true; +} + CAmount CWallet::GetRequiredFee(unsigned int nTxBytes) { return std::max(minTxFee.GetFee(nTxBytes), ::minRelayTxFee.GetFee(nTxBytes)); diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 719f11f206..7e846569ff 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -531,6 +531,11 @@ public: } std::map<uint256, CWalletTx> mapWallet; + std::list<CAccountingEntry> laccentries; + + typedef std::pair<CWalletTx*, CAccountingEntry*> TxPair; + typedef std::multimap<int64_t, TxPair > TxItems; + TxItems wtxOrdered; int64_t nOrderPosNext; std::map<uint256, int> mapRequestCount; @@ -617,16 +622,6 @@ public: */ int64_t IncOrderPosNext(CWalletDB *pwalletdb = NULL); - typedef std::pair<CWalletTx*, CAccountingEntry*> TxPair; - typedef std::multimap<int64_t, TxPair > TxItems; - - /** - * Get the wallet's activity log - * @return multimap of ordered transactions and accounting entries - * @warning Returned pointers are *only* valid within the scope of passed acentries - */ - TxItems OrderedTxItems(std::list<CAccountingEntry>& acentries, std::string strAccount = ""); - void MarkDirty(); bool AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet, CWalletDB* pwalletdb); void SyncTransaction(const CTransaction& tx, const CBlock* pblock); @@ -656,6 +651,8 @@ public: std::string& strFailReason, const CCoinControl *coinControl = NULL, bool sign = true); bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey); + bool AddAccountingEntry(const CAccountingEntry&, CWalletDB & pwalletdb); + static CFeeRate minTxFee; /** * Estimate the minimum fee considering user set parameters diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index ea8a4eb043..9ce9f53bd9 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -191,7 +191,7 @@ bool CWalletDB::WriteAccountingEntry(const uint64_t nAccEntryNum, const CAccount return Write(std::make_pair(std::string("acentry"), std::make_pair(acentry.strAccount, nAccEntryNum)), acentry); } -bool CWalletDB::WriteAccountingEntry(const CAccountingEntry& acentry) +bool CWalletDB::WriteAccountingEntry_Backend(const CAccountingEntry& acentry) { return WriteAccountingEntry(++nAccountingEntryNumber, acentry); } @@ -709,6 +709,12 @@ DBErrors CWalletDB::LoadWallet(CWallet* pwallet) if (wss.fAnyUnordered) result = ReorderTransactions(pwallet); + pwallet->laccentries.clear(); + ListAccountCreditDebit("*", pwallet->laccentries); + BOOST_FOREACH(CAccountingEntry& entry, pwallet->laccentries) { + pwallet->wtxOrdered.insert(make_pair(entry.nOrderPos, CWallet::TxPair((CWalletTx*)0, &entry))); + } + return result; } diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h index 270f826aed..3ebc05afd1 100644 --- a/src/wallet/walletdb.h +++ b/src/wallet/walletdb.h @@ -110,6 +110,9 @@ public: bool WriteMinVersion(int nVersion); + /// This writes directly to the database, and will not update the CWallet's cached accounting entries! + /// Use wallet.AddAccountingEntry instead, to write *and* update its caches. + bool WriteAccountingEntry_Backend(const CAccountingEntry& acentry); bool ReadAccount(const std::string& strAccount, CAccount& account); bool WriteAccount(const std::string& strAccount, const CAccount& account); @@ -118,7 +121,6 @@ public: /// Erase destination data tuple from wallet database bool EraseDestData(const std::string &address, const std::string &key); - bool WriteAccountingEntry(const CAccountingEntry& acentry); CAmount GetAccountCreditDebit(const std::string& strAccount); void ListAccountCreditDebit(const std::string& strAccount, std::list<CAccountingEntry>& acentries); |