From 7ed3a340d4a39ec3658f2358362cb35843e71f36 Mon Sep 17 00:00:00 2001 From: Nodari Chkuaselidze Date: Tue, 17 Jun 2025 16:10:20 +0400 Subject: [PATCH] txdb: fix limit on value coin selector. --- lib/wallet/txdb.js | 11 ++++++++++- test/wallet-coinselection-test.js | 17 +++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/lib/wallet/txdb.js b/lib/wallet/txdb.js index c9b60c0a..9f87c607 100644 --- a/lib/wallet/txdb.js +++ b/lib/wallet/txdb.js @@ -3821,7 +3821,7 @@ class TXDB { * @param {Object} [options] * @param {Number} [options.minValue=0] * @param {Number} [options.maxValue=MAX_MONEY] - * @param {Number} [options.limit=-1] + * @param {Number?} [options.limit] * @param {Boolean} [options.reverse=false] * @param {Boolean} [options.inclusive=true] * @returns {AsyncGenerator} @@ -3872,6 +3872,7 @@ class TXDB { iterOpts[lesser] = max; const iter = this.bucket.iterator(iterOpts); + let items = 0; for await (const key of iter.keysAsync()) { const decoded = prefix.decode(key); @@ -3881,6 +3882,7 @@ class TXDB { assert(credit); yield credit; + items++; } // now process unconfirmed. @@ -3897,6 +3899,13 @@ class TXDB { iterOpts[greater] = min; iterOpts[lesser] = max; + if (limit != null && limit > 0) { + if (items >= limit) + return; + + iterOpts.limit = limit - items; + } + const ucIter = this.bucket.iterator(iterOpts); for await (const key of ucIter.keysAsync()) { diff --git a/test/wallet-coinselection-test.js b/test/wallet-coinselection-test.js index f4cf7783..2a7a9e6c 100644 --- a/test/wallet-coinselection-test.js +++ b/test/wallet-coinselection-test.js @@ -102,6 +102,17 @@ describe('Wallet Coin Selection', function() { let isSorted, getCredits; const sumCredits = credits => credits.reduce((acc, c) => acc + c.coin.value, 0); + const checkWithLimits = async (credits, wallet, acct) => { + for (let i = 1; i < credits.length; i++) { + const creditsLimit = await getCredits(wallet, acct, { + limit: i + }); + assert.strictEqual(creditsLimit.length, i); + assert(isSorted(creditsLimit), 'Credits not sorted.'); + assert.deepStrictEqual(creditsLimit, credits.slice(0, i)); + assert(sumCredits(creditsLimit) === sumCredits(credits.slice(0, i))); + } + }; before(() => { switch (indexType) { @@ -631,15 +642,21 @@ describe('Wallet Coin Selection', function() { assert(isSorted(credits0), 'Credits not sorted.'); assert(sumCredits(credits0) === sum0); + await checkWithLimits(credits0, wallet); + const credits1 = await getCredits(wallet, 1); assert.strictEqual(credits1.length, 4); assert(isSorted(credits1), 'Credits not sorted.'); assert(sumCredits(credits1) === sum1); + await checkWithLimits(credits1, wallet, 1); + const both = await getCredits(wallet, -1); assert.strictEqual(both.length, 8); assert(isSorted(both), 'Credits not sorted.'); assert(sumCredits(both) === sum0 + sum1); + + await checkWithLimits(both, wallet, -1); }); }); }