From 3d447ded79c3f329cb1a0e8f1eec62b68e4fa2a5 Mon Sep 17 00:00:00 2001 From: Braydon Fuller Date: Thu, 30 Apr 2015 11:20:09 -0400 Subject: [PATCH 1/5] Update bn.js to 2.0.4 to handle 53 bit precision number input. --- lib/transaction/output.js | 8 +++-- lib/transaction/transaction.js | 14 ++++++-- lib/util/js.js | 4 +-- npm-shrinkwrap.json | 61 +++++++++++++-------------------- package.json | 4 +-- test/transaction/deserialize.js | 24 +++++++------ test/transaction/output.js | 8 ++--- test/util/js.js | 18 +++++----- 8 files changed, 72 insertions(+), 69 deletions(-) diff --git a/lib/transaction/output.js b/lib/transaction/output.js index 66385fc..20823f3 100644 --- a/lib/transaction/output.js +++ b/lib/transaction/output.js @@ -48,12 +48,16 @@ Object.defineProperty(Output.prototype, 'satoshis', { this._satoshis = parseInt(num); this._satoshisBN = BN.fromNumber(this._satoshis); } else { + $.checkArgument( + JSUtil.isNaturalNumber(num), + 'Output satoshis is not a natural number' + ); this._satoshisBN = BN.fromNumber(num); this._satoshis = num; } $.checkState( - JSUtil.isPositiveInteger(this._satoshis), - 'Output satoshis is not a positive integer' + JSUtil.isNaturalNumber(this._satoshis), + 'Output satoshis is not a natural number' ); } }); diff --git a/lib/transaction/transaction.js b/lib/transaction/transaction.js index 1b1b986..d75d17c 100644 --- a/lib/transaction/transaction.js +++ b/lib/transaction/transaction.js @@ -60,6 +60,7 @@ function Transaction(serialized) { var CURRENT_VERSION = 1; var DEFAULT_NLOCKTIME = 0; +var MAX_SAFE_INTEGER = 0x1fffffffffffff; // Minimum amount for an output for it not to be considered a dust output Transaction.DUST_AMOUNT = 546; @@ -644,7 +645,7 @@ Transaction.prototype.getChangeOutput = function() { */ Transaction.prototype.to = function(address, amount) { $.checkArgument( - JSUtil.isPositiveInteger(amount), + JSUtil.isNaturalNumber(amount), 'Amount is expected to be a positive integer' ); this.addOutput(new Output({ @@ -990,7 +991,16 @@ Transaction.prototype.verify = function() { var valueoutbn = new BN(0); for (var i = 0; i < this.outputs.length; i++) { var txout = this.outputs[i]; - var valuebn = txout._satoshisBN; + + if (txout._satoshis > MAX_SAFE_INTEGER) { + return 'transaction txout ' + i + ' satoshis greater than max safe integer'; + } + + if (txout._satoshis !== txout._satoshisBN.toNumber()) { + return 'transaction txout ' + i + ' satoshis has corrupted value'; + } + + var valuebn = new BN(txout._satoshis, 10); if (valuebn.lt(BN.Zero)) { return 'transaction txout ' + i + ' negative'; } diff --git a/lib/util/js.js b/lib/util/js.js index 02fe4f4..c53e1e1 100644 --- a/lib/util/js.js +++ b/lib/util/js.js @@ -70,12 +70,12 @@ module.exports = { return target; }, /** - * Checks that a value is a positive integer + * Checks that a value is a natural number, a positive integer or zero. * * @param {*} value * @return {Boolean} */ - isPositiveInteger: function isPositiveInteger(value) { + isNaturalNumber: function isNaturalNumber(value) { return typeof value === 'number' && isFinite(value) && Math.floor(value) === value && diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 8c35dc9..1818acf 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -1,63 +1,48 @@ { "name": "bitcore", - "version": "0.9.0", + "version": "0.12.3", "dependencies": { "bn.js": { - "version": "0.16.1", - "from": "bn.js@0.16.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-0.16.1.tgz" + "version": "2.0.4", + "from": "bn.js@=2.0.4", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-2.0.4.tgz" }, "bs58": { "version": "2.0.0", - "from": "bs58@2.0.0", + "from": "bs58@=2.0.0", "resolved": "https://registry.npmjs.org/bs58/-/bs58-2.0.0.tgz" }, "elliptic": { - "version": "0.16.0", - "from": "elliptic@0.16.0", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-0.16.0.tgz", + "version": "3.0.3", + "from": "elliptic@=3.0.3", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-3.0.3.tgz", "dependencies": { - "bn.js": { - "version": "0.16.1", - "from": "bn.js@0.16.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-0.16.1.tgz" - }, "brorand": { - "version": "1.0.1", - "from": "brorand@1.0.1", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.0.1.tgz" + "version": "1.0.5", + "from": "brorand@^1.0.1", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.0.5.tgz" }, "hash.js": { - "version": "0.3.2", - "from": "hash.js@0.3.2", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-0.3.2.tgz" - }, - "inherits": { - "version": "2.0.1", - "from": "inherits@^2.0.1" + "version": "1.0.2", + "from": "hash.js@^1.0.0", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.0.2.tgz" } } }, + "hash.js": { + "version": "0.3.2", + "from": "hash.js@=0.3.2", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-0.3.2.tgz" + }, "inherits": { "version": "2.0.1", - "from": "inherits@2.0.1", + "from": "inherits@=2.0.1", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" }, - "hash.js": { - "version": "0.3.2", - "from": "hash.js@0.3.2", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-0.3.2.tgz", - "dependencies": { - "inherits": { - "version": "2.0.1", - "from": "inherits@^2.0.1" - } - } - }, "lodash": { - "version": "2.4.1", - "from": "lodash@=2.4.1", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.1.tgz" + "version": "2.4.1", + "from": "lodash@=2.4.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.1.tgz" }, "sha512": { "version": "0.0.1", diff --git a/package.json b/package.json index bebfdec..61ee6fc 100644 --- a/package.json +++ b/package.json @@ -79,9 +79,9 @@ "request": "browser-request" }, "dependencies": { - "bn.js": "=0.16.1", + "bn.js": "=2.0.4", "bs58": "=2.0.0", - "elliptic": "=0.16.0", + "elliptic": "=3.0.3", "hash.js": "=0.3.2", "inherits": "=2.0.1", "lodash": "=2.4.1", diff --git a/test/transaction/deserialize.js b/test/transaction/deserialize.js index 28993d9..e9f43b8 100644 --- a/test/transaction/deserialize.js +++ b/test/transaction/deserialize.js @@ -10,21 +10,25 @@ describe('Transaction deserialization', function() { describe('valid transaction test case', function() { var index = 0; vectors_valid.forEach(function(vector) { - if (vector.length > 1) { - var hexa = vector[1]; - Transaction(hexa).serialize(true).should.equal(hexa); - index++; - } + it('vector #' + index, function() { + if (vector.length > 1) { + var hexa = vector[1]; + Transaction(hexa).serialize(true).should.equal(hexa); + index++; + } + }); }); }); describe('invalid transaction test case', function() { var index = 0; vectors_invalid.forEach(function(vector) { - if (vector.length > 1) { - var hexa = vector[1]; - Transaction(hexa).serialize(true).should.equal(hexa); - index++; - } + it('invalid vector #' + index, function() { + if (vector.length > 1) { + var hexa = vector[1]; + Transaction(hexa).serialize(true).should.equal(hexa); + index++; + } + }); }); }); }); diff --git a/test/transaction/output.js b/test/transaction/output.js index fdade46..0ded9d5 100644 --- a/test/transaction/output.js +++ b/test/transaction/output.js @@ -45,7 +45,7 @@ describe('Output', function() { satoshis: -100, script: Script.empty() }); - }).should.throw('Output satoshis is not a positive integer'); + }).should.throw('Output satoshis is not a natural number'); }); it('1.1', function() { @@ -54,7 +54,7 @@ describe('Output', function() { satoshis: 1.1, script: Script.empty() }); - }).should.throw('Output satoshis is not a positive integer'); + }).should.throw('Output satoshis is not a natural number'); }); it('NaN', function() { @@ -63,7 +63,7 @@ describe('Output', function() { satoshis: NaN, script: Script.empty() }); - }).should.throw('Output satoshis is not a positive integer'); + }).should.throw('Output satoshis is not a natural number'); }); it('Infinity', function() { @@ -72,7 +72,7 @@ describe('Output', function() { satoshis: Infinity, script: Script.empty() }); - }).should.throw('Output satoshis is not a positive integer'); + }).should.throw('Output satoshis is not a natural number'); }); }); diff --git a/test/util/js.js b/test/util/js.js index 1e79d32..00070bc 100644 --- a/test/util/js.js +++ b/test/util/js.js @@ -32,44 +32,44 @@ describe('js utils', function() { }); - describe('isPositiveInteger', function() { + describe('isNaturalNumber', function() { it('false for float', function() { - var a = JSUtil.isPositiveInteger(0.1); + var a = JSUtil.isNaturalNumber(0.1); a.should.equal(false); }); it('false for string float', function() { - var a = JSUtil.isPositiveInteger('0.1'); + var a = JSUtil.isNaturalNumber('0.1'); a.should.equal(false); }); it('false for string integer', function() { - var a = JSUtil.isPositiveInteger('1'); + var a = JSUtil.isNaturalNumber('1'); a.should.equal(false); }); it('false for negative integer', function() { - var a = JSUtil.isPositiveInteger(-1); + var a = JSUtil.isNaturalNumber(-1); a.should.equal(false); }); it('false for negative integer string', function() { - var a = JSUtil.isPositiveInteger('-1'); + var a = JSUtil.isNaturalNumber('-1'); a.should.equal(false); }); it('false for infinity', function() { - var a = JSUtil.isPositiveInteger(Infinity); + var a = JSUtil.isNaturalNumber(Infinity); a.should.equal(false); }); it('false for NaN', function() { - var a = JSUtil.isPositiveInteger(NaN); + var a = JSUtil.isNaturalNumber(NaN); a.should.equal(false); }); it('true for positive integer', function() { - var a = JSUtil.isPositiveInteger(1000); + var a = JSUtil.isNaturalNumber(1000); a.should.equal(true); }); From cd12164faea4628d4bc4469697004c3d639b8d15 Mon Sep 17 00:00:00 2001 From: Braydon Fuller Date: Thu, 30 Apr 2015 12:09:59 -0400 Subject: [PATCH 2/5] Added test coverage to transaction.verify --- lib/transaction/transaction.js | 24 ++++++-------- test/transaction/transaction.js | 56 +++++++++++++++++++++++++++++++-- 2 files changed, 64 insertions(+), 16 deletions(-) diff --git a/lib/transaction/transaction.js b/lib/transaction/transaction.js index d75d17c..ac8acdb 100644 --- a/lib/transaction/transaction.js +++ b/lib/transaction/transaction.js @@ -21,9 +21,10 @@ var MultiSigScriptHashInput = Input.MultiSigScriptHash; var Output = require('./output'); var Script = require('../script'); var PrivateKey = require('../privatekey'); -var Block = require('../block'); var BN = require('../crypto/bn'); +var MAX_BLOCK_SIZE = 1000000; + /** * Represents a transaction, a set of inputs and outputs to change ownership of tokens * @@ -186,7 +187,6 @@ Transaction.prototype.getSerializationError = function(opts) { var feeIsTooLarge = this._isFeeTooLarge(); var feeIsTooSmall = this._isFeeTooSmall(); var isFullySigned = this.isFullySigned(); - var hasDustOutputs = this._hasDustOutputs(); if (!opts.disableLargeFees && feeIsTooLarge) { if (missingChange) { @@ -982,37 +982,33 @@ Transaction.prototype.verify = function() { return 'transaction txouts empty'; } - // Size limits - if (this.toBuffer().length > Block.MAX_BLOCK_SIZE) { - return 'transaction over the maximum block size'; - } - // Check for negative or overflow output values var valueoutbn = new BN(0); for (var i = 0; i < this.outputs.length; i++) { var txout = this.outputs[i]; - if (txout._satoshis > MAX_SAFE_INTEGER) { return 'transaction txout ' + i + ' satoshis greater than max safe integer'; } - if (txout._satoshis !== txout._satoshisBN.toNumber()) { return 'transaction txout ' + i + ' satoshis has corrupted value'; } - - var valuebn = new BN(txout._satoshis, 10); - if (valuebn.lt(BN.Zero)) { + if (txout._satoshis < 0) { return 'transaction txout ' + i + ' negative'; } - if (valuebn.gt(new BN(Transaction.MAX_MONEY, 10))) { + if (txout._satoshisBN.gt(new BN(Transaction.MAX_MONEY, 10))) { return 'transaction txout ' + i + ' greater than MAX_MONEY'; } - valueoutbn = valueoutbn.add(valuebn); + valueoutbn = valueoutbn.add(txout._satoshisBN); if (valueoutbn.gt(new BN(Transaction.MAX_MONEY))) { return 'transaction txout ' + i + ' total output greater than MAX_MONEY'; } } + // Size limits + if (this.toBuffer().length > MAX_BLOCK_SIZE) { + return 'transaction over the maximum block size'; + } + // Check for duplicate inputs var txinmap = {}; for (i = 0; i < this.inputs.length; i++) { diff --git a/test/transaction/transaction.js b/test/transaction/transaction.js index 2651038..27f8b5f 100644 --- a/test/transaction/transaction.js +++ b/test/transaction/transaction.js @@ -8,6 +8,7 @@ var _ = require('lodash'); var sinon = require('sinon'); var bitcore = require('../..'); +var BN = bitcore.crypto.BN; var Transaction = bitcore.Transaction; var PrivateKey = bitcore.PrivateKey; var Script = bitcore.Script; @@ -355,7 +356,7 @@ describe('Transaction', function() { var buildSkipTest = function(builder, check) { return function() { var transaction = new Transaction(); - transaction.from(simpleUtxoWith1BTC) + transaction.from(simpleUtxoWith1BTC); builder(transaction); var options = {}; @@ -410,6 +411,57 @@ describe('Transaction', function() { }); }); + describe('#verify', function() { + + it('not if _satoshis and _satoshisBN have different values', function() { + var tx = new Transaction() + .from({ + 'txId': testPrevTx, + 'outputIndex': 0, + 'script': testScript, + 'satoshis': testAmount + }).to('mrU9pEmAx26HcbKVrABvgL7AwA5fjNFoDc', testAmount - 10000); + + tx.outputs[0]._satoshis = 100; + tx.outputs[0]._satoshisBN = new BN('fffffffffffffff', 16); + var verify = tx.verify(); + verify.should.equal('transaction txout 0 satoshis has corrupted value'); + }); + + it('not if _satoshis is negative', function() { + var tx = new Transaction() + .from({ + 'txId': testPrevTx, + 'outputIndex': 0, + 'script': testScript, + 'satoshis': testAmount + }).to('mrU9pEmAx26HcbKVrABvgL7AwA5fjNFoDc', testAmount - 10000); + + tx.outputs[0]._satoshis = -100; + tx.outputs[0]._satoshisBN = new BN(-100, 10); + var verify = tx.verify(); + verify.should.equal('transaction txout 0 negative'); + }); + + it('not if transaction is greater than max block size', function() { + + var tx = new Transaction() + .from({ + 'txId': testPrevTx, + 'outputIndex': 0, + 'script': testScript, + 'satoshis': testAmount + }).to('mrU9pEmAx26HcbKVrABvgL7AwA5fjNFoDc', testAmount - 10000); + + tx.toBuffer = sinon.stub().returns({length: 10000000}); + + var verify = tx.verify(); + verify.should.equal('transaction over the maximum block size'); + + }); + + }); + describe('to and from JSON', function() { it('takes a string that is a valid JSON and deserializes from it', function() { var simple = new Transaction(); @@ -616,7 +668,7 @@ describe('Transaction', function() { transaction.outputAmount.should.equal(99990000); }); it('returns correct values for coinjoin transaction', function() { - // see livenet tx c16467eea05f1f30d50ed6dbc06a38539d9bb15110e4b7dc6653046a3678a718 + // see livenet tx c16467eea05f1f30d50ed6dbc06a38539d9bb15110e4b7dc6653046a3678a718 var transaction = new Transaction(txCoinJoinHex); transaction.outputAmount.should.equal(4191290961); expect(function() { From f8ea7e39cc31eecec69b198f2076ac09c6689581 Mon Sep 17 00:00:00 2001 From: Braydon Fuller Date: Thu, 30 Apr 2015 13:14:19 -0400 Subject: [PATCH 3/5] Included satoshis check during checked serialization. --- lib/errors/spec.js | 3 +++ lib/transaction/output.js | 15 +++++++++++++++ lib/transaction/transaction.js | 32 ++++++++++++++++++++------------ test/transaction/transaction.js | 16 ++++++++++++++-- 4 files changed, 52 insertions(+), 14 deletions(-) diff --git a/lib/errors/spec.js b/lib/errors/spec.js index 3815b59..81a3e2f 100644 --- a/lib/errors/spec.js +++ b/lib/errors/spec.js @@ -81,6 +81,9 @@ module.exports = [{ }, { name: 'DustOutputs', message: 'Dust amount detected in one output' + }, { + name: 'InvalidSatoshis', + message: 'Output satoshis are invalid', }, { name: 'FeeError', message: 'Fees are not correctly set {0}', diff --git a/lib/transaction/output.js b/lib/transaction/output.js index 20823f3..558f38e 100644 --- a/lib/transaction/output.js +++ b/lib/transaction/output.js @@ -9,6 +9,8 @@ var BufferWriter = require('../encoding/bufferwriter'); var Script = require('../script'); var $ = require('../util/preconditions'); +var MAX_SAFE_INTEGER = 0x1fffffffffffff; + function Output(params) { if (!(this instanceof Output)) { return new Output(params); @@ -62,6 +64,19 @@ Object.defineProperty(Output.prototype, 'satoshis', { } }); +Output.prototype.invalidSatoshis = function() { + if (this._satoshis > MAX_SAFE_INTEGER) { + return 'transaction txout satoshis greater than max safe integer'; + } + if (this._satoshis !== this._satoshisBN.toNumber()) { + return 'transaction txout satoshis has corrupted value'; + } + if (this._satoshis < 0) { + return 'transaction txout negative'; + } + return false; +}; + Output.prototype._fromObject = function(param) { this.satoshis = param.satoshis; if (param.script || param.scriptBuffer) { diff --git a/lib/transaction/transaction.js b/lib/transaction/transaction.js index ac8acdb..8749355 100644 --- a/lib/transaction/transaction.js +++ b/lib/transaction/transaction.js @@ -23,8 +23,6 @@ var Script = require('../script'); var PrivateKey = require('../privatekey'); var BN = require('../crypto/bn'); -var MAX_BLOCK_SIZE = 1000000; - /** * Represents a transaction, a set of inputs and outputs to change ownership of tokens * @@ -61,7 +59,7 @@ function Transaction(serialized) { var CURRENT_VERSION = 1; var DEFAULT_NLOCKTIME = 0; -var MAX_SAFE_INTEGER = 0x1fffffffffffff; +var MAX_BLOCK_SIZE = 1000000; // Minimum amount for an output for it not to be considered a dust output Transaction.DUST_AMOUNT = 546; @@ -169,12 +167,22 @@ Transaction.prototype.checkedSerialize = function(opts) { var serializationError = this.getSerializationError(opts); if (serializationError) { serializationError.message += ' Use Transaction#uncheckedSerialize if you want to skip security checks. ' + - 'See http://bitcore.io/guide/transaction.html#Serialization for more info.' + 'See http://bitcore.io/guide/transaction.html#Serialization for more info.'; throw serializationError; } return this.uncheckedSerialize(); }; +Transaction.prototype.invalidSatoshis = function() { + var invalid = false; + for (var i = 0; i < this.outputs.length; i++) { + if (this.outputs[i].invalidSatoshis()) { + invalid = true; + } + } + return invalid; +}; + /** * Retrieve a possible error that could appear when trying to serialize and broadcast this transaction * @@ -183,6 +191,11 @@ Transaction.prototype.checkedSerialize = function(opts) { */ Transaction.prototype.getSerializationError = function(opts) { opts = opts || {}; + + if (this.invalidSatoshis()) { + return new errors.Transaction.InvalidSatoshis(); + } + var missingChange = this._missingChange(); var feeIsTooLarge = this._isFeeTooLarge(); var feeIsTooSmall = this._isFeeTooSmall(); @@ -986,14 +999,9 @@ Transaction.prototype.verify = function() { var valueoutbn = new BN(0); for (var i = 0; i < this.outputs.length; i++) { var txout = this.outputs[i]; - if (txout._satoshis > MAX_SAFE_INTEGER) { - return 'transaction txout ' + i + ' satoshis greater than max safe integer'; - } - if (txout._satoshis !== txout._satoshisBN.toNumber()) { - return 'transaction txout ' + i + ' satoshis has corrupted value'; - } - if (txout._satoshis < 0) { - return 'transaction txout ' + i + ' negative'; + + if (txout.invalidSatoshis()) { + return 'transaction txout ' + i + ' satoshis is invalid'; } if (txout._satoshisBN.gt(new BN(Transaction.MAX_MONEY, 10))) { return 'transaction txout ' + i + ' greater than MAX_MONEY'; diff --git a/test/transaction/transaction.js b/test/transaction/transaction.js index 27f8b5f..7841f8a 100644 --- a/test/transaction/transaction.js +++ b/test/transaction/transaction.js @@ -246,6 +246,18 @@ describe('Transaction', function() { transaction.outputs.length.should.equal(2); transaction.outputs[1].satoshis.should.equal(10000); }); + it('if satoshis are invalid', function() { + var transaction = new Transaction() + .from(simpleUtxoWith100000Satoshis) + .to(toAddress, 99999) + .change(changeAddress) + .sign(privateKey); + transaction.outputs[0]._satoshis = 100; + transaction.outputs[0]._satoshisBN = new BN(101, 10); + expect(function() { + return transaction.serialize(); + }).to.throw(errors.Transaction.InvalidSatoshis); + }); it('if fee is too small, fail serialization', function() { var transaction = new Transaction() .from(simpleUtxoWith100000Satoshis) @@ -425,7 +437,7 @@ describe('Transaction', function() { tx.outputs[0]._satoshis = 100; tx.outputs[0]._satoshisBN = new BN('fffffffffffffff', 16); var verify = tx.verify(); - verify.should.equal('transaction txout 0 satoshis has corrupted value'); + verify.should.equal('transaction txout 0 satoshis is invalid'); }); it('not if _satoshis is negative', function() { @@ -440,7 +452,7 @@ describe('Transaction', function() { tx.outputs[0]._satoshis = -100; tx.outputs[0]._satoshisBN = new BN(-100, 10); var verify = tx.verify(); - verify.should.equal('transaction txout 0 negative'); + verify.should.equal('transaction txout 0 satoshis is invalid'); }); it('not if transaction is greater than max block size', function() { From efa0777b082768de66b31877fce44f0e55e0089a Mon Sep 17 00:00:00 2001 From: Braydon Fuller Date: Thu, 30 Apr 2015 13:50:05 -0400 Subject: [PATCH 4/5] Update hash.js to 1.0.2 --- npm-shrinkwrap.json | 11 +++-------- package.json | 2 +- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 1818acf..2e2a696 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -21,18 +21,13 @@ "version": "1.0.5", "from": "brorand@^1.0.1", "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.0.5.tgz" - }, - "hash.js": { - "version": "1.0.2", - "from": "hash.js@^1.0.0", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.0.2.tgz" } } }, "hash.js": { - "version": "0.3.2", - "from": "hash.js@=0.3.2", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-0.3.2.tgz" + "version": "1.0.2", + "from": "hash.js@^1.0.0", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.0.2.tgz" }, "inherits": { "version": "2.0.1", diff --git a/package.json b/package.json index 61ee6fc..9f3f9c0 100644 --- a/package.json +++ b/package.json @@ -82,7 +82,7 @@ "bn.js": "=2.0.4", "bs58": "=2.0.0", "elliptic": "=3.0.3", - "hash.js": "=0.3.2", + "hash.js": "=1.0.2", "inherits": "=2.0.1", "lodash": "=2.4.1", "sha512": "=0.0.1" From b688334bf31bd373d86a18905e7ad516d9d9b475 Mon Sep 17 00:00:00 2001 From: Braydon Fuller Date: Wed, 6 May 2015 13:37:17 -0400 Subject: [PATCH 5/5] Added test case for zero in isNaturalNumber tests. --- test/util/js.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/util/js.js b/test/util/js.js index 00070bc..0928b8d 100644 --- a/test/util/js.js +++ b/test/util/js.js @@ -68,6 +68,11 @@ describe('js utils', function() { a.should.equal(false); }); + it('true for zero', function() { + var a = JSUtil.isNaturalNumber(0); + a.should.equal(true); + }); + it('true for positive integer', function() { var a = JSUtil.isNaturalNumber(1000); a.should.equal(true);