Matias Alejo Garcia
10 years ago
8 changed files with 26 additions and 197 deletions
@ -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; |
|
@ -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…
Reference in new issue