diff --git a/lib/http/base.js b/lib/http/base.js index 4797be1aa..a1dd0e9ac 100644 --- a/lib/http/base.js +++ b/lib/http/base.js @@ -892,8 +892,7 @@ HTTPBaseOptions.prototype.fromOptions = function fromOptions(options) { } if (options.port != null) { - assert(typeof options.port === 'number', 'Port must be a number.'); - assert(options.port > 0 && options.port <= 0xffff); + assert(util.isU16(options.port), 'Port must be a number.'); this.port = options.port; } diff --git a/lib/http/server.js b/lib/http/server.js index c8f7b6067..a68cf2522 100644 --- a/lib/http/server.js +++ b/lib/http/server.js @@ -766,8 +766,7 @@ HTTPOptions.prototype.fromOptions = function fromOptions(options) { } if (options.port != null) { - assert(typeof options.port === 'number', 'Port must be a number.'); - assert(options.port > 0 && options.port <= 0xffff); + assert(util.isU16(options.port), 'Port must be a number.'); this.port = options.port; } diff --git a/lib/net/pool.js b/lib/net/pool.js index 7859a55ce..cfd923178 100644 --- a/lib/net/pool.js +++ b/lib/net/pool.js @@ -3726,8 +3726,7 @@ PoolOptions.prototype.fromOptions = function fromOptions(options) { } if (options.port != null) { - assert(typeof options.port === 'number'); - assert(options.port > 0 && options.port <= 0xffff); + assert(util.isU16(options.port)); this.port = options.port; this.publicPort = options.port; } @@ -3738,8 +3737,7 @@ PoolOptions.prototype.fromOptions = function fromOptions(options) { } if (options.publicPort != null) { - assert(typeof options.publicPort === 'number'); - assert(options.publicPort > 0 && options.publicPort <= 0xffff); + assert(util.isU16(options.publicPort)); this.publicPort = options.publicPort; } diff --git a/lib/utils/util.js b/lib/utils/util.js index 5e7e390b3..e7d9288c4 100644 --- a/lib/utils/util.js +++ b/lib/utils/util.js @@ -31,154 +31,54 @@ const inspectOptions = { }; /** - * Return hrtime (shim for browser). - * @param {Array} time - * @returns {Array} - */ - -util.hrtime = function hrtime(time) { - if (!process.hrtime) { - const now = util.ms(); - - if (time) { - const [hi, lo] = time; - const start = hi * 1000 + lo / 1e6; - return now - start; - } - - const ms = now % 1000; - const sec = (now - ms) / 1000; - - return [sec, ms * 1e6]; - } - - if (time) { - const [hi, lo] = process.hrtime(time); - return hi * 1000 + lo / 1e6; - } - - return process.hrtime(); -}; - -/** - * Test whether a string is base58 (note that you - * may get a false positive on a hex string). - * @param {String?} obj - * @returns {Boolean} - */ - -util.isBase58 = function isBase58(obj) { - return typeof obj === 'string' && /^[1-9a-zA-Z]+$/.test(obj); -}; - -/** - * Test whether a string is hex (length must be even). - * Note that this _could_ await a false positive on - * base58 strings. - * @param {String?} obj + * Test whether a number is Number, + * finite, and below MAX_SAFE_INTEGER. + * @param {Number?} value * @returns {Boolean} */ -util.isHex = function isHex(obj) { - return typeof obj === 'string' - && /^[0-9a-f]+$/i.test(obj) - && obj.length % 2 === 0; -}; - -/** - * Reverse a hex-string (used because of - * bitcoind's affinity for uint256le). - * @param {String} data - Hex string. - * @returns {String} Reversed hex string. - */ - -util.revHex = function revHex(data) { - assert(typeof data === 'string'); - assert(data.length > 0); - assert(data.length % 2 === 0); - - let out = ''; - - for (let i = 0; i < data.length; i += 2) - out = data.slice(i, i + 2) + out; - - return out; +util.isNumber = function isNumber(value) { + return Number.isSafeInteger(value); }; /** - * Test whether the result of a positive - * addition would be below MAX_SAFE_INTEGER. - * @param {Number} value + * Test whether an object is an int. + * @param {Number?} value * @returns {Boolean} */ -util.isSafeAddition = function isSafeAddition(a, b) { - // We only work on positive numbers. - assert(a >= 0); - assert(b >= 0); - - // Fast case. - if (a <= 0xfffffffffffff && b <= 0xfffffffffffff) - return true; - - // Do a 64 bit addition and check the top 11 bits. - let ahi = (a * (1 / 0x100000000)) | 0; - const alo = a | 0; - - let bhi = (b * (1 / 0x100000000)) | 0; - const blo = b | 0; - - // Credit to @indutny for this method. - const lo = (alo + blo) | 0; - - const s = lo >> 31; - const as = alo >> 31; - const bs = blo >> 31; - - const c = ((as & bs) | (~s & (as ^ bs))) & 1; - - let hi = (((ahi + bhi) | 0) + c) | 0; - - hi >>>= 0; - ahi >>>= 0; - bhi >>>= 0; - - // Overflow? - if (hi < ahi || hi < bhi) - return false; - - return (hi & 0xffe00000) === 0; +util.isInt = function isInt(value) { + return util.isNumber(value) && value % 1 === 0; }; /** - * Test whether a number is Number, - * finite, and below MAX_SAFE_INTEGER. + * Test whether an object is an int. * @param {Number?} value * @returns {Boolean} */ -util.isNumber = function isNumber(value) { - return Number.isSafeInteger(value); +util.isUint = function isUint(value) { + return util.isInt(value) && value >= 0; }; /** - * Test whether an object is an int. + * Test whether a number is a float. * @param {Number?} value * @returns {Boolean} */ -util.isInt = function isInt(value) { - return util.isNumber(value) && value % 1 === 0; +util.isFloat = function isFloat(value) { + return typeof value === 'number' && isFinite(value); }; /** - * Test whether an object is an int. + * Test whether a number is a positive float. * @param {Number?} value * @returns {Boolean} */ -util.isUint = function isUint(value) { - return util.isInt(value) && value >= 0; +util.isUfloat = function isUfloat(value) { + return util.isFloat(value) && value >= 0; }; /** @@ -261,24 +161,109 @@ util.isU64 = function isU64(value) { return util.isUint(value); }; +/** + * Test whether a string is a plain + * ascii string (no control characters). + * @param {String} str + * @returns {Boolean} + */ + +util.isAscii = function isAscii(str) { + return typeof str === 'string' && /^[\t\n\r -~]*$/.test(str); +}; + +/** + * Test whether a string is base58 (note that you + * may get a false positive on a hex string). + * @param {String?} str + * @returns {Boolean} + */ + +util.isBase58 = function isBase58(str) { + return typeof str === 'string' && /^[1-9a-zA-Z]+$/.test(str); +}; + +/** + * Test whether a string is hex (length must be even). + * Note that this _could_ await a false positive on + * base58 strings. + * @param {String?} str + * @returns {Boolean} + */ + +util.isHex = function isHex(str) { + if (typeof str !== 'string') + return false; + return /^[0-9a-f]+$/i.test(str) && str.length % 2 === 0; +}; + /** * Test whether an object is a 160 bit hash (hex string). - * @param {String?} value + * @param {String?} hash * @returns {Boolean} */ util.isHex160 = function isHex160(hash) { - return util.isHex(hash) && hash.length === 40; + if (typeof hash !== 'string') + return false; + return hash.length === 40 && util.isHex(hash); }; /** * Test whether an object is a 256 bit hash (hex string). - * @param {String?} value + * @param {String?} hash * @returns {Boolean} */ util.isHex256 = function isHex256(hash) { - return util.isHex(hash) && hash.length === 64; + if (typeof hash !== 'string') + return false; + return hash.length === 64 && util.isHex(hash); +}; + +/** + * Test whether the result of a positive + * addition would be below MAX_SAFE_INTEGER. + * @param {Number} value + * @returns {Boolean} + */ + +util.isSafeAddition = function isSafeAddition(a, b) { + // We only work on positive numbers. + assert(a >= 0); + assert(b >= 0); + + // Fast case. + if (a <= 0xfffffffffffff && b <= 0xfffffffffffff) + return true; + + // Do a 64 bit addition and check the top 11 bits. + let ahi = (a * (1 / 0x100000000)) | 0; + const alo = a | 0; + + let bhi = (b * (1 / 0x100000000)) | 0; + const blo = b | 0; + + // Credit to @indutny for this method. + const lo = (alo + blo) | 0; + + const s = lo >> 31; + const as = alo >> 31; + const bs = blo >> 31; + + const c = ((as & bs) | (~s & (as ^ bs))) & 1; + + let hi = (((ahi + bhi) | 0) + c) | 0; + + hi >>>= 0; + ahi >>>= 0; + bhi >>>= 0; + + // Overflow? + if (hi < ahi || hi < bhi) + return false; + + return (hi & 0xffe00000) === 0; }; /** @@ -367,6 +352,36 @@ util.error = function error(...args) { process.stderr.write(msg + '\n'); }; +/** + * Return hrtime (shim for browser). + * @param {Array} time + * @returns {Array} + */ + +util.hrtime = function hrtime(time) { + if (!process.hrtime) { + const now = util.ms(); + + if (time) { + const [hi, lo] = time; + const start = hi * 1000 + lo / 1e6; + return now - start; + } + + const ms = now % 1000; + const sec = (now - ms) / 1000; + + return [sec, ms * 1e6]; + } + + if (time) { + const [hi, lo] = process.hrtime(time); + return hi * 1000 + lo / 1e6; + } + + return process.hrtime(); +}; + /** * Get current time in unix time (seconds). * @returns {Number} @@ -651,6 +666,26 @@ util.hex32 = function hex32(num) { throw new Error('Number too big.'); }; +/** + * Reverse a hex-string (used because of + * bitcoind's affinity for uint256le). + * @param {String} data - Hex string. + * @returns {String} Reversed hex string. + */ + +util.revHex = function revHex(data) { + assert(typeof data === 'string'); + assert(data.length > 0); + assert(data.length % 2 === 0); + + let out = ''; + + for (let i = 0; i < data.length; i += 2) + out = data.slice(i, i + 2) + out; + + return out; +}; + /** * Reverse an object's keys and values. * @param {Object} obj @@ -772,17 +807,6 @@ if (!''.startsWith) { }; } -/** - * Test whether a string is a plain - * ascii string (no control characters). - * @param {String} str - * @returns {Boolean} - */ - -util.isAscii = function isAscii(str) { - return /^[\t\n\r -~]*$/.test(str); -}; - /** * Get memory usage info. * @returns {Object} diff --git a/lib/wallet/http.js b/lib/wallet/http.js index 01e95d3bb..0c650b852 100644 --- a/lib/wallet/http.js +++ b/lib/wallet/http.js @@ -1016,8 +1016,7 @@ HTTPOptions.prototype.fromOptions = function fromOptions(options) { } if (options.port != null) { - assert(typeof options.port === 'number', 'Port must be a number.'); - assert(options.port > 0 && options.port <= 0xffff); + assert(util.isU16(options.port), 'Port must be a number.'); this.port = options.port; }