From c2ea0b79c2ec6f6f3f6505365f9a90a4f1966355 Mon Sep 17 00:00:00 2001 From: "Ryan X. Charles" Date: Tue, 10 Jun 2014 10:46:10 -0700 Subject: [PATCH 01/13] fix getEncryptedObj test getEncryptedObj doesn't even exist any more. I remove the test for that function, and add a test for the new function, export, which replaces it. --- test/test.storage.LocalEncrypted.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/test.storage.LocalEncrypted.js b/test/test.storage.LocalEncrypted.js index 8e674a52f..60b16966b 100644 --- a/test/test.storage.LocalEncrypted.js +++ b/test/test.storage.LocalEncrypted.js @@ -46,13 +46,13 @@ if (typeof process === 'undefined' || !process.version) { }); }); - describe('#getEncryptedObj', function() { - it('should encrypt the wallet', function() { + describe('#export', function() { + it('should export the encrypted wallet', function() { localStorage.clear(); var storage = new LocalEncrypted({password: 'password'}); storage.set('walletId', 'test', 'testval'); var obj = {test:'testval'}; - var encrypted = storage.getEncryptedObj('walletId'); + var encrypted = storage.export(obj); encrypted.length.should.be.greaterThan(10); //encrypted.slice(0,6).should.equal("53616c"); }); From 57464a2a4812a50e2decda5fdc1b4d6cd6a2e4d9 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Wed, 11 Jun 2014 10:05:48 -0300 Subject: [PATCH 02/13] update references to bitcore --- test/index.html | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/index.html b/test/index.html index aea485bfa..0e3170129 100644 --- a/test/index.html +++ b/test/index.html @@ -12,12 +12,11 @@ - + - From 5c56b7972f07cb6358a43c969529ecafcaff8229 Mon Sep 17 00:00:00 2001 From: Yemel Jardi Date: Wed, 11 Jun 2014 15:39:56 -0300 Subject: [PATCH 03/13] Change wording of very weak password, add strength tip, add tests --- index.html | 4 +- js/directives.js | 51 ++++++++------------------ test/unit/directives/directivesSpec.js | 35 ++++++++++++++++++ 3 files changed, 53 insertions(+), 37 deletions(-) diff --git a/index.html b/index.html index c369e0920..ed5abe484 100644 --- a/index.html +++ b/index.html @@ -230,7 +230,7 @@

Join a Wallet in Creation

- +
@@ -316,7 +316,7 @@
diff --git a/js/directives.js b/js/directives.js index f1f5bbee8..c99a5bd93 100644 --- a/js/directives.js +++ b/js/directives.js @@ -126,49 +126,30 @@ angular.module('copayApp.directives') restrict: 'EACM', require: 'ngModel', link: function(scope, element, attrs) { - var _grep = function(elems, callback, invert) { - var callbackInverse, - matches = [], - i = 0, - length = elems.length, - callbackExpect = !invert; - - // Go through the array, only saving the items - // that pass the validator function - for (; i < length; i++) { - callbackInverse = !callback(elems[i], i); - if (callbackInverse !== callbackExpect) { - matches.push(elems[i]); - } - } - - return matches; - }; - var strength = { - messages: ['too weak', 'weak', 'weak', 'medium', 'strong'], + messages: ['very weak', 'weak', 'weak', 'medium', 'strong'], colors: ['#c0392b', '#e74c3c', '#d35400', '#f39c12', '#27ae60'], mesureStrength: function (p) { - var _force = 0; - var _regex = /[$-/:-?{-~!"^_`\[\]]/g; - var _lowerLetters = /[a-z]+/.test(p); - var _upperLetters = /[A-Z]+/.test(p); - var _numbers = /[0-9]+/.test(p); - var _symbols = _regex.test(p); - var _flags = [_lowerLetters, _upperLetters, _numbers, _symbols]; - var _passedMatches = _grep(_flags, function (el) { return el === true; }).length; + var force = 0; + var regex = /[$-/:-?{-~!"^_`\[\]]/g; + var lowerLetters = /[a-z]+/.test(p); + var upperLetters = /[A-Z]+/.test(p); + var numbers = /[0-9]+/.test(p); + var symbols = regex.test(p); + var flags = [lowerLetters, upperLetters, numbers, symbols]; + var passedMatches = flags.filter(function (el) { return !!el; }).length; - _force += 2 * p.length + ((p.length >= 10) ? 1 : 0); - _force += _passedMatches * 10; + force = 2 * p.length + (p.length >= 10 ? 1 : 0); + force += passedMatches * 10; // penality (short password) - _force = (p.length <= 6) ? Math.min(_force, 10) : _force; + force = (p.length <= 6) ? Math.min(force, 10) : force; // penality (poor variety of characters) - _force = (_passedMatches == 1) ? Math.min(_force, 10) : _force; - _force = (_passedMatches == 2) ? Math.min(_force, 20) : _force; - _force = (_passedMatches == 3) ? Math.min(_force, 40) : _force; - return _force; + force = (passedMatches == 1) ? Math.min(force, 10) : force; + force = (passedMatches == 2) ? Math.min(force, 20) : force; + force = (passedMatches == 3) ? Math.min(force, 40) : force; + return force; }, getColor: function (s) { var idx = 0; diff --git a/test/unit/directives/directivesSpec.js b/test/unit/directives/directivesSpec.js index 4f3b76d82..f6bc00bc0 100644 --- a/test/unit/directives/directivesSpec.js +++ b/test/unit/directives/directivesSpec.js @@ -63,4 +63,39 @@ describe("Unit: Testing Directives", function() { }); }); + describe('Password strength', function() { + beforeEach(inject(function($compile, $rootScope) { + $scope = $rootScope; + var element = angular.element( + '' + ); + $compile(element)($scope); + $scope.$digest(); + })); + + it('should check very weak password', function() { + $scope.password = 'asd'; + $scope.$digest(); + expect($scope.passwordStrength).to.equal('very weak'); + }); + + it('should check weak password', function() { + $scope.password = 'asdasdASDASD'; + $scope.$digest(); + expect($scope.passwordStrength).to.equal('weak'); + }); + + it('should check medium password', function() { + $scope.password = 'asdasdASDASD1'; + $scope.$digest(); + expect($scope.passwordStrength).to.equal('medium'); + }); + + it('should check strong password', function() { + $scope.password = 'asdasdASDASD1{'; + $scope.$digest(); + expect($scope.passwordStrength).to.equal('strong'); + }); + + }); }); From 4a2ca1c3bf377e124c9a1449bc808913b86b8f4f Mon Sep 17 00:00:00 2001 From: "Making GitHub Delicious." Date: Wed, 11 Jun 2014 14:00:48 -0600 Subject: [PATCH 04/13] add waffle.io badge --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 8c8260121..f1cdffa5d 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,4 @@ +[![Stories in Ready](https://badge.waffle.io/bitpay/copay.png?label=ready&title=Ready)](https://waffle.io/bitpay/copay) # Copay [![Build Status](https://secure.travis-ci.org/bitpay/copay.png)](http://travis-ci.org/bitpay/copay) [![Coverage Status](https://coveralls.io/repos/bitpay/copay/badge.png?branch=)](https://coveralls.io/r/bitpay/copay?branch=) From e5f798d5ed21cfc5f6c74ba1955cf269303eeeb6 Mon Sep 17 00:00:00 2001 From: Yemel Jardi Date: Wed, 11 Jun 2014 17:49:14 -0300 Subject: [PATCH 05/13] Add highlight on QR change, add selected address below the QR --- css/main.css | 26 ++++++++++++++++++++++++++ index.html | 5 +++-- js/directives.js | 11 +++++++++++ 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/css/main.css b/css/main.css index b29cbe070..f7f6a6f17 100644 --- a/css/main.css +++ b/css/main.css @@ -478,6 +478,32 @@ a.loading { vertical-align:middle } +@-webkit-keyframes yellow-flash { + 0% { + background-color: #FFFFE0; + opacity:1; + } + 22% { + background-color: #FFFFE0; + } + 100% { + background-color: none; + } +} + +.highlight{ + -webkit-animation-name: yellow-flash; + -webkit-animation-duration: 400ms; + -webkit-animation-iteration-count: 1; + -webkit-animation-timing-function: linear; + -moz-animation-name: yellow-flash; + -moz-animation-duration: 400ms; + -moz-animation-iteration-count: 1; + -moz-animation-timing-function: linear; +} + + + /* notifications */ .dr-notification-container { diff --git a/index.html b/index.html index c369e0920..a553b140c 100644 --- a/index.html +++ b/index.html @@ -399,7 +399,7 @@ Show less -
+

@@ -411,7 +411,8 @@ - + + {{selectedAddr.address}}
{{selectedAddr.balance || 0}}
diff --git a/js/directives.js b/js/directives.js index f1f5bbee8..d975d82b6 100644 --- a/js/directives.js +++ b/js/directives.js @@ -120,6 +120,17 @@ angular.module('copayApp.directives') } } }) + .directive('highlightOnChange', function() { + return { + restrict: 'A', + link: function(scope, element, attrs) { + scope.$watch(attrs.highlightOnChange, function (newValue, oldValue) { + element.addClass('highlight'); + setTimeout(function() { element.removeClass('highlight'); }, 500); + }); + } + } + }) .directive('checkStrength', function() { return { replace: false, From 0df0015755cd4960112b09a77d0fcdd8b004a301 Mon Sep 17 00:00:00 2001 From: Yemel Jardi Date: Thu, 12 Jun 2014 12:49:08 -0300 Subject: [PATCH 06/13] Fix transaction sorting comparator --- js/services/controllerUtils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/services/controllerUtils.js b/js/services/controllerUtils.js index 501adbd66..d0ce6bfbf 100644 --- a/js/services/controllerUtils.js +++ b/js/services/controllerUtils.js @@ -138,7 +138,7 @@ angular.module('copayApp.services') var myCopayerId = w.getMyCopayerId(); var pendingForUs = 0; - var inT = w.getTxProposals().sort(function(t1, t2) { return t1.createdTs < t2.createdTs }); + var inT = w.getTxProposals().sort(function(t1, t2) { return t2.createdTs - t1.createdTs }); var txs = []; inT.forEach(function(i, index){ From b568473d0e5672df470c4f63e3e05e7bf08fa456 Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Tue, 10 Jun 2014 10:39:57 -0300 Subject: [PATCH 07/13] add fail search script --- test/test.TxProposals.js | 362 ++++++++++++++++++++++----------------- 1 file changed, 201 insertions(+), 161 deletions(-) diff --git a/test/test.TxProposals.js b/test/test.TxProposals.js index 78bd50196..7c3c945fe 100644 --- a/test/test.TxProposals.js +++ b/test/test.TxProposals.js @@ -1,64 +1,63 @@ '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 bignum = bitcore.bignum; -var Script = bitcore.Script; -var Builder = bitcore.TransactionBuilder; -var util = bitcore.util; -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 = is_browser ? copay.PublicKeyRing : - require('soop').load('../js/models/core/PublicKeyRing', {Storage: fakeStorage}); -var is_browser = (typeof process.versions === 'undefined') +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 bignum = bitcore.bignum; +var Script = bitcore.Script; +var Builder = bitcore.TransactionBuilder; +var util = bitcore.util; +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 = is_browser ? copay.PublicKeyRing : + require('soop').load('../js/models/core/PublicKeyRing', { + Storage: fakeStorage + }); +var is_browser = (typeof process.versions === 'undefined') var config = { - networkName:'livenet', + networkName: 'livenet', }; -var unspentTest = [ - { - "address": "dummy", - "scriptPubKey": "dummy", - "txid": "2ac165fa7a3a2b535d106a0041c7568d03b531e58aeccdd3199d7289ab12cfc1", - "vout": 1, - "amount": 10, - "confirmations":7 - } -]; +var unspentTest = [{ + "address": "dummy", + "scriptPubKey": "dummy", + "txid": "2ac165fa7a3a2b535d106a0041c7568d03b531e58aeccdd3199d7289ab12cfc1", + "vout": 1, + "amount": 10, + "confirmations": 7 +}]; -var createPKR = function (bip32s) { +var createPKR = function(bip32s) { var w = new PublicKeyRing(config); should.exist(w); - for(var i=0; i<5; i++) { + for (var i = 0; i < 5; i++) { if (bip32s) { - var b=bip32s[i]; - w.addCopayer(b?b.deriveBIP45Branch().extendedPublicKeyString():null); - } - else + var b = bip32s[i]; + w.addCopayer(b ? b.deriveBIP45Branch().extendedPublicKeyString() : null); + } else w.addCopayer(); } - w.generateAddress(true); - w.generateAddress(true); - w.generateAddress(true); - w.generateAddress(false); - w.generateAddress(false); - w.generateAddress(false); - //3x3 indexes - + w.generateAddress(true); + w.generateAddress(true); + w.generateAddress(true); + w.generateAddress(false); + w.generateAddress(false); + w.generateAddress(false); + //3x3 indexes + return w; }; -var vopts = { +var vopts = { verifyP2SH: true, dontVerifyStrictEnc: true }; @@ -66,25 +65,29 @@ var vopts = { describe('TxProposals model', function() { - it('verify TXs', function (done) { + it('verify TXs', function(done) { 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, priv2, priv3]); - var opts = {remainderOut: { address: pkr.generateAddress(true).toString() }}; + var isChange = 0; + var index = 0; + var pkr = createPKR([priv, priv2, priv3]); + var opts = { + remainderOut: { + address: pkr.generateAddress(true).toString() + } + }; var w = new TxProposals({ networkName: config.networkName, }); - unspentTest[0].address = pkr.getAddress(index, isChange).toString(); - unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange); + unspentTest[0].address = pkr.getAddress(index, isChange).toString(); + unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange); w.add(createTx( - '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', - '123456789', + '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', + '123456789', unspentTest, opts, priv, @@ -94,25 +97,25 @@ describe('TxProposals model', function() { var b = w.txps[k].builder; var tx = b.build(); tx.isComplete().should.equal(false); - b.sign(priv2.getAll(pkr.indexes.getReceiveIndex(), pkr.indexes.getChangeIndex()) ); - b.sign(priv3.getAll(pkr.indexes.getReceiveIndex(), pkr.indexes.getChangeIndex()) ); + b.sign(priv2.getAll(pkr.indexes.getReceiveIndex(), pkr.indexes.getChangeIndex())); + b.sign(priv3.getAll(pkr.indexes.getReceiveIndex(), pkr.indexes.getChangeIndex())); tx = b.build(); tx.isComplete().should.equal(true); - var s = new Script(new Buffer(unspentTest[0].scriptPubKey,'hex')); + var s = new Script(new Buffer(unspentTest[0].scriptPubKey, 'hex')); - tx.verifyInput(0,s, { + tx.verifyInput(0, s, { verifyP2SH: true, dontVerifyStrictEnc: true - }, function(err, results){ - should.not.exist(err); - results.should.equal(true); + }, function(err, results) { + should.not.exist(err); + results.should.equal(true); done(); }); }); - - it('should create an instance', function () { + + it('should create an instance', function() { var w = new TxProposals({ networkName: config.networkName }); @@ -120,57 +123,60 @@ describe('TxProposals model', function() { w.network.name.should.equal('livenet'); }); - function createTx(toAddress, amountSatStr, utxos, opts, priv, pkr) { + var createTx = function(toAddress, amountSatStr, utxos, opts, priv, pkr) { opts = opts || {}; var amountSat = bitcore.bignum(amountSatStr); - if(! pkr.isComplete() ) { + if (!pkr.isComplete()) { throw new Error('publicKeyRing is not complete'); } if (!opts.remainderOut) { - opts.remainderOut ={ address: pkr.generateAddress(true).toString() }; + opts.remainderOut = { + address: pkr.generateAddress(true).toString() + }; }; var b = new Builder(opts) - .setUnspent(utxos) - .setHashToScriptMap(pkr.getRedeemScriptMap()) - .setOutputs([{address: toAddress, amountSat: amountSat}]) - ; + .setUnspent(utxos) + .setHashToScriptMap(pkr.getRedeemScriptMap()) + .setOutputs([{ + address: toAddress, + amountSat: amountSat + }]); - var signRet; + var signRet; if (priv) { - b.sign( priv.getAll(pkr.indexes.getReceiveIndex(), pkr.indexes.getChangeIndex()) ); + b.sign(priv.getAll(pkr.indexes.getReceiveIndex(), pkr.indexes.getChangeIndex())); } var me = {}; if (priv) me[priv.id] = Date.now(); return { signedBy: priv && b.signaturesAdded ? me : {}, - seenBy: priv ? me : {}, + seenBy: priv ? me : {}, builder: b, }; }; - it('#getUsedUnspend', function () { + it('#getUsedUnspend', function() { var priv = new PrivateKey(config); var w = new TxProposals({ networkName: config.networkName, }); var start = new Date().getTime(); - var pkr=createPKR([priv]); + var pkr = createPKR([priv]); var ts = Date.now(); - var isChange=0; - var index=0; - unspentTest[0].address = pkr.getAddress(index, isChange).toString(); - unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange); + var isChange = 0; + var index = 0; + unspentTest[0].address = pkr.getAddress(index, isChange).toString(); + unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange); w.add(createTx( - '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', - '123456789', - unspentTest, - {}, + '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', + '123456789', + unspentTest, {}, priv, pkr )); @@ -180,24 +186,23 @@ describe('TxProposals model', function() { uuk[0].split(',')[0].should.equal(unspentTest[0].txid); }); - it('#merge with self', function () { + it('#merge with self', function() { var priv = new PrivateKey(config); var w = new TxProposals({ networkName: config.networkName, }); var start = new Date().getTime(); - var pkr=createPKR([priv]); + var pkr = createPKR([priv]); var ts = Date.now(); - var isChange=0; - var index=0; + var isChange = 0; + var index = 0; - unspentTest[0].address = pkr.getAddress(index, isChange).toString(); - unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange); + unspentTest[0].address = pkr.getAddress(index, isChange).toString(); + unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange); w.add(createTx( - '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', - '123456789', - unspentTest, - {}, + '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', + '123456789', + unspentTest, {}, priv, pkr )); @@ -221,24 +226,28 @@ describe('TxProposals model', function() { - it('#merge, merge signatures case 1', function () { + 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 isChange = 0; + var index = 0; var pkr = createPKR([priv]); - var opts = {remainderOut: { address: pkr.generateAddress(true).toString() }}; + var opts = { + remainderOut: { + address: pkr.generateAddress(true).toString() + } + }; var w = new TxProposals({ networkName: config.networkName, }); - unspentTest[0].address = pkr.getAddress(index, isChange).toString(); - unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange); + unspentTest[0].address = pkr.getAddress(index, isChange).toString(); + unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange); w.add(createTx( - '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', - '123456789', + '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', + '123456789', unspentTest, opts, priv2, @@ -258,11 +267,11 @@ describe('TxProposals model', function() { networkName: config.networkName, publicKeyRing: w.publicKeyRing, }); - unspentTest[0].address = pkr.getAddress(index, isChange).toString(); - unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange); + unspentTest[0].address = pkr.getAddress(index, isChange).toString(); + unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange); w2.add(createTx( - '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', - '123456789', + '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', + '123456789', unspentTest, opts, priv, @@ -285,61 +294,69 @@ describe('TxProposals model', function() { tx.countInputMissingSignatures(0).should.equal(2); (w.txps[k].signedBy[priv.id] - ts > 0).should.equal(true); (w.txps[k].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); + console.log('8 should'); (w2.txps[k].seenBy[priv.id] - ts > 0).should.equal(true); w.merge(w2); + console.log('9 should'); Object.keys(w.txps).length.should.equal(1); tx = w.txps[k].builder.build(); + console.log('10 should'); tx.isComplete().should.equal(false); + console.log('11 should'); tx.countInputMissingSignatures(0).should.equal(2); + console.log('12 should'); (w.txps[k].signedBy[priv.id] - ts > 0).should.equal(true); + console.log('13 should'); (w.txps[k].seenBy[priv.id] - ts > 0).should.equal(true); @@ -367,57 +393,72 @@ var _dumpChunks = function (scriptSig, label) { networkName: config.networkName, publicKeyRing: pkr, }); - unspentTest[0].address = pkr.getAddress(index, isChange).toString(); - unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange); + unspentTest[0].address = pkr.getAddress(index, isChange).toString(); + unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange); w3.add(createTx( - '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', - '123456789', + '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', + '123456789', unspentTest, opts, priv2, pkr )); tx = w3.txps[k].builder.build(); + console.log('14 should'); tx.isComplete().should.equal(false); + console.log('15 should'); tx.countInputMissingSignatures(0).should.equal(2); + console.log('16 should'); (w3.txps[k].signedBy[priv2.id] - ts > 0).should.equal(true); + console.log('17 should'); (w3.txps[k].seenBy[priv2.id] - ts > 0).should.equal(true); w.merge(w3); + console.log('18 should'); Object.keys(w.txps).length.should.equal(1); + console.log('19 should'); (w.txps[k].signedBy[priv.id] - ts > 0).should.equal(true); + console.log('20 should'); (w.txps[k].seenBy[priv.id] - ts > 0).should.equal(true); + console.log('21 should'); (w.txps[k].signedBy[priv2.id] - ts > 0).should.equal(true); + console.log('22 should'); (w.txps[k].seenBy[priv2.id] - ts > 0).should.equal(true); tx = w.txps[k].builder.build(); + console.log('23 should'); tx.isComplete().should.equal(false); + console.log('24 should'); tx.countInputMissingSignatures(0).should.equal(1); }); - it('#merge, merge signatures case 3', function () { + 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, priv2, priv3]); - var opts = {remainderOut: { address: pkr.generateAddress(true).toString() }}; + var ts = Date.now(); + var isChange = 0; + var index = 0; + var pkr = createPKR([priv, priv2, priv3]); + var opts = { + remainderOut: { + address: pkr.generateAddress(true).toString() + } + }; var w = new TxProposals({ networkName: config.networkName, }); - unspentTest[0].address = pkr.getAddress(index, isChange).toString(); - unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange); + unspentTest[0].address = pkr.getAddress(index, isChange).toString(); + unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange); w.add(createTx( - '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', - '123456789', + '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', + '123456789', unspentTest, opts, priv, @@ -434,11 +475,11 @@ var _dumpChunks = function (scriptSig, label) { var w2 = new TxProposals({ networkName: config.networkName, }); - unspentTest[0].address = pkr.getAddress(index, isChange).toString(); - unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange); + unspentTest[0].address = pkr.getAddress(index, isChange).toString(); + unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange); w2.add(createTx( - '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', - '123456789', + '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', + '123456789', unspentTest, opts, priv2, @@ -454,11 +495,11 @@ var _dumpChunks = function (scriptSig, label) { var w3 = new TxProposals({ networkName: config.networkName, }); - unspentTest[0].address = pkr.getAddress(index, isChange).toString(); - unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange); + unspentTest[0].address = pkr.getAddress(index, isChange).toString(); + unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange); w3.add(createTx( - '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', - '123456789', + '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', + '123456789', unspentTest, opts, priv3, @@ -496,7 +537,7 @@ var _dumpChunks = function (scriptSig, label) { - it('#toObj #fromObj roundtrip', function () { + it('#toObj #fromObj roundtrip', function() { var priv = new PrivateKey(config); var pkr = createPKR([priv]); @@ -505,16 +546,15 @@ var _dumpChunks = function (scriptSig, label) { networkName: config.networkName, }); var ts = Date.now(); - var isChange=0; - var index=0; + var isChange = 0; + var index = 0; - unspentTest[0].address = pkr.getAddress(index, isChange).toString(); - unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange); + unspentTest[0].address = pkr.getAddress(index, isChange).toString(); + unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange); w.add(createTx( - '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', - '123456789', - unspentTest, - {}, + '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', + '123456789', + unspentTest, {}, priv, pkr )); @@ -545,7 +585,7 @@ var _dumpChunks = function (scriptSig, label) { (w2.txps[k].seenBy[priv.id] - ts > 0).should.equal(true); should.exist(w2.txps[k].builder); should.exist(w2.txps[k].builder.valueInSat); - + w2.merge(w); Object.keys(w2.txps).length.should.equal(1); }); From a5cef11e475f211d340df54c380c293c2ff2eeb0 Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Wed, 11 Jun 2014 11:22:48 -0300 Subject: [PATCH 08/13] trying to fix failing test --- test/test.TxProposals.js | 52 +++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/test/test.TxProposals.js b/test/test.TxProposals.js index 7c3c945fe..52034627e 100644 --- a/test/test.TxProposals.js +++ b/test/test.TxProposals.js @@ -23,7 +23,7 @@ var PublicKeyRing = is_browser ? copay.PublicKeyRing : var is_browser = (typeof process.versions === 'undefined') var config = { - networkName: 'livenet', + networkName: 'testnet', }; var unspentTest = [{ @@ -40,20 +40,13 @@ var createPKR = function(bip32s) { should.exist(w); for (var i = 0; i < 5; i++) { - if (bip32s) { + if (bip32s && i < bip32s.length) { var b = bip32s[i]; - w.addCopayer(b ? b.deriveBIP45Branch().extendedPublicKeyString() : null); - } else + w.addCopayer(b.deriveBIP45Branch().extendedPublicKeyString()); + } else { w.addCopayer(); + } } - w.generateAddress(true); - w.generateAddress(true); - w.generateAddress(true); - w.generateAddress(false); - w.generateAddress(false); - w.generateAddress(false); - //3x3 indexes - return w; }; @@ -149,6 +142,7 @@ describe('TxProposals model', function() { var signRet; if (priv) { b.sign(priv.getAll(pkr.indexes.getReceiveIndex(), pkr.indexes.getChangeIndex())); + console.log('signed with priv'); } var me = {}; if (priv) me[priv.id] = Date.now(); @@ -316,15 +310,18 @@ describe('TxProposals model', function() { var pkr = createPKR([priv, priv2]); var opts = { remainderOut: { - address: pkr.generateAddress(true).toString() + address: '2MxK2m7cPtEwjZBB8Ksq7ppjkgJyFPJGemr' } }; + var addressToSign = pkr.generateAddress(false); + unspentTest[0].address = addressToSign.toString(); + unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange); + var tx, txb; + /* var w = new TxProposals({ networkName: config.networkName, }); - unspentTest[0].address = pkr.getAddress(index, isChange).toString(); - unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange); w.add(createTx( '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', @@ -336,7 +333,11 @@ describe('TxProposals model', function() { )); var ntxid = Object.keys(w.txps)[0]; - var tx = w.txps[ntxid].builder.build(); + txb = w.txps[ntxid].builder; + console.log('new should A'); + txb.signaturesAdded.should.equal(0); + tx = txb.build(); + console.log('first should'); tx.isComplete().should.equal(false); console.log('2 should'); @@ -346,14 +347,12 @@ describe('TxProposals model', function() { Object.keys(w.txps[ntxid].signedBy).length.should.equal(0); console.log('4 should'); Object.keys(w.txps[ntxid].seenBy).length.should.equal(1); - + */ var w2 = new TxProposals({ networkName: config.networkName, }); - unspentTest[0].address = pkr.getAddress(index, isChange).toString(); - unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange); w2.add(createTx( '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', '123456789', @@ -362,17 +361,22 @@ describe('TxProposals model', function() { priv, pkr )); - var k = Object.keys(w2.txps)[0]; - tx = w2.txps[k].builder.build(); + var ntxid = Object.keys(w2.txps)[0]; + txb = w2.txps[ntxid].builder; + tx = txb.build(); + + console.log('new should B'); + txb.signaturesAdded.should.equal(1); console.log('5 should'); tx.isComplete().should.equal(false); console.log('6 should'); tx.countInputMissingSignatures(0).should.equal(2); + return; console.log('7 should'); - (w2.txps[k].signedBy[priv.id] - ts > 0).should.equal(true); + (w2.txps[ntxid].signedBy[priv.id] - ts > 0).should.equal(true); console.log('8 should'); - (w2.txps[k].seenBy[priv.id] - ts > 0).should.equal(true); + (w2.txps[ntxid].seenBy[priv.id] - ts > 0).should.equal(true); w.merge(w2); console.log('9 should'); @@ -393,8 +397,6 @@ describe('TxProposals model', function() { networkName: config.networkName, publicKeyRing: pkr, }); - unspentTest[0].address = pkr.getAddress(index, isChange).toString(); - unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange); w3.add(createTx( '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', '123456789', From 322a793b6286c50dcd96bf92731a77b786e9e5c8 Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Thu, 12 Jun 2014 14:27:53 -0300 Subject: [PATCH 09/13] trying to fix tests --- js/models/blockchain/Insight.js | 3 -- js/models/core/PrivateKey.js | 3 +- js/models/core/PublicKeyRing.js | 1 + js/models/core/Wallet.js | 2 +- test/test.TxProposals.js | 78 +++++++++++++-------------------- 5 files changed, 35 insertions(+), 52 deletions(-) diff --git a/js/models/blockchain/Insight.js b/js/models/blockchain/Insight.js index d5692ac51..92f31bc47 100644 --- a/js/models/blockchain/Insight.js +++ b/js/models/blockchain/Insight.js @@ -182,7 +182,6 @@ Insight.prototype._request = function(options, callback) { request.open(options.method, url, true); request.timeout = 5000; request.ontimeout = function() { - console.log('Insight timeout...retrying'); setTimeout(function() { return self._request(options,callback); }, self.retryDelay); @@ -206,9 +205,7 @@ Insight.prototype._request = function(options, callback) { else { var err= 'Error code: ' + request.status + ' - Status: ' + request.statusText + ' - Description: ' + request.responseText; - console.log('Insight Temporary error (will retry):', err); setTimeout(function() { - console.log('### Retrying Insight Request....'); //TODO return self._request(options,callback); }, self.retryDelay); return callback(new Error(err)); diff --git a/js/models/core/PrivateKey.js b/js/models/core/PrivateKey.js index 7475f9146..1efe93694 100644 --- a/js/models/core/PrivateKey.js +++ b/js/models/core/PrivateKey.js @@ -58,7 +58,8 @@ PrivateKey.prototype._getHK = function(path) { if (typeof path === 'undefined') { return this.bip; } - return this.bip.derive(path); + var ret = this.bip.derive(path); + return ret; }; PrivateKey.prototype.getForPaths = function(paths) { diff --git a/js/models/core/PublicKeyRing.js b/js/models/core/PublicKeyRing.js index f449158cc..bc3148606 100644 --- a/js/models/core/PublicKeyRing.js +++ b/js/models/core/PublicKeyRing.js @@ -151,6 +151,7 @@ PublicKeyRing.prototype.getPubKeys = function(index, isChange) { pubKeys = pubKeys.map(function(s){return new Buffer(s,'hex');}); } + return pubKeys; }; diff --git a/js/models/core/Wallet.js b/js/models/core/Wallet.js index e6d45201c..9f20ea35e 100644 --- a/js/models/core/Wallet.js +++ b/js/models/core/Wallet.js @@ -92,7 +92,7 @@ Wallet.prototype._handlePublicKeyRing = function(senderId, data, isInbound) { try{ hasChanged = this.publicKeyRing.merge(inPKR, true); } catch (e){ - console.log('## WALLET ERROR', e); //TODO + this.log('## WALLET ERROR', e); //TODO this.emit('connectionError', e.message); return; } diff --git a/test/test.TxProposals.js b/test/test.TxProposals.js index 52034627e..bf459ca01 100644 --- a/test/test.TxProposals.js +++ b/test/test.TxProposals.js @@ -141,8 +141,8 @@ describe('TxProposals model', function() { var signRet; if (priv) { - b.sign(priv.getAll(pkr.indexes.getReceiveIndex(), pkr.indexes.getChangeIndex())); - console.log('signed with priv'); + var pkeys = priv.getAll(pkr.indexes.getReceiveIndex(), pkr.indexes.getChangeIndex()); + b.sign(pkeys); } var me = {}; if (priv) me[priv.id] = Date.now(); @@ -299,11 +299,23 @@ describe('TxProposals model', function() { }; - it.only('#merge, merge signatures case 2', function() { + it('#merge, merge signatures case 2', function() { + + var o1 ={ extendedPrivateKeyString: 'tprv8ZgxMBicQKsPdSF1avR6mXyDj5Uv1XY2UyUHSDpAXQ5TvPN7prGeDppjy4562rBB9gMMAhRfFdJrNDpQ4t69kkqHNEEen3PX1zBJqSehJDH', + networkName: 'testnet', + privateKeyCache: {} }; + var o2 ={ extendedPrivateKeyString: 'tprv8ZgxMBicQKsPdVeB5RzuxS9JQcACueZYgUaM5eWzaEBkHjW5Pg6Mqez1APSqoUP1jUdbT8WVG7ZJYTXvUL7XtPzFYBXjmdKuwSor1dcNQ8j', + networkName: 'testnet', + privateKeyCache: {} }; + var o3 ={ extendedPrivateKeyString: 'tprv8ZgxMBicQKsPeHWNrPVZtQVgcCtXBr5TACNbDQ56rwqNJce9MEc64US6DJKxpWsrebEomxxWZFDtkvkZGkzA43uLvdF4XHiWqoNaL6Dq2Gd', + networkName: 'testnet', + privateKeyCache: {} }; + + + var priv = PrivateKey.fromObj(o1); + var priv2 = PrivateKey.fromObj(o2); + var priv3 = PrivateKey.fromObj(o3); - 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; @@ -318,7 +330,6 @@ describe('TxProposals model', function() { unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange); var tx, txb; - /* var w = new TxProposals({ networkName: config.networkName, }); @@ -334,25 +345,21 @@ describe('TxProposals model', function() { var ntxid = Object.keys(w.txps)[0]; txb = w.txps[ntxid].builder; - console.log('new should A'); txb.signaturesAdded.should.equal(0); tx = txb.build(); - console.log('first should'); tx.isComplete().should.equal(false); - console.log('2 should'); tx.countInputMissingSignatures(0).should.equal(1); - console.log('3 should'); Object.keys(w.txps[ntxid].signedBy).length.should.equal(0); - console.log('4 should'); Object.keys(w.txps[ntxid].seenBy).length.should.equal(1); - */ var w2 = new TxProposals({ networkName: config.networkName, }); + + w2.add(createTx( '15q6HKjWHAksHcH91JW23BJEuzZgFwydBt', '123456789', @@ -365,32 +372,21 @@ describe('TxProposals model', function() { txb = w2.txps[ntxid].builder; tx = txb.build(); - console.log('new should B'); txb.signaturesAdded.should.equal(1); - console.log('5 should'); tx.isComplete().should.equal(false); - console.log('6 should'); tx.countInputMissingSignatures(0).should.equal(2); - return; - console.log('7 should'); (w2.txps[ntxid].signedBy[priv.id] - ts > 0).should.equal(true); - console.log('8 should'); (w2.txps[ntxid].seenBy[priv.id] - ts > 0).should.equal(true); w.merge(w2); - console.log('9 should'); Object.keys(w.txps).length.should.equal(1); - tx = w.txps[k].builder.build(); - console.log('10 should'); + tx = w.txps[ntxid].builder.build(); tx.isComplete().should.equal(false); - console.log('11 should'); tx.countInputMissingSignatures(0).should.equal(2); - console.log('12 should'); - (w.txps[k].signedBy[priv.id] - ts > 0).should.equal(true); - console.log('13 should'); - (w.txps[k].seenBy[priv.id] - ts > 0).should.equal(true); + (w.txps[ntxid].signedBy[priv.id] - ts > 0).should.equal(true); + (w.txps[ntxid].seenBy[priv.id] - ts > 0).should.equal(true); var w3 = new TxProposals({ @@ -405,36 +401,24 @@ describe('TxProposals model', function() { priv2, pkr )); - tx = w3.txps[k].builder.build(); - console.log('14 should'); + tx = w3.txps[ntxid].builder.build(); tx.isComplete().should.equal(false); - console.log('15 should'); tx.countInputMissingSignatures(0).should.equal(2); - console.log('16 should'); - (w3.txps[k].signedBy[priv2.id] - ts > 0).should.equal(true); - console.log('17 should'); - (w3.txps[k].seenBy[priv2.id] - ts > 0).should.equal(true); + (w3.txps[ntxid].signedBy[priv2.id] - ts > 0).should.equal(true); + (w3.txps[ntxid].seenBy[priv2.id] - ts > 0).should.equal(true); w.merge(w3); - console.log('18 should'); Object.keys(w.txps).length.should.equal(1); - console.log('19 should'); - (w.txps[k].signedBy[priv.id] - ts > 0).should.equal(true); - console.log('20 should'); - (w.txps[k].seenBy[priv.id] - ts > 0).should.equal(true); - console.log('21 should'); - (w.txps[k].signedBy[priv2.id] - ts > 0).should.equal(true); - console.log('22 should'); - (w.txps[k].seenBy[priv2.id] - ts > 0).should.equal(true); + (w.txps[ntxid].signedBy[priv.id] - ts > 0).should.equal(true); + (w.txps[ntxid].seenBy[priv.id] - ts > 0).should.equal(true); + (w.txps[ntxid].signedBy[priv2.id] - ts > 0).should.equal(true); + (w.txps[ntxid].seenBy[priv2.id] - ts > 0).should.equal(true); - tx = w.txps[k].builder.build(); - console.log('23 should'); + tx = w.txps[ntxid].builder.build(); tx.isComplete().should.equal(false); - console.log('24 should'); tx.countInputMissingSignatures(0).should.equal(1); - }); From 2bec53135c3a571ab32ab052a65a73bc2e0dc588 Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Thu, 12 Jun 2014 14:34:32 -0300 Subject: [PATCH 10/13] fix older tests --- test/test.TxProposals.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/test/test.TxProposals.js b/test/test.TxProposals.js index bf459ca01..b2aae9f3b 100644 --- a/test/test.TxProposals.js +++ b/test/test.TxProposals.js @@ -47,6 +47,13 @@ var createPKR = function(bip32s) { w.addCopayer(); } } + w.generateAddress(false); + w.generateAddress(false); + w.generateAddress(false); + w.generateAddress(true); + w.generateAddress(true); + w.generateAddress(true); + return w; }; @@ -113,7 +120,7 @@ describe('TxProposals model', function() { networkName: config.networkName }); should.exist(w); - w.network.name.should.equal('livenet'); + w.network.name.should.equal(config.networkName); }); var createTx = function(toAddress, amountSatStr, utxos, opts, priv, pkr) { From bcbb6b54d1d0ee56a0f8cc0c9f275c7963dc14f6 Mon Sep 17 00:00:00 2001 From: Yemel Jardi Date: Fri, 13 Jun 2014 10:33:30 -0300 Subject: [PATCH 11/13] Add user comment to transaction propossal --- css/main.css | 8 +++++ index.html | 22 +++++++++++++- js/controllers/send.js | 9 +++--- js/models/core/PublicKeyRing.js | 2 +- js/models/core/TxProposals.js | 1 + js/models/core/Wallet.js | 11 +++++-- test/test.Wallet.js | 53 ++++++++++++++++++++++++++++++--- util/find_m_n.js | 2 +- 8 files changed, 93 insertions(+), 15 deletions(-) diff --git a/css/main.css b/css/main.css index b29cbe070..c3b5cbdaf 100644 --- a/css/main.css +++ b/css/main.css @@ -422,6 +422,14 @@ hr { margin: 2.25rem 0;} background: #C0392B; } +.box-note { + text-align: center; + clear: both; + font-style: italic; + color: gray; + margin-bottom: 10px; +} + .box-signin { padding: 20px 40px; border: 1px solid #eee; diff --git a/index.html b/index.html index c369e0920..0a13cac95 100644 --- a/index.html +++ b/index.html @@ -189,7 +189,7 @@ src="./img/satoshi.gif" />

- {{c.nick || 'NN'}} + {{c.nick}}
@@ -455,6 +455,9 @@
+
+ "{{tx.comment}}" - {{$root.wallet.publicKeyRing.nicknameForCopayer(tx.creator)}} +
@@ -664,6 +667,23 @@
+ +
+
+
+ +
+ +
+
+
+
+