Browse Source

rm hdpath

activeAddress
Ivan Socolsky 10 years ago
parent
commit
0672c9084f
  1. 117
      lib/hdpath.js
  2. 21
      lib/model/addressmanager.js
  3. 4
      lib/server.js
  4. 1
      lib/walletutils.js
  5. 71
      test/hdpath.js

117
lib/hdpath.js

@ -1,117 +0,0 @@
'use strict';
// 90.2% typed (by google's closure-compiler account)
var preconditions = require('preconditions').singleton();
var _ = require('lodash');
/**
* @namespace
* @desc
* HDPath contains helper functions to handle BIP32 branches as
* Copay uses them.
* Based on https://github.com/maraoz/bips/blob/master/bip-NNNN.mediawiki
* <pre>
* m / purpose' / copayerIndex / change:boolean / addressIndex
* </pre>
*/
var HDPath = {};
/**
* @desc Copay's BIP45 purpose code
* @const
* @type number
*/
HDPath.PURPOSE = 45;
/**
* @desc Maximum number for non-hardened values (BIP32)
* @const
* @type number
*/
HDPath.MAX_NON_HARDENED = 0x80000000 - 1;
/**
* @desc Shared Index: used for creating addresses for no particular purpose
* @const
* @type number
*/
HDPath.SHARED_INDEX = HDPath.MAX_NON_HARDENED - 0;
/**
* @desc ???
* @const
* @type number
*/
HDPath.ID_INDEX = HDPath.MAX_NON_HARDENED - 1;
/**
* @desc BIP45 prefix for COPAY
* @const
* @type string
*/
HDPath.BIP45_PUBLIC_PREFIX = 'm/' + HDPath.PURPOSE + '\'';
/**
* @desc Retrieve a string to be used with bitcore representing a Copay branch
* @param {number} addressIndex - the last value of the HD derivation
* @param {boolean} isChange - whether this is a change address or a receive
* @param {number} copayerIndex - the index of the copayer in the pubkeyring
* @return {string} - the path for the HD derivation
*/
HDPath.Branch = function(addressIndex, isChange, copayerIndex) {
preconditions.checkArgument(_.isNumber(addressIndex));
preconditions.checkArgument(_.isBoolean(isChange));
var ret = 'm/' +
(typeof copayerIndex !== 'undefined' ? copayerIndex : HDPath.SHARED_INDEX) + '/' +
(isChange ? 1 : 0) + '/' +
addressIndex;
return ret;
};
/**
* @desc ???
* @param {number} addressIndex - the last value of the HD derivation
* @param {boolean} isChange - whether this is a change address or a receive
* @param {number} copayerIndex - the index of the copayer in the pubkeyring
* @return {string} - the path for the HD derivation
*/
HDPath.FullBranch = function(addressIndex, isChange, copayerIndex) {
preconditions.checkArgument(_.isNumber(addressIndex));
preconditions.checkArgument(_.isBoolean(isChange));
var sub = HDPath.Branch(addressIndex, isChange, copayerIndex);
sub = sub.substring(2);
return HDPath.BIP45_PUBLIC_PREFIX + '/' + sub;
};
/**
* @desc
* Decompose a string and retrieve its arguments as if it where a Copay address.
* @param {string} path - the HD path
* @returns {Object} an object with three keys: addressIndex, isChange, and
* copayerIndex
*/
HDPath.indexesForPath = function(path) {
preconditions.checkArgument(_.isString(path));
var s = path.split('/');
var l = s.length;
return {
isChange: s[l - 2] === '1',
addressIndex: parseInt(s[l - 1], 10),
copayerIndex: parseInt(s[l - 3], 10)
};
};
/**
* @desc The ID for a shared branch
*/
HDPath.IdFullBranch = HDPath.FullBranch(0, false, HDPath.ID_INDEX);
/**
* @desc Partial ID for a shared branch
*/
HDPath.IdBranch = HDPath.Branch(0, false, HDPath.ID_INDEX);
module.exports = HDPath;

21
lib/model/addressmanager.js

@ -1,5 +1,6 @@
var _ = require('lodash');
var HDPath = require('../hdpath');
var SHARED_INDEX = 0x80000000 - 1;
function AddressManager() {
this.version = '1.0.0';
@ -12,7 +13,7 @@ AddressManager.create = function(opts) {
x.receiveAddressIndex = 0;
x.changeAddressIndex = 0;
x.copayerIndex = (opts && _.isNumber(opts.copayerIndex)) ? opts.copayerIndex : HDPath.SHARED_INDEX;
x.copayerIndex = (opts && _.isNumber(opts.copayerIndex)) ? opts.copayerIndex : SHARED_INDEX;
return x;
};
@ -28,6 +29,7 @@ AddressManager.fromObj = function(obj) {
return x;
};
AddressManager.prototype._incrementIndex = function(isChange) {
if (isChange) {
this.changeAddressIndex++;
@ -37,7 +39,20 @@ AddressManager.prototype._incrementIndex = function(isChange) {
};
AddressManager.prototype.getCurrentAddressPath = function(isChange) {
return HDPath.Branch(isChange ? this.changeAddressIndex : this.receiveAddressIndex, isChange, this.copayerIndex);
return 'm/' +
(this.copayerIndex || SHARED_INDEX) + '/' +
(isChange ? 1 : 0) + '/' +
(isChange ? this.changeAddressIndex : this.receiveAddressIndex);
};
AddressManager.getIndexesForPath = function(path) {
var s = path.split('/');
var l = s.length;
return {
isChange: s[l - 2] === '1',
addressIndex: parseInt(s[l - 1], 10),
copayerIndex: parseInt(s[l - 3], 10)
};
};
AddressManager.prototype.getNewAddressPath = function(isChange) {

4
lib/server.js

@ -17,12 +17,12 @@ var Explorers = require('bitcore-explorers');
var ClientError = require('./clienterror');
var Utils = require('./utils');
var Storage = require('./storage');
var HDPath = require('./hdpath');
var WalletUtils = require('./walletutils');
var Wallet = require('./model/wallet');
var Copayer = require('./model/copayer');
var Address = require('./model/address');
var AddressManager = require('./model/addressmanager');
var TxProposal = require('./model/txproposal');
var Notification = require('./model/notification');
@ -291,7 +291,7 @@ WalletService.prototype.getMainAddresses = function(opts, cb) {
self.storage.fetchAddresses(self.walletId, function(err, addresses) {
if (err) return cb(err);
var mainAddresses = _.filter(addresses, function(x) {
return !HDPath.indexesForPath(x.path).isChange;
return !AddressManager.getIndexesForPath(x.path).isChange;
});
return cb(null, mainAddresses);

1
lib/walletutils.js

@ -10,7 +10,6 @@ var PrivateKey = Bitcore.PrivateKey;
var PublicKey = Bitcore.PublicKey;
var crypto = Bitcore.crypto;
var encoding = Bitcore.encoding;
var HDPath = require('./hdpath');
var Utils = require('./utils');
function WalletUtils() {};

71
test/hdpath.js

@ -1,71 +0,0 @@
'use strict';
var HDPath = require('../lib/hdpath');
describe('HDPath model', function() {
it('should have the correct constants', function() {
HDPath.MAX_NON_HARDENED.should.equal(Math.pow(2, 31) - 1);
HDPath.SHARED_INDEX.should.equal(HDPath.MAX_NON_HARDENED);
HDPath.ID_INDEX.should.equal(HDPath.SHARED_INDEX - 1);
HDPath.IdFullBranch.should.equal('m/45\'/2147483646/0/0');
});
it('should get the correct branches', function() {
// shared branch (no cosigner index specified)
HDPath.FullBranch(0, false).should.equal('m/45\'/2147483647/0/0');
// copayer 0, address 0, external address (receiving)
HDPath.FullBranch(0, false, 0).should.equal('m/45\'/0/0/0');
// copayer 0, address 10, external address (receiving)
HDPath.FullBranch(0, false, 10).should.equal('m/45\'/10/0/0');
// copayer 0, address 0, internal address (change)
HDPath.FullBranch(0, true, 0).should.equal('m/45\'/0/1/0');
// copayer 0, address 10, internal address (change)
HDPath.FullBranch(10, true, 0).should.equal('m/45\'/0/1/10');
// copayer 7, address 10, internal address (change)
HDPath.FullBranch(10, true, 7).should.equal('m/45\'/7/1/10');
});
[
['m/45\'/0/0/0', {
index: 0,
isChange: false
}],
['m/45\'/0/0/1', {
index: 1,
isChange: false
}],
['m/45\'/0/0/2', {
index: 2,
isChange: false
}],
['m/45\'/0/1/0', {
index: 0,
isChange: true
}],
['m/45\'/0/1/1', {
index: 1,
isChange: true
}],
['m/45\'/0/1/2', {
index: 2,
isChange: true
}],
['m/45\'/0/0/900', {
index: 900,
isChange: false
}],
].forEach(function(datum) {
var path = datum[0];
var result = datum[1];
it('should get the correct indexes for path ' + path, function() {
var i = HDPath.indexesForPath(path);
i.addressIndex.should.equal(result.index);
i.isChange.should.equal(result.isChange);
});
});
});
Loading…
Cancel
Save