Merge pull request #1041 from gavinandresen/listtransactionsfix

Bug fix listtransactions from/count handling.
This commit is contained in:
Gavin Andresen 2012-04-12 12:20:51 -07:00
commit b7dc02381f

View File

@ -1281,14 +1281,21 @@ Value listtransactions(const Array& params, bool fHelp)
if (params.size() > 2) if (params.size() > 2)
nFrom = params[2].get_int(); nFrom = params[2].get_int();
if (nCount < 0)
throw JSONRPCError(-8, "Negative count");
if (nFrom < 0)
throw JSONRPCError(-8, "Negative from");
Array ret; Array ret;
CWalletDB walletdb(pwalletMain->strWalletFile); 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<CWalletTx*, CAccountingEntry*> TxPair; typedef pair<CWalletTx*, CAccountingEntry*> TxPair;
typedef multimap<int64, TxPair > TxItems; typedef multimap<int64, TxPair > TxItems;
TxItems txByTime; 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<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
{ {
CWalletTx* wtx = &((*it).second); CWalletTx* wtx = &((*it).second);
@ -1301,10 +1308,8 @@ Value listtransactions(const Array& params, bool fHelp)
txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry))); txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry)));
} }
// Now: iterate backwards until we have nCount items to return: // iterate backwards until we have nCount items to return:
TxItems::reverse_iterator it = txByTime.rbegin(); for (TxItems::reverse_iterator it = txByTime.rbegin(); it != txByTime.rend(); ++it)
if (txByTime.size() > nFrom) std::advance(it, nFrom);
for (; it != txByTime.rend(); ++it)
{ {
CWalletTx *const pwtx = (*it).second.first; CWalletTx *const pwtx = (*it).second.first;
if (pwtx != 0) if (pwtx != 0)
@ -1313,18 +1318,21 @@ Value listtransactions(const Array& params, bool fHelp)
if (pacentry != 0) if (pacentry != 0)
AcentryToJSON(*pacentry, strAccount, ret); 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 (nFrom > ret.size()) nFrom = ret.size();
if (ret.size() > nCount) if (nFrom+nCount > ret.size()) nCount = ret.size()-nFrom;
{ Array::iterator first = ret.begin();
Array::iterator last = ret.begin(); std::advance(first, nFrom);
std::advance(last, nCount); Array::iterator last = ret.begin();
ret.erase(last, ret.end()); std::advance(last, nFrom+nCount);
}
std::reverse(ret.begin(), ret.end()); // oldest to newest 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; return ret;
} }