From 7b27f5dc9bf60c5ae8d04fec184d321bdd75b139 Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Tue, 12 Jan 2016 04:08:25 -0800 Subject: [PATCH] hard fee calculation. --- lib/bcoin/tx.js | 72 ++++++++++++++++++++++++++++++------------------- 1 file changed, 45 insertions(+), 27 deletions(-) diff --git a/lib/bcoin/tx.js b/lib/bcoin/tx.js index 44e7ed81..32df2726 100644 --- a/lib/bcoin/tx.js +++ b/lib/bcoin/tx.js @@ -41,6 +41,10 @@ function TX(data, block) { this._lock = this.lock; + this._fee = !(data instanceof bcoin.tx) + ? data.fee + : data._fee; + if (data.inputs) { data.inputs.forEach(function(input) { this.input(input, null); @@ -781,7 +785,7 @@ TX.prototype.maxSize = function maxSize() { return total; }; -TX.prototype.getUnspent = function getUnspent(unspent) { +TX.prototype.getUnspent = function getUnspent(unspent, hardFee) { var tx = this.clone(); var cost = tx.funds('out'); var fee = 1; @@ -790,48 +794,59 @@ TX.prototype.getUnspent = function getUnspent(unspent) { var lastAdded = 0; var size, addFee, change; + if (!hardFee) + hardFee = this._fee; + + if (hardFee) { + total = cost.add(hardFee); + this._fee = hardFee; + } + function addInput(unspent) { - // Add new inputs until TX will have enough funds to cover both - // minimum post cost and fee + // Add new inputs until TX will have enough + // funds to cover both minimum post cost + // and fee. var index = tx._input(unspent); inputs.push(tx.inputs[index]); lastAdded++; return tx.funds('in').cmp(total) < 0; } - // Transfer `total` funds maximum - // var unspent = wallet.unspent(); + // Transfer `total` funds maximum. unspent.every(addInput); - // Add dummy output (for `change`) to calculate maximum TX size - tx.output({ - script: [], - value: new bn(0) - }); + if (!hardFee) { + // Add dummy output (for `change`) to + // calculate maximum TX size. + tx.output({ + script: [], + 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 - size = tx.maxSize(); + // Change fee value if it is more than 1024 + // bytes (10000 satoshi for every 1024 bytes). + do { + // Calculate max possible size after signing. + size = tx.maxSize(); - addFee = Math.ceil(size / 1024) - fee; - total.iaddn(addFee * constants.tx.fee); - fee += addFee; + addFee = Math.ceil(size / 1024) - fee; + total.iaddn(addFee * constants.tx.fee); + fee += addFee; - // Failed to get enough funds, add more inputs - if (tx.funds('in').cmp(total) < 0) - unspent.slice(lastAdded).every(addInput); - } while (tx.funds('in').cmp(total) < 0 && lastAdded < unspent.length); + // Failed to get enough funds, add more inputs. + if (tx.funds('in').cmp(total) < 0) + unspent.slice(lastAdded).every(addInput); + } while (tx.funds('in').cmp(total) < 0 && lastAdded < unspent.length); + } - // Expose `total` + // Expose `total`. Useful for error messages. this.total = total; - // Still failing to get enough funds + // Still failing to get enough funds. if (tx.funds('in').cmp(total) < 0) return null; - // How much money is left after sending outputs + // How much money is left after filling outputs. change = tx.funds('in').sub(total); // Return necessary inputs and change. @@ -844,8 +859,8 @@ TX.prototype.getUnspent = function getUnspent(unspent) { }; }; -TX.prototype.fillUnspent = function fillUnspent(unspent, changeAddress) { - var result = unspent.cost ? unspent : this.getUnspent(unspent); +TX.prototype.fillUnspent = function fillUnspent(unspent, changeAddress, fee) { + var result = this.getUnspent(unspent, fee); if (!result) return result; @@ -884,6 +899,9 @@ TX.prototype._recalculateFee = function recalculateFee() { var output = this.changeOutput; var size, real, fee; + if (this._fee) + return; + if (!output) { this.output({ address: this.changeAddress,