From 88df346c5156e5eb385f6b22e468ae27c3a92fc1 Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Wed, 4 Jun 2014 12:28:26 -0300 Subject: [PATCH 1/4] working towards new AddressIndex obj --- js/models/core/AddressIndex.js | 79 +++++++++++++++++++++++++++++++++ js/models/core/PrivateKey.js | 6 +-- js/models/core/PublicKeyRing.js | 53 +++++----------------- 3 files changed, 94 insertions(+), 44 deletions(-) create mode 100644 js/models/core/AddressIndex.js diff --git a/js/models/core/AddressIndex.js b/js/models/core/AddressIndex.js new file mode 100644 index 000000000..b5a4aab68 --- /dev/null +++ b/js/models/core/AddressIndex.js @@ -0,0 +1,79 @@ +'use strict'; + + +var imports = require('soop').imports(); +var bitcore = require('bitcore'); +var HK = bitcore.HierarchicalKey; +var PrivateKey = require('./PrivateKey'); +var Structure = require('./Structure'); +var Address = bitcore.Address; +var Script = bitcore.Script; +var coinUtil = bitcore.util; +var Transaction = bitcore.Transaction +var util = bitcore.util; + +function AddressIndex(opts) { + opts = opts || {}; + + this.walletId = opts.walletId; + + this.changeIndex = opts.changeIndex || 0; + this.receiveIndex = opts.receiveIndex || 0; +} + +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; +}; + +AddressIndex.prototype.toObj = function() { + return { + walletId: this.walletId, + changeIndex: this.changeIndex, + receiveIndex: this.receiveIndex, + }; +}; + +AddressIndex.prototype._checkIndexRange = function(index, isChange) { + if ((isChange && index > this.changeIndex) || + (!isChange && index > this.receiveIndex)) { + throw new Error('Out of bounds at index %d isChange: %d', index, isChange); + } +}; + + +AddressIndex.prorotype.getChangeIndex = function() { + return this.changeIndex; +}; +AddressIndex.prorotype.getReceiveIndex = function() { + return this.receiveIndex; +}; + +AddressIndex.prototype.increment = function(isChange) { + if (isChange) { + this.changeIndex++; + } else { + this.receiveIndex++; + } +}; + +AddressIndex.prototype.merge = function(inAddressIndex) { + var hasChanged = false; + + // Indexes + if (inAddressIndex.changeIndex > this.changeIndex) { + this.changeIndex = inAddressIndex.changeIndex; + hasChanged = true; + } + + if (inAddressIndex.receiveIndex > this.receiveIndex) { + this.receiveIndex = inAddressIndex.receiveIndex; + hasChanged = true; + } + return hasChanged; +}; + +module.exports = require('soop')(AddressIndex); diff --git a/js/models/core/PrivateKey.js b/js/models/core/PrivateKey.js index cc2a4d715..d324f1831 100644 --- a/js/models/core/PrivateKey.js +++ b/js/models/core/PrivateKey.js @@ -81,12 +81,12 @@ PrivateKey.prototype.get = function(index,isChange) { return this.getForPath(path); }; -PrivateKey.prototype.getAll = function(addressIndex, changeAddressIndex) { +PrivateKey.prototype.getAll = function(receiveIndex, changeIndex) { var ret = []; - for(var i=0;i this.changeAddressIndex) || - (!isChange && index > this.addressIndex)) { - throw new Error('Out of bounds at getAddress: Index %d isChange: %d', index, isChange); - } -}; - // TODO this could be cached PublicKeyRing.prototype.getRedeemScript = function (index, isChange) { this._checkIndexRange(index, isChange); @@ -197,14 +189,9 @@ PublicKeyRing.prototype.getScriptPubKeyHex = function (index, isChange) { //generate a new address, update index. PublicKeyRing.prototype.generateAddress = function(isChange) { - var ret = - this.getAddress(isChange ? this.changeAddressIndex : this.addressIndex, isChange); - if (isChange) { - this.changeAddressIndex++; - } else { - this.addressIndex++; - } - + var index = isChange ? this.indexes.getChangeIndex() : this.indexes.getReceiveIndex(); + var ret = this.getAddress(index, isChange); + this.indexes.increment(isChange); return ret; }; @@ -219,7 +206,7 @@ PublicKeyRing.prototype.getAddressesInfo = function(opts) { var ret = []; if (!opts.excludeChange) { - for (var i=0; i this.changeAddressIndex) { - this.changeAddressIndex = inPKR.changeAddressIndex; - hasChanged = true; - } - - if (inPKR.addressIndex > this.addressIndex) { - this.addressIndex = inPKR.addressIndex; - hasChanged = true; - } - return hasChanged; -}; - PublicKeyRing.prototype._mergePubkeys = function(inPKR) { var self = this; var hasChanged = false; @@ -330,7 +301,7 @@ PublicKeyRing.prototype.merge = function(inPKR, ignoreId) { this._checkInPRK(inPKR, ignoreId); - if (this._mergeIndexes(inPKR)) + if (this.indexes.merge(inPKR.indexes)) hasChanged = true; if (this._mergePubkeys(inPKR)) From 51d5d7164ec652fcab39e958afc89014b78f28da Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Wed, 4 Jun 2014 13:44:32 -0300 Subject: [PATCH 2/4] add AddressIndex model --- copay.js | 1 + js/models/core/AddressIndex.js | 6 +-- js/models/core/PrivateKey.js | 3 ++ js/models/core/PublicKeyRing.js | 4 +- test/test.AddressIndex.js | 84 +++++++++++++++++++++++++++++++++ test/test.PublicKeyRing.js | 12 ++--- test/test.TxProposals.js | 7 ++- test/test.WalletFactory.js | 3 +- 8 files changed, 104 insertions(+), 16 deletions(-) create mode 100644 test/test.AddressIndex.js diff --git a/copay.js b/copay.js index 9149fa071..585fc1677 100644 --- a/copay.js +++ b/copay.js @@ -5,6 +5,7 @@ module.exports.TxProposals = require('./js/models/core/TxProposals'); module.exports.PrivateKey = require('./js/models/core/PrivateKey'); module.exports.Passphrase = require('./js/models/core/Passphrase'); module.exports.Structure = require('./js/models/core/Structure'); +module.exports.AddressIndex = require('./js/models/core/AddressIndex'); // components diff --git a/js/models/core/AddressIndex.js b/js/models/core/AddressIndex.js index b5a4aab68..14e42ffc6 100644 --- a/js/models/core/AddressIndex.js +++ b/js/models/core/AddressIndex.js @@ -37,7 +37,7 @@ AddressIndex.prototype.toObj = function() { }; }; -AddressIndex.prototype._checkIndexRange = function(index, isChange) { +AddressIndex.prototype.checkRange = function(index, isChange) { if ((isChange && index > this.changeIndex) || (!isChange && index > this.receiveIndex)) { throw new Error('Out of bounds at index %d isChange: %d', index, isChange); @@ -45,10 +45,10 @@ AddressIndex.prototype._checkIndexRange = function(index, isChange) { }; -AddressIndex.prorotype.getChangeIndex = function() { +AddressIndex.prototype.getChangeIndex = function() { return this.changeIndex; }; -AddressIndex.prorotype.getReceiveIndex = function() { +AddressIndex.prototype.getReceiveIndex = function() { return this.receiveIndex; }; diff --git a/js/models/core/PrivateKey.js b/js/models/core/PrivateKey.js index d324f1831..7475f9146 100644 --- a/js/models/core/PrivateKey.js +++ b/js/models/core/PrivateKey.js @@ -82,6 +82,9 @@ PrivateKey.prototype.get = function(index,isChange) { }; PrivateKey.prototype.getAll = function(receiveIndex, changeIndex) { + if (typeof receiveIndex === 'undefined' || typeof changeIndex === 'undefined') + throw new Error('Invalid parameters'); + var ret = []; for(var i=0;i Date: Wed, 4 Jun 2014 14:24:46 -0300 Subject: [PATCH 3/4] change protocol to send only indexes on new addr --- js/models/core/AddressIndex.js | 1 - js/models/core/Wallet.js | 30 ++++++++++++++++++++++++++---- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/js/models/core/AddressIndex.js b/js/models/core/AddressIndex.js index 14e42ffc6..94328b40e 100644 --- a/js/models/core/AddressIndex.js +++ b/js/models/core/AddressIndex.js @@ -14,7 +14,6 @@ var util = bitcore.util; function AddressIndex(opts) { opts = opts || {}; - this.walletId = opts.walletId; this.changeIndex = opts.changeIndex || 0; diff --git a/js/models/core/Wallet.js b/js/models/core/Wallet.js index 3a6f32138..72f25743f 100644 --- a/js/models/core/Wallet.js +++ b/js/models/core/Wallet.js @@ -72,6 +72,16 @@ Wallet.prototype.connectToAll = function() { } }; +Wallet.prototype._handleIndexes = function(senderId, data, isInbound) { + this.log('RECV INDEXES:', data); + var inIndexes = copay.AddressIndex.fromObj(data.indexes); + var hasChanged = this.publicKeyRing.indexes.merge(inIndexes); + if (hasChanged) { + this.emit('publicKeyRingUpdated'); + this.store(); + } +}; + Wallet.prototype._handlePublicKeyRing = function(senderId, data, isInbound) { this.log('RECV PUBLICKEYRING:', data); @@ -87,9 +97,9 @@ Wallet.prototype._handlePublicKeyRing = function(senderId, data, isInbound) { if (this.publicKeyRing.isComplete()) { this._lockIncomming(); } + this.emit('publicKeyRingUpdated'); + this.store(); } - this.emit('publicKeyRingUpdated'); - this.store(); }; @@ -142,6 +152,9 @@ Wallet.prototype._handleData = function(senderId, data, isInbound) { case 'txProposals': this._handleTxProposals(senderId, data, isInbound); break; + case 'indexes': + this._handleIndexes(senderId, data, isInbound); + break; } }; @@ -378,6 +391,15 @@ Wallet.prototype.sendPublicKeyRing = function(recipients) { walletId: this.id, }); }; +Wallet.prototype.sendIndexes = function(recipients) { + this.log('### INDEXES TO:', recipients || 'All', this.publicKeyRing.indexes.toObj()); + + this.network.send(recipients, { + type: 'indexes', + indexes: this.publicKeyRing.indexes.toObj(), + walletId: this.id, + }); +}; Wallet.prototype.getName = function() { return this.name || this.id; @@ -390,7 +412,7 @@ Wallet.prototype._doGenerateAddress = function(isChange) { Wallet.prototype.generateAddress = function(isChange, cb) { var addr = this._doGenerateAddress(isChange); - this.sendPublicKeyRing(); + this.sendIndexes(); this.store(); if (cb) return cb(addr); return addr; @@ -596,7 +618,7 @@ Wallet.prototype.createTx = function(toAddress, amountSatStr, opts, cb) { this.getUnspent(function(err, safeUnspent) { var ntxid = self.createTxSync(toAddress, amountSatStr, safeUnspent, opts); if (ntxid) { - self.sendPublicKeyRing(); + self.sendIndexes(); self.sendTxProposals(null, ntxid); self.store(); self.emit('txProposalsUpdated'); From 77a7bda71ba32636688bcdbc5eed1a09216e1aef Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Wed, 4 Jun 2014 14:28:47 -0300 Subject: [PATCH 4/4] clean imports --- js/models/core/AddressIndex.js | 9 --------- js/models/core/PublicKeyRing.js | 3 --- 2 files changed, 12 deletions(-) diff --git a/js/models/core/AddressIndex.js b/js/models/core/AddressIndex.js index 94328b40e..8bfe2ffb6 100644 --- a/js/models/core/AddressIndex.js +++ b/js/models/core/AddressIndex.js @@ -2,15 +2,6 @@ var imports = require('soop').imports(); -var bitcore = require('bitcore'); -var HK = bitcore.HierarchicalKey; -var PrivateKey = require('./PrivateKey'); -var Structure = require('./Structure'); -var Address = bitcore.Address; -var Script = bitcore.Script; -var coinUtil = bitcore.util; -var Transaction = bitcore.Transaction -var util = bitcore.util; function AddressIndex(opts) { opts = opts || {}; diff --git a/js/models/core/PublicKeyRing.js b/js/models/core/PublicKeyRing.js index 270bf8d4d..38fc912e0 100644 --- a/js/models/core/PublicKeyRing.js +++ b/js/models/core/PublicKeyRing.js @@ -10,9 +10,6 @@ var Structure = require('./Structure'); var AddressIndex= require('./AddressIndex'); var Address = bitcore.Address; var Script = bitcore.Script; -var coinUtil = bitcore.util; -var Transaction = bitcore.Transaction -var util = bitcore.util; function PublicKeyRing(opts) { opts = opts || {};