Skip to content

Commit 3c94eb3

Browse files
committed
wallet: add by value indexes for credits.
1 parent d6eafc4 commit 3c94eb3

File tree

3 files changed

+82
-39
lines changed

3 files changed

+82
-39
lines changed

lib/wallet/txdb.js

+52
Original file line numberDiff line numberDiff line change
@@ -3763,6 +3763,58 @@ class TXDB {
37633763
return coins;
37643764
}
37653765

3766+
/**
3767+
* Get credits iterator sorted by value.
3768+
* @param {Number} acct
3769+
* @param {Object} [options]
3770+
* @param {Number} [options.minValue=0]
3771+
* @param {Number} [options.maxValue=MAX_MONEY]
3772+
* @param {Number} [options.limit=-1]
3773+
* @param {Boolean} [options.reverse=false]
3774+
* @returns {AsyncGenerator<Credit>}
3775+
*/
3776+
3777+
async *getAccountCreditIterByValue(acct, options = {}) {
3778+
assert(typeof acct === 'number');
3779+
assert(acct >= 0);
3780+
assert(options && typeof options === 'object');
3781+
3782+
let minValue = 0;
3783+
let maxValue = consensus.MAX_MONEY;
3784+
3785+
if (options.minValue != null) {
3786+
assert(typeof options.minValue === 'number');
3787+
minValue = options.minValue;
3788+
}
3789+
3790+
if (options.maxValue != null) {
3791+
assert(typeof options.maxValue === 'number');
3792+
maxValue = options.maxValue;
3793+
}
3794+
3795+
assert(minValue <= maxValue);
3796+
3797+
const min = layout.SV.min(acct, minValue);
3798+
const max = layout.SV.max(acct, maxValue);
3799+
3800+
const iter = this.bucket.iterator({
3801+
gte: min,
3802+
lte: max,
3803+
limit: options.limit,
3804+
reverse: options.reverse,
3805+
keys: true,
3806+
values: false
3807+
});
3808+
3809+
for await (const {key} of iter) {
3810+
const [,, hash, index] = layout.SV.decode(key);
3811+
const credit = await this.getCredit(hash, index);
3812+
3813+
assert(credit);
3814+
yield credit;
3815+
}
3816+
}
3817+
37663818
/**
37673819
* Get a coin viewpoint.
37683820
* @param {TX} tx

test/util/primitives.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ const Covenant = require('../../lib/primitives/covenant');
1414
/** @typedef {import('../../lib/types').Hash} Hash */
1515

1616
exports.coinbaseInput = () => {
17-
return Input.fromOutpoint(new Outpoint(Buffer.alloc(32), 0));
17+
return Input.fromOutpoint(new Outpoint());
1818
};
1919

2020
exports.dummyInput = () => {

test/wallet-coinselection-test.js

+29-38
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ const {coinbaseInput, dummyInput} = primutils;
1414
/** @typedef {import('../lib/wallet/wallet')} Wallet */
1515
/** @typedef {import('../lib/covenants/rules').types} covenantTypes */
1616
/** @typedef {import('../lib/primitives/output')} Output */
17+
/** @typedef {import('../lib/primitives/tx')} TX */
1718

1819
// Use main instead of regtest because (deprecated)
1920
// CoinSelector.MAX_FEE was network agnostic
@@ -238,42 +239,6 @@ describe('Wallet Coin Selection', function() {
238239
}
239240
});
240241

241-
it('should index disconnect tx output (spent)', async () => {
242-
await fundWallet(wallet, TX_OPTIONS, false);
243-
const currentBlock = curBlock(wdb);
244-
245-
const spendAll = await wallet.createTX({
246-
hardFee: 0,
247-
outputs: [{ value: TOTAL_FUNDS, address: primutils.randomP2PKAddress() }]
248-
});
249-
250-
await wdb.addTX(spendAll.toTX());
251-
252-
let iter = wallet.getAccountCreditIterByValue(0);
253-
let creditsByValue = await collectIter(iter);
254-
assert.strictEqual(creditsByValue.length, TOTAL_COINS);
255-
assert(isSortedByValue(creditsByValue), 'Credits not sorted.');
256-
257-
for (const credit of creditsByValue) {
258-
assert.strictEqual(credit.coin.height, currentBlock.height);
259-
assert.strictEqual(credit.spent, true);
260-
}
261-
262-
// disconnect last block.
263-
await wdb.removeBlock(currentBlock);
264-
265-
// Only thing that must change is the HEIGHT.
266-
iter = wallet.getAccountCreditIterByValue(0);
267-
creditsByValue = await collectIter(iter);
268-
assert.strictEqual(creditsByValue.length, TOTAL_COINS);
269-
assert(isSortedByValue(creditsByValue), 'Credits not sorted.');
270-
271-
for (const credit of creditsByValue) {
272-
assert.strictEqual(credit.coin.height, -1);
273-
assert.strictEqual(credit.spent, true);
274-
}
275-
});
276-
277242
it('should index disconnect tx input', async () => {
278243
await fundWallet(wallet, TX_OPTIONS, false);
279244
const createCoinHeight = curBlock(wdb).height;
@@ -361,6 +326,32 @@ describe('Wallet Coin Selection', function() {
361326
creditsByValue = await collectIter(iter);
362327
assert.strictEqual(creditsByValue.length, 0);
363328
});
329+
330+
it('should index erase (block) tx output', async () => {
331+
const txOptions = [...TX_OPTIONS];
332+
txOptions[0].coinbase = true;
333+
const txs = await fundWallet(wallet, txOptions, false);
334+
assert(txs[0].isCoinbase());
335+
assert.strictEqual(txs.length, 1);
336+
337+
const currentBlock = curBlock(wdb);
338+
339+
let iter = wallet.getAccountCreditIterByValue(0);
340+
let creditsByValue = await collectIter(iter);
341+
assert.strictEqual(creditsByValue.length, TOTAL_COINS);
342+
assert(isSortedByValue(creditsByValue), 'Credits not sorted.');
343+
344+
for (const credit of creditsByValue) {
345+
assert.strictEqual(credit.coin.height, currentBlock.height);
346+
assert.strictEqual(credit.spent, false);
347+
}
348+
349+
await wdb.removeBlock(currentBlock);
350+
351+
iter = wallet.getAccountCreditIterByValue(0);
352+
creditsByValue = await collectIter(iter);
353+
assert.strictEqual(creditsByValue.length, 0);
354+
});
364355
});
365356

366357
describe('Selection types', function() {
@@ -437,7 +428,7 @@ describe('Wallet Coin Selection', function() {
437428
});
438429
});
439430

440-
describe('Fees', function () {
431+
describe('Fees', function() {
441432
before(beforeFn);
442433
after(afterFn);
443434

@@ -613,7 +604,7 @@ async function createInboundTXs(wallet, outputInfos, txPerOutput = true) {
613604
if (info.coinbase && !hadCoinbase) {
614605
hadCoinbase = true;
615606
mtx.addInput(coinbaseInput());
616-
} else {
607+
} else if (!hadCoinbase) {
617608
mtx.addInput(dummyInput());
618609
}
619610

0 commit comments

Comments
 (0)