From 861fb94f668917a7da77cedbaa3fa07a5ce496db Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Wed, 9 Apr 2014 14:30:12 -0300 Subject: [PATCH 01/22] fix test on node --- copay.js | 1 + js/models/CopayPeer.js | 1 - js/models/PublicKeyRing.js | 11 +++++------ test/FakeStorage.js | 8 ++++---- test/test.publickeyring.js | 31 ++++++++++++++----------------- 5 files changed, 24 insertions(+), 28 deletions(-) diff --git a/copay.js b/copay.js index 5b2a2951c..389ae66dc 100644 --- a/copay.js +++ b/copay.js @@ -1,5 +1,6 @@ module.exports.Storage = require('./js/models/Storage'); module.exports.PublicKeyRing = require('./js/models/PublicKeyRing'); +module.exports.TxProposals = require('./js/models/TxProposals'); module.exports.CopayPeer = require('./js/models/CopayPeer'); module.exports.FakeStorage = require('./test/FakeStorage'); diff --git a/js/models/CopayPeer.js b/js/models/CopayPeer.js index 5a25206de..eecbca8e7 100644 --- a/js/models/CopayPeer.js +++ b/js/models/CopayPeer.js @@ -236,7 +236,6 @@ CopayPeer.prototype.send = function(peerIds, data, cb) { peerIds = this.connectedPeers; data.isBroadcast = 1; } -console.log('[CopayPeer.js.216:SENDD:]',data); //TODO if (Array.isArray(peerIds)) { var l = peerIds.length; diff --git a/js/models/PublicKeyRing.js b/js/models/PublicKeyRing.js index ec159403b..42e6fa626 100644 --- a/js/models/PublicKeyRing.js +++ b/js/models/PublicKeyRing.js @@ -123,7 +123,6 @@ PublicKeyRing.prototype.store = function (passphrase) { if (!this.id) throw new Error('wallet has no id'); - storage.set(this.id, PublicKeyRing.encrypt(passphrase,this.serialize())); this.dirty = 0; @@ -136,13 +135,13 @@ PublicKeyRing.prototype.registeredCopayers = function () { -PublicKeyRing.prototype.haveAllRequiredPubKeys = function () { +PublicKeyRing.prototype.isComplete = function () { return this.registeredCopayers() >= this.totalCopayers; }; PublicKeyRing.prototype._checkKeys = function() { - if (!this.haveAllRequiredPubKeys()) + if (!this.isComplete()) throw new Error('dont have required keys yet'); }; @@ -154,7 +153,7 @@ PublicKeyRing.prototype._newExtendedPublicKey = function () { PublicKeyRing.prototype.addCopayer = function (newEpk) { - if (this.haveAllRequiredPubKeys()) + if (this.isComplete()) throw new Error('already have all required key:' + this.totalCopayers); if (!newEpk) { @@ -172,7 +171,7 @@ PublicKeyRing.prototype.addCopayer = function (newEpk) { }; -PublicKeyRing.prototype.getCopayersPubKeys = function (index, isChange) { +PublicKeyRing.prototype.getPubKeys = function (index, isChange) { this._checkKeys(); var pubKeys = []; @@ -197,7 +196,7 @@ PublicKeyRing.prototype._checkIndexRange = function (index, isChange) { PublicKeyRing.prototype.getRedeemScript = function (index, isChange) { this._checkIndexRange(index, isChange); - var pubKeys = this.getCopayersPubKeys(index, isChange); + var pubKeys = this.getPubKeys(index, isChange); var script = Script.createMultisig(this.requiredCopayers, pubKeys); return script; }; diff --git a/test/FakeStorage.js b/test/FakeStorage.js index f12fc6f95..dd3af45cf 100644 --- a/test/FakeStorage.js +++ b/test/FakeStorage.js @@ -3,12 +3,12 @@ var FakeStorage = function(){ this.storage = {}; }; -FakeStorage.prototype.set = function (id) { - return this.storage[id]; +FakeStorage.prototype.set = function (id, payload) { + this.storage[id] = payload; }; -FakeStorage.prototype.get = function(id, payload) { - this.storage[id] = payload; +FakeStorage.prototype.get = function(id) { + return this.storage[id]; } module.exports = require('soop')(FakeStorage); diff --git a/test/test.publickeyring.js b/test/test.publickeyring.js index b78896aeb..9c4bb2cac 100644 --- a/test/test.publickeyring.js +++ b/test/test.publickeyring.js @@ -7,7 +7,9 @@ var Address = bitcore.Address; var buffertools = bitcore.buffertools; var copay = copay || require('../copay'); var fakeStorage = copay.FakeStorage; -var PublicKeyRing = copay.PublicKeyRing || require('soop').load('../js/models/PublicKeyRing', {Storage: fakeStorage}); + +var PublicKeyRing = (typeof process.versions === 'undefined') ? copay.PublicKeyRing : + require('soop').load('../js/models/PublicKeyRing', {Storage: fakeStorage}); var aMasterPubKey = 'tprv8ZgxMBicQKsPdSVTiWXEqCCzqRaRr9EAQdn5UVMpT9UHX67Dh1FmzEMbavPumpAicsUm2XvC6NTdcWB89yN5DUWx5HQ7z3KByUg7Ht74VRZ'; @@ -17,7 +19,6 @@ var config = { }; var createW = function (networkName) { - var config = { networkName: networkName || 'livenet', }; @@ -27,7 +28,7 @@ var createW = function (networkName) { var copayers = []; for(var i=0; i<5; i++) { - w.haveAllRequiredPubKeys().should.equal(false); + w.isComplete().should.equal(false); var newEpk = w.addCopayer(); copayers.push(newEpk); } @@ -55,7 +56,7 @@ describe('PublicKeyRing model', function() { should.exist(w2); w2.registeredCopayers().should.equal(0); - w2.haveAllRequiredPubKeys().should.equal(false); + w2.isComplete().should.equal(false); w2.getAddress.bind(false).should.throw(); }); @@ -65,7 +66,7 @@ describe('PublicKeyRing model', function() { var w = k.w; var copayers = k.copayers; - w.haveAllRequiredPubKeys().should.equal(true); + w.isComplete().should.equal(true); w.addCopayer.bind().should.throw(); for(var i =0; i<5; i++) w.addCopayer.bind(copayers[i]).should.throw(); @@ -86,7 +87,7 @@ describe('PublicKeyRing model', function() { w.store.bind().should.throw(); var w2 = PublicKeyRing.read(ID); - w2.haveAllRequiredPubKeys().should.equal(true); + w2.isComplete().should.equal(true); w2.addCopayer.bind().should.throw(); for(var i =0; i<5; i++) w2.addCopayer.bind(copayers[i]).should.throw(); @@ -188,12 +189,8 @@ describe('PublicKeyRing model', function() { }); (function() { w2.merge(w.toObj());}).should.throw(); (function() { w2.merge(w,true);}).should.throw(); - -console.log('[test.publickeyring.js.190]'); //TODO w2.merge(w.toObj(),true).should.equal(true); -console.log('[test.publickeyring.js.193]'); //TODO - var w3 = new PublicKeyRing({ networkName: 'livenet', @@ -232,7 +229,7 @@ console.log('[test.publickeyring.js.193]'); //TODO should.exist(w); var copayers = []; for(var i=0; i<2; i++) { - w.haveAllRequiredPubKeys().should.equal(false); + w.isComplete().should.equal(false); w.addCopayer(); } @@ -243,16 +240,16 @@ console.log('[test.publickeyring.js.193]'); //TODO should.exist(w); var copayers = []; for(var i=0; i<3; i++) { - w2.haveAllRequiredPubKeys().should.equal(false); + w2.isComplete().should.equal(false); w2.addCopayer(); } w2.merge(w.toObj()).should.equal(true); - w2.haveAllRequiredPubKeys().should.equal(true); + w2.isComplete().should.equal(true); w2.merge(w.toObj()).should.equal(false); - w.haveAllRequiredPubKeys().should.equal(false); + w.isComplete().should.equal(false); w.merge(w2.toObj()).should.equal(true); - w.haveAllRequiredPubKeys().should.equal(true); + w.isComplete().should.equal(true); w.merge(w2.toObj()).should.equal(false); }); @@ -261,7 +258,7 @@ console.log('[test.publickeyring.js.193]'); //TODO should.exist(w); for(var i=0; i<5; i++) { - w.haveAllRequiredPubKeys().should.equal(false); + w.isComplete().should.equal(false); var w2 = new PublicKeyRing({ networkName: 'livenet', id: w.id, @@ -269,7 +266,7 @@ console.log('[test.publickeyring.js.193]'); //TODO w2.addCopayer(); w.merge(w2.toObj()).should.equal(true); } - w.haveAllRequiredPubKeys().should.equal(true); + w.isComplete().should.equal(true); }); }); From 1caea999173d18a6eb5c93b6e6b34b684ce428cd Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Wed, 9 Apr 2014 17:28:35 -0300 Subject: [PATCH 02/22] txproposal basic features and test --- js/models/PublicKeyRing.js | 45 +++++++++---- js/models/TxProposals.js | 77 ++++++++++++++++++++++ test/test.publickeyring.js | 18 ++++++ test/test.txproposal.js | 127 +++++++++++++++++++++++++++++++++++++ 4 files changed, 255 insertions(+), 12 deletions(-) create mode 100644 js/models/TxProposals.js create mode 100644 test/test.txproposal.js diff --git a/js/models/PublicKeyRing.js b/js/models/PublicKeyRing.js index 42e6fa626..dba051db9 100644 --- a/js/models/PublicKeyRing.js +++ b/js/models/PublicKeyRing.js @@ -14,17 +14,6 @@ var buffertools = bitcore.buffertools; var Storage = imports.Storage || require('./Storage'); var storage = Storage.default(); -/* - * This follow Electrum convetion, as described in - * https://bitcointalk.org/index.php?topic=274182.0 - * - * We should probably adopt the next standard once it's ready, as discussed in: - * http://sourceforge.net/p/bitcoin/mailman/message/32148600/ - * - */ - -var PUBLIC_BRANCH = 'm/0/'; -var CHANGE_BRANCH = 'm/1/'; function PublicKeyRing(opts) { opts = opts || {}; @@ -44,6 +33,22 @@ function PublicKeyRing(opts) { this.addressIndex=0; } +/* + * This follow Electrum convetion, as described in + * https://bitcointalk.org/index.php?topic=274182.0 + * + * We should probably adopt the next standard once it's ready, as discussed in: + * http://sourceforge.net/p/bitcoin/mailman/message/32148600/ + * + */ + +PublicKeyRing.PublicBranch = function (index) { + return 'm/0/'+index; +}; + +PublicKeyRing.ChangeBranch = function (index) { + return 'm/1/'+index; +}; PublicKeyRing.getRandomId = function () { return buffertools.toHex(coinUtil.generateNonce()); @@ -177,7 +182,7 @@ PublicKeyRing.prototype.getPubKeys = function (index, isChange) { var pubKeys = []; var l = this.copayersBIP32.length; for(var i=0; i Date: Wed, 9 Apr 2014 20:37:14 -0300 Subject: [PATCH 03/22] BIP32 PrivateKey wrapper --- copay.js | 1 + js/models/PrivateKey.js | 35 ++++++++++++++++++++++++++++ js/models/TxProposals.js | 31 ++++++++++++++----------- test/test.PrivateKey.js | 50 ++++++++++++++++++++++++++++++++++++++++ test/test.txproposal.js | 32 +++++++++---------------- 5 files changed, 114 insertions(+), 35 deletions(-) create mode 100644 js/models/PrivateKey.js create mode 100644 test/test.PrivateKey.js diff --git a/copay.js b/copay.js index 389ae66dc..b7e382094 100644 --- a/copay.js +++ b/copay.js @@ -3,4 +3,5 @@ module.exports.Storage = require('./js/models/Storage'); module.exports.PublicKeyRing = require('./js/models/PublicKeyRing'); module.exports.TxProposals = require('./js/models/TxProposals'); module.exports.CopayPeer = require('./js/models/CopayPeer'); +module.exports.PrivateKey = require('./js/models/PrivateKey'); module.exports.FakeStorage = require('./test/FakeStorage'); diff --git a/js/models/PrivateKey.js b/js/models/PrivateKey.js new file mode 100644 index 000000000..8e60ebf05 --- /dev/null +++ b/js/models/PrivateKey.js @@ -0,0 +1,35 @@ +'use strict'; + + +var imports = require('soop').imports(); +var bitcore = require('bitcore'); +var BIP32 = bitcore.BIP32; +var WalletKey = bitcore.WalletKey; +var networks = bitcore.networks; +var PublicKeyRing = require('./PublicKeyRing'); + +function PrivateKey(opts) { + this.id = opts.id; + this.network = opts.networkName === 'testnet' ? + networks.testnet : networks.livenet; + this.BIP32 = opts.BIP32 || new BIP32(this.network.name); +}; + + +PrivateKey.prototype.getBIP32 = function(index,isChange) { + if (typeof index === 'undefined') { + return this.BIP32; + } + return this.BIP32.derive( isChange ? + PublicKeyRing.ChangeBranch(index):PublicKeyRing.PublicBranch(index) ); +}; + +PrivateKey.prototype.get = function(index,isChange) { + var derivedBIP32 = this.getBIP32(index,isChange); + var wk = new WalletKey({network: this.network}); + var p = derivedBIP32.eckey.private.toString('hex'); + wk.fromObj({priv: p}); + return wk; +}; + +module.exports = require('soop')(PrivateKey); diff --git a/js/models/TxProposals.js b/js/models/TxProposals.js index d823a4d5e..ab414ce85 100644 --- a/js/models/TxProposals.js +++ b/js/models/TxProposals.js @@ -12,17 +12,13 @@ var buffertools = bitcore.buffertools; var Storage = imports.Storage || require('./Storage'); var storage = Storage.default(); -/* - * This follow Electrum convetion, as described in - * https://bitcointalk.org/index.php?topic=274182.0 - * - * We should probably adopt the next standard once it's ready, as discussed in: - * http://sourceforge.net/p/bitcoin/mailman/message/32148600/ - * - */ +function TxProposal(opts) { + this.tx = opts.tx; + this.seenBy = {}; + this.signedBy = {}; +}; +module.exports = require('soop')(TxProposal); -var PUBLIC_BRANCH = 'm/0/'; -var CHANGE_BRANCH = 'm/1/'; function TxProposals(opts) { opts = opts || {}; @@ -36,9 +32,9 @@ function TxProposals(opts) { this.dirty = 1; } - TxProposals.prototype.list = function() { var ret = []; + var ret = []; this.txs.forEach(function(tx) { }); @@ -66,9 +62,16 @@ TxProposals.prototype.create = function(toAddress, amountSat, utxos, onePrivKey) } var tx = b.build(); - var txHex = tx.serialize(); - this.txs.push(txHex); - return txHex; + this.txs.push( + new TxProposal({ + signedBy: { + }, + seenBy: { + }, + tx: tx + }) + ); + return tx; }; TxProposals.prototype.sign = function(index) { diff --git a/test/test.PrivateKey.js b/test/test.PrivateKey.js new file mode 100644 index 000000000..30c7ddd91 --- /dev/null +++ b/test/test.PrivateKey.js @@ -0,0 +1,50 @@ +'use strict'; + +var chai = chai || require('chai'); +var should = chai.should(); +var bitcore = bitcore || require('bitcore'); +var Transaction = bitcore.Transaction; +var buffertools = bitcore.buffertools; +var WalletKey = bitcore.WalletKey; +var Key = bitcore.Key; +var BIP32 = bitcore.BIP32; +var bignum = bitcore.bignum; +var networks = bitcore.networks; +var Address = bitcore.Address; +var BitcorePrivateKey = bitcore.PrivateKey; +var copay = copay || require('../copay'); +var PrivateKey = copay.PrivateKey || require('../js/models/PrivateKey'); + +var config = { + networkName:'livenet', +}; + +describe('PrivateKey model', function() { + + it('should create an instance', function () { + var w = new PrivateKey(config); + should.exist(w); + should.exist(w.BIP32); + should.exist(w.BIP32.derive); + }); + + it('should derive priv keys', function () { + var w = new PrivateKey(config); + for(var j=0; j<2; j++) { + for(var i=0; i<3; i++) { + var wk = w.get(i,j); + should.exist(wk); + var o=wk.storeObj(); + should.exist(o); + should.exist(o.priv); + should.exist(o.pub); + should.exist(o.addr); + var a = new Address(o.addr); + a.isValid().should.equal(true); + (function() { + var p = new PrivateKey(o.priv) + }).should.not.throw(); + } + } + }); +}); diff --git a/test/test.txproposal.js b/test/test.txproposal.js index adcafbc0a..164ffbb2c 100644 --- a/test/test.txproposal.js +++ b/test/test.txproposal.js @@ -12,6 +12,7 @@ var bignum = bitcore.bignum; var networks = bitcore.networks; var copay = copay || require('../copay'); var fakeStorage = copay.FakeStorage; +var PrivateKey = copay.PrivateKey || require('../js/models/PrivateKey'); var TxProposals = copay.TxProposals || require('../js/models/TxProposal'); var PublicKeyRing = (typeof process.versions === 'undefined') ? copay.PublicKeyRing : require('soop').load('../js/models/PublicKeyRing', {Storage: fakeStorage}); @@ -74,25 +75,21 @@ describe('TxProposals model', function() { unspentTest[0].address = w.publicKeyRing.getAddress(1, true); unspentTest[0].scriptPubKey = w.publicKeyRing.getRedeemScript(1, true).getBuffer(); - var txHex = w.create( + var tx = w.create( '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', bignum('123456789'), unspentTest ); - should.exist(txHex); - - var t2=new Transaction(); - t2.parse(txHex); - t2.isComplete().should.equal(false); + should.exist(tx); + tx.isComplete().should.equal(false); }); it('#create. Singing with derivate keys', function () { - var oneBIP32 = new BIP32(config.networkName); - + var priv = new PrivateKey(config); var w = new TxProposals({ networkName: config.networkName, - publicKeyRing: createW([oneBIP32]), + publicKeyRing: createW([priv.getBIP32()]), }); should.exist(w); w.network.name.should.equal('livenet'); @@ -103,22 +100,15 @@ describe('TxProposals model', function() { unspentTest[0].address = w.publicKeyRing.getAddress(index, isChange); unspentTest[0].scriptPubKey = w.publicKeyRing.getRedeemScript(index, isChange).getBuffer(); - var derivedBip32 = oneBIP32.derive( isChange ? PublicKeyRing.ChangeBranch(index):PublicKeyRing.PublicBranch(index) ); - var wk = new WalletKey({network: networks.livenet}); - var p = derivedBip32.eckey.private.toString('hex'); - wk.fromObj({priv: p}); - - var txHex = w.create( + var tx = w.create( '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', bignum('123456789'), unspentTest, - wk + priv.get(index,isChange) ); - should.exist(txHex); - var t2=new Transaction(); - t2.parse(txHex); - t2.isComplete().should.equal(false); - t2.countInputMissingSignatures(0).should.equal(2); + should.exist(tx); + tx.isComplete().should.equal(false); + tx.countInputMissingSignatures(0).should.equal(2); } } From 307d3aaeecfcb606cb869950e180790d1b333cb6 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Wed, 9 Apr 2014 23:04:22 -0300 Subject: [PATCH 04/22] add sign in block --- js/models/PrivateKey.js | 13 +++++++++++++ js/models/PublicKeyRing.js | 21 +++++---------------- js/models/TxProposals.js | 6 +++--- test/test.PrivateKey.js | 20 ++++++++++++++++++++ test/test.publickeyring.js | 17 +++++++---------- test/test.txproposal.js | 34 ++++++++++++++++++++++++++++++++-- 6 files changed, 80 insertions(+), 31 deletions(-) diff --git a/js/models/PrivateKey.js b/js/models/PrivateKey.js index 8e60ebf05..1b27fe7d3 100644 --- a/js/models/PrivateKey.js +++ b/js/models/PrivateKey.js @@ -32,4 +32,17 @@ PrivateKey.prototype.get = function(index,isChange) { return wk; }; +PrivateKey.prototype.getAll = function(addressIndex, changeAddressIndex) { + var ret = []; + for(var i=0;i Date: Wed, 9 Apr 2014 23:07:21 -0300 Subject: [PATCH 05/22] add sign in block --- test/test.txproposal.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test.txproposal.js b/test/test.txproposal.js index 8e8e4852a..89194d0e1 100644 --- a/test/test.txproposal.js +++ b/test/test.txproposal.js @@ -39,7 +39,7 @@ var createW = function (bip32s) { for(var i=0; i<5; i++) { if (bip32s) { var b=bip32s[i]; - w.addCopayer(b?b.extendedPrivateKeyString():null); + w.addCopayer(b?b.extendedPublicKeyString():null); } else w.addCopayer(); From fe989c5c3941f19b71bb26f368f3cb1673d3aa63 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Thu, 10 Apr 2014 02:16:57 -0300 Subject: [PATCH 06/22] tx proposal test. PrivateKey --- js/controllers/signin.js | 2 -- js/models/PrivateKey.js | 24 +++++++++++-- js/models/TxProposals.js | 62 +++++++++++++++++++++++----------- js/services/network.js | 37 +++++++++++++++----- test/test.PrivateKey.js | 21 ++++++++++++ test/test.txproposal.js | 73 ++++++++++++++++++++++------------------ 6 files changed, 155 insertions(+), 64 deletions(-) diff --git a/js/controllers/signin.js b/js/controllers/signin.js index fee00a14a..7ecd0680c 100644 --- a/js/controllers/signin.js +++ b/js/controllers/signin.js @@ -43,8 +43,6 @@ angular.module('copay.signin').controller('SigninController', $location.path('peer'); $rootScope.$digest(); }, function() { - -console.log('[signin.js.46] SETTING MESSAGE'); //TODO $rootScope.flashMessage = { message: 'Connection refussed', type: 'error'}; $location.path('home'); $rootScope.$digest(); diff --git a/js/models/PrivateKey.js b/js/models/PrivateKey.js index 1b27fe7d3..1f827277f 100644 --- a/js/models/PrivateKey.js +++ b/js/models/PrivateKey.js @@ -6,15 +6,19 @@ var bitcore = require('bitcore'); var BIP32 = bitcore.BIP32; var WalletKey = bitcore.WalletKey; var networks = bitcore.networks; +var util = bitcore.util; var PublicKeyRing = require('./PublicKeyRing'); function PrivateKey(opts) { - this.id = opts.id; this.network = opts.networkName === 'testnet' ? networks.testnet : networks.livenet; - this.BIP32 = opts.BIP32 || new BIP32(this.network.name); + this.BIP32 = opts.BIP32 || new BIP32(opts.extendedPrivateKeyString || this.network.name); + this._calcId(); }; +PrivateKey.prototype._calcId = function() { + this.id = util.ripe160(this.BIP32.extendedPublicKey).toString('hex'); +}; PrivateKey.prototype.getBIP32 = function(index,isChange) { if (typeof index === 'undefined') { @@ -24,6 +28,21 @@ PrivateKey.prototype.getBIP32 = function(index,isChange) { PublicKeyRing.ChangeBranch(index):PublicKeyRing.PublicBranch(index) ); }; + +PrivateKey.fromObj = function(o) { + return new PrivateKey({ + extendedPrivateKeyString: o.extendedPrivateKeyString, + networkName: o.networkName, + }); +}; + +PrivateKey.prototype.toObj = function() { + return { + extendedPrivateKeyString: this.BIP32.extendedPrivateKeyString(), + networkName: this.network.name, + }; +}; + PrivateKey.prototype.get = function(index,isChange) { var derivedBIP32 = this.getBIP32(index,isChange); var wk = new WalletKey({network: this.network}); @@ -34,6 +53,7 @@ PrivateKey.prototype.get = function(index,isChange) { PrivateKey.prototype.getAll = function(addressIndex, changeAddressIndex) { var ret = []; + for(var i=0;i probably not in network.js var createWallet = function(walletId) { + console.log('### CREATING WALLET. ID:' + walletId); + var priv = new copay.PrivateKey({networkName: config.networkName}); + console.log('\t### PrivateKey Initialized'); + //TODO create a wallet and WalletId, not only pkr var pkr = new copay.PublicKeyRing({ - network: config.networkName, + networkName: config.networkName, id: walletId, }); - pkr.addCopayer(); - console.log('\t### PublicKeyRing Initialized:'); + + // Add self to the ring. + pkr.addCopayer(priv.getBIP32().extendedPublicKeyString()); + console.log('\t### PublicKeyRing Initialized'); + + var txp = new copay.TxProposals({ + networkName: config.networkName, + publicKeyRing: pkr, + }); + console.log('\t### TxProposals Initialized'); + Storage.addWalletId(pkr.id); Storage.set(pkr.id, 'publicKeyRing', pkr.toObj()); + Storage.set(pkr.id, 'privateKey', priv.toObj()); + Storage.set(pkr.id, 'txProposals', txp.toObj()); + console.log('\t### Wallet Stored'); + // Store it on rootScope + $rootScope.priv = priv; // TODO secure this. $rootScope.walletId = pkr.id; $rootScope.publicKeyRing = pkr; + $rootScope.txProposals = txp; }; var openWallet = function (walletId) { var ret = false; var pkr = Storage.get(walletId, 'publicKeyRing'); + var priv = Storage.get(walletId, 'privateKey'); + var txp = Storage.get(walletId, 'txProposals'); if (pkr) { console.log('### WALLET OPENED:', walletId, pkr); $rootScope.walletId = walletId; $rootScope.publicKeyRing = new copay.PublicKeyRing.fromObj(pkr); + $rootScope.txProposals = new copay.TxProposals.fromObj(txp); + $rootScope.priv = new copay.PrivateKey.fromObj(priv); //TODO secure ret = true; } return ret; @@ -133,7 +156,6 @@ angular.module('copay.network') // public methods var init = function(cb) { - var cp = $rootScope.cp = new copay.CopayPeer({ apiKey: config.p2pApiKey, debug: config.p2pDebug, @@ -141,7 +163,6 @@ angular.module('copay.network') }); _setupHandlers(); - // inicia session cp.start(function(peerId) { return cb(); }); @@ -156,15 +177,15 @@ angular.module('copay.network') _refreshUx(); }; - var connect = function(peerId, openCallback, failCallBack) { + var connect = function(peerId, openCallback, failCallback) { if ($rootScope.cp) { $rootScope.cp.connectTo(peerId, openCallback, function () { disconnect(); - failCallBack(); + failCallback(); }); } else - return failCallBack(); + return failCallback(); }; return { diff --git a/test/test.PrivateKey.js b/test/test.PrivateKey.js index d1325e971..1c678aa0e 100644 --- a/test/test.PrivateKey.js +++ b/test/test.PrivateKey.js @@ -67,4 +67,25 @@ describe('PrivateKey model', function() { } }); + it('should calculate .id', function () { + var w1 = new PrivateKey(config); + should.exist(w1.id); + w1.id.length.should.equal(40); + }); + it('fromObj toObj roundtrip', function () { + var w1 = new PrivateKey(config); + var w2 = PrivateKey.fromObj(w1.toObj()); + + w2.getBIP32().extendedPrivateKeyString().should.equal(w1.getBIP32().extendedPrivateKeyString()); + w2.getBIP32().extendedPublicKeyString().should.equal(w1.getBIP32().extendedPublicKeyString()); + w2.id.should.equal(w1.id); + + + w2.getBIP32(1,1).extendedPrivateKeyString().should + .equal(w1.getBIP32(1,1).extendedPrivateKeyString()); + w2.getBIP32(1,0).extendedPrivateKeyString().should + .equal(w1.getBIP32(1,0).extendedPrivateKeyString()); + }); + + }); diff --git a/test/test.txproposal.js b/test/test.txproposal.js index 89194d0e1..8377a0206 100644 --- a/test/test.txproposal.js +++ b/test/test.txproposal.js @@ -44,11 +44,13 @@ var createW = function (bip32s) { else w.addCopayer(); } - w.generateAddress(true); - w.generateAddress(true); - w.generateAddress(true); - w.generateAddress(false); - w.generateAddress(false); + w.generateAddress(true); + w.generateAddress(true); + w.generateAddress(true); + w.generateAddress(false); + w.generateAddress(false); + w.generateAddress(false); + //3x3 indexes return w; }; @@ -91,57 +93,64 @@ describe('TxProposals model', function() { networkName: config.networkName, publicKeyRing: createW([priv.getBIP32()]), }); - should.exist(w); - w.network.name.should.equal('livenet'); - + var ts = Date.now(); for (var isChange=0; isChange<2; isChange++) { for (var index=0; index<3; index++) { unspentTest[0].address = w.publicKeyRing.getAddress(index, isChange); unspentTest[0].scriptPubKey = w.publicKeyRing.getRedeemScript(index, isChange).getBuffer(); - var tx = w.create( '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', bignum('123456789'), unspentTest, - [priv.get(index,isChange)] + priv ); should.exist(tx); tx.isComplete().should.equal(false); tx.countInputMissingSignatures(0).should.equal(2); + (w.txs[0].signedBy[priv.id] - ts > 0).should.equal(true); + (w.txs[0].seenBy[priv.id] - ts > 0).should.equal(true); } } - }); - it('#create. Signing with derivate keys block', function () { + it('#toObj #fromObj roundtrip', function () { var priv = new PrivateKey(config); - - var privs = priv.getAll(3,3); - var w = new TxProposals({ networkName: config.networkName, publicKeyRing: createW([priv.getBIP32()]), }); - should.exist(w); - w.network.name.should.equal('livenet'); + var ts = Date.now(); + var isChange=0; + var index=0; - for (var isChange=0; isChange<2; isChange++) { - for (var index=0; index<3; index++) { - unspentTest[0].address = w.publicKeyRing.getAddress(index, isChange); - unspentTest[0].scriptPubKey = w.publicKeyRing.getRedeemScript(index, isChange).getBuffer(); - var tx = w.create( - '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', - bignum('123456789'), - unspentTest, - privs - ); - should.exist(tx); - tx.isComplete().should.equal(false); - tx.countInputMissingSignatures(0).should.equal(2); - } - } + unspentTest[0].address = w.publicKeyRing.getAddress(index, isChange); + unspentTest[0].scriptPubKey = w.publicKeyRing.getRedeemScript(index, isChange).getBuffer(); + var tx = w.create( + '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', + bignum('123456789'), + unspentTest, + priv + ); + tx.isComplete().should.equal(false); + tx.countInputMissingSignatures(0).should.equal(2); + (w.txs[0].signedBy[priv.id] - ts > 0).should.equal(true); + (w.txs[0].seenBy[priv.id] - ts > 0).should.equal(true); + var o = w.toObj(); + should.exist(o); + o.txs.length.should.equal(1); + should.exist(o.txs[0].txHex); + should.exist(o.txs[0].signedBy); + should.exist(o.txs[0].seenBy); + should.exist(o.txs[0].signedBy[priv.id]); + + var w2 = TxProposals.fromObj(o); + var tx2 = w2.txs[0].tx; + tx2.isComplete().should.equal(false); + tx2.countInputMissingSignatures(0).should.equal(2); + (w2.txs[0].signedBy[priv.id] - ts > 0).should.equal(true); + (w2.txs[0].seenBy[priv.id] - ts > 0).should.equal(true); }); }); From 0960f21a169ae3fe8b03b2522f0f2897c9f71273 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Fri, 11 Apr 2014 01:09:42 -0300 Subject: [PATCH 07/22] txpropal MERGE working! --- js/models/PublicKeyRing.js | 16 +- js/models/TxProposals.js | 219 ++++++++++++++++++++-- test/test.publickeyring.js | 9 +- test/test.txproposal.js | 361 ++++++++++++++++++++++++++++++++++--- 4 files changed, 556 insertions(+), 49 deletions(-) diff --git a/js/models/PublicKeyRing.js b/js/models/PublicKeyRing.js index 9251f7eca..ace3f70d6 100644 --- a/js/models/PublicKeyRing.js +++ b/js/models/PublicKeyRing.js @@ -201,11 +201,19 @@ PublicKeyRing.prototype.getAddress = function (index, isChange) { var script = this.getRedeemScript(index,isChange); var hash = coinUtil.sha256ripe160(script.getBuffer()); - var version = this.network.addressScript; + var version = this.network.P2SHVersion; var addr = new Address(version, hash); - return addr.as('base58'); + return addr; }; +PublicKeyRing.prototype.getScriptPubKeyHex = function (index, isChange) { + this._checkIndexRange(index, isChange); + var addr = this.getAddress(index,isChange); + return Script.createP2SH(addr.payload()).getBuffer().toString('hex'); +}; + + + //generate a new address, update index. PublicKeyRing.prototype.generateAddress = function(isChange) { @@ -237,11 +245,11 @@ PublicKeyRing.prototype.getRedeemScriptMap = function () { var ret = {}; for (var i=0; i1) { - w.getAddress(i-1,isChange).should - .not.equal(w.getAddress(i-2,isChange)); + w.getAddress(i-1,isChange).toString().should + .not.equal(w.getAddress(i-2,isChange).toString()); } } } @@ -128,7 +127,7 @@ describe('PublicKeyRing model', function() { var as = w.getAddresses(); as.length.should.equal(12); for(var j in as) { - var a = new Address(as[j]); + var a = as[j]; a.isValid().should.equal(true); } }); diff --git a/test/test.txproposal.js b/test/test.txproposal.js index 8377a0206..d26938f2d 100644 --- a/test/test.txproposal.js +++ b/test/test.txproposal.js @@ -9,6 +9,8 @@ var WalletKey = bitcore.WalletKey; var Key = bitcore.Key; var BIP32 = bitcore.BIP32; var bignum = bitcore.bignum; +var Script = bitcore.Script; +var util = bitcore.util; var networks = bitcore.networks; var copay = copay || require('../copay'); var fakeStorage = copay.FakeStorage; @@ -32,7 +34,7 @@ var unspentTest = [ } ]; -var createW = function (bip32s) { +var createPKR = function (bip32s) { var w = new PublicKeyRing(config); should.exist(w); @@ -66,16 +68,16 @@ describe('TxProposals model', function() { w.network.name.should.equal('livenet'); }); - it('#create', function () { + it('#create, no signing', function () { var w = new TxProposals({ networkName: config.networkName, - publicKeyRing: createW(), + publicKeyRing: createPKR(), }); should.exist(w); w.network.name.should.equal('livenet'); - unspentTest[0].address = w.publicKeyRing.getAddress(1, true); - unspentTest[0].scriptPubKey = w.publicKeyRing.getRedeemScript(1, true).getBuffer(); + unspentTest[0].address = w.publicKeyRing.getAddress(1, true).toString(); + unspentTest[0].scriptPubKey = w.publicKeyRing.getScriptPubKeyHex(1, true); var tx = w.create( '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', @@ -84,21 +86,49 @@ describe('TxProposals model', function() { ); should.exist(tx); tx.isComplete().should.equal(false); + Object.keys(w.txps[0].signedBy).length.should.equal(0); + Object.keys(w.txps[0].seenBy).length.should.equal(0); }); + + it('#create, signing with wrong key', function () { + var w = new TxProposals({ + networkName: config.networkName, + publicKeyRing: createPKR(), + }); + should.exist(w); + w.network.name.should.equal('livenet'); + + unspentTest[0].address = w.publicKeyRing.getAddress(1, true).toString(); + unspentTest[0].scriptPubKey = w.publicKeyRing.getScriptPubKeyHex(1, true); + + var priv = new PrivateKey(config); + var tx = w.create( + '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', + bignum('123456789'), + unspentTest, + priv + ); + should.exist(tx); + tx.isComplete().should.equal(false); + Object.keys(w.txps[0].signedBy).length.should.equal(0); + Object.keys(w.txps[0].seenBy).length.should.equal(1); + }); + + it('#create. Signing with derivate keys', function () { var priv = new PrivateKey(config); var w = new TxProposals({ networkName: config.networkName, - publicKeyRing: createW([priv.getBIP32()]), + publicKeyRing: createPKR([priv.getBIP32()]), }); var ts = Date.now(); for (var isChange=0; isChange<2; isChange++) { for (var index=0; index<3; index++) { - unspentTest[0].address = w.publicKeyRing.getAddress(index, isChange); - unspentTest[0].scriptPubKey = w.publicKeyRing.getRedeemScript(index, isChange).getBuffer(); + unspentTest[0].address = w.publicKeyRing.getAddress(index, isChange).toString(); + unspentTest[0].scriptPubKey = w.publicKeyRing.getScriptPubKeyHex(index, isChange); var tx = w.create( '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', bignum('123456789'), @@ -107,25 +137,307 @@ describe('TxProposals model', function() { ); should.exist(tx); tx.isComplete().should.equal(false); + tx.countInputMissingSignatures(0).should.equal(2); - (w.txs[0].signedBy[priv.id] - ts > 0).should.equal(true); - (w.txs[0].seenBy[priv.id] - ts > 0).should.equal(true); + + (w.txps[0].signedBy[priv.id] - ts > 0).should.equal(true); + (w.txps[0].seenBy[priv.id] - ts > 0).should.equal(true); } } }); - it('#toObj #fromObj roundtrip', function () { + + it('#merge with self', function () { var priv = new PrivateKey(config); var w = new TxProposals({ networkName: config.networkName, - publicKeyRing: createW([priv.getBIP32()]), + publicKeyRing: createPKR([priv.getBIP32()]), }); var ts = Date.now(); var isChange=0; var index=0; - unspentTest[0].address = w.publicKeyRing.getAddress(index, isChange); - unspentTest[0].scriptPubKey = w.publicKeyRing.getRedeemScript(index, isChange).getBuffer(); + unspentTest[0].address = w.publicKeyRing.getAddress(index, isChange).toString(); + unspentTest[0].scriptPubKey = w.publicKeyRing.getScriptPubKeyHex(index, isChange); + var tx = w.create( + '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', + bignum('123456789'), + unspentTest, + priv + ); + + tx.isComplete().should.equal(false); + tx.countInputMissingSignatures(0).should.equal(2); + + (w.txps[0].signedBy[priv.id] - ts > 0).should.equal(true); + (w.txps[0].seenBy[priv.id] - ts > 0).should.equal(true); + + w.merge(w); + w.txps.length.should.equal(1); + + tx.isComplete().should.equal(false); + tx.countInputMissingSignatures(0).should.equal(2); + + (w.txps[0].signedBy[priv.id] - ts > 0).should.equal(true); + (w.txps[0].seenBy[priv.id] - ts > 0).should.equal(true); + + }); + + + + it('#merge, merge signatures case 1', function () { + + var priv2 = new PrivateKey(config); + var priv = new PrivateKey(config); + var ts = Date.now(); + var isChange=0; + var index=0; + var pkr = createPKR([priv.getBIP32()]); + var opts = {remainderOut: { address: pkr.generateAddress(true).toString() }}; + + + var w = new TxProposals({ + networkName: config.networkName, + publicKeyRing: pkr, + }); + unspentTest[0].address = w.publicKeyRing.getAddress(index, isChange).toString(); + unspentTest[0].scriptPubKey = w.publicKeyRing.getScriptPubKeyHex(index, isChange); + w.create( + '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', + bignum('123456789'), + unspentTest, + priv2, + opts + ); + + w.txps[0].tx.isComplete().should.equal(false); + w.txps[0].tx.countInputMissingSignatures(0).should.equal(1); + + Object.keys(w.txps[0].signedBy).length.should.equal(0); + Object.keys(w.txps[0].seenBy).length.should.equal(1); + + + var w2 = new TxProposals({ + networkName: config.networkName, + publicKeyRing: w.publicKeyRing, + }); + unspentTest[0].address = w.publicKeyRing.getAddress(index, isChange).toString(); + unspentTest[0].scriptPubKey = w.publicKeyRing.getScriptPubKeyHex(index, isChange); + w2.create( + '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', + bignum('123456789'), + unspentTest, + priv, + opts + ); + + w2.txps[0].tx.isComplete().should.equal(false); + w2.txps[0].tx.countInputMissingSignatures(0).should.equal(2); + + (w2.txps[0].signedBy[priv.id] - ts > 0).should.equal(true); + (w2.txps[0].seenBy[priv.id] - ts > 0).should.equal(true); + + w.merge(w2); + w.txps.length.should.equal(1); + + w.txps[0].tx.isComplete().should.equal(false); + w.txps[0].tx.countInputMissingSignatures(0).should.equal(2); + (w.txps[0].signedBy[priv.id] - ts > 0).should.equal(true); + (w.txps[0].seenBy[priv.id] - ts > 0).should.equal(true); + + }); + +var _dumpChunks = function (scriptSig, label) { + console.log('## DUMP: ' + label + ' ##'); + for(var i=0; i 0).should.equal(true); + (w2.txps[0].seenBy[priv.id] - ts > 0).should.equal(true); + + w.merge(w2); + w.txps.length.should.equal(1); + w.txps[0].tx.isComplete().should.equal(false); + w.txps[0].tx.countInputMissingSignatures(0).should.equal(2); + (w.txps[0].signedBy[priv.id] - ts > 0).should.equal(true); + (w.txps[0].seenBy[priv.id] - ts > 0).should.equal(true); + + + var w3 = new TxProposals({ + networkName: config.networkName, + publicKeyRing: pkr, + }); + unspentTest[0].address = w.publicKeyRing.getAddress(index, isChange).toString(); + unspentTest[0].scriptPubKey = w.publicKeyRing.getScriptPubKeyHex(index, isChange); + w3.create( + '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', + bignum('123456789'), + unspentTest, + priv2, + opts + ); + w3.txps[0].tx.isComplete().should.equal(false); + w3.txps[0].tx.countInputMissingSignatures(0).should.equal(2); + + (w3.txps[0].signedBy[priv2.id] - ts > 0).should.equal(true); + (w3.txps[0].seenBy[priv2.id] - ts > 0).should.equal(true); + + w.merge(w3); + w.txps.length.should.equal(1); + + (w.txps[0].signedBy[priv.id] - ts > 0).should.equal(true); + (w.txps[0].seenBy[priv.id] - ts > 0).should.equal(true); + (w.txps[0].signedBy[priv2.id] - ts > 0).should.equal(true); + (w.txps[0].seenBy[priv2.id] - ts > 0).should.equal(true); + + w.txps[0].tx.isComplete().should.equal(false); + w.txps[0].tx.countInputMissingSignatures(0).should.equal(1); + }); + + + it('#merge, merge signatures case 3', function () { + + var priv = new PrivateKey(config); + var priv2 = new PrivateKey(config); + var priv3 = new PrivateKey(config); + var ts = Date.now(); + var isChange=0; + var index=0; + var pkr = createPKR([priv.getBIP32(), priv2.getBIP32(), priv3.getBIP32() ]); + var opts = {remainderOut: { address: pkr.generateAddress(true).toString() }}; + + var w = new TxProposals({ + networkName: config.networkName, + publicKeyRing: pkr, + }); + unspentTest[0].address = w.publicKeyRing.getAddress(index, isChange).toString(); + unspentTest[0].scriptPubKey = w.publicKeyRing.getScriptPubKeyHex(index, isChange); + w.create( + '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', + bignum('123456789'), + unspentTest, + priv, + opts + ); + w.txps[0].tx.isComplete().should.equal(false); + w.txps[0].tx.countInputMissingSignatures(0).should.equal(2); + (w.txps[0].signedBy[priv.id] - ts > 0).should.equal(true); + (w.txps[0].seenBy[priv.id] - ts > 0).should.equal(true); + + + var w2 = new TxProposals({ + networkName: config.networkName, + publicKeyRing: pkr, + }); + unspentTest[0].address = w.publicKeyRing.getAddress(index, isChange).toString(); + unspentTest[0].scriptPubKey = w.publicKeyRing.getScriptPubKeyHex(index, isChange); + w2.create( + '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', + bignum('123456789'), + unspentTest, + priv2, + opts + ); + w2.txps[0].tx.isComplete().should.equal(false); + w2.txps[0].tx.countInputMissingSignatures(0).should.equal(2); + (w2.txps[0].signedBy[priv2.id] - ts > 0).should.equal(true); + (w2.txps[0].seenBy[priv2.id] - ts > 0).should.equal(true); + + + var w3 = new TxProposals({ + networkName: config.networkName, + publicKeyRing: pkr, + }); + unspentTest[0].address = w.publicKeyRing.getAddress(index, isChange).toString(); + unspentTest[0].scriptPubKey = w.publicKeyRing.getScriptPubKeyHex(index, isChange); + w3.create( + '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', + bignum('123456789'), + unspentTest, + priv3, + opts + ); + w3.txps[0].tx.isComplete().should.equal(false); + w3.txps[0].tx.countInputMissingSignatures(0).should.equal(2); + (w3.txps[0].signedBy[priv3.id] - ts > 0).should.equal(true); + (w3.txps[0].seenBy[priv3.id] - ts > 0).should.equal(true); + + w.merge(w2); + w.txps[0].tx.isComplete().should.equal(false); + w.txps[0].tx.countInputMissingSignatures(0).should.equal(1); + + + w.merge(w3); + w.txps[0].tx.isComplete().should.equal(true); + w.txps[0].tx.countInputMissingSignatures(0).should.equal(0); + }); + + + + it('#toObj #fromObj roundtrip', function () { + + var priv = new PrivateKey(config); + var w = new TxProposals({ + networkName: config.networkName, + publicKeyRing: createPKR([priv.getBIP32()]), + }); + var ts = Date.now(); + var isChange=0; + var index=0; + + unspentTest[0].address = w.publicKeyRing.getAddress(index, isChange).toString(); + unspentTest[0].scriptPubKey = w.publicKeyRing.getScriptPubKeyHex(index, isChange); var tx = w.create( '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', bignum('123456789'), @@ -134,23 +446,24 @@ describe('TxProposals model', function() { ); tx.isComplete().should.equal(false); tx.countInputMissingSignatures(0).should.equal(2); - (w.txs[0].signedBy[priv.id] - ts > 0).should.equal(true); - (w.txs[0].seenBy[priv.id] - ts > 0).should.equal(true); + (w.txps[0].signedBy[priv.id] - ts > 0).should.equal(true); + (w.txps[0].seenBy[priv.id] - ts > 0).should.equal(true); var o = w.toObj(); should.exist(o); - o.txs.length.should.equal(1); - should.exist(o.txs[0].txHex); - should.exist(o.txs[0].signedBy); - should.exist(o.txs[0].seenBy); - should.exist(o.txs[0].signedBy[priv.id]); + o.txps.length.should.equal(1); + should.exist(o.txps[0].txHex); + should.exist(o.txps[0].signedBy); + should.exist(o.txps[0].seenBy); + should.exist(o.txps[0].signedBy[priv.id]); var w2 = TxProposals.fromObj(o); - var tx2 = w2.txs[0].tx; + var tx2 = w2.txps[0].tx; tx2.isComplete().should.equal(false); tx2.countInputMissingSignatures(0).should.equal(2); - (w2.txs[0].signedBy[priv.id] - ts > 0).should.equal(true); - (w2.txs[0].seenBy[priv.id] - ts > 0).should.equal(true); + (w2.txps[0].signedBy[priv.id] - ts > 0).should.equal(true); + (w2.txps[0].seenBy[priv.id] - ts > 0).should.equal(true); }); + }); From dbd5ed43463928786aa474e9294e495b6c44183b Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Fri, 11 Apr 2014 07:36:43 -0300 Subject: [PATCH 08/22] add testes to test.txproposal --- test/test.txproposal.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/test.txproposal.js b/test/test.txproposal.js index d26938f2d..213dcaa07 100644 --- a/test/test.txproposal.js +++ b/test/test.txproposal.js @@ -414,13 +414,25 @@ var _dumpChunks = function (scriptSig, label) { (w3.txps[0].seenBy[priv3.id] - ts > 0).should.equal(true); w.merge(w2); + w.txps.length.should.equal(1); w.txps[0].tx.isComplete().should.equal(false); w.txps[0].tx.countInputMissingSignatures(0).should.equal(1); + (w.txps[0].seenBy[priv.id] - ts > 0).should.equal(true); + (w.txps[0].seenBy[priv2.id] - ts > 0).should.equal(true); + (w.txps[0].signedBy[priv.id] - ts > 0).should.equal(true); + (w.txps[0].signedBy[priv2.id] - ts > 0).should.equal(true); w.merge(w3); w.txps[0].tx.isComplete().should.equal(true); w.txps[0].tx.countInputMissingSignatures(0).should.equal(0); + w.txps.length.should.equal(1); + (w.txps[0].seenBy[priv.id] - ts > 0).should.equal(true); + (w.txps[0].seenBy[priv2.id] - ts > 0).should.equal(true); + (w.txps[0].seenBy[priv3.id] - ts > 0).should.equal(true); + (w.txps[0].signedBy[priv.id] - ts > 0).should.equal(true); + (w.txps[0].signedBy[priv2.id] - ts > 0).should.equal(true); + (w.txps[0].signedBy[priv3.id] - ts > 0).should.equal(true); }); From 333ecb352a8bb7477029fd960b62189ab46ddf74 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Fri, 11 Apr 2014 13:26:36 -0300 Subject: [PATCH 09/22] txproposal comuninication between peers. Still WIP --- index.html | 10 +- js/config.js | 2 + js/controllers/header.js | 3 + js/controllers/send.js | 34 +++++- js/controllers/signin.js | 1 + js/models/PrivateKey.js | 4 +- js/models/PublicKeyRing.js | 30 +++--- js/models/TxProposals.js | 14 ++- js/services/network.js | 205 +++++++++++++++++++++++++++---------- js/services/storage.js | 7 ++ test/test.publickeyring.js | 72 +++++++------ test/test.txproposal.js | 30 +++--- 12 files changed, 285 insertions(+), 127 deletions(-) diff --git a/index.html b/index.html index b5942f087..91fef6c63 100644 --- a/index.html +++ b/index.html @@ -23,6 +23,7 @@