validation: use stricter validation for ints.
This commit is contained in:
parent
d8aea55f97
commit
4ce070fad4
@ -1,5 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
const assert = require('assert');
|
||||
const net = require('net');
|
||||
const EventEmitter = require('events').EventEmitter;
|
||||
const IOServer = require('socket.io');
|
||||
@ -26,27 +27,32 @@ function WSProxy(options) {
|
||||
this.options = options;
|
||||
this.target = options.target || TARGET;
|
||||
this.pow = options.pow === true;
|
||||
this.ports = options.ports || [];
|
||||
this.ports = new Set();
|
||||
this.io = new IOServer();
|
||||
this.sockets = new WeakMap();
|
||||
|
||||
this._init();
|
||||
if (options.ports) {
|
||||
for (const port of options.ports)
|
||||
this.ports.add(port);
|
||||
}
|
||||
|
||||
this.init();
|
||||
}
|
||||
|
||||
util.inherits(WSProxy, EventEmitter);
|
||||
|
||||
WSProxy.prototype._init = function _init() {
|
||||
WSProxy.prototype.init = function init() {
|
||||
this.io.on('error', (err) => {
|
||||
this.emit('error', err);
|
||||
});
|
||||
|
||||
this.io.on('connection', (ws) => {
|
||||
this._handleSocket(ws);
|
||||
this.handleSocket(ws);
|
||||
});
|
||||
};
|
||||
|
||||
WSProxy.prototype._handleSocket = function _handleSocket(ws) {
|
||||
let state = new SocketState(this, ws);
|
||||
WSProxy.prototype.handleSocket = function handleSocket(ws) {
|
||||
const state = new SocketState(this, ws);
|
||||
|
||||
// Use a weak map to avoid
|
||||
// mutating the websocket object.
|
||||
@ -59,20 +65,20 @@ WSProxy.prototype._handleSocket = function _handleSocket(ws) {
|
||||
});
|
||||
|
||||
ws.on('tcp connect', (port, host, nonce) => {
|
||||
this._handleConnect(ws, port, host, nonce);
|
||||
this.handleConnect(ws, port, host, nonce);
|
||||
});
|
||||
};
|
||||
|
||||
WSProxy.prototype._handleConnect = function _handleConnect(ws, port, host, nonce) {
|
||||
let state = this.sockets.get(ws);
|
||||
let socket, pow, raw;
|
||||
WSProxy.prototype.handleConnect = function handleConnect(ws, port, host, nonce) {
|
||||
const state = this.sockets.get(ws);
|
||||
assert(state);
|
||||
|
||||
if (state.socket) {
|
||||
this.log('Client is trying to reconnect (%s).', state.host);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!util.isNumber(port)
|
||||
if (!util.isU16(port)
|
||||
|| typeof host !== 'string'
|
||||
|| host.length === 0) {
|
||||
this.log('Client gave bad arguments (%s).', state.host);
|
||||
@ -82,19 +88,20 @@ WSProxy.prototype._handleConnect = function _handleConnect(ws, port, host, nonce
|
||||
}
|
||||
|
||||
if (this.pow) {
|
||||
if (!util.isNumber(nonce)) {
|
||||
if (!util.isU32(nonce)) {
|
||||
this.log('Client did not solve proof of work (%s).', state.host);
|
||||
ws.emit('tcp close');
|
||||
ws.disconnect();
|
||||
return;
|
||||
}
|
||||
|
||||
pow = new BufferWriter();
|
||||
pow.writeU32(nonce);
|
||||
pow.writeBytes(state.snonce);
|
||||
pow.writeU32(port);
|
||||
pow.writeString(host, 'ascii');
|
||||
pow = pow.render();
|
||||
const bw = new BufferWriter();
|
||||
bw.writeU32(nonce);
|
||||
bw.writeBytes(state.snonce);
|
||||
bw.writeU32(port);
|
||||
bw.writeString(host, 'ascii');
|
||||
|
||||
const pow = bw.render();
|
||||
|
||||
if (digest.hash256(pow).compare(this.target) > 0) {
|
||||
this.log('Client did not solve proof of work (%s).', state.host);
|
||||
@ -104,9 +111,10 @@ WSProxy.prototype._handleConnect = function _handleConnect(ws, port, host, nonce
|
||||
}
|
||||
}
|
||||
|
||||
let raw, addr;
|
||||
try {
|
||||
raw = IP.toBuffer(host);
|
||||
host = IP.toString(raw);
|
||||
addr = IP.toString(raw);
|
||||
} catch (e) {
|
||||
this.log('Client gave a bad host: %s (%s).', host, state.host);
|
||||
ws.emit('tcp error', {
|
||||
@ -120,7 +128,7 @@ WSProxy.prototype._handleConnect = function _handleConnect(ws, port, host, nonce
|
||||
if (!IP.isRoutable(raw) || IP.isOnion(raw)) {
|
||||
this.log(
|
||||
'Client is trying to connect to a bad ip: %s (%s).',
|
||||
host, state.host);
|
||||
addr, state.host);
|
||||
ws.emit('tcp error', {
|
||||
message: 'ENETUNREACH',
|
||||
code: 'ENETUNREACH'
|
||||
@ -129,7 +137,7 @@ WSProxy.prototype._handleConnect = function _handleConnect(ws, port, host, nonce
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.ports.indexOf(port) === -1) {
|
||||
if (!this.ports.has(port)) {
|
||||
this.log('Client is connecting to non-whitelist port (%s).', state.host);
|
||||
ws.emit('tcp error', {
|
||||
message: 'ENETUNREACH',
|
||||
@ -139,8 +147,9 @@ WSProxy.prototype._handleConnect = function _handleConnect(ws, port, host, nonce
|
||||
return;
|
||||
}
|
||||
|
||||
let socket;
|
||||
try {
|
||||
socket = state.connect(port, host);
|
||||
socket = state.connect(port, addr);
|
||||
this.log('Connecting to %s (%s).', state.remoteHost, state.host);
|
||||
} catch (e) {
|
||||
this.log(e.message);
|
||||
|
||||
@ -64,12 +64,12 @@ PaymentDetails.prototype.fromOptions = function fromOptions(options) {
|
||||
}
|
||||
|
||||
if (options.time != null) {
|
||||
assert(util.isNumber(options.time));
|
||||
assert(util.isInt(options.time));
|
||||
this.time = options.time;
|
||||
}
|
||||
|
||||
if (options.expires != null) {
|
||||
assert(util.isNumber(options.expires));
|
||||
assert(util.isInt(options.expires));
|
||||
this.expires = options.expires;
|
||||
}
|
||||
|
||||
|
||||
@ -50,7 +50,7 @@ function PaymentRequest(options) {
|
||||
|
||||
PaymentRequest.prototype.fromOptions = function fromOptions(options) {
|
||||
if (options.version != null) {
|
||||
assert(util.isNumber(options.version));
|
||||
assert(util.isInt(options.version));
|
||||
this.version = options.version;
|
||||
}
|
||||
|
||||
|
||||
@ -2455,12 +2455,12 @@ ChainOptions.prototype.fromOptions = function fromOptions(options) {
|
||||
}
|
||||
|
||||
if (options.maxFiles != null) {
|
||||
assert(util.isNumber(options.maxFiles));
|
||||
assert(util.isU32(options.maxFiles));
|
||||
this.maxFiles = options.maxFiles;
|
||||
}
|
||||
|
||||
if (options.cacheSize != null) {
|
||||
assert(util.isNumber(options.cacheSize));
|
||||
assert(util.isU64(options.cacheSize));
|
||||
this.cacheSize = options.cacheSize;
|
||||
}
|
||||
|
||||
@ -2500,17 +2500,17 @@ ChainOptions.prototype.fromOptions = function fromOptions(options) {
|
||||
}
|
||||
|
||||
if (options.coinCache != null) {
|
||||
assert(util.isNumber(options.coinCache));
|
||||
assert(util.isU64(options.coinCache));
|
||||
this.coinCache = options.coinCache;
|
||||
}
|
||||
|
||||
if (options.entryCache != null) {
|
||||
assert(util.isNumber(options.entryCache));
|
||||
assert(util.isU32(options.entryCache));
|
||||
this.entryCache = options.entryCache;
|
||||
}
|
||||
|
||||
if (options.maxOrphans != null) {
|
||||
assert(util.isNumber(options.maxOrphans));
|
||||
assert(util.isU32(options.maxOrphans));
|
||||
this.maxOrphans = options.maxOrphans;
|
||||
}
|
||||
|
||||
|
||||
@ -56,7 +56,7 @@ function ChainEntry(chain, options, prev) {
|
||||
this.time = 0;
|
||||
this.bits = 0;
|
||||
this.nonce = 0;
|
||||
this.height = -1;
|
||||
this.height = 0;
|
||||
this.chainwork = ZERO;
|
||||
|
||||
if (options)
|
||||
@ -88,12 +88,13 @@ ChainEntry.MEDIAN_TIMESPAN = 11;
|
||||
ChainEntry.prototype.fromOptions = function fromOptions(options, prev) {
|
||||
assert(options, 'Block data is required.');
|
||||
assert(typeof options.hash === 'string');
|
||||
assert(util.isNumber(options.version));
|
||||
assert(util.isU32(options.version));
|
||||
assert(typeof options.prevBlock === 'string');
|
||||
assert(typeof options.merkleRoot === 'string');
|
||||
assert(util.isNumber(options.time));
|
||||
assert(util.isNumber(options.bits));
|
||||
assert(util.isNumber(options.nonce));
|
||||
assert(util.isU32(options.time));
|
||||
assert(util.isU32(options.bits));
|
||||
assert(util.isU32(options.nonce));
|
||||
assert(util.isU32(options.height));
|
||||
assert(!options.chainwork || BN.isBN(options.chainwork));
|
||||
|
||||
this.hash = options.hash;
|
||||
@ -104,7 +105,7 @@ ChainEntry.prototype.fromOptions = function fromOptions(options, prev) {
|
||||
this.bits = options.bits;
|
||||
this.nonce = options.nonce;
|
||||
this.height = options.height;
|
||||
this.chainwork = options.chainwork;
|
||||
this.chainwork = options.chainwork || ZERO;
|
||||
|
||||
if (!this.chainwork)
|
||||
this.chainwork = this.getChainwork(prev);
|
||||
|
||||
@ -371,10 +371,8 @@ Amount.encode = function encode(value, exp, num) {
|
||||
*/
|
||||
|
||||
Amount.decode = function decode(str, exp, num) {
|
||||
if (num && typeof str === 'number') {
|
||||
assert(util.isNumber(str), 'Non-BTC value for conversion.');
|
||||
if (num && typeof str === 'number')
|
||||
str = str.toString(10);
|
||||
}
|
||||
|
||||
return util.fromFixed(str, exp);
|
||||
};
|
||||
|
||||
@ -77,7 +77,7 @@ Mnemonic.prototype.fromOptions = function fromOptions(options) {
|
||||
options = { phrase: options };
|
||||
|
||||
if (options.bits != null) {
|
||||
assert(util.isNumber(options.bits));
|
||||
assert(util.isU16(options.bits));
|
||||
assert(options.bits >= common.MIN_ENTROPY);
|
||||
assert(options.bits <= common.MAX_ENTROPY);
|
||||
assert(options.bits % 32 === 0);
|
||||
@ -377,7 +377,7 @@ Mnemonic.prototype.toJSON = function toJSON() {
|
||||
*/
|
||||
|
||||
Mnemonic.prototype.fromJSON = function fromJSON(json) {
|
||||
assert(util.isNumber(json.bits));
|
||||
assert(util.isU16(json.bits));
|
||||
assert(typeof json.language === 'string');
|
||||
assert(typeof json.entropy === 'string');
|
||||
assert(typeof json.phrase === 'string');
|
||||
|
||||
@ -70,10 +70,9 @@ function HDPrivateKey(options) {
|
||||
|
||||
HDPrivateKey.prototype.fromOptions = function fromOptions(options) {
|
||||
assert(options, 'No options for HD private key.');
|
||||
assert(util.isNumber(options.depth));
|
||||
assert(options.depth >= 0 && options.depth <= 0xff);
|
||||
assert(util.isU8(options.depth));
|
||||
assert(Buffer.isBuffer(options.parentFingerPrint));
|
||||
assert(util.isNumber(options.childIndex));
|
||||
assert(util.isU32(options.childIndex));
|
||||
assert(Buffer.isBuffer(options.chainCode));
|
||||
assert(Buffer.isBuffer(options.privateKey));
|
||||
|
||||
@ -258,7 +257,7 @@ HDPrivateKey.prototype.getID = function getID(index) {
|
||||
*/
|
||||
|
||||
HDPrivateKey.prototype.deriveBIP44 = function deriveBIP44(account, bip48) {
|
||||
assert(util.isNumber(account), 'Account index must be a number.');
|
||||
assert(util.isU32(account), 'Account index must be a number.');
|
||||
assert(this.isMaster(), 'Cannot derive account index.');
|
||||
return this
|
||||
.derive(bip48 ? 48 : 44, true)
|
||||
|
||||
@ -64,10 +64,9 @@ function HDPublicKey(options) {
|
||||
|
||||
HDPublicKey.prototype.fromOptions = function fromOptions(options) {
|
||||
assert(options, 'No options for HDPublicKey');
|
||||
assert(util.isNumber(options.depth));
|
||||
assert(options.depth >= 0 && options.depth <= 0xff);
|
||||
assert(util.isU8(options.depth));
|
||||
assert(Buffer.isBuffer(options.parentFingerPrint));
|
||||
assert(util.isNumber(options.childIndex));
|
||||
assert(util.isU32(options.childIndex));
|
||||
assert(Buffer.isBuffer(options.chainCode));
|
||||
assert(Buffer.isBuffer(options.publicKey));
|
||||
|
||||
|
||||
@ -427,7 +427,7 @@ MinerOptions.prototype.fromOptions = function fromOptions(options) {
|
||||
}
|
||||
|
||||
if (options.version != null) {
|
||||
assert(util.isNumber(options.version));
|
||||
assert(util.isInt(options.version));
|
||||
this.version = options.version;
|
||||
}
|
||||
|
||||
@ -461,41 +461,41 @@ MinerOptions.prototype.fromOptions = function fromOptions(options) {
|
||||
}
|
||||
|
||||
if (options.minWeight != null) {
|
||||
assert(util.isNumber(options.minWeight));
|
||||
assert(util.isU32(options.minWeight));
|
||||
this.minWeight = options.minWeight;
|
||||
}
|
||||
|
||||
if (options.maxWeight != null) {
|
||||
assert(util.isNumber(options.maxWeight));
|
||||
assert(util.isU32(options.maxWeight));
|
||||
assert(options.maxWeight <= consensus.MAX_BLOCK_WEIGHT,
|
||||
'Max weight must be below MAX_BLOCK_WEIGHT');
|
||||
this.maxWeight = options.maxWeight;
|
||||
}
|
||||
|
||||
if (options.maxSigops != null) {
|
||||
assert(util.isNumber(options.maxSigops));
|
||||
assert(util.isU32(options.maxSigops));
|
||||
assert(options.maxSigops <= consensus.MAX_BLOCK_SIGOPS_COST,
|
||||
'Max sigops must be below MAX_BLOCK_SIGOPS_COST');
|
||||
this.maxSigops = options.maxSigops;
|
||||
}
|
||||
|
||||
if (options.priorityWeight != null) {
|
||||
assert(util.isNumber(options.priorityWeight));
|
||||
assert(util.isU32(options.priorityWeight));
|
||||
this.priorityWeight = options.priorityWeight;
|
||||
}
|
||||
|
||||
if (options.priorityThreshold != null) {
|
||||
assert(util.isNumber(options.priorityThreshold));
|
||||
assert(util.isU32(options.priorityThreshold));
|
||||
this.priorityThreshold = options.priorityThreshold;
|
||||
}
|
||||
|
||||
if (options.reservedWeight != null) {
|
||||
assert(util.isNumber(options.reservedWeight));
|
||||
assert(util.isU32(options.reservedWeight));
|
||||
this.reservedWeight = options.reservedWeight;
|
||||
}
|
||||
|
||||
if (options.reservedSigops != null) {
|
||||
assert(util.isNumber(options.reservedSigops));
|
||||
assert(util.isU32(options.reservedSigops));
|
||||
this.reservedSigops = options.reservedSigops;
|
||||
}
|
||||
|
||||
|
||||
@ -1374,13 +1374,13 @@ HostEntry.prototype.fromJSON = function fromJSON(json, network) {
|
||||
assert(typeof json.services === 'string');
|
||||
assert(json.services.length > 0);
|
||||
assert(json.services.length <= 32);
|
||||
this.addr.services = parseInt(json.services, 2);
|
||||
assert(util.isU32(this.addr.services));
|
||||
const services = parseInt(json.services, 2);
|
||||
assert(util.isU32(services));
|
||||
this.addr.services = services;
|
||||
}
|
||||
|
||||
if (json.time != null) {
|
||||
assert(util.isNumber(json.time));
|
||||
assert(json.time >= 0);
|
||||
assert(util.isU64(json.time));
|
||||
this.addr.time = json.time;
|
||||
}
|
||||
|
||||
@ -1390,20 +1390,17 @@ HostEntry.prototype.fromJSON = function fromJSON(json, network) {
|
||||
}
|
||||
|
||||
if (json.attempts != null) {
|
||||
assert(util.isNumber(json.attempts));
|
||||
assert(json.attempts >= 0);
|
||||
assert(util.isU64(json.attempts));
|
||||
this.attempts = json.attempts;
|
||||
}
|
||||
|
||||
if (json.lastSuccess != null) {
|
||||
assert(util.isNumber(json.lastSuccess));
|
||||
assert(json.lastSuccess >= 0);
|
||||
assert(util.isU64(json.lastSuccess));
|
||||
this.lastSuccess = json.lastSuccess;
|
||||
}
|
||||
|
||||
if (json.lastAttempt != null) {
|
||||
assert(util.isNumber(json.lastAttempt));
|
||||
assert(json.lastAttempt >= 0);
|
||||
assert(util.isU64(json.lastAttempt));
|
||||
this.lastAttempt = json.lastAttempt;
|
||||
}
|
||||
|
||||
|
||||
@ -202,9 +202,14 @@ Config.prototype.get = function get(key, fallback) {
|
||||
|
||||
if (typeof key === 'number') {
|
||||
assert(key >= 0, 'Index must be positive.');
|
||||
|
||||
if (key >= this.argv.length)
|
||||
return fallback;
|
||||
return this.argv[key];
|
||||
|
||||
if (this.argv[key] != null)
|
||||
return this.argv[key];
|
||||
|
||||
return fallback;
|
||||
}
|
||||
|
||||
assert(typeof key === 'string', 'Key must be a string.');
|
||||
@ -232,6 +237,21 @@ Config.prototype.get = function get(key, fallback) {
|
||||
return fallback;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get a value's type.
|
||||
* @param {String} key
|
||||
* @returns {String}
|
||||
*/
|
||||
|
||||
Config.prototype.typeOf = function typeOf(key) {
|
||||
const value = this.get(key);
|
||||
|
||||
if (value === null)
|
||||
return 'null';
|
||||
|
||||
return typeof value;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get a config option (as a string).
|
||||
* @param {String} key
|
||||
@ -275,10 +295,7 @@ Config.prototype.int = function int(key, fallback) {
|
||||
throw new Error(`${fmt(key)} must be an int.`);
|
||||
|
||||
if (!Number.isSafeInteger(value))
|
||||
throw new Error(`${fmt(key)} must be an int (53 bit max).`);
|
||||
|
||||
if (value % 1 !== 0)
|
||||
throw new Error(`${fmt(key)} must be an int (float).`);
|
||||
throw new Error(`${fmt(key)} must be an int.`);
|
||||
|
||||
return value;
|
||||
}
|
||||
@ -289,7 +306,7 @@ Config.prototype.int = function int(key, fallback) {
|
||||
value = parseInt(value, 10);
|
||||
|
||||
if (!Number.isSafeInteger(value))
|
||||
throw new Error(`${fmt(key)} must be an int (53 bit max).`);
|
||||
throw new Error(`${fmt(key)} must be an int.`);
|
||||
|
||||
return value;
|
||||
};
|
||||
@ -441,6 +458,15 @@ Config.prototype.bool = function bool(key, fallback) {
|
||||
if (value === null)
|
||||
return fallback;
|
||||
|
||||
// Bitcoin Core compat.
|
||||
if (typeof value === 'number') {
|
||||
if (value === 1)
|
||||
return true;
|
||||
|
||||
if (value === 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (typeof value !== 'string') {
|
||||
if (typeof value !== 'boolean')
|
||||
throw new Error(`${fmt(key)} must be a boolean.`);
|
||||
@ -484,7 +510,7 @@ Config.prototype.buf = function buf(key, fallback, enc) {
|
||||
const data = Buffer.from(value, enc);
|
||||
|
||||
if (data.length !== Buffer.byteLength(value, enc))
|
||||
throw new Error(`${fmt(key)} must be a hex string.`);
|
||||
throw new Error(`${fmt(key)} must be a ${enc} string.`);
|
||||
|
||||
return data;
|
||||
};
|
||||
@ -540,7 +566,7 @@ Config.prototype.obj = function obj(key, fallback) {
|
||||
if (value === null)
|
||||
return fallback;
|
||||
|
||||
if (!value || typeof value !== 'object')
|
||||
if (typeof value !== 'object')
|
||||
throw new Error(`${fmt(key)} must be an object.`);
|
||||
|
||||
return value;
|
||||
|
||||
@ -57,12 +57,12 @@ function AbstractBlock() {
|
||||
|
||||
AbstractBlock.prototype.parseOptions = function parseOptions(options) {
|
||||
assert(options, 'Block data is required.');
|
||||
assert(util.isNumber(options.version));
|
||||
assert(util.isU32(options.version));
|
||||
assert(typeof options.prevBlock === 'string');
|
||||
assert(typeof options.merkleRoot === 'string');
|
||||
assert(util.isNumber(options.time));
|
||||
assert(util.isNumber(options.bits));
|
||||
assert(util.isNumber(options.nonce));
|
||||
assert(util.isU32(options.time));
|
||||
assert(util.isU32(options.bits));
|
||||
assert(util.isU32(options.nonce));
|
||||
|
||||
this.version = options.version;
|
||||
this.prevBlock = options.prevBlock;
|
||||
@ -85,12 +85,12 @@ AbstractBlock.prototype.parseOptions = function parseOptions(options) {
|
||||
|
||||
AbstractBlock.prototype.parseJSON = function parseJSON(json) {
|
||||
assert(json, 'Block data is required.');
|
||||
assert(util.isNumber(json.version));
|
||||
assert(util.isU32(json.version));
|
||||
assert(typeof json.prevBlock === 'string');
|
||||
assert(typeof json.merkleRoot === 'string');
|
||||
assert(util.isNumber(json.time));
|
||||
assert(util.isNumber(json.bits));
|
||||
assert(util.isNumber(json.nonce));
|
||||
assert(util.isU32(json.time));
|
||||
assert(util.isU32(json.bits));
|
||||
assert(util.isU32(json.nonce));
|
||||
|
||||
this.version = json.version;
|
||||
this.prevBlock = util.revHex(json.prevBlock);
|
||||
|
||||
@ -579,8 +579,8 @@ Address.prototype.fromHash = function fromHash(hash, type, version, network) {
|
||||
network = Network.get(network);
|
||||
|
||||
assert(Buffer.isBuffer(hash));
|
||||
assert(util.isNumber(type));
|
||||
assert(util.isNumber(version));
|
||||
assert(util.isU8(type));
|
||||
assert(util.isI8(version));
|
||||
|
||||
assert(type >= Address.types.PUBKEYHASH && type <= Address.types.WITNESS,
|
||||
'Not a valid address type.');
|
||||
|
||||
@ -1519,37 +1519,36 @@ CoinSelector.prototype.fromOptions = function fromOptions(options) {
|
||||
}
|
||||
|
||||
if (options.height != null) {
|
||||
assert(util.isNumber(options.height));
|
||||
assert(util.isInt(options.height));
|
||||
assert(options.height >= -1);
|
||||
this.height = options.height;
|
||||
}
|
||||
|
||||
if (options.confirmations != null) {
|
||||
assert(util.isNumber(options.confirmations));
|
||||
assert(util.isInt(options.confirmations));
|
||||
assert(options.confirmations >= -1);
|
||||
this.depth = options.confirmations;
|
||||
}
|
||||
|
||||
if (options.depth != null) {
|
||||
assert(util.isNumber(options.depth));
|
||||
assert(util.isInt(options.depth));
|
||||
assert(options.depth >= -1);
|
||||
this.depth = options.depth;
|
||||
}
|
||||
|
||||
if (options.hardFee != null) {
|
||||
assert(util.isNumber(options.hardFee));
|
||||
assert(util.isInt(options.hardFee));
|
||||
assert(options.hardFee >= -1);
|
||||
this.hardFee = options.hardFee;
|
||||
}
|
||||
|
||||
if (options.rate != null) {
|
||||
assert(util.isNumber(options.rate));
|
||||
assert(options.rate >= 0);
|
||||
assert(util.isU64(options.rate));
|
||||
this.rate = options.rate;
|
||||
}
|
||||
|
||||
if (options.maxFee != null) {
|
||||
assert(util.isNumber(options.maxFee));
|
||||
assert(util.isInt(options.maxFee));
|
||||
assert(options.maxFee >= -1);
|
||||
this.maxFee = options.maxFee;
|
||||
}
|
||||
|
||||
@ -439,10 +439,9 @@ NetAddress.prototype.toJSON = function toJSON() {
|
||||
*/
|
||||
|
||||
NetAddress.prototype.fromJSON = function fromJSON(json) {
|
||||
assert(util.isNumber(json.port));
|
||||
assert(json.port >= 0 && json.port <= 0xffff);
|
||||
assert(util.isNumber(json.services));
|
||||
assert(util.isNumber(json.time));
|
||||
assert(util.isU16(json.port));
|
||||
assert(util.isU32(json.services));
|
||||
assert(util.isU32(json.time));
|
||||
this.raw = IP.toBuffer(json.host);
|
||||
this.host = json.host;
|
||||
this.port = json.port;
|
||||
|
||||
@ -28,7 +28,7 @@ function TXMeta(options) {
|
||||
this.height = -1;
|
||||
this.block = null;
|
||||
this.time = 0;
|
||||
this.index = 0;
|
||||
this.index = -1;
|
||||
|
||||
if (options)
|
||||
this.fromOptions(options);
|
||||
@ -47,12 +47,12 @@ TXMeta.prototype.fromOptions = function fromOptions(options) {
|
||||
}
|
||||
|
||||
if (options.mtime != null) {
|
||||
assert(util.isNumber(options.mtime));
|
||||
assert(util.isU32(options.mtime));
|
||||
this.mtime = options.mtime;
|
||||
}
|
||||
|
||||
if (options.height != null) {
|
||||
assert(util.isNumber(options.height));
|
||||
assert(util.isInt(options.height));
|
||||
this.height = options.height;
|
||||
}
|
||||
|
||||
@ -62,12 +62,12 @@ TXMeta.prototype.fromOptions = function fromOptions(options) {
|
||||
}
|
||||
|
||||
if (options.time != null) {
|
||||
assert(util.isNumber(options.time));
|
||||
assert(util.isU32(options.time));
|
||||
this.time = options.time;
|
||||
}
|
||||
|
||||
if (options.index != null) {
|
||||
assert(util.isNumber(options.index));
|
||||
assert(util.isInt(options.index));
|
||||
this.index = options.index;
|
||||
}
|
||||
|
||||
@ -169,11 +169,11 @@ TXMeta.prototype.getJSON = function getJSON(network, view) {
|
||||
TXMeta.prototype.fromJSON = function fromJSON(json) {
|
||||
this.tx.fromJSON(json);
|
||||
|
||||
assert(util.isNumber(json.mtime));
|
||||
assert(util.isNumber(json.height));
|
||||
assert(util.isU32(json.mtime));
|
||||
assert(util.isInt(json.height));
|
||||
assert(!json.block || typeof json.block === 'string');
|
||||
assert(util.isNumber(json.time));
|
||||
assert(util.isNumber(json.index));
|
||||
assert(util.isU32(json.time));
|
||||
assert(util.isInt(json.index));
|
||||
|
||||
this.mtime = json.mtime;
|
||||
this.height = json.height;
|
||||
|
||||
@ -758,8 +758,10 @@ exports.num = function num(value, minimal, size) {
|
||||
*/
|
||||
|
||||
exports.array = function array(value) {
|
||||
if (util.isNumber(value))
|
||||
if (typeof value === 'number') {
|
||||
assert(util.isInt(value));
|
||||
value = new BN(value);
|
||||
}
|
||||
|
||||
assert(BN.isBN(value));
|
||||
|
||||
|
||||
@ -357,7 +357,7 @@ Opcode.fromNumber = function fromNumber(num) {
|
||||
*/
|
||||
|
||||
Opcode.fromSmall = function fromSmall(num) {
|
||||
assert(util.isNumber(num) && num >= 0 && num <= 16);
|
||||
assert(util.isU8(num) && num >= 0 && num <= 16);
|
||||
return Opcode.fromOp(num === 0 ? 0 : num + 0x50);
|
||||
};
|
||||
|
||||
|
||||
@ -29,9 +29,9 @@ function Program(version, data) {
|
||||
if (!(this instanceof Program))
|
||||
return new Program(version, data);
|
||||
|
||||
assert(util.isNumber(version));
|
||||
assert(Buffer.isBuffer(data));
|
||||
assert(util.isU8(version));
|
||||
assert(version >= 0 && version <= 16);
|
||||
assert(Buffer.isBuffer(data));
|
||||
assert(data.length >= 2 && data.length <= 40);
|
||||
|
||||
this.version = version;
|
||||
|
||||
@ -1470,7 +1470,7 @@ Script.fromPubkeyhash = function fromPubkeyhash(hash) {
|
||||
*/
|
||||
|
||||
Script.prototype.fromMultisig = function fromMultisig(m, n, keys) {
|
||||
assert(util.isNumber(m) && util.isNumber(n));
|
||||
assert(util.isU8(m) && util.isU8(n));
|
||||
assert(Array.isArray(keys));
|
||||
assert(keys.length === n, '`n` keys are required for multisig.');
|
||||
assert(m >= 1 && m <= n);
|
||||
@ -1570,7 +1570,7 @@ Script.fromNulldata = function fromNulldata(flags) {
|
||||
*/
|
||||
|
||||
Script.prototype.fromProgram = function fromProgram(version, data) {
|
||||
assert(util.isNumber(version) && version >= 0 && version <= 16);
|
||||
assert(util.isU8(version) && version >= 0 && version <= 16);
|
||||
assert(Buffer.isBuffer(data) && data.length >= 2 && data.length <= 40);
|
||||
|
||||
const op = Opcode.fromSmall(version);
|
||||
|
||||
@ -27,8 +27,7 @@ function SigCache(size) {
|
||||
if (size == null)
|
||||
size = 10000;
|
||||
|
||||
assert(util.isNumber(size));
|
||||
assert(size >= 0);
|
||||
assert(util.isU32(size));
|
||||
|
||||
this.size = size;
|
||||
this.keys = [];
|
||||
@ -41,8 +40,7 @@ function SigCache(size) {
|
||||
*/
|
||||
|
||||
SigCache.prototype.resize = function resize(size) {
|
||||
assert(util.isNumber(size));
|
||||
assert(size >= 0);
|
||||
assert(util.isU32(size));
|
||||
|
||||
this.size = size;
|
||||
this.keys.length = 0;
|
||||
|
||||
@ -152,7 +152,7 @@ AsyncEmitter.prototype.removeListener = function removeListener(type, handler) {
|
||||
AsyncEmitter.prototype.setMaxListeners = function setMaxListeners(max) {
|
||||
assert(typeof max === 'number', '`max` must be a number.');
|
||||
assert(max >= 0, '`max` must be non-negative.');
|
||||
assert(max % 1 === 0, '`max` must be an integer.');
|
||||
assert(Number.isSafeInteger(max), '`max` must be an integer.');
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -119,7 +119,7 @@ Bloom.flagsByVal = {
|
||||
Bloom.prototype.fromOptions = function fromOptions(size, n, tweak, update) {
|
||||
assert(typeof size === 'number', '`size` must be a number.');
|
||||
assert(size > 0, '`size` must be greater than zero.');
|
||||
assert(size % 1 === 0, '`size` must be an integer.');
|
||||
assert(Number.isSafeInteger(size), '`size` must be an integer.');
|
||||
|
||||
size -= size % 8;
|
||||
|
||||
@ -139,9 +139,9 @@ Bloom.prototype.fromOptions = function fromOptions(size, n, tweak, update) {
|
||||
|
||||
assert(size > 0, '`size` must be greater than zero.');
|
||||
assert(n > 0, '`n` must be greater than zero.');
|
||||
assert(n % 1 === 0, '`n` must be an integer.');
|
||||
assert(Number.isSafeInteger(n), '`n` must be an integer.');
|
||||
assert(typeof tweak === 'number', '`tweak` must be a number.');
|
||||
assert(tweak % 1 === 0, '`tweak` must be an integer.');
|
||||
assert(Number.isSafeInteger(tweak), '`tweak` must be an integer.');
|
||||
assert(Bloom.flagsByVal[update], 'Unknown update flag.');
|
||||
|
||||
this.filter = filter;
|
||||
@ -258,7 +258,7 @@ Bloom.prototype.added = function added(val, enc) {
|
||||
Bloom.fromRate = function fromRate(items, rate, update) {
|
||||
assert(typeof items === 'number', '`items` must be a number.');
|
||||
assert(items > 0, '`items` must be greater than zero.');
|
||||
assert(items % 1 === 0, '`items` must be an integer.');
|
||||
assert(Number.isSafeInteger(items), '`items` must be an integer.');
|
||||
assert(typeof rate === 'number', '`rate` must be a number.');
|
||||
assert(rate >= 0 && rate <= 1, '`rate` must be between 0.0 and 1.0.');
|
||||
|
||||
|
||||
@ -12,6 +12,7 @@
|
||||
*/
|
||||
|
||||
const BN = require('bn.js');
|
||||
const util = require('./util');
|
||||
const MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER;
|
||||
const encoding = exports;
|
||||
|
||||
@ -1037,7 +1038,7 @@ encoding.EncodingError = function EncodingError(offset, reason) {
|
||||
Error.captureStackTrace(this, EncodingError);
|
||||
};
|
||||
|
||||
inherits(encoding.EncodingError, Error);
|
||||
util.inherits(encoding.EncodingError, Error);
|
||||
|
||||
/*
|
||||
* Helpers
|
||||
@ -1048,15 +1049,6 @@ function Varint(size, value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
function inherits(child, parent) {
|
||||
child.super_ = parent;
|
||||
Object.setPrototypeOf(child.prototype, parent.prototype);
|
||||
Object.defineProperty(child.prototype, 'constructor', {
|
||||
value: child,
|
||||
enumerable: false
|
||||
});
|
||||
}
|
||||
|
||||
function enforce(value, offset, reason) {
|
||||
if (!value)
|
||||
throw new encoding.EncodingError(offset, reason);
|
||||
|
||||
@ -50,7 +50,7 @@ function RollingFilter(items, rate) {
|
||||
RollingFilter.prototype.fromRate = function fromRate(items, rate) {
|
||||
assert(typeof items === 'number', '`items` must be a number.');
|
||||
assert(items > 0, '`items` must be greater than zero.');
|
||||
assert(items % 1 === 0, '`items` must be an integer.');
|
||||
assert(Number.isSafeInteger(items), '`items` must be an integer.');
|
||||
assert(typeof rate === 'number', '`rate` must be a number.');
|
||||
assert(rate >= 0 && rate <= 1, '`rate` must be between 0.0 and 1.0.');
|
||||
|
||||
|
||||
@ -38,7 +38,10 @@ const inspectOptions = {
|
||||
*/
|
||||
|
||||
util.isNumber = function isNumber(value) {
|
||||
return Number.isSafeInteger(value);
|
||||
return typeof value === 'number'
|
||||
&& isFinite(value)
|
||||
&& value >= -Number.MAX_SAFE_INTEGER
|
||||
&& value <= Number.MAX_SAFE_INTEGER;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -48,11 +51,11 @@ util.isNumber = function isNumber(value) {
|
||||
*/
|
||||
|
||||
util.isInt = function isInt(value) {
|
||||
return util.isNumber(value) && value % 1 === 0;
|
||||
return Number.isSafeInteger(value);
|
||||
};
|
||||
|
||||
/**
|
||||
* Test whether an object is an int.
|
||||
* Test whether an object is a uint.
|
||||
* @param {Number?} value
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
@ -844,7 +847,7 @@ util.memoryUsage = function memoryUsage() {
|
||||
|
||||
util.toFixed = function toFixed(num, exp) {
|
||||
assert(typeof num === 'number');
|
||||
assert(Number.isSafeInteger(num) && num % 1 === 0, 'Invalid integer value.');
|
||||
assert(Number.isSafeInteger(num), 'Invalid integer value.');
|
||||
|
||||
let sign = '';
|
||||
|
||||
|
||||
@ -97,6 +97,21 @@ Validator.prototype.get = function get(key, fallback) {
|
||||
return fallback;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get a value's type.
|
||||
* @param {String} key
|
||||
* @returns {String}
|
||||
*/
|
||||
|
||||
Validator.prototype.typeOf = function typeOf(key) {
|
||||
const value = this.get(key);
|
||||
|
||||
if (value == null)
|
||||
return 'null';
|
||||
|
||||
return typeof value;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get a value (as a string).
|
||||
* @param {String} key
|
||||
@ -140,10 +155,7 @@ Validator.prototype.int = function int(key, fallback) {
|
||||
throw new ValidationError(key, 'int');
|
||||
|
||||
if (!Number.isSafeInteger(value))
|
||||
throw new ValidationError(key, 'int (53 bit max)');
|
||||
|
||||
if (value % 1 !== 0)
|
||||
throw new ValidationError(key, 'int (float)');
|
||||
throw new ValidationError(key, 'int');
|
||||
|
||||
return value;
|
||||
}
|
||||
@ -154,7 +166,7 @@ Validator.prototype.int = function int(key, fallback) {
|
||||
value = parseInt(value, 10);
|
||||
|
||||
if (!Number.isSafeInteger(value))
|
||||
throw new ValidationError(key, 'int (53 bit max)');
|
||||
throw new ValidationError(key, 'int');
|
||||
|
||||
return value;
|
||||
};
|
||||
@ -492,15 +504,9 @@ Validator.prototype.hash = function hash(key, fallback) {
|
||||
*/
|
||||
|
||||
Validator.prototype.numhash = function numhash(key, fallback) {
|
||||
const value = this.get(key);
|
||||
|
||||
if (value === null)
|
||||
return fallback;
|
||||
|
||||
if (typeof value === 'string')
|
||||
return this.hash(key);
|
||||
|
||||
return this.uint(key);
|
||||
if (this.typeOf(key) === 'string')
|
||||
return this.hash(key, fallback);
|
||||
return this.uint(key, fallback);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -519,14 +525,14 @@ Validator.prototype.bool = function bool(key, fallback) {
|
||||
if (value === null)
|
||||
return fallback;
|
||||
|
||||
// Bitcoin Core mixes semantics of truthiness
|
||||
// amoung rpc methods most "verbose" parameters
|
||||
// are bools, but getrawtransaction is 1/0.
|
||||
if (value === 1)
|
||||
return true;
|
||||
// Bitcoin Core compat.
|
||||
if (typeof value === 'number') {
|
||||
if (value === 1)
|
||||
return true;
|
||||
|
||||
if (value === 0)
|
||||
return false;
|
||||
if (value === 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (typeof value !== 'string') {
|
||||
if (typeof value !== 'boolean')
|
||||
@ -628,7 +634,7 @@ Validator.prototype.obj = function obj(key, fallback) {
|
||||
if (value === null)
|
||||
return fallback;
|
||||
|
||||
if (!value || typeof value !== 'object')
|
||||
if (typeof value !== 'object')
|
||||
throw new ValidationError(key, 'object');
|
||||
|
||||
return value;
|
||||
|
||||
@ -105,10 +105,10 @@ Account.typesByVal = {
|
||||
|
||||
Account.prototype.fromOptions = function fromOptions(options) {
|
||||
assert(options, 'Options are required.');
|
||||
assert(util.isNumber(options.wid));
|
||||
assert(util.isU32(options.wid));
|
||||
assert(common.isName(options.id), 'Bad Wallet ID.');
|
||||
assert(HD.isHD(options.accountKey), 'Account key is required.');
|
||||
assert(util.isNumber(options.accountIndex), 'Account index is required.');
|
||||
assert(util.isU32(options.accountIndex), 'Account index is required.');
|
||||
|
||||
this.wid = options.wid;
|
||||
this.id = options.id;
|
||||
@ -145,37 +145,37 @@ Account.prototype.fromOptions = function fromOptions(options) {
|
||||
}
|
||||
|
||||
if (options.m != null) {
|
||||
assert(util.isNumber(options.m));
|
||||
assert(util.isU8(options.m));
|
||||
this.m = options.m;
|
||||
}
|
||||
|
||||
if (options.n != null) {
|
||||
assert(util.isNumber(options.n));
|
||||
assert(util.isU8(options.n));
|
||||
this.n = options.n;
|
||||
}
|
||||
|
||||
if (options.accountIndex != null) {
|
||||
assert(util.isNumber(options.accountIndex));
|
||||
assert(util.isU32(options.accountIndex));
|
||||
this.accountIndex = options.accountIndex;
|
||||
}
|
||||
|
||||
if (options.receiveDepth != null) {
|
||||
assert(util.isNumber(options.receiveDepth));
|
||||
assert(util.isU32(options.receiveDepth));
|
||||
this.receiveDepth = options.receiveDepth;
|
||||
}
|
||||
|
||||
if (options.changeDepth != null) {
|
||||
assert(util.isNumber(options.changeDepth));
|
||||
assert(util.isU32(options.changeDepth));
|
||||
this.changeDepth = options.changeDepth;
|
||||
}
|
||||
|
||||
if (options.nestedDepth != null) {
|
||||
assert(util.isNumber(options.nestedDepth));
|
||||
assert(util.isU32(options.nestedDepth));
|
||||
this.nestedDepth = options.nestedDepth;
|
||||
}
|
||||
|
||||
if (options.lookahead != null) {
|
||||
assert(util.isNumber(options.lookahead));
|
||||
assert(util.isU32(options.lookahead));
|
||||
assert(options.lookahead >= 0);
|
||||
assert(options.lookahead <= Account.MAX_LOOKAHEAD);
|
||||
this.lookahead = options.lookahead;
|
||||
|
||||
@ -129,22 +129,22 @@ MasterKey.prototype.fromOptions = function fromOptions(options) {
|
||||
}
|
||||
|
||||
if (options.rounds != null) {
|
||||
assert(util.isNumber(options.rounds));
|
||||
assert(util.isU32(options.rounds));
|
||||
this.N = options.rounds;
|
||||
}
|
||||
|
||||
if (options.N != null) {
|
||||
assert(util.isNumber(options.N));
|
||||
assert(util.isU32(options.N));
|
||||
this.N = options.N;
|
||||
}
|
||||
|
||||
if (options.r != null) {
|
||||
assert(util.isNumber(options.r));
|
||||
assert(util.isU32(options.r));
|
||||
this.r = options.r;
|
||||
}
|
||||
|
||||
if (options.p != null) {
|
||||
assert(util.isNumber(options.p));
|
||||
assert(util.isU32(options.p));
|
||||
this.p = options.p;
|
||||
}
|
||||
|
||||
|
||||
@ -124,7 +124,7 @@ Wallet.prototype.fromOptions = function fromOptions(options) {
|
||||
this.master.fromKey(key, mnemonic);
|
||||
|
||||
if (options.wid != null) {
|
||||
assert(util.isNumber(options.wid));
|
||||
assert(util.isU32(options.wid));
|
||||
this.wid = options.wid;
|
||||
}
|
||||
|
||||
@ -144,7 +144,7 @@ Wallet.prototype.fromOptions = function fromOptions(options) {
|
||||
}
|
||||
|
||||
if (options.accountDepth != null) {
|
||||
assert(util.isNumber(options.accountDepth));
|
||||
assert(util.isU32(options.accountDepth));
|
||||
this.accountDepth = options.accountDepth;
|
||||
}
|
||||
|
||||
@ -155,7 +155,7 @@ Wallet.prototype.fromOptions = function fromOptions(options) {
|
||||
}
|
||||
|
||||
if (options.tokenDepth != null) {
|
||||
assert(util.isNumber(options.tokenDepth));
|
||||
assert(util.isU32(options.tokenDepth));
|
||||
this.tokenDepth = options.tokenDepth;
|
||||
}
|
||||
|
||||
|
||||
@ -2220,12 +2220,12 @@ WalletOptions.prototype.fromOptions = function fromOptions(options) {
|
||||
}
|
||||
|
||||
if (options.maxFiles != null) {
|
||||
assert(util.isNumber(options.maxFiles));
|
||||
assert(util.isU32(options.maxFiles));
|
||||
this.maxFiles = options.maxFiles;
|
||||
}
|
||||
|
||||
if (options.cacheSize != null) {
|
||||
assert(util.isNumber(options.cacheSize));
|
||||
assert(util.isU64(options.cacheSize));
|
||||
this.cacheSize = options.cacheSize;
|
||||
}
|
||||
|
||||
|
||||
@ -68,14 +68,14 @@ WorkerPool.prototype.set = function set(options) {
|
||||
}
|
||||
|
||||
if (options.size != null) {
|
||||
assert(util.isNumber(options.size));
|
||||
assert(util.isU32(options.size));
|
||||
assert(options.size > 0);
|
||||
this.size = options.size;
|
||||
}
|
||||
|
||||
if (options.timeout != null) {
|
||||
assert(util.isNumber(options.timeout));
|
||||
assert(options.timeout > 0);
|
||||
assert(util.isInt(options.timeout));
|
||||
assert(options.timeout >= -1);
|
||||
this.timeout = options.timeout;
|
||||
}
|
||||
|
||||
|
||||
@ -52,7 +52,7 @@ function Coins(options) {
|
||||
|
||||
Coins.prototype.fromOptions = function fromOptions(options) {
|
||||
if (options.version != null) {
|
||||
assert(util.isNumber(options.version));
|
||||
assert(util.isU32(options.version));
|
||||
this.version = options.version;
|
||||
}
|
||||
|
||||
@ -62,7 +62,7 @@ Coins.prototype.fromOptions = function fromOptions(options) {
|
||||
}
|
||||
|
||||
if (options.height != null) {
|
||||
assert(util.isNumber(options.height));
|
||||
assert(util.isInt(options.height));
|
||||
this.height = options.height;
|
||||
}
|
||||
|
||||
|
||||
@ -64,7 +64,7 @@ Coins.prototype.fromOptions = function fromOptions(options) {
|
||||
}
|
||||
|
||||
if (options.height != null) {
|
||||
assert(util.isNumber(options.height));
|
||||
assert(util.isInt(options.height));
|
||||
this.height = options.height;
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user