diff --git a/lib/bcoin/tx.js b/lib/bcoin/tx.js index 5f1ddb38..1f74dc7b 100644 --- a/lib/bcoin/tx.js +++ b/lib/bcoin/tx.js @@ -655,73 +655,69 @@ TX.prototype.maxSize = function maxSize() { return size; }; -TX.prototype.utxos = function utxos(unspent) { +TX.prototype.getUnspent = function getUnspent(unspent) { + var tx = this.clone(); + // NOTE: tx should be prefilled with all outputs - var cost = this.funds('out'); + var cost = tx.funds('out'); // Use initial fee for starters var fee = 1; // total = cost + fee - var total = cost.add(new bn(TX.fee)); + var total = cost.addn(TX.fee); - var inputs = this.inputs.slice(); - var utxos = []; + var inputs = []; var lastAdded = 0; var byteSize, addFee, change; - function addInput(unspent, i) { + function addInput(unspent) { // Add new inputs until TX will have enough funds to cover both // minimum post cost and fee - var index = this._input(unspent); - utxos.push(this.inputs[index]); + var index = tx._input(unspent); + inputs.push(tx.inputs[index]); lastAdded++; - return this.funds('in').cmp(total) < 0; + return tx.funds('in').cmp(total) < 0; } // Transfer `total` funds maximum // var unspent = wallet.unspent(); - unspent.every(addInput, this); + unspent.every(addInput); // Add dummy output (for `change`) to calculate maximum TX size - this.output({ address: null, value: new bn(0) }); + tx.output({ address: null, value: new bn(0) }); // Change fee value if it is more than 1024 bytes // (10000 satoshi for every 1024 bytes) do { // Calculate maximum possible size after signing - byteSize = this.maxSize(); + byteSize = tx.maxSize(); addFee = Math.ceil(byteSize / 1024) - fee; - total.iadd(new bn(addFee * TX.fee)); + total.iaddn(addFee * TX.fee); fee += addFee; // Failed to get enough funds, add more inputs - if (this.funds('in').cmp(total) < 0) - unspent.slice(lastAdded).every(addInput, this); - } while (this.funds('in').cmp(total) < 0 && lastAdded < unspent.length); + if (tx.funds('in').cmp(total) < 0) + unspent.slice(lastAdded).every(addInput); + } while (tx.funds('in').cmp(total) < 0 && lastAdded < unspent.length); // Still failing to get enough funds - if (this.funds('in').cmp(total) < 0) { - this.inputs = inputs; + if (tx.funds('in').cmp(total) < 0) { this.total = total; - this.outputs.pop(); return null; } // How much money is left after sending outputs - change = this.funds('in').sub(total); + change = tx.funds('in').sub(total); - // Clear the tx of everything we added. - this.inputs = inputs; this.total = total; - this.outputs.pop(); - // Return necessary utxos and change. + // Return necessary inputs and change. return { - utxos: utxos, + inputs: inputs, change: change, cost: cost, fee: total.sub(cost), @@ -730,22 +726,25 @@ TX.prototype.utxos = function utxos(unspent) { }; TX.prototype.fillUnspent = function fillUnspent(unspent, changeAddress) { - var result = unspent.utxos ? unspent : this.utxos(unspent); - - this.changeAddress = changeAddress - || this.changeAddress - || utxos[0].output.addr; + var result = unspent.cost ? unspent : this.getUnspent(unspent); if (!result) return result; - result.utxos.forEach(function(input) { + this.changeAddress = changeAddress + || this.changeAddress + || result.inputs[0].output.addr; + + result.inputs.forEach(function(input) { this.input(input); }, this); if (result.change.cmpn(TX.dust) < 0) { // Do nothing. Change is added to fee. - assert(this.getFee().cmp(result.fee.add(result.change)) === 0); + assert.equal( + this.getFee().toNumber(), + result.fee.add(result.change).toNumber() + ); this.changeOutput = null; } else { if (!this.changeAddress)