From 2e56a782bd3dfccdb6d1cb3a12ee32fa96fb6975 Mon Sep 17 00:00:00 2001 From: Yemel Jardi Date: Fri, 27 Jun 2014 15:06:39 -0300 Subject: [PATCH 01/10] Add cosigner index to AddressIndex --- js/models/core/AddressIndex.js | 12 +++++++++--- test/test.AddressIndex.js | 21 ++++++++++++++++++++- test/test.WalletFactory.js | 3 +-- 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/js/models/core/AddressIndex.js b/js/models/core/AddressIndex.js index 7920b44a2..f5532905c 100644 --- a/js/models/core/AddressIndex.js +++ b/js/models/core/AddressIndex.js @@ -1,11 +1,12 @@ 'use strict'; - var imports = require('soop').imports(); +var preconditions = require('preconditions').singleton(); function AddressIndex(opts) { opts = opts || {}; this.walletId = opts.walletId; + this.cosigner = opts.cosigner || 0; this.changeIndex = opts.changeIndex || 0; this.receiveIndex = opts.receiveIndex || 0; @@ -22,8 +23,9 @@ AddressIndex.fromObj = function(data) { AddressIndex.prototype.toObj = function() { return { walletId: this.walletId, + cosigner: this.cosigner, changeIndex: this.changeIndex, - receiveIndex: this.receiveIndex, + receiveIndex: this.receiveIndex }; }; @@ -34,10 +36,10 @@ AddressIndex.prototype.checkRange = function(index, isChange) { } }; - AddressIndex.prototype.getChangeIndex = function() { return this.changeIndex; }; + AddressIndex.prototype.getReceiveIndex = function() { return this.receiveIndex; }; @@ -51,6 +53,10 @@ AddressIndex.prototype.increment = function(isChange) { }; AddressIndex.prototype.merge = function(inAddressIndex) { + preconditions.shouldBeObject(inAddressIndex) + .checkArgument(this.walletId == inAddressIndex.walletId) + .checkArgument(this.cosigner == inAddressIndex.cosigner); + var hasChanged = false; // Indexes diff --git a/test/test.AddressIndex.js b/test/test.AddressIndex.js index 7b1acc513..ccb08ff96 100644 --- a/test/test.AddressIndex.js +++ b/test/test.AddressIndex.js @@ -23,6 +23,7 @@ var createAI = function() { should.exist(i); i.walletId = '1234567'; + i.cosigner = 1; return i; }; @@ -34,7 +35,7 @@ describe('AddressIndex model', function() { should.exist(i); }); - it('show be able to tostore and read', function() { + it('show be able to store and read', function() { var i = createAI(); var changeN = 2; var addressN = 2; @@ -50,6 +51,7 @@ describe('AddressIndex model', function() { var i2 = AddressIndex.fromObj(data); i2.walletId.should.equal(i.walletId); + i2.cosigner.should.equal(i.cosigner); i2.getChangeIndex().should.equal(changeN); i2.getReceiveIndex().should.equal(addressN); @@ -75,6 +77,7 @@ describe('AddressIndex model', function() { j.increment(false); var j2 = new AddressIndex({ walletId: j.walletId, + cosigner: j.cosigner, }); j2.merge(j).should.equal(true); j2.changeIndex.should.equal(15); @@ -83,4 +86,20 @@ describe('AddressIndex model', function() { j2.merge(j).should.equal(false); }); + it('#merge should fail with different walletId', function() { + var j1 = new AddressIndex({ walletId: '1234' }); + var j2 = new AddressIndex({ walletId: '4321' }); + + var merge = function() { j2.merge(j1); }; + merge.should.throw(Error); + }) + + it('#merge should fail with different cosigner index', function() { + var j1 = new AddressIndex({ walletId: '1234', cosigner: 2 }); + var j2 = new AddressIndex({ walletId: '1234', cosigner: 3 }); + + var merge = function() { j2.merge(j1); }; + merge.should.throw(Error); + }) + }); diff --git a/test/test.WalletFactory.js b/test/test.WalletFactory.js index 3042e5775..d240acace 100644 --- a/test/test.WalletFactory.js +++ b/test/test.WalletFactory.js @@ -10,7 +10,7 @@ var FakeBlockchain = require('./mocks/FakeBlockchain'); var FakeStorage = require('./mocks/FakeStorage'); var WalletFactory = require('../js/models/core/WalletFactory'); -var o = '{"opts":{"id":"dbfe10c3fae71cea","spendUnconfirmed":1,"requiredCopayers":3,"totalCopayers":5,"version":"0.0.5"},"publicKeyRing":{"walletId":"dbfe10c3fae71cea","networkName":"testnet","requiredCopayers":3,"totalCopayers":5,"indexes":{"changeIndex":0,"receiveIndex":0},"copayersExtPubKeys":["tpubD6NzVbkrYhZ4YGK8ZhZ8WVeBXNAAoTYjjpw9twCPiNGrGQYFktP3iVQkKmZNiFnUcAFMJRxJVJF6Nq9MDv2kiRceExJaHFbxUCGUiRhmy97","tpubD6NzVbkrYhZ4YKGDJkzWdQsQV3AcFemaQKiwNhV4RL8FHnBFvinidGdQtP8RKj3h34E65RkdtxjrggZYqsEwJ8RhhN2zz9VrjLnrnwbXYNc","tpubD6NzVbkrYhZ4YkDiewjb32Pp3Sz9WK2jpp37KnL7RCrHAyPpnLfgdfRnTdpn6DTWmPS7niywfgWiT42aJb1J6CjWVNmkgsMCxuw7j9DaGKB","tpubD6NzVbkrYhZ4XEtUAz4UUTWbprewbLTaMhR8NUvSJUEAh4Sidxr6rRPFdqqVRR73btKf13wUjds2i8vVCNo8sbKrAnyoTr3o5Y6QSbboQjk","tpubD6NzVbkrYhZ4Yj9AAt6xUVuGPVd8jXCrEE6V2wp7U3PFh8jYYvVad31b4VUXEYXzSnkco4fktu8r4icBsB2t3pCR3WnhVLedY2hxGcPFLKD"],"nicknameFor":{},"publicKeysCache":{"m/0/1/0":["0314368b8efa07e8c7dad30498d0a7e3aa575db1fef833347c6d381c1a33a17b17","02cfd95f89ab46bd3bd86954dd9f83dbab0cd2e4466dee587e8e4d8d733fc0d748","02568969eb6212fe946450be6c5b3353fc754a40b2cdc4aed501a8976fec371da8","0360f870a088ae0ef1c37035a9b6a462ca8dcdd5da275f4e2dcd19f44b81d3e7e4","0300ad8f1bded838b02e127bb25961fbcee718db2df81f680f889692acdcbdd73d"],"m/0/1/1":["024f97a9adb2fa9306c4e3d9244f5e5355c7e2c6b3dd4122ba804e17dc9729df5d","0214834a5adcbc4ad0f3bbbc1c280b8ac480387fcc9a1fd988c1526ed496d923c4","024e72338bd5e976375d076bd71a9649e9141b4cbfc9e16cb7109b354b3e913a05","0322045ea35c3118aa7ab9f2c9f182b0120956b0aa65cc72b9d093f145327a4b17","030dc2450c72df366c1960739c577a2efd4451070bd78effcb6f71d1bcd7dfc7a8"],"m/0/1/2":["0247de59deb66783b8f9b0c326234a9569d00866c2a73f599e77a4d0cab5cbce8f","0376e49f0ac3647404034aae0dc8dd927c34a634ef24ea36f56a272f75fce9539b","032fbaa2593bd1eea4a46e7ac15f15802cdd1eb65a7d5bc4364ddd9d52f0838234","03a81f2a7e1f7191aa0b0c6e0a4ccefc71edd3564e86014972fe338045f68d5a5a","02eb8a012ea9a709392502cacda6ef5115d6d2319ab470d546d9068ab941621a99"],"m/0/0/0":["036dcbd378b4352120d6b720b6294dd2d0dd02801fcf010bb69dadbec1f3999279","022089eedb85dc45d1efa418e1ea226588deedebc1d85acca15ff72783e33636c0","0388aa5fd432b74c56427396f350d236c3ca8f7b2f62da513ce4c2e6ff04a67e9c","02fc4caa7449db7483d2e1fccdacac6fa2f736278c758af9966402589b5632f13e","02e4a15b885d8b2d586f82fa85d16179644e60a154674bde0ec3004810b1bdab99"],"m/0/0/1":["039afa26b2f341c76c7b3c3d0672438f35ac6ebb67b1ddfefac9cd79b7b24418c1","021acaaf500d431ebc396f50630767b01c91ce98ae48e968775ceaad932b7e3b8e","022a947259c4a9f76d5e95c0849df31d01233df41d0d75d631b89317a48d8cddce","03d38d9f94217da780303d9a8987c86d737ef39683febc0cd6632cddbfa62186fd","0394d2581b307fe2af19721888d922aab58ab198ef88cedf9506177e30d807811e"],"m/0/0/2":["037825ffce15d34f9bd6c02bcda7701826706471a4d6ab5004eb965f98811c2098","023768dd6d3c71b7df5733ccda5b2d8b454d5b4c4179d91a6fda74db8b869a2406","021a79e91f003f308764d43039e9b5d56bc8f33ca2f4d30ec6cc5a37c0d09dc273","02437f1e388b273936319f79a5d22958ef5ebff9c8cd7b6f6f72518445b1e30867","0373b0881cb4fd02baa62589023fdfe9739c6148cf104d907549f2528eb80146f5"]}},"txProposals":{"txps":[],"walletId":"dbfe10c3fae71cea","networkName":"testnet"},"privateKey":{"extendedPrivateKeyString":"tprv8ZgxMBicQKsPeoHLg3tY75z4xLeEe8MqAXLNcRA6J6UTRvHV8VZTXznt9eoTmSk1fwSrwZtMhY3XkNsceJ14h6sCXHSWinRqMSSbY8tfhHi","networkName":"testnet","privateKeyCache":{}},"addressBook":{},"backupOffered":false}'; +var o = '{"opts":{"id":"dbfe10c3fae71cea","spendUnconfirmed":1,"requiredCopayers":3,"totalCopayers":5,"version":"0.0.5"},"publicKeyRing":{"walletId":"dbfe10c3fae71cea","networkName":"testnet","requiredCopayers":3,"totalCopayers":5,"indexes":{"cosigner":2,"changeIndex":0,"receiveIndex":0},"copayersExtPubKeys":["tpubD6NzVbkrYhZ4YGK8ZhZ8WVeBXNAAoTYjjpw9twCPiNGrGQYFktP3iVQkKmZNiFnUcAFMJRxJVJF6Nq9MDv2kiRceExJaHFbxUCGUiRhmy97","tpubD6NzVbkrYhZ4YKGDJkzWdQsQV3AcFemaQKiwNhV4RL8FHnBFvinidGdQtP8RKj3h34E65RkdtxjrggZYqsEwJ8RhhN2zz9VrjLnrnwbXYNc","tpubD6NzVbkrYhZ4YkDiewjb32Pp3Sz9WK2jpp37KnL7RCrHAyPpnLfgdfRnTdpn6DTWmPS7niywfgWiT42aJb1J6CjWVNmkgsMCxuw7j9DaGKB","tpubD6NzVbkrYhZ4XEtUAz4UUTWbprewbLTaMhR8NUvSJUEAh4Sidxr6rRPFdqqVRR73btKf13wUjds2i8vVCNo8sbKrAnyoTr3o5Y6QSbboQjk","tpubD6NzVbkrYhZ4Yj9AAt6xUVuGPVd8jXCrEE6V2wp7U3PFh8jYYvVad31b4VUXEYXzSnkco4fktu8r4icBsB2t3pCR3WnhVLedY2hxGcPFLKD"],"nicknameFor":{},"publicKeysCache":{"m/0/1/0":["0314368b8efa07e8c7dad30498d0a7e3aa575db1fef833347c6d381c1a33a17b17","02cfd95f89ab46bd3bd86954dd9f83dbab0cd2e4466dee587e8e4d8d733fc0d748","02568969eb6212fe946450be6c5b3353fc754a40b2cdc4aed501a8976fec371da8","0360f870a088ae0ef1c37035a9b6a462ca8dcdd5da275f4e2dcd19f44b81d3e7e4","0300ad8f1bded838b02e127bb25961fbcee718db2df81f680f889692acdcbdd73d"],"m/0/1/1":["024f97a9adb2fa9306c4e3d9244f5e5355c7e2c6b3dd4122ba804e17dc9729df5d","0214834a5adcbc4ad0f3bbbc1c280b8ac480387fcc9a1fd988c1526ed496d923c4","024e72338bd5e976375d076bd71a9649e9141b4cbfc9e16cb7109b354b3e913a05","0322045ea35c3118aa7ab9f2c9f182b0120956b0aa65cc72b9d093f145327a4b17","030dc2450c72df366c1960739c577a2efd4451070bd78effcb6f71d1bcd7dfc7a8"],"m/0/1/2":["0247de59deb66783b8f9b0c326234a9569d00866c2a73f599e77a4d0cab5cbce8f","0376e49f0ac3647404034aae0dc8dd927c34a634ef24ea36f56a272f75fce9539b","032fbaa2593bd1eea4a46e7ac15f15802cdd1eb65a7d5bc4364ddd9d52f0838234","03a81f2a7e1f7191aa0b0c6e0a4ccefc71edd3564e86014972fe338045f68d5a5a","02eb8a012ea9a709392502cacda6ef5115d6d2319ab470d546d9068ab941621a99"],"m/0/0/0":["036dcbd378b4352120d6b720b6294dd2d0dd02801fcf010bb69dadbec1f3999279","022089eedb85dc45d1efa418e1ea226588deedebc1d85acca15ff72783e33636c0","0388aa5fd432b74c56427396f350d236c3ca8f7b2f62da513ce4c2e6ff04a67e9c","02fc4caa7449db7483d2e1fccdacac6fa2f736278c758af9966402589b5632f13e","02e4a15b885d8b2d586f82fa85d16179644e60a154674bde0ec3004810b1bdab99"],"m/0/0/1":["039afa26b2f341c76c7b3c3d0672438f35ac6ebb67b1ddfefac9cd79b7b24418c1","021acaaf500d431ebc396f50630767b01c91ce98ae48e968775ceaad932b7e3b8e","022a947259c4a9f76d5e95c0849df31d01233df41d0d75d631b89317a48d8cddce","03d38d9f94217da780303d9a8987c86d737ef39683febc0cd6632cddbfa62186fd","0394d2581b307fe2af19721888d922aab58ab198ef88cedf9506177e30d807811e"],"m/0/0/2":["037825ffce15d34f9bd6c02bcda7701826706471a4d6ab5004eb965f98811c2098","023768dd6d3c71b7df5733ccda5b2d8b454d5b4c4179d91a6fda74db8b869a2406","021a79e91f003f308764d43039e9b5d56bc8f33ca2f4d30ec6cc5a37c0d09dc273","02437f1e388b273936319f79a5d22958ef5ebff9c8cd7b6f6f72518445b1e30867","0373b0881cb4fd02baa62589023fdfe9739c6148cf104d907549f2528eb80146f5"]}},"txProposals":{"txps":[],"walletId":"dbfe10c3fae71cea","networkName":"testnet"},"privateKey":{"extendedPrivateKeyString":"tprv8ZgxMBicQKsPeoHLg3tY75z4xLeEe8MqAXLNcRA6J6UTRvHV8VZTXznt9eoTmSk1fwSrwZtMhY3XkNsceJ14h6sCXHSWinRqMSSbY8tfhHi","networkName":"testnet","privateKeyCache":{}},"addressBook":{},"backupOffered":false}'; describe('WalletFactory model', function() { var config = { @@ -82,7 +82,6 @@ describe('WalletFactory model', function() { }); it('#fromObj #toObj round trip', function() { - var wf = new WalletFactory(config, '0.0.5'); var w = wf.fromObj(JSON.parse(o)); From e9f20b5de6fa05952d2770ea280643b1e94b2738 Mon Sep 17 00:00:00 2001 From: Yemel Jardi Date: Tue, 1 Jul 2014 09:41:28 -0300 Subject: [PATCH 02/10] Change PublicKeyRing index to array of AddressIndex --- js/models/core/AddressIndex.js | 14 ++++---- js/models/core/PublicKeyRing.js | 59 +++++++++++++++++++++++++-------- js/models/core/Wallet.js | 17 +++++----- test/test.AddressIndex.js | 11 ------ test/test.PublicKeyRing.js | 17 ++++++---- test/test.TxProposals.js | 4 +-- test/test.Wallet.js | 27 ++++++++------- test/test.WalletFactory.js | 18 +++++++++- 8 files changed, 105 insertions(+), 62 deletions(-) diff --git a/js/models/core/AddressIndex.js b/js/models/core/AddressIndex.js index f5532905c..bfc9b6464 100644 --- a/js/models/core/AddressIndex.js +++ b/js/models/core/AddressIndex.js @@ -2,27 +2,28 @@ var imports = require('soop').imports(); var preconditions = require('preconditions').singleton(); +var Structure = require('./Structure'); function AddressIndex(opts) { opts = opts || {}; - this.walletId = opts.walletId; - this.cosigner = opts.cosigner || 0; - + this.cosigner = opts.cosigner || Structure.SHARED_INDEX; this.changeIndex = opts.changeIndex || 0; this.receiveIndex = opts.receiveIndex || 0; } +AddressIndex.fromList = function(indexes) { + return indexes.map(function(i) { return AddressIndex.fromObj(i); }); +} + AddressIndex.fromObj = function(data) { if (data instanceof AddressIndex) { throw new Error('bad data format: Did you use .toObj()?'); } - var ret = new AddressIndex(data); - return ret; + return new AddressIndex(data); }; AddressIndex.prototype.toObj = function() { return { - walletId: this.walletId, cosigner: this.cosigner, changeIndex: this.changeIndex, receiveIndex: this.receiveIndex @@ -54,7 +55,6 @@ AddressIndex.prototype.increment = function(isChange) { AddressIndex.prototype.merge = function(inAddressIndex) { preconditions.shouldBeObject(inAddressIndex) - .checkArgument(this.walletId == inAddressIndex.walletId) .checkArgument(this.cosigner == inAddressIndex.cosigner); var hasChanged = false; diff --git a/js/models/core/PublicKeyRing.js b/js/models/core/PublicKeyRing.js index e05fa8049..f9e608afb 100644 --- a/js/models/core/PublicKeyRing.js +++ b/js/models/core/PublicKeyRing.js @@ -24,7 +24,7 @@ function PublicKeyRing(opts) { this.copayersHK = opts.copayersHK || []; - this.indexes = AddressIndex.fromObj(opts.indexes) || new AddressIndex(opts); + this.indexes = opts.indexes ? AddressIndex.fromList(opts.indexes) : [new AddressIndex()]; this.publicKeysCache = opts.publicKeysCache || {}; this.nicknameFor = opts.nicknameFor || {}; @@ -36,6 +36,13 @@ PublicKeyRing.fromObj = function(data) { if (data instanceof PublicKeyRing) { throw new Error('bad data format: Did you use .toObj()?'); } + + // Support old indexes schema + if (!Array.isArray(data.indexes)) { + data.indexes.cosigner = Structure.SHARED_INDEX; + data.indexes = [data.indexes]; + } + var ret = new PublicKeyRing(data); for (var k in data.copayersExtPubKeys) { @@ -51,7 +58,7 @@ PublicKeyRing.prototype.toObj = function() { networkName: this.network.name, requiredCopayers: this.requiredCopayers, totalCopayers: this.totalCopayers, - indexes: this.indexes.toObj(), + indexes: this.getIndexesObj(), copayersExtPubKeys: this.copayersHK.map(function(b) { return b.extendedPublicKeyString(); @@ -61,6 +68,10 @@ PublicKeyRing.prototype.toObj = function() { }; }; +PublicKeyRing.prototype.getIndexesObj = function(i) { + return this.indexes.map(function(i) { return i.toObj(); }); +} + PublicKeyRing.prototype.getCopayerId = function(i) { preconditions.checkArgument(typeof i !== 'undefined'); return this.copayerIds[i]; @@ -176,6 +187,16 @@ PublicKeyRing.prototype.getAddress = function(index, isChange) { return address; }; +PublicKeyRing.prototype.getSharedIndex = function() { + return this.getIndex(Structure.SHARED_INDEX); +}; + +PublicKeyRing.prototype.getIndex = function(cosigner) { + var index = this.indexes.filter(function(i) { return i.cosigner == cosigner }); + if (index.length != 1) throw new Error('no index for cosigner'); + return index[0]; +}; + PublicKeyRing.prototype.pathForAddress = function(address) { var path = this.addressToPath[address]; if (!path) throw new Error('Couldn\'t find path for address ' + address); @@ -191,9 +212,10 @@ PublicKeyRing.prototype.getScriptPubKeyHex = function(index, isChange) { //generate a new address, update index. PublicKeyRing.prototype.generateAddress = function(isChange) { isChange = !!isChange; - var index = isChange ? this.indexes.getChangeIndex() : this.indexes.getReceiveIndex(); + var shared = this.getIndex(Structure.SHARED_INDEX); + var index = isChange ? shared.getChangeIndex() : shared.getReceiveIndex(); var ret = this.getAddress(index, isChange); - this.indexes.increment(isChange); + shared.increment(isChange); return ret; }; @@ -206,9 +228,10 @@ PublicKeyRing.prototype.getAddresses = function(opts) { PublicKeyRing.prototype.getAddressesInfo = function(opts) { opts = opts || {}; + var shared = this.getIndex(Structure.SHARED_INDEX); var ret = []; if (!opts.excludeChange) { - for (var i = 0; i < this.indexes.getChangeIndex(); i++) { + for (var i = 0; i < shared.getChangeIndex(); i++) { var a = this.getAddress(i, true); ret.unshift({ address: this.getAddress(i, true), @@ -219,7 +242,7 @@ PublicKeyRing.prototype.getAddressesInfo = function(opts) { } if (!opts.excludeMain) { - for (var i = 0; i < this.indexes.getReceiveIndex(); i++) { + for (var i = 0; i < shared.getReceiveIndex(); i++) { var a = this.getAddress(i, false); ret.unshift({ address: a, @@ -303,17 +326,25 @@ PublicKeyRing.prototype._mergePubkeys = function(inPKR) { }; PublicKeyRing.prototype.merge = function(inPKR, ignoreId) { - var hasChanged = false; - this._checkInPKR(inPKR, ignoreId); - if (this.indexes.merge(inPKR.indexes)) - hasChanged = true; + var hasChanged = false; + hasChanged |= this.mergeIndexes(inPKR.indexes); + hasChanged |= this._mergePubkeys(inPKR); - if (this._mergePubkeys(inPKR)) - hasChanged = true; - - return hasChanged; + return !!hasChanged; }; +PublicKeyRing.prototype.mergeIndexes = function(indexes) { + var self = this; + var hasChanged = false; + + indexes.forEach(function(theirs) { + var mine = self.getIndex(theirs.cosigner); + hasChanged |= mine.merge(theirs); + }); + + return !!hasChanged +} + module.exports = require('soop')(PublicKeyRing); diff --git a/js/models/core/Wallet.js b/js/models/core/Wallet.js index fec67735b..20e5d1b1f 100644 --- a/js/models/core/Wallet.js +++ b/js/models/core/Wallet.js @@ -81,8 +81,8 @@ Wallet.prototype.connectToAll = function() { Wallet.prototype._handleIndexes = function(senderId, data, isInbound) { this.log('RECV INDEXES:', data); - var inIndexes = AddressIndex.fromObj(data.indexes); - var hasChanged = this.publicKeyRing.indexes.merge(inIndexes); + var inIndexes = AddressIndex.fromList(data.indexes); + var hasChanged = this.publicKeyRing.mergeIndexes(inIndexes); if (hasChanged) { this.emit('publicKeyRingUpdated'); this.store(); @@ -439,11 +439,11 @@ Wallet.prototype.sendPublicKeyRing = function(recipients) { }); }; Wallet.prototype.sendIndexes = function(recipients) { - this.log('### INDEXES TO:', recipients || 'All', this.publicKeyRing.indexes.toObj()); + this.log('### INDEXES TO:', recipients || 'All', this.publicKeyRing.getIndexesObj()); this.network.send(recipients, { type: 'indexes', - indexes: this.publicKeyRing.indexes.toObj(), + indexes: this.publicKeyRing.getIndexesObj(), walletId: this.id, }); }; @@ -752,20 +752,21 @@ Wallet.prototype.createTxSync = function(toAddress, amountSatStr, comment, utxos return ntxid; }; +// TODO: Updetear todos los indices Wallet.prototype.updateIndexes = function(callback) { var self = this; - var start = self.publicKeyRing.indexes.changeIndex; + var start = self.publicKeyRing.getSharedIndex().changeIndex; self.log('Updating indexes...'); self.indexDiscovery(start, true, 20, function(err, changeIndex) { if (err) return callback(err); if (changeIndex != -1) - self.publicKeyRing.indexes.changeIndex = changeIndex + 1; + self.publicKeyRing.getSharedIndex().changeIndex = changeIndex + 1; - start = self.publicKeyRing.indexes.receiveIndex; + start = self.publicKeyRing.getSharedIndex().receiveIndex; self.indexDiscovery(start, false, 20, function(err, receiveIndex) { if (err) return callback(err); if (receiveIndex != -1) - self.publicKeyRing.indexes.receiveIndex = receiveIndex + 1; + self.publicKeyRing.getSharedIndex().receiveIndex = receiveIndex + 1; self.log('Indexes updated'); self.emit('publicKeyRingUpdated'); diff --git a/test/test.AddressIndex.js b/test/test.AddressIndex.js index ccb08ff96..767041529 100644 --- a/test/test.AddressIndex.js +++ b/test/test.AddressIndex.js @@ -22,7 +22,6 @@ var createAI = function() { var i = new AddressIndex(); should.exist(i); - i.walletId = '1234567'; i.cosigner = 1; return i; @@ -50,7 +49,6 @@ describe('AddressIndex model', function() { should.exist(data); var i2 = AddressIndex.fromObj(data); - i2.walletId.should.equal(i.walletId); i2.cosigner.should.equal(i.cosigner); i2.getChangeIndex().should.equal(changeN); @@ -76,7 +74,6 @@ describe('AddressIndex model', function() { for (var i = 0; i < 7; i++) j.increment(false); var j2 = new AddressIndex({ - walletId: j.walletId, cosigner: j.cosigner, }); j2.merge(j).should.equal(true); @@ -86,14 +83,6 @@ describe('AddressIndex model', function() { j2.merge(j).should.equal(false); }); - it('#merge should fail with different walletId', function() { - var j1 = new AddressIndex({ walletId: '1234' }); - var j2 = new AddressIndex({ walletId: '4321' }); - - var merge = function() { j2.merge(j1); }; - merge.should.throw(Error); - }) - it('#merge should fail with different cosigner index', function() { var j1 = new AddressIndex({ walletId: '1234', cosigner: 2 }); var j2 = new AddressIndex({ walletId: '1234', cosigner: 3 }); diff --git a/test/test.PublicKeyRing.js b/test/test.PublicKeyRing.js index b2405a161..c60aa8b01 100644 --- a/test/test.PublicKeyRing.js +++ b/test/test.PublicKeyRing.js @@ -5,6 +5,9 @@ var should = chai.should(); var bitcore = bitcore || require('bitcore'); var Address = bitcore.Address; var buffertools = bitcore.buffertools; + +var Structure = require('../js/models/core/Structure'); + try { var copay = require('copay'); //browser } catch (e) { @@ -85,7 +88,7 @@ describe('PublicKeyRing model', function() { } }); - it('show be able to tostore and read', function() { + it('show be able to to store and read', function() { var k = createW(); var w = k.w; var copayers = k.copayers; @@ -112,8 +115,8 @@ describe('PublicKeyRing model', function() { }).should.throw(); } - w2.indexes.getChangeIndex().should.equal(changeN); - w2.indexes.getReceiveIndex().should.equal(addressN); + w2.getSharedIndex().getChangeIndex().should.equal(changeN); + w2.getSharedIndex().getReceiveIndex().should.equal(addressN); }); @@ -168,8 +171,8 @@ describe('PublicKeyRing model', function() { for (var i = 0; i < 2; i++) w.generateAddress(false); - w.indexes.getChangeIndex().should.equal(3); - w.indexes.getReceiveIndex().should.equal(2); + w.getSharedIndex().getChangeIndex().should.equal(3); + w.getSharedIndex().getReceiveIndex().should.equal(2); }); it('#merge index tests', function() { @@ -188,8 +191,8 @@ describe('PublicKeyRing model', function() { w2.merge(w).should.equal(true); w2.requiredCopayers.should.equal(3); w2.totalCopayers.should.equal(5); - w2.indexes.getChangeIndex().should.equal(2); - w2.indexes.getReceiveIndex().should.equal(3); + w2.getSharedIndex().getChangeIndex().should.equal(2); + w2.getSharedIndex().getReceiveIndex().should.equal(3); // w2.merge(w).should.equal(false); diff --git a/test/test.TxProposals.js b/test/test.TxProposals.js index 30615a990..b0aa3a622 100644 --- a/test/test.TxProposals.js +++ b/test/test.TxProposals.js @@ -102,8 +102,8 @@ describe('TxProposals model', function() { var b = w.txps[ntxid].builder; var tx = b.build(); tx.isComplete().should.equal(false); - b.sign(priv2.getAll(pkr.indexes.getReceiveIndex(), pkr.indexes.getChangeIndex())); - b.sign(priv3.getAll(pkr.indexes.getReceiveIndex(), pkr.indexes.getChangeIndex())); + b.sign(priv2.getAll(pkr.getSharedIndex().getReceiveIndex(), pkr.getSharedIndex().getChangeIndex())); + b.sign(priv3.getAll(pkr.getSharedIndex().getReceiveIndex(), pkr.getSharedIndex().getChangeIndex())); tx = b.build(); tx.isComplete().should.equal(true); diff --git a/test/test.Wallet.js b/test/test.Wallet.js index 20dd4b6ba..3e392833c 100644 --- a/test/test.Wallet.js +++ b/test/test.Wallet.js @@ -9,6 +9,7 @@ try { var copay = require('../copay'); //node } var Wallet = require('../js/models/core/Wallet'); +var Structure = require('../js/models/core/Structure'); var Storage = require('./mocks/FakeStorage'); var Network = require('./mocks/FakeNetwork'); var Blockchain = require('./mocks/FakeBlockchain'); @@ -341,13 +342,15 @@ describe('Wallet model', function() { it('handle network indexes correctly', function() { var w = createW(); var aiObj = { - walletId: w.id, - changeIndex: 3, - receiveIndex: 2 + indexes: [{ + cosigner: Structure.SHARED_INDEX, + changeIndex: 3, + receiveIndex: 2 + }] }; w._handleIndexes('senderID', aiObj, true); - w.publicKeyRing.indexes.getReceiveIndex(2); - w.publicKeyRing.indexes.getChangeIndex(3); + w.publicKeyRing.getSharedIndex().getReceiveIndex(2); + w.publicKeyRing.getSharedIndex().getChangeIndex(3); }); it('handle network pubKeyRings correctly', function() { @@ -363,19 +366,19 @@ describe('Wallet model', function() { networkName: w.networkName, requiredCopayers: w.requiredCopayers, totalCopayers: w.totalCopayers, - indexes: { - walletId: undefined, + indexes: [{ + cosigner: Structure.SHARED_INDEX, changeIndex: 2, receiveIndex: 3 - }, + }], copayersExtPubKeys: cepk, nicknameFor: {}, }; w._handlePublicKeyRing('senderID', { publicKeyRing: pkrObj }, true); - w.publicKeyRing.indexes.getReceiveIndex(2); - w.publicKeyRing.indexes.getChangeIndex(3); + w.publicKeyRing.getSharedIndex().getReceiveIndex(2); + w.publicKeyRing.getSharedIndex().getChangeIndex(3); for (var i = 0; i < w.requiredCopayers; i++) { w.publicKeyRing.toObj().copayersExtPubKeys[i].should.equal(cepk[i]); } @@ -729,8 +732,8 @@ describe('Wallet model', function() { }); w.updateIndexes(function(err) { - w.publicKeyRing.indexes.receiveIndex.should.equal(15); - w.publicKeyRing.indexes.changeIndex.should.equal(15); + w.publicKeyRing.getSharedIndex().receiveIndex.should.equal(15); + w.publicKeyRing.getSharedIndex().changeIndex.should.equal(15); done(); }); }); diff --git a/test/test.WalletFactory.js b/test/test.WalletFactory.js index d240acace..f57b740c7 100644 --- a/test/test.WalletFactory.js +++ b/test/test.WalletFactory.js @@ -10,7 +10,7 @@ var FakeBlockchain = require('./mocks/FakeBlockchain'); var FakeStorage = require('./mocks/FakeStorage'); var WalletFactory = require('../js/models/core/WalletFactory'); -var o = '{"opts":{"id":"dbfe10c3fae71cea","spendUnconfirmed":1,"requiredCopayers":3,"totalCopayers":5,"version":"0.0.5"},"publicKeyRing":{"walletId":"dbfe10c3fae71cea","networkName":"testnet","requiredCopayers":3,"totalCopayers":5,"indexes":{"cosigner":2,"changeIndex":0,"receiveIndex":0},"copayersExtPubKeys":["tpubD6NzVbkrYhZ4YGK8ZhZ8WVeBXNAAoTYjjpw9twCPiNGrGQYFktP3iVQkKmZNiFnUcAFMJRxJVJF6Nq9MDv2kiRceExJaHFbxUCGUiRhmy97","tpubD6NzVbkrYhZ4YKGDJkzWdQsQV3AcFemaQKiwNhV4RL8FHnBFvinidGdQtP8RKj3h34E65RkdtxjrggZYqsEwJ8RhhN2zz9VrjLnrnwbXYNc","tpubD6NzVbkrYhZ4YkDiewjb32Pp3Sz9WK2jpp37KnL7RCrHAyPpnLfgdfRnTdpn6DTWmPS7niywfgWiT42aJb1J6CjWVNmkgsMCxuw7j9DaGKB","tpubD6NzVbkrYhZ4XEtUAz4UUTWbprewbLTaMhR8NUvSJUEAh4Sidxr6rRPFdqqVRR73btKf13wUjds2i8vVCNo8sbKrAnyoTr3o5Y6QSbboQjk","tpubD6NzVbkrYhZ4Yj9AAt6xUVuGPVd8jXCrEE6V2wp7U3PFh8jYYvVad31b4VUXEYXzSnkco4fktu8r4icBsB2t3pCR3WnhVLedY2hxGcPFLKD"],"nicknameFor":{},"publicKeysCache":{"m/0/1/0":["0314368b8efa07e8c7dad30498d0a7e3aa575db1fef833347c6d381c1a33a17b17","02cfd95f89ab46bd3bd86954dd9f83dbab0cd2e4466dee587e8e4d8d733fc0d748","02568969eb6212fe946450be6c5b3353fc754a40b2cdc4aed501a8976fec371da8","0360f870a088ae0ef1c37035a9b6a462ca8dcdd5da275f4e2dcd19f44b81d3e7e4","0300ad8f1bded838b02e127bb25961fbcee718db2df81f680f889692acdcbdd73d"],"m/0/1/1":["024f97a9adb2fa9306c4e3d9244f5e5355c7e2c6b3dd4122ba804e17dc9729df5d","0214834a5adcbc4ad0f3bbbc1c280b8ac480387fcc9a1fd988c1526ed496d923c4","024e72338bd5e976375d076bd71a9649e9141b4cbfc9e16cb7109b354b3e913a05","0322045ea35c3118aa7ab9f2c9f182b0120956b0aa65cc72b9d093f145327a4b17","030dc2450c72df366c1960739c577a2efd4451070bd78effcb6f71d1bcd7dfc7a8"],"m/0/1/2":["0247de59deb66783b8f9b0c326234a9569d00866c2a73f599e77a4d0cab5cbce8f","0376e49f0ac3647404034aae0dc8dd927c34a634ef24ea36f56a272f75fce9539b","032fbaa2593bd1eea4a46e7ac15f15802cdd1eb65a7d5bc4364ddd9d52f0838234","03a81f2a7e1f7191aa0b0c6e0a4ccefc71edd3564e86014972fe338045f68d5a5a","02eb8a012ea9a709392502cacda6ef5115d6d2319ab470d546d9068ab941621a99"],"m/0/0/0":["036dcbd378b4352120d6b720b6294dd2d0dd02801fcf010bb69dadbec1f3999279","022089eedb85dc45d1efa418e1ea226588deedebc1d85acca15ff72783e33636c0","0388aa5fd432b74c56427396f350d236c3ca8f7b2f62da513ce4c2e6ff04a67e9c","02fc4caa7449db7483d2e1fccdacac6fa2f736278c758af9966402589b5632f13e","02e4a15b885d8b2d586f82fa85d16179644e60a154674bde0ec3004810b1bdab99"],"m/0/0/1":["039afa26b2f341c76c7b3c3d0672438f35ac6ebb67b1ddfefac9cd79b7b24418c1","021acaaf500d431ebc396f50630767b01c91ce98ae48e968775ceaad932b7e3b8e","022a947259c4a9f76d5e95c0849df31d01233df41d0d75d631b89317a48d8cddce","03d38d9f94217da780303d9a8987c86d737ef39683febc0cd6632cddbfa62186fd","0394d2581b307fe2af19721888d922aab58ab198ef88cedf9506177e30d807811e"],"m/0/0/2":["037825ffce15d34f9bd6c02bcda7701826706471a4d6ab5004eb965f98811c2098","023768dd6d3c71b7df5733ccda5b2d8b454d5b4c4179d91a6fda74db8b869a2406","021a79e91f003f308764d43039e9b5d56bc8f33ca2f4d30ec6cc5a37c0d09dc273","02437f1e388b273936319f79a5d22958ef5ebff9c8cd7b6f6f72518445b1e30867","0373b0881cb4fd02baa62589023fdfe9739c6148cf104d907549f2528eb80146f5"]}},"txProposals":{"txps":[],"walletId":"dbfe10c3fae71cea","networkName":"testnet"},"privateKey":{"extendedPrivateKeyString":"tprv8ZgxMBicQKsPeoHLg3tY75z4xLeEe8MqAXLNcRA6J6UTRvHV8VZTXznt9eoTmSk1fwSrwZtMhY3XkNsceJ14h6sCXHSWinRqMSSbY8tfhHi","networkName":"testnet","privateKeyCache":{}},"addressBook":{},"backupOffered":false}'; +var o = '{"opts":{"id":"dbfe10c3fae71cea","spendUnconfirmed":1,"requiredCopayers":3,"totalCopayers":5,"version":"0.0.5"},"publicKeyRing":{"walletId":"dbfe10c3fae71cea","networkName":"testnet","requiredCopayers":3,"totalCopayers":5,"indexes":[{"cosigner":2,"changeIndex":0,"receiveIndex":0}],"copayersExtPubKeys":["tpubD6NzVbkrYhZ4YGK8ZhZ8WVeBXNAAoTYjjpw9twCPiNGrGQYFktP3iVQkKmZNiFnUcAFMJRxJVJF6Nq9MDv2kiRceExJaHFbxUCGUiRhmy97","tpubD6NzVbkrYhZ4YKGDJkzWdQsQV3AcFemaQKiwNhV4RL8FHnBFvinidGdQtP8RKj3h34E65RkdtxjrggZYqsEwJ8RhhN2zz9VrjLnrnwbXYNc","tpubD6NzVbkrYhZ4YkDiewjb32Pp3Sz9WK2jpp37KnL7RCrHAyPpnLfgdfRnTdpn6DTWmPS7niywfgWiT42aJb1J6CjWVNmkgsMCxuw7j9DaGKB","tpubD6NzVbkrYhZ4XEtUAz4UUTWbprewbLTaMhR8NUvSJUEAh4Sidxr6rRPFdqqVRR73btKf13wUjds2i8vVCNo8sbKrAnyoTr3o5Y6QSbboQjk","tpubD6NzVbkrYhZ4Yj9AAt6xUVuGPVd8jXCrEE6V2wp7U3PFh8jYYvVad31b4VUXEYXzSnkco4fktu8r4icBsB2t3pCR3WnhVLedY2hxGcPFLKD"],"nicknameFor":{},"publicKeysCache":{"m/0/1/0":["0314368b8efa07e8c7dad30498d0a7e3aa575db1fef833347c6d381c1a33a17b17","02cfd95f89ab46bd3bd86954dd9f83dbab0cd2e4466dee587e8e4d8d733fc0d748","02568969eb6212fe946450be6c5b3353fc754a40b2cdc4aed501a8976fec371da8","0360f870a088ae0ef1c37035a9b6a462ca8dcdd5da275f4e2dcd19f44b81d3e7e4","0300ad8f1bded838b02e127bb25961fbcee718db2df81f680f889692acdcbdd73d"],"m/0/1/1":["024f97a9adb2fa9306c4e3d9244f5e5355c7e2c6b3dd4122ba804e17dc9729df5d","0214834a5adcbc4ad0f3bbbc1c280b8ac480387fcc9a1fd988c1526ed496d923c4","024e72338bd5e976375d076bd71a9649e9141b4cbfc9e16cb7109b354b3e913a05","0322045ea35c3118aa7ab9f2c9f182b0120956b0aa65cc72b9d093f145327a4b17","030dc2450c72df366c1960739c577a2efd4451070bd78effcb6f71d1bcd7dfc7a8"],"m/0/1/2":["0247de59deb66783b8f9b0c326234a9569d00866c2a73f599e77a4d0cab5cbce8f","0376e49f0ac3647404034aae0dc8dd927c34a634ef24ea36f56a272f75fce9539b","032fbaa2593bd1eea4a46e7ac15f15802cdd1eb65a7d5bc4364ddd9d52f0838234","03a81f2a7e1f7191aa0b0c6e0a4ccefc71edd3564e86014972fe338045f68d5a5a","02eb8a012ea9a709392502cacda6ef5115d6d2319ab470d546d9068ab941621a99"],"m/0/0/0":["036dcbd378b4352120d6b720b6294dd2d0dd02801fcf010bb69dadbec1f3999279","022089eedb85dc45d1efa418e1ea226588deedebc1d85acca15ff72783e33636c0","0388aa5fd432b74c56427396f350d236c3ca8f7b2f62da513ce4c2e6ff04a67e9c","02fc4caa7449db7483d2e1fccdacac6fa2f736278c758af9966402589b5632f13e","02e4a15b885d8b2d586f82fa85d16179644e60a154674bde0ec3004810b1bdab99"],"m/0/0/1":["039afa26b2f341c76c7b3c3d0672438f35ac6ebb67b1ddfefac9cd79b7b24418c1","021acaaf500d431ebc396f50630767b01c91ce98ae48e968775ceaad932b7e3b8e","022a947259c4a9f76d5e95c0849df31d01233df41d0d75d631b89317a48d8cddce","03d38d9f94217da780303d9a8987c86d737ef39683febc0cd6632cddbfa62186fd","0394d2581b307fe2af19721888d922aab58ab198ef88cedf9506177e30d807811e"],"m/0/0/2":["037825ffce15d34f9bd6c02bcda7701826706471a4d6ab5004eb965f98811c2098","023768dd6d3c71b7df5733ccda5b2d8b454d5b4c4179d91a6fda74db8b869a2406","021a79e91f003f308764d43039e9b5d56bc8f33ca2f4d30ec6cc5a37c0d09dc273","02437f1e388b273936319f79a5d22958ef5ebff9c8cd7b6f6f72518445b1e30867","0373b0881cb4fd02baa62589023fdfe9739c6148cf104d907549f2528eb80146f5"]}},"txProposals":{"txps":[],"walletId":"dbfe10c3fae71cea","networkName":"testnet"},"privateKey":{"extendedPrivateKeyString":"tprv8ZgxMBicQKsPeoHLg3tY75z4xLeEe8MqAXLNcRA6J6UTRvHV8VZTXznt9eoTmSk1fwSrwZtMhY3XkNsceJ14h6sCXHSWinRqMSSbY8tfhHi","networkName":"testnet","privateKeyCache":{}},"addressBook":{},"backupOffered":false}'; describe('WalletFactory model', function() { var config = { @@ -94,6 +94,22 @@ describe('WalletFactory model', function() { JSON.stringify(w.toObj()).should.equal(o); }); + it('support old index schema: #fromObj #toObj round trip', function() { + var o = '{"opts":{"id":"dbfe10c3fae71cea","spendUnconfirmed":1,"requiredCopayers":3,"totalCopayers":5,"version":"0.0.5"},"publicKeyRing":{"walletId":"dbfe10c3fae71cea","networkName":"testnet","requiredCopayers":3,"totalCopayers":5,"indexes":{"changeIndex":0,"receiveIndex":0},"copayersExtPubKeys":["tpubD6NzVbkrYhZ4YGK8ZhZ8WVeBXNAAoTYjjpw9twCPiNGrGQYFktP3iVQkKmZNiFnUcAFMJRxJVJF6Nq9MDv2kiRceExJaHFbxUCGUiRhmy97","tpubD6NzVbkrYhZ4YKGDJkzWdQsQV3AcFemaQKiwNhV4RL8FHnBFvinidGdQtP8RKj3h34E65RkdtxjrggZYqsEwJ8RhhN2zz9VrjLnrnwbXYNc","tpubD6NzVbkrYhZ4YkDiewjb32Pp3Sz9WK2jpp37KnL7RCrHAyPpnLfgdfRnTdpn6DTWmPS7niywfgWiT42aJb1J6CjWVNmkgsMCxuw7j9DaGKB","tpubD6NzVbkrYhZ4XEtUAz4UUTWbprewbLTaMhR8NUvSJUEAh4Sidxr6rRPFdqqVRR73btKf13wUjds2i8vVCNo8sbKrAnyoTr3o5Y6QSbboQjk","tpubD6NzVbkrYhZ4Yj9AAt6xUVuGPVd8jXCrEE6V2wp7U3PFh8jYYvVad31b4VUXEYXzSnkco4fktu8r4icBsB2t3pCR3WnhVLedY2hxGcPFLKD"],"nicknameFor":{},"publicKeysCache":{"m/0/1/0":["0314368b8efa07e8c7dad30498d0a7e3aa575db1fef833347c6d381c1a33a17b17","02cfd95f89ab46bd3bd86954dd9f83dbab0cd2e4466dee587e8e4d8d733fc0d748","02568969eb6212fe946450be6c5b3353fc754a40b2cdc4aed501a8976fec371da8","0360f870a088ae0ef1c37035a9b6a462ca8dcdd5da275f4e2dcd19f44b81d3e7e4","0300ad8f1bded838b02e127bb25961fbcee718db2df81f680f889692acdcbdd73d"],"m/0/1/1":["024f97a9adb2fa9306c4e3d9244f5e5355c7e2c6b3dd4122ba804e17dc9729df5d","0214834a5adcbc4ad0f3bbbc1c280b8ac480387fcc9a1fd988c1526ed496d923c4","024e72338bd5e976375d076bd71a9649e9141b4cbfc9e16cb7109b354b3e913a05","0322045ea35c3118aa7ab9f2c9f182b0120956b0aa65cc72b9d093f145327a4b17","030dc2450c72df366c1960739c577a2efd4451070bd78effcb6f71d1bcd7dfc7a8"],"m/0/1/2":["0247de59deb66783b8f9b0c326234a9569d00866c2a73f599e77a4d0cab5cbce8f","0376e49f0ac3647404034aae0dc8dd927c34a634ef24ea36f56a272f75fce9539b","032fbaa2593bd1eea4a46e7ac15f15802cdd1eb65a7d5bc4364ddd9d52f0838234","03a81f2a7e1f7191aa0b0c6e0a4ccefc71edd3564e86014972fe338045f68d5a5a","02eb8a012ea9a709392502cacda6ef5115d6d2319ab470d546d9068ab941621a99"],"m/0/0/0":["036dcbd378b4352120d6b720b6294dd2d0dd02801fcf010bb69dadbec1f3999279","022089eedb85dc45d1efa418e1ea226588deedebc1d85acca15ff72783e33636c0","0388aa5fd432b74c56427396f350d236c3ca8f7b2f62da513ce4c2e6ff04a67e9c","02fc4caa7449db7483d2e1fccdacac6fa2f736278c758af9966402589b5632f13e","02e4a15b885d8b2d586f82fa85d16179644e60a154674bde0ec3004810b1bdab99"],"m/0/0/1":["039afa26b2f341c76c7b3c3d0672438f35ac6ebb67b1ddfefac9cd79b7b24418c1","021acaaf500d431ebc396f50630767b01c91ce98ae48e968775ceaad932b7e3b8e","022a947259c4a9f76d5e95c0849df31d01233df41d0d75d631b89317a48d8cddce","03d38d9f94217da780303d9a8987c86d737ef39683febc0cd6632cddbfa62186fd","0394d2581b307fe2af19721888d922aab58ab198ef88cedf9506177e30d807811e"],"m/0/0/2":["037825ffce15d34f9bd6c02bcda7701826706471a4d6ab5004eb965f98811c2098","023768dd6d3c71b7df5733ccda5b2d8b454d5b4c4179d91a6fda74db8b869a2406","021a79e91f003f308764d43039e9b5d56bc8f33ca2f4d30ec6cc5a37c0d09dc273","02437f1e388b273936319f79a5d22958ef5ebff9c8cd7b6f6f72518445b1e30867","0373b0881cb4fd02baa62589023fdfe9739c6148cf104d907549f2528eb80146f5"]}},"txProposals":{"txps":[],"walletId":"dbfe10c3fae71cea","networkName":"testnet"},"privateKey":{"extendedPrivateKeyString":"tprv8ZgxMBicQKsPeoHLg3tY75z4xLeEe8MqAXLNcRA6J6UTRvHV8VZTXznt9eoTmSk1fwSrwZtMhY3XkNsceJ14h6sCXHSWinRqMSSbY8tfhHi","networkName":"testnet","privateKeyCache":{}},"addressBook":{},"backupOffered":false}'; + var o2 = '{"opts":{"id":"dbfe10c3fae71cea","spendUnconfirmed":1,"requiredCopayers":3,"totalCopayers":5,"version":"0.0.5"},"publicKeyRing":{"walletId":"dbfe10c3fae71cea","networkName":"testnet","requiredCopayers":3,"totalCopayers":5,"indexes":[{"cosigner":2147483647,"changeIndex":0,"receiveIndex":0}],"copayersExtPubKeys":["tpubD6NzVbkrYhZ4YGK8ZhZ8WVeBXNAAoTYjjpw9twCPiNGrGQYFktP3iVQkKmZNiFnUcAFMJRxJVJF6Nq9MDv2kiRceExJaHFbxUCGUiRhmy97","tpubD6NzVbkrYhZ4YKGDJkzWdQsQV3AcFemaQKiwNhV4RL8FHnBFvinidGdQtP8RKj3h34E65RkdtxjrggZYqsEwJ8RhhN2zz9VrjLnrnwbXYNc","tpubD6NzVbkrYhZ4YkDiewjb32Pp3Sz9WK2jpp37KnL7RCrHAyPpnLfgdfRnTdpn6DTWmPS7niywfgWiT42aJb1J6CjWVNmkgsMCxuw7j9DaGKB","tpubD6NzVbkrYhZ4XEtUAz4UUTWbprewbLTaMhR8NUvSJUEAh4Sidxr6rRPFdqqVRR73btKf13wUjds2i8vVCNo8sbKrAnyoTr3o5Y6QSbboQjk","tpubD6NzVbkrYhZ4Yj9AAt6xUVuGPVd8jXCrEE6V2wp7U3PFh8jYYvVad31b4VUXEYXzSnkco4fktu8r4icBsB2t3pCR3WnhVLedY2hxGcPFLKD"],"nicknameFor":{},"publicKeysCache":{"m/0/1/0":["0314368b8efa07e8c7dad30498d0a7e3aa575db1fef833347c6d381c1a33a17b17","02cfd95f89ab46bd3bd86954dd9f83dbab0cd2e4466dee587e8e4d8d733fc0d748","02568969eb6212fe946450be6c5b3353fc754a40b2cdc4aed501a8976fec371da8","0360f870a088ae0ef1c37035a9b6a462ca8dcdd5da275f4e2dcd19f44b81d3e7e4","0300ad8f1bded838b02e127bb25961fbcee718db2df81f680f889692acdcbdd73d"],"m/0/1/1":["024f97a9adb2fa9306c4e3d9244f5e5355c7e2c6b3dd4122ba804e17dc9729df5d","0214834a5adcbc4ad0f3bbbc1c280b8ac480387fcc9a1fd988c1526ed496d923c4","024e72338bd5e976375d076bd71a9649e9141b4cbfc9e16cb7109b354b3e913a05","0322045ea35c3118aa7ab9f2c9f182b0120956b0aa65cc72b9d093f145327a4b17","030dc2450c72df366c1960739c577a2efd4451070bd78effcb6f71d1bcd7dfc7a8"],"m/0/1/2":["0247de59deb66783b8f9b0c326234a9569d00866c2a73f599e77a4d0cab5cbce8f","0376e49f0ac3647404034aae0dc8dd927c34a634ef24ea36f56a272f75fce9539b","032fbaa2593bd1eea4a46e7ac15f15802cdd1eb65a7d5bc4364ddd9d52f0838234","03a81f2a7e1f7191aa0b0c6e0a4ccefc71edd3564e86014972fe338045f68d5a5a","02eb8a012ea9a709392502cacda6ef5115d6d2319ab470d546d9068ab941621a99"],"m/0/0/0":["036dcbd378b4352120d6b720b6294dd2d0dd02801fcf010bb69dadbec1f3999279","022089eedb85dc45d1efa418e1ea226588deedebc1d85acca15ff72783e33636c0","0388aa5fd432b74c56427396f350d236c3ca8f7b2f62da513ce4c2e6ff04a67e9c","02fc4caa7449db7483d2e1fccdacac6fa2f736278c758af9966402589b5632f13e","02e4a15b885d8b2d586f82fa85d16179644e60a154674bde0ec3004810b1bdab99"],"m/0/0/1":["039afa26b2f341c76c7b3c3d0672438f35ac6ebb67b1ddfefac9cd79b7b24418c1","021acaaf500d431ebc396f50630767b01c91ce98ae48e968775ceaad932b7e3b8e","022a947259c4a9f76d5e95c0849df31d01233df41d0d75d631b89317a48d8cddce","03d38d9f94217da780303d9a8987c86d737ef39683febc0cd6632cddbfa62186fd","0394d2581b307fe2af19721888d922aab58ab198ef88cedf9506177e30d807811e"],"m/0/0/2":["037825ffce15d34f9bd6c02bcda7701826706471a4d6ab5004eb965f98811c2098","023768dd6d3c71b7df5733ccda5b2d8b454d5b4c4179d91a6fda74db8b869a2406","021a79e91f003f308764d43039e9b5d56bc8f33ca2f4d30ec6cc5a37c0d09dc273","02437f1e388b273936319f79a5d22958ef5ebff9c8cd7b6f6f72518445b1e30867","0373b0881cb4fd02baa62589023fdfe9739c6148cf104d907549f2528eb80146f5"]}},"txProposals":{"txps":[],"walletId":"dbfe10c3fae71cea","networkName":"testnet"},"privateKey":{"extendedPrivateKeyString":"tprv8ZgxMBicQKsPeoHLg3tY75z4xLeEe8MqAXLNcRA6J6UTRvHV8VZTXznt9eoTmSk1fwSrwZtMhY3XkNsceJ14h6sCXHSWinRqMSSbY8tfhHi","networkName":"testnet","privateKeyCache":{}},"addressBook":{},"backupOffered":false}'; + + var wf = new WalletFactory(config, '0.0.5'); + var w = wf.fromObj(JSON.parse(o)); + + should.exist(w); + w.id.should.equal("dbfe10c3fae71cea"); + should.exist(w.publicKeyRing.getCopayerId); + should.exist(w.txProposals.toObj); + should.exist(w.privateKey.toObj); + + JSON.stringify(w.toObj()).should.equal(o2); + }); + it('should create wallet from encrypted object', function() { var wf = new WalletFactory(config, '0.0.1'); var walletObj = JSON.parse(o); From b02cb1798992d69ab08499e76ff6f8e7d31708a5 Mon Sep 17 00:00:00 2001 From: Yemel Jardi Date: Tue, 1 Jul 2014 12:49:50 -0300 Subject: [PATCH 03/10] Create indexes for all copayers --- js/models/core/AddressIndex.js | 15 ++++++++++++++- js/models/core/PublicKeyRing.js | 3 ++- test/test.AddressIndex.js | 13 +++++++++++++ test/test.PublicKeyRing.js | 23 +++++++++++++++++++++++ 4 files changed, 52 insertions(+), 2 deletions(-) diff --git a/js/models/core/AddressIndex.js b/js/models/core/AddressIndex.js index bfc9b6464..484865b87 100644 --- a/js/models/core/AddressIndex.js +++ b/js/models/core/AddressIndex.js @@ -6,9 +6,22 @@ var Structure = require('./Structure'); function AddressIndex(opts) { opts = opts || {}; - this.cosigner = opts.cosigner || Structure.SHARED_INDEX; + this.cosigner = opts.cosigner this.changeIndex = opts.changeIndex || 0; this.receiveIndex = opts.receiveIndex || 0; + + if (typeof this.cosigner === 'undefined') { + this.cosigner = Structure.SHARED_INDEX; + } +} + +AddressIndex.init = function(totalCopayers) { + preconditions.shouldBeNumber(totalCopayers); + var indexes = [new AddressIndex()]; + for (var i = 0 ; i < totalCopayers ; i++) { + indexes.push(new AddressIndex({cosigner: i})); + } + return indexes; } AddressIndex.fromList = function(indexes) { diff --git a/js/models/core/PublicKeyRing.js b/js/models/core/PublicKeyRing.js index f9e608afb..627706128 100644 --- a/js/models/core/PublicKeyRing.js +++ b/js/models/core/PublicKeyRing.js @@ -24,7 +24,8 @@ function PublicKeyRing(opts) { this.copayersHK = opts.copayersHK || []; - this.indexes = opts.indexes ? AddressIndex.fromList(opts.indexes) : [new AddressIndex()]; + this.indexes = opts.indexes ? AddressIndex.fromList(opts.indexes) + : AddressIndex.init(this.totalCopayers); this.publicKeysCache = opts.publicKeysCache || {}; this.nicknameFor = opts.nicknameFor || {}; diff --git a/test/test.AddressIndex.js b/test/test.AddressIndex.js index 767041529..3d87d9868 100644 --- a/test/test.AddressIndex.js +++ b/test/test.AddressIndex.js @@ -12,6 +12,7 @@ try { } var PublicKeyRing = copay.PublicKeyRing; var AddressIndex = copay.AddressIndex; +var Structure = copay.Structure; var config = { @@ -34,6 +35,18 @@ describe('AddressIndex model', function() { should.exist(i); }); + it('should init indexes', function() { + var is = AddressIndex.init(2); + should.exist(is); + is.length.should.equal(3); + + var cosigners = is.map(function(i) { return i.cosigner; }); + cosigners.indexOf(Structure.SHARED_INDEX).should.not.equal(-1); + cosigners.indexOf(0).should.not.equal(-1); + cosigners.indexOf(1).should.not.equal(-1); + cosigners.indexOf(2).should.equal(-1); + }); + it('show be able to store and read', function() { var i = createAI(); var changeN = 2; diff --git a/test/test.PublicKeyRing.js b/test/test.PublicKeyRing.js index c60aa8b01..0bb2523a5 100644 --- a/test/test.PublicKeyRing.js +++ b/test/test.PublicKeyRing.js @@ -383,6 +383,29 @@ describe('PublicKeyRing model', function() { }); + it('#getIndex should return the right one', function() { + var config = { + networkName: 'livenet', + }; + var p = new PublicKeyRing(config); + var i = p.getIndex(Structure.SHARED_INDEX); + should.exist(i); + i.cosigner.should.equal(Structure.SHARED_INDEX); + var shared = p.getSharedIndex(); + shared.should.equal(i); + }); + + it('#getIndex should throw error', function() { + var config = { + networkName: 'livenet', + }; + var p = new PublicKeyRing(config); + + (function badCosigner() { + return p.getIndex(54); + }).should.throw(); + }); + it('#getRedeemScriptMap check tests', function() { var k = createW(); var w = k.w; From 04b6aa40036d4a4b3eca389451b226983e88ba8a Mon Sep 17 00:00:00 2001 From: Yemel Jardi Date: Thu, 3 Jul 2014 11:18:01 -0300 Subject: [PATCH 04/10] PublicKeyRing handles one index for each cosigner --- js/models/core/PrivateKey.js | 11 +++-- js/models/core/PublicKeyRing.js | 72 +++++++++++++++++++--------- js/models/core/Structure.js | 1 + js/models/core/Wallet.js | 4 +- test/test.PublicKeyRing.js | 39 ++++++++------- test/test.TxProposals.js | 85 ++++++++++++++++++++------------- test/test.Wallet.js | 18 +++---- 7 files changed, 140 insertions(+), 90 deletions(-) diff --git a/js/models/core/PrivateKey.js b/js/models/core/PrivateKey.js index b1149f28b..9abd30e95 100644 --- a/js/models/core/PrivateKey.js +++ b/js/models/core/PrivateKey.js @@ -16,6 +16,7 @@ function PrivateKey(opts) { var init = opts.extendedPrivateKeyString || this.network.name; this.bip = opts.HK || new HK(init); this.privateKeyCache = opts.privateKeyCache || {}; + this.publicHex = this.deriveBIP45Branch().eckey.public.toString('hex'); }; PrivateKey.prototype.getId = function() { @@ -101,21 +102,21 @@ PrivateKey.prototype.getForPath = function(path) { return wk; }; -PrivateKey.prototype.get = function(index, isChange) { - var path = Structure.FullBranch(index, isChange); +PrivateKey.prototype.get = function(index, isChange, cosigner) { + var path = Structure.FullBranch(index, isChange, cosigner); return this.getForPath(path); }; -PrivateKey.prototype.getAll = function(receiveIndex, changeIndex) { +PrivateKey.prototype.getAll = function(receiveIndex, changeIndex, cosigner) { if (typeof receiveIndex === 'undefined' || typeof changeIndex === 'undefined') throw new Error('Invalid parameters'); var ret = []; for (var i = 0; i < receiveIndex; i++) { - ret.push(this.get(i, false)); + ret.push(this.get(i, false, cosigner)); } for (var i = 0; i < changeIndex; i++) { - ret.push(this.get(i, true)); + ret.push(this.get(i, true, cosigner)); } return ret; }; diff --git a/js/models/core/PublicKeyRing.js b/js/models/core/PublicKeyRing.js index 627706128..b82c76365 100644 --- a/js/models/core/PublicKeyRing.js +++ b/js/models/core/PublicKeyRing.js @@ -148,10 +148,10 @@ PublicKeyRing.prototype.addCopayer = function(newEpk, nickname) { return newEpk; }; -PublicKeyRing.prototype.getPubKeys = function(index, isChange) { +PublicKeyRing.prototype.getPubKeys = function(index, isChange, cosigner) { this._checkKeys(); - var path = Structure.Branch(index, isChange); + var path = Structure.Branch(index, isChange, cosigner); var pubKeys = this.publicKeysCache[path]; if (!pubKeys) { pubKeys = []; @@ -174,17 +174,19 @@ PublicKeyRing.prototype.getPubKeys = function(index, isChange) { }; // TODO this could be cached -PublicKeyRing.prototype.getRedeemScript = function(index, isChange) { - var pubKeys = this.getPubKeys(index, isChange); +PublicKeyRing.prototype.getRedeemScript = function(index, isChange, cosigner) { + var pubKeys = this.getPubKeys(index, isChange, cosigner); var script = Script.createMultisig(this.requiredCopayers, pubKeys); return script; }; // TODO this could be cached -PublicKeyRing.prototype.getAddress = function(index, isChange) { - var script = this.getRedeemScript(index, isChange); +PublicKeyRing.prototype.getAddress = function(index, isChange, id) { + var cosigner = typeof id === 'string' ? this.getCosigner(id) : id; + + var script = this.getRedeemScript(index, isChange, cosigner); var address = Address.fromScript(script, this.network.name); - this.addressToPath[address.toString()] = Structure.FullBranch(index, isChange); + this.addressToPath[address.toString()] = Structure.FullBranch(index, isChange, cosigner); return address; }; @@ -192,7 +194,10 @@ PublicKeyRing.prototype.getSharedIndex = function() { return this.getIndex(Structure.SHARED_INDEX); }; -PublicKeyRing.prototype.getIndex = function(cosigner) { +// Overloaded to receive a PubkeyString or a consigner index +PublicKeyRing.prototype.getIndex = function(id) { + var cosigner = typeof id === 'string' ? this.getCosigner(id) : id; + var index = this.indexes.filter(function(i) { return i.cosigner == cosigner }); if (index.length != 1) throw new Error('no index for cosigner'); return index[0]; @@ -205,18 +210,20 @@ PublicKeyRing.prototype.pathForAddress = function(address) { }; // TODO this could be cached -PublicKeyRing.prototype.getScriptPubKeyHex = function(index, isChange) { - var addr = this.getAddress(index, isChange); +PublicKeyRing.prototype.getScriptPubKeyHex = function(index, isChange, pubkey) { + var cosigner = this.getCosigner(pubkey); + var addr = this.getAddress(index, isChange, cosigner); return Script.createP2SH(addr.payload()).getBuffer().toString('hex'); }; //generate a new address, update index. -PublicKeyRing.prototype.generateAddress = function(isChange) { +PublicKeyRing.prototype.generateAddress = function(isChange, pubkey) { isChange = !!isChange; - var shared = this.getIndex(Structure.SHARED_INDEX); - var index = isChange ? shared.getChangeIndex() : shared.getReceiveIndex(); - var ret = this.getAddress(index, isChange); - shared.increment(isChange); + var cosigner = this.getCosigner(pubkey); + var addrIndex = this.getIndex(cosigner); + var index = isChange ? addrIndex.getChangeIndex() : addrIndex.getReceiveIndex(); + var ret = this.getAddress(index, isChange, cosigner); + addrIndex.increment(isChange); return ret; }; @@ -226,16 +233,37 @@ PublicKeyRing.prototype.getAddresses = function(opts) { }); }; +PublicKeyRing.prototype.getCosigner = function(pubKey) { + preconditions.checkArgument(pubKey); + var sorted = this.copayersHK.map(function(h, i){ + return h.eckey.public.toString('hex'); + }).sort(function(h1, h2){ return h1.localeCompare(h2); }); + + var index = sorted.indexOf(pubKey); + if (index == -1) throw new Error('no public key in ring'); + + return index; +} + + PublicKeyRing.prototype.getAddressesInfo = function(opts) { + var ret = []; + var self = this; + this.indexes.forEach(function(index) { + ret = ret.concat(self.getAddressesInfoForIndex(index, opts)); + }); + return ret; +} + +PublicKeyRing.prototype.getAddressesInfoForIndex = function(index, opts) { opts = opts || {}; - var shared = this.getIndex(Structure.SHARED_INDEX); var ret = []; if (!opts.excludeChange) { - for (var i = 0; i < shared.getChangeIndex(); i++) { - var a = this.getAddress(i, true); + for (var i = 0; i < index.changeIndex; i++) { + var a = this.getAddress(i, true, index.cosigner); ret.unshift({ - address: this.getAddress(i, true), + address: a, addressStr: a.toString(), isChange: true }); @@ -243,8 +271,8 @@ PublicKeyRing.prototype.getAddressesInfo = function(opts) { } if (!opts.excludeMain) { - for (var i = 0; i < shared.getReceiveIndex(); i++) { - var a = this.getAddress(i, false); + for (var i = 0; i < index.receiveIndex; i++) { + var a = this.getAddress(i, false, index.cosigner); ret.unshift({ address: a, addressStr: a.toString(), @@ -259,7 +287,7 @@ PublicKeyRing.prototype.getAddressesInfo = function(opts) { // TODO this could be cached PublicKeyRing.prototype._addScriptMap = function(map, path) { var p = Structure.indicesForPath(path); - var script = this.getRedeemScript(p.index, p.isChange); + var script = this.getRedeemScript(p.index, p.isChange, p.cosigner); map[Address.fromScript(script, this.network.name).toString()] = script.getBuffer().toString('hex'); }; diff --git a/js/models/core/Structure.js b/js/models/core/Structure.js index aafee4c0f..ff47c43f0 100644 --- a/js/models/core/Structure.js +++ b/js/models/core/Structure.js @@ -40,6 +40,7 @@ Structure.indicesForPath = function(path) { return { isChange: s[3] === '1', index: parseInt(s[4]), + cosigner: parseInt(s[2]) }; }; diff --git a/js/models/core/Wallet.js b/js/models/core/Wallet.js index 20e5d1b1f..800ef5d8e 100644 --- a/js/models/core/Wallet.js +++ b/js/models/core/Wallet.js @@ -51,6 +51,7 @@ function Wallet(opts) { this.registeredPeerIds = []; this.addressBook = opts.addressBook || {}; this.backupOffered = opts.backupOffered || false; + this.publicKey = this.privateKey.publicHex; } Wallet.parent = EventEmitter; @@ -462,7 +463,7 @@ Wallet.prototype.getName = function() { }; Wallet.prototype._doGenerateAddress = function(isChange) { - return this.publicKeyRing.generateAddress(isChange); + return this.publicKeyRing.generateAddress(isChange, this.publicKey); }; @@ -516,7 +517,6 @@ Wallet.prototype.sign = function(ntxid, cb) { if (cb) cb(false); } - var pkr = self.publicKeyRing; var keys = self.privateKey.getForPaths(txp.inputChainPaths); var b = txp.builder; diff --git a/test/test.PublicKeyRing.js b/test/test.PublicKeyRing.js index 0bb2523a5..11051de07 100644 --- a/test/test.PublicKeyRing.js +++ b/test/test.PublicKeyRing.js @@ -36,7 +36,8 @@ var createW = function(networkName) { return { w: w, - copayers: copayers + copayers: copayers, + pub: w.copayersHK[0].eckey.public.toString('hex') }; }; @@ -88,7 +89,7 @@ describe('PublicKeyRing model', function() { } }); - it('show be able to to store and read', function() { + it('should be able to to store and read', function() { var k = createW(); var w = k.w; var copayers = k.copayers; @@ -96,10 +97,10 @@ describe('PublicKeyRing model', function() { var addressN = 2; var start = new Date().getTime(); for (var i = 0; i < changeN; i++) { - w.generateAddress(true); + w.generateAddress(true, k.pub); } for (var i = 0; i < addressN; i++) { - w.generateAddress(false); + w.generateAddress(false, k.pub); } var data = w.toObj(); @@ -115,8 +116,8 @@ describe('PublicKeyRing model', function() { }).should.throw(); } - w2.getSharedIndex().getChangeIndex().should.equal(changeN); - w2.getSharedIndex().getReceiveIndex().should.equal(addressN); + w2.getIndex(k.pub).getChangeIndex().should.equal(changeN); + w2.getIndex(k.pub).getReceiveIndex().should.equal(addressN); }); @@ -126,7 +127,7 @@ describe('PublicKeyRing model', function() { [true, false].forEach(function(isChange){ for (var i = 0; i < 2; i++) { - var a = w.generateAddress(isChange); + var a = w.generateAddress(isChange, k.pub); a.isValid().should.equal(true); a.isScript().should.equal(true); a.network().name.should.equal('livenet'); @@ -148,7 +149,7 @@ describe('PublicKeyRing model', function() { [true, false].forEach(function(isChange){ for (var i = 0; i < 2; i++) { - w.generateAddress(isChange); + w.generateAddress(isChange, k.pub); } }); @@ -167,12 +168,12 @@ describe('PublicKeyRing model', function() { var w = k.w; for (var i = 0; i < 3; i++) - w.generateAddress(true); + w.generateAddress(true, k.pub); for (var i = 0; i < 2; i++) - w.generateAddress(false); + w.generateAddress(false, k.pub); - w.getSharedIndex().getChangeIndex().should.equal(3); - w.getSharedIndex().getReceiveIndex().should.equal(2); + w.getIndex(k.pub).getChangeIndex().should.equal(3); + w.getIndex(k.pub).getReceiveIndex().should.equal(2); }); it('#merge index tests', function() { @@ -180,9 +181,9 @@ describe('PublicKeyRing model', function() { var w = k.w; for (var i = 0; i < 2; i++) - w.generateAddress(true); + w.generateAddress(true, k.pub); for (var i = 0; i < 3; i++) - w.generateAddress(false); + w.generateAddress(false, k.pub); var w2 = new PublicKeyRing({ networkName: 'livenet', @@ -191,8 +192,8 @@ describe('PublicKeyRing model', function() { w2.merge(w).should.equal(true); w2.requiredCopayers.should.equal(3); w2.totalCopayers.should.equal(5); - w2.getSharedIndex().getChangeIndex().should.equal(2); - w2.getSharedIndex().getReceiveIndex().should.equal(3); + w2.getIndex(k.pub).getChangeIndex().should.equal(2); + w2.getIndex(k.pub).getReceiveIndex().should.equal(3); // w2.merge(w).should.equal(false); @@ -391,8 +392,6 @@ describe('PublicKeyRing model', function() { var i = p.getIndex(Structure.SHARED_INDEX); should.exist(i); i.cosigner.should.equal(Structure.SHARED_INDEX); - var shared = p.getSharedIndex(); - shared.should.equal(i); }); it('#getIndex should throw error', function() { @@ -412,9 +411,9 @@ describe('PublicKeyRing model', function() { var amount = 2; for (var i = 0; i < amount; i++) - w.generateAddress(true); + w.generateAddress(true, k.pub); for (var i = 0; i < amount; i++) - w.generateAddress(false); + w.generateAddress(false, k.pub); var m = w.getRedeemScriptMap([ 'm/45\'/2147483647/1/0', diff --git a/test/test.TxProposals.js b/test/test.TxProposals.js index b0aa3a622..de069446d 100644 --- a/test/test.TxProposals.js +++ b/test/test.TxProposals.js @@ -51,12 +51,15 @@ var createPKR = function(bip32s) { w.addCopayer(); } } - w.generateAddress(false); - w.generateAddress(false); - w.generateAddress(false); - w.generateAddress(true); - w.generateAddress(true); - w.generateAddress(true); + + var pubkey = bip32s[0].publicHex; + + w.generateAddress(false, pubkey); + w.generateAddress(false, pubkey); + w.generateAddress(false, pubkey); + w.generateAddress(true, pubkey); + w.generateAddress(true, pubkey); + w.generateAddress(true, pubkey); return w; }; @@ -77,19 +80,22 @@ describe('TxProposals model', function() { var priv = new PrivateKey(config); var priv2 = new PrivateKey(config); var priv3 = new PrivateKey(config); + var pub = priv.publicHex; + var ts = Date.now(); var pkr = createPKR([priv, priv2, priv3]); var opts = { remainderOut: { - address: pkr.generateAddress(true).toString() + address: pkr.generateAddress(true, pub).toString() } }; var w = new TxProposals({ networkName: config.networkName, }); - unspentTest[0].address = pkr.getAddress(index, isChange).toString(); - unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange); + + unspentTest[0].address = pkr.getAddress(index, isChange, pub).toString(); + unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange, pub); w.add(createTx( '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', '123456789', @@ -102,8 +108,10 @@ describe('TxProposals model', function() { var b = w.txps[ntxid].builder; var tx = b.build(); tx.isComplete().should.equal(false); - b.sign(priv2.getAll(pkr.getSharedIndex().getReceiveIndex(), pkr.getSharedIndex().getChangeIndex())); - b.sign(priv3.getAll(pkr.getSharedIndex().getReceiveIndex(), pkr.getSharedIndex().getChangeIndex())); + + var ringIndex = pkr.getIndex(pub); + b.sign(priv2.getAll(ringIndex.getReceiveIndex(), ringIndex.getChangeIndex(), ringIndex.cosigner)); + b.sign(priv3.getAll(ringIndex.getReceiveIndex(), ringIndex.getChangeIndex(), ringIndex.cosigner)); tx = b.build(); tx.isComplete().should.equal(true); @@ -132,6 +140,7 @@ describe('TxProposals model', function() { opts = opts || {}; var amountSat = bitcore.Bignum(amountSatStr); + var pub = priv.publicHex; if (!pkr.isComplete()) { throw new Error('publicKeyRing is not complete'); @@ -139,7 +148,7 @@ describe('TxProposals model', function() { if (!opts.remainderOut) { opts.remainderOut = { - address: pkr.generateAddress(true).toString() + address: pkr.generateAddress(true, pub).toString() }; }; @@ -181,14 +190,16 @@ describe('TxProposals model', function() { it('#getUsedUnspend', function() { var priv = new PrivateKey(config); + var pub = priv.publicHex; + var w = new TxProposals({ networkName: config.networkName, }); var start = new Date().getTime(); var pkr = createPKR([priv]); var ts = Date.now(); - unspentTest[0].address = pkr.getAddress(index, isChange).toString(); - unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange); + unspentTest[0].address = pkr.getAddress(index, isChange, pub).toString(); + unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange, pub); w.add(createTx( '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', '123456789', @@ -204,6 +215,8 @@ describe('TxProposals model', function() { it('#merge with self', function() { var priv = new PrivateKey(config); + var pub = priv.publicHex; + var w = new TxProposals({ networkName: config.networkName, }); @@ -211,8 +224,8 @@ describe('TxProposals model', function() { var pkr = createPKR([priv]); var ts = Date.now(); - unspentTest[0].address = pkr.getAddress(index, isChange).toString(); - unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange); + unspentTest[0].address = pkr.getAddress(index, isChange, pub).toString(); + unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange, pub); w.add(createTx( '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', '123456789', @@ -246,11 +259,13 @@ describe('TxProposals model', function() { it('#merge, merge signatures case 1', function() { var priv2 = new PrivateKey(config); var priv = new PrivateKey(config); + var pub = priv.publicHex; + var ts = Date.now(); var pkr = createPKR([priv]); var opts = { remainderOut: { - address: pkr.generateAddress(true).toString() + address: pkr.generateAddress(true, pub).toString() } }; @@ -258,8 +273,8 @@ describe('TxProposals model', function() { var w = new TxProposals({ networkName: config.networkName, }); - unspentTest[0].address = pkr.getAddress(index, isChange).toString(); - unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange); + unspentTest[0].address = pkr.getAddress(index, isChange, pub).toString(); + unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange, pub); w.add(createTx( '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', '123456789', @@ -282,8 +297,8 @@ describe('TxProposals model', function() { networkName: config.networkName, publicKeyRing: w.publicKeyRing, }); - unspentTest[0].address = pkr.getAddress(index, isChange).toString(); - unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange); + unspentTest[0].address = pkr.getAddress(index, isChange, pub).toString(); + unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange, pub); w2.add(createTx( '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', '123456789', @@ -346,6 +361,7 @@ describe('TxProposals model', function() { var priv = PrivateKey.fromObj(o1); var priv2 = PrivateKey.fromObj(o2); var priv3 = PrivateKey.fromObj(o3); + var pub = priv.publicHex; var ts = Date.now(); var pkr = createPKR([priv, priv2]); @@ -354,9 +370,9 @@ describe('TxProposals model', function() { address: '2MxK2m7cPtEwjZBB8Ksq7ppjkgJyFPJGemr' } }; - var addressToSign = pkr.generateAddress(false); + var addressToSign = pkr.generateAddress(false, pub); unspentTest[0].address = addressToSign.toString(); - unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange); + unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange, pub); var tx, txb; var w = new TxProposals({ @@ -459,19 +475,22 @@ describe('TxProposals model', function() { var priv = new PrivateKey(config); var priv2 = new PrivateKey(config); var priv3 = new PrivateKey(config); + var pub = priv.publicHex; + + var ts = Date.now(); var pkr = createPKR([priv, priv2, priv3]); var opts = { remainderOut: { - address: pkr.generateAddress(true).toString() + address: pkr.generateAddress(true, pub).toString() } }; var w = new TxProposals({ networkName: config.networkName, }); - unspentTest[0].address = pkr.getAddress(index, isChange).toString(); - unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange); + unspentTest[0].address = pkr.getAddress(index, isChange, pub).toString(); + unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange, pub); w.add(createTx( '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', '123456789', @@ -491,8 +510,8 @@ describe('TxProposals model', function() { var w2 = new TxProposals({ networkName: config.networkName, }); - unspentTest[0].address = pkr.getAddress(index, isChange).toString(); - unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange); + unspentTest[0].address = pkr.getAddress(index, isChange, pub).toString(); + unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange, pub); w2.add(createTx( '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', '123456789', @@ -511,8 +530,8 @@ describe('TxProposals model', function() { var w3 = new TxProposals({ networkName: config.networkName, }); - unspentTest[0].address = pkr.getAddress(index, isChange).toString(); - unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange); + unspentTest[0].address = pkr.getAddress(index, isChange, pub).toString(); + unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange, pub); w3.add(createTx( '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', '123456789', @@ -558,6 +577,8 @@ describe('TxProposals model', function() { it('#toObj #fromObj roundtrip', function() { var priv = new PrivateKey(config); + var pub = priv.publicHex; + var pkr = createPKR([priv]); var w = new TxProposals({ walletId: 'qwerty', @@ -565,8 +586,8 @@ describe('TxProposals model', function() { }); var ts = Date.now(); - unspentTest[0].address = pkr.getAddress(index, isChange).toString(); - unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange); + unspentTest[0].address = pkr.getAddress(index, isChange, pub).toString(); + unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange, pub); w.add(createTx( '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', '123456789', diff --git a/test/test.Wallet.js b/test/test.Wallet.js index 3e392833c..ce4196a0b 100644 --- a/test/test.Wallet.js +++ b/test/test.Wallet.js @@ -123,7 +123,7 @@ describe('Wallet model', function() { var opts = {}; var w = cachedCreateW(); addCopayers(w); - w.publicKeyRing.generateAddress(false); + w.publicKeyRing.generateAddress(false, w.publicKey); w.publicKeyRing.isComplete().should.equal(true); w.generateAddress(true).isValid().should.equal(true); w.generateAddress(true, function(addr) { @@ -177,8 +177,8 @@ describe('Wallet model', function() { var w = cachedCreateW2(); - unspentTest[0].address = w.publicKeyRing.getAddress(1, true).toString(); - unspentTest[0].scriptPubKey = w.publicKeyRing.getScriptPubKeyHex(1, true); + unspentTest[0].address = w.publicKeyRing.getAddress(1, true, w.publicKey).toString(); + unspentTest[0].scriptPubKey = w.publicKeyRing.getScriptPubKeyHex(1, true, w.publicKey); var ntxid = w.createTxSync( '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', @@ -202,8 +202,8 @@ describe('Wallet model', function() { var w = cachedCreateW2(); var comment = 'This is a comment'; - unspentTest[0].address = w.publicKeyRing.getAddress(1, true).toString(); - unspentTest[0].scriptPubKey = w.publicKeyRing.getScriptPubKeyHex(1, true); + unspentTest[0].address = w.publicKeyRing.getAddress(1, true, w.publicKey).toString(); + unspentTest[0].scriptPubKey = w.publicKeyRing.getScriptPubKeyHex(1, true, w.publicKey); var ntxid = w.createTxSync( '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', @@ -224,8 +224,8 @@ describe('Wallet model', function() { var w = cachedCreateW2(); var comment = 'Lorem ipsum dolor sit amet, suas euismod vis te, velit deleniti vix an. Pri ex suscipit similique, inermis per'; - unspentTest[0].address = w.publicKeyRing.getAddress(1, true).toString(); - unspentTest[0].scriptPubKey = w.publicKeyRing.getScriptPubKeyHex(1, true); + unspentTest[0].address = w.publicKeyRing.getAddress(1, true, w.publicKey).toString(); + unspentTest[0].scriptPubKey = w.publicKeyRing.getScriptPubKeyHex(1, true, w.publicKey); var badCreate = function() { w.createTxSync( @@ -260,8 +260,8 @@ describe('Wallet model', function() { var ts = Date.now(); for (var isChange = false; !isChange; isChange = true) { for (var index = 0; index < 3; index++) { - unspentTest[0].address = w.publicKeyRing.getAddress(index, isChange).toString(); - unspentTest[0].scriptPubKey = w.publicKeyRing.getScriptPubKeyHex(index, isChange); + unspentTest[0].address = w.publicKeyRing.getAddress(index, isChange, w.publicKey).toString(); + unspentTest[0].scriptPubKey = w.publicKeyRing.getScriptPubKeyHex(index, isChange, w.publicKey); w.createTxSync( '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', '123456789', From fd2cf54eb4c6c2069c4aa4169ed255a4aefcc5e4 Mon Sep 17 00:00:00 2001 From: Yemel Jardi Date: Thu, 3 Jul 2014 13:04:01 -0300 Subject: [PATCH 05/10] Hide empty addresses from othe copayers --- index.html | 4 ++-- js/controllers/addresses.js | 3 ++- js/filters.js | 8 ++++++++ js/models/core/PublicKeyRing.js | 16 +++++++++++----- js/models/core/Wallet.js | 2 +- 5 files changed, 24 insertions(+), 9 deletions(-) diff --git a/index.html b/index.html index c08288641..6c7d97a0d 100644 --- a/index.html +++ b/index.html @@ -389,7 +389,7 @@
- @@ -411,7 +411,7 @@ - + Show all Show less diff --git a/js/controllers/addresses.js b/js/controllers/addresses.js index 3a0f7bacd..a0281e1b1 100644 --- a/js/controllers/addresses.js +++ b/js/controllers/addresses.js @@ -33,7 +33,8 @@ angular.module('copayApp.controllers').controller('AddressesController', $scope.addresses.push({ 'address': addrinfo.addressStr, 'balance': $rootScope.balanceByAddr ? $rootScope.balanceByAddr[addrinfo.addressStr] : 0, - 'isChange': addrinfo.isChange + 'isChange': addrinfo.isChange, + 'owned': addrinfo.owned }); } $scope.selectedAddr = $scope.addresses[0]; diff --git a/js/filters.js b/js/filters.js index 46d56469d..6b0a99ab0 100644 --- a/js/filters.js +++ b/js/filters.js @@ -17,6 +17,14 @@ angular.module('copayApp.filters', []) return false; }; }) + .filter('removeEmpty', function() { + return function(elements) { + // Hide empty addresses from other copayers + return elements.filter(function(e) { + return e.owned || e.balance > 0; + }); + } + }) .filter('limitAddress', function() { return function(elements, showAll) { if (elements.length <= 1 || showAll) { diff --git a/js/models/core/PublicKeyRing.js b/js/models/core/PublicKeyRing.js index b82c76365..90cab98cd 100644 --- a/js/models/core/PublicKeyRing.js +++ b/js/models/core/PublicKeyRing.js @@ -246,18 +246,22 @@ PublicKeyRing.prototype.getCosigner = function(pubKey) { } -PublicKeyRing.prototype.getAddressesInfo = function(opts) { +PublicKeyRing.prototype.getAddressesInfo = function(opts, pubkey) { var ret = []; var self = this; + var cosigner = pubkey && this.getCosigner(pubkey); this.indexes.forEach(function(index) { - ret = ret.concat(self.getAddressesInfoForIndex(index, opts)); + ret = ret.concat(self.getAddressesInfoForIndex(index, opts, cosigner)); }); return ret; } -PublicKeyRing.prototype.getAddressesInfoForIndex = function(index, opts) { +PublicKeyRing.prototype.getAddressesInfoForIndex = function(index, opts, cosigner) { opts = opts || {}; + var isOwned = index.cosigner == Structure.SHARED_INDEX + || index.cosigner == cosigner; + var ret = []; if (!opts.excludeChange) { for (var i = 0; i < index.changeIndex; i++) { @@ -265,7 +269,8 @@ PublicKeyRing.prototype.getAddressesInfoForIndex = function(index, opts) { ret.unshift({ address: a, addressStr: a.toString(), - isChange: true + isChange: true, + owned: isOwned }); } } @@ -276,7 +281,8 @@ PublicKeyRing.prototype.getAddressesInfoForIndex = function(index, opts) { ret.unshift({ address: a, addressStr: a.toString(), - isChange: false + isChange: false, + owned: isOwned }); } } diff --git a/js/models/core/Wallet.js b/js/models/core/Wallet.js index 800ef5d8e..ae9514926 100644 --- a/js/models/core/Wallet.js +++ b/js/models/core/Wallet.js @@ -588,7 +588,7 @@ Wallet.prototype.getAddressesStr = function(opts) { }; Wallet.prototype.getAddressesInfo = function(opts) { - return this.publicKeyRing.getAddressesInfo(opts); + return this.publicKeyRing.getAddressesInfo(opts, this.publicKey); }; Wallet.prototype.addressIsOwn = function(addrStr, opts) { From 2abc35ae577024fbe99b6cae89d633e814daef46 Mon Sep 17 00:00:00 2001 From: Yemel Jardi Date: Thu, 3 Jul 2014 16:42:03 -0300 Subject: [PATCH 06/10] Add update indexes and support old indexes schema --- js/models/core/AddressIndex.js | 11 ++++++++ js/models/core/PublicKeyRing.js | 9 ++----- js/models/core/Wallet.js | 46 +++++++++++++++++++++------------ test/test.Wallet.js | 23 ++++++++++------- test/test.WalletFactory.js | 2 +- 5 files changed, 56 insertions(+), 35 deletions(-) diff --git a/js/models/core/AddressIndex.js b/js/models/core/AddressIndex.js index 484865b87..d6f953a53 100644 --- a/js/models/core/AddressIndex.js +++ b/js/models/core/AddressIndex.js @@ -35,6 +35,17 @@ AddressIndex.fromObj = function(data) { return new AddressIndex(data); }; +AddressIndex.serialize = function(indexes) { + return indexes.map(function(i) { return i.toObj(); }); +} + +AddressIndex.update = function(shared, totalCopayers) { + var indexes = this.init(totalCopayers); + indexes[0].changeIndex = shared.changeIndex; + indexes[0].receiveIndex = shared.receiveIndex; + return this.serialize(indexes); +}; + AddressIndex.prototype.toObj = function() { return { cosigner: this.cosigner, diff --git a/js/models/core/PublicKeyRing.js b/js/models/core/PublicKeyRing.js index 90cab98cd..a08c160cf 100644 --- a/js/models/core/PublicKeyRing.js +++ b/js/models/core/PublicKeyRing.js @@ -40,8 +40,7 @@ PublicKeyRing.fromObj = function(data) { // Support old indexes schema if (!Array.isArray(data.indexes)) { - data.indexes.cosigner = Structure.SHARED_INDEX; - data.indexes = [data.indexes]; + data.indexes = AddressIndex.update(data.indexes, data.totalCopayers); } var ret = new PublicKeyRing(data); @@ -59,7 +58,7 @@ PublicKeyRing.prototype.toObj = function() { networkName: this.network.name, requiredCopayers: this.requiredCopayers, totalCopayers: this.totalCopayers, - indexes: this.getIndexesObj(), + indexes: AddressIndex.serialize(this.indexes), copayersExtPubKeys: this.copayersHK.map(function(b) { return b.extendedPublicKeyString(); @@ -69,10 +68,6 @@ PublicKeyRing.prototype.toObj = function() { }; }; -PublicKeyRing.prototype.getIndexesObj = function(i) { - return this.indexes.map(function(i) { return i.toObj(); }); -} - PublicKeyRing.prototype.getCopayerId = function(i) { preconditions.checkArgument(typeof i !== 'undefined'); return this.copayerIds[i]; diff --git a/js/models/core/Wallet.js b/js/models/core/Wallet.js index ae9514926..e03a75762 100644 --- a/js/models/core/Wallet.js +++ b/js/models/core/Wallet.js @@ -440,11 +440,12 @@ Wallet.prototype.sendPublicKeyRing = function(recipients) { }); }; Wallet.prototype.sendIndexes = function(recipients) { - this.log('### INDEXES TO:', recipients || 'All', this.publicKeyRing.getIndexesObj()); + var indexes = AddressIndex.serialize(this.publicKeyRing.indexes); + this.log('### INDEXES TO:', recipients || 'All', indexes); this.network.send(recipients, { type: 'indexes', - indexes: this.publicKeyRing.getIndexesObj(), + indexes: indexes, walletId: this.id, }); }; @@ -752,34 +753,45 @@ Wallet.prototype.createTxSync = function(toAddress, amountSatStr, comment, utxos return ntxid; }; -// TODO: Updetear todos los indices Wallet.prototype.updateIndexes = function(callback) { var self = this; - var start = self.publicKeyRing.getSharedIndex().changeIndex; self.log('Updating indexes...'); - self.indexDiscovery(start, true, 20, function(err, changeIndex) { + + var tasks = this.publicKeyRing.indexes.map(function(index) { + return function(callback) { + self.updateIndex(index, callback); + }; + }); + + async.parallel(tasks, function(err) { + if (err) callback(err); + self.log('Indexes updated'); + self.emit('publicKeyRingUpdated'); + self.store(); + callback(); + }); +} + +Wallet.prototype.updateIndex = function(index, callback) { + var self = this; + self.indexDiscovery(index.changeIndex, true, index.cosigner, 20, function(err, changeIndex) { if (err) return callback(err); if (changeIndex != -1) - self.publicKeyRing.getSharedIndex().changeIndex = changeIndex + 1; + index.changeIndex = changeIndex + 1; - start = self.publicKeyRing.getSharedIndex().receiveIndex; - self.indexDiscovery(start, false, 20, function(err, receiveIndex) { + self.indexDiscovery(index.receiveIndex, false, index.cosigner, 20, function(err, receiveIndex) { if (err) return callback(err); if (receiveIndex != -1) - self.publicKeyRing.getSharedIndex().receiveIndex = receiveIndex + 1; - - self.log('Indexes updated'); - self.emit('publicKeyRingUpdated'); - self.store(); + index.receiveIndex = receiveIndex + 1; callback(); }); }); } -Wallet.prototype.deriveAddresses = function(index, amout, isChange) { +Wallet.prototype.deriveAddresses = function(index, amout, isChange, cosigner) { var ret = new Array(amout); for (var i = 0; i < amout; i++) { - ret[i] = this.publicKeyRing.getAddress(index + i, isChange).toString(); + ret[i] = this.publicKeyRing.getAddress(index + i, isChange, cosigner).toString(); } return ret; } @@ -787,7 +799,7 @@ Wallet.prototype.deriveAddresses = function(index, amout, isChange) { // This function scans the publicKeyRing branch starting at index @start and reports the index with last activity, // using a scan window of @gap. The argument @change defines the branch to scan: internal or external. // Returns -1 if no activity is found in range. -Wallet.prototype.indexDiscovery = function(start, change, gap, cb) { +Wallet.prototype.indexDiscovery = function(start, change, cosigner, gap, cb) { var scanIndex = start; var lastActive = -1; var hasActivity = false; @@ -797,7 +809,7 @@ Wallet.prototype.indexDiscovery = function(start, change, gap, cb) { function _do(next) { // Optimize window to minimize the derivations. var scanWindow = (lastActive == -1) ? gap : gap - (scanIndex - lastActive) + 1; - var addresses = self.deriveAddresses(scanIndex, scanWindow, change); + var addresses = self.deriveAddresses(scanIndex, scanWindow, change, cosigner); self.blockchain.checkActivity(addresses, function(err, actives) { if (err) throw err; diff --git a/test/test.Wallet.js b/test/test.Wallet.js index ce4196a0b..b21f25774 100644 --- a/test/test.Wallet.js +++ b/test/test.Wallet.js @@ -670,8 +670,8 @@ describe('Wallet model', function() { before(function() { w = cachedCreateW2(); - ADDRESSES_CHANGE = w.deriveAddresses(0, 20, true); - ADDRESSES_RECEIVE = w.deriveAddresses(0, 20, false); + ADDRESSES_CHANGE = w.deriveAddresses(0, 20, true, 0); + ADDRESSES_RECEIVE = w.deriveAddresses(0, 20, false, 0); }); var mockFakeActivity = function(f) { @@ -690,7 +690,7 @@ describe('Wallet model', function() { mockFakeActivity(function(index) { return false; }); - w.indexDiscovery(0, false, 5, function(e, lastActive) { + w.indexDiscovery(0, false, 0, 5, function(e, lastActive) { lastActive.should.equal(-1); done(); }); @@ -700,7 +700,7 @@ describe('Wallet model', function() { mockFakeActivity(function(index) { return index <= 7; }); - w.indexDiscovery(0, false, 5, function(e, lastActive) { + w.indexDiscovery(0, false, 0, 5, function(e, lastActive) { lastActive.should.equal(7); done(); }); @@ -710,7 +710,7 @@ describe('Wallet model', function() { mockFakeActivity(function(index) { return index <= 10 || index == 17; }); - w.indexDiscovery(0, false, 5, function(e, lastActive) { + w.indexDiscovery(0, false, 0, 5, function(e, lastActive) { lastActive.should.equal(10); done(); }); @@ -720,7 +720,7 @@ describe('Wallet model', function() { mockFakeActivity(function(index) { return index <= 14 && index % 2 == 0; }); - w.indexDiscovery(0, false, 5, function(e, lastActive) { + w.indexDiscovery(0, false, 0, 5, function(e, lastActive) { lastActive.should.equal(14); done(); }); @@ -732,8 +732,11 @@ describe('Wallet model', function() { }); w.updateIndexes(function(err) { - w.publicKeyRing.getSharedIndex().receiveIndex.should.equal(15); - w.publicKeyRing.getSharedIndex().changeIndex.should.equal(15); + w.publicKeyRing.getIndex(0).receiveIndex.should.equal(15); + w.publicKeyRing.getIndex(0).changeIndex.should.equal(15); + + w.publicKeyRing.getIndex(1).receiveIndex.should.equal(0); + w.publicKeyRing.getIndex(1).changeIndex.should.equal(0); done(); }); }); @@ -753,8 +756,8 @@ describe('Wallet model', function() { it('#deriveAddresses', function(done) { var w = cachedCreateW2(); - var addresses1 = w.deriveAddresses(0, 5, false); - var addresses2 = w.deriveAddresses(4, 5, false); + var addresses1 = w.deriveAddresses(0, 5, false, 0); + var addresses2 = w.deriveAddresses(4, 5, false, 0); addresses1.length.should.equal(5); addresses2.length.should.equal(5); diff --git a/test/test.WalletFactory.js b/test/test.WalletFactory.js index f57b740c7..018779871 100644 --- a/test/test.WalletFactory.js +++ b/test/test.WalletFactory.js @@ -96,7 +96,7 @@ describe('WalletFactory model', function() { it('support old index schema: #fromObj #toObj round trip', function() { var o = '{"opts":{"id":"dbfe10c3fae71cea","spendUnconfirmed":1,"requiredCopayers":3,"totalCopayers":5,"version":"0.0.5"},"publicKeyRing":{"walletId":"dbfe10c3fae71cea","networkName":"testnet","requiredCopayers":3,"totalCopayers":5,"indexes":{"changeIndex":0,"receiveIndex":0},"copayersExtPubKeys":["tpubD6NzVbkrYhZ4YGK8ZhZ8WVeBXNAAoTYjjpw9twCPiNGrGQYFktP3iVQkKmZNiFnUcAFMJRxJVJF6Nq9MDv2kiRceExJaHFbxUCGUiRhmy97","tpubD6NzVbkrYhZ4YKGDJkzWdQsQV3AcFemaQKiwNhV4RL8FHnBFvinidGdQtP8RKj3h34E65RkdtxjrggZYqsEwJ8RhhN2zz9VrjLnrnwbXYNc","tpubD6NzVbkrYhZ4YkDiewjb32Pp3Sz9WK2jpp37KnL7RCrHAyPpnLfgdfRnTdpn6DTWmPS7niywfgWiT42aJb1J6CjWVNmkgsMCxuw7j9DaGKB","tpubD6NzVbkrYhZ4XEtUAz4UUTWbprewbLTaMhR8NUvSJUEAh4Sidxr6rRPFdqqVRR73btKf13wUjds2i8vVCNo8sbKrAnyoTr3o5Y6QSbboQjk","tpubD6NzVbkrYhZ4Yj9AAt6xUVuGPVd8jXCrEE6V2wp7U3PFh8jYYvVad31b4VUXEYXzSnkco4fktu8r4icBsB2t3pCR3WnhVLedY2hxGcPFLKD"],"nicknameFor":{},"publicKeysCache":{"m/0/1/0":["0314368b8efa07e8c7dad30498d0a7e3aa575db1fef833347c6d381c1a33a17b17","02cfd95f89ab46bd3bd86954dd9f83dbab0cd2e4466dee587e8e4d8d733fc0d748","02568969eb6212fe946450be6c5b3353fc754a40b2cdc4aed501a8976fec371da8","0360f870a088ae0ef1c37035a9b6a462ca8dcdd5da275f4e2dcd19f44b81d3e7e4","0300ad8f1bded838b02e127bb25961fbcee718db2df81f680f889692acdcbdd73d"],"m/0/1/1":["024f97a9adb2fa9306c4e3d9244f5e5355c7e2c6b3dd4122ba804e17dc9729df5d","0214834a5adcbc4ad0f3bbbc1c280b8ac480387fcc9a1fd988c1526ed496d923c4","024e72338bd5e976375d076bd71a9649e9141b4cbfc9e16cb7109b354b3e913a05","0322045ea35c3118aa7ab9f2c9f182b0120956b0aa65cc72b9d093f145327a4b17","030dc2450c72df366c1960739c577a2efd4451070bd78effcb6f71d1bcd7dfc7a8"],"m/0/1/2":["0247de59deb66783b8f9b0c326234a9569d00866c2a73f599e77a4d0cab5cbce8f","0376e49f0ac3647404034aae0dc8dd927c34a634ef24ea36f56a272f75fce9539b","032fbaa2593bd1eea4a46e7ac15f15802cdd1eb65a7d5bc4364ddd9d52f0838234","03a81f2a7e1f7191aa0b0c6e0a4ccefc71edd3564e86014972fe338045f68d5a5a","02eb8a012ea9a709392502cacda6ef5115d6d2319ab470d546d9068ab941621a99"],"m/0/0/0":["036dcbd378b4352120d6b720b6294dd2d0dd02801fcf010bb69dadbec1f3999279","022089eedb85dc45d1efa418e1ea226588deedebc1d85acca15ff72783e33636c0","0388aa5fd432b74c56427396f350d236c3ca8f7b2f62da513ce4c2e6ff04a67e9c","02fc4caa7449db7483d2e1fccdacac6fa2f736278c758af9966402589b5632f13e","02e4a15b885d8b2d586f82fa85d16179644e60a154674bde0ec3004810b1bdab99"],"m/0/0/1":["039afa26b2f341c76c7b3c3d0672438f35ac6ebb67b1ddfefac9cd79b7b24418c1","021acaaf500d431ebc396f50630767b01c91ce98ae48e968775ceaad932b7e3b8e","022a947259c4a9f76d5e95c0849df31d01233df41d0d75d631b89317a48d8cddce","03d38d9f94217da780303d9a8987c86d737ef39683febc0cd6632cddbfa62186fd","0394d2581b307fe2af19721888d922aab58ab198ef88cedf9506177e30d807811e"],"m/0/0/2":["037825ffce15d34f9bd6c02bcda7701826706471a4d6ab5004eb965f98811c2098","023768dd6d3c71b7df5733ccda5b2d8b454d5b4c4179d91a6fda74db8b869a2406","021a79e91f003f308764d43039e9b5d56bc8f33ca2f4d30ec6cc5a37c0d09dc273","02437f1e388b273936319f79a5d22958ef5ebff9c8cd7b6f6f72518445b1e30867","0373b0881cb4fd02baa62589023fdfe9739c6148cf104d907549f2528eb80146f5"]}},"txProposals":{"txps":[],"walletId":"dbfe10c3fae71cea","networkName":"testnet"},"privateKey":{"extendedPrivateKeyString":"tprv8ZgxMBicQKsPeoHLg3tY75z4xLeEe8MqAXLNcRA6J6UTRvHV8VZTXznt9eoTmSk1fwSrwZtMhY3XkNsceJ14h6sCXHSWinRqMSSbY8tfhHi","networkName":"testnet","privateKeyCache":{}},"addressBook":{},"backupOffered":false}'; - var o2 = '{"opts":{"id":"dbfe10c3fae71cea","spendUnconfirmed":1,"requiredCopayers":3,"totalCopayers":5,"version":"0.0.5"},"publicKeyRing":{"walletId":"dbfe10c3fae71cea","networkName":"testnet","requiredCopayers":3,"totalCopayers":5,"indexes":[{"cosigner":2147483647,"changeIndex":0,"receiveIndex":0}],"copayersExtPubKeys":["tpubD6NzVbkrYhZ4YGK8ZhZ8WVeBXNAAoTYjjpw9twCPiNGrGQYFktP3iVQkKmZNiFnUcAFMJRxJVJF6Nq9MDv2kiRceExJaHFbxUCGUiRhmy97","tpubD6NzVbkrYhZ4YKGDJkzWdQsQV3AcFemaQKiwNhV4RL8FHnBFvinidGdQtP8RKj3h34E65RkdtxjrggZYqsEwJ8RhhN2zz9VrjLnrnwbXYNc","tpubD6NzVbkrYhZ4YkDiewjb32Pp3Sz9WK2jpp37KnL7RCrHAyPpnLfgdfRnTdpn6DTWmPS7niywfgWiT42aJb1J6CjWVNmkgsMCxuw7j9DaGKB","tpubD6NzVbkrYhZ4XEtUAz4UUTWbprewbLTaMhR8NUvSJUEAh4Sidxr6rRPFdqqVRR73btKf13wUjds2i8vVCNo8sbKrAnyoTr3o5Y6QSbboQjk","tpubD6NzVbkrYhZ4Yj9AAt6xUVuGPVd8jXCrEE6V2wp7U3PFh8jYYvVad31b4VUXEYXzSnkco4fktu8r4icBsB2t3pCR3WnhVLedY2hxGcPFLKD"],"nicknameFor":{},"publicKeysCache":{"m/0/1/0":["0314368b8efa07e8c7dad30498d0a7e3aa575db1fef833347c6d381c1a33a17b17","02cfd95f89ab46bd3bd86954dd9f83dbab0cd2e4466dee587e8e4d8d733fc0d748","02568969eb6212fe946450be6c5b3353fc754a40b2cdc4aed501a8976fec371da8","0360f870a088ae0ef1c37035a9b6a462ca8dcdd5da275f4e2dcd19f44b81d3e7e4","0300ad8f1bded838b02e127bb25961fbcee718db2df81f680f889692acdcbdd73d"],"m/0/1/1":["024f97a9adb2fa9306c4e3d9244f5e5355c7e2c6b3dd4122ba804e17dc9729df5d","0214834a5adcbc4ad0f3bbbc1c280b8ac480387fcc9a1fd988c1526ed496d923c4","024e72338bd5e976375d076bd71a9649e9141b4cbfc9e16cb7109b354b3e913a05","0322045ea35c3118aa7ab9f2c9f182b0120956b0aa65cc72b9d093f145327a4b17","030dc2450c72df366c1960739c577a2efd4451070bd78effcb6f71d1bcd7dfc7a8"],"m/0/1/2":["0247de59deb66783b8f9b0c326234a9569d00866c2a73f599e77a4d0cab5cbce8f","0376e49f0ac3647404034aae0dc8dd927c34a634ef24ea36f56a272f75fce9539b","032fbaa2593bd1eea4a46e7ac15f15802cdd1eb65a7d5bc4364ddd9d52f0838234","03a81f2a7e1f7191aa0b0c6e0a4ccefc71edd3564e86014972fe338045f68d5a5a","02eb8a012ea9a709392502cacda6ef5115d6d2319ab470d546d9068ab941621a99"],"m/0/0/0":["036dcbd378b4352120d6b720b6294dd2d0dd02801fcf010bb69dadbec1f3999279","022089eedb85dc45d1efa418e1ea226588deedebc1d85acca15ff72783e33636c0","0388aa5fd432b74c56427396f350d236c3ca8f7b2f62da513ce4c2e6ff04a67e9c","02fc4caa7449db7483d2e1fccdacac6fa2f736278c758af9966402589b5632f13e","02e4a15b885d8b2d586f82fa85d16179644e60a154674bde0ec3004810b1bdab99"],"m/0/0/1":["039afa26b2f341c76c7b3c3d0672438f35ac6ebb67b1ddfefac9cd79b7b24418c1","021acaaf500d431ebc396f50630767b01c91ce98ae48e968775ceaad932b7e3b8e","022a947259c4a9f76d5e95c0849df31d01233df41d0d75d631b89317a48d8cddce","03d38d9f94217da780303d9a8987c86d737ef39683febc0cd6632cddbfa62186fd","0394d2581b307fe2af19721888d922aab58ab198ef88cedf9506177e30d807811e"],"m/0/0/2":["037825ffce15d34f9bd6c02bcda7701826706471a4d6ab5004eb965f98811c2098","023768dd6d3c71b7df5733ccda5b2d8b454d5b4c4179d91a6fda74db8b869a2406","021a79e91f003f308764d43039e9b5d56bc8f33ca2f4d30ec6cc5a37c0d09dc273","02437f1e388b273936319f79a5d22958ef5ebff9c8cd7b6f6f72518445b1e30867","0373b0881cb4fd02baa62589023fdfe9739c6148cf104d907549f2528eb80146f5"]}},"txProposals":{"txps":[],"walletId":"dbfe10c3fae71cea","networkName":"testnet"},"privateKey":{"extendedPrivateKeyString":"tprv8ZgxMBicQKsPeoHLg3tY75z4xLeEe8MqAXLNcRA6J6UTRvHV8VZTXznt9eoTmSk1fwSrwZtMhY3XkNsceJ14h6sCXHSWinRqMSSbY8tfhHi","networkName":"testnet","privateKeyCache":{}},"addressBook":{},"backupOffered":false}'; + var o2 = '{"opts":{"id":"dbfe10c3fae71cea","spendUnconfirmed":1,"requiredCopayers":3,"totalCopayers":5,"version":"0.0.5"},"publicKeyRing":{"walletId":"dbfe10c3fae71cea","networkName":"testnet","requiredCopayers":3,"totalCopayers":5,"indexes":[{"cosigner":2147483647,"changeIndex":0,"receiveIndex":0},{"cosigner":0,"changeIndex":0,"receiveIndex":0},{"cosigner":1,"changeIndex":0,"receiveIndex":0},{"cosigner":2,"changeIndex":0,"receiveIndex":0},{"cosigner":3,"changeIndex":0,"receiveIndex":0},{"cosigner":4,"changeIndex":0,"receiveIndex":0}],"copayersExtPubKeys":["tpubD6NzVbkrYhZ4YGK8ZhZ8WVeBXNAAoTYjjpw9twCPiNGrGQYFktP3iVQkKmZNiFnUcAFMJRxJVJF6Nq9MDv2kiRceExJaHFbxUCGUiRhmy97","tpubD6NzVbkrYhZ4YKGDJkzWdQsQV3AcFemaQKiwNhV4RL8FHnBFvinidGdQtP8RKj3h34E65RkdtxjrggZYqsEwJ8RhhN2zz9VrjLnrnwbXYNc","tpubD6NzVbkrYhZ4YkDiewjb32Pp3Sz9WK2jpp37KnL7RCrHAyPpnLfgdfRnTdpn6DTWmPS7niywfgWiT42aJb1J6CjWVNmkgsMCxuw7j9DaGKB","tpubD6NzVbkrYhZ4XEtUAz4UUTWbprewbLTaMhR8NUvSJUEAh4Sidxr6rRPFdqqVRR73btKf13wUjds2i8vVCNo8sbKrAnyoTr3o5Y6QSbboQjk","tpubD6NzVbkrYhZ4Yj9AAt6xUVuGPVd8jXCrEE6V2wp7U3PFh8jYYvVad31b4VUXEYXzSnkco4fktu8r4icBsB2t3pCR3WnhVLedY2hxGcPFLKD"],"nicknameFor":{},"publicKeysCache":{"m/0/1/0":["0314368b8efa07e8c7dad30498d0a7e3aa575db1fef833347c6d381c1a33a17b17","02cfd95f89ab46bd3bd86954dd9f83dbab0cd2e4466dee587e8e4d8d733fc0d748","02568969eb6212fe946450be6c5b3353fc754a40b2cdc4aed501a8976fec371da8","0360f870a088ae0ef1c37035a9b6a462ca8dcdd5da275f4e2dcd19f44b81d3e7e4","0300ad8f1bded838b02e127bb25961fbcee718db2df81f680f889692acdcbdd73d"],"m/0/1/1":["024f97a9adb2fa9306c4e3d9244f5e5355c7e2c6b3dd4122ba804e17dc9729df5d","0214834a5adcbc4ad0f3bbbc1c280b8ac480387fcc9a1fd988c1526ed496d923c4","024e72338bd5e976375d076bd71a9649e9141b4cbfc9e16cb7109b354b3e913a05","0322045ea35c3118aa7ab9f2c9f182b0120956b0aa65cc72b9d093f145327a4b17","030dc2450c72df366c1960739c577a2efd4451070bd78effcb6f71d1bcd7dfc7a8"],"m/0/1/2":["0247de59deb66783b8f9b0c326234a9569d00866c2a73f599e77a4d0cab5cbce8f","0376e49f0ac3647404034aae0dc8dd927c34a634ef24ea36f56a272f75fce9539b","032fbaa2593bd1eea4a46e7ac15f15802cdd1eb65a7d5bc4364ddd9d52f0838234","03a81f2a7e1f7191aa0b0c6e0a4ccefc71edd3564e86014972fe338045f68d5a5a","02eb8a012ea9a709392502cacda6ef5115d6d2319ab470d546d9068ab941621a99"],"m/0/0/0":["036dcbd378b4352120d6b720b6294dd2d0dd02801fcf010bb69dadbec1f3999279","022089eedb85dc45d1efa418e1ea226588deedebc1d85acca15ff72783e33636c0","0388aa5fd432b74c56427396f350d236c3ca8f7b2f62da513ce4c2e6ff04a67e9c","02fc4caa7449db7483d2e1fccdacac6fa2f736278c758af9966402589b5632f13e","02e4a15b885d8b2d586f82fa85d16179644e60a154674bde0ec3004810b1bdab99"],"m/0/0/1":["039afa26b2f341c76c7b3c3d0672438f35ac6ebb67b1ddfefac9cd79b7b24418c1","021acaaf500d431ebc396f50630767b01c91ce98ae48e968775ceaad932b7e3b8e","022a947259c4a9f76d5e95c0849df31d01233df41d0d75d631b89317a48d8cddce","03d38d9f94217da780303d9a8987c86d737ef39683febc0cd6632cddbfa62186fd","0394d2581b307fe2af19721888d922aab58ab198ef88cedf9506177e30d807811e"],"m/0/0/2":["037825ffce15d34f9bd6c02bcda7701826706471a4d6ab5004eb965f98811c2098","023768dd6d3c71b7df5733ccda5b2d8b454d5b4c4179d91a6fda74db8b869a2406","021a79e91f003f308764d43039e9b5d56bc8f33ca2f4d30ec6cc5a37c0d09dc273","02437f1e388b273936319f79a5d22958ef5ebff9c8cd7b6f6f72518445b1e30867","0373b0881cb4fd02baa62589023fdfe9739c6148cf104d907549f2528eb80146f5"]}},"txProposals":{"txps":[],"walletId":"dbfe10c3fae71cea","networkName":"testnet"},"privateKey":{"extendedPrivateKeyString":"tprv8ZgxMBicQKsPeoHLg3tY75z4xLeEe8MqAXLNcRA6J6UTRvHV8VZTXznt9eoTmSk1fwSrwZtMhY3XkNsceJ14h6sCXHSWinRqMSSbY8tfhHi","networkName":"testnet","privateKeyCache":{}},"addressBook":{},"backupOffered":false}'; var wf = new WalletFactory(config, '0.0.5'); var w = wf.fromObj(JSON.parse(o)); From 680b0b553ead2481c000c7b3a397682f4e4cc72b Mon Sep 17 00:00:00 2001 From: Yemel Jardi Date: Thu, 3 Jul 2014 16:57:07 -0300 Subject: [PATCH 07/10] bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3bbbc4c45..226fbe6b3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "copay", - "version": "0.2.1", + "version": "0.3.1", "description": "A multisignature wallet", "repository": { "type": "git", From 7562c3f9e71cd5bd23f861ff8cd86d40d5225ea4 Mon Sep 17 00:00:00 2001 From: Yemel Jardi Date: Fri, 4 Jul 2014 09:45:02 -0300 Subject: [PATCH 08/10] Add some test and refactor getCosigner --- js/models/core/PublicKeyRing.js | 19 +++++++------------ test/test.AddressIndex.js | 12 ++++++++++++ test/test.Wallet.js | 12 ++++++------ test/unit/filters/filtersSpec.js | 29 +++++++++++++++++++++++++++++ 4 files changed, 54 insertions(+), 18 deletions(-) diff --git a/js/models/core/PublicKeyRing.js b/js/models/core/PublicKeyRing.js index a08c160cf..ea56d20f8 100644 --- a/js/models/core/PublicKeyRing.js +++ b/js/models/core/PublicKeyRing.js @@ -177,22 +177,16 @@ PublicKeyRing.prototype.getRedeemScript = function(index, isChange, cosigner) { // TODO this could be cached PublicKeyRing.prototype.getAddress = function(index, isChange, id) { - var cosigner = typeof id === 'string' ? this.getCosigner(id) : id; - + var cosigner = this.getCosigner(id); var script = this.getRedeemScript(index, isChange, cosigner); var address = Address.fromScript(script, this.network.name); this.addressToPath[address.toString()] = Structure.FullBranch(index, isChange, cosigner); return address; }; -PublicKeyRing.prototype.getSharedIndex = function() { - return this.getIndex(Structure.SHARED_INDEX); -}; - // Overloaded to receive a PubkeyString or a consigner index PublicKeyRing.prototype.getIndex = function(id) { - var cosigner = typeof id === 'string' ? this.getCosigner(id) : id; - + var cosigner = this.getCosigner(id); var index = this.indexes.filter(function(i) { return i.cosigner == cosigner }); if (index.length != 1) throw new Error('no index for cosigner'); return index[0]; @@ -214,10 +208,9 @@ PublicKeyRing.prototype.getScriptPubKeyHex = function(index, isChange, pubkey) { //generate a new address, update index. PublicKeyRing.prototype.generateAddress = function(isChange, pubkey) { isChange = !!isChange; - var cosigner = this.getCosigner(pubkey); - var addrIndex = this.getIndex(cosigner); + var addrIndex = this.getIndex(pubkey); var index = isChange ? addrIndex.getChangeIndex() : addrIndex.getReceiveIndex(); - var ret = this.getAddress(index, isChange, cosigner); + var ret = this.getAddress(index, isChange, addrIndex.cosigner); addrIndex.increment(isChange); return ret; }; @@ -229,7 +222,9 @@ PublicKeyRing.prototype.getAddresses = function(opts) { }; PublicKeyRing.prototype.getCosigner = function(pubKey) { - preconditions.checkArgument(pubKey); + if (typeof pubKey == 'undefined') return Structure.SHARED_INDEX; + if (typeof pubKey == 'number') return pubKey; + var sorted = this.copayersHK.map(function(h, i){ return h.eckey.public.toString('hex'); }).sort(function(h1, h2){ return h1.localeCompare(h2); }); diff --git a/test/test.AddressIndex.js b/test/test.AddressIndex.js index 3d87d9868..2ba38bfd0 100644 --- a/test/test.AddressIndex.js +++ b/test/test.AddressIndex.js @@ -47,6 +47,18 @@ describe('AddressIndex model', function() { cosigners.indexOf(2).should.equal(-1); }); + it('should serialize to object list and back', function() { + var is = AddressIndex.init(3); + should.exist(is); + is.length.should.equal(4); + + var list = AddressIndex.serialize(is); + list.length.should.equal(4); + + var is2 = AddressIndex.fromList(list); + is2.length.should.equal(4); + }); + it('show be able to store and read', function() { var i = createAI(); var changeN = 2; diff --git a/test/test.Wallet.js b/test/test.Wallet.js index b21f25774..0e3c2cdc3 100644 --- a/test/test.Wallet.js +++ b/test/test.Wallet.js @@ -343,14 +343,14 @@ describe('Wallet model', function() { var w = createW(); var aiObj = { indexes: [{ - cosigner: Structure.SHARED_INDEX, + cosigner: 0, changeIndex: 3, receiveIndex: 2 }] }; w._handleIndexes('senderID', aiObj, true); - w.publicKeyRing.getSharedIndex().getReceiveIndex(2); - w.publicKeyRing.getSharedIndex().getChangeIndex(3); + w.publicKeyRing.getIndex(0).getReceiveIndex(2); + w.publicKeyRing.getIndex(0).getChangeIndex(3); }); it('handle network pubKeyRings correctly', function() { @@ -367,7 +367,7 @@ describe('Wallet model', function() { requiredCopayers: w.requiredCopayers, totalCopayers: w.totalCopayers, indexes: [{ - cosigner: Structure.SHARED_INDEX, + cosigner: 0, changeIndex: 2, receiveIndex: 3 }], @@ -377,8 +377,8 @@ describe('Wallet model', function() { w._handlePublicKeyRing('senderID', { publicKeyRing: pkrObj }, true); - w.publicKeyRing.getSharedIndex().getReceiveIndex(2); - w.publicKeyRing.getSharedIndex().getChangeIndex(3); + w.publicKeyRing.getIndex(0).getReceiveIndex(2); + w.publicKeyRing.getIndex(0).getChangeIndex(3); for (var i = 0; i < w.requiredCopayers; i++) { w.publicKeyRing.toObj().copayersExtPubKeys[i].should.equal(cepk[i]); } diff --git a/test/unit/filters/filtersSpec.js b/test/unit/filters/filtersSpec.js index fe180659f..1b3f3acc2 100644 --- a/test/unit/filters/filtersSpec.js +++ b/test/unit/filters/filtersSpec.js @@ -69,6 +69,35 @@ describe('Unit: Testing Filters', function() { })); }); + describe('removeEmpty addresses', function() { + it('should work with empty lists', inject(function($filter) { + var removeEmpty = $filter('removeEmpty'); + expect(removeEmpty([]).length).to.equal(0); + })); + + it('should filter empty addresses from other copayers', inject(function($filter) { + var removeEmpty = $filter('removeEmpty'); + var addresses = [{ + owned: true, + balance: 0 + }, { + owned: false, + balance: 0 + }, { + owned: true, + balance: 0 + }, { + owned: false, + balance: 0 + }]; + expect(removeEmpty(addresses).length).to.equal(2); + addresses[1].owned = true; + expect(removeEmpty(addresses).length).to.equal(3); + addresses[3].balance = 10; + expect(removeEmpty(addresses).length).to.equal(4); + })); + }); + describe('noFractionNumber bits', function() { beforeEach(function() { config.unitToSatoshi = 100; From 13cf5e4216b72d90589cbd6d6961d0fa5582464b Mon Sep 17 00:00:00 2001 From: Yemel Jardi Date: Mon, 7 Jul 2014 10:32:19 -0300 Subject: [PATCH 09/10] change import to fix index.html tests --- test/test.Wallet.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test.Wallet.js b/test/test.Wallet.js index 0e3c2cdc3..4eabaf429 100644 --- a/test/test.Wallet.js +++ b/test/test.Wallet.js @@ -9,7 +9,7 @@ try { var copay = require('../copay'); //node } var Wallet = require('../js/models/core/Wallet'); -var Structure = require('../js/models/core/Structure'); +var Structure = copay.Structure; var Storage = require('./mocks/FakeStorage'); var Network = require('./mocks/FakeNetwork'); var Blockchain = require('./mocks/FakeBlockchain'); From d0693442ceae354b0aff3f12545850807c7dc83b Mon Sep 17 00:00:00 2001 From: Yemel Jardi Date: Mon, 7 Jul 2014 12:26:42 -0300 Subject: [PATCH 10/10] Remove magic number fixes #736 --- js/models/core/Wallet.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/js/models/core/Wallet.js b/js/models/core/Wallet.js index e03a75762..5ccea0ce5 100644 --- a/js/models/core/Wallet.js +++ b/js/models/core/Wallet.js @@ -774,12 +774,13 @@ Wallet.prototype.updateIndexes = function(callback) { Wallet.prototype.updateIndex = function(index, callback) { var self = this; - self.indexDiscovery(index.changeIndex, true, index.cosigner, 20, function(err, changeIndex) { + var SCANN_WINDOW = 20; + self.indexDiscovery(index.changeIndex, true, index.cosigner, SCANN_WINDOW, function(err, changeIndex) { if (err) return callback(err); if (changeIndex != -1) index.changeIndex = changeIndex + 1; - self.indexDiscovery(index.receiveIndex, false, index.cosigner, 20, function(err, receiveIndex) { + self.indexDiscovery(index.receiveIndex, false, index.cosigner, SCANN_WINDOW, function(err, receiveIndex) { if (err) return callback(err); if (receiveIndex != -1) index.receiveIndex = receiveIndex + 1;