From 889edf4b920086fafd2a8aadeaa50efba5f4b22c Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Wed, 18 Jun 2014 10:09:40 -0300 Subject: [PATCH] add preconditions and tests --- js/models/core/TxProposals.js | 9 +-- js/models/core/Wallet.js | 29 ++++++---- package.json | 3 +- test/test.TxProposals.js | 14 ++--- test/test.Wallet.js | 101 ++++++++++++++++++---------------- 5 files changed, 87 insertions(+), 69 deletions(-) diff --git a/js/models/core/TxProposals.js b/js/models/core/TxProposals.js index 655b36f9f..83945b7b3 100644 --- a/js/models/core/TxProposals.js +++ b/js/models/core/TxProposals.js @@ -54,8 +54,7 @@ TxProposal.getSentTs = function() { TxProposal.prototype.merge = function(other) { var ret = {}; ret.events = this.mergeMetadata(other); - ret.hasChanged = this.mergeBuilder(other); // TODO: use this? - + ret.hasChanged = this.mergeBuilder(other); return ret; }; @@ -151,6 +150,7 @@ TxProposals.prototype.getNtxids = function() { }; TxProposals.prototype.toObj = function(onlyThisNtxid) { + if (onlyThisNtxid) throw new Error(); var ret = []; for (var id in this.txps) { @@ -172,14 +172,15 @@ TxProposals.prototype.merge = function(inTxp) { var myTxps = this.txps; var ntxid = inTxp.getID(); - var ret; + var ret = {}; + ret.events = []; + ret.events.hasChanged = false; if (myTxps[ntxid]) { var v0 = myTxps[ntxid]; var v1 = inTxp; ret = v0.merge(v1); } else { - ret.events = {}; ret.hasChanged = true; ret.events.push({ type: 'new', diff --git a/js/models/core/Wallet.js b/js/models/core/Wallet.js index 920ed9fcd..6d415ea56 100644 --- a/js/models/core/Wallet.js +++ b/js/models/core/Wallet.js @@ -5,6 +5,7 @@ var imports = require('soop').imports(); var http = require('http'); var EventEmitter = imports.EventEmitter || require('events').EventEmitter; var async = require('async'); +var preconditions = require('preconditions').instance(); var bitcore = require('bitcore'); var bignum = bitcore.Bignum; @@ -126,7 +127,7 @@ Wallet.prototype._handleTxProposal = function(senderId, data) { if (mergeInfo.hasChanged || added) { this.log('### BROADCASTING txProposals. '); - this.sendTxProposals(null, inTxp.getID()); + this.sendTxProposal(inTxp.getID()); } this.emit('txProposalsUpdated'); @@ -153,7 +154,7 @@ Wallet.prototype._handleData = function(senderId, data, isInbound) { break; case 'walletReady': this.sendPublicKeyRing(senderId); - this.sendTxProposals(senderId); // send old + this.sendAllTxProposals(senderId); // send old txps break; case 'publicKeyRing': this._handlePublicKeyRing(senderId, data, isInbound); @@ -355,12 +356,20 @@ Wallet.prototype.toEncryptedObj = function() { return this.storage.export(walletObj); }; -Wallet.prototype.sendTxProposal = function(recipients, ntxid) { - this.log('### SENDING txProposals TO:', recipients || 'All', this.txProposals); - var id = toSend[i]; +Wallet.prototype.sendAllTxProposals = function(recipients) { + var ntxids = this.txProposals.getNtxids(); + for (var i in ntxids) { + var ntxid = ntxids[i]; + this.sendTxProposal(ntxid, recipients); + } +}; + +Wallet.prototype.sendTxProposal = function(ntxid, recipients) { + preconditions.checkArgument(ntxid); + this.log('### SENDING txProposal '+ntxid+' TO:', recipients || 'All', this.txProposals); this.network.send(recipients, { type: 'txProposal', - txProposals: this.txProposals.toObj(id), + txProposal: this.txProposals.txps[ntxid].toObj(), walletId: this.id, }); }; @@ -450,7 +459,7 @@ Wallet.prototype.reject = function(ntxid) { } txp.rejectedBy[myId] = Date.now(); - this.sendTxProposals(null, ntxid); + this.sendTxProposal(ntxid); this.store(); this.emit('txProposalsUpdated'); }; @@ -475,7 +484,7 @@ Wallet.prototype.sign = function(ntxid, cb) { var ret = false; if (b.signaturesAdded > before) { txp.signedBy[myId] = Date.now(); - self.sendTxProposals(null, ntxid); + self.sendTxProposal(ntxid); self.store(); self.emit('txProposalsUpdated'); ret = true; @@ -503,7 +512,7 @@ Wallet.prototype.sendTx = function(ntxid, cb) { self.log('BITCOIND txid:', txid); if (txid) { self.txProposals.setSent(ntxid, txid); - self.sendTxProposals(null, ntxid); + self.sendTxProposal(ntxid); self.store(); } return cb(txid); @@ -630,7 +639,7 @@ Wallet.prototype.createTx = function(toAddress, amountSatStr, comment, opts, cb) var ntxid = self.createTxSync(toAddress, amountSatStr, comment, safeUnspent, opts); if (ntxid) { self.sendIndexes(); - self.sendTxProposals(null, ntxid); + self.sendTxProposal(ntxid); self.store(); self.emit('txProposalsUpdated'); } diff --git a/package.json b/package.json index 626a0d965..92d07ce8b 100644 --- a/package.json +++ b/package.json @@ -58,6 +58,7 @@ }, "dependencies": { "mocha": "^1.18.2", - "mocha-lcov-reporter": "0.0.1" + "mocha-lcov-reporter": "0.0.1", + "preconditions": "^1.0.7" } } diff --git a/test/test.TxProposals.js b/test/test.TxProposals.js index 8ccaf4cba..ccd930ec4 100644 --- a/test/test.TxProposals.js +++ b/test/test.TxProposals.js @@ -219,7 +219,7 @@ describe('TxProposals model', function() { (w.txps[ntxid].signedBy[priv.id] - ts > 0).should.equal(true); (w.txps[ntxid].seenBy[priv.id] - ts > 0).should.equal(true); - var info = w.merge(w.txps[0]); + var info = w.merge(w.txps[ntxid]); info.events.length.should.equal(0); Object.keys(w.txps).length.should.equal(1); @@ -293,7 +293,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); + var info = w.merge(w2.txps[ntxid]); info.events.length.should.equal(1); info.events[0].type.should.equal('signed'); @@ -401,7 +401,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); + var info = w.merge(w2.txps[ntxid]); info.events.length.should.equal(1); info.events[0].type.should.equal('signed'); @@ -431,7 +431,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); + var info = w.merge(w3.txps[ntxid]); info.events.length.should.equal(0); Object.keys(w.txps).length.should.equal(1); @@ -522,7 +522,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); + var info = w.merge(w2.txps[ntxid]); info.events.length.should.equal(0); Object.keys(w.txps).length.should.equal(1); @@ -535,7 +535,7 @@ describe('TxProposals model', function() { (w.txps[ntxid].signedBy[priv2.id] - ts > 0).should.equal(true); - var info = w.merge(w3); + var info = w.merge(w3.txps[ntxid]); info.events.length.should.equal(0); var tx = w.txps[ntxid].builder.build(); @@ -601,7 +601,7 @@ describe('TxProposals model', function() { should.exist(w2.txps[ntxid].builder); should.exist(w2.txps[ntxid].builder.valueInSat); - w2.merge(w); + w2.merge(w.txps[ntxid]); Object.keys(w2.txps).length.should.equal(1); }); diff --git a/test/test.Wallet.js b/test/test.Wallet.js index a5d4f06e7..60a4dfe7d 100644 --- a/test/test.Wallet.js +++ b/test/test.Wallet.js @@ -37,6 +37,10 @@ describe('Wallet model', function() { }).should. throw(); }); + it('should getNetworkName', function() { + var w = createW(); + w.getNetworkName().should.equal('testnet'); + }); var createW = function(netKey, N) { @@ -358,51 +362,48 @@ describe('Wallet model', function() { it('handle network txProposals correctly', function() { var w = createW(); var txps = { - 'txProposals': { - "txps": [{ - "seenBy": { - "undefined": 1402337282806 + 'txProposal': { + "seenBy": { + "undefined": 1402337282806 + }, + "signedBy": { + "undefined": 1402337282841 + }, + "rejectedBy": {}, + "sentTs": null, + "sentTxid": null, + "inputChainPaths": [], + "builderObj": { + "valueInSat": "1000000000", + "valueOutSat": "123456789", + "feeSat": "10000", + "remainderSat": "876533211", + "hashToScriptMap": { + "3QjgeBsNeiDkoVQxDAw4sSEe9BVaqhmpnd": "5321025c2951a7e94e39f2c3210fb2d71b7d79044f7daa6b007556a6feb4b2059091e921026c56eea4ef632b24c4efe9d5391ea0e15e306450e5b7db26cd1a7a33d9d4e82821026d06e532385186793121633fb365fa2f0c7246b30590db78cba795641c94734521035051d2b742263bc5257c5a4461e1a6fa32c3f1965f5ab5e8b0f0f80c9e28bc702103ddb0d39c1cd88295e7b81050dcab11ca4419bf64fba3ef9d9130ea64d6604ab055ae", + "365dPtmHPAdUUNvPBcnfidYt2Snyaka7AH": "5321020faaf739abda51e822621d42062470c5743a127186369a67fd3303f71727fb1d210237063d3b27c21767054dad203298bfed90cb08dca371950a08b88aa979c33bd22102a3780cb275b6dcb8b379514679387d4578068745f08c5799e4ee1a90aa3a70922102f4fea0cd5bc2418892278f480682690857f4d963deeb95d88febfa255e4ce0b821035d53fa74fee26873c3f5a4acf4dce53ff9d50db59e1ca4acddb82168dd429a3355ae", + "372DueknmmjVR3zcWfEfADp8FwJ3ARhGaN": "532102666c2873c9e6f58ca594cd6c8327a1515db32ebadbaff4fe75e63b917560b7d021031ca2d159ae8868a5eef6d67a5a8a5bcc6fb2e8b711669f1c1e8b05327236a3cf2103798a4ce34929cb450bf88557dd90cae538c67f9d0c76314ae18679200be9c17021039624dec23dc1bb628cea55e949ea26225949a3349346a0732fef9def6f1f75292103d1edaadb8555012b752dd7a5c6672c379ce827e4bc0d4e992ee1ab3488b445b255ae", + "3GLJbHv7RqPeFk2SqWapqJ3XibVibiKi8f": "5321021a33d48b9f5d3adc41004709313277d4c6969268cf41e3f5b695a934c676829a21031b87321307db7a0f6ea22847a538505188f1a2231eba68867e17c5f0e4434c0721035dee0a6e1df66a6c9c7592ef03aa02bba9b06742134d27bd08f356e33f21259c2103768a109d682a76c09f865912e9e64a8689b03c1a231c613d87ec9bd535fd74c22103911038638b9fc52b2d375ce207c8388bd5ee7f2d54ab9b4148bd406c6d7dcad355ae", + "3E1d1z7gJSFeZM2d3k12MJ1jGwrBRy1YTw": "5321027da98ce0407138461f4ad803a1fb67afa4246f06ad0e1256a087daeffd82a8642102e7f87f2b094ec322be2fb99d3ca81fd6ac0ab26ce081e51ab18c507f8b6d1d162102ed5d256036e10568c33e0a15021cc1806e04d7d24c8f020aaae23ec2deecb4302103b6f88231bb5a5f4629e4d097492321f86968c6aeb012196a1fe3b217fe4ae0ac2103f6b5e2c1db3124a5058a0e3e83d5d0c412b9a5b50e2ef97e2b7e1c0af57ab3e355ae", + "3QYueyPXq2QDRQCDo7agTimz9673NKV25E": "5321021543292c2942708ccc83354ebf507044b310ed0d33a19e2327a49be53e0f314221024a1a83f8c50f6cad7c134b9cded509dabf196ae49eca157a39ad95798943dc95210292698fbb97e8f6e67296b22b36367ba85c8101fcbc27bb4b00b43623639212ac2102d86980796027a00ba7aa9b53671762c908962654f969f5dec340071bb30e8d7621038fb3fa5e77dafd24c09d819dbdc7c11dca55b350511bf3bc499c09316a89286e55ae", + "372BzC1GGjziT8zGYbryja3kF2KaTeobRK": "53210214ec25e5cb42e51883d4e615316748feefe91133fcfc0f93f0b5a24a55e0a347210262336210b3173aa4ca90d292990f463e42bdeb2e73112925dc712c5a2e749bcb210277517855f512564f225e63c650dad7720565aa563901d50743be4b0f0267dcc72102d2777a9faf5d2e2b2363e1270d61021bc2e36e8cb19ca9d29dedbba9a0348b532103a57db80b6ae573e5cef2115e36e73e5ef41f8a099bfb5087d80320c04a7db72e55ae" }, - "signedBy": { - "undefined": 1402337282841 - }, - "rejectedBy": {}, - "sentTs": null, - "sentTxid": null, - "inputChainPaths": [], - "builderObj": { - "valueInSat": "1000000000", - "valueOutSat": "123456789", - "feeSat": "10000", - "remainderSat": "876533211", - "hashToScriptMap": { - "3QjgeBsNeiDkoVQxDAw4sSEe9BVaqhmpnd": "5321025c2951a7e94e39f2c3210fb2d71b7d79044f7daa6b007556a6feb4b2059091e921026c56eea4ef632b24c4efe9d5391ea0e15e306450e5b7db26cd1a7a33d9d4e82821026d06e532385186793121633fb365fa2f0c7246b30590db78cba795641c94734521035051d2b742263bc5257c5a4461e1a6fa32c3f1965f5ab5e8b0f0f80c9e28bc702103ddb0d39c1cd88295e7b81050dcab11ca4419bf64fba3ef9d9130ea64d6604ab055ae", - "365dPtmHPAdUUNvPBcnfidYt2Snyaka7AH": "5321020faaf739abda51e822621d42062470c5743a127186369a67fd3303f71727fb1d210237063d3b27c21767054dad203298bfed90cb08dca371950a08b88aa979c33bd22102a3780cb275b6dcb8b379514679387d4578068745f08c5799e4ee1a90aa3a70922102f4fea0cd5bc2418892278f480682690857f4d963deeb95d88febfa255e4ce0b821035d53fa74fee26873c3f5a4acf4dce53ff9d50db59e1ca4acddb82168dd429a3355ae", - "372DueknmmjVR3zcWfEfADp8FwJ3ARhGaN": "532102666c2873c9e6f58ca594cd6c8327a1515db32ebadbaff4fe75e63b917560b7d021031ca2d159ae8868a5eef6d67a5a8a5bcc6fb2e8b711669f1c1e8b05327236a3cf2103798a4ce34929cb450bf88557dd90cae538c67f9d0c76314ae18679200be9c17021039624dec23dc1bb628cea55e949ea26225949a3349346a0732fef9def6f1f75292103d1edaadb8555012b752dd7a5c6672c379ce827e4bc0d4e992ee1ab3488b445b255ae", - "3GLJbHv7RqPeFk2SqWapqJ3XibVibiKi8f": "5321021a33d48b9f5d3adc41004709313277d4c6969268cf41e3f5b695a934c676829a21031b87321307db7a0f6ea22847a538505188f1a2231eba68867e17c5f0e4434c0721035dee0a6e1df66a6c9c7592ef03aa02bba9b06742134d27bd08f356e33f21259c2103768a109d682a76c09f865912e9e64a8689b03c1a231c613d87ec9bd535fd74c22103911038638b9fc52b2d375ce207c8388bd5ee7f2d54ab9b4148bd406c6d7dcad355ae", - "3E1d1z7gJSFeZM2d3k12MJ1jGwrBRy1YTw": "5321027da98ce0407138461f4ad803a1fb67afa4246f06ad0e1256a087daeffd82a8642102e7f87f2b094ec322be2fb99d3ca81fd6ac0ab26ce081e51ab18c507f8b6d1d162102ed5d256036e10568c33e0a15021cc1806e04d7d24c8f020aaae23ec2deecb4302103b6f88231bb5a5f4629e4d097492321f86968c6aeb012196a1fe3b217fe4ae0ac2103f6b5e2c1db3124a5058a0e3e83d5d0c412b9a5b50e2ef97e2b7e1c0af57ab3e355ae", - "3QYueyPXq2QDRQCDo7agTimz9673NKV25E": "5321021543292c2942708ccc83354ebf507044b310ed0d33a19e2327a49be53e0f314221024a1a83f8c50f6cad7c134b9cded509dabf196ae49eca157a39ad95798943dc95210292698fbb97e8f6e67296b22b36367ba85c8101fcbc27bb4b00b43623639212ac2102d86980796027a00ba7aa9b53671762c908962654f969f5dec340071bb30e8d7621038fb3fa5e77dafd24c09d819dbdc7c11dca55b350511bf3bc499c09316a89286e55ae", - "372BzC1GGjziT8zGYbryja3kF2KaTeobRK": "53210214ec25e5cb42e51883d4e615316748feefe91133fcfc0f93f0b5a24a55e0a347210262336210b3173aa4ca90d292990f463e42bdeb2e73112925dc712c5a2e749bcb210277517855f512564f225e63c650dad7720565aa563901d50743be4b0f0267dcc72102d2777a9faf5d2e2b2363e1270d61021bc2e36e8cb19ca9d29dedbba9a0348b532103a57db80b6ae573e5cef2115e36e73e5ef41f8a099bfb5087d80320c04a7db72e55ae" - }, - "selectedUtxos": [{ - "address": "3E1d1z7gJSFeZM2d3k12MJ1jGwrBRy1YTw", - "scriptPubKey": "a91487264aa41e3df76f3156c7fa587fd7d5b1f7b96b87", - "txid": "2ac165fa7a3a2b535d106a0041c7568d03b531e58aeccdd3199d7289ab12cfc1", - "vout": 1, - "amount": 10, - "confirmations": 7 - }], - "inputsSigned": 0, - "signaturesAdded": 1, - "signhash": 1, - "spendUnconfirmed": false, - "tx": "0100000001c1cf12ab89729d19d3cdec8ae531b5038d56c741006a105d532b3a7afa65c12a01000000fd40010047304402201aad0ea92f929be21d60afb741b76bfcf2aa9614079cb9da76b15b3a1210f07b02205bc5c1895105da3ee682e532d2d49dfd1214fa6123fb9c9d552336f135c77eff0147304402203f02f15bb4ad4bc7d0ca4612fd9e9ae05a1331f3d62f302cf08dba56695f5dcf0220700110562fe228ebba324b120de64a7bbaddf049d67a313f749e9b32ee88787d014cad5321027da98ce0407138461f4ad803a1fb67afa4246f06ad0e1256a087daeffd82a8642102e7f87f2b094ec322be2fb99d3ca81fd6ac0ab26ce081e51ab18c507f8b6d1d162102ed5d256036e10568c33e0a15021cc1806e04d7d24c8f020aaae23ec2deecb4302103b6f88231bb5a5f4629e4d097492321f86968c6aeb012196a1fe3b217fe4ae0ac2103f6b5e2c1db3124a5058a0e3e83d5d0c412b9a5b50e2ef97e2b7e1c0af57ab3e355aeffffffff0215cd5b07000000001976a91434f8e0c5be216025a52addf18a987543cad23f7a88acdbd53e340000000017a914a09f10bc42b61ecf9d3d09550765c228f1cb808a8700000000" - } - }], - "networkName": "testnet" + "selectedUtxos": [{ + "address": "3E1d1z7gJSFeZM2d3k12MJ1jGwrBRy1YTw", + "scriptPubKey": "a91487264aa41e3df76f3156c7fa587fd7d5b1f7b96b87", + "txid": "2ac165fa7a3a2b535d106a0041c7568d03b531e58aeccdd3199d7289ab12cfc1", + "vout": 1, + "amount": 10, + "confirmations": 7 + }], + "inputsSigned": 0, + "signaturesAdded": 1, + "signhash": 1, + "spendUnconfirmed": false, + "tx": "0100000001c1cf12ab89729d19d3cdec8ae531b5038d56c741006a105d532b3a7afa65c12a01000000fd40010047304402201aad0ea92f929be21d60afb741b76bfcf2aa9614079cb9da76b15b3a1210f07b02205bc5c1895105da3ee682e532d2d49dfd1214fa6123fb9c9d552336f135c77eff0147304402203f02f15bb4ad4bc7d0ca4612fd9e9ae05a1331f3d62f302cf08dba56695f5dcf0220700110562fe228ebba324b120de64a7bbaddf049d67a313f749e9b32ee88787d014cad5321027da98ce0407138461f4ad803a1fb67afa4246f06ad0e1256a087daeffd82a8642102e7f87f2b094ec322be2fb99d3ca81fd6ac0ab26ce081e51ab18c507f8b6d1d162102ed5d256036e10568c33e0a15021cc1806e04d7d24c8f020aaae23ec2deecb4302103b6f88231bb5a5f4629e4d097492321f86968c6aeb012196a1fe3b217fe4ae0ac2103f6b5e2c1db3124a5058a0e3e83d5d0c412b9a5b50e2ef97e2b7e1c0af57ab3e355aeffffffff0215cd5b07000000001976a91434f8e0c5be216025a52addf18a987543cad23f7a88acdbd53e340000000017a914a09f10bc42b61ecf9d3d09550765c228f1cb808a8700000000" + } } }; - w._handleTxProposals('senderID', txps, true); + w._handleTxProposal('senderID', txps, true); Object.keys(w.txProposals.txps).length.should.equal(1); w.getTxProposals().length.should.equal(1); }); @@ -514,7 +515,6 @@ describe('Wallet model', function() { }); - // tx handling var createUTXO = function(w) { @@ -577,7 +577,6 @@ describe('Wallet model', function() { }); }); it('should create & sign & send a transaction', function(done) { - var w = createW2(null, 1); var utxo = createUTXO(w); w.blockchain.fixUnspent(utxo); @@ -588,9 +587,17 @@ describe('Wallet model', function() { }); }); }); - it('#getNetworkName', function() { - var w = createW(); - w.getNetworkName().should.equal('testnet'); + it('should send TxProposal', function(done) { + var w = createW2(); + var utxo = createUTXO(w); + w.blockchain.fixUnspent(utxo); + w.createTx(toAddress, amountSatStr, null, function(ntxid) { + w.sendTxProposal.should.throw('Illegal Argument.'); + (function() { + w.sendTxProposal(ntxid) + }).should.not.throw(); + done(); + }); }); var mockFakeActivity = function(w, f) {