Browse Source

implement variable fee per kb

activeAddress
Ivan Socolsky 10 years ago
parent
commit
366638b2d4
  1. 2
      lib/model/txproposal.js
  2. 12
      lib/server.js
  3. 30
      test/integration/server.js

2
lib/model/txproposal.js

@ -37,6 +37,7 @@ TxProposal.create = function(opts) {
x.outputOrder = _.shuffle(_.range(2));
x.fee = null;
x.network = Bitcore.Address(x.toAddress).toObject().network;
x.feePerKb = opts.feePerKb;
return x;
};
@ -68,6 +69,7 @@ TxProposal.fromObj = function(obj) {
x.outputOrder = obj.outputOrder;
x.fee = obj.fee;
x.network = obj.network;
x.feePerKb = obj.feePerKb;
return x;
};

12
lib/server.js

@ -693,8 +693,6 @@ WalletService.prototype.getBalance = function(opts, cb) {
WalletService.prototype._selectTxInputs = function(txp, cb) {
var self = this;
Bitcore.Transaction.FEE_SECURITY_MARGIN = 1;
self._getUtxos(function(err, utxos) {
if (err) return cb(err);
@ -730,6 +728,7 @@ WalletService.prototype._selectTxInputs = function(txp, cb) {
if (!bitcoreError) {
txp.inputPaths = _.pluck(txp.inputs, 'path');
txp.fee = bitcoreTx.getFee();
$.checkState(txp.fee < 1e8, 'Fees are too high!');
return cb();
}
} catch (ex) {
@ -787,7 +786,8 @@ WalletService.prototype._canCreateTx = function(copayerId, cb) {
* @param {number} opts.amount - Amount to transfer in satoshi.
* @param {string} opts.message - A message to attach to this transaction.
* @param {string} opts.proposalSignature - S(toAddress|amount|message|payProUrl). Used by other copayers to verify the proposal.
* @param {string} opts.payProUrl - Options: Paypro URL for peers to verify TX
* @param {string} opts.feePerKb - Optional: Use an alternative fee per KB for this TX
* @param {string} opts.payProUrl - Optional: Paypro URL for peers to verify TX
* @returns {TxProposal} Transaction proposal.
*/
WalletService.prototype.createTx = function(opts, cb) {
@ -796,6 +796,10 @@ WalletService.prototype.createTx = function(opts, cb) {
if (!Utils.checkRequired(opts, ['toAddress', 'amount', 'proposalSignature']))
return cb(new ClientError('Required argument missing'));
var feePerKb = opts.feePerKb || 10000;
if (!_.contains([1000, 5000, 10000], feePerKb))
return cb(new ClientError('Invalid fee per KB value'));
self._runLocked(cb, function(cb) {
self.getWallet({}, function(err, wallet) {
if (err) return cb(err);
@ -827,7 +831,6 @@ WalletService.prototype.createTx = function(opts, cb) {
if (opts.amount < Bitcore.Transaction.DUST_AMOUNT)
return cb(new ClientError('DUSTAMOUNT', 'Amount below dust threshold'));
var changeAddress = wallet.createAddress(true);
var txp = Model.TxProposal.create({
@ -837,6 +840,7 @@ WalletService.prototype.createTx = function(opts, cb) {
amount: opts.amount,
message: opts.message,
proposalSignature: opts.proposalSignature,
feePerKb: feePerKb,
payProUrl: opts.payProUrl,
changeAddress: changeAddress,
requiredSignatures: wallet.m,

30
test/integration/server.js

@ -184,13 +184,15 @@ helpers.stubAddressActivity = function(activeAddresses) {
helpers.clientSign = WalletUtils.signTxp;
helpers.createProposalOpts = function(toAddress, amount, message, signingKey) {
helpers.createProposalOpts = function(toAddress, amount, message, signingKey, feePerKb) {
var opts = {
toAddress: toAddress,
amount: helpers.toSatoshi(amount),
message: message,
proposalSignature: null,
};
if (feePerKb) opts.feePerKb = feePerKb;
var hash = WalletUtils.getProposalHash(opts.toAddress, opts.amount, opts.message);
try {
opts.proposalSignature = WalletUtils.signMessage(hash, signingKey);
@ -1431,6 +1433,30 @@ describe('Wallet service', function() {
});
});
it('should be possible to use a smaller fee', function(done) {
helpers.stubUtxos(server, wallet, 1, function() {
var txOpts = helpers.createProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 0.99995, null, TestData.copayers[0].privKey_1H_0);
server.createTx(txOpts, function(err, tx) {
should.exist(err);
err.code.should.equal('INSUFFICIENTFUNDS');
var txOpts = helpers.createProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 0.99995, null, TestData.copayers[0].privKey_1H_0, 5000);
server.createTx(txOpts, function(err, tx) {
should.not.exist(err);
tx.fee.should.equal(5000);
var signatures = helpers.clientSign(tx, TestData.copayers[0].xPrivKey);
// Sign it to make sure Bitcore doesn't complain about the fees
server.signTx({
txProposalId: tx.id,
signatures: signatures,
}, function(err) {
should.not.exist(err);
done();
});
});
});
});
});
it('should fail to create tx for dust amount', function(done) {
helpers.stubUtxos(server, wallet, [1], function() {
var txOpts = helpers.createProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 0.00000001, null, TestData.copayers[0].privKey_1H_0);
@ -1445,7 +1471,7 @@ describe('Wallet service', function() {
it('should fail to create tx that would return change for dust amount', function(done) {
helpers.stubUtxos(server, wallet, [1], function() {
var fee = Bitcore.Transaction.FEE_PER_KB / 1e8;
var fee = 10000 / 1e8;
var change = 0.00000001;
var amount = 1 - fee - change;

Loading…
Cancel
Save