Browse Source

Merge pull request #1271 from isocolsky/fix/fee_estimation

Fix/fee estimation
patch-2
Matias Alejo Garcia 10 years ago
parent
commit
a4ac3f50d3
  1. 27
      lib/transaction/transaction.js
  2. 20
      test/transaction/transaction.js

27
lib/transaction/transaction.js

@ -205,7 +205,7 @@ Transaction.prototype.getSerializationError = function(opts) {
unspentError = this._hasFeeError(opts, unspent); unspentError = this._hasFeeError(opts, unspent);
} }
return unspentError || return unspentError ||
this._hasDustOutputs(opts) || this._hasDustOutputs(opts) ||
this._isMissingSignatures(opts); this._isMissingSignatures(opts);
}; };
@ -394,7 +394,7 @@ Transaction.prototype._checkConsistency = function() {
$.checkState(this._changeScript); $.checkState(this._changeScript);
$.checkState(this.outputs[this._changeIndex]); $.checkState(this.outputs[this._changeIndex]);
$.checkState(this.outputs[this._changeIndex].script.toString() === $.checkState(this.outputs[this._changeIndex].script.toString() ===
this._changeScript.toString()); this._changeScript.toString());
} }
// TODO: add other checks // TODO: add other checks
}; };
@ -634,6 +634,21 @@ Transaction.prototype.fee = function(amount) {
return this; return this;
}; };
/**
* Manually set the fee per KB for this transaction. Beware that this resets all the signatures
* for inputs (in further versions, SIGHASH_SINGLE or SIGHASH_NONE signatures will not
* be reset).
*
* @param {number} amount satoshis per KB to be sent
* @return {Transaction} this, for chaining
*/
Transaction.prototype.feePerKb = function(amount) {
$.checkArgument(_.isNumber(amount), 'amount must be a number');
this._feePerKb = amount;
this._updateChangeOutput();
return this;
};
/* Output management */ /* Output management */
/** /**
@ -831,7 +846,7 @@ Transaction.prototype.getFee = function() {
Transaction.prototype._estimateFee = function() { Transaction.prototype._estimateFee = function() {
var estimatedSize = this._estimateSize(); var estimatedSize = this._estimateSize();
var available = this._getUnspentValue(); var available = this._getUnspentValue();
return Transaction._estimateFee(estimatedSize, available); return Transaction._estimateFee(estimatedSize, available, this._feePerKb);
}; };
Transaction.prototype._getUnspentValue = function() { Transaction.prototype._getUnspentValue = function() {
@ -844,12 +859,12 @@ Transaction.prototype._clearSignatures = function() {
}); });
}; };
Transaction._estimateFee = function(size, amountAvailable) { Transaction._estimateFee = function(size, amountAvailable, feePerKb) {
var fee = Math.ceil(size / Transaction.FEE_PER_KB); var fee = Math.ceil(size / 1000) * (feePerKb || Transaction.FEE_PER_KB);
if (amountAvailable > fee) { if (amountAvailable > fee) {
size += Transaction.CHANGE_OUTPUT_MAX_SIZE; size += Transaction.CHANGE_OUTPUT_MAX_SIZE;
} }
return Math.ceil(size / 1000) * Transaction.FEE_PER_KB; return Math.ceil(size / 1000) * (feePerKb || Transaction.FEE_PER_KB);
}; };
Transaction.prototype._estimateSize = function() { Transaction.prototype._estimateSize = function() {

20
test/transaction/transaction.js

@ -257,6 +257,22 @@ describe('Transaction', function() {
transaction.outputs.length.should.equal(2); transaction.outputs.length.should.equal(2);
transaction.outputs[1].satoshis.should.equal(10000); transaction.outputs[1].satoshis.should.equal(10000);
}); });
it('fee per kb can be set up manually', function() {
var inputs = _.map(_.range(10), function(i) {
var utxo = _.clone(simpleUtxoWith100000Satoshis);
utxo.outputIndex = i;
return utxo;
});
var transaction = new Transaction()
.from(inputs)
.to(toAddress, 950000)
.feePerKb(8000)
.change(changeAddress)
.sign(privateKey);
transaction._estimateSize().should.be.within(1000, 1999);
transaction.outputs.length.should.equal(2);
transaction.outputs[1].satoshis.should.equal(34000);
});
it('if satoshis are invalid', function() { it('if satoshis are invalid', function() {
var transaction = new Transaction() var transaction = new Transaction()
.from(simpleUtxoWith100000Satoshis) .from(simpleUtxoWith100000Satoshis)
@ -406,7 +422,9 @@ describe('Transaction', function() {
.fee(10000000); .fee(10000000);
expect(function() { expect(function() {
return transaction.serialize({disableMoreOutputThanInput: true}); return transaction.serialize({
disableMoreOutputThanInput: true
});
}).to.throw(errors.Transaction.FeeError.TooLarge); }).to.throw(errors.Transaction.FeeError.TooLarge);
}); });
describe('skipping checks', function() { describe('skipping checks', function() {

Loading…
Cancel
Save