hard fee calculation.

This commit is contained in:
Christopher Jeffrey 2016-01-12 04:08:25 -08:00
parent 3c8442b1bb
commit 7b27f5dc9b

View File

@ -41,6 +41,10 @@ function TX(data, block) {
this._lock = this.lock; this._lock = this.lock;
this._fee = !(data instanceof bcoin.tx)
? data.fee
: data._fee;
if (data.inputs) { if (data.inputs) {
data.inputs.forEach(function(input) { data.inputs.forEach(function(input) {
this.input(input, null); this.input(input, null);
@ -781,7 +785,7 @@ TX.prototype.maxSize = function maxSize() {
return total; return total;
}; };
TX.prototype.getUnspent = function getUnspent(unspent) { TX.prototype.getUnspent = function getUnspent(unspent, hardFee) {
var tx = this.clone(); var tx = this.clone();
var cost = tx.funds('out'); var cost = tx.funds('out');
var fee = 1; var fee = 1;
@ -790,48 +794,59 @@ TX.prototype.getUnspent = function getUnspent(unspent) {
var lastAdded = 0; var lastAdded = 0;
var size, addFee, change; var size, addFee, change;
if (!hardFee)
hardFee = this._fee;
if (hardFee) {
total = cost.add(hardFee);
this._fee = hardFee;
}
function addInput(unspent) { function addInput(unspent) {
// Add new inputs until TX will have enough funds to cover both // Add new inputs until TX will have enough
// minimum post cost and fee // funds to cover both minimum post cost
// and fee.
var index = tx._input(unspent); var index = tx._input(unspent);
inputs.push(tx.inputs[index]); inputs.push(tx.inputs[index]);
lastAdded++; lastAdded++;
return tx.funds('in').cmp(total) < 0; return tx.funds('in').cmp(total) < 0;
} }
// Transfer `total` funds maximum // Transfer `total` funds maximum.
// var unspent = wallet.unspent();
unspent.every(addInput); unspent.every(addInput);
// Add dummy output (for `change`) to calculate maximum TX size if (!hardFee) {
tx.output({ // Add dummy output (for `change`) to
script: [], // calculate maximum TX size.
value: new bn(0) tx.output({
}); script: [],
value: new bn(0)
});
// Change fee value if it is more than 1024 bytes // Change fee value if it is more than 1024
// (10000 satoshi for every 1024 bytes) // bytes (10000 satoshi for every 1024 bytes).
do { do {
// Calculate maximum possible size after signing // Calculate max possible size after signing.
size = tx.maxSize(); size = tx.maxSize();
addFee = Math.ceil(size / 1024) - fee; addFee = Math.ceil(size / 1024) - fee;
total.iaddn(addFee * constants.tx.fee); total.iaddn(addFee * constants.tx.fee);
fee += addFee; fee += addFee;
// Failed to get enough funds, add more inputs // Failed to get enough funds, add more inputs.
if (tx.funds('in').cmp(total) < 0) if (tx.funds('in').cmp(total) < 0)
unspent.slice(lastAdded).every(addInput); unspent.slice(lastAdded).every(addInput);
} while (tx.funds('in').cmp(total) < 0 && lastAdded < unspent.length); } while (tx.funds('in').cmp(total) < 0 && lastAdded < unspent.length);
}
// Expose `total` // Expose `total`. Useful for error messages.
this.total = total; this.total = total;
// Still failing to get enough funds // Still failing to get enough funds.
if (tx.funds('in').cmp(total) < 0) if (tx.funds('in').cmp(total) < 0)
return null; return null;
// How much money is left after sending outputs // How much money is left after filling outputs.
change = tx.funds('in').sub(total); change = tx.funds('in').sub(total);
// Return necessary inputs and change. // Return necessary inputs and change.
@ -844,8 +859,8 @@ TX.prototype.getUnspent = function getUnspent(unspent) {
}; };
}; };
TX.prototype.fillUnspent = function fillUnspent(unspent, changeAddress) { TX.prototype.fillUnspent = function fillUnspent(unspent, changeAddress, fee) {
var result = unspent.cost ? unspent : this.getUnspent(unspent); var result = this.getUnspent(unspent, fee);
if (!result) if (!result)
return result; return result;
@ -884,6 +899,9 @@ TX.prototype._recalculateFee = function recalculateFee() {
var output = this.changeOutput; var output = this.changeOutput;
var size, real, fee; var size, real, fee;
if (this._fee)
return;
if (!output) { if (!output) {
this.output({ this.output({
address: this.changeAddress, address: this.changeAddress,