diff --git a/lib/primitives/mtx.js b/lib/primitives/mtx.js index 5d96782d..d20a507c 100644 --- a/lib/primitives/mtx.js +++ b/lib/primitives/mtx.js @@ -1592,10 +1592,13 @@ class CoinSelector { this.maxFee = -1; this.round = false; this.changeAddress = null; + this.inputs = new Map(); // Needed for size estimation. this.estimate = null; + this.injectInputs(); + if (options) this.fromOptions(options); } @@ -1687,9 +1690,35 @@ class CoinSelector { this.estimate = options.estimate; } + if (options.inputs) { + assert(Array.isArray(options.inputs)); + for (let i = 0; i < options.inputs.length; i++) { + const prevout = options.inputs[i]; + assert(prevout && typeof prevout === 'object'); + const {hash, index} = prevout; + assert(typeof hash === 'string'); + assert(typeof index === 'number'); + this.inputs.set(Outpoint.toKey(hash, index), i); + } + } + return this; } + /** + * Attempt to inject existing inputs. + * @private + */ + + injectInputs() { + if (this.tx.inputs.length > 0) { + for (let i = 0; i < this.tx.inputs.length; i++) { + const {prevout} = this.tx.inputs[i]; + this.inputs.set(prevout.toKey(), i); + } + } + } + /** * Initialize the selector with coins to select from. * @param {Coin[]} coins @@ -1749,6 +1778,9 @@ class CoinSelector { */ isSpendable(coin) { + if (this.tx.view.hasEntry(coin)) + return false; + if (this.height === -1) return true; @@ -1799,6 +1831,33 @@ class CoinSelector { */ fund() { + // Ensure all preferred inputs first. + if (this.inputs.size > 0) { + const coins = []; + + for (let i = 0; i < this.inputs.size; i++) + coins.push(null); + + for (const coin of this.coins) { + const {hash, index} = coin; + const key = Outpoint.toKey(hash, index); + const i = this.inputs.get(key); + + if (i != null) { + coins[i] = coin; + this.inputs.delete(key); + } + } + + if (this.inputs.size > 0) + throw new Error('Could not resolve preferred inputs.'); + + for (const coin of coins) { + this.tx.addCoin(coin); + this.chosen.push(coin); + } + } + while (this.index < this.coins.length) { const coin = this.coins[this.index++];