From bf8b663c5d57c2cb881ab70351ec64a94b3b1430 Mon Sep 17 00:00:00 2001 From: Kagami Hiiragi Date: Sat, 3 Jan 2015 17:52:27 +0300 Subject: [PATCH] Do not use promises in crypto Because sha.js is faster than WebCryptoAPI for POW. --- README.md | 17 +--- lib/address.js | 218 +++++++++++++++++----------------------- lib/crypto.js | 6 +- lib/messages.js | 2 +- lib/objects.js | 2 +- lib/platform.browser.js | 25 +---- lib/platform.js | 15 +-- lib/wif.js | 31 ++---- package.json | 4 +- test.js | 101 ++++++++----------- 10 files changed, 163 insertions(+), 258 deletions(-) diff --git a/README.md b/README.md index 0ecf627..d6b03ed 100644 --- a/README.md +++ b/README.md @@ -12,14 +12,6 @@ API documentation is available [here](https://bitchan.github.io/bitmessage/docs/ * [Protocol specification](https://bitmessage.org/wiki/Protocol_specification) * [Whitepaper](https://bitmessage.org/bitmessage.pdf) -## Implementation details - -With the help of browserify `bitmessage` provides different implementations for Browser and Node.js with the same API. Because WebCryptoAPI defines asynchronous promise-driven API, implementation for Node needs to use promises too. - -* Use Node.js crypto module/library bindings where possible -* Use WebCryptoAPI where possible -* Promise-driven API - ## Feature matrix (both Browser and Node) - [ ] crypto @@ -83,13 +75,10 @@ With the help of browserify `bitmessage` provides different implementations for ## Usage ```js -// Generating a new Bitmessage identity. +// Generate a new random Bitmessage identity. var Address = require("bitmessage").Address; -Address.fromRandom().then(function(addr) { - addr.encode().then(function(str) { - console.log("New random Bitmessage address:", str); - }); -}); +var addr = Address.fromRandom(); +console.log("New random Bitmessage address:", addr.encode()); ``` ## License diff --git a/lib/address.js b/lib/address.js index 096a05a..f978db8 100644 --- a/lib/address.js +++ b/lib/address.js @@ -6,7 +6,6 @@ "use strict"; -require("es6-promise").polyfill(); require("object.assign").shim(); var assert = require("assert"); var bufferEqual = require("buffer-equal"); @@ -30,14 +29,20 @@ function Address(opts) { assert(this.version >= 1, "Version too low"); this.stream = this.stream || 1; if (this.ripe) { - assertripelen(getripelen(this.ripe), this.version); + assertripelen(getripelen(this.ripe), this.version, this.ripe); + if (this.ripe.length < 20) { + var fullripe = new Buffer(20); + fullripe.fill(0); + this.ripe.copy(fullripe, 20 - this.ripe.length); + this.ripe = fullripe; + } } } /** * Parse Bitmessage address into address object. * @param {String} str - Address string (with or without `BM-` prefix) - * @return {Promise.
} Decoded address object. + * @return {Address} Decoded address object. */ Address.decode = function(str) { str = str.trim(); @@ -45,47 +50,29 @@ Address.decode = function(str) { str = str.slice(3); } - var bytes; - try { - bytes = bs58.decode(str); - } catch(e) { - return Promise.reject(e); - } - - // Checksum validating. + var bytes = bs58.decode(str); var data = new Buffer(bytes.slice(0, -4)); var checksum = new Buffer(bytes.slice(-4)); - return getchecksum(data).then(function(realchecksum) { - assert(bufferEqual(checksum, realchecksum), "Bad checkum"); + assert(bufferEqual(checksum, getchecksum(data)), "Bad checkum"); - var decoded = var_int.decode(data); - var version = decoded.value; + var decoded = var_int.decode(data); + var version = decoded.value; - data = decoded.rest; - decoded = var_int.decode(data); - var stream = decoded.value; + data = decoded.rest; + decoded = var_int.decode(data); + var stream = decoded.value; - var ripe = decoded.rest; - var ripelen = ripe.length; - if (version === 4) { - assert(ripe[0] !== 0, "Ripe encode error"); - } + var ripe = decoded.rest; + if (version === 4) { + assert(ripe[0] !== 0, "Ripe encode error"); + } - // Prevent extra allocation. God, kill me please for premature - // optimizations. - if (ripelen < 20) { - var zeroes = new Buffer(Array(20 - ripelen)); - ripe = Buffer.concat([zeroes, ripe]); - } - return new Address({version: version, stream: stream, ripe: ripe}); - }); + return new Address({version: version, stream: stream, ripe: ripe}); }; // Compute the Bitmessage checksum for the given data. function getchecksum(data) { - return bmcrypto.sha512(data).then(bmcrypto.sha512).then(function(dhash) { - return dhash.slice(0, 4); - }); + return bmcrypto.sha512(bmcrypto.sha512(data)).slice(0, 4); } // Get RIPEMD160(SHA512(SIGN_PUBLIC_KEY || ENC_PUBLIC_KEY)). @@ -104,39 +91,36 @@ function keys2ripe(signKey, encKey) { encPublicKey = encKey; } var concat = Buffer.concat([signPublicKey, encPublicKey]); - return bmcrypto.sha512(concat).then(bmcrypto.ripemd160); + return bmcrypto.ripemd160(bmcrypto.sha512(concat)); } /** - * Calculate the Ripe hash of the address. + * Calculate the ripe hash of the address. * @param {?Object} opts - Options - * @return {Promise.} Resulting Ripe hash. + * @return {Buffer} Resulting ripe hash. */ Address.prototype.getRipe = function(opts) { - var self = this; - var ripepromise; - if (self.ripe) { - ripepromise = Promise.resolve(self.ripe); + var ripe; + opts = opts || {}; + if (this.ripe) { + ripe = this.ripe; } else { - opts = opts || {}; - var signKey = self.signPrivateKey || self.signPublicKey; + var signKey = this.signPrivateKey || this.signPublicKey; assert(signKey, "No signing key"); - var encKey = self.encPrivateKey || self.encPublicKey; + var encKey = this.encPrivateKey || this.encPublicKey; assert(encKey, "No encryption key"); - ripepromise = keys2ripe(signKey, encKey); + ripe = keys2ripe(signKey, encKey); + } + var ripelen = getripelen(ripe); + assertripelen(ripelen, this.version, ripe); + if (opts.short) { + return ripe.slice(20 - ripelen); + } else { + return ripe; } - return ripepromise.then(function(ripe) { - var ripelen = getripelen(ripe); - assertripelen(ripelen, self.version); - if (opts.short) { - return ripe.slice(20 - ripelen); - } else { - return ripe; - } - }); }; -// Get truncated Ripe hash length. +// Get truncated ripe hash length. function getripelen(ripe) { var zeroes = 0; for (var i = 0; i < 20, ripe[i] === 0; i++) { @@ -145,21 +129,24 @@ function getripelen(ripe) { return 20 - zeroes; } -// Do neccessary checkings of the truncated Ripe hash length depending +// Do neccessary checkings of the truncated ripe hash length depending // on the address version. -function assertripelen(ripelen, version) { +function assertripelen(ripelen, version, ripe) { + if (ripe) { + assert(ripe.length <= 20, "Bad ripe"); + } switch (version) { case 1: assert(ripelen === 20, "Bad ripe length"); break; case 2: case 3: - assert(ripelen >= 18, "Ripe too short"); - assert(ripelen <= 20, "Ripe too long"); + assert(ripelen >= 18, "Ripe is too short"); + assert(ripelen <= 20, "Ripe is too long"); break; case 4: - assert(ripelen >= 4, "Ripe too short"); - assert(ripelen <= 20, "Ripe too long"); + assert(ripelen >= 4, "Ripe is too short"); + assert(ripelen <= 20, "Ripe is too long"); break; default: throw new Error("Bad version"); @@ -179,82 +166,67 @@ function checkripelen(ripelen, version) { /** * Encode Bitmessage address object into address string. - * @return {Promise.} Address string. + * @return {string} Address string. */ Address.prototype.encode = function() { - var self = this; - return self.getRipe({short: true}).then(function(ripe) { - var data = Buffer.concat([ - var_int.encode(self.version), - var_int.encode(self.stream), - ripe, - ]); - return getchecksum(data).then(function(checksum) { - var addr = Buffer.concat([data, checksum]); - return "BM-" + bs58.encode(addr); - }); - }); + var ripe = this.getRipe({short: true}); + var data = Buffer.concat([ + var_int.encode(this.version), + var_int.encode(this.stream), + ripe, + ]); + var addr = Buffer.concat([data, getchecksum(data)]); + return "BM-" + bs58.encode(addr); }; +function popkey(obj, key) { + var value = obj[key]; + delete obj[key]; + return value; +} + /** * Create new Bitmessage address from random encryption and signing * private keys. * @param {?Object} opts - Address options - * @return {Promise.
} Generated address object. + * @return {Address} Generated address object. */ Address.fromRandom = function(opts) { - opts = opts || {}; - var version = opts.version || 4; - var ripelen = opts.ripelen || 19; - try { - assertripelen(ripelen, version); - } catch(e) { - return Promise.reject(e); - } - // Should the generated Ripe length be strictly equal to the specified - // (less-or-equal by default); - var strictripelen = !!opts.strictripelen; - var nextTick = typeof setImmediate === "undefined" ? - process.nextTick : - setImmediate; + opts = Object.assign({}, opts); + var version = opts.version = opts.version || 4; + var ripelen = popkey(opts, "ripelen") || 19; + assertripelen(ripelen, version); + // Should the generated ripe length be strictly equal to the specified + // (less or equal by default). + var strictripelen = !!popkey(opts, "strictripelen"); + // TODO(Kagami): Speed it up using web workers in Browser. + // TODO(Kagami): Bind to C++ version of this code in Node. + var encPrivateKey, encPublicKey, ripe; var signPrivateKey = bmcrypto.getPrivate(); var signPublicKey = bmcrypto.getPublic(signPrivateKey); - - // FIXME(Kagami): This function is rather slow in browsers so - // generation of ripelen=18 currently is disabled (see `test.js`). It - // should be heavily profiled to determine the bottleneck. - // TODO(Kagami): We may want to run this in the web worker to speedup - // the search. Currently WebCryptoAPI is not available in Firefox in - // web workers (see - // ) but is - // available in Chrome (at least in 39.0+). - return new Promise(function(resolve, reject) { - function tryKey() { - var encPrivateKey = bmcrypto.getPrivate(); - var encPublicKey = bmcrypto.getPublic(encPrivateKey); - return keys2ripe(signPublicKey, encPublicKey).then(function(ripe) { - var len = getripelen(ripe); - if ( - (strictripelen && len === ripelen) || - (!strictripelen && len <= ripelen && checkripelen(ripelen, version)) - ) { - // TODO(Kagami): Do we need to put all these properties or compute - // them manually via ECMA5 getters/setters instead? - resolve(new Address(Object.assign({ - signPrivateKey: signPrivateKey, - signPublicKey: signPublicKey, - encPrivateKey: encPrivateKey, - encPublicKey: encPublicKey, - ripe: ripe, - }, opts))); - } else { - nextTick(tryKey); - } - }).catch(reject); + var keysbuf = Buffer(130); + signPublicKey.copy(keysbuf); + while (true) { + encPrivateKey = bmcrypto.getPrivate(); + encPublicKey = bmcrypto.getPublic(encPrivateKey); + encPublicKey.copy(keysbuf, 65); + ripe = bmcrypto.ripemd160(bmcrypto.sha512(keysbuf)); + var len = getripelen(ripe); + if ( + (strictripelen && len === ripelen) || + (!strictripelen && len <= ripelen && checkripelen(ripelen, version)) + ) { + // TODO(Kagami): Do we need to put all these properties or compute + // them manually via ECMA5 getters/setters instead? + opts.signPrivateKey = signPrivateKey; + opts.signPublicKey = signPublicKey; + opts.encPrivateKey = encPrivateKey; + opts.encPublicKey = encPublicKey; + opts.ripe = ripe; + return new Address(opts); } - tryKey(); - }); + } }; module.exports = Address; diff --git a/lib/crypto.js b/lib/crypto.js index 79ce268..829e064 100644 --- a/lib/crypto.js +++ b/lib/crypto.js @@ -12,7 +12,7 @@ var platform = require("./platform"); /** * Calculate SHA-512 hash. * @param {Buffer} buf - Input data - * @return {Promise.} Resulting hash. + * @return {Buffer} Resulting hash. * @function */ exports.sha512 = platform.sha512; @@ -20,7 +20,7 @@ exports.sha512 = platform.sha512; /** * Calculate SHA-256 hash. * @param {Buffer} buf - Input data - * @return {Promise.} Resulting hash. + * @return {Buffer} Resulting hash. * @function */ exports.sha256 = platform.sha256; @@ -28,7 +28,7 @@ exports.sha256 = platform.sha256; /** * Calculate RIPEMD-160 hash. * @param {Buffer} buf - Input data - * @return {Promise.} Resulting hash. + * @return {Buffer} Resulting hash. * @function */ exports.ripemd160 = platform.ripemd160; diff --git a/lib/messages.js b/lib/messages.js index aa42f6d..e5e0d6b 100644 --- a/lib/messages.js +++ b/lib/messages.js @@ -1,5 +1,5 @@ /** * Working with messages. * @see {@link https://bitmessage.org/wiki/Protocol_specification#Message_types} - * @module bitmessage/message + * @module bitmessage/messages */ diff --git a/lib/objects.js b/lib/objects.js index 9a8b78e..d5bcc96 100644 --- a/lib/objects.js +++ b/lib/objects.js @@ -1,5 +1,5 @@ /** * Working with objects. * @see {@link https://bitmessage.org/wiki/Protocol_specification#Object_types} - * @module bitmessage/object + * @module bitmessage/objects */ diff --git a/lib/platform.browser.js b/lib/platform.browser.js index 7c4b5e1..3710a16 100644 --- a/lib/platform.browser.js +++ b/lib/platform.browser.js @@ -1,38 +1,21 @@ /** * Browser implementation of platform-specific routines. - * @see {@link http://www.w3.org/TR/WebCryptoAPI/} - * @see {@link http://caniuse.com/#feat=cryptography} - * @see {@link https://sites.google.com/a/chromium.org/dev/blink/webcrypto} */ "use strict"; -require("es6-promise").polyfill(); -var assert = require("assert"); +var createHash = require("sha.js"); var ripemd160 = require("ripemd160"); -// Support `webkit` prefix for Safari (not tested yet). -// TODO(Kagami): Try to support IE11. -var subtle = window.crypto.subtle || window.crypto.webkitSubtle; -assert(subtle, "WebCryptoAPI is not supported"); - exports.sha512 = function(buf) { - return subtle.digest({name: "SHA-512"}, buf).then(function(arr) { - return new Buffer(new Uint8Array(arr)); - }); + return createHash("sha512").update(buf).digest(); }; exports.sha256 = function(buf) { - return subtle.digest({name: "SHA-256"}, buf).then(function(arr) { - return new Buffer(new Uint8Array(arr)); - }); + return createHash("sha256").update(buf).digest(); }; -exports.ripemd160 = function(buf) { - // XXX(Kagami): RIPEMD is not defined in WebCryptoAPI so we provide it - // using pure JS third-party implementation. - return Promise.resolve(ripemd160(buf)); -}; +exports.ripemd160 = ripemd160; exports.randomBytes = function(size) { var arr = new Uint8Array(size); diff --git a/lib/platform.js b/lib/platform.js index 26884f1..2c7f0b1 100644 --- a/lib/platform.js +++ b/lib/platform.js @@ -1,29 +1,22 @@ /** * Node.js implementation of platform-specific routines. - * @see {@link http://nodejs.org/api/crypto.html} */ "use strict"; -require("es6-promise").polyfill(); var crypto = require("crypto"); +var createHash = crypto.createHash; exports.sha512 = function(buf) { - var hash = crypto.createHash("sha512"); - hash.update(buf); - return Promise.resolve(hash.digest()); + return createHash("sha512").update(buf).digest(); }; exports.sha256 = function(buf) { - var hash = crypto.createHash("sha256"); - hash.update(buf); - return Promise.resolve(hash.digest()); + return createHash("sha256").update(buf).digest(); }; exports.ripemd160 = function(buf) { - var hash = crypto.createHash("ripemd160"); - hash.update(buf); - return Promise.resolve(hash.digest()); + return createHash("ripemd160").update(buf).digest(); }; exports.randomBytes = crypto.randomBytes; diff --git a/lib/wif.js b/lib/wif.js index 17bd5cf..ae5041b 100644 --- a/lib/wif.js +++ b/lib/wif.js @@ -6,7 +6,6 @@ "use strict"; -require("es6-promise").polyfill(); var assert = require("assert"); var bufferEqual = require("buffer-equal"); var bs58 = require("bs58"); @@ -14,41 +13,31 @@ var bmcrypto = require("./crypto"); // Compute the WIF checksum for the given data. function getchecksum(data) { - return bmcrypto.sha256(data).then(bmcrypto.sha256).then(function(dhash) { - return dhash.slice(0, 4); - }); + return bmcrypto.sha256(bmcrypto.sha256(data)).slice(0, 4); } /** * Decode WIF encoded private key. * @param {string} wif - Encoded key - * @return {Promise.} Private key. + * @return {Buffer} Private key. */ exports.decode = function(wif) { - var bytes; - try { - bytes = bs58.decode(wif); - assert(bytes[0] === 0x80, "Bad WIF"); - } catch(e) { - return Promise.reject(e); - } + var bytes = bs58.decode(wif); + assert(bytes[0] === 0x80, "Bad WIF"); var data = new Buffer(bytes.slice(0, -4)); var checksum = new Buffer(bytes.slice(-4)); - return getchecksum(data).then(function(realchecksum) { - assert(bufferEqual(checksum, realchecksum), "Bad checkum"); - return data.slice(1); - }); + assert(bufferEqual(checksum, getchecksum(data)), "Bad checkum"); + return data.slice(1); }; /** * Convert private key to a WIF. * @param {Buffer} privateKey - A private key to encode - * @return {Promise.} Encoded private key. + * @return {string} Encoded private key. */ exports.encode = function(privateKey) { var data = Buffer.concat([new Buffer([0x80]), privateKey]); - return getchecksum(data).then(function(checksum) { - var bytes = Buffer.concat([data, checksum]); - return bs58.encode(bytes); - }); + var checksum = getchecksum(data); + var bytes = Buffer.concat([data, checksum]); + return bs58.encode(bytes); }; diff --git a/package.json b/package.json index 295a111..c1b432a 100644 --- a/package.json +++ b/package.json @@ -48,8 +48,8 @@ "bs58": "^2.0.0", "buffer-equal": "~0.0.1", "eccrypto": "^0.1.1", - "es6-promise": "^2.0.1", "object.assign": "^1.1.1", - "ripemd160": "^0.2.0" + "ripemd160": "^0.2.0", + "sha.js": "^2.3.0" } } diff --git a/test.js b/test.js index fbc649c..035b7c6 100644 --- a/test.js +++ b/test.js @@ -13,21 +13,15 @@ var Address = bitmessage.Address; describe("Crypto", function() { it("should implement SHA-512 hash", function() { - return bmcrypto.sha512(Buffer("test")).then(function(res) { - expect(res.toString("hex")).to.equal("ee26b0dd4af7e749aa1a8ee3c10ae9923f618980772e473f8819a5d4940e0db27ac185f8a0e1d5f84f88bc887fd67b143732c304cc5fa9ad8e6f57f50028a8ff"); - }); + expect(bmcrypto.sha512(Buffer("test")).toString("hex")).to.equal("ee26b0dd4af7e749aa1a8ee3c10ae9923f618980772e473f8819a5d4940e0db27ac185f8a0e1d5f84f88bc887fd67b143732c304cc5fa9ad8e6f57f50028a8ff"); }); it("should implement SHA-256 hash", function() { - return bmcrypto.sha256(Buffer("test")).then(function(res) { - expect(res.toString("hex")).to.equal("9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08"); - }); + expect(bmcrypto.sha256(Buffer("test")).toString("hex")).to.equal("9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08"); }); it("should implement RIPEMD-160 hash", function() { - return bmcrypto.ripemd160(Buffer("test")).then(function(res) { - expect(res.toString("hex")).to.equal("5e52fee47e6b070565f74372468cdc699de89107"); - }); + expect(bmcrypto.ripemd160(Buffer("test")).toString("hex")).to.equal("5e52fee47e6b070565f74372468cdc699de89107"); }); it("should implement cryptographically secure PRNG", function() { @@ -165,78 +159,63 @@ describe("WIF", function() { var encPrivateKey = Buffer("9f9969c93c2d186787a7653f70e49be34c03c4a853e6ad0c867db0946bc433c6", "hex"); it("should decode", function() { - return WIF.decode(wifSign) - .then(function(key1) { - expect(Buffer.isBuffer(key1)).to.be.true; - expect(key1.length).to.equal(32); - expect(key1.toString("hex")).to.equal(signPrivateKey.toString("hex")); - return WIF.decode(wifEnc).then(function(key2) { - expect(Buffer.isBuffer(key2)).to.be.true; - expect(key2.length).to.equal(32); - expect(key2.toString("hex")).to.equal(encPrivateKey.toString("hex")); - return Address({signPrivateKey: key1, encPrivateKey: key2}).encode(); - }); - }).then(function(str) { - expect(str).to.equal("BM-2cTux3PGRqHTEH6wyUP2sWeT4LrsGgy63z"); - }); + var key1 = WIF.decode(wifSign); + expect(Buffer.isBuffer(key1)).to.be.true; + expect(key1.length).to.equal(32); + expect(key1.toString("hex")).to.equal(signPrivateKey.toString("hex")); + var key2 = WIF.decode(wifEnc); + expect(Buffer.isBuffer(key2)).to.be.true; + expect(key2.length).to.equal(32); + expect(key2.toString("hex")).to.equal(encPrivateKey.toString("hex")); + var addrStr = Address({signPrivateKey: key1, encPrivateKey: key2}).encode(); + expect(addrStr).to.equal("BM-2cTux3PGRqHTEH6wyUP2sWeT4LrsGgy63z"); }); it("should encode", function() { - return WIF.encode(signPrivateKey).then(function(wif1) { - expect(wif1).to.equal(wifSign); - return WIF.encode(encPrivateKey); - }).then(function(wif2) { - expect(wif2).to.equal(wifEnc); - }); + var wif1 = WIF.encode(signPrivateKey); + expect(wif1).to.equal(wifSign); + var wif2 = WIF.encode(encPrivateKey); + expect(wif2).to.equal(wifEnc); }); }); describe("Address", function() { it("should decode Bitmessage address", function() { - return Address.decode("BM-2cTux3PGRqHTEH6wyUP2sWeT4LrsGgy63z") - .then(function(addr) { - expect(addr.version).to.equal(4); - expect(addr.stream).to.equal(1); - expect(addr.ripe.toString("hex")).to.equal("003ab6655de4bd8c603eba9b00dd5970725fdd56"); - }); + var addr = Address.decode("BM-2cTux3PGRqHTEH6wyUP2sWeT4LrsGgy63z") + expect(addr.version).to.equal(4); + expect(addr.stream).to.equal(1); + expect(addr.ripe.toString("hex")).to.equal("003ab6655de4bd8c603eba9b00dd5970725fdd56"); }); it("should decode Bitmessage address badly formatted", function() { - return Address.decode(" 2cTux3PGRqHTEH6wyUP2sWeT4LrsGgy63z ") - .then(function(addr) { - expect(addr.version).to.equal(4); - expect(addr.stream).to.equal(1); - expect(addr.ripe.toString("hex")).to.equal("003ab6655de4bd8c603eba9b00dd5970725fdd56"); - }); + var addr = Address.decode(" 2cTux3PGRqHTEH6wyUP2sWeT4LrsGgy63z ") + expect(addr.version).to.equal(4); + expect(addr.stream).to.equal(1); + expect(addr.ripe.toString("hex")).to.equal("003ab6655de4bd8c603eba9b00dd5970725fdd56"); }); it("should allow to generate new Bitmessage address", function() { this.timeout(10000); - return Address.fromRandom().then(function(addr) { - expect(addr.version).to.equal(4); - expect(addr.stream).to.equal(1); - expect(addr.signPrivateKey.length).to.equal(32); - expect(addr.encPrivateKey.length).to.equal(32); - return addr.encode().then(function(str) { - expect(str.slice(0, 3)).to.equal("BM-"); - return Address.decode(str).then(function(addr2) { - expect(addr2.version).to.equal(4); - expect(addr2.stream).to.equal(1); - expect(addr2.ripe.length).to.equal(20); - expect(addr2.ripe[0]).to.equal(0); - }); - }); - }); + var addr = Address.fromRandom(); + expect(addr.version).to.equal(4); + expect(addr.stream).to.equal(1); + expect(addr.signPrivateKey.length).to.equal(32); + expect(addr.encPrivateKey.length).to.equal(32); + var str = addr.encode(); + expect(str.slice(0, 3)).to.equal("BM-"); + var addr2 = Address.decode(str); + expect(addr2.version).to.equal(4); + expect(addr2.stream).to.equal(1); + expect(addr2.ripe.length).to.equal(20); + expect(addr2.ripe[0]).to.equal(0); }); if (allTests) { it("should allow to generate shorter address", function() { this.timeout(60000); - return Address.fromRandom({ripelen: 18}).then(function(addr) { - return addr.getRipe({short: true}).then(function(ripe) { - expect(ripe.length).to.be.at.most(18); - }); - }); + var addr = Address.fromRandom({ripelen: 18}); + var ripe = addr.getRipe({short: true}); + expect(ripe.length).to.be.at.most(18); }); } });