From e88b6b341d75536f2743ce735c338c9fe93ba272 Mon Sep 17 00:00:00 2001 From: Gavin Andresen Date: Wed, 4 Apr 2012 20:56:13 -0400 Subject: [PATCH 1/5] Bug fix listtransactions from/count handling. --- src/rpc.cpp | 38 +++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/src/rpc.cpp b/src/rpc.cpp index aade32ac1d8..b62da8ecdf0 100644 --- a/src/rpc.cpp +++ b/src/rpc.cpp @@ -1099,14 +1099,21 @@ Value listtransactions(const Array& params, bool fHelp) if (params.size() > 2) nFrom = params[2].get_int(); + if (nCount < 0) + throw JSONRPCError(-8, "Negative count"); + if (nFrom < 0) + throw JSONRPCError(-8, "Negative from"); + Array ret; CWalletDB walletdb(pwalletMain->strWalletFile); - // Firs: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap: + // First: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap. typedef pair TxPair; typedef multimap TxItems; TxItems txByTime; + // 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::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) { CWalletTx* wtx = &((*it).second); @@ -1119,10 +1126,8 @@ Value listtransactions(const Array& params, bool fHelp) txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry))); } - // Now: iterate backwards until we have nCount items to return: - TxItems::reverse_iterator it = txByTime.rbegin(); - if (txByTime.size() > nFrom) std::advance(it, nFrom); - for (; it != txByTime.rend(); ++it) + // iterate backwards until we have nCount items to return: + for (TxItems::reverse_iterator it = txByTime.rbegin(); it != txByTime.rend(); ++it) { CWalletTx *const pwtx = (*it).second.first; if (pwtx != 0) @@ -1131,18 +1136,21 @@ Value listtransactions(const Array& params, bool fHelp) if (pacentry != 0) AcentryToJSON(*pacentry, strAccount, ret); - if (ret.size() >= nCount) break; + if (ret.size() >= (nCount+nFrom)) break; } - // ret is now newest to oldest + // ret is newest to oldest - // Make sure we return only last nCount items (sends-to-self might give us an extra): - if (ret.size() > nCount) - { - Array::iterator last = ret.begin(); - std::advance(last, nCount); - ret.erase(last, ret.end()); - } - std::reverse(ret.begin(), ret.end()); // oldest to newest + if (nFrom > ret.size()) nFrom = ret.size(); + if (nFrom+nCount > ret.size()) nCount = ret.size()-nFrom; + Array::iterator first = ret.begin(); + std::advance(first, nFrom); + Array::iterator last = ret.begin(); + std::advance(last, nFrom+nCount); + + if (last != ret.end()) ret.erase(last, ret.end()); + if (first != ret.begin()) ret.erase(ret.begin(), first); + + std::reverse(ret.begin(), ret.end()); // Return oldest to newest return ret; } From 401db6d96b34bbfa8942af1090ce29cafcf79859 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Sun, 15 Apr 2012 11:42:40 +0200 Subject: [PATCH 2/5] work around issue in boost::program_options that prevents from compiling in clang --- src/util.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/util.cpp b/src/util.cpp index 0f496bc455a..c3290f4176d 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -4,6 +4,17 @@ // file license.txt or http://www.opensource.org/licenses/mit-license.php. #include "headers.h" #include "strlcpy.h" + +// Work around clang compilation problem in Boost 1.46: +// /usr/include/boost/program_options/detail/config_file.hpp:163:17: error: call to function 'to_internal' that is neither visible in the template definition nor found by argument-dependent lookup +// See also: http://stackoverflow.com/questions/10020179/compilation-fail-in-boost-librairies-program-options +// http://clang.debian.net/status.php?version=3.0&key=CANNOT_FIND_FUNCTION +namespace boost { + namespace program_options { + std::string to_internal(const std::string&); + } +} + #include #include #include From f650d62fc66d67e9afb6917de9220b1e0e6759fe Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Sun, 15 Apr 2012 12:22:30 +0200 Subject: [PATCH 3/5] fix warnings: array subscript is of type 'char' [-Wchar-subscripts] --- src/bignum.h | 2 +- src/uint256.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bignum.h b/src/bignum.h index 6e8d3cb8aba..641ebf4b051 100644 --- a/src/bignum.h +++ b/src/bignum.h @@ -300,7 +300,7 @@ public: while (isxdigit(*psz)) { *this <<= 4; - int n = phexdigit[*psz++]; + int n = phexdigit[(unsigned char)*psz++]; *this += n; } if (fNegative) diff --git a/src/uint256.h b/src/uint256.h index ae263346a86..07809e49a8f 100644 --- a/src/uint256.h +++ b/src/uint256.h @@ -315,7 +315,7 @@ public: // hex string to uint static char phexdigit[256] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0, 0,0xa,0xb,0xc,0xd,0xe,0xf,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0xa,0xb,0xc,0xd,0xe,0xf,0,0,0,0,0,0,0,0,0 }; const char* pbegin = psz; - while (phexdigit[*psz] || *psz == '0') + while (phexdigit[(unsigned char)*psz] || *psz == '0') psz++; psz--; unsigned char* p1 = (unsigned char*)pn; From 678a319888f88cf5bae2312afc3ba73533c0f901 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Sun, 15 Apr 2012 12:59:20 +0200 Subject: [PATCH 4/5] fix warnings: delete called on 'XX' that has virtual functions but non-virtual destructor [-Wdelete-non-virtual-dtor] --- src/keystore.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/keystore.h b/src/keystore.h index 1f2c6aea3ea..cb297c35ab5 100644 --- a/src/keystore.h +++ b/src/keystore.h @@ -13,6 +13,8 @@ protected: mutable CCriticalSection cs_KeyStore; public: + virtual ~CKeyStore() {} + virtual bool AddKey(const CKey& key) =0; virtual bool HaveKey(const CBitcoinAddress &address) const =0; virtual bool GetKey(const CBitcoinAddress &address, CKey& keyOut) const =0; From 8460185dec74383b1e49500683cfc7aa9ceba554 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Sun, 15 Apr 2012 13:27:00 +0200 Subject: [PATCH 5/5] fix warnings: suggest explicit braces to avoid ambiguous 'else' [-Wparentheses] --- src/main.cpp | 4 ++++ src/main.h | 2 ++ src/rpc.cpp | 4 ++++ src/wallet.cpp | 2 ++ src/wallet.h | 2 ++ 5 files changed, 14 insertions(+) diff --git a/src/main.cpp b/src/main.cpp index 4316d242f9f..059dd3db9e0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1149,14 +1149,18 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex) // This rule applies to all blocks whose timestamp is after March 15, 2012, 0:00 UTC. // On testnet it is enabled as of februari 20, 2012, 0:00 UTC. if (pindex->nTime > 1331769600 || (fTestNet && pindex->nTime > 1329696000)) + { BOOST_FOREACH(CTransaction& tx, vtx) { CTxIndex txindexOld; if (txdb.ReadTxIndex(tx.GetHash(), txindexOld)) + { BOOST_FOREACH(CDiskTxPos &pos, txindexOld.vSpent) if (pos.IsNull()) return false; + } } + } // P2SH didn't become active until Apr 1 2012 (Feb 15 on testnet) int64 nEvalSwitchTime = fTestNet ? 1329264000 : 1333238400; diff --git a/src/main.h b/src/main.h index e6f60a6a8db..b0f713e876e 100644 --- a/src/main.h +++ b/src/main.h @@ -572,9 +572,11 @@ public: // To limit dust spam, require MIN_TX_FEE/MIN_RELAY_TX_FEE if any output is less than 0.01 if (nMinFee < nBaseFee) + { BOOST_FOREACH(const CTxOut& txout, vout) if (txout.nValue < CENT) nMinFee = nBaseFee; + } // Raise the price as the block approaches full if (nBlockSize != 1 && nNewBlockSize >= MAX_BLOCK_SIZE_GEN/2) diff --git a/src/rpc.cpp b/src/rpc.cpp index b62da8ecdf0..bbfea33d765 100644 --- a/src/rpc.cpp +++ b/src/rpc.cpp @@ -685,8 +685,10 @@ Value getbalance(const Array& params, bool fHelp) list > listSent; wtx.GetAmounts(allGeneratedImmature, allGeneratedMature, listReceived, listSent, allFee, strSentAccount); if (wtx.GetDepthInMainChain() >= nMinDepth) + { BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listReceived) nBalance += r.second; + } BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listSent) nBalance -= r.second; nBalance -= allFee; @@ -1046,6 +1048,7 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe // Received if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth) + { BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, int64)& r, listReceived) { string account; @@ -1063,6 +1066,7 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe ret.push_back(entry); } } + } } void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret) diff --git a/src/wallet.cpp b/src/wallet.cpp index 9f7422d1fbc..3f51313e9bf 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -545,8 +545,10 @@ void CWalletTx::AddSupportingTransactions(CTxDB& txdb) vtxPrev.push_back(tx); if (nDepth < COPY_DEPTH) + { BOOST_FOREACH(const CTxIn& txin, tx.vin) vWorkQueue.push_back(txin.prevout.hash); + } } } } diff --git a/src/wallet.h b/src/wallet.h index 4387e1a01fd..bb9177b6849 100644 --- a/src/wallet.h +++ b/src/wallet.h @@ -499,8 +499,10 @@ public: return false; if (mapPrev.empty()) + { BOOST_FOREACH(const CMerkleTx& tx, vtxPrev) mapPrev[tx.GetHash()] = &tx; + } BOOST_FOREACH(const CTxIn& txin, ptx->vin) {