Merge pull request #326 from isocolsky/fee_level_def

Redefine fee levels
This commit is contained in:
Matias Alejo Garcia 2015-08-14 10:29:32 -03:00
commit 3bcabaf9e4
2 changed files with 50 additions and 35 deletions

View File

@ -53,20 +53,35 @@ function WalletService() {
// Time after which a Tx proposal can be erased by any copayer. in seconds // Time after which a Tx proposal can be erased by any copayer. in seconds
WalletService.deleteLockTime = 24 * 3600; WalletService.DELETE_LOCKTIME = 24 * 3600;
// Allowed consecutive txp rejections before backoff is applied. // Allowed consecutive txp rejections before backoff is applied.
WalletService.backoffOffset = 3; WalletService.BACKOFF_OFFSET = 3;
// Time a copayer need to wait to create a new TX after her tx previous proposal we rejected. (incremental). in Minutes. // Time a copayer need to wait to create a new TX after her tx previous proposal we rejected. (incremental). in Minutes.
WalletService.backoffTimeMinutes = 2; WalletService.BACKOFF_TIME = 2;
// Fund scanning parameters // Fund scanning parameters
WalletService.scanConfig = { WalletService.SCAN_CONFIG = {
SCAN_WINDOW: 20, scanWindow: 20,
DERIVATION_DELAY: 10, // in milliseconds derivationDelay: 10, // in milliseconds
}; };
WalletService.FEE_LEVELS = [{
name: 'priority',
nbBlocks: 1,
defaultValue: 50000
}, {
name: 'normal',
nbBlocks: 2,
defaultValue: 20000
}, {
name: 'economy',
nbBlocks: 6,
defaultValue: 10000
}];
/** /**
* Initializes global settings for all instances. * Initializes global settings for all instances.
* @param {Object} opts * @param {Object} opts
@ -810,7 +825,7 @@ WalletService.prototype.getFeeLevels = function(opts, cb) {
if (network != 'livenet' && network != 'testnet') if (network != 'livenet' && network != 'testnet')
return cb(new ClientError('Invalid network')); return cb(new ClientError('Invalid network'));
var levels = WalletUtils.FEE_LEVELS; var levels = WalletService.FEE_LEVELS;
var samplePoints = _.uniq(_.pluck(levels, 'nbBlocks')); var samplePoints = _.uniq(_.pluck(levels, 'nbBlocks'));
self._sampleFeeLevels(network, samplePoints, function(err, feeSamples) { self._sampleFeeLevels(network, samplePoints, function(err, feeSamples) {
var values = _.map(levels, function(level) { var values = _.map(levels, function(level) {
@ -924,7 +939,7 @@ WalletService.prototype._selectTxInputs = function(txp, cb) {
WalletService.prototype._canCreateTx = function(copayerId, cb) { WalletService.prototype._canCreateTx = function(copayerId, cb) {
var self = this; var self = this;
self.storage.fetchLastTxs(self.walletId, copayerId, 5 + WalletService.backoffOffset, function(err, txs) { self.storage.fetchLastTxs(self.walletId, copayerId, 5 + WalletService.BACKOFF_OFFSET, function(err, txs) {
if (err) return cb(err); if (err) return cb(err);
if (!txs.length) if (!txs.length)
@ -934,7 +949,7 @@ WalletService.prototype._canCreateTx = function(copayerId, cb) {
status: 'rejected' status: 'rejected'
}); });
var exceededRejections = lastRejections.length - WalletService.backoffOffset; var exceededRejections = lastRejections.length - WalletService.BACKOFF_OFFSET;
if (exceededRejections <= 0) if (exceededRejections <= 0)
return cb(null, true); return cb(null, true);
@ -942,7 +957,7 @@ WalletService.prototype._canCreateTx = function(copayerId, cb) {
var lastTxTs = txs[0].createdOn; var lastTxTs = txs[0].createdOn;
var now = Math.floor(Date.now() / 1000); var now = Math.floor(Date.now() / 1000);
var timeSinceLastRejection = now - lastTxTs; var timeSinceLastRejection = now - lastTxTs;
var backoffTime = 60 * Math.pow(WalletService.backoffTimeMinutes, exceededRejections); var backoffTime = 60 * Math.pow(WalletService.BACKOFF_TIME, exceededRejections);
if (timeSinceLastRejection <= backoffTime) if (timeSinceLastRejection <= backoffTime)
log.debug('Not allowing to create TX: timeSinceLastRejection/backoffTime', timeSinceLastRejection, backoffTime); log.debug('Not allowing to create TX: timeSinceLastRejection/backoffTime', timeSinceLastRejection, backoffTime);
@ -1132,7 +1147,7 @@ WalletService.prototype.removeWallet = function(opts, cb) {
WalletService.prototype.getRemainingDeleteLockTime = function(txp) { WalletService.prototype.getRemainingDeleteLockTime = function(txp) {
var now = Math.floor(Date.now() / 1000); var now = Math.floor(Date.now() / 1000);
var lockTimeRemaining = txp.createdOn + WalletService.deleteLockTime - now; var lockTimeRemaining = txp.createdOn + WalletService.DELETE_LOCKTIME - now;
if (lockTimeRemaining < 0) if (lockTimeRemaining < 0)
return 0; return 0;
@ -1663,7 +1678,7 @@ WalletService.prototype.scan = function(opts, cb) {
async.mapSeries(_.range(size), function(i, next) { async.mapSeries(_.range(size), function(i, next) {
setTimeout(function() { setTimeout(function() {
next(null, derivator.derive()); next(null, derivator.derive());
}, WalletService.scanConfig.DERIVATION_DELAY) }, WalletService.SCAN_CONFIG.derivationDelay)
}, cb); }, cb);
}; };
@ -1679,7 +1694,7 @@ WalletService.prototype.scan = function(opts, cb) {
async.whilst(function() { async.whilst(function() {
return activity; return activity;
}, function(next) { }, function(next) {
deriveAddresses(WalletService.scanConfig.SCAN_WINDOW, derivator, function(err, addresses) { deriveAddresses(WalletService.SCAN_CONFIG.scanWindow, derivator, function(err, addresses) {
if (err) return next(err); if (err) return next(err);
networkName = networkName || Bitcore.Address(addresses[0].address).toObject().network; networkName = networkName || Bitcore.Address(addresses[0].address).toObject().network;
checkActivity(_.pluck(addresses, 'address'), networkName, function(err, thereIsActivity) { checkActivity(_.pluck(addresses, 'address'), networkName, function(err, thereIsActivity) {
@ -1689,7 +1704,7 @@ WalletService.prototype.scan = function(opts, cb) {
if (thereIsActivity) { if (thereIsActivity) {
allAddresses.push(addresses); allAddresses.push(addresses);
} else { } else {
derivator.rewind(WalletService.scanConfig.SCAN_WINDOW); derivator.rewind(WalletService.SCAN_CONFIG.scanWindow);
} }
next(); next();
}); });

View File

@ -1523,8 +1523,8 @@ describe('Wallet service', function() {
it('should get current fee levels', function(done) { it('should get current fee levels', function(done) {
helpers.stubFeeLevels({ helpers.stubFeeLevels({
1: 40000, 1: 40000,
4: 20000, 2: 20000,
12: 18000, 6: 18000,
}); });
server.getFeeLevels({}, function(err, fees) { server.getFeeLevels({}, function(err, fees) {
should.not.exist(err); should.not.exist(err);
@ -1535,10 +1535,10 @@ describe('Wallet service', function() {
fees.priority.nbBlocks.should.equal(1); fees.priority.nbBlocks.should.equal(1);
fees.normal.feePerKB.should.equal(20000); fees.normal.feePerKB.should.equal(20000);
fees.normal.nbBlocks.should.equal(4); fees.normal.nbBlocks.should.equal(2);
fees.economy.feePerKB.should.equal(18000); fees.economy.feePerKB.should.equal(18000);
fees.economy.nbBlocks.should.equal(12); fees.economy.nbBlocks.should.equal(6);
done(); done();
}); });
}); });
@ -1558,8 +1558,8 @@ describe('Wallet service', function() {
it('should get default fees if network cannot estimate (returns -1)', function(done) { it('should get default fees if network cannot estimate (returns -1)', function(done) {
helpers.stubFeeLevels({ helpers.stubFeeLevels({
1: -1, 1: -1,
4: 18000, 2: 18000,
12: 0, 6: 0,
}); });
server.getFeeLevels({}, function(err, fees) { server.getFeeLevels({}, function(err, fees) {
should.not.exist(err); should.not.exist(err);
@ -1570,10 +1570,10 @@ describe('Wallet service', function() {
should.not.exist(fees.priority.nbBlocks); should.not.exist(fees.priority.nbBlocks);
fees.normal.feePerKB.should.equal(18000); fees.normal.feePerKB.should.equal(18000);
fees.normal.nbBlocks.should.equal(4); fees.normal.nbBlocks.should.equal(2);
fees.economy.feePerKB.should.equal(0); fees.economy.feePerKB.should.equal(0);
fees.economy.nbBlocks.should.equal(12); fees.economy.nbBlocks.should.equal(6);
done(); done();
}); });
}); });
@ -2247,7 +2247,7 @@ describe('Wallet service', function() {
}); });
}, },
function(next) { function(next) {
var clock = sinon.useFakeTimers(Date.now() + (WalletService.backoffTimeMinutes + 2) * 60 * 1000, 'Date'); var clock = sinon.useFakeTimers(Date.now() + (WalletService.BACKOFF_TIME + 2) * 60 * 1000, 'Date');
var txOpts = helpers.createSimpleProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 1, null, TestData.copayers[0].privKey_1H_0); var txOpts = helpers.createSimpleProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 1, null, TestData.copayers[0].privKey_1H_0);
server.createTx(txOpts, function(err, tx) { server.createTx(txOpts, function(err, tx) {
clock.restore(); clock.restore();
@ -2259,7 +2259,7 @@ describe('Wallet service', function() {
}, },
function(next) { function(next) {
// Do not allow a 5th tx before backoff time // Do not allow a 5th tx before backoff time
var clock = sinon.useFakeTimers(Date.now() + (WalletService.backoffTimeMinutes + 2) * 60 * 1000 + 1, 'Date'); var clock = sinon.useFakeTimers(Date.now() + (WalletService.BACKOFF_TIME + 2) * 60 * 1000 + 1, 'Date');
var txOpts = helpers.createSimpleProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 1, null, TestData.copayers[0].privKey_1H_0); var txOpts = helpers.createSimpleProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 1, null, TestData.copayers[0].privKey_1H_0);
server.createTx(txOpts, function(err, tx) { server.createTx(txOpts, function(err, tx) {
clock.restore(); clock.restore();
@ -3514,7 +3514,7 @@ describe('Wallet service', function() {
server.getPendingTxs({}, function(err, txs) { server.getPendingTxs({}, function(err, txs) {
should.not.exist(err); should.not.exist(err);
txs[0].deleteLockTime.should.be.above(WalletService.deleteLockTime - 10); txs[0].deleteLockTime.should.be.above(WalletService.DELETE_LOCKTIME - 10);
var clock = sinon.useFakeTimers(Date.now() + 1 + 24 * 3600 * 1000, 'Date'); var clock = sinon.useFakeTimers(Date.now() + 1 + 24 * 3600 * 1000, 'Date');
server.removePendingTx({ server.removePendingTx({
@ -3539,7 +3539,7 @@ describe('Wallet service', function() {
}, function(err) { }, function(err) {
should.not.exist(err); should.not.exist(err);
var clock = sinon.useFakeTimers(Date.now() + 2000 + WalletService.deleteLockTime * 1000, 'Date'); var clock = sinon.useFakeTimers(Date.now() + 2000 + WalletService.DELETE_LOCKTIME * 1000, 'Date');
server2.removePendingTx({ server2.removePendingTx({
txProposalId: txp.id txProposalId: txp.id
}, function(err) { }, function(err) {
@ -3856,11 +3856,11 @@ describe('Wallet service', function() {
describe('#scan', function() { describe('#scan', function() {
var server, wallet; var server, wallet;
var scanConfigOld = WalletService.scanConfig; var scanConfigOld = WalletService.SCAN_CONFIG;
beforeEach(function(done) { beforeEach(function(done) {
this.timeout(5000); this.timeout(5000);
WalletService.scanConfig.SCAN_WINDOW = 2; WalletService.SCAN_CONFIG.scanWindow = 2;
WalletService.scanConfig.DERIVATION_DELAY = 0; WalletService.SCAN_CONFIG.derivationDelay = 0;
helpers.createAndJoinWallet(1, 2, function(s, w) { helpers.createAndJoinWallet(1, 2, function(s, w) {
server = s; server = s;
@ -3869,7 +3869,7 @@ describe('Wallet service', function() {
}); });
}); });
afterEach(function() { afterEach(function() {
WalletService.scanConfig = scanConfigOld; WalletService.SCAN_CONFIG = scanConfigOld;
}); });
it('should scan main addresses', function(done) { it('should scan main addresses', function(done) {
@ -3999,11 +3999,11 @@ describe('Wallet service', function() {
describe('#startScan', function() { describe('#startScan', function() {
var server, wallet; var server, wallet;
var scanConfigOld = WalletService.scanConfig; var scanConfigOld = WalletService.SCAN_CONFIG;
beforeEach(function(done) { beforeEach(function(done) {
this.timeout(5000); this.timeout(5000);
WalletService.scanConfig.SCAN_WINDOW = 2; WalletService.SCAN_CONFIG.scanWindow = 2;
WalletService.scanConfig.DERIVATION_DELAY = 0; WalletService.SCAN_CONFIG.derivationDelay = 0;
helpers.createAndJoinWallet(1, 2, function(s, w) { helpers.createAndJoinWallet(1, 2, function(s, w) {
server = s; server = s;
@ -4012,7 +4012,7 @@ describe('Wallet service', function() {
}); });
}); });
afterEach(function() { afterEach(function() {
WalletService.scanConfig = scanConfigOld; WalletService.SCAN_CONFIG = scanConfigOld;
server.messageBroker.removeAllListeners(); server.messageBroker.removeAllListeners();
}); });
@ -4072,7 +4072,7 @@ describe('Wallet service', function() {
}); });
it('should start multiple asynchronous scans for different wallets', function(done) { it('should start multiple asynchronous scans for different wallets', function(done) {
helpers.stubAddressActivity(['3K2VWMXheGZ4qG35DyGjA2dLeKfaSr534A']); helpers.stubAddressActivity(['3K2VWMXheGZ4qG35DyGjA2dLeKfaSr534A']);
WalletService.scanConfig.SCAN_WINDOW = 1; WalletService.SCAN_CONFIG.scanWindow = 1;
var scans = 0; var scans = 0;
server.messageBroker.onMessage(function(n) { server.messageBroker.onMessage(function(n) {