From 28a1eae0be4b8045655abf63e14a6703fb15e682 Mon Sep 17 00:00:00 2001 From: Esteban Ordano Date: Tue, 27 Jan 2015 11:59:20 -0300 Subject: [PATCH 1/4] HDKeys: add toBuffer/fromBuffer to HDPrivateKey --- lib/hdprivatekey.js | 8 ++++++++ test/hdprivatekey.js | 11 +++++++++++ 2 files changed, 19 insertions(+) diff --git a/lib/hdprivatekey.js b/lib/hdprivatekey.js index 8e4041127..27b9e8f96 100644 --- a/lib/hdprivatekey.js +++ b/lib/hdprivatekey.js @@ -484,6 +484,14 @@ HDPrivateKey.prototype.toJSON = function toJSON() { return JSON.stringify(this.toObject()); }; +HDPrivateKey.fromBuffer = function(arg) { + return new HDPrivateKey(arg); +}; + +HDPrivateKey.prototype.toBuffer = function() { + return this._buffers.xprivkey; +}; + HDPrivateKey.DefaultDepth = 0; HDPrivateKey.DefaultFingerprint = 0; HDPrivateKey.DefaultChildIndex = 0; diff --git a/test/hdprivatekey.js b/test/hdprivatekey.js index e6c57e800..140351b89 100644 --- a/test/hdprivatekey.js +++ b/test/hdprivatekey.js @@ -262,6 +262,17 @@ describe('HDPrivate key interface', function() { }); }); + describe.only('conversion to/from buffer', function() { + var str = 'xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi'; + it('should roundtrip to/from a buffer', function() { + var priv = new HDPrivateKey(str); + var toBuffer = priv.toBuffer(); + var fromBuffer = HDPrivateKey.fromBuffer(toBuffer); + var roundTrip = new HDPrivateKey(fromBuffer.toBuffer()); + roundTrip.xprivkey.should.equal(str); + }); + }); + describe('conversion to plain object/json', function() { var plainObject = { 'network':'livenet', From 0ff4c9a922e796d65fdc62ad5767092ef27411fd Mon Sep 17 00:00:00 2001 From: Esteban Ordano Date: Tue, 27 Jan 2015 13:00:58 -0300 Subject: [PATCH 2/4] HDKeys: Add jsdocs to hdprivatekey --- lib/hdprivatekey.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/lib/hdprivatekey.js b/lib/hdprivatekey.js index 27b9e8f96..7a2ca008e 100644 --- a/lib/hdprivatekey.js +++ b/lib/hdprivatekey.js @@ -480,14 +480,30 @@ HDPrivateKey.prototype.toObject = function toObject() { }; }; +/** + * Returns a JSON representation of the HDPrivateKey + * + * @return {string} + */ HDPrivateKey.prototype.toJSON = function toJSON() { return JSON.stringify(this.toObject()); }; +/** + * Build a HDPrivateKey from a buffer + * + * @param {Buffer} arg + * @return {HDPrivateKey} + */ HDPrivateKey.fromBuffer = function(arg) { return new HDPrivateKey(arg); }; +/** + * Returns a buffer representation of the HDPrivateKey + * + * @return {string} + */ HDPrivateKey.prototype.toBuffer = function() { return this._buffers.xprivkey; }; From 7a73f582b4cdbded73405e667e1534b88d655abe Mon Sep 17 00:00:00 2001 From: Esteban Ordano Date: Tue, 27 Jan 2015 12:24:00 -0300 Subject: [PATCH 3/4] HDKeys: add toBuffer/fromBuffer to HDPublicKey --- lib/hdpublickey.js | 19 +++++++++++++++++++ test/hdprivatekey.js | 2 +- test/hdpublickey.js | 11 +++++++++++ 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/lib/hdpublickey.js b/lib/hdpublickey.js index 721b18ac4..7126d5071 100644 --- a/lib/hdpublickey.js +++ b/lib/hdpublickey.js @@ -417,6 +417,25 @@ HDPublicKey.prototype.toJSON = function toJSON() { return JSON.stringify(this.toObject()); }; +/** + * Create a HDPublicKey from a buffer argument + * + * @param {Buffer} arg + * @return {HDPublicKey} + */ +HDPublicKey.fromBuffer = function(arg) { + return new HDPublicKey(arg); +}; + +/** + * Return a buffer representation of the xpubkey + * + * @return {Buffer} + */ +HDPublicKey.prototype.toBuffer = function() { + return this._buffers.xpubkey; +}; + HDPublicKey.Hardened = 0x80000000; HDPublicKey.RootElementAlias = ['m', 'M']; diff --git a/test/hdprivatekey.js b/test/hdprivatekey.js index 140351b89..1c2788cb9 100644 --- a/test/hdprivatekey.js +++ b/test/hdprivatekey.js @@ -262,7 +262,7 @@ describe('HDPrivate key interface', function() { }); }); - describe.only('conversion to/from buffer', function() { + describe('conversion to/from buffer', function() { var str = 'xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi'; it('should roundtrip to/from a buffer', function() { var priv = new HDPrivateKey(str); diff --git a/test/hdpublickey.js b/test/hdpublickey.js index f67b1e426..4d48f88bd 100644 --- a/test/hdpublickey.js +++ b/test/hdpublickey.js @@ -153,6 +153,17 @@ describe('HDPublicKey interface', function() { pubKey.inspect().should.equal(''); }); + describe('conversion to/from buffer', function() { + + it('should roundtrip to an equivalent object', function() { + var pubKey = new HDPublicKey(xpubkey); + var toBuffer = pubKey.toBuffer(); + var fromBuffer = HDPublicKey.fromBuffer(toBuffer); + var roundTrip = new HDPublicKey(fromBuffer.toBuffer()); + roundTrip.xpubkey.should.equal(xpubkey); + }); + }); + describe('conversion to different formats', function() { var plainObject = { 'network':'livenet', From 69b466470ae6590a07304cc80b48632d12436012 Mon Sep 17 00:00:00 2001 From: Esteban Ordano Date: Tue, 27 Jan 2015 14:13:41 -0300 Subject: [PATCH 4/4] HDKeys: Return a copy buffer instead of the original instance --- lib/hdprivatekey.js | 14 ++++++-------- lib/hdpublickey.js | 12 +++++------- lib/util/buffer.js | 12 ++++++++++++ 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/lib/hdprivatekey.js b/lib/hdprivatekey.js index 7a2ca008e..262f37d79 100644 --- a/lib/hdprivatekey.js +++ b/lib/hdprivatekey.js @@ -52,6 +52,8 @@ function HDPrivateKey(arg) { this._buildFromSerialized(arg); } else if (JSUtil.isValidJSON(arg)) { this._buildFromJSON(arg); + } else if (BufferUtil.isBuffer(arg) && HDPrivateKey.isValidSerialized(arg.toString())) { + this._buildFromSerialized(arg.toString()); } else { throw HDPrivateKey.getSerializedError(arg); } @@ -377,12 +379,8 @@ HDPrivateKey.prototype._buildFromBuffers = function(arg) { } var xprivkey; - - if (!arg.xprivkey) { - xprivkey = Base58Check.encode(buffer.Buffer.concat(sequence)); - } else { - xprivkey = arg.xprivkey; - } + xprivkey = Base58Check.encode(buffer.Buffer.concat(sequence)); + arg.xprivkey = new Buffer(xprivkey); var privateKey = new PrivateKey(BN.fromBuffer(arg.privateKey)); var publicKey = privateKey.toPublicKey(); @@ -496,7 +494,7 @@ HDPrivateKey.prototype.toJSON = function toJSON() { * @return {HDPrivateKey} */ HDPrivateKey.fromBuffer = function(arg) { - return new HDPrivateKey(arg); + return new HDPrivateKey(arg.toString()); }; /** @@ -505,7 +503,7 @@ HDPrivateKey.fromBuffer = function(arg) { * @return {string} */ HDPrivateKey.prototype.toBuffer = function() { - return this._buffers.xprivkey; + return BufferUtil.copy(this._buffers.xprivkey); }; HDPrivateKey.DefaultDepth = 0; diff --git a/lib/hdpublickey.js b/lib/hdpublickey.js index 7126d5071..7b38fdda3 100644 --- a/lib/hdpublickey.js +++ b/lib/hdpublickey.js @@ -43,6 +43,8 @@ function HDPublicKey(arg) { return this._buildFromSerialized(arg); } else if (JSUtil.isValidJSON(arg)) { return this._buildFromJSON(arg); + } else if (BufferUtil.isBuffer(arg) && !HDPublicKey.getSerializedError(arg.toString())) { + return this._buildFromSerialized(arg.toString()); } else { if (error instanceof hdErrors.ArgumentIsPrivateExtended) { return new HDPrivateKey(arg).hdPublicKey; @@ -316,12 +318,8 @@ HDPublicKey.prototype._buildFromBuffers = function (arg) { } var xpubkey; - - if (!arg.xpubkey) { - xpubkey = Base58Check.encode(BufferUtil.concat(sequence)); - } else { - xpubkey = arg.xpubkey; - } + xpubkey = Base58Check.encode(BufferUtil.concat(sequence)); + arg.xpubkey = new Buffer(xpubkey); var publicKey = PublicKey.fromString(arg.publicKey); var size = HDPublicKey.ParentFingerPrintSize; @@ -433,7 +431,7 @@ HDPublicKey.fromBuffer = function(arg) { * @return {Buffer} */ HDPublicKey.prototype.toBuffer = function() { - return this._buffers.xpubkey; + return BufferUtil.copy(this._buffers.xpubkey); }; HDPublicKey.Hardened = 0x80000000; diff --git a/lib/util/buffer.js b/lib/util/buffer.js index f750b5e21..332b4be80 100644 --- a/lib/util/buffer.js +++ b/lib/util/buffer.js @@ -37,6 +37,18 @@ module.exports = { return buffer; }, + /** + * Return a copy of a buffer + * + * @param {Buffer} original + * @return {Buffer} + */ + copy: function(original) { + var buffer = new Buffer(original.length); + original.copy(buffer); + return buffer; + }, + /** * Returns true if the given argument is an instance of a buffer. Tests for * both node's Buffer and Uint8Array