From 781adacbefa6338109766ca888f1bd71daa70aa2 Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Tue, 17 Jun 2014 14:28:26 -0300 Subject: [PATCH 1/6] fix dependency management --- js/models/core/Wallet.js | 1 - 1 file changed, 1 deletion(-) diff --git a/js/models/core/Wallet.js b/js/models/core/Wallet.js index f0e94993d..ebbb54c05 100644 --- a/js/models/core/Wallet.js +++ b/js/models/core/Wallet.js @@ -121,7 +121,6 @@ Wallet.prototype._handleTxProposal = function(senderId, data) { this.log('RECV TXPROPOSAL:', data); var inTxp = TxProposals.TxProposal.fromObj(data.txProposal); - var mergeInfo = this.txProposals.merge(inTxp); var added = this.addSeenToTxProposals(); From 542f6d5ceab9b9d2a4f89e0c06bb4cdf1e4338a6 Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Wed, 18 Jun 2014 10:09:40 -0300 Subject: [PATCH 2/6] add preconditions and tests --- test/test.Wallet.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/test.Wallet.js b/test/test.Wallet.js index 4c89a54b4..8715cf7bc 100644 --- a/test/test.Wallet.js +++ b/test/test.Wallet.js @@ -753,6 +753,12 @@ describe('Wallet model', function() { data.addressBook['msj42CCGruhRsFrGATiUuh25dtxYtnpbTx'].createdTs = 1403102215; w._handleAddressBook('senderID', data, true); Object.keys(w.addressBook).length.should.equal(3); + w.sendTxProposal.should.throw('Illegal Argument.'); + (function() { + w.sendTxProposal(ntxid) + }).should.not.throw(); + done(); + }); }); it('#getNetworkName', function() { From cf159241a98ea4c9c44483b8af1b98d7a370afa4 Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Wed, 18 Jun 2014 18:39:29 -0300 Subject: [PATCH 3/6] working towards fixing tests with new rules --- js/models/core/PublicKeyRing.js | 2 ++ js/models/core/TxProposals.js | 19 ++++++++++++++----- js/models/core/Wallet.js | 5 +++-- test/test.TxProposals.js | 28 ++++++++++++++++++---------- 4 files changed, 37 insertions(+), 17 deletions(-) diff --git a/js/models/core/PublicKeyRing.js b/js/models/core/PublicKeyRing.js index fdb0ad8e8..90f1a199e 100644 --- a/js/models/core/PublicKeyRing.js +++ b/js/models/core/PublicKeyRing.js @@ -3,6 +3,7 @@ var imports = require('soop').imports(); +var preconditions = require('preconditions').instance(); var bitcore = require('bitcore'); var HK = bitcore.HierarchicalKey; var PrivateKey = require('./PrivateKey'); @@ -62,6 +63,7 @@ PublicKeyRing.prototype.toObj = function() { }; PublicKeyRing.prototype.getCopayerId = function(i) { + preconditions.checkArgument(typeof i !== 'undefined'); return this.copayerIds[i]; }; diff --git a/js/models/core/TxProposals.js b/js/models/core/TxProposals.js index 2851abf36..c13a7bcfc 100644 --- a/js/models/core/TxProposals.js +++ b/js/models/core/TxProposals.js @@ -51,9 +51,9 @@ TxProposal.getSentTs = function() { return this.sentTs; }; -TxProposal.prototype.merge = function(other) { +TxProposal.prototype.merge = function(other, author) { var ret = {}; - ret.events = this.mergeMetadata(other); + ret.events = this.mergeMetadata(other, author); ret.hasChanged = this.mergeBuilder(other); return ret; }; @@ -69,7 +69,7 @@ TxProposal.prototype.mergeBuilder = function(other) { return after !== before; }; -TxProposal.prototype.mergeMetadata = function(v1) { +TxProposal.prototype.mergeMetadata = function(v1, author) { var events = []; var v0 = this; @@ -77,6 +77,7 @@ TxProposal.prototype.mergeMetadata = function(v1) { Object.keys(v1.seenBy).forEach(function(k) { if (!v0.seenBy[k]) { + if (k != author) throw new Error('Non authoritative seenBy change by '+author); v0.seenBy[k] = v1.seenBy[k]; events.push({ type: 'seen', @@ -88,6 +89,7 @@ TxProposal.prototype.mergeMetadata = function(v1) { Object.keys(v1.signedBy).forEach(function(k) { if (!v0.signedBy[k]) { + if (k != author) throw new Error('Non authoritative signedBy change by '+author); v0.signedBy[k] = v1.signedBy[k]; events.push({ type: 'signed', @@ -99,6 +101,7 @@ TxProposal.prototype.mergeMetadata = function(v1) { Object.keys(v1.rejectedBy).forEach(function(k) { if (!v0.rejectedBy[k]) { + if (k != author) throw new Error('Non authoritative rejectedBy change by '+author); v0.rejectedBy[k] = v1.rejectedBy[k]; events.push({ type: 'rejected', @@ -168,7 +171,7 @@ TxProposals.prototype.toObj = function(onlyThisNtxid) { }; }; -TxProposals.prototype.merge = function(inTxp) { +TxProposals.prototype.merge = function(inTxp, author) { var myTxps = this.txps; var ntxid = inTxp.getID(); @@ -179,7 +182,7 @@ TxProposals.prototype.merge = function(inTxp) { if (myTxps[ntxid]) { var v0 = myTxps[ntxid]; var v1 = inTxp; - ret = v0.merge(v1); + ret = v0.merge(v1, author); } else { this.txps[ntxid] = inTxp; ret.hasChanged = true; @@ -192,7 +195,13 @@ TxProposals.prototype.merge = function(inTxp) { return ret; }; +var preconditions = require('preconditions').instance(); TxProposals.prototype.add = function(data) { + preconditions.checkArgument(data.inputChainPaths); + preconditions.checkArgument(data.signedBy); + preconditions.checkArgument(data.creator); + preconditions.checkArgument(data.createdTs); + preconditions.checkArgument(data.builder); var txp = new TxProposal(data); var ntxid = txp.getID(); this.txps[ntxid] = txp; diff --git a/js/models/core/Wallet.js b/js/models/core/Wallet.js index ebbb54c05..0bf8eabb0 100644 --- a/js/models/core/Wallet.js +++ b/js/models/core/Wallet.js @@ -118,10 +118,11 @@ Wallet.prototype._handlePublicKeyRing = function(senderId, data, isInbound) { Wallet.prototype._handleTxProposal = function(senderId, data) { + preconditions.checkArgument(senderId); this.log('RECV TXPROPOSAL:', data); var inTxp = TxProposals.TxProposal.fromObj(data.txProposal); - var mergeInfo = this.txProposals.merge(inTxp); + var mergeInfo = this.txProposals.merge(inTxp, senderId); var added = this.addSeenToTxProposals(); this.emit('txProposalsUpdated'); @@ -498,6 +499,7 @@ Wallet.prototype.reject = function(ntxid) { Wallet.prototype.sign = function(ntxid, cb) { + preconditions.checkState(typeof this.getMyCopayerId() !== 'undefined'); var self = this; setTimeout(function() { var myId = self.getMyCopayerId(); @@ -709,7 +711,6 @@ Wallet.prototype.createTxSync = function(toAddress, amountSatStr, comment, utxos }]); var selectedUtxos = b.getSelectedUnspent(); - var inputChainPaths = selectedUtxos.map(function(utxo) { return pkr.pathForAddress(utxo.address); }); diff --git a/test/test.TxProposals.js b/test/test.TxProposals.js index ccd930ec4..6b129967b 100644 --- a/test/test.TxProposals.js +++ b/test/test.TxProposals.js @@ -149,16 +149,23 @@ describe('TxProposals model', function() { address: toAddress, amountSat: amountSat }]); + var selectedUtxos = b.getSelectedUnspent(); + var inputChainPaths = selectedUtxos.map(function(utxo) { + return pkr.pathForAddress(utxo.address); + }); var signRet; if (priv) { - var pkeys = priv.getAll(pkr.indexes.getReceiveIndex(), pkr.indexes.getChangeIndex()); + var pkeys = priv.getForPaths(inputChainPaths); b.sign(pkeys); } var me = {}; - if (priv) me[priv.id] = Date.now(); + if (priv) me[priv.getId()] = Date.now(); return { + inputChainPaths: inputChainPaths, + creator: priv.getId(), + createdTs: new Date(), signedBy: priv && b.signaturesAdded ? me : {}, seenBy: priv ? me : {}, builder: b, @@ -216,10 +223,11 @@ describe('TxProposals model', function() { tx.isComplete().should.equal(false); tx.countInputMissingSignatures(0).should.equal(2); - (w.txps[ntxid].signedBy[priv.id] - ts > 0).should.equal(true); + var x = priv.getId(); + (w.txps[ntxid].signedBy[priv.getId()] - ts > 0).should.equal(true); (w.txps[ntxid].seenBy[priv.id] - ts > 0).should.equal(true); - var info = w.merge(w.txps[ntxid]); + var info = w.merge(w.txps[ntxid], pkr.getCopayerId(0)); info.events.length.should.equal(0); Object.keys(w.txps).length.should.equal(1); @@ -293,7 +301,7 @@ describe('TxProposals model', function() { (w2.txps[ntxid].signedBy[priv.id] - ts > 0).should.equal(true); (w2.txps[ntxid].seenBy[priv.id] - ts > 0).should.equal(true); - var info = w.merge(w2.txps[ntxid]); + var info = w.merge(w2.txps[ntxid], pkr.getCopayerId(0)); info.events.length.should.equal(1); info.events[0].type.should.equal('signed'); @@ -401,7 +409,7 @@ describe('TxProposals model', function() { (w2.txps[ntxid].signedBy[priv.id] - ts > 0).should.equal(true); (w2.txps[ntxid].seenBy[priv.id] - ts > 0).should.equal(true); - var info = w.merge(w2.txps[ntxid]); + var info = w.merge(w2.txps[ntxid], pkr.getCopayerId(0)); info.events.length.should.equal(1); info.events[0].type.should.equal('signed'); @@ -431,7 +439,7 @@ describe('TxProposals model', function() { (w3.txps[ntxid].signedBy[priv2.id] - ts > 0).should.equal(true); (w3.txps[ntxid].seenBy[priv2.id] - ts > 0).should.equal(true); - var info = w.merge(w3.txps[ntxid]); + var info = w.merge(w3.txps[ntxid], pkr.getCopayerId(0)); info.events.length.should.equal(0); Object.keys(w.txps).length.should.equal(1); @@ -522,7 +530,7 @@ describe('TxProposals model', function() { (w3.txps[ntxid].signedBy[priv3.id] - ts > 0).should.equal(true); (w3.txps[ntxid].seenBy[priv3.id] - ts > 0).should.equal(true); - var info = w.merge(w2.txps[ntxid]); + var info = w.merge(w2.txps[ntxid], pkr.getCopayerId(0)); info.events.length.should.equal(0); Object.keys(w.txps).length.should.equal(1); @@ -535,7 +543,7 @@ describe('TxProposals model', function() { (w.txps[ntxid].signedBy[priv2.id] - ts > 0).should.equal(true); - var info = w.merge(w3.txps[ntxid]); + var info = w.merge(w3.txps[ntxid], pkr.getCopayerId(0)); info.events.length.should.equal(0); var tx = w.txps[ntxid].builder.build(); @@ -601,7 +609,7 @@ describe('TxProposals model', function() { should.exist(w2.txps[ntxid].builder); should.exist(w2.txps[ntxid].builder.valueInSat); - w2.merge(w.txps[ntxid]); + w2.merge(w.txps[ntxid], pkr.getCopayerId(0)); Object.keys(w2.txps).length.should.equal(1); }); From 6252047cd3c6368e24d732c74fbcbbf891a97cfc Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Thu, 19 Jun 2014 11:28:50 -0300 Subject: [PATCH 4/6] fix tests --- test/test.TxProposals.js | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/test/test.TxProposals.js b/test/test.TxProposals.js index 6b129967b..de7719b4f 100644 --- a/test/test.TxProposals.js +++ b/test/test.TxProposals.js @@ -302,8 +302,9 @@ describe('TxProposals model', function() { (w2.txps[ntxid].seenBy[priv.id] - ts > 0).should.equal(true); var info = w.merge(w2.txps[ntxid], pkr.getCopayerId(0)); - info.events.length.should.equal(1); - info.events[0].type.should.equal('signed'); + info.events.length.should.equal(2); + info.events[0].type.should.equal('seen'); + info.events[1].type.should.equal('signed'); Object.keys(w.txps).length.should.equal(1); @@ -410,8 +411,9 @@ describe('TxProposals model', function() { (w2.txps[ntxid].seenBy[priv.id] - ts > 0).should.equal(true); var info = w.merge(w2.txps[ntxid], pkr.getCopayerId(0)); - info.events.length.should.equal(1); - info.events[0].type.should.equal('signed'); + info.events.length.should.equal(2); + info.events[0].type.should.equal('seen'); + info.events[1].type.should.equal('signed'); tx = w.txps[ntxid].builder.build(); tx.isComplete().should.equal(false); @@ -439,8 +441,7 @@ describe('TxProposals model', function() { (w3.txps[ntxid].signedBy[priv2.id] - ts > 0).should.equal(true); (w3.txps[ntxid].seenBy[priv2.id] - ts > 0).should.equal(true); - var info = w.merge(w3.txps[ntxid], pkr.getCopayerId(0)); - info.events.length.should.equal(0); + var info = w.merge(w3.txps[ntxid], pkr.getCopayerId(1)); Object.keys(w.txps).length.should.equal(1); @@ -530,8 +531,7 @@ describe('TxProposals model', function() { (w3.txps[ntxid].signedBy[priv3.id] - ts > 0).should.equal(true); (w3.txps[ntxid].seenBy[priv3.id] - ts > 0).should.equal(true); - var info = w.merge(w2.txps[ntxid], pkr.getCopayerId(0)); - info.events.length.should.equal(0); + var info = w.merge(w2.txps[ntxid], pkr.getCopayerId(1)); Object.keys(w.txps).length.should.equal(1); var tx = w.txps[ntxid].builder.build(); @@ -543,8 +543,7 @@ describe('TxProposals model', function() { (w.txps[ntxid].signedBy[priv2.id] - ts > 0).should.equal(true); - var info = w.merge(w3.txps[ntxid], pkr.getCopayerId(0)); - info.events.length.should.equal(0); + var info = w.merge(w3.txps[ntxid], pkr.getCopayerId(2)); var tx = w.txps[ntxid].builder.build(); tx.isComplete().should.equal(true); From f4a5202a999a11060a1f762389b336eb3978b645 Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Thu, 19 Jun 2014 12:38:21 -0300 Subject: [PATCH 5/6] add seenBy fix --- js/models/core/Wallet.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/js/models/core/Wallet.js b/js/models/core/Wallet.js index 0bf8eabb0..e360fb5b2 100644 --- a/js/models/core/Wallet.js +++ b/js/models/core/Wallet.js @@ -125,6 +125,11 @@ Wallet.prototype._handleTxProposal = function(senderId, data) { var mergeInfo = this.txProposals.merge(inTxp, senderId); var added = this.addSeenToTxProposals(); + if (added) { + this.log('### BROADCASTING txProposals with my seenBy updated.'); + this.sendTxProposal(inTxp.getID()); + } + this.emit('txProposalsUpdated'); this.store(); From 3ce3af440817909ac8ea8cd7a93c0bd37d52d327 Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Mon, 23 Jun 2014 10:59:33 -0300 Subject: [PATCH 6/6] fix merge with master --- test/test.Wallet.js | 73 +++++++++++++++++++++++---------------------- 1 file changed, 38 insertions(+), 35 deletions(-) diff --git a/test/test.Wallet.js b/test/test.Wallet.js index 8715cf7bc..08872a753 100644 --- a/test/test.Wallet.js +++ b/test/test.Wallet.js @@ -67,13 +67,13 @@ describe('Wallet model', function() { c.network = new Network(config.network); c.blockchain = new Blockchain(config.blockchain); - c.addressBook = { - '2NFR2kzH9NUdp8vsXTB4wWQtTtzhpKxsyoJ' : { + c.addressBook = { + '2NFR2kzH9NUdp8vsXTB4wWQtTtzhpKxsyoJ': { label: 'John', copayerId: '026a55261b7c898fff760ebe14fd22a71892295f3b49e0ca66727bc0a0d7f94d03', createdTs: 1403102115, - }, - '2MtP8WyiwG7ZdVWM96CVsk2M1N8zyfiVQsY' : { + }, + '2MtP8WyiwG7ZdVWM96CVsk2M1N8zyfiVQsY': { label: 'Jennifer', copayerId: '032991f836543a492bd6d0bb112552bfc7c5f3b7d5388fcbcbf2fbb893b44770d7', createdTs: 1403103115, @@ -312,7 +312,7 @@ describe('Wallet model', function() { setTimeout(function() { sinon.assert.callCount(spy, callCount); done(); - }, w.reconnectDelay*callCount*(callCount+1)/2); + }, w.reconnectDelay * callCount * (callCount + 1) / 2); }); it('handle network indexes correctly', function() { @@ -616,7 +616,7 @@ describe('Wallet model', function() { var ADDRESSES_RECEIVE = w.deriveAddresses(0, 20, false); w.blockchain.checkActivity = function(addresses, cb) { var activity = new Array(addresses.length); - for(var i=0; i