From 3298a01498c84a50f1b7bbca260a3fd79c5170ba Mon Sep 17 00:00:00 2001 From: Braydon Fuller Date: Mon, 1 Dec 2014 12:44:32 -0500 Subject: [PATCH] Immutable Address, PublicKey and PrivateKey --- lib/address.js | 24 +++++++++++++++++------- lib/privatekey.js | 17 ++++++++++++++--- lib/publickey.js | 21 ++++++++++++++------- test/privatekey.js | 6 ++---- 4 files changed, 47 insertions(+), 21 deletions(-) diff --git a/lib/address.js b/lib/address.js index e199a295d..64276e030 100644 --- a/lib/address.js +++ b/lib/address.js @@ -22,7 +22,7 @@ var Hash = require('./crypto/hash'); * * // get an address from a public key * var address = Address(publicKey, 'testnet').toString(); - * + * * * @param {String} data - The encoded data in various formats * @param {String} [network] - The network: 'mainnet' or 'testnet' @@ -69,10 +69,20 @@ function Address(data, network, type) { info.network = info.network || network || 'mainnet'; info.type = info.type || type || 'pubkeyhash'; - // set the validated values - this.hashBuffer = info.hashBuffer; - this.network = info.network; - this.type = info.type; + Object.defineProperty(this, 'hashBuffer', { + configurable: false, + value: info.hashBuffer + }); + + Object.defineProperty(this, 'network', { + configurable: false, + value: info.network + }); + + Object.defineProperty(this, 'type', { + configurable: false, + value: info.type + }); return this; @@ -130,7 +140,7 @@ Address._transformBuffer = function(buffer, network, type){ bufNetwork = 'mainnet'; bufType = 'scripthash'; break; - + case networks.testnet.pubkeyhash: bufNetwork = 'testnet'; bufType = 'pubkeyhash'; @@ -141,7 +151,7 @@ Address._transformBuffer = function(buffer, network, type){ bufType = 'scripthash'; break; } - + if (!bufNetwork || (network && network !== bufNetwork)) { throw new TypeError('Address has mismatched network type.'); } diff --git a/lib/privatekey.js b/lib/privatekey.js index eb9a4dbd8..7e549fcd5 100644 --- a/lib/privatekey.js +++ b/lib/privatekey.js @@ -67,9 +67,20 @@ var PrivateKey = function PrivateKey(data, network, compressed) { throw new TypeError('Must specify whether the corresponding public key is compressed or not (true or false)'); } - this.bn = info.bn; - this.compressed = info.compressed; - this.network = info.network; + Object.defineProperty(this, 'bn', { + configurable: false, + value: info.bn + }); + + Object.defineProperty(this, 'compressed', { + configurable: false, + value: info.compressed + }); + + Object.defineProperty(this, 'network', { + configurable: false, + value: info.network + }); return this; diff --git a/lib/publickey.js b/lib/publickey.js index 3bffc6ed1..8245f1490 100644 --- a/lib/publickey.js +++ b/lib/publickey.js @@ -11,10 +11,10 @@ var BN = require('./crypto/bn'); * * // instantiate from a private key * var key = PublicKey(privateKey, true); - * - * // export to as a DER hex encoded string + * + * // export to as a DER hex encoded string * var exported = key.toString(); - * + * * // import the public key * var imported = PublicKey.fromString(exported); * @@ -44,7 +44,7 @@ var PublicKey = function PublicKey(data, compressed) { info = PublicKey._transformDER(new Buffer(data, 'hex' )); } else if (data instanceof Buffer || data instanceof Uint8Array){ info = PublicKey._transformDER(data); - } else if (data.constructor && (data.constructor.name && + } else if (data.constructor && (data.constructor.name && data.constructor.name === 'PrivateKey')) { info = PublicKey._transformPrivateKey(data); } else { @@ -62,8 +62,15 @@ var PublicKey = function PublicKey(data, compressed) { //https://www.iacr.org/archive/pkc2003/25670211/25670211.pdf info.point.validate(); - this.point = info.point; - this.compressed = info.compressed; + Object.defineProperty(this, 'point', { + configurable: false, + value: info.point + }); + + Object.defineProperty(this, 'compressed', { + configurable: false, + value: info.compressed + }); return this; @@ -78,7 +85,7 @@ var PublicKey = function PublicKey(data, compressed) { */ PublicKey._transformPrivateKey = function(privkey) { var info = {}; - if (!privkey.constructor || + if (!privkey.constructor || (privkey.constructor.name && privkey.constructor.name !== 'PrivateKey')) { throw new TypeError('Must be an instance of PrivateKey'); } diff --git a/test/privatekey.js b/test/privatekey.js index 76663d3cf..4bf33d1db 100644 --- a/test/privatekey.js +++ b/test/privatekey.js @@ -251,16 +251,14 @@ describe('PrivateKey', function() { it('should convert this known PrivateKey to known PublicKey and preserve compressed=true', function() { var privhex = '906977a061af29276e40bf377042ffbde414e496ae2260bbf1fa9d085637bfff'; - var privkey = new PrivateKey(BN(new Buffer(privhex, 'hex'))); - privkey.compressed = true; + var privkey = new PrivateKey(BN(new Buffer(privhex, 'hex')), 'livenet', true); var pubkey = privkey.toPublicKey(); pubkey.compressed.should.equal(true); }); it('should convert this known PrivateKey to known PublicKey and preserve compressed=true', function() { var privhex = '906977a061af29276e40bf377042ffbde414e496ae2260bbf1fa9d085637bfff'; - var privkey = new PrivateKey(BN(new Buffer(privhex, 'hex'))); - privkey.compressed = false; + var privkey = new PrivateKey(BN(new Buffer(privhex, 'hex')), 'livenet', false); var pubkey = privkey.toPublicKey(); pubkey.compressed.should.equal(false); });