From b49661ebd83099e284f5ae930afa2df9798d0a8c Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Fri, 31 Oct 2014 12:27:22 -0300 Subject: [PATCH 1/5] split ts, better syncing --- js/models/Async.js | 15 +++++++++++- js/models/Identity.js | 2 +- js/models/Wallet.js | 45 ++++++++++++++++++++++------------ js/services/controllerUtils.js | 12 ++++----- 4 files changed, 50 insertions(+), 24 deletions(-) diff --git a/js/models/Async.js b/js/models/Async.js index 60f089030..1d31c01e8 100644 --- a/js/models/Async.js +++ b/js/models/Async.js @@ -204,6 +204,11 @@ Network.prototype._onMessage = function(enc) { } log.debug('Async: receiving ' + JSON.stringify(payload)); + if (this.ignoreMessageFromTs && this.ignoreMessageFromTs === enc.ts) { + log.debug('Ignoring message from ', enc.ts); + return; + } + var self = this; switch (payload.type) { case 'hello': @@ -247,7 +252,15 @@ Network.prototype._setupConnectionHandlers = function(opts, cb) { }); self.socket.on('subscribed', function(m) { - var fromTs = (opts.lastTimestamp || 0) + 1; + var fromTs = opts.syncedTimestamp || 0; + + // We ask for this message, and then ignore it, only to see if the + // server has erased our old messages. + + if (fromTs) { + self.ignoreMessageFromTs = fromTs; + } + log.info('Async: synchronizing from: ',fromTs); self.socket.emit('sync', fromTs); self.started = true; }); diff --git a/js/models/Identity.js b/js/models/Identity.js index f52125772..c3c6174c4 100644 --- a/js/models/Identity.js +++ b/js/models/Identity.js @@ -566,7 +566,7 @@ Identity.prototype.decodeSecret = function(secret) { Identity.prototype.getLastFocusedWallet = function() { if (_.keys(this.wallets).length == 0) return; return _.max(this.wallets, function(wallet) { - return wallet.lastTimestamp || 0; + return wallet.focusedTimestamp || 0; }); }; diff --git a/js/models/Wallet.js b/js/models/Wallet.js index 8c63878f6..efd145cbe 100644 --- a/js/models/Wallet.js +++ b/js/models/Wallet.js @@ -92,7 +92,9 @@ function Wallet(opts) { this.registeredPeerIds = []; this.addressBook = opts.addressBook || {}; this.publicKey = this.privateKey.publicHex; - this.lastTimestamp = opts.lastTimestamp || 0; + this.focusedTimestamp = opts.focusedTimestamp || 0; + this.syncedTimestamp = opts.syncedTimestamp || 0; +console.log('[Wallet.js.96:syncedTimestamp:]',this.syncedTimestamp); //TODO this.lastMessageFrom = {}; this.paymentRequests = opts.paymentRequests || {}; @@ -147,7 +149,8 @@ Wallet.PERSISTED_PROPERTIES = [ 'txProposals', 'privateKey', 'addressBook', - 'lastTimestamp', + 'focusedTimestamp', + 'syncedTimestamp', 'secretNumber', ]; @@ -571,24 +574,31 @@ Wallet.prototype._onAddressBook = function(senderId, data) { * @desc Updates the wallet's last modified timestamp and triggers a save * @param {number} ts - the timestamp */ -Wallet.prototype.updateTimestamp = function(ts, callback) { +Wallet.prototype.updateFocusedTimestamp = function(ts) { preconditions.checkArgument(ts); preconditions.checkArgument(_.isNumber(ts)); - this.lastTimestamp = ts; - // we dont store here - if (callback) { - return callback(null); - } + preconditions.checkArgument(ts > 2999999999, 'use miliseconds'); + this.focusedTimestamp = ts; }; +Wallet.prototype.updateSyncedTimestamp = function(ts) { + preconditions.checkArgument(ts); + preconditions.checkArgument(_.isNumber(ts)); + preconditions.checkArgument(ts > 2999999999999, 'use microseconds'); + this.syncedTimestamp = ts; +}; + + + /** * @desc Called when there are no messages in the server * Triggers a call to {@link Wallet#sendWalletReady} */ Wallet.prototype._onNoMessages = function() { - log.debug('Wallet:' + this.id + ' No messages at the server. Requesting peer sync from: ' + (this.lastTimestamp + 1)); - this.sendWalletReady(null, parseInt((this.lastTimestamp + 1) / 1000)); - this.updateTimestamp(parseInt(Date.now() / 1000)); + if (!this.isShared()) return; + + log.debug('Wallet:' + this.id + ' No messages at the server. Requesting peer sync from: ' + (this.syncedTimestamp + 1)); + this.sendWalletReady(null, parseInt((this.syncedTimestamp + 1) / 1000000)); }; /** @@ -608,7 +618,7 @@ Wallet.prototype._onData = function(senderId, data, ts) { preconditions.checkArgument(_.isNumber(ts)); log.debug('Wallet:' + this.id + ' RECV', senderId, data); - this.updateTimestamp(ts); + this.updateSyncedTimestamp(ts); if (data.type !== 'walletId' && this.id !== data.walletId) { log.debug('Wallet:' + this.id + ' Received corrupt message:', data) @@ -872,7 +882,7 @@ Wallet.prototype.netStart = function() { copayerId: myId, privkey: myIdPriv, maxPeers: self.totalCopayers, - lastTimestamp: this.lastTimestamp || 0, + syncedTimestamp: this.syncedTimestamp || 0, secretNumber: self.secretNumber, }; @@ -967,7 +977,8 @@ Wallet.prototype.toObj = function() { txProposals: this.txProposals.toObj(), privateKey: this.privateKey ? this.privateKey.toObj() : undefined, addressBook: this.addressBook, - lastTimestamp: this.lastTimestamp || 0, + syncedTimestamp: this.syncedTimestamp || 0, + focusedTimestamp: this.focusedTimestamp || 0, secretNumber: this.secretNumber, }; @@ -993,7 +1004,7 @@ Wallet.fromUntrustedObj = function(obj, readOpts) { * @param {Object} o.privateKey - Private key to be deserialized by {@link PrivateKey#fromObj} * @param {string} o.networkName - 'livenet' or 'testnet' * @param {Object} o.publicKeyRing - PublicKeyRing to be deserialized by {@link PublicKeyRing#fromObj} - * @param {number} o.lastTimestamp - last time this wallet object was deserialized + * @param {number} o.Timestamp - last time this wallet object was deserialized * @param {Object} o.txProposals - TxProposals to be deserialized by {@link TxProposals#fromObj} * @param {string} o.nickname - user's nickname * @@ -1065,7 +1076,8 @@ Wallet.fromObj = function(o, readOpts) { }); } - opts.lastTimestamp = o.lastTimestamp || 0; + opts.syncedTimestamp = o.syncedTimestamp || 0; + opts.focusedTimestamp = o.focusedTimestamp || 0; opts.blockchainOpts = readOpts.blockchainOpts; opts.networkOpts = readOpts.networkOpts; @@ -1073,6 +1085,7 @@ Wallet.fromObj = function(o, readOpts) { return new Wallet(opts); }; + /** * @desc Send a message to other peers * @param {string[]} recipients - the pubkey of the recipients of the message diff --git a/js/services/controllerUtils.js b/js/services/controllerUtils.js index b371bd332..51243c5e0 100644 --- a/js/services/controllerUtils.js +++ b/js/services/controllerUtils.js @@ -205,15 +205,15 @@ angular.module('copayApp.services') root.setFocusedWallet = function(w) { if (!_.isObject(w)) w = $rootScope.iden.getWalletById(w); + preconditions.checkState(w && _.isObject(w)); $rootScope.wallet = w; - w.updateTimestamp(new Date().getTime(), function() { - root.redirIfLogged(); - root.updateBalance(w, function() { - $rootScope.$digest(); - }) - }); + w.updateFocusedTimestamp(Date.now()); + root.redirIfLogged(); + root.updateBalance(w, function() { + $rootScope.$digest(); + }) }; root.bindProfile = function($scope, iden, w) { From f39588e295bf2b30672aec48e0db3cffb7ae8b6a Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Fri, 31 Oct 2014 14:06:48 -0300 Subject: [PATCH 2/5] rm console.log --- js/models/Wallet.js | 1 - 1 file changed, 1 deletion(-) diff --git a/js/models/Wallet.js b/js/models/Wallet.js index efd145cbe..d323b60bf 100644 --- a/js/models/Wallet.js +++ b/js/models/Wallet.js @@ -94,7 +94,6 @@ function Wallet(opts) { this.publicKey = this.privateKey.publicHex; this.focusedTimestamp = opts.focusedTimestamp || 0; this.syncedTimestamp = opts.syncedTimestamp || 0; -console.log('[Wallet.js.96:syncedTimestamp:]',this.syncedTimestamp); //TODO this.lastMessageFrom = {}; this.paymentRequests = opts.paymentRequests || {}; From b3e42cb427be0f56c67ce2db83cb049bda412abf Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Fri, 31 Oct 2014 14:08:50 -0300 Subject: [PATCH 3/5] fix docs --- js/models/Wallet.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/js/models/Wallet.js b/js/models/Wallet.js index d323b60bf..f70633adf 100644 --- a/js/models/Wallet.js +++ b/js/models/Wallet.js @@ -1003,7 +1003,8 @@ Wallet.fromUntrustedObj = function(obj, readOpts) { * @param {Object} o.privateKey - Private key to be deserialized by {@link PrivateKey#fromObj} * @param {string} o.networkName - 'livenet' or 'testnet' * @param {Object} o.publicKeyRing - PublicKeyRing to be deserialized by {@link PublicKeyRing#fromObj} - * @param {number} o.Timestamp - last time this wallet object was deserialized + * @param {number} o.syncedTimestamp - ts of the last synced message with insifht (in microseconds, as insight returns ts) + * @param {number} o.focusedTimestamp - last time this wallet was focused (open) by a user (in miliseconds) * @param {Object} o.txProposals - TxProposals to be deserialized by {@link TxProposals#fromObj} * @param {string} o.nickname - user's nickname * From 5adc4fd5d2429b4e3043e9cf49b4e91ef4e34c4b Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Fri, 31 Oct 2014 15:49:56 -0300 Subject: [PATCH 4/5] add debounce --- js/models/Identity.js | 41 ++++++++++++++++++++--------------------- js/models/Wallet.js | 4 ++-- 2 files changed, 22 insertions(+), 23 deletions(-) diff --git a/js/models/Identity.js b/js/models/Identity.js index c3c6174c4..97832d96f 100644 --- a/js/models/Identity.js +++ b/js/models/Identity.js @@ -182,13 +182,6 @@ Identity.prototype.retrieveWalletFromStorage = function(walletId, opts, callback }); }; -/** - * TODO (matiu): What is this supposed to do? - */ -Identity.isAvailable = function(email, opts, cb) { - return cb(); -}; - /** * @param {Wallet} wallet * @param {Function} cb @@ -198,6 +191,7 @@ Identity.prototype.storeWallet = function(wallet, cb) { var val = wallet.toObj(); var key = wallet.getStorageKey(); + log.debug('Storing wallet:' + wallet.getName()); this.storage.setItem(key, val, function(err) { if (err) { @@ -208,6 +202,18 @@ Identity.prototype.storeWallet = function(wallet, cb) { }); }; + +/** + * @param {Identity} identity + * @param {Wallet} wallet + * @param {Function} cb + */ +Identity.storeWalletDebounced = _.debounce(function(identity, wallet, cb) { + identity.storeWallet(wallet,cb); +}, 3000); + + + Identity.prototype.toObj = function() { return _.extend({ walletIds: _.keys(this.wallets) @@ -373,36 +379,29 @@ Identity.prototype.bindWallet = function(w) { log.debug('Binding wallet ' + w.getName()); w.on('txProposalsUpdated', function() { - log.debug('> Wallet' + w.getName()); - self.storeWallet(w); + Identity.storeWalletDebounced(self, w); }); w.on('newAddresses', function() { - log.debug(' Wallet' + w.getName()); - self.storeWallet(w); + Identity.storeWalletDebounced(self, w); }); w.on('settingsUpdated', function() { - log.debug(' Wallet' + w.getName()); - self.storeWallet(w); + Identity.storeWalletDebounced(self, w); }); w.on('txProposalEvent', function() { - log.debug(' Wallet' + w.getName()); - self.storeWallet(w); + Identity.storeWalletDebounced(self, w); }); w.on('ready', function() { - log.debug(' Wallet' + w.getName()); self.store({ noWallets: true }, function() { - self.storeWallet(w); + Identity.storeWalletDebounced(self, w); }); }); w.on('addressBookUpdated', function() { - log.debug(' Wallet' + w.getName()); - self.storeWallet(w); + Identity.storeWalletDebounced(self, w); }); w.on('publicKeyRingUpdated', function() { - log.debug(' Wallet' + w.getName()); - self.storeWallet(w); + Identity.storeWalletDebounced(self, w); }); }; diff --git a/js/models/Wallet.js b/js/models/Wallet.js index f70633adf..5aeff5161 100644 --- a/js/models/Wallet.js +++ b/js/models/Wallet.js @@ -580,6 +580,7 @@ Wallet.prototype.updateFocusedTimestamp = function(ts) { this.focusedTimestamp = ts; }; + Wallet.prototype.updateSyncedTimestamp = function(ts) { preconditions.checkArgument(ts); preconditions.checkArgument(_.isNumber(ts)); @@ -588,7 +589,6 @@ Wallet.prototype.updateSyncedTimestamp = function(ts) { }; - /** * @desc Called when there are no messages in the server * Triggers a call to {@link Wallet#sendWalletReady} @@ -617,6 +617,7 @@ Wallet.prototype._onData = function(senderId, data, ts) { preconditions.checkArgument(_.isNumber(ts)); log.debug('Wallet:' + this.id + ' RECV', senderId, data); + this.updateSyncedTimestamp(ts); if (data.type !== 'walletId' && this.id !== data.walletId) { @@ -631,7 +632,6 @@ Wallet.prototype._onData = function(senderId, data, ts) { this.sendWalletReady(senderId); break; case 'walletReady': - if (this.lastMessageFrom[senderId] !== 'walletReady') { log.debug('Wallet:' + this.id + ' peer Sync received. since: ' + (data.sinceTs || 0)); this.sendPublicKeyRing(senderId); From ed4d08f48b12496374256523f98331b9677ee7cc Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Fri, 31 Oct 2014 16:36:12 -0300 Subject: [PATCH 5/5] add err to log --- js/models/Identity.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/models/Identity.js b/js/models/Identity.js index 97832d96f..abae78376 100644 --- a/js/models/Identity.js +++ b/js/models/Identity.js @@ -195,7 +195,7 @@ Identity.prototype.storeWallet = function(wallet, cb) { this.storage.setItem(key, val, function(err) { if (err) { - log.debug('Wallet:' + wallet.getName() + ' couldnt be stored'); + log.debug('Wallet:' + wallet.getName() + ' couldnt be stored:', err); } if (cb) return cb(err);