refactor constants+defaults+utils -> common

This commit is contained in:
Ivan Socolsky 2015-10-30 17:16:20 -03:00
parent d451fff6fc
commit 795097bf04
14 changed files with 129 additions and 115 deletions

22
lib/common/constants.js Normal file
View File

@ -0,0 +1,22 @@
'use strict';
var Constants = {};
Constants.SCRIPT_TYPES = {
P2SH: 'P2SH',
P2PKH: 'P2PKH',
};
Constants.DERIVATION_STRATEGIES = {
BIP44: 'BIP44',
BIP45: 'BIP45',
};
Constants.PATHS = {
REQUEST_KEY: "m/1'/0",
TXPROPOSAL_KEY: "m/1'/1",
REQUEST_KEY_AUTH: "m/2", // relative to BASE
};
Constants.BIP45_SHARED_INDEX = 0x80000000 - 1;
module.exports = Constants;

40
lib/common/defaults.js Normal file
View File

@ -0,0 +1,40 @@
'use strict';
var Defaults = {};
Defaults.DEFAULT_FEE_PER_KB = 10000;
Defaults.MIN_FEE_PER_KB = 0;
Defaults.MAX_FEE_PER_KB = 1000000;
Defaults.MAX_TX_FEE = 1 * 1e8;
Defaults.MAX_KEYS = 100;
// Time after which a Tx proposal can be erased by any copayer. in seconds
Defaults.DELETE_LOCKTIME = 24 * 3600;
// Allowed consecutive txp rejections before backoff is applied.
Defaults.BACKOFF_OFFSET = 3;
// Time a copayer need to wait to create a new TX after her tx previous proposal we rejected. (incremental). in Minutes.
Defaults.BACKOFF_TIME = 2;
Defaults.MAX_MAIN_ADDRESS_GAP = 20;
// TODO: should allow different gap sizes for external/internal chains
Defaults.SCAN_ADDRESS_GAP = Defaults.MAX_MAIN_ADDRESS_GAP;
Defaults.FEE_LEVELS = [{
name: 'priority',
nbBlocks: 1,
defaultValue: 50000
}, {
name: 'normal',
nbBlocks: 2,
defaultValue: 20000
}, {
name: 'economy',
nbBlocks: 6,
defaultValue: 10000
}];
module.exports = Defaults;

7
lib/common/index.js Normal file
View File

@ -0,0 +1,7 @@
var Common = {};
Common.Constants = require('./constants');
Common.Defaults = require('./defaults');
Common.Utils = require('./utils');
module.exports = Common;

View File

@ -7,6 +7,7 @@ var crypto = Bitcore.crypto;
var encoding = Bitcore.encoding;
var Constants = require('./constants');
var Defaults = require('./defaults');
var Utils = {};
@ -120,7 +121,7 @@ Utils.buildTx = function(txp) {
return +o.satoshis + memo;
}, 0);
$.checkState(totalInputs - totalOutputs <= Constants.MAX_TX_FEE);
$.checkState(totalInputs - totalOutputs <= Defaults.MAX_TX_FEE);
return t;
};

View File

@ -1,55 +0,0 @@
'use strict';
var Constants = {};
Constants.SCRIPT_TYPES = {
P2SH: 'P2SH',
P2PKH: 'P2PKH',
};
Constants.DERIVATION_STRATEGIES = {
BIP44: 'BIP44',
BIP45: 'BIP45',
};
Constants.PATHS = {
REQUEST_KEY: "m/1'/0",
TXPROPOSAL_KEY: "m/1'/1",
REQUEST_KEY_AUTH: "m/2", // relative to BASE
};
Constants.DEFAULT_FEE_PER_KB = 10000;
Constants.MIN_FEE_PER_KB = 0;
Constants.MAX_FEE_PER_KB = 1000000;
Constants.MAX_TX_FEE = 1 * 1e8;
Constants.MAX_KEYS = 100;
// Time after which a Tx proposal can be erased by any copayer. in seconds
Constants.DELETE_LOCKTIME = 24 * 3600;
// Allowed consecutive txp rejections before backoff is applied.
Constants.BACKOFF_OFFSET = 3;
// Time a copayer need to wait to create a new TX after her tx previous proposal we rejected. (incremental). in Minutes.
Constants.BACKOFF_TIME = 2;
Constants.MAX_MAIN_ADDRESS_GAP = 20;
// TODO: should allow different gap sizes for external/internal chains
Constants.SCAN_ADDRESS_GAP = Constants.MAX_MAIN_ADDRESS_GAP;
Constants.FEE_LEVELS = [{
name: 'priority',
nbBlocks: 1,
defaultValue: 50000
}, {
name: 'normal',
nbBlocks: 2,
defaultValue: 20000
}, {
name: 'economy',
nbBlocks: 6,
defaultValue: 10000
}];
module.exports = Constants;

View File

@ -10,7 +10,7 @@ var fs = require('fs');
var path = require('path');
var nodemailer = require('nodemailer');
var Utils = require('./utils');
var Utils = require('./common/utils');
var Storage = require('./storage');
var MessageBroker = require('./messagebroker');
var Lock = require('./lock');

View File

@ -1,7 +1,7 @@
'use strict';
var Bitcore = require('bitcore-lib');
var Constants = require('../constants');
var Constants = require('../common/constants');
function Address() {};

View File

@ -2,9 +2,7 @@ var _ = require('lodash');
var $ = require('preconditions').singleton();
var Bitcore = require('bitcore-lib');
var Constants = require('../constants');
var BIP45_SHARED_INDEX = 0x80000000 - 1;
var Constants = require('../common/constants');
function AddressManager() {};
@ -19,7 +17,7 @@ AddressManager.create = function(opts) {
x.receiveAddressIndex = 0;
x.changeAddressIndex = 0;
x.copayerIndex = _.isNumber(opts.copayerIndex) ? opts.copayerIndex : BIP45_SHARED_INDEX;
x.copayerIndex = _.isNumber(opts.copayerIndex) ? opts.copayerIndex : Constants.BIP45_SHARED_INDEX;
return x;
};

View File

@ -9,8 +9,8 @@ var sjcl = require('sjcl');
var Address = require('./address');
var AddressManager = require('./addressmanager');
var Bitcore = require('bitcore-lib');
var Constants = require('../constants');
var Utils = require('../utils');
var Common = require('../common');
function Copayer() {};
@ -41,7 +41,7 @@ Copayer.create = function(opts) {
signature: opts.signature,
}];
var derivationStrategy = opts.derivationStrategy || Constants.DERIVATION_STRATEGIES.BIP45;
var derivationStrategy = opts.derivationStrategy || Common.Constants.DERIVATION_STRATEGIES.BIP45;
if (AddressManager.supportsCopayerBranches(derivationStrategy)) {
x.addressManager = AddressManager.create({
derivationStrategy: derivationStrategy,
@ -87,7 +87,7 @@ Copayer.prototype.createAddress = function(wallet, isChange) {
$.checkState(wallet.isComplete());
var path = this.addressManager.getNewAddressPath(isChange);
var raw = Address.create(Utils.deriveAddress(wallet.addressType, wallet.publicKeyRing, path, wallet.m, wallet.network));
var raw = Address.create(Common.Utils.deriveAddress(wallet.addressType, wallet.publicKeyRing, path, wallet.m, wallet.network));
var address = Address.create(_.extend(raw, {
walletId: wallet.id,
type: wallet.addressType,

View File

@ -8,8 +8,9 @@ log.debug = log.verbose;
log.disableColor();
var Bitcore = require('bitcore-lib');
var Constants = require('../constants');
var Utils = require('../utils');
var Common = require('../common');
var Constants = Common.Constants;
var TxProposalAction = require('./txproposalaction');
@ -164,7 +165,7 @@ TxProposal.prototype._getCurrentSignatures = function() {
TxProposal.prototype.getBitcoreTx = function() {
var self = this;
var t = Utils.buildTx(this);
var t = Common.Utils.buildTx(this);
var sigs = this._getCurrentSignatures();
_.each(sigs, function(x) {

View File

@ -8,8 +8,9 @@ var Uuid = require('uuid');
var Address = require('./address');
var Copayer = require('./copayer');
var AddressManager = require('./addressmanager');
var Constants = require('../constants');
var Utils = require('../utils');
var Common = require('../common');
var Constants = Common.Constants;
function Wallet() {};
@ -154,7 +155,7 @@ Wallet.prototype.createAddress = function(isChange) {
var self = this;
var path = this.addressManager.getNewAddressPath(isChange);
var raw = Utils.deriveAddress(this.addressType, this.publicKeyRing, path, this.m, this.network);
var raw = Common.Utils.deriveAddress(this.addressType, this.publicKeyRing, path, this.m, this.network);
var address = Address.create(_.extend(raw, {
walletId: self.id,
type: self.addressType,

View File

@ -10,11 +10,14 @@ var Stringify = require('json-stable-stringify');
var Bitcore = require('bitcore-lib');
var Constants = require('./constants');
var Common = require('./common');
var Utils = Common.Utils;
var Constants = Common.Constants;
var Defaults = Common.Defaults;
var ClientError = require('./errors/clienterror');
var Errors = require('./errors/errordefinitions');
var Utils = require('./utils');
var Lock = require('./lock');
var Storage = require('./storage');
var MessageBroker = require('./messagebroker');
@ -498,7 +501,7 @@ WalletService.prototype.addAccess = function(opts, cb) {
return cb(Errors.NOT_AUTHORIZED);
}
if (copayer.requestPubKeys.length > Constants.MAX_KEYS)
if (copayer.requestPubKeys.length > Defaults.MAX_KEYS)
return cb(Errors.TOO_MANY_KEYS);
self._addKeyToCopayer(wallet, copayer, opts, cb);
@ -682,8 +685,8 @@ WalletService.prototype._canCreateAddress = function(ignoreMaxGap, cb) {
if (err) return cb(err);
var latestAddresses = _.takeRight(_.reject(addresses, {
isChange: true
}), Constants.MAX_MAIN_ADDRESS_GAP);
if (latestAddresses.length < Constants.MAX_MAIN_ADDRESS_GAP || _.any(latestAddresses, {
}), Defaults.MAX_MAIN_ADDRESS_GAP);
if (latestAddresses.length < Defaults.MAX_MAIN_ADDRESS_GAP || _.any(latestAddresses, {
hasActivity: true
})) return cb(null, true);
@ -1002,7 +1005,7 @@ WalletService.prototype.getFeeLevels = function(opts, cb) {
if (network != 'livenet' && network != 'testnet')
return cb(new ClientError('Invalid network'));
var levels = Constants.FEE_LEVELS;
var levels = Defaults.FEE_LEVELS;
var samplePoints = _.uniq(_.pluck(levels, 'nbBlocks'));
self._sampleFeeLevels(network, samplePoints, function(err, feeSamples) {
var values = _.map(levels, function(level) {
@ -1125,7 +1128,7 @@ WalletService.prototype._selectTxInputs = function(txp, utxosToExclude, cb) {
WalletService.prototype._canCreateTx = function(copayerId, cb) {
var self = this;
self.storage.fetchLastTxs(self.walletId, copayerId, 5 + Constants.BACKOFF_OFFSET, function(err, txs) {
self.storage.fetchLastTxs(self.walletId, copayerId, 5 + Defaults.BACKOFF_OFFSET, function(err, txs) {
if (err) return cb(err);
if (!txs.length)
@ -1135,7 +1138,7 @@ WalletService.prototype._canCreateTx = function(copayerId, cb) {
status: 'rejected'
});
var exceededRejections = lastRejections.length - Constants.BACKOFF_OFFSET;
var exceededRejections = lastRejections.length - Defaults.BACKOFF_OFFSET;
if (exceededRejections <= 0)
return cb(null, true);
@ -1143,7 +1146,7 @@ WalletService.prototype._canCreateTx = function(copayerId, cb) {
var lastTxTs = txs[0].createdOn;
var now = Math.floor(Date.now() / 1000);
var timeSinceLastRejection = now - lastTxTs;
var backoffTime = 60 * Math.pow(Constants.BACKOFF_TIME, exceededRejections);
var backoffTime = 60 * Math.pow(Defaults.BACKOFF_TIME, exceededRejections);
if (timeSinceLastRejection <= backoffTime)
log.debug('Not allowing to create TX: timeSinceLastRejection/backoffTime', timeSinceLastRejection, backoffTime);
@ -1206,8 +1209,8 @@ WalletService.prototype.createTx = function(opts, cb) {
valid: false
})) return;
var feePerKb = opts.feePerKb || Constants.DEFAULT_FEE_PER_KB;
if (feePerKb < Constants.MIN_FEE_PER_KB || feePerKb > Constants.MAX_FEE_PER_KB)
var feePerKb = opts.feePerKb || Defaults.DEFAULT_FEE_PER_KB;
if (feePerKb < Defaults.MIN_FEE_PER_KB || feePerKb > Defaults.MAX_FEE_PER_KB)
return cb(new ClientError('Invalid fee per KB value'));
self._runLocked(cb, function(cb) {
@ -1357,7 +1360,7 @@ WalletService.prototype.removeWallet = function(opts, cb) {
WalletService.prototype.getRemainingDeleteLockTime = function(txp) {
var now = Math.floor(Date.now() / 1000);
var lockTimeRemaining = txp.createdOn + Constants.DELETE_LOCKTIME - now;
var lockTimeRemaining = txp.createdOn + Defaults.DELETE_LOCKTIME - now;
if (lockTimeRemaining < 0)
return 0;
@ -1937,7 +1940,7 @@ WalletService.prototype.scan = function(opts, cb) {
function scanBranch(derivator, cb) {
var inactiveCounter = 0;
var allAddresses = [];
var gap = Constants.SCAN_ADDRESS_GAP;
var gap = Defaults.SCAN_ADDRESS_GAP;
async.whilst(function() {
return inactiveCounter < gap;

View File

@ -17,8 +17,11 @@ var tingodb = require('tingodb')({
var Bitcore = require('bitcore-lib');
var Constants = require('../../lib/constants');
var Utils = require('../../lib/utils');
var Common = require('../../lib/common');
var Utils = Common.Utils;
var Constants = Common.Constants;
var Defaults = Common.Defaults;
var Storage = require('../../lib/storage');
var Model = require('../../lib/model');
@ -1770,8 +1773,8 @@ describe('Wallet service', function() {
});
it('should fail to create more consecutive addresses with no activity than allowed', function(done) {
var MAX_MAIN_ADDRESS_GAP_old = Constants.MAX_MAIN_ADDRESS_GAP;
Constants.MAX_MAIN_ADDRESS_GAP = 2;
var MAX_MAIN_ADDRESS_GAP_old = Defaults.MAX_MAIN_ADDRESS_GAP;
Defaults.MAX_MAIN_ADDRESS_GAP = 2;
helpers.stubAddressActivity([]);
async.map(_.range(2), function(i, next) {
server.createAddress({}, next);
@ -1797,7 +1800,7 @@ describe('Wallet service', function() {
should.exist(address);
address.path.should.equal('m/0/3');
Constants.MAX_MAIN_ADDRESS_GAP = MAX_MAIN_ADDRESS_GAP_old;
Defaults.MAX_MAIN_ADDRESS_GAP = MAX_MAIN_ADDRESS_GAP_old;
done();
});
});
@ -1806,8 +1809,8 @@ describe('Wallet service', function() {
});
it('should cache address activity', function(done) {
var MAX_MAIN_ADDRESS_GAP_old = Constants.MAX_MAIN_ADDRESS_GAP;
Constants.MAX_MAIN_ADDRESS_GAP = 2;
var MAX_MAIN_ADDRESS_GAP_old = Defaults.MAX_MAIN_ADDRESS_GAP;
Defaults.MAX_MAIN_ADDRESS_GAP = 2;
helpers.stubAddressActivity([]);
async.map(_.range(2), function(i, next) {
server.createAddress({}, next);
@ -1821,7 +1824,7 @@ describe('Wallet service', function() {
server.createAddress({}, function(err, address) {
should.not.exist(err);
getAddressActivitySpy.callCount.should.equal(1);
Constants.MAX_MAIN_ADDRESS_GAP = MAX_MAIN_ADDRESS_GAP_old;
Defaults.MAX_MAIN_ADDRESS_GAP = MAX_MAIN_ADDRESS_GAP_old;
done();
});
});
@ -2475,7 +2478,7 @@ describe('Wallet service', function() {
tx.isAccepted().should.equal.false;
tx.isRejected().should.equal.false;
tx.amount.should.equal(helpers.toSatoshi(80));
var estimatedFee = Constants.DEFAULT_FEE_PER_KB * 400 / 1000; // fully signed tx should have about 400 bytes
var estimatedFee = Defaults.DEFAULT_FEE_PER_KB * 400 / 1000; // fully signed tx should have about 400 bytes
tx.fee.should.be.within(0.9 * estimatedFee, 1.1 * estimatedFee);
server.getPendingTxs({}, function(err, txs) {
should.not.exist(err);
@ -2730,7 +2733,7 @@ describe('Wallet service', function() {
var txOpts = helpers.createSimpleProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 3.5, TestData.copayers[0].privKey_1H_0);
server.createTx(txOpts, function(err, tx) {
should.not.exist(err);
var estimatedFee = Constants.DEFAULT_FEE_PER_KB * 1300 / 1000; // fully signed tx should have about 1300 bytes
var estimatedFee = Defaults.DEFAULT_FEE_PER_KB * 1300 / 1000; // fully signed tx should have about 1300 bytes
tx.fee.should.be.within(0.9 * estimatedFee, 1.1 * estimatedFee);
done();
});
@ -3126,7 +3129,7 @@ describe('Wallet service', function() {
});
},
function(next) {
var clock = sinon.useFakeTimers(Date.now() + (Constants.BACKOFF_TIME + 2) * 60 * 1000, 'Date');
var clock = sinon.useFakeTimers(Date.now() + (Defaults.BACKOFF_TIME + 2) * 60 * 1000, 'Date');
var txOpts = helpers.createSimpleProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 1, TestData.copayers[0].privKey_1H_0);
server.createTx(txOpts, function(err, tx) {
clock.restore();
@ -3138,7 +3141,7 @@ describe('Wallet service', function() {
},
function(next) {
// Do not allow a 5th tx before backoff time
var clock = sinon.useFakeTimers(Date.now() + (Constants.BACKOFF_TIME + 2) * 60 * 1000 + 1, 'Date');
var clock = sinon.useFakeTimers(Date.now() + (Defaults.BACKOFF_TIME + 2) * 60 * 1000 + 1, 'Date');
var txOpts = helpers.createSimpleProposalOpts('18PzpUFkFZE8zKWUPvfykkTxmB9oMR8qP7', 1, TestData.copayers[0].privKey_1H_0);
server.createTx(txOpts, function(err, tx) {
clock.restore();
@ -4598,7 +4601,7 @@ describe('Wallet service', function() {
server.getPendingTxs({}, function(err, txs) {
should.not.exist(err);
txs[0].deleteLockTime.should.be.above(Constants.DELETE_LOCKTIME - 10);
txs[0].deleteLockTime.should.be.above(Defaults.DELETE_LOCKTIME - 10);
var clock = sinon.useFakeTimers(Date.now() + 1 + 24 * 3600 * 1000, 'Date');
server.removePendingTx({
@ -4623,7 +4626,7 @@ describe('Wallet service', function() {
}, function(err) {
should.not.exist(err);
var clock = sinon.useFakeTimers(Date.now() + 2000 + Constants.DELETE_LOCKTIME * 1000, 'Date');
var clock = sinon.useFakeTimers(Date.now() + 2000 + Defaults.DELETE_LOCKTIME * 1000, 'Date');
server2.removePendingTx({
txProposalId: txp.id
}, function(err) {
@ -4948,12 +4951,11 @@ describe('Wallet service', function() {
describe('#scan', function() {
var server, wallet;
var scanConfigOld = Constants.SCAN_CONFIG;
describe('1-of-1 wallet (BIP44 & P2PKH)', function() {
beforeEach(function(done) {
this.timeout(5000);
Constants.SCAN_ADDRESS_GAP = 2;
Defaults.SCAN_ADDRESS_GAP = 2;
helpers.createAndJoinWallet(1, 1, function(s, w) {
server = s;
@ -4961,9 +4963,7 @@ describe('Wallet service', function() {
done();
});
});
afterEach(function() {
Constants.SCAN_CONFIG = scanConfigOld;
});
afterEach(function() {});
it('should scan main addresses', function(done) {
helpers.stubAddressActivity(
@ -5145,7 +5145,7 @@ describe('Wallet service', function() {
beforeEach(function(done) {
this.timeout(5000);
Constants.SCAN_ADDRESS_GAP = 2;
Defaults.SCAN_ADDRESS_GAP = 2;
helpers.createAndJoinWallet(1, 2, {
supportBIP44AndP2PKH: false
@ -5155,9 +5155,7 @@ describe('Wallet service', function() {
done();
});
});
afterEach(function() {
Constants.SCAN_CONFIG = scanConfigOld;
});
afterEach(function() {});
it('should scan main addresses', function(done) {
helpers.stubAddressActivity(
@ -5224,10 +5222,9 @@ describe('Wallet service', function() {
describe('#startScan', function() {
var server, wallet;
var scanConfigOld = Constants.SCAN_CONFIG;
beforeEach(function(done) {
this.timeout(5000);
Constants.SCAN_ADDRESS_GAP = 2;
Defaults.SCAN_ADDRESS_GAP = 2;
helpers.createAndJoinWallet(1, 1, {
supportBIP44AndP2PKH: false
@ -5238,7 +5235,6 @@ describe('Wallet service', function() {
});
});
afterEach(function() {
Constants.SCAN_CONFIG = scanConfigOld;
server.messageBroker.removeAllListeners();
});
@ -5296,7 +5292,7 @@ describe('Wallet service', function() {
});
it('should start multiple asynchronous scans for different wallets', function(done) {
helpers.stubAddressActivity(['3K2VWMXheGZ4qG35DyGjA2dLeKfaSr534A']);
Constants.SCAN_ADDRESS_GAP = 1;
Defaults.SCAN_ADDRESS_GAP = 1;
var scans = 0;
server.messageBroker.onMessage(function(n) {
@ -5372,7 +5368,7 @@ describe('Wallet service', function() {
should.not.exist(err);
should.exist(tx);
tx.amount.should.equal(helpers.toSatoshi(80));
tx.fee.should.equal(Constants.DEFAULT_FEE_PER_KB);
tx.fee.should.equal(Defaults.DEFAULT_FEE_PER_KB);
done();
});
});
@ -5462,7 +5458,7 @@ describe('Wallet service', function() {
should.not.exist(err);
should.exist(tx);
tx.amount.should.equal(helpers.toSatoshi(80));
tx.fee.should.equal(Constants.DEFAULT_FEE_PER_KB);
tx.fee.should.equal(Defaults.DEFAULT_FEE_PER_KB);
helpers.getAuthServer(wallet.copayers[0].id, function(server) {
var signatures = helpers.clientSign(tx, TestData.copayers[0].xPrivKey);
server.signTx({

View File

@ -4,7 +4,7 @@ var _ = require('lodash');
var chai = require('chai');
var sinon = require('sinon');
var should = chai.should();
var Utils = require('../lib/utils');
var Utils = require('../lib/common/utils');
describe('Utils', function() {
describe('#checkRequired', function() {