From 1324974c4d17c01d2a19ea84dc0363c7c92fba70 Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Wed, 19 Mar 2014 16:20:41 -0300 Subject: [PATCH 1/9] add isScript to Address --- Address.js | 5 +++++ test/test.Address.js | 23 ++++++++++++++++++----- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/Address.js b/Address.js index f8dcf8e49..679dbb3d1 100644 --- a/Address.js +++ b/Address.js @@ -38,4 +38,9 @@ Address.prototype.network = function() { return answer; }; +Address.prototype.isScript = function() { + return this.isValid() && this.version() === this.network().addressScript; +}; + + module.exports = require('soop')(Address); diff --git a/test/test.Address.js b/test/test.Address.js index 3e0441f67..e1d73d87f 100644 --- a/test/test.Address.js +++ b/test/test.Address.js @@ -48,23 +48,36 @@ describe('Address', function() { }); }); it('should be able to detect network from an address', function() { + // livenet var a = new Address('1KfyjCgBSMsLqiCbakfSdeoBUqMqLUiu3T'); a.network().name.should.equal('livenet'); - var a = new Address('1dice8EMZmqKvrGE4Qc9bUFf9PX3xaYDp'); + a = new Address('1dice8EMZmqKvrGE4Qc9bUFf9PX3xaYDp'); a.network().name.should.equal('livenet'); //p2sh - var a = new Address('3QRhucKtEn5P9i7YPxzXCqBtPJTPbRFycn'); + a = new Address('3QRhucKtEn5P9i7YPxzXCqBtPJTPbRFycn'); a.network().name.should.equal('livenet'); //testnet - var a = new Address('mrPnbY1yKDBsdgbHbS7kJ8GVm8F66hWHLE'); + a = new Address('mrPnbY1yKDBsdgbHbS7kJ8GVm8F66hWHLE'); a.network().name.should.equal('testnet'); - var a = new Address('n2ekxibY5keRiMaoKFGfiNfXQCS4zTUpct'); + a = new Address('n2ekxibY5keRiMaoKFGfiNfXQCS4zTUpct'); a.network().name.should.equal('testnet'); //p2sh - var a = new Address('2NBSBcf2KfjPEEqVusmrWdmUeNHRiUTS3Li'); + a = new Address('2NBSBcf2KfjPEEqVusmrWdmUeNHRiUTS3Li'); a.network().name.should.equal('testnet'); }); + it('#isScript should work', function() { + // invalid + new Address('1T').isScript().should.equal(false); + // pubKeyHash livenet + new Address('1KfyjCgBSMsLqiCbakfSdeoBUqMqLUiu3T').isScript().should.equal(false); + // script livenet + new Address('3QRhucKtEn5P9i7YPxzXCqBtPJTPbRFycn').isScript().should.equal(true); + // pubKeyHash testnet + new Address('mrPnbY1yKDBsdgbHbS7kJ8GVm8F66hWHLE').isScript().should.equal(false); + // script testnet + new Address('2NBSBcf2KfjPEEqVusmrWdmUeNHRiUTS3Li').isScript().should.equal(true); + }); }); From 4b430be5c827ccae1b00fa2c80276c5efdf1c4ae Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Wed, 19 Mar 2014 16:25:23 -0300 Subject: [PATCH 2/9] add base58key tests for Address case --- test/test.misc.js | 19 +++++++++++++++++++ test/testdata.js | 5 +++++ 2 files changed, 24 insertions(+) diff --git a/test/test.misc.js b/test/test.misc.js index d5528b951..8757da485 100644 --- a/test/test.misc.js +++ b/test/test.misc.js @@ -12,6 +12,9 @@ var bignum = bitcore.bignum; var base58 = bitcore.base58; var base58Check = base58.base58Check; +var Address = bitcore.Address; +var networks = bitcore.networks; + describe('Miscelaneous stuff', function() { it('should initialze the config object', function() { should.exist(bitcore.config); @@ -63,6 +66,22 @@ describe('Miscelaneous stuff', function() { buffertools.toHex(base58.decode(datum[1])).should.equal(datum[0]); }); }); + testdata.dataBase58KeysValid.forEach(function(datum) { + var b58 = datum[0]; + var hexPayload = datum[1]; + var meta = datum[2]; + it('base58 keys valid ' + b58, function() { + if (meta.isPrivkey) { + (true).should.equal(true); + } else { + var a = new Address(b58); + a.isValid().should.equal(true); + a.isScript().should.equal(meta.addrType === 'script'); + a.network().should.equal(meta.isTestnet?networks.testnet:networks.livenet); + } + + }); + }); }); diff --git a/test/testdata.js b/test/testdata.js index 217d81272..3c7f3fda5 100644 --- a/test/testdata.js +++ b/test/testdata.js @@ -11,6 +11,8 @@ var dataUnspent = JSON.parse(fs.readFileSync('test/data/unspent.json')); var dataUnspentSign = JSON.parse(fs.readFileSync('test/data/unspentSign.json')); var dataSigCanonical = JSON.parse(fs.readFileSync('test/data/sig_canonical.json')); var dataSigNonCanonical = JSON.parse(fs.readFileSync('test/data/sig_noncanonical.json')); +var dataBase58KeysValid = JSON.parse(fs.readFileSync('test/data/base58_keys_valid.json')); +var dataBase58KeysInvalid = JSON.parse(fs.readFileSync('test/data/base58_keys_invalid.json')); module.exports.dataValid = dataValid; module.exports.dataInvalid = dataInvalid; @@ -25,3 +27,6 @@ module.exports.dataUnspentSign = dataUnspentSign; module.exports.dataSigCanonical = dataSigCanonical; module.exports.dataSigNonCanonical = dataSigNonCanonical; +module.exports.dataBase58KeysValid = dataBase58KeysValid; +module.exports.dataBase58KeysInvalid = dataBase58KeysInvalid; + From f0b9cd0cab8963dd9e83f5b5a7db073cca9c93e4 Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Wed, 19 Mar 2014 17:12:24 -0300 Subject: [PATCH 3/9] complete base58_keys_valid tests --- Key.js | 2 +- test/test.misc.js | 11 ++++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/Key.js b/Key.js index e81c7b355..97d958f4b 100644 --- a/Key.js +++ b/Key.js @@ -33,7 +33,7 @@ if (process.versions) { throw new Error('Arg should be a buffer'); } var type = p[0]; - this.compressed = type!==4; + this.compressed = type!==0x04; this._pub = p; }, get: function(){ diff --git a/test/test.misc.js b/test/test.misc.js index 8757da485..822b83679 100644 --- a/test/test.misc.js +++ b/test/test.misc.js @@ -14,6 +14,7 @@ var base58Check = base58.base58Check; var Address = bitcore.Address; var networks = bitcore.networks; +var WalletKey = bitcore.WalletKey; describe('Miscelaneous stuff', function() { it('should initialze the config object', function() { @@ -71,15 +72,19 @@ describe('Miscelaneous stuff', function() { var hexPayload = datum[1]; var meta = datum[2]; it('base58 keys valid ' + b58, function() { + var network = meta.isTestnet?networks.testnet:networks.livenet; if (meta.isPrivkey) { - (true).should.equal(true); + var k = new WalletKey({network: network}); + k.fromObj({priv: b58}); + k.privKey.compressed.should.equal(meta.isCompressed); + buffertools.toHex(k.privKey.private).should.equal(hexPayload); + new Address(b58).isValid().should.equal(false); } else { var a = new Address(b58); a.isValid().should.equal(true); a.isScript().should.equal(meta.addrType === 'script'); - a.network().should.equal(meta.isTestnet?networks.testnet:networks.livenet); + a.network().should.equal(network); } - }); }); From d84dc652d990218e940150353dafc314f7f79085 Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Wed, 19 Mar 2014 17:35:14 -0300 Subject: [PATCH 4/9] refactor valid b58 tests --- test/test.misc.js | 67 +++++++++++++++++++++++++++++++---------------- 1 file changed, 44 insertions(+), 23 deletions(-) diff --git a/test/test.misc.js b/test/test.misc.js index 822b83679..b854abac1 100644 --- a/test/test.misc.js +++ b/test/test.misc.js @@ -42,8 +42,8 @@ describe('Miscelaneous stuff', function() { }); it('should perform basic math operations for bignum', function() { var b = bignum('782910138827292261791972728324982') - .sub('182373273283402171237474774728373') - .div(13); + .sub('182373273283402171237474774728373') + .div(13); b.toNumber().should.equal(46195143503376160811884457968969); }); @@ -71,27 +71,48 @@ describe('Miscelaneous stuff', function() { var b58 = datum[0]; var hexPayload = datum[1]; var meta = datum[2]; - it('base58 keys valid ' + b58, function() { - var network = meta.isTestnet?networks.testnet:networks.livenet; - if (meta.isPrivkey) { - var k = new WalletKey({network: network}); - k.fromObj({priv: b58}); - k.privKey.compressed.should.equal(meta.isCompressed); - buffertools.toHex(k.privKey.private).should.equal(hexPayload); - new Address(b58).isValid().should.equal(false); - } else { - var a = new Address(b58); - a.isValid().should.equal(true); - a.isScript().should.equal(meta.addrType === 'script'); - a.network().should.equal(network); - } - }); + var network = meta.isTestnet ? networks.testnet : networks.livenet; + if (meta.isPrivkey) { + describe('base58 private key valid ' + b58, function() { + var k; + before(function() { + k = new WalletKey({ + network: network + }); + }); + it('parse', function() { + k.fromObj({ + priv: b58 + }); + should.exist(k.privKey); + }); + it('should have compressed state', function() { + k.privKey.compressed.should.equal(meta.isCompressed); + }); + it('private key should have correct payload', function() { + buffertools.toHex(k.privKey.private).should.equal(hexPayload); + }); + it('should not be an Address', function() { + new Address(b58).isValid().should.equal(false); + }); + }); + } else { + describe('base58 address valid ' + b58, function() { + var a; + before(function() { + a = new Address(b58); + }); + it('should be valid', function() { + a.isValid().should.equal(true); + }); + it('should be of correct type', function() { + a.isScript().should.equal(meta.addrType === 'script'); + }); + it('should get correct network', function() { + a.network().should.equal(network); + }); + }); + } }); }); - - - - - - From 53eb98babc8141e278d8632b40ac455f6041882e Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Wed, 19 Mar 2014 17:52:34 -0300 Subject: [PATCH 5/9] should generate from hex added --- WalletKey.js | 11 +++++------ test/test.misc.js | 17 +++++++++++++---- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/WalletKey.js b/WalletKey.js index 0c2abb517..2c9c6e31c 100644 --- a/WalletKey.js +++ b/WalletKey.js @@ -2,7 +2,7 @@ var imports = require('soop').imports(); var coinUtil = require('./util/util'); var timeUtil = require('./util/time'); -var Key= require('./Key'); +var Key = require('./Key'); var PrivateKey = require('./PrivateKey'); var Address = require('./Address'); @@ -37,11 +37,10 @@ WalletKey.prototype.storeObj = function() { WalletKey.prototype.fromObj = function(obj) { this.created = obj.created; this.privKey = new Key(); - if (obj.priv.length==64) { - this.privKey.private = new Buffer(obj.priv,'hex'); - this.privKey.compressed = true; - } - else { + if (obj.priv.length == 64) { + this.privKey.private = new Buffer(obj.priv, 'hex'); + this.privKey.compressed = typeof obj.compressed === 'undefined'? true: obj.compressed; + } else { var priv = new PrivateKey(obj.priv); this.privKey.private = new Buffer(priv.payload()); this.privKey.compressed = priv.compressed(); diff --git a/test/test.misc.js b/test/test.misc.js index b854abac1..22bfc40fc 100644 --- a/test/test.misc.js +++ b/test/test.misc.js @@ -75,12 +75,13 @@ describe('Miscelaneous stuff', function() { if (meta.isPrivkey) { describe('base58 private key valid ' + b58, function() { var k; + var opts = { + network: network + }; before(function() { - k = new WalletKey({ - network: network - }); + k = new WalletKey(opts); }); - it('parse', function() { + it('should generate correctly from WIF', function() { k.fromObj({ priv: b58 }); @@ -95,6 +96,14 @@ describe('Miscelaneous stuff', function() { it('should not be an Address', function() { new Address(b58).isValid().should.equal(false); }); + it('should generate correctly from hex', function() { + var k2 = new WalletKey(opts); + k2.fromObj({ + priv: hexPayload, + compressed: meta.isCompressed + }); + k2.storeObj().priv.should.equal(b58); + }); }); } else { describe('base58 address valid ' + b58, function() { From f2be0f386c04167ae536be8d0a8d91cca533a89e Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Wed, 19 Mar 2014 17:57:28 -0300 Subject: [PATCH 6/9] add hex generation of addresses test --- test/test.misc.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/test/test.misc.js b/test/test.misc.js index 22bfc40fc..e58bfccd2 100644 --- a/test/test.misc.js +++ b/test/test.misc.js @@ -108,6 +108,7 @@ describe('Miscelaneous stuff', function() { } else { describe('base58 address valid ' + b58, function() { var a; + var shouldBeScript = meta.addrType === 'script'; before(function() { a = new Address(b58); }); @@ -115,11 +116,16 @@ describe('Miscelaneous stuff', function() { a.isValid().should.equal(true); }); it('should be of correct type', function() { - a.isScript().should.equal(meta.addrType === 'script'); + a.isScript().should.equal(shouldBeScript); }); it('should get correct network', function() { a.network().should.equal(network); }); + it('should generate correctly from hex', function() { + var version = shouldBeScript? network.addressScript: network.addressPubkey; + var b = new Address(version, new Buffer(hexPayload, 'hex')); + b.toString().should.equal(b58); + }); }); } }); From 2323e2a67a11c4f5c562dbac63f3f2037602bb19 Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Wed, 19 Mar 2014 18:10:04 -0300 Subject: [PATCH 7/9] fix skipped Opcode test --- test/test.Opcode.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/test/test.Opcode.js b/test/test.Opcode.js index 4c9a5e947..235f26cb9 100644 --- a/test/test.Opcode.js +++ b/test/test.Opcode.js @@ -20,12 +20,10 @@ describe('Opcode', function() { var oc = new Opcode(); should.exist(oc); }); - it.skip('should be able to create some constants', function() { + it('should be able to create some constants', function() { // TODO: test works in node but not in browser for (var i in Opcode.map) { - console.log('var '+i + ' = ' + Opcode.map[i] + ';'); eval('var '+i + ' = ' + Opcode.map[i] + ';'); - console.log(eval(i)); } should.exist(OP_VER); should.exist(OP_HASH160); From 3cd4e31c3176079d13bead2ae0fa962482c4a6e1 Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Wed, 19 Mar 2014 18:44:24 -0300 Subject: [PATCH 8/9] fix Address validation issue --- Address.js | 1 + test/test.Address.js | 3 +++ test/test.misc.js | 10 +++++++++- 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/Address.js b/Address.js index 679dbb3d1..89b8211b6 100644 --- a/Address.js +++ b/Address.js @@ -16,6 +16,7 @@ Address.prototype.validate = function() { Address.super(this, 'validate', arguments); if(this.data.length !== 21) throw new Error('invalid data length'); }); + if (typeof this.network() === 'undefined') throw new Error('invalid network'); }; Address.prototype.isValid = function() { diff --git a/test/test.Address.js b/test/test.Address.js index e1d73d87f..19825534a 100644 --- a/test/test.Address.js +++ b/test/test.Address.js @@ -35,6 +35,9 @@ describe('Address', function() { ['1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62iz', false], // too long Bitcoin address ['1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62izz', false],// too long Bitcoin address ['2cFupjhnEsSn59qHXstmK2ffpLv2', false], // valid base58 invalid data + ['dB7cwYdcPSgiyAwKWL3JwCVwSk6epU2txw', false], // valid base58, valid length, invalid network + ['2MnmgiRH4eGLyLc9eAqStzk7dFgBjFtUCtu', false], // valid base58, valid length, invalid network + ['32QBdjycLwbDTuGafUwaU5p5GxzSLPYoF6', true], // valid base58, valid length, valid network ]; data.forEach(function(datum) { var address = datum[0]; diff --git a/test/test.misc.js b/test/test.misc.js index e58bfccd2..0a4b36830 100644 --- a/test/test.misc.js +++ b/test/test.misc.js @@ -122,12 +122,20 @@ describe('Miscelaneous stuff', function() { a.network().should.equal(network); }); it('should generate correctly from hex', function() { - var version = shouldBeScript? network.addressScript: network.addressPubkey; + var version = shouldBeScript ? network.addressScript : network.addressPubkey; var b = new Address(version, new Buffer(hexPayload, 'hex')); b.toString().should.equal(b58); }); }); } }); + testdata.dataBase58KeysInvalid.forEach(function(datum) { + var b58 = datum[0]; + it('shouldnt be able to create Address nor WalletKey with ' + b58, function() { + var a = new Address(b58); + var invalidAddress = (!a.isValid()); + invalidAddress.should.equal(true); + }); + }); }); From 150a9434473160139654c75fa1d2ca5f61aa223d Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Wed, 19 Mar 2014 19:00:45 -0300 Subject: [PATCH 9/9] fix private key validation and base58 invalid tests --- PrivateKey.js | 1 + WalletKey.js | 1 + test/test.misc.js | 22 +++++++++++++++++++++- 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/PrivateKey.js b/PrivateKey.js index 9e2eac612..32adb6729 100644 --- a/PrivateKey.js +++ b/PrivateKey.js @@ -19,6 +19,7 @@ PrivateKey.prototype.validate = function() { if (this.data.length < 32 || (this.data.length > 1+32 && !this.compressed()) || (this.data.length==1+32+1 && this.data[1+32+1-1]!=1) || this.data.length>1+32+1) throw new Error('invalid data length'); }); + if (typeof this.network() === 'undefined') throw new Error('invalid network'); }; // get or set the payload data (as a Buffer object) diff --git a/WalletKey.js b/WalletKey.js index 2c9c6e31c..3ff6214eb 100644 --- a/WalletKey.js +++ b/WalletKey.js @@ -42,6 +42,7 @@ WalletKey.prototype.fromObj = function(obj) { this.privKey.compressed = typeof obj.compressed === 'undefined'? true: obj.compressed; } else { var priv = new PrivateKey(obj.priv); + priv.validate(); this.privKey.private = new Buffer(priv.payload()); this.privKey.compressed = priv.compressed(); } diff --git a/test/test.misc.js b/test/test.misc.js index 0a4b36830..1172b03e3 100644 --- a/test/test.misc.js +++ b/test/test.misc.js @@ -131,11 +131,31 @@ describe('Miscelaneous stuff', function() { }); testdata.dataBase58KeysInvalid.forEach(function(datum) { var b58 = datum[0]; - it('shouldnt be able to create Address nor WalletKey with ' + b58, function() { + it('shouldnt be able to create Address with ' + b58, function() { var a = new Address(b58); var invalidAddress = (!a.isValid()); invalidAddress.should.equal(true); }); + it('shouldnt be able to create WalletKey with ' + b58, function() { + var kl = new WalletKey({ + network: networks.livenet + }); + var kt = new WalletKey({ + network: networks.livenet + }); + var createLivenet = function() { + kl.fromObj({ + priv: b58 + }); + }; + var createTestnet = function() { + kt.fromObj({ + priv: b58 + }); + }; + createLivenet.should.throw(); + createTestnet.should.throw(); + }); }); });