From cc0a042f2f947667a8e3b57fbecde7df5135d11b Mon Sep 17 00:00:00 2001 From: Wei Lu Date: Fri, 28 Feb 2014 12:05:48 +0800 Subject: [PATCH 1/7] squashed commits from #27 --- src/hdwallet.js | 10 ++++++---- test/wallet.js | 17 +++++++++++++++++ 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/hdwallet.js b/src/hdwallet.js index 00a02c0..f40582f 100644 --- a/src/hdwallet.js +++ b/src/hdwallet.js @@ -13,7 +13,8 @@ var HDWallet = module.exports = function(seed, network) { var I = Crypto.HMAC(Crypto.SHA512, seed, 'Bitcoin seed', { asBytes: true }) this.chaincode = I.slice(32) - this.priv = new ECKey(I.slice(0, 32).concat([1]), true) + this.keyVersion = network == 'Bitcoin' ? Address.address_types.prod : Address.address_types.testnet + this.priv = new ECKey(I.slice(0, 32).concat([1]), true, this.keyVersion) this.pub = this.priv.getPub() this.network = network || 'Bitcoin' this.index = 0 @@ -106,10 +107,10 @@ HDWallet.fromBytes = function(input) { // 33 bytes: the public key or private key data (0x02 + X or 0x03 + X for // public keys, 0x00 + k for private keys) if (type == 'private') { - hd.priv = new ECKey(input.slice(46, 78).concat([1]), true) + hd.priv = new ECKey(input.slice(46, 78).concat([1]), true, this.keyVersion) hd.pub = hd.priv.getPub() } else { - hd.pub = new ECPubKey(input.slice(45, 78), true) + hd.pub = new ECPubKey(input.slice(45, 78), true, this.keyVersion) } return hd @@ -213,10 +214,11 @@ HDWallet.prototype.derive = function(i) { // ki = IL + kpar (mod n). hd.priv = this.priv.add(new ECKey(IL.concat([1]))) hd.priv.compressed = true + hd.priv.version = this.keyVersion hd.pub = hd.priv.getPub() } else { // Ki = (IL + kpar)*G = IL*G + Kpar - hd.pub = this.pub.add(new ECKey(IL.concat([1])).getPub()) + hd.pub = this.pub.add(new ECKey(IL.concat([1]), true, this.keyVersion).getPub()) } // ci = IR. diff --git a/test/wallet.js b/test/wallet.js index 0f39d02..44f6164 100644 --- a/test/wallet.js +++ b/test/wallet.js @@ -1,4 +1,5 @@ var Wallet = require('../src/wallet.js') +var Address = require('../src/address.js') var assert = require('assert') describe('Wallet', function() { @@ -33,4 +34,20 @@ describe('Wallet', function() { assert.equal(wallet.derivationMethod, 'public') }) }) + + describe('networkType', function() { + it('ensures that a mainnet Wallet has mainnet child keys (pub and priv)', function() { + var w = Wallet("foobar", {network: "Bitcoin"}) + assert(w.getMasterKey().priv.version == Address.address_types['prod']) + w.generateAddress() + assert(w.getPrivateKey(0).priv.version == Address.address_types['prod']) + }) + + it('ensures that a testnet Wallet has testnet child keys (pub and priv)', function() { + var w = Wallet("foobar", {network: "BitcoinTest"}) + assert(w.getMasterKey().priv.version == Address.address_types['testnet']) + w.generateAddress() + assert(w.getPrivateKey(0).priv.version == Address.address_types['testnet']) + }) + }) }) From c3528680808f3ae703c37f40a759e2ef75eed882 Mon Sep 17 00:00:00 2001 From: Wei Lu Date: Fri, 28 Feb 2014 14:08:34 +0800 Subject: [PATCH 2/7] key version check always always relies on the network property [#27] --- src/hdwallet.js | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/hdwallet.js b/src/hdwallet.js index f40582f..68836dd 100644 --- a/src/hdwallet.js +++ b/src/hdwallet.js @@ -13,10 +13,9 @@ var HDWallet = module.exports = function(seed, network) { var I = Crypto.HMAC(Crypto.SHA512, seed, 'Bitcoin seed', { asBytes: true }) this.chaincode = I.slice(32) - this.keyVersion = network == 'Bitcoin' ? Address.address_types.prod : Address.address_types.testnet - this.priv = new ECKey(I.slice(0, 32).concat([1]), true, this.keyVersion) - this.pub = this.priv.getPub() this.network = network || 'Bitcoin' + this.priv = new ECKey(I.slice(0, 32).concat([1]), true, this.getKeyVersion()) + this.pub = this.priv.getPub() this.index = 0 this.depth = 0 } @@ -107,10 +106,10 @@ HDWallet.fromBytes = function(input) { // 33 bytes: the public key or private key data (0x02 + X or 0x03 + X for // public keys, 0x00 + k for private keys) if (type == 'private') { - hd.priv = new ECKey(input.slice(46, 78).concat([1]), true, this.keyVersion) + hd.priv = new ECKey(input.slice(46, 78).concat([1]), true, hd.getKeyVersion()) hd.pub = hd.priv.getPub() } else { - hd.pub = new ECPubKey(input.slice(45, 78), true, this.keyVersion) + hd.pub = new ECPubKey(input.slice(45, 78), true, hd.getKeyVersion()) } return hd @@ -214,11 +213,11 @@ HDWallet.prototype.derive = function(i) { // ki = IL + kpar (mod n). hd.priv = this.priv.add(new ECKey(IL.concat([1]))) hd.priv.compressed = true - hd.priv.version = this.keyVersion + hd.priv.version = this.getKeyVersion() hd.pub = hd.priv.getPub() } else { // Ki = (IL + kpar)*G = IL*G + Kpar - hd.pub = this.pub.add(new ECKey(IL.concat([1]), true, this.keyVersion).getPub()) + hd.pub = this.pub.add(new ECKey(IL.concat([1]), true, this.getKeyVersion()).getPub()) } // ci = IR. @@ -234,4 +233,8 @@ HDWallet.prototype.derivePrivate = function(index) { return this.derive(index + HDWallet.HIGHEST_BIT) } +HDWallet.prototype.getKeyVersion = function() { + return this.network == 'Bitcoin' ? Address.address_types.prod : Address.address_types.testnet +} + HDWallet.prototype.toString = HDWallet.prototype.toBase58 From 293c864f4f0ffca7c8409925820ca8e890fda98e Mon Sep 17 00:00:00 2001 From: Wei Lu Date: Fri, 28 Feb 2014 14:27:31 +0800 Subject: [PATCH 3/7] HD wallet versions: Bitcoin -> prod, BitcoinTest -> testnet --- src/hdwallet.js | 11 +++++------ src/wallet.js | 2 +- test/wallet.js | 12 ++++++------ 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/hdwallet.js b/src/hdwallet.js index 68836dd..2d286f9 100644 --- a/src/hdwallet.js +++ b/src/hdwallet.js @@ -13,7 +13,7 @@ var HDWallet = module.exports = function(seed, network) { var I = Crypto.HMAC(Crypto.SHA512, seed, 'Bitcoin seed', { asBytes: true }) this.chaincode = I.slice(32) - this.network = network || 'Bitcoin' + this.network = network || 'prod' this.priv = new ECKey(I.slice(0, 32).concat([1]), true, this.getKeyVersion()) this.pub = this.priv.getPub() this.index = 0 @@ -24,8 +24,8 @@ HDWallet.HIGHEST_BIT = 0x80000000 HDWallet.LENGTH = 78 HDWallet.VERSIONS = { - Bitcoin: [0x0488B21E, 0x0488ADE4], - BitcoinTest: [0x043587CF, 0x04358394] + prod: [0x0488B21E, 0x0488ADE4], + testnet: [0x043587CF, 0x04358394] } function arrayEqual(a, b) { @@ -124,8 +124,7 @@ HDWallet.prototype.getFingerprint = function() { } HDWallet.prototype.getBitcoinAddress = function() { - var test = this.network.match(/Test$/) - return new Address(util.sha256ripe160(this.pub.toBytes()), test ? 111 : 0) + return new Address(util.sha256ripe160(this.pub.toBytes()), this.getKeyVersion()) } HDWallet.prototype.toBytes = function(priv) { @@ -234,7 +233,7 @@ HDWallet.prototype.derivePrivate = function(index) { } HDWallet.prototype.getKeyVersion = function() { - return this.network == 'Bitcoin' ? Address.address_types.prod : Address.address_types.testnet + return this.network == 'prod' ? Address.address_types.prod : Address.address_types.testnet } HDWallet.prototype.toString = HDWallet.prototype.toBase58 diff --git a/src/wallet.js b/src/wallet.js index 95f2e91..ead9af6 100644 --- a/src/wallet.js +++ b/src/wallet.js @@ -18,7 +18,7 @@ var Wallet = function (seed, options) { if (!(this instanceof Wallet)) { return new Wallet(seed, options); } var options = options || {} - var network = options.network || 'Bitcoin' + var network = options.network || 'prod' // HD first-level child derivation method (i.e. public or private child key derivation) // NB: if not specified, defaults to private child derivation diff --git a/test/wallet.js b/test/wallet.js index 44f6164..45ef084 100644 --- a/test/wallet.js +++ b/test/wallet.js @@ -11,8 +11,8 @@ describe('Wallet', function() { wallet = new Wallet(seed) }) - it('defaults to Bitcoin network', function() { - assert.equal(wallet.getMasterKey().network, 'Bitcoin') + it('defaults to Bitcoin mainnet', function() { + assert.equal(wallet.getMasterKey().network, 'prod') }) it('defaults to private derivationMethod', function() { @@ -23,11 +23,11 @@ describe('Wallet', function() { describe('constructor options', function() { var wallet; beforeEach(function() { - wallet = new Wallet(seed, {network: 'Test', derivationMethod: 'public'}) + wallet = new Wallet(seed, {network: 'testnet', derivationMethod: 'public'}) }) it('uses the network if specified', function() { - assert.equal(wallet.getMasterKey().network, 'Test') + assert.equal(wallet.getMasterKey().network, 'testnet') }) it('uses the derivationMethod if specified', function() { @@ -37,14 +37,14 @@ describe('Wallet', function() { describe('networkType', function() { it('ensures that a mainnet Wallet has mainnet child keys (pub and priv)', function() { - var w = Wallet("foobar", {network: "Bitcoin"}) + var w = Wallet("foobar", {network: "prod"}) assert(w.getMasterKey().priv.version == Address.address_types['prod']) w.generateAddress() assert(w.getPrivateKey(0).priv.version == Address.address_types['prod']) }) it('ensures that a testnet Wallet has testnet child keys (pub and priv)', function() { - var w = Wallet("foobar", {network: "BitcoinTest"}) + var w = Wallet("foobar", {network: "testnet"}) assert(w.getMasterKey().priv.version == Address.address_types['testnet']) w.generateAddress() assert(w.getPrivateKey(0).priv.version == Address.address_types['testnet']) From eaf84c42839a8c07700a276ef5de03451142ab18 Mon Sep 17 00:00:00 2001 From: Wei Lu Date: Fri, 28 Feb 2014 16:05:43 +0800 Subject: [PATCH 4/7] move address versions into network Also change address type name: address_types -> addressVersion p2sh_types -> p2shVersion prod -> mainnet --- src/address.js | 17 ++++------------- src/eckey.js | 27 +++++++++++++++------------ src/hdwallet.js | 21 ++++++++++++--------- src/network.js | 10 ++++++++++ test/eckey.js | 23 +++++++++++++---------- test/wallet.js | 12 +++++++----- 6 files changed, 61 insertions(+), 49 deletions(-) create mode 100644 src/network.js diff --git a/src/address.js b/src/address.js index 680a561..c99e4bd 100644 --- a/src/address.js +++ b/src/address.js @@ -2,6 +2,7 @@ var base58 = require('./base58'); var Crypto = require('./crypto-js/crypto'); var conv = require('./convert'); var util = require('./util'); +var mainnet = require('./network').mainnet.addressVersion; var Address = function (bytes, version) { if (!(this instanceof Address)) { return new Address(bytes, version); } @@ -15,11 +16,11 @@ var Address = function (bytes, version) { : bytes.length <= 40 ? conv.hexToBytes(bytes) : util.error('Bad input'); - this.version = version || this.hash.version || Address.address_types.prod; + this.version = version || this.hash.version || mainnet; } else { this.hash = bytes; - this.version = version || bytes.version || Address.address_types.prod; + this.version = version || bytes.version || mainnet; } }; @@ -29,7 +30,7 @@ var Address = function (bytes, version) { * Returns the address as a base58-encoded string in the standardized format. */ Address.prototype.toString = function () { - return base58.checkEncode(this.hash.slice(0),this.version); + return base58.checkEncode(this.hash.slice(0), this.version); }; Address.prototype.getHash = function () { @@ -56,14 +57,4 @@ Address.decodeString = function (string) { return base58.checkDecode(string); }; -Address.address_types = { - prod: 0, - testnet: 111 -}; - -Address.p2sh_types = { - prod: 5, - testnet: 196 -}; - module.exports = Address; diff --git a/src/eckey.js b/src/eckey.js index 68aecd1..ddec4f0 100644 --- a/src/eckey.js +++ b/src/eckey.js @@ -7,6 +7,9 @@ var conv = require('./convert'); var Address = require('./address'); var ecdsa = require('./ecdsa'); var ECPointFp = require('./jsbn/ec').ECPointFp; +var Network = require('./network') +var mainnet = Network.mainnet.addressVersion +var testnet = Network.testnet.addressVersion var ecparams = sec("secp256k1"); @@ -18,7 +21,7 @@ var ECKey = function (input,compressed,version) { var n = ecparams.getN(); this.priv = ecdsa.getBigRandom(n); this.compressed = compressed || false; - this.version = version || Address.address_types.prod; + this.version = version || mainnet; } else this.import(input,compressed,version) }; @@ -57,16 +60,16 @@ ECKey.prototype.import = function (input,compressed,version) { this.version = version !== undefined ? version : input instanceof ECKey ? input.version - : input instanceof BigInteger ? Address.address_types.prod - : util.isArray(input) ? Address.address_types.prod + : input instanceof BigInteger ? mainnet + : util.isArray(input) ? mainnet : typeof input != "string" ? null - : input.length == 44 ? Address.address_types.prod - : input.length == 51 && input[0] == '5' ? Address.address_types.prod - : input.length == 51 && input[0] == '9' ? Address.address_types.testnet - : input.length == 52 && has('LK',input[0]) ? Address.address_types.prod - : input.length == 52 && input[0] == 'c' ? Address.address_types.testnet - : input.length == 64 ? Address.address_types.prod - : input.length == 65 ? Address.address_types.prod + : input.length == 44 ? mainnet + : input.length == 51 && input[0] == '5' ? mainnet + : input.length == 51 && input[0] == '9' ? testnet + : input.length == 52 && has('LK',input[0]) ? mainnet + : input.length == 52 && input[0] == 'c' ? testnet + : input.length == 64 ? mainnet + : input.length == 65 ? mainnet : null }; @@ -133,7 +136,7 @@ var ECPubKey = function(input,compressed,version) { var n = ecparams.getN(); this.pub = ecparams.getG().multiply(ecdsa.getBigRandom(n)) this.compressed = compressed || false; - this.version = version || Address.address_types.prod; + this.version = version || mainnet; } else this.import(input,compressed,version) } @@ -158,7 +161,7 @@ ECPubKey.prototype.import = function(input,compressed,version) { version ? version : input instanceof ECPointFp ? input.version : input instanceof ECPubKey ? input.version - : Address.address_types.prod + : mainnet } ECPubKey.prototype.add = function(key) { diff --git a/src/hdwallet.js b/src/hdwallet.js index 2d286f9..a65c2bd 100644 --- a/src/hdwallet.js +++ b/src/hdwallet.js @@ -1,12 +1,15 @@ var convert = require('./convert.js') -, base58 = require('./base58.js') -, assert = require('assert') -, format = require('util').format -, util = require('./util.js') -, Crypto = require('./crypto-js/crypto.js') -, ECKey = require('./eckey.js').ECKey -, ECPubKey = require('./eckey.js').ECPubKey -, Address = require('./address.js') +var base58 = require('./base58.js') +var assert = require('assert') +var format = require('util').format +var util = require('./util.js') +var Crypto = require('./crypto-js/crypto.js') +var ECKey = require('./eckey.js').ECKey +var ECPubKey = require('./eckey.js').ECPubKey +var Address = require('./address.js') +var Network = require('./network') +var mainnet = Network.mainnet.addressVersion +var testnet = Network.testnet.addressVersion var HDWallet = module.exports = function(seed, network) { if (seed === undefined) return @@ -233,7 +236,7 @@ HDWallet.prototype.derivePrivate = function(index) { } HDWallet.prototype.getKeyVersion = function() { - return this.network == 'prod' ? Address.address_types.prod : Address.address_types.testnet + return this.network == 'prod' ? mainnet : testnet } HDWallet.prototype.toString = HDWallet.prototype.toBase58 diff --git a/src/network.js b/src/network.js new file mode 100644 index 0000000..e02fd01 --- /dev/null +++ b/src/network.js @@ -0,0 +1,10 @@ +module.exports = { + mainnet: { + addressVersion: 0, + p2shVersion: 5 + }, + testnet: { + addressVersion: 111, + p2shVersion: 196 + } +}; diff --git a/test/eckey.js b/test/eckey.js index edd86c6..c0caa41 100644 --- a/test/eckey.js +++ b/test/eckey.js @@ -5,6 +5,9 @@ var convert = require('../src/convert.js'); var bytesToHex = convert.bytesToHex; var hexToBytes = convert.hexToBytes; var Address = require('../src/address'); +var Network = require('../src/network') +var mainnet = Network.mainnet.addressVersion +var testnet = Network.testnet.addressVersion describe('ECKey', function() { describe('constructor (base58 private) on mainnet', function() { @@ -16,7 +19,7 @@ describe('ECKey', function() { assert.equal(key.getPub().toHex(), pub); assert.equal(key.compressed, false); - assert.equal(key.version, Address.address_types.prod); + assert.equal(key.version, mainnet); }) it('parses base64', function() { @@ -27,7 +30,7 @@ describe('ECKey', function() { assert.equal(key.getPub().toHex(), pub); assert.equal(key.compressed, false); - assert.equal(key.version, Address.address_types.prod); + assert.equal(key.version, mainnet); }) it('parses WIF', function() { @@ -40,7 +43,7 @@ describe('ECKey', function() { assert.equal(key.compressed, false); assert.equal(key.getPub().toHex(), pub); assert.equal(key.getBitcoinAddress().toString(), addr); - assert.equal(key.version, Address.address_types.prod); + assert.equal(key.version, mainnet); }) it('parses compressed WIF', function() { @@ -52,7 +55,7 @@ describe('ECKey', function() { assert.equal(key.compressed, true); assert.equal(key.getPub().toHex(), pub); assert.equal(key.getBitcoinAddress().toString(), addr); - assert.equal(key.version, Address.address_types.prod); + assert.equal(key.version, mainnet); }) }) @@ -61,11 +64,11 @@ describe('ECKey', function() { var priv = 'ca48ec9783cf3ad0dfeff1fc254395a2e403cbbc666477b61b45e31d3b8ab458'; var pub = '044b12d9d7c77db68388b6ff7c89046174c871546436806bcd80d07c28ea81199' + '283fbec990dad6fb98f93f712d50cb874dd717de6a184158d63886dda3090f566'; - var key = new ECKey(priv, false, Address.address_types.testnet); + var key = new ECKey(priv, false, testnet); assert.equal(key.getPub().toHex(), pub); assert.equal(key.compressed, false); - assert.equal(key.version, Address.address_types.testnet); + assert.equal(key.version, testnet); assert.equal(key.toHex(), priv); }) @@ -73,11 +76,11 @@ describe('ECKey', function() { var priv = 'VYdB+iv47y5FaUVIPdQInkgATrABeuD1lACUoM4x7tU='; var pub = '042f43c16c08849fed20a35bb7b1947bbf0923c52d613ee13b5c665a1e10d24b2' + '8be909a70f5f87c1adb79fbcd1b3f17d20aa91c04fc355112dba2ce9b1cbf013b'; - var key = new ECKey(priv, false, Address.address_types.testnet); + var key = new ECKey(priv, false, testnet); assert.equal(key.getPub().toHex(), pub); assert.equal(key.compressed, false); - assert.equal(key.version, Address.address_types.testnet); + assert.equal(key.version, testnet); assert.equal(key.toBase64(), priv); }) @@ -91,7 +94,7 @@ describe('ECKey', function() { assert.equal(key.compressed, false); assert.equal(key.getPub().toHex(), pub); assert.equal(key.getBitcoinAddress().toString(), addr); - assert.equal(key.version, Address.address_types.testnet); + assert.equal(key.version, testnet); assert.equal(key.toBase58(), priv); }) @@ -104,7 +107,7 @@ describe('ECKey', function() { assert.equal(key.compressed, true); assert.equal(key.getPub().toHex(), pub); assert.equal(key.getBitcoinAddress().toString(), addr); - assert.equal(key.version, Address.address_types.testnet); + assert.equal(key.version, testnet); assert.equal(key.toBase58(), priv); }) }) diff --git a/test/wallet.js b/test/wallet.js index 45ef084..5617c41 100644 --- a/test/wallet.js +++ b/test/wallet.js @@ -1,5 +1,7 @@ var Wallet = require('../src/wallet.js') -var Address = require('../src/address.js') +var Network = require('../src/network') +var mainnet = Network.mainnet.addressVersion +var testnet = Network.testnet.addressVersion var assert = require('assert') describe('Wallet', function() { @@ -38,16 +40,16 @@ describe('Wallet', function() { describe('networkType', function() { it('ensures that a mainnet Wallet has mainnet child keys (pub and priv)', function() { var w = Wallet("foobar", {network: "prod"}) - assert(w.getMasterKey().priv.version == Address.address_types['prod']) + assert(w.getMasterKey().priv.version == mainnet) w.generateAddress() - assert(w.getPrivateKey(0).priv.version == Address.address_types['prod']) + assert(w.getPrivateKey(0).priv.version == mainnet) }) it('ensures that a testnet Wallet has testnet child keys (pub and priv)', function() { var w = Wallet("foobar", {network: "testnet"}) - assert(w.getMasterKey().priv.version == Address.address_types['testnet']) + assert(w.getMasterKey().priv.version == testnet) w.generateAddress() - assert(w.getPrivateKey(0).priv.version == Address.address_types['testnet']) + assert(w.getPrivateKey(0).priv.version == testnet) }) }) }) From 02b3a2b5640f3765031361c8d1290acfa2a5f6f5 Mon Sep 17 00:00:00 2001 From: Wei Lu Date: Fri, 28 Feb 2014 16:57:44 +0800 Subject: [PATCH 5/7] HDWallet prod -> mainnet --- src/hdwallet.js | 8 +++----- src/wallet.js | 2 +- test/address.js | 6 +++--- test/wallet.js | 4 ++-- 4 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/hdwallet.js b/src/hdwallet.js index a65c2bd..acc7764 100644 --- a/src/hdwallet.js +++ b/src/hdwallet.js @@ -8,15 +8,13 @@ var ECKey = require('./eckey.js').ECKey var ECPubKey = require('./eckey.js').ECPubKey var Address = require('./address.js') var Network = require('./network') -var mainnet = Network.mainnet.addressVersion -var testnet = Network.testnet.addressVersion var HDWallet = module.exports = function(seed, network) { if (seed === undefined) return var I = Crypto.HMAC(Crypto.SHA512, seed, 'Bitcoin seed', { asBytes: true }) this.chaincode = I.slice(32) - this.network = network || 'prod' + this.network = network || 'mainnet' this.priv = new ECKey(I.slice(0, 32).concat([1]), true, this.getKeyVersion()) this.pub = this.priv.getPub() this.index = 0 @@ -27,7 +25,7 @@ HDWallet.HIGHEST_BIT = 0x80000000 HDWallet.LENGTH = 78 HDWallet.VERSIONS = { - prod: [0x0488B21E, 0x0488ADE4], + mainnet: [0x0488B21E, 0x0488ADE4], testnet: [0x043587CF, 0x04358394] } @@ -236,7 +234,7 @@ HDWallet.prototype.derivePrivate = function(index) { } HDWallet.prototype.getKeyVersion = function() { - return this.network == 'prod' ? mainnet : testnet + return Network[this.network].addressVersion } HDWallet.prototype.toString = HDWallet.prototype.toBase58 diff --git a/src/wallet.js b/src/wallet.js index ead9af6..bf6efe2 100644 --- a/src/wallet.js +++ b/src/wallet.js @@ -18,7 +18,7 @@ var Wallet = function (seed, options) { if (!(this instanceof Wallet)) { return new Wallet(seed, options); } var options = options || {} - var network = options.network || 'prod' + var network = options.network || 'mainnet' // HD first-level child derivation method (i.e. public or private child key derivation) // NB: if not specified, defaults to private child derivation diff --git a/test/address.js b/test/address.js index 2a9fb2c..40de751 100644 --- a/test/address.js +++ b/test/address.js @@ -17,7 +17,7 @@ describe('Address', function() { } validate('1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa'); - // validate('1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa', 'prod'); + // validate('1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa', 'mainnet'); validate('mzBc4XEFSdzCDcTxAgf6EZXgsZWpztRhef'); // validate('mzBc4XEFSdzCDcTxAgf6EZXgsZWpztRhef', 'testnet'); @@ -29,7 +29,7 @@ describe('Address', function() { // p2sh addresses validate('3NJZLcZEEYBpxYEUGewU4knsQRn1WM5Fkt'); - // validate('3NJZLcZEEYBpxYEUGewU4knsQRn1WM5Fkt', 'prod'); + // validate('3NJZLcZEEYBpxYEUGewU4knsQRn1WM5Fkt', 'mainnet'); validate('2MxKEf2su6FGAUfCEAHreGFQvEYrfYNHvL7'); // validate('2MxKEf2su6FGAUfCEAHreGFQvEYrfYNHvL7', 'testnet'); }) @@ -43,7 +43,7 @@ describe('Address', function() { invalid('mzBc4XEFSdzCDcTxAgf6EZXgsZWpztRhe'); // invalid('1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa', 'testnet'); - // invalid('mzBc4XEFSdzCDcTxAgf6EZXgsZWpztRhef', 'prod'); + // invalid('mzBc4XEFSdzCDcTxAgf6EZXgsZWpztRhef', 'mainnet'); // invalid base58 string invalid('%%@'); diff --git a/test/wallet.js b/test/wallet.js index 5617c41..44474ac 100644 --- a/test/wallet.js +++ b/test/wallet.js @@ -14,7 +14,7 @@ describe('Wallet', function() { }) it('defaults to Bitcoin mainnet', function() { - assert.equal(wallet.getMasterKey().network, 'prod') + assert.equal(wallet.getMasterKey().network, 'mainnet') }) it('defaults to private derivationMethod', function() { @@ -39,7 +39,7 @@ describe('Wallet', function() { describe('networkType', function() { it('ensures that a mainnet Wallet has mainnet child keys (pub and priv)', function() { - var w = Wallet("foobar", {network: "prod"}) + var w = Wallet("foobar", {network: "mainnet"}) assert(w.getMasterKey().priv.version == mainnet) w.generateAddress() assert(w.getPrivateKey(0).priv.version == mainnet) From 2e9782837913d4b7d6d58a4b623e0795a8f621de Mon Sep 17 00:00:00 2001 From: Wei Lu Date: Fri, 28 Feb 2014 17:26:16 +0800 Subject: [PATCH 6/7] throws exception if specified network is unknown also move network type tests to hdwallet --- src/hdwallet.js | 4 ++++ test/hdwallet.js | 35 +++++++++++++++++++++++++++++++++-- test/wallet.js | 18 ------------------ 3 files changed, 37 insertions(+), 20 deletions(-) diff --git a/src/hdwallet.js b/src/hdwallet.js index acc7764..98cf7b8 100644 --- a/src/hdwallet.js +++ b/src/hdwallet.js @@ -15,6 +15,10 @@ var HDWallet = module.exports = function(seed, network) { var I = Crypto.HMAC(Crypto.SHA512, seed, 'Bitcoin seed', { asBytes: true }) this.chaincode = I.slice(32) this.network = network || 'mainnet' + if(!Network.hasOwnProperty(this.network)) { + throw new Error("Unknown network: " + this.network) + } + this.priv = new ECKey(I.slice(0, 32).concat([1]), true, this.getKeyVersion()) this.pub = this.priv.getPub() this.index = 0 diff --git a/test/hdwallet.js b/test/hdwallet.js index 974c06e..85d2ae4 100644 --- a/test/hdwallet.js +++ b/test/hdwallet.js @@ -1,7 +1,10 @@ /* global describe, it */ var HDWallet = require('../src/hdwallet.js') -, assert = require('assert') -, convert = require('../src/convert.js') +var assert = require('assert') +var convert = require('../src/convert.js') +var Network = require('../src/network') +var mainnet = Network.mainnet.addressVersion +var testnet = Network.testnet.addressVersion var b2h = convert.bytesToHex @@ -214,4 +217,32 @@ describe('HDWallet', function() { assert.equal(hd.toBase58(true), 'xprvA2nrNbFZABcdryreWet9Ea4LvTJcGsqrMzxHx98MMrotbir7yrKCEXw7nadnHM8Dq38EGfSh6dqA9QWTyefMLEcBYJUuekgW4BYPJcr9E7j') }) }) + + describe('network types', function() { + it('ensures that a mainnet Wallet has mainnet child keys (pub and priv)', function() { + var wallet = new HDWallet("foobar", "mainnet") + assert.equal(wallet.priv.version, mainnet) + + var privChild = wallet.derivePrivate(0) + assert.equal(privChild.priv.version, mainnet) + + var pubChild = wallet.derive(0) + assert.equal(pubChild.priv.version, mainnet) + }) + + it('ensures that a testnet Wallet has testnet child keys (pub and priv)', function() { + var wallet = new HDWallet("foobar", "testnet") + assert.equal(wallet.priv.version, testnet) + + var privChild = wallet.derivePrivate(0) + assert.equal(privChild.priv.version, testnet) + + var pubChild = wallet.derive(0) + assert.equal(pubChild.priv.version, testnet) + }) + + it('throws an excption when unknown network type is passed in', function() { + assert.throws(function() { new HDWallet("foobar", "doge") }) + }) + }) }) diff --git a/test/wallet.js b/test/wallet.js index 44474ac..650ad5c 100644 --- a/test/wallet.js +++ b/test/wallet.js @@ -1,7 +1,4 @@ var Wallet = require('../src/wallet.js') -var Network = require('../src/network') -var mainnet = Network.mainnet.addressVersion -var testnet = Network.testnet.addressVersion var assert = require('assert') describe('Wallet', function() { @@ -37,19 +34,4 @@ describe('Wallet', function() { }) }) - describe('networkType', function() { - it('ensures that a mainnet Wallet has mainnet child keys (pub and priv)', function() { - var w = Wallet("foobar", {network: "mainnet"}) - assert(w.getMasterKey().priv.version == mainnet) - w.generateAddress() - assert(w.getPrivateKey(0).priv.version == mainnet) - }) - - it('ensures that a testnet Wallet has testnet child keys (pub and priv)', function() { - var w = Wallet("foobar", {network: "testnet"}) - assert(w.getMasterKey().priv.version == testnet) - w.generateAddress() - assert(w.getPrivateKey(0).priv.version == testnet) - }) - }) }) From 65a13cbf4147b9ba6b94ccc0ea9fdce81b13e7d3 Mon Sep 17 00:00:00 2001 From: Wei Lu Date: Fri, 28 Feb 2014 18:07:31 +0800 Subject: [PATCH 7/7] pull out hdwallet network specific values --- src/hdwallet.js | 29 +++++++++++++---------------- src/network.js | 13 +++++++++++-- 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/src/hdwallet.js b/src/hdwallet.js index 98cf7b8..8a65b1a 100644 --- a/src/hdwallet.js +++ b/src/hdwallet.js @@ -28,11 +28,6 @@ var HDWallet = module.exports = function(seed, network) { HDWallet.HIGHEST_BIT = 0x80000000 HDWallet.LENGTH = 78 -HDWallet.VERSIONS = { - mainnet: [0x0488B21E, 0x0488ADE4], - testnet: [0x043587CF, 0x04358394] -} - function arrayEqual(a, b) { return !(a < b || a > b) } @@ -78,16 +73,17 @@ HDWallet.fromBytes = function(input) { // 4 byte: version bytes (mainnet: 0x0488B21E public, 0x0488ADE4 private; // testnet: 0x043587CF public, 0x04358394 private) var versionBytes = input.slice(0, 4) - , versionWord = util.bytesToWords(versionBytes)[0] - , type - - Object.keys(HDWallet.VERSIONS).forEach(function(name) { - HDWallet.VERSIONS[name].forEach(function(word, i) { - if (versionWord != word) return - type = i ? 'private' : 'public' + var versionWord = util.bytesToWords(versionBytes)[0] + var type + + for(var name in Network) { + var network = Network[name] + for(var t in network.hdVersions) { + if (versionWord != network.hdVersions[t]) continue + type = t hd.network = name - }) - }) + } + } if (!hd.network) { throw new Error(format('Could not find version %s', convert.bytesToHex(versionBytes))) @@ -110,7 +106,7 @@ HDWallet.fromBytes = function(input) { // 33 bytes: the public key or private key data (0x02 + X or 0x03 + X for // public keys, 0x00 + k for private keys) - if (type == 'private') { + if (type == 'priv') { hd.priv = new ECKey(input.slice(46, 78).concat([1]), true, hd.getKeyVersion()) hd.pub = hd.priv.getPub() } else { @@ -138,7 +134,8 @@ HDWallet.prototype.toBytes = function(priv) { // Version // 4 byte: version bytes (mainnet: 0x0488B21E public, 0x0488ADE4 private; testnet: 0x043587CF public, // 0x04358394 private) - var vBytes = util.wordsToBytes([HDWallet.VERSIONS[this.network][priv ? 1 : 0]]) + var version = Network[this.network].hdVersions[priv ? 'priv' : 'pub'] + var vBytes = util.wordsToBytes([version]) buffer = buffer.concat(vBytes) assert.equal(buffer.length, 4) diff --git a/src/network.js b/src/network.js index e02fd01..78e7617 100644 --- a/src/network.js +++ b/src/network.js @@ -1,10 +1,19 @@ module.exports = { mainnet: { addressVersion: 0, - p2shVersion: 5 + p2shVersion: 5, + hdVersions: { + pub: 0x0488B21E, + priv: 0x0488ADE4 + } }, testnet: { addressVersion: 111, - p2shVersion: 196 + p2shVersion: 196, + hdVersions: { + pub: 0x043587CF, + priv: 0x04358394 + } } }; +