From b8e20c1ee7caa61fff4ec8cc571e3c59c4c3a649 Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Wed, 28 May 2014 16:10:05 -0300 Subject: [PATCH 1/6] change BIP32 structure to match our new BIP --- js/models/core/PrivateKey.js | 17 ++++++--- js/models/core/PublicKeyRing.js | 65 ++++++++++++++++++++------------- js/models/core/WalletFactory.js | 12 ++---- 3 files changed, 53 insertions(+), 41 deletions(-) diff --git a/js/models/core/PrivateKey.js b/js/models/core/PrivateKey.js index 8f0643b59..110dca65b 100644 --- a/js/models/core/PrivateKey.js +++ b/js/models/core/PrivateKey.js @@ -20,13 +20,20 @@ function PrivateKey(opts) { PrivateKey.prototype.getId = function() { if (!this.id) { - var path = PublicKeyRing.ID_BRANCH; - var bip32 = this.bip.derive(path); - this.id= bip32.eckey.public.toString('hex'); + var path = PublicKeyRing.IdFullBranch(); + var idhk = this.bip.derive(path); + this.id= idhk.eckey.public.toString('hex'); } return this.id; }; +PrivateKey.prototype.deriveBIP45Branch = function() { + if (!this.bip45Branch) { + this.bip45Branch = this.bip.derive(PublicKeyRing.BIP45_PUBLIC_PREFIX); + } + return this.bip45Branch; +} + PrivateKey.fromObj = function(obj) { return new PrivateKey(obj); }; @@ -55,13 +62,11 @@ PrivateKey.prototype._getHK = function(path) { }; PrivateKey.prototype.get = function(index,isChange) { - var path = PublicKeyRing.Branch(index, isChange); + var path = PublicKeyRing.FullBranch(index, isChange); var pk = this.privateKeyCache[path]; if (!pk) { var derivedHK = this._getHK(path); pk = this.privateKeyCache[path] = derivedHK.eckey.private.toString('hex'); - } else { - //console.log('cache hit!'); } var wk = new WalletKey({network: this.network}); wk.fromObj({priv: pk}); diff --git a/js/models/core/PublicKeyRing.js b/js/models/core/PublicKeyRing.js index c76d0914d..14ae83add 100644 --- a/js/models/core/PublicKeyRing.js +++ b/js/models/core/PublicKeyRing.js @@ -36,21 +36,39 @@ function PublicKeyRing(opts) { this.copayerIds = []; } -/* - * This follow Electrum convetion, as described in - * https://bitcointalk.org/index.php?topic=274182.0 - * - * We should probably adopt the next standard once it's ready, as discussed in: - * http://sourceforge.net/p/bitcoin/mailman/message/32148600/ - * - */ -PublicKeyRing.Branch = function (index, isChange) { - // first 0 is for future use: could be copayerId. - return 'm/0/'+(isChange?1:0)+'/'+index; +/* + * Based on https://github.com/maraoz/bips/blob/master/bip-NNNN.mediawiki + * m / purpose' / cosigner_index / change / address_index + */ +var PURPOSE = 45; +var MAX_NON_HARDENED = 0x8000000 - 1; + +var SHARED_INDEX = MAX_NON_HARDENED - 0; +var ID_INDEX = MAX_NON_HARDENED - 1; + +var BIP45_PUBLIC_PREFIX = 'm/'+ PURPOSE+'\''; +PublicKeyRing.BIP45_PUBLIC_PREFIX = BIP45_PUBLIC_PREFIX; + + +PublicKeyRing.Branch = function(address_index, isChange, cosigner_index) { + var ret = 'm/'+ + (typeof cosigner_index !== 'undefined'? cosigner_index: SHARED_INDEX)+'/'+ + (isChange?1:0)+'/'+ + address_index; + return ret; }; -PublicKeyRing.ID_BRANCH = 'm/100/0/0'; +PublicKeyRing.FullBranch = function(address_index, isChange, cosigner_index) { + var sub = PublicKeyRing.Branch(address_index, isChange, cosigner_index); + sub = sub.substring(2); + return BIP45_PUBLIC_PREFIX + '/' + sub; +}; +PublicKeyRing.IdFullBranch = function() { + return PublicKeyRing.FullBranch(0, 0, ID_INDEX); +}; + + PublicKeyRing.fromObj = function (data) { if (data instanceof PublicKeyRing) { @@ -114,8 +132,7 @@ PublicKeyRing.prototype._newExtendedPublicKey = function () { }; PublicKeyRing.prototype._updateBip = function (index) { - var path = PublicKeyRing.ID_BRANCH; - var hk = this.copayersHK[index].derive(path); + var hk = this.copayersHK[index].derive(PublicKeyRing.Branch(0, 0, ID_INDEX)); this.copayerIds[index]= hk.eckey.public.toString('hex'); }; @@ -123,38 +140,34 @@ PublicKeyRing.prototype._setNicknameForIndex = function (index, nickname) { this.nicknameFor[this.copayerIds[index]] = nickname; }; -PublicKeyRing.prototype.nicknameForIndex = function (index) { +PublicKeyRing.prototype.nicknameForIndex = function(index) { return this.nicknameFor[this.copayerIds[index]]; }; -PublicKeyRing.prototype.nicknameForCopayer = function (copayerId) { +PublicKeyRing.prototype.nicknameForCopayer = function(copayerId) { return this.nicknameFor[copayerId]; }; -PublicKeyRing.prototype.addCopayer = function (newEpk, nickname) { +PublicKeyRing.prototype.addCopayer = function(newEpk, nickname) { if (this.isComplete()) - throw new Error('already have all required key:' + this.totalCopayers); - - if (!newEpk) { - newEpk = this._newExtendedPublicKey(); - } + throw new Error('PKR already has all required key:' + this.totalCopayers); this.copayersHK.forEach(function(b){ if (b.extendedPublicKeyString() === newEpk) - throw new Error('already have that key'); + throw new Error('PKR already has that key'); }); - var i=this.copayersHK.length; + var i = this.copayersHK.length; var bip = new HK(newEpk); this.copayersHK.push(bip); this._updateBip(i); if (nickname) { - this._setNicknameForIndex(i,nickname); + this._setNicknameForIndex(i, nickname); } return newEpk; }; -PublicKeyRing.prototype.getPubKeys = function (index, isChange) { +PublicKeyRing.prototype.getPubKeys = function(index, isChange) { this._checkKeys(); var path = PublicKeyRing.Branch(index, isChange); diff --git a/js/models/core/WalletFactory.js b/js/models/core/WalletFactory.js index 602d8c3a2..afd322d6f 100644 --- a/js/models/core/WalletFactory.js +++ b/js/models/core/WalletFactory.js @@ -53,14 +53,6 @@ WalletFactory.prototype.fromObj = function(obj) { console.log('## Decrypting'); //TODO var w = Wallet.fromObj(obj, this.storage, this.network, this.blockchain); w.verbose = this.verbose; - // JIC: Add our key - try { - w.publicKeyRing.addCopayer( - w.privateKey.getExtendedPublicKeyString() - ); - } catch (e) { - // No really an error, just to be sure. - } this.log('### WALLET OPENED:', w.id); return w; }; @@ -107,7 +99,9 @@ WalletFactory.prototype.create = function(opts) { requiredCopayers: requiredCopayers, totalCopayers: totalCopayers, }); - opts.publicKeyRing.addCopayer(opts.privateKey.getExtendedPublicKeyString(), opts.nickname); + opts.publicKeyRing.addCopayer( + opts.privateKey.deriveBIP45Branch().extendedPublicKeyString(), + opts.nickname); this.log('\t### PublicKeyRing Initialized'); opts.txProposals = opts.txProposals || new TxProposals({ From 56f4c32646fb0eec29238d44d0e38df702c39c6d Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Thu, 29 May 2014 14:02:52 -0300 Subject: [PATCH 2/6] fix tests --- js/models/core/PublicKeyRing.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/js/models/core/PublicKeyRing.js b/js/models/core/PublicKeyRing.js index 14ae83add..76edc40e1 100644 --- a/js/models/core/PublicKeyRing.js +++ b/js/models/core/PublicKeyRing.js @@ -157,6 +157,10 @@ PublicKeyRing.prototype.addCopayer = function(newEpk, nickname) { throw new Error('PKR already has that key'); }); + if (!newEpk) { + newEpk = this._newExtendedPublicKey(); + } + var i = this.copayersHK.length; var bip = new HK(newEpk); this.copayersHK.push(bip); From 4cd90c45a28eaa01198030622bc3897706530e7d Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Thu, 29 May 2014 16:17:17 -0300 Subject: [PATCH 3/6] fixing tests --- js/models/core/PrivateKey.js | 3 ++- js/models/core/PublicKeyRing.js | 4 +++- test/test.TxProposals.js | 4 ++-- test/test.Wallet.js | 1 + 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/js/models/core/PrivateKey.js b/js/models/core/PrivateKey.js index 110dca65b..f1cee7f48 100644 --- a/js/models/core/PrivateKey.js +++ b/js/models/core/PrivateKey.js @@ -7,7 +7,7 @@ var HK = bitcore.HierarchicalKey; var WalletKey = bitcore.WalletKey; var networks = bitcore.networks; var util = bitcore.util; -var PublicKeyRing = require('./PublicKeyRing'); +var PublicKeyRing = require('./PublicKeyRing'); function PrivateKey(opts) { opts = opts || {}; @@ -62,6 +62,7 @@ PrivateKey.prototype._getHK = function(path) { }; PrivateKey.prototype.get = function(index,isChange) { + console.log(PublicKeyRing); var path = PublicKeyRing.FullBranch(index, isChange); var pk = this.privateKeyCache[path]; if (!pk) { diff --git a/js/models/core/PublicKeyRing.js b/js/models/core/PublicKeyRing.js index 76edc40e1..2dd7e62ba 100644 --- a/js/models/core/PublicKeyRing.js +++ b/js/models/core/PublicKeyRing.js @@ -5,6 +5,7 @@ var imports = require('soop').imports(); var bitcore = require('bitcore'); var HK = bitcore.HierarchicalKey; +var PrivateKey = require('./PrivateKey'); var Address = bitcore.Address; var Script = bitcore.Script; var coinUtil = bitcore.util; @@ -127,7 +128,8 @@ PublicKeyRing.prototype._checkKeys = function() { }; PublicKeyRing.prototype._newExtendedPublicKey = function () { - return new HK(this.network.name) + return new PrivateKey({networkName: this.network.name}) + .deriveBIP45Branch() .extendedPublicKeyString(); }; diff --git a/test/test.TxProposals.js b/test/test.TxProposals.js index 1d76b1bae..41ecc2002 100644 --- a/test/test.TxProposals.js +++ b/test/test.TxProposals.js @@ -42,7 +42,7 @@ var createPKR = function (bip32s) { for(var i=0; i<5; i++) { if (bip32s) { var b=bip32s[i]; - w.addCopayer(b?b.getExtendedPublicKeyString():null); + w.addCopayer(b?b.deriveBIP45Branch().extendedPublicKeyString():null); } else w.addCopayer(); @@ -72,7 +72,7 @@ describe('TxProposals model', function() { var priv = new PrivateKey(config); var priv2 = new PrivateKey(config); var priv3 = new PrivateKey(config); - var ts = Date.now(); + var ts = Date.now(); var isChange=0; var index=0; var pkr = createPKR([priv, priv2, priv3]); diff --git a/test/test.Wallet.js b/test/test.Wallet.js index 53a235fe9..fd1c2fe50 100644 --- a/test/test.Wallet.js +++ b/test/test.Wallet.js @@ -132,6 +132,7 @@ describe('Wallet model', function() { ); var t = w.txProposals; + console.log(t); var k = Object.keys(t.txps)[0]; var tx = t.txps[k].builder.build(); should.exist(tx); From f13dea2376d7a44052541f2102514c9202c9529e Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Thu, 29 May 2014 17:18:55 -0300 Subject: [PATCH 4/6] fix tests --- copay.js | 1 + js/models/core/PrivateKey.js | 11 +++++----- js/models/core/PublicKeyRing.js | 39 +++------------------------------ js/models/core/Wallet.js | 2 +- test/test.PrivateKey.js | 4 ++-- test/test.Wallet.js | 20 ++++++++--------- 6 files changed, 22 insertions(+), 55 deletions(-) diff --git a/copay.js b/copay.js index 8f127e2d9..9149fa071 100644 --- a/copay.js +++ b/copay.js @@ -4,6 +4,7 @@ module.exports.PublicKeyRing = require('./js/models/core/PublicKeyRing'); module.exports.TxProposals = require('./js/models/core/TxProposals'); module.exports.PrivateKey = require('./js/models/core/PrivateKey'); module.exports.Passphrase = require('./js/models/core/Passphrase'); +module.exports.Structure = require('./js/models/core/Structure'); // components diff --git a/js/models/core/PrivateKey.js b/js/models/core/PrivateKey.js index f1cee7f48..086f2561b 100644 --- a/js/models/core/PrivateKey.js +++ b/js/models/core/PrivateKey.js @@ -3,11 +3,11 @@ var imports = require('soop').imports(); var bitcore = require('bitcore'); -var HK = bitcore.HierarchicalKey; +var HK = bitcore.HierarchicalKey; var WalletKey = bitcore.WalletKey; var networks = bitcore.networks; var util = bitcore.util; -var PublicKeyRing = require('./PublicKeyRing'); +var Structure = require('./Structure'); function PrivateKey(opts) { opts = opts || {}; @@ -20,7 +20,7 @@ function PrivateKey(opts) { PrivateKey.prototype.getId = function() { if (!this.id) { - var path = PublicKeyRing.IdFullBranch(); + var path = Structure.IdFullBranch; var idhk = this.bip.derive(path); this.id= idhk.eckey.public.toString('hex'); } @@ -29,7 +29,7 @@ PrivateKey.prototype.getId = function() { PrivateKey.prototype.deriveBIP45Branch = function() { if (!this.bip45Branch) { - this.bip45Branch = this.bip.derive(PublicKeyRing.BIP45_PUBLIC_PREFIX); + this.bip45Branch = this.bip.derive(Structure.BIP45_PUBLIC_PREFIX); } return this.bip45Branch; } @@ -62,8 +62,7 @@ PrivateKey.prototype._getHK = function(path) { }; PrivateKey.prototype.get = function(index,isChange) { - console.log(PublicKeyRing); - var path = PublicKeyRing.FullBranch(index, isChange); + var path = Structure.FullBranch(index, isChange); var pk = this.privateKeyCache[path]; if (!pk) { var derivedHK = this._getHK(path); diff --git a/js/models/core/PublicKeyRing.js b/js/models/core/PublicKeyRing.js index 2dd7e62ba..12a5317bd 100644 --- a/js/models/core/PublicKeyRing.js +++ b/js/models/core/PublicKeyRing.js @@ -6,6 +6,7 @@ var imports = require('soop').imports(); var bitcore = require('bitcore'); var HK = bitcore.HierarchicalKey; var PrivateKey = require('./PrivateKey'); +var Structure = require('./Structure'); var Address = bitcore.Address; var Script = bitcore.Script; var coinUtil = bitcore.util; @@ -37,40 +38,6 @@ function PublicKeyRing(opts) { this.copayerIds = []; } - -/* - * Based on https://github.com/maraoz/bips/blob/master/bip-NNNN.mediawiki - * m / purpose' / cosigner_index / change / address_index - */ -var PURPOSE = 45; -var MAX_NON_HARDENED = 0x8000000 - 1; - -var SHARED_INDEX = MAX_NON_HARDENED - 0; -var ID_INDEX = MAX_NON_HARDENED - 1; - -var BIP45_PUBLIC_PREFIX = 'm/'+ PURPOSE+'\''; -PublicKeyRing.BIP45_PUBLIC_PREFIX = BIP45_PUBLIC_PREFIX; - - -PublicKeyRing.Branch = function(address_index, isChange, cosigner_index) { - var ret = 'm/'+ - (typeof cosigner_index !== 'undefined'? cosigner_index: SHARED_INDEX)+'/'+ - (isChange?1:0)+'/'+ - address_index; - return ret; -}; - -PublicKeyRing.FullBranch = function(address_index, isChange, cosigner_index) { - var sub = PublicKeyRing.Branch(address_index, isChange, cosigner_index); - sub = sub.substring(2); - return BIP45_PUBLIC_PREFIX + '/' + sub; -}; -PublicKeyRing.IdFullBranch = function() { - return PublicKeyRing.FullBranch(0, 0, ID_INDEX); -}; - - - PublicKeyRing.fromObj = function (data) { if (data instanceof PublicKeyRing) { throw new Error('bad data format: Did you use .toObj()?'); @@ -134,7 +101,7 @@ PublicKeyRing.prototype._newExtendedPublicKey = function () { }; PublicKeyRing.prototype._updateBip = function (index) { - var hk = this.copayersHK[index].derive(PublicKeyRing.Branch(0, 0, ID_INDEX)); + var hk = this.copayersHK[index].derive(Structure.IdBranch); this.copayerIds[index]= hk.eckey.public.toString('hex'); }; @@ -176,7 +143,7 @@ PublicKeyRing.prototype.addCopayer = function(newEpk, nickname) { PublicKeyRing.prototype.getPubKeys = function(index, isChange) { this._checkKeys(); - var path = PublicKeyRing.Branch(index, isChange); + var path = Structure.Branch(index, isChange); var pubKeys = this.publicKeysCache[path]; if (!pubKeys) { pubKeys = []; diff --git a/js/models/core/Wallet.js b/js/models/core/Wallet.js index 1893c6acc..7ffbfa58b 100644 --- a/js/models/core/Wallet.js +++ b/js/models/core/Wallet.js @@ -628,7 +628,7 @@ Wallet.prototype.createTxSync = function(toAddress, amountSatStr, utxos, opts) { var signRet; if (priv) { - b.sign(priv.getAll(pkr.addressIndex, pkr.changeAddressIndex)); + var signed = b.sign(priv.getAll(pkr.addressIndex, pkr.changeAddressIndex)); } var myId = this.getMyCopayerId(); var now = Date.now(); diff --git a/test/test.PrivateKey.js b/test/test.PrivateKey.js index 15edb360e..0bfb820c8 100644 --- a/test/test.PrivateKey.js +++ b/test/test.PrivateKey.js @@ -28,10 +28,10 @@ describe('PrivateKey model', function() { }); it('should derive priv keys', function () { - var w = new PrivateKey(config); + var pk = new PrivateKey(config); for(var j=0; j<2; j++) { for(var i=0; i<3; i++) { - var wk = w.get(i,j); + var wk = pk.get(i,j); should.exist(wk); var o=wk.storeObj(); should.exist(o); diff --git a/test/test.Wallet.js b/test/test.Wallet.js index fd1c2fe50..1bcd60c2a 100644 --- a/test/test.Wallet.js +++ b/test/test.Wallet.js @@ -42,7 +42,8 @@ describe('Wallet model', function() { requiredCopayers: c.requiredCopayers, totalCopayers: c.totalCopayers, }); - c.publicKeyRing.addCopayer(c.privateKey.getExtendedPublicKeyString()); + var copayerEPK = c.privateKey.deriveBIP45Branch().extendedPublicKeyString() + c.publicKeyRing.addCopayer(copayerEPK); c.txProposals = new copay.TxProposals({ networkName: c.networkName, @@ -102,10 +103,10 @@ describe('Wallet model', function() { for(var i=0; i<4; i++) { if (privateKeys) { var k=privateKeys[i]; - pkr.addCopayer(k?k.getExtendedPublicKeyString():null); - } - else + pkr.addCopayer(k?k.deriveBIP45Branch().extendedPublicKeyString():null); + } else { pkr.addCopayer(); + } } pkr.generateAddress(true); pkr.generateAddress(true); @@ -125,20 +126,19 @@ describe('Wallet model', function() { unspentTest[0].address = w.publicKeyRing.getAddress(1, true).toString(); unspentTest[0].scriptPubKey = w.publicKeyRing.getScriptPubKeyHex(1, true); - w.createTxSync( + var ntxid = w.createTxSync( '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', '123456789', unspentTest ); var t = w.txProposals; - console.log(t); - var k = Object.keys(t.txps)[0]; - var tx = t.txps[k].builder.build(); + var txp = t.txps[ntxid]; + var tx = txp.builder.build(); should.exist(tx); tx.isComplete().should.equal(false); - Object.keys(t.txps[k].signedBy).length.should.equal(1); - Object.keys(t.txps[k].seenBy).length.should.equal(1); + Object.keys(txp.seenBy).length.should.equal(1); + Object.keys(txp.signedBy).length.should.equal(1); }); it('#addressIsOwn', function () { From 6a0d5ce89a15fbb595b64a58103ba143b784f7dd Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Thu, 29 May 2014 17:19:14 -0300 Subject: [PATCH 5/6] Add structure --- js/models/core/Structure.js | 40 +++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 js/models/core/Structure.js diff --git a/js/models/core/Structure.js b/js/models/core/Structure.js new file mode 100644 index 000000000..eaedb88e7 --- /dev/null +++ b/js/models/core/Structure.js @@ -0,0 +1,40 @@ +'use strict'; + + +var imports = require('soop').imports(); + +function Structure() { +} + + +/* + * Based on https://github.com/maraoz/bips/blob/master/bip-NNNN.mediawiki + * m / purpose' / cosigner_index / change / address_index + */ +var PURPOSE = 45; +var MAX_NON_HARDENED = 0x8000000 - 1; + +var SHARED_INDEX = MAX_NON_HARDENED - 0; +var ID_INDEX = MAX_NON_HARDENED - 1; + +var BIP45_PUBLIC_PREFIX = 'm/'+ PURPOSE+'\''; +Structure.BIP45_PUBLIC_PREFIX = BIP45_PUBLIC_PREFIX; + +Structure.Branch = function(address_index, isChange, cosigner_index) { + var ret = 'm/'+ + (typeof cosigner_index !== 'undefined'? cosigner_index: SHARED_INDEX)+'/'+ + (isChange?1:0)+'/'+ + address_index; + return ret; +}; + +Structure.FullBranch = function(address_index, isChange, cosigner_index) { + var sub = Structure.Branch(address_index, isChange, cosigner_index); + sub = sub.substring(2); + return BIP45_PUBLIC_PREFIX + '/' + sub; +}; +Structure.IdFullBranch = Structure.FullBranch(0, 0, ID_INDEX); +Structure.IdBranch = Structure.Branch(0, 0, ID_INDEX); + + +module.exports = require('soop')(Structure); From 7dcc8f8b34722e4c881704c36f4e07a2aa559bb2 Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Fri, 30 May 2014 10:29:51 -0300 Subject: [PATCH 6/6] minor fix and tests --- js/models/core/Structure.js | 7 +++++-- test/test.Structure.js | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 test/test.Structure.js diff --git a/js/models/core/Structure.js b/js/models/core/Structure.js index eaedb88e7..591360815 100644 --- a/js/models/core/Structure.js +++ b/js/models/core/Structure.js @@ -12,7 +12,7 @@ function Structure() { * m / purpose' / cosigner_index / change / address_index */ var PURPOSE = 45; -var MAX_NON_HARDENED = 0x8000000 - 1; +var MAX_NON_HARDENED = 0x80000000 - 1; var SHARED_INDEX = MAX_NON_HARDENED - 0; var ID_INDEX = MAX_NON_HARDENED - 1; @@ -35,6 +35,9 @@ Structure.FullBranch = function(address_index, isChange, cosigner_index) { }; Structure.IdFullBranch = Structure.FullBranch(0, 0, ID_INDEX); Structure.IdBranch = Structure.Branch(0, 0, ID_INDEX); - +Structure.PURPOSE = PURPOSE; +Structure.MAX_NON_HARDENED = MAX_NON_HARDENED; +Structure.SHARED_INDEX = SHARED_INDEX; +Structure.ID_INDEX = ID_INDEX; module.exports = require('soop')(Structure); diff --git a/test/test.Structure.js b/test/test.Structure.js new file mode 100644 index 000000000..722497ab0 --- /dev/null +++ b/test/test.Structure.js @@ -0,0 +1,37 @@ +'use strict'; + +var chai = chai || require('chai'); +var should = chai.should(); +var bitcore = bitcore || require('bitcore'); +var copay = copay || require('../copay'); +var Structure = require('../js/models/core/Structure'); + +describe('Structure model', function() { + it('should have the correct constants', function () { + Structure.MAX_NON_HARDENED.should.equal(Math.pow(2,31) - 1); + Structure.SHARED_INDEX.should.equal(Structure.MAX_NON_HARDENED); + Structure.ID_INDEX.should.equal(Structure.SHARED_INDEX - 1); + Structure.IdFullBranch.should.equal('m/45\'/2147483646/0/0'); + }); + + it('should get the correct branches', function () { + // shared branch (no cosigner index specified) + Structure.FullBranch(0,false).should.equal('m/45\'/2147483647/0/0'); + + // copayer 0, address 0, external address (receiving) + Structure.FullBranch(0,false,0).should.equal('m/45\'/0/0/0'); + + // copayer 0, address 10, external address (receiving) + Structure.FullBranch(0,false,10).should.equal('m/45\'/10/0/0'); + + // copayer 0, address 0, internal address (change) + Structure.FullBranch(0,true,0).should.equal('m/45\'/0/1/0'); + + // copayer 0, address 10, internal address (change) + Structure.FullBranch(10,true,0).should.equal('m/45\'/0/1/10'); + + // copayer 7, address 10, internal address (change) + Structure.FullBranch(10,true,7).should.equal('m/45\'/7/1/10'); + }); + +});