Skip to content

Commit 001d7ba

Browse files
fanquakePastaPastaPasta
authored andcommitted
Merge bitcoin#25464: rpc: Reduce Univalue push_backV peak memory usage in listtransactions
fa8a1c0 rpc: Fix Univalue push_backV OOM in listtransactions (MacroFake) Pull request description: Related to, but not intended as a fix for bitcoin#25229. Currently the RPC will have the same data stored thrice: * `UniValue ret` (memory filled by `ListTransactions`) * `std::vector<UniValue> vec` (constructed by calling `push_backV`) * `UniValue result` (the actual result, memory filled by `push_backV`) Fix this by filling the memory only once: * `std::vector<UniValue> ret` (memory filled by `ListTransactions`) * Pass iterators to `push_backV` instead of creating a full copy * Move memory into `UniValue result` instead of copying it ACKs for top commit: shaavan: Code Review ACK fa8a1c0 Tree-SHA512: 1c3ca40fc8497134a4141195160e4aa9fe72b3c00c5998c972b58ad0eb498ebea05013f9105bb80e7264c9db1d0e7a2032396a8a4af1f326d831fbee20f32ea3
1 parent 1cd9ebd commit 001d7ba

File tree

2 files changed

+16
-6
lines changed

2 files changed

+16
-6
lines changed

src/univalue/include/univalue.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,8 @@ class UniValue {
111111
return push_back(tmpVal);
112112
}
113113
bool push_backV(const std::vector<UniValue>& vec);
114+
template <class It>
115+
bool push_backV(It first, It last);
114116

115117
void __pushKV(const std::string& key, const UniValue& val);
116118
bool pushKV(const std::string& key, const UniValue& val);
@@ -180,6 +182,14 @@ class UniValue {
180182
friend const UniValue& find_value( const UniValue& obj, const std::string& name);
181183
};
182184

185+
template <class It>
186+
bool UniValue::push_backV(It first, It last)
187+
{
188+
if (typ != VARR) return false;
189+
values.insert(values.end(), first, last);
190+
return true;
191+
}
192+
183193
enum jtokentype {
184194
JTOK_ERR = -1,
185195
JTOK_NONE = 0, // eof

src/wallet/rpc/transactions.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -328,11 +328,12 @@ static void MaybePushAddress(UniValue & entry, const CTxDestination &dest)
328328
* @param wtx The wallet transaction.
329329
* @param nMinDepth The minimum confirmation depth.
330330
* @param fLong Whether to include the JSON version of the transaction.
331-
* @param ret The UniValue into which the result is stored.
331+
* @param ret The vector into which the result is stored.
332332
* @param filter_ismine The "is mine" filter flags.
333333
* @param filter_label Optional label string to filter incoming transactions.
334334
*/
335-
static void ListTransactions(const CWallet& wallet, const CWalletTx& wtx, int nMinDepth, bool fLong, UniValue& ret, const isminefilter& filter_ismine, const std::string* filter_label) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
335+
template <class Vec>
336+
static void ListTransactions(const CWallet& wallet, const CWalletTx& wtx, int nMinDepth, bool fLong, Vec& ret, const isminefilter& filter_ismine, const std::string* filter_label) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
336337
{
337338
CAmount nFee;
338339
std::list<COutputEntry> listReceived;
@@ -519,8 +520,7 @@ RPCHelpMan listtransactions()
519520
if (nFrom < 0)
520521
throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative from");
521522

522-
UniValue ret(UniValue::VARR);
523-
523+
std::vector<UniValue> ret;
524524
{
525525
LOCK(pwallet->cs_wallet);
526526

@@ -542,9 +542,9 @@ RPCHelpMan listtransactions()
542542
if ((nFrom + nCount) > (int)ret.size())
543543
nCount = ret.size() - nFrom;
544544

545-
const std::vector<UniValue>& txs = ret.getValues();
545+
auto txs_rev_it{std::make_move_iterator(ret.rend())};
546546
UniValue result{UniValue::VARR};
547-
result.push_backV({ txs.rend() - nFrom - nCount, txs.rend() - nFrom }); // Return oldest to newest
547+
result.push_backV(txs_rev_it - nFrom - nCount, txs_rev_it - nFrom); // Return oldest to newest
548548
return result;
549549
},
550550
};

0 commit comments

Comments
 (0)