bcoin: remove dependence on util.js.

This commit is contained in:
Christopher Jeffrey 2017-10-26 04:07:36 -07:00
parent 1a5782fa06
commit d0ed214067
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
86 changed files with 1673 additions and 1620 deletions

23
bin/cli
View File

@ -3,7 +3,6 @@
'use strict';
const Config = require('../lib/node/config');
const util = require('../lib/utils/util');
const {NodeClient, WalletClient} = require('bclient');
const ports = {
@ -178,9 +177,9 @@ CLI.prototype.getWallet = async function getWallet() {
};
CLI.prototype.getTX = async function getTX() {
const hash = this.config.str(0);
const hash = this.config.str(0, '');
if (util.isBase58(hash) || util.isBech32(hash)) {
if (hash.length !== 64) {
const txs = await this.client.getTXByAddress(hash);
this.log(txs);
return;
@ -197,7 +196,7 @@ CLI.prototype.getTX = async function getTX() {
};
CLI.prototype.getBlock = async function getBlock() {
let hash = this.config.str(0);
let hash = this.config.str(0, '');
if (hash.length !== 64)
hash = parseInt(hash, 10);
@ -213,10 +212,10 @@ CLI.prototype.getBlock = async function getBlock() {
};
CLI.prototype.getCoin = async function getCoin() {
const hash = this.config.str(0);
const hash = this.config.str(0, '');
const index = this.config.uint(1);
if (util.isBase58(hash) || util.isBech32(hash)) {
if (hash.length !== 64) {
const coins = await this.client.getCoinsByAddress(hash);
this.log(coins);
return;
@ -471,19 +470,15 @@ CLI.prototype.importKey = async function importKey() {
if (!key)
throw new Error('No key for import.');
if (util.isBase58(key)) {
await this.wallet.importPrivate(account, key, passphrase);
this.log('Imported private key.');
return;
}
if (util.isHex(key)) {
if (key.length === 66 || key.length === 130) {
await this.wallet.importPublic(account, key);
this.log('Imported public key.');
return;
}
throw new Error('Bad key for import.');
await this.wallet.importPrivate(account, key, passphrase);
this.log('Imported private key.');
};
CLI.prototype.importAddress = async function importAddress() {

View File

@ -6,7 +6,6 @@ process.title = 'bcoin';
const assert = require('assert');
const SPVNode = require('../lib/node/spvnode');
const util = require('../lib/utils/util');
const Outpoint = require('../lib/primitives/outpoint');
const node = SPVNode({
@ -44,7 +43,7 @@ process.on('unhandledRejection', (err, promise) => {
node.on('block', (block) => {
assert(block.txs.length >= 1);
if (block.txs.length > 1)
util.log(block.txs[1]);
console.log(block.txs[1]);
});
}

View File

@ -31,14 +31,15 @@ floating.onmouseup = function(ev) {
};
function show(obj) {
floating.innerHTML = escape(util.inspectify(obj, false));
const json = obj && obj.toJSON ? obj.toJSON() : null;
floating.innerHTML = escape(JSON.stringify(json, null, 2));
floating.style.display = 'block';
}
logger = new bcoin.logger({ level: 'debug', console: true });
logger.writeConsole = function(level, module, args) {
var name = bcoin.logger.levelsByVal[level];
var msg = util.format(args, false);
var msg = this.fmt(args, false);
if (++scrollback > 1000) {
log.innerHTML = '';
scrollback = 1;

View File

@ -4,7 +4,6 @@ const assert = require('assert');
const net = require('net');
const EventEmitter = require('events');
const bsock = require('bsock');
const util = require('../lib/utils/util');
const digest = require('bcrypto/lib/digest');
const IP = require('../lib/utils/ip');
const BufferWriter = require('../lib/utils/writer');
@ -76,7 +75,7 @@ WSProxy.prototype.handleConnect = function handleConnect(ws, port, host, nonce)
return;
}
if (!util.isU16(port)
if ((port & 0xffff) !== port
|| typeof host !== 'string'
|| host.length === 0) {
this.log('Client gave bad arguments (%s).', state.host);
@ -86,7 +85,7 @@ WSProxy.prototype.handleConnect = function handleConnect(ws, port, host, nonce)
}
if (this.pow) {
if (!util.isU32(nonce)) {
if ((nonce >>> 0) !== nonce) {
this.log('Client did not solve proof of work (%s).', state.host);
ws.fire('tcp close');
ws.destroy();
@ -228,7 +227,7 @@ WSProxy.prototype.attach = function attach(server) {
function SocketState(server, socket) {
this.pow = server.pow;
this.target = server.target;
this.snonce = util.nonce();
this.snonce = nonce();
this.socket = null;
this.host = IP.normalize(socket.conn.remoteAddress);
this.remoteHost = null;
@ -248,4 +247,11 @@ SocketState.prototype.connect = function connect(port, host) {
return this.socket;
};
function nonce() {
const buf = Buffer.allocUnsafe(8);
buf.writeUInt32LE(Math.random() * 0x100000000, 0, true);
buf.writeUInt32LE(Math.random() * 0x100000000, 4, true);
return buf;
}
module.exports = WSProxy;

View File

@ -64,12 +64,12 @@ PaymentDetails.prototype.fromOptions = function fromOptions(options) {
}
if (options.time != null) {
assert(util.isInt(options.time));
assert(Number.isSafeInteger(options.time));
this.time = options.time;
}
if (options.expires != null) {
assert(util.isInt(options.expires));
assert(Number.isSafeInteger(options.expires));
this.expires = options.expires;
}

View File

@ -7,10 +7,9 @@
'use strict';
const assert = require('assert');
const util = require('../utils/util');
const digest = require('bcrypto/lib/digest');
const PEM = require('bcrypto/lib/utils/pem');
const x509 = require('./x509');
const PEM = require('../utils/pem');
const ProtoReader = require('../utils/protoreader');
const ProtoWriter = require('../utils/protowriter');
const PaymentDetails = require('./paymentdetails');
@ -50,7 +49,7 @@ function PaymentRequest(options) {
PaymentRequest.prototype.fromOptions = function fromOptions(options) {
if (options.version != null) {
assert(util.isInt(options.version));
assert((options.version | 0) === options.version);
this.version = options.version;
}

View File

@ -7,8 +7,8 @@
'use strict';
const assert = require('assert');
const ASN1 = require('../utils/asn1');
const PEM = require('../utils/pem');
const ASN1 = require('bcrypto/lib/utils/asn1');
const PEM = require('bcrypto/lib/utils/pem');
const util = require('../utils/util');
const digest = require('bcrypto/lib/digest');
const pk = require('./pk');

View File

@ -1071,7 +1071,7 @@ Chain.prototype.setBestChain = async function setBestChain(entry, block, prev, f
if (entry.hasUnknown(this.network)) {
this.logger.warning(
'Unknown version bits in block %d: %s.',
entry.height, util.hex32(entry.version));
entry.height, entry.version.toString(16));
}
// Otherwise, everything is in order.
@ -1136,7 +1136,7 @@ Chain.prototype.saveAlternate = async function saveAlternate(entry, block, prev,
if (entry.hasUnknown(this.network)) {
this.logger.warning(
'Unknown version bits in block %d: %s.',
entry.height, util.hex32(entry.version));
entry.height, entry.version.toString(16));
}
await this.db.save(entry, block);
@ -1549,7 +1549,7 @@ Chain.prototype.logStatus = function logStatus(start, block, entry) {
if (this.db.coinCache.capacity > 0) {
this.logger.debug('Coin Cache: size=%dmb, items=%d.',
util.mb(this.db.coinCache.size), this.db.coinCache.items);
this.db.coinCache.size / (1 << 20), this.db.coinCache.items);
}
};
@ -2747,12 +2747,13 @@ ChainOptions.prototype.fromOptions = function fromOptions(options) {
}
if (options.maxFiles != null) {
assert(util.isU32(options.maxFiles));
assert((options.maxFiles >>> 0) === options.maxFiles);
this.maxFiles = options.maxFiles;
}
if (options.cacheSize != null) {
assert(util.isU64(options.cacheSize));
assert(Number.isSafeInteger(options.cacheSize));
assert(options.cacheSize >= 0);
this.cacheSize = options.cacheSize;
}
@ -2792,17 +2793,17 @@ ChainOptions.prototype.fromOptions = function fromOptions(options) {
}
if (options.coinCache != null) {
assert(util.isU64(options.coinCache));
assert((options.coinCache >>> 0) === options.coinCache);
this.coinCache = options.coinCache;
}
if (options.entryCache != null) {
assert(util.isU32(options.entryCache));
assert((options.entryCache >>> 0) === options.entryCache);
this.entryCache = options.entryCache;
}
if (options.maxOrphans != null) {
assert(util.isU32(options.maxOrphans));
assert((options.maxOrphans >>> 0) === options.maxOrphans);
this.maxOrphans = options.maxOrphans;
}

View File

@ -76,13 +76,13 @@ ChainEntry.MAX_CHAINWORK = new BN(1).ushln(256);
ChainEntry.prototype.fromOptions = function fromOptions(options) {
assert(options, 'Block data is required.');
assert(typeof options.hash === 'string');
assert(util.isU32(options.version));
assert((options.version >>> 0) === options.version);
assert(typeof options.prevBlock === 'string');
assert(typeof options.merkleRoot === 'string');
assert(util.isU32(options.time));
assert(util.isU32(options.bits));
assert(util.isU32(options.nonce));
assert(util.isU32(options.height));
assert((options.time >>> 0) === options.time);
assert((options.bits >>> 0) === options.bits);
assert((options.nonce >>> 0) === options.nonce);
assert((options.height >>> 0) === options.height);
assert(!options.chainwork || BN.isBN(options.chainwork));
this.hash = options.hash;
@ -298,12 +298,12 @@ ChainEntry.prototype.toJSON = function toJSON() {
ChainEntry.prototype.fromJSON = function fromJSON(json) {
assert(json, 'Block data is required.');
assert(typeof json.hash === 'string');
assert(util.isU32(json.version));
assert((json.version >>> 0) === json.version);
assert(typeof json.prevBlock === 'string');
assert(typeof json.merkleRoot === 'string');
assert(util.isU32(json.time));
assert(util.isU32(json.bits));
assert(util.isU32(json.nonce));
assert((json.time >>> 0) === json.time);
assert((json.bits >>> 0) === json.bits);
assert((json.nonce >>> 0) === json.nonce);
assert(typeof json.chainwork === 'string');
this.hash = util.revHex(json.hash);
@ -354,7 +354,7 @@ ChainEntry.prototype.toInv = function toInv() {
ChainEntry.prototype.inspect = function inspect() {
const json = this.toJSON();
json.version = util.hex32(json.version);
json.version = json.version.toString(16);
return json;
};

View File

@ -7,9 +7,6 @@
'use strict';
const assert = require('assert');
const util = require('../utils/util');
const pad8 = util.pad8;
const pad32 = util.pad32;
const layout = {
binary: false,
@ -23,7 +20,7 @@ const layout = {
return 'h' + hex(hash);
},
H: function H(height) {
return 'H' + pad32(height);
return 'H' + hex32(height);
},
n: function n(hash) {
return 'n' + hex(hash);
@ -38,18 +35,18 @@ const layout = {
return 't' + hex(hash);
},
c: function c(hash, index) {
return 'c' + hex(hash) + pad32(index);
return 'c' + hex(hash) + hex32(index);
},
u: function u(hash) {
return 'u' + hex(hash);
},
v: function v(bit, hash) {
return 'v' + pad8(bit) + hex(hash);
return 'v' + hex8(bit) + hex(hash);
},
vv: function vv(key) {
assert(typeof key === 'string');
assert(key.length === 36);
return [parseInt(key.slice(1, 4), 10), key.slice(4, 36)];
return [parseInt(key.slice(1, 3), 16), key.slice(3, 35)];
},
T: function T(addr, hash) {
addr = hex(addr);
@ -64,10 +61,10 @@ const layout = {
addr = hex(addr);
if (addr.length === 64)
return 'X' + addr + hex(hash) + pad32(index);
return 'X' + addr + hex(hash) + hex32(index);
assert(addr.length === 40);
return 'C' + addr + hex(hash) + pad32(index);
return 'C' + addr + hex(hash) + hex32(index);
},
pp: function pp(key) {
assert(typeof key === 'string');
@ -78,12 +75,12 @@ const layout = {
assert(typeof key === 'string');
let hash, index;
if (key.length === 139) {
if (key.length === 137) {
hash = key.slice(65, 129);
index = parseInt(key.slice(129), 10);
} else if (key.length === 115) {
index = parseInt(key.slice(129), 16);
} else if (key.length === 113) {
hash = key.slice(41, 105);
index = parseInt(key.slice(105), 10);
index = parseInt(key.slice(105), 16);
} else {
assert(false);
}
@ -112,6 +109,47 @@ function hex(hash) {
return hash;
}
function hex8(num) {
assert(typeof num === 'number');
assert(num >= 0 && num <= 255);
if (num <= 0x0f)
return '0' + num.toString(16);
if (num <= 0xff)
return num.toString(16);
throw new Error('Number too big.');
}
function hex32(num) {
assert(typeof num === 'number');
assert(num >= 0);
num = num.toString(16);
switch (num.length) {
case 1:
return '0000000' + num;
case 2:
return '000000' + num;
case 3:
return '00000' + num;
case 4:
return '0000' + num;
case 5:
return '000' + num;
case 6:
return '00' + num;
case 7:
return '0' + num;
case 8:
return num;
}
throw new Error('Number too big.');
}
/*
* Expose
*/

View File

@ -7,7 +7,7 @@
'use strict';
const assert = require('assert');
const util = require('../utils/util');
const fixed = require('../utils/fixed');
/**
* Represents a bitcoin amount (satoshis internally).
@ -138,7 +138,7 @@ Amount.prototype.toString = function toString() {
*/
Amount.prototype.fromValue = function fromValue(value) {
assert(util.isI64(value), 'Value must be an int64.');
assert(Number.isSafeInteger(value) && value >= 0, 'Value must be an int64.');
this.value = value;
return this;
};
@ -335,8 +335,8 @@ Amount.value = function value(str) {
Amount.encode = function encode(value, exp, num) {
if (num)
return util.toFloat(value, exp);
return util.toFixed(value, exp);
return fixed.toFloat(value, exp);
return fixed.encode(value, exp);
};
/**
@ -349,8 +349,8 @@ Amount.encode = function encode(value, exp, num) {
Amount.decode = function decode(value, exp) {
if (typeof value === 'number')
return util.fromFloat(value, exp);
return util.fromFixed(value, exp);
return fixed.fromFloat(value, exp);
return fixed.decode(value, exp);
};
/*

View File

@ -7,7 +7,6 @@
'use strict';
const assert = require('assert');
const util = require('../utils/util');
const Address = require('../primitives/address');
const Amount = require('./amount');
@ -52,7 +51,8 @@ URI.prototype.fromOptions = function fromOptions(options) {
this.address.fromOptions(options.address);
if (options.amount != null) {
assert(util.isU64(options.amount), 'Amount must be a uint64.');
assert(Number.isSafeInteger(options.amount) && options.amount >= 0,
'Amount must be a uint64.');
this.amount = options.amount;
}

View File

@ -7,7 +7,6 @@
'use strict';
const assert = require('assert');
const util = require('../utils/util');
const digest = require('bcrypto/lib/digest');
const cleanse = require('bcrypto/lib/cleanse');
const random = require('bcrypto/lib/random');
@ -84,7 +83,7 @@ Mnemonic.prototype.fromOptions = function fromOptions(options) {
options = { phrase: options };
if (options.bits != null) {
assert(util.isU16(options.bits));
assert((options.bits & 0xffff) === options.bits);
assert(options.bits >= common.MIN_ENTROPY);
assert(options.bits <= common.MAX_ENTROPY);
assert(options.bits % 32 === 0);
@ -403,7 +402,8 @@ Mnemonic.prototype.toJSON = function toJSON() {
*/
Mnemonic.prototype.fromJSON = function fromJSON(json) {
assert(util.isU16(json.bits));
assert(json);
assert((json.bits & 0xffff) === json.bits);
assert(typeof json.language === 'string');
assert(typeof json.entropy === 'string');
assert(typeof json.phrase === 'string');

View File

@ -7,7 +7,6 @@
'use strict';
const assert = require('assert');
const util = require('../utils/util');
const digest = require('bcrypto/lib/digest');
const cleanse = require('bcrypto/lib/cleanse');
const random = require('bcrypto/lib/random');
@ -72,9 +71,9 @@ function HDPrivateKey(options) {
HDPrivateKey.prototype.fromOptions = function fromOptions(options) {
assert(options, 'No options for HD private key.');
assert(util.isU8(options.depth));
assert(util.isU32(options.parentFingerPrint));
assert(util.isU32(options.childIndex));
assert((options.depth & 0xff) === options.depth);
assert((options.parentFingerPrint >>> 0) === options.parentFingerPrint);
assert((options.childIndex >>> 0) === options.childIndex);
assert(Buffer.isBuffer(options.chainCode));
assert(Buffer.isBuffer(options.privateKey));
@ -250,9 +249,9 @@ HDPrivateKey.prototype.getID = function getID(index) {
*/
HDPrivateKey.prototype.deriveAccount = function deriveAccount(purpose, type, account) {
assert(util.isU32(purpose), 'Purpose must be a number.');
assert(util.isU32(type), 'Account index must be a number.');
assert(util.isU32(account), 'Account index must be a number.');
assert((purpose >>> 0) === purpose, 'Purpose must be a number.');
assert((type >>> 0) === type, 'Account index must be a number.');
assert((account >>> 0) === account, 'Account index must be a number.');
assert(this.isMaster(), 'Cannot derive account index.');
return this
.derive(purpose, true)

View File

@ -7,7 +7,6 @@
'use strict';
const assert = require('assert');
const util = require('../utils/util');
const digest = require('bcrypto/lib/digest');
const cleanse = require('bcrypto/lib/cleanse');
const secp256k1 = require('bcrypto/lib/secp256k1');
@ -60,9 +59,9 @@ function HDPublicKey(options) {
HDPublicKey.prototype.fromOptions = function fromOptions(options) {
assert(options, 'No options for HDPublicKey');
assert(util.isU8(options.depth));
assert(util.isU32(options.parentFingerPrint));
assert(util.isU32(options.childIndex));
assert((options.depth & 0xff) === options.depth);
assert((options.parentFingerPrint >>> 0) === options.parentFingerPrint);
assert((options.childIndex >>> 0) === options.childIndex);
assert(Buffer.isBuffer(options.chainCode));
assert(Buffer.isBuffer(options.publicKey));
@ -211,9 +210,9 @@ HDPublicKey.prototype.getID = function getID(index) {
*/
HDPublicKey.prototype.deriveAccount = function deriveAccount(purpose, type, account) {
assert(util.isU32(purpose));
assert(util.isU32(type));
assert(util.isU32(account));
assert((purpose >>> 0) === purpose);
assert((type >>> 0) === type);
assert((account >>> 0) === account);
assert(this.isAccount(account), 'Cannot derive account index.');
return this;
};

View File

@ -121,11 +121,11 @@ class RPC extends RPCBase {
case 'RPCError':
return err.code;
case 'ValidationError':
return errors.TYPE_ERROR;
return errs.TYPE_ERROR;
case 'EncodingError':
return errors.DESERIALIZATION_ERROR;
return errs.DESERIALIZATION_ERROR;
default:
return errors.INTERNAL_ERROR;
return errs.INTERNAL_ERROR;
}
}
@ -307,7 +307,7 @@ class RPC extends RPCBase {
version: pkg.version,
subversion: this.pool.options.agent,
protocolversion: this.pool.options.version,
localservices: util.hex32(this.pool.options.services),
localservices: hex32(this.pool.options.services),
localrelay: !this.pool.options.noRelay,
timeoffset: this.network.time.offset,
networkactive: this.pool.connected,
@ -446,7 +446,7 @@ class RPC extends RPCBase {
return {
totalbytesrecv: recv,
totalbytessent: sent,
timemillis: util.ms()
timemillis: Date.now()
};
}
@ -474,13 +474,13 @@ class RPC extends RPCBase {
addrlocal: !peer.local.isNull()
? peer.local.hostname
: undefined,
services: util.hex32(peer.services),
services: hex32(peer.services),
relaytxes: !peer.noRelay,
lastsend: peer.lastSend / 1000 | 0,
lastrecv: peer.lastRecv / 1000 | 0,
bytessent: peer.socket.bytesWritten,
bytesrecv: peer.socket.bytesRead,
conntime: peer.time !== 0 ? (util.ms() - peer.time) / 1000 | 0 : 0,
conntime: peer.time !== 0 ? (Date.now() - peer.time) / 1000 | 0 : 0,
timeoffset: offset,
pingtime: peer.lastPong !== -1
? (peer.lastPong - peer.lastPing) / 1000
@ -626,8 +626,10 @@ class RPC extends RPCBase {
if (this.chain.options.spv)
throw new RPCError(errs.MISC_ERROR, 'Block not available (spv mode)');
if (this.chain.options.prune)
throw new RPCError(errs.MISC_ERROR, 'Block not available (pruned data)');
if (this.chain.options.prune) {
throw new RPCError(errs.MISC_ERROR,
'Block not available (pruned data)');
}
throw new RPCError(errs.MISC_ERROR, 'Can\'t read block from disk');
}
@ -663,8 +665,10 @@ class RPC extends RPCBase {
if (this.chain.options.spv)
throw new RPCError(errs.MISC_ERROR, 'Block not available (spv mode)');
if (this.chain.options.prune)
throw new RPCError(errs.MISC_ERROR, 'Block not available (pruned data)');
if (this.chain.options.prune) {
throw new RPCError(errs.MISC_ERROR,
'Block not available (pruned data)');
}
throw new RPCError(errs.DATABASE_ERROR, 'Can\'t read block from disk');
}
@ -798,8 +802,10 @@ class RPC extends RPCBase {
}
async getMempoolDescendants(args, help) {
if (help || args.length < 1 || args.length > 2)
throw new RPCError(errs.MISC_ERROR, 'getmempooldescendants txid (verbose)');
if (help || args.length < 1 || args.length > 2) {
throw new RPCError(errs.MISC_ERROR,
'getmempooldescendants txid (verbose)');
}
const valid = new Validator(args);
const hash = valid.rhash(0);
@ -876,8 +882,10 @@ class RPC extends RPCBase {
}
async getTXOut(args, help) {
if (help || args.length < 2 || args.length > 3)
throw new RPCError(errs.MISC_ERROR, 'gettxout "txid" n ( includemempool )');
if (help || args.length < 2 || args.length > 3) {
throw new RPCError(errs.MISC_ERROR,
'gettxout "txid" n ( includemempool )');
}
const valid = new Validator(args);
const hash = valid.rhash(0);
@ -1018,8 +1026,10 @@ class RPC extends RPCBase {
if (help || args.length !== 0)
throw new RPCError(errs.MISC_ERROR, 'gettxoutsetinfo');
if (this.chain.options.spv)
throw new RPCError(errs.MISC_ERROR, 'Chainstate not available (SPV mode).');
if (this.chain.options.spv) {
throw new RPCError(errs.MISC_ERROR,
'Chainstate not available (SPV mode).');
}
return {
height: this.chain.height,
@ -1053,8 +1063,10 @@ class RPC extends RPCBase {
}
async verifyChain(args, help) {
if (help || args.length > 2)
throw new RPCError(errs.MISC_ERROR, 'verifychain ( checklevel numblocks )');
if (help || args.length > 2) {
throw new RPCError(errs.MISC_ERROR,
'verifychain ( checklevel numblocks )');
}
const valid = new Validator(args);
const level = valid.u32(0);
@ -1451,7 +1463,7 @@ class RPC extends RPCBase {
height: attempt.height,
previousblockhash: util.revHex(attempt.prevBlock),
target: util.revHex(attempt.target.toString('hex')),
bits: util.hex32(attempt.bits),
bits: hex32(attempt.bits),
noncerange: '00000000ffffffff',
curtime: attempt.time,
mintime: attempt.mtp + 1,
@ -1460,7 +1472,7 @@ class RPC extends RPCBase {
sigoplimit: consensus.MAX_BLOCK_SIGOPS_COST / scale | 0,
sizelimit: consensus.MAX_BLOCK_SIZE,
weightlimit: undefined,
longpollid: this.chain.tip.rhash() + util.pad32(this.totalTX()),
longpollid: this.chain.tip.rhash() + hex32(this.totalTX()),
submitold: false,
coinbaseaux: {
flags: attempt.coinbaseFlags.toString('hex')
@ -1817,8 +1829,10 @@ class RPC extends RPCBase {
}
async getRawTransaction(args, help) {
if (help || args.length < 1 || args.length > 2)
throw new RPCError(errs.MISC_ERROR, 'getrawtransaction "txid" ( verbose )');
if (help || args.length < 1 || args.length > 2) {
throw new RPCError(errs.MISC_ERROR,
'getrawtransaction "txid" ( verbose )');
}
const valid = new Validator(args);
const hash = valid.rhash(0);
@ -1985,8 +1999,10 @@ class RPC extends RPCBase {
*/
async createMultisig(args, help) {
if (help || args.length < 2 || args.length > 2)
throw new RPCError(errs.MISC_ERROR, 'createmultisig nrequired ["key",...]');
if (help || args.length < 2 || args.length > 2) {
throw new RPCError(errs.MISC_ERROR,
'createmultisig nrequired ["key",...]');
}
const valid = new Validator(args);
const keys = valid.array(1, []);
@ -2012,8 +2028,10 @@ class RPC extends RPCBase {
const script = Script.fromMultisig(m, n, keys);
if (script.getSize() > consensus.MAX_SCRIPT_PUSH)
throw new RPCError(errs.VERIFY_ERROR, 'Redeem script exceeds size limit.');
if (script.getSize() > consensus.MAX_SCRIPT_PUSH) {
throw new RPCError(errs.VERIFY_ERROR,
'Redeem script exceeds size limit.');
}
const addr = script.getAddress();
@ -2239,7 +2257,7 @@ class RPC extends RPCBase {
if (help || args.length !== 0)
throw new RPCError(errs.MISC_ERROR, 'getmemoryinfo');
return util.memoryUsage();
return this.logger.memoryUsage();
}
async setLogLevel(args, help) {
@ -2259,13 +2277,13 @@ class RPC extends RPCBase {
*/
async handleLongpoll(lpid) {
if (lpid.length !== 74)
if (lpid.length !== 72)
throw new RPCError(errs.INVALID_PARAMETER, 'Invalid longpoll ID.');
const watched = lpid.slice(0, 64);
const lastTX = parseInt(lpid.slice(64, 74), 10);
const lastTX = parseInt(lpid.slice(64, 72), 16);
if (!util.isHex(watched) || !util.isU32(lastTX))
if ((lastTX >>> 0) !== lastTX)
throw new RPCError(errs.INVALID_PARAMETER, 'Invalid longpoll ID.');
const hash = util.revHex(watched);
@ -2680,7 +2698,7 @@ class RPC extends RPCBase {
confirmations: this.chain.height - entry.height + 1,
height: entry.height,
version: entry.version,
versionHex: util.hex32(entry.version),
versionHex: hex32(entry.version),
merkleroot: util.revHex(entry.merkleRoot),
time: entry.time,
mediantime: mtp,
@ -2716,7 +2734,7 @@ class RPC extends RPCBase {
weight: block.getWeight(),
height: entry.height,
version: entry.version,
versionHex: util.hex32(entry.version),
versionHex: hex32(entry.version),
merkleroot: util.revHex(entry.merkleRoot),
coinbase: block.txs[0].inputs[0].script.toJSON(),
tx: txs,
@ -2825,6 +2843,19 @@ function toDifficulty(bits) {
return diff;
}
function hex32(num) {
assert(num >= 0);
num = num.toString(16);
assert(num.length <= 8);
while (num.length < 8)
num = '0' + num;
return num;
}
/*
* Expose
*/

View File

@ -140,7 +140,7 @@ class HTTPServer extends Server {
adjusted: this.network.now(),
offset: this.network.time.offset
},
memory: util.memoryUsage()
memory: this.logger.memoryUsage()
});
});
@ -715,8 +715,6 @@ class HTTPOptions {
'API key must be a string.');
assert(options.apiKey.length <= 255,
'API key must be under 256 bytes.');
assert(util.isAscii(options.apiKey),
'API key must be ascii.');
this.apiKey = options.apiKey;
this.apiHash = digest.hash256(Buffer.from(this.apiKey, 'ascii'));
}
@ -739,7 +737,8 @@ class HTTPOptions {
}
if (options.port != null) {
assert(util.isU16(options.port), 'Port must be a number.');
assert((options.port & 0xffff) === options.port,
'Port must be a number.');
this.port = options.port;
}

View File

@ -10,6 +10,7 @@
const assert = require('assert');
const util = require('../utils/util');
const binary = require('../utils/binary');
const consensus = require('../protocol/consensus');
const policy = require('../protocol/policy');
const BufferReader = require('../utils/reader');
@ -691,7 +692,7 @@ PolicyEstimator.prototype.estimateFee = function estimateFee(target, smart) {
if (smart == null)
smart = true;
assert(util.isU32(target), 'Target must be a number.');
assert((target >>> 0) === target, 'Target must be a number.');
assert(target <= this.feeStats.maxConfirms,
'Too many confirmations for estimate.');
@ -735,7 +736,7 @@ PolicyEstimator.prototype.estimatePriority = function estimatePriority(target, s
if (smart == null)
smart = true;
assert(util.isU32(target), 'Target must be a number.');
assert((target >>> 0) === target, 'Target must be a number.');
assert(target <= this.priStats.maxConfirms,
'Too many confirmations for estimate.');
@ -856,12 +857,12 @@ function DoubleMap() {
}
DoubleMap.prototype.insert = function insert(key, value) {
const i = util.binarySearch(this.buckets, key, compare, true);
const i = binary.search(this.buckets, key, compare, true);
this.buckets.splice(i, 0, [key, value]);
};
DoubleMap.prototype.search = function search(key) {
const i = util.binarySearch(this.buckets, key, compare, true);
const i = binary.search(this.buckets, key, compare, true);
assert(this.buckets.length !== 0, 'Cannot search.');
return this.buckets[i][1];
};

View File

@ -2035,7 +2035,7 @@ MempoolOptions.prototype.fromOptions = function fromOptions(options) {
}
if (options.limitFreeRelay != null) {
assert(util.isU32(options.limitFreeRelay));
assert((options.limitFreeRelay >>> 0) === options.limitFreeRelay);
this.limitFreeRelay = options.limitFreeRelay;
}
@ -2070,27 +2070,27 @@ MempoolOptions.prototype.fromOptions = function fromOptions(options) {
}
if (options.maxSize != null) {
assert(util.isU64(options.maxSize));
assert((options.maxSize >>> 0) === options.maxSize);
this.maxSize = options.maxSize;
}
if (options.maxOrphans != null) {
assert(util.isU32(options.maxOrphans));
assert((options.maxOrphans >>> 0) === options.maxOrphans);
this.maxOrphans = options.maxOrphans;
}
if (options.maxAncestors != null) {
assert(util.isU32(options.maxAncestors));
assert((options.maxAncestors >>> 0) === options.maxAncestors);
this.maxAncestors = options.maxAncestors;
}
if (options.expiryTime != null) {
assert(util.isU32(options.expiryTime));
assert((options.expiryTime >>> 0) === options.expiryTime);
this.expiryTime = options.expiryTime;
}
if (options.minRelay != null) {
assert(util.isU64(options.minRelay));
assert((options.minRelay >>> 0) === options.minRelay);
this.minRelay = options.minRelay;
}
@ -2111,12 +2111,13 @@ MempoolOptions.prototype.fromOptions = function fromOptions(options) {
}
if (options.maxFiles != null) {
assert(util.isU32(options.maxFiles));
assert((options.maxFiles >>> 0) === options.maxFiles);
this.maxFiles = options.maxFiles;
}
if (options.cacheSize != null) {
assert(util.isU64(options.cacheSize));
assert(Number.isSafeInteger(options.cacheSize));
assert(options.cacheSize >= 0);
this.cacheSize = options.cacheSize;
}

View File

@ -8,7 +8,6 @@
'use strict';
const assert = require('assert');
const util = require('../utils/util');
const Heap = require('../utils/heap');
const AsyncObject = require('../utils/asyncobject');
const Amount = require('../btc/amount');
@ -429,7 +428,7 @@ MinerOptions.prototype.fromOptions = function fromOptions(options) {
}
if (options.version != null) {
assert(util.isInt(options.version));
assert((options.version >>> 0) === options.version);
this.version = options.version;
}
@ -463,41 +462,41 @@ MinerOptions.prototype.fromOptions = function fromOptions(options) {
}
if (options.minWeight != null) {
assert(util.isU32(options.minWeight));
assert((options.minWeight >>> 0) === options.minWeight);
this.minWeight = options.minWeight;
}
if (options.maxWeight != null) {
assert(util.isU32(options.maxWeight));
assert((options.maxWeight >>> 0) === 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.isU32(options.maxSigops));
assert((options.maxSigops >>> 0) === 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.isU32(options.priorityWeight));
assert((options.priorityWeight >>> 0) === options.priorityWeight);
this.priorityWeight = options.priorityWeight;
}
if (options.priorityThreshold != null) {
assert(util.isU32(options.priorityThreshold));
assert((options.priorityThreshold >>> 0) === options.priorityThreshold);
this.priorityThreshold = options.priorityThreshold;
}
if (options.reservedWeight != null) {
assert(util.isU32(options.reservedWeight));
assert((options.reservedWeight >>> 0) === options.reservedWeight);
this.reservedWeight = options.reservedWeight;
}
if (options.reservedSigops != null) {
assert(util.isU32(options.reservedSigops));
assert((options.reservedSigops >>> 0) === options.reservedSigops);
this.reservedSigops = options.reservedSigops;
}

View File

@ -246,7 +246,9 @@ BlockTemplate.prototype.createCoinbase = function createCoinbase(hash) {
input.script.pushData(encoding.ZERO_HASH160);
// Smaller nonce for good measure.
input.script.pushData(util.nonce(4));
const nonce = Buffer.allocUnsafe(4);
nonce.writeUInt32LE(Math.random() * 0x100000000, 0, true);
input.script.pushData(nonce);
// Extra nonce: incremented when
// the nonce overflows.

View File

@ -14,6 +14,7 @@
const assert = require('assert');
const EventEmitter = require('events');
const {format} = require('util');
const util = require('../utils/util');
const co = require('../utils/co');
const hash256 = require('bcrypto/lib/hash256');
@ -350,7 +351,7 @@ BIP151.MAX_MESSAGE = 12 * 1000 * 1000;
*/
BIP151.prototype.error = function error() {
const msg = util.fmt.apply(util, arguments);
const msg = format.apply(null, arguments);
this.emit('error', new Error(msg));
};
@ -700,7 +701,7 @@ BIP151.prototype.parse = function parse(data) {
// Note that 6 is the minimum size:
// varint-cmdlen(1) str-cmd(1) u32-size(4) payload(0)
if (size < 6 || size > BIP151.MAX_MESSAGE) {
this.error('Bad packet size: %d.', util.mb(size));
this.error('Bad packet size: %d.', size);
return;
}

View File

@ -11,7 +11,6 @@
*/
const assert = require('assert');
const util = require('../utils/util');
const BufferReader = require('../utils/reader');
const StaticWriter = require('../utils/staticwriter');
const encoding = require('../utils/encoding');
@ -22,6 +21,7 @@ const AbstractBlock = require('../primitives/abstractblock');
const TX = require('../primitives/tx');
const Headers = require('../primitives/headers');
const Block = require('../primitives/block');
const common = require('./common');
/**
* Represents a compact block (bip152): `cmpctblock` packet.
@ -494,7 +494,7 @@ CompactBlock.prototype.fromBlock = function fromBlock(block, witness, nonce) {
this._hhash = block._hhash;
if (!nonce)
nonce = util.nonce();
nonce = common.nonce();
this.keyNonce = nonce;
this.sipKey = this.getKey();

View File

@ -159,3 +159,15 @@ exports.BAN_TIME = 24 * 60 * 60;
*/
exports.BAN_SCORE = 100;
/**
* Create a nonce.
* @returns {Buffer}
*/
exports.nonce = function nonce() {
const data = Buffer.allocUnsafe(8);
data.writeUInt32LE(Math.random() * 0x100000000, true, 0);
data.writeUInt32LE(Math.random() * 0x100000000, true, 4);
return data;
};

View File

@ -409,7 +409,7 @@ HostList.prototype.getHost = function getHost() {
buckets = this.fresh;
if (this.totalUsed > 0) {
if (this.totalFresh === 0 || util.random(0, 2) === 0)
if (this.totalFresh === 0 || random(2) === 0)
buckets = this.used;
}
@ -420,13 +420,13 @@ HostList.prototype.getHost = function getHost() {
let factor = 1;
for (;;) {
let index = util.random(0, buckets.length);
let index = random(buckets.length);
const bucket = buckets[index];
if (bucket.size === 0)
continue;
index = util.random(0, bucket.size);
index = random(bucket.size);
let entry;
if (buckets === this.used) {
@ -441,7 +441,7 @@ HostList.prototype.getHost = function getHost() {
}
}
const num = util.random(0, 1 << 30);
const num = random(1 << 30);
if (num < factor * entry.chance(now) * (1 << 30))
return entry;
@ -541,7 +541,7 @@ HostList.prototype.add = function add(addr, src) {
for (let i = 0; i < entry.refCount; i++)
factor *= 2;
if (util.random(0, factor) !== 0)
if (random(factor) !== 0)
return false;
} else {
if (this.isFull())
@ -1374,12 +1374,13 @@ HostEntry.prototype.fromJSON = function fromJSON(json, network) {
assert(json.services.length > 0);
assert(json.services.length <= 32);
const services = parseInt(json.services, 2);
assert(util.isU32(services));
assert((services >>> 0) === services);
this.addr.services = services;
}
if (json.time != null) {
assert(util.isU64(json.time));
assert(Number.isSafeInteger(json.time));
assert(json.time >= 0);
this.addr.time = json.time;
}
@ -1389,17 +1390,19 @@ HostEntry.prototype.fromJSON = function fromJSON(json, network) {
}
if (json.attempts != null) {
assert(util.isU64(json.attempts));
assert((json.attempts >>> 0) === json.attempts);
this.attempts = json.attempts;
}
if (json.lastSuccess != null) {
assert(util.isU64(json.lastSuccess));
assert(Number.isSafeInteger(json.lastSuccess));
assert(json.lastSuccess >= 0);
this.lastSuccess = json.lastSuccess;
}
if (json.lastAttempt != null) {
assert(util.isU64(json.lastAttempt));
assert(Number.isSafeInteger(json.lastAttempt));
assert(json.lastAttempt >= 0);
this.lastAttempt = json.lastAttempt;
}
@ -1594,6 +1597,10 @@ function concat32(left, right) {
return data;
}
function random(max) {
return Math.floor(Math.random() * max);
}
/*
* Expose
*/

View File

@ -67,8 +67,8 @@ exports.types = {
AUTHPROPOSE: 30,
UNKNOWN: 31,
// Internal
INTERNAL: 100,
DATA: 101
INTERNAL: 32,
DATA: 33
};
/**
@ -77,7 +77,43 @@ exports.types = {
* @default
*/
exports.typesByVal = util.reverse(exports.types);
exports.typesByVal = [
'VERSION',
'VERACK',
'PING',
'PONG',
'GETADDR',
'ADDR',
'INV',
'GETDATA',
'NOTFOUND',
'GETBLOCKS',
'GETHEADERS',
'HEADERS',
'SENDHEADERS',
'BLOCK',
'TX',
'REJECT',
'MEMPOOL',
'FILTERLOAD',
'FILTERADD',
'FILTERCLEAR',
'MERKLEBLOCK',
'FEEFILTER',
'SENDCMPCT',
'CMPCTBLOCK',
'GETBLOCKTXN',
'BLOCKTXN',
'ENCINIT',
'ENCACK',
'AUTHCHALLENGE',
'AUTHREPLY',
'AUTHPROPOSE',
'UNKNOWN',
// Internal
'INTERNAL',
'DATA'
];
/**
* Base Packet
@ -1462,9 +1498,9 @@ RejectPacket.codes = {
CHECKPOINT: 0x43,
// Internal codes (NOT FOR USE ON NETWORK)
INTERNAL: 0x100,
HIGHFEE: 0x100,
ALREADYKNOWN: 0x101,
CONFLICT: 0x102
HIGHFEE: 0x101,
ALREADYKNOWN: 0x102,
CONFLICT: 0x103
};
/**
@ -1472,7 +1508,21 @@ RejectPacket.codes = {
* @const {RevMap}
*/
RejectPacket.codesByVal = util.reverse(RejectPacket.codes);
RejectPacket.codesByVal = {
0x01: 'MALFORMED',
0x10: 'INVALID',
0x11: 'OBSOLETE',
0x12: 'DUPLICATE',
0x40: 'NONSTANDARD',
0x41: 'DUST',
0x42: 'INSUFFICIENTFEE',
0x43: 'CHECKPOINT',
// Internal codes (NOT FOR USE ON NETWORK)
0x100: 'INTERNAL',
0x101: 'HIGHFEE',
0x102: 'ALREADYKNOWN',
0x103: 'CONFLICT'
};
RejectPacket.prototype.cmd = 'reject';
RejectPacket.prototype.type = exports.types.REJECT;

View File

@ -11,8 +11,8 @@
const assert = require('assert');
const EventEmitter = require('events');
const {format} = require('util');
const Network = require('../protocol/network');
const util = require('../utils/util');
const digest = require('bcrypto/lib/digest');
const common = require('./common');
const packets = require('./packets');
@ -49,7 +49,7 @@ Object.setPrototypeOf(Parser.prototype, EventEmitter.prototype);
*/
Parser.prototype.error = function error() {
const msg = util.fmt.apply(util, arguments);
const msg = format.apply(null, arguments);
this.emit('error', new Error(msg));
};
@ -100,7 +100,7 @@ Parser.prototype.parse = function parse(data) {
if (checksum !== this.header.checksum) {
this.waiting = 24;
this.header = null;
this.error('Invalid checksum: %s.', util.hex32(checksum));
this.error('Invalid checksum: %s.', checksum.toString(16));
return;
}
@ -130,7 +130,7 @@ Parser.prototype.parseHeader = function parseHeader(data) {
const magic = data.readUInt32LE(0, true);
if (magic !== this.network.magic) {
this.error('Invalid magic value: %s.', util.hex32(magic));
this.error('Invalid magic value: %s.', magic.toString(16));
return null;
}
@ -149,7 +149,7 @@ Parser.prototype.parseHeader = function parseHeader(data) {
if (size > common.MAX_MESSAGE) {
this.waiting = 24;
this.error('Packet length too large: %dmb.', util.mb(size));
this.error('Packet length too large: %d.', size);
return null;
}

View File

@ -9,6 +9,7 @@
const assert = require('assert');
const EventEmitter = require('events');
const {format} = require('util');
const util = require('../utils/util');
const co = require('../utils/co');
const Parser = require('./parser');
@ -400,7 +401,7 @@ Peer.prototype.bind = function bind(socket) {
});
this.socket.on('data', (chunk) => {
this.lastRecv = util.ms();
this.lastRecv = Date.now();
this.feedParser(chunk);
});
@ -418,7 +419,7 @@ Peer.prototype.accept = function accept(socket) {
this.address = NetAddress.fromSocket(socket, this.network);
this.address.services = 0;
this.time = util.ms();
this.time = Date.now();
this.outbound = false;
this.connected = true;
@ -530,7 +531,7 @@ Peer.prototype.initConnect = function initConnect() {
};
this.socket.once('connect', () => {
this.time = util.ms();
this.time = Date.now();
this.connected = true;
this.emit('connect');
@ -981,8 +982,8 @@ Peer.prototype.sendPing = function sendPing() {
return;
}
this.lastPing = util.ms();
this.challenge = util.nonce();
this.lastPing = Date.now();
this.challenge = common.nonce();
this.send(new packets.PingPacket(this.challenge));
};
@ -1085,7 +1086,7 @@ Peer.prototype.write = function write(data) {
if (this.destroyed)
throw new Error('Peer is destroyed (write).');
this.lastSend = util.ms();
this.lastSend = Date.now();
if (this.socket.write(data) === false)
this.needsDrain(data.length);
@ -1176,7 +1177,7 @@ Peer.prototype.needsDrain = function needsDrain(size) {
if (this.drainSize >= Peer.DRAIN_MAX) {
this.logger.warning(
'Peer is not reading: %dmb buffered (%s).',
util.mb(this.drainSize),
this.drainSize / (1 << 20),
this.hostname());
this.error('Peer stalled (drain).');
this.destroy();
@ -1243,7 +1244,7 @@ Peer.prototype.fulfill = function fulfill(packet) {
*/
Peer.prototype.maybeTimeout = function maybeTimeout() {
const now = util.ms();
const now = Date.now();
for (const [key, entry] of this.responseMap) {
if (now > entry.timeout) {
@ -1403,7 +1404,7 @@ Peer.prototype.error = function error(err) {
return;
if (typeof err === 'string') {
const msg = util.fmt.apply(util, arguments);
const msg = format.apply(null, arguments);
err = new Error(msg);
}
@ -1748,7 +1749,7 @@ Peer.prototype.handlePing = async function handlePing(packet) {
Peer.prototype.handlePong = async function handlePong(packet) {
const nonce = packet.nonce;
const now = util.ms();
const now = Date.now();
if (!this.challenge) {
this.logger.debug('Peer sent an unsolicited pong (%s).', this.hostname());
@ -2398,7 +2399,7 @@ PeerOptions.hasWitness = function hasWitness() {
*/
PeerOptions.createNonce = function createNonce(hostname) {
return util.nonce();
return common.nonce();
};
/**
@ -2439,7 +2440,7 @@ RequestEntry.prototype.addJob = function addJob(resolve, reject) {
};
RequestEntry.prototype.setTimeout = function setTimeout(timeout) {
this.timeout = util.ms() + timeout;
this.timeout = Date.now() + timeout;
};
RequestEntry.prototype.reject = function reject(err) {

View File

@ -813,7 +813,7 @@ Pool.prototype.sendSync = async function sendSync(peer) {
return false;
peer.syncing = true;
peer.blockTime = util.ms();
peer.blockTime = Date.now();
let locator;
try {
@ -847,7 +847,7 @@ Pool.prototype.sendLocator = function sendLocator(locator, peer) {
}
peer.syncing = true;
peer.blockTime = util.ms();
peer.blockTime = Date.now();
if (this.checkpoints) {
peer.sendGetHeaders(locator, this.headerTip.hash);
@ -2136,7 +2136,7 @@ Pool.prototype._handleHeaders = async function _handleHeaders(peer, packet) {
// If we received a valid header
// chain, consider this a "block".
peer.blockTime = util.ms();
peer.blockTime = Date.now();
// Request the blocks we just added.
if (checkpoint) {
@ -2226,7 +2226,7 @@ Pool.prototype._addBlock = async function _addBlock(peer, block, flags) {
return;
}
peer.blockTime = util.ms();
peer.blockTime = Date.now();
let entry;
try {
@ -2689,7 +2689,7 @@ Pool.prototype._handleMerkleBlock = async function _handleMerkleBlock(peer, pack
}
peer.merkleBlock = block;
peer.merkleTime = util.ms();
peer.merkleTime = Date.now();
peer.merkleMatches = tree.matches.length;
peer.merkleMap = new Set();
};
@ -2772,7 +2772,7 @@ Pool.prototype.handleCmpctBlock = async function handleCmpctBlock(peer, packet)
peer.destroy();
return;
}
peer.blockMap.set(hash, util.ms());
peer.blockMap.set(hash, Date.now());
assert(!this.blockMap.has(hash));
this.blockMap.add(hash);
}
@ -2829,7 +2829,7 @@ Pool.prototype.handleCmpctBlock = async function handleCmpctBlock(peer, packet)
}
}
block.now = util.ms();
block.now = Date.now();
assert(!peer.compactBlocks.has(hash));
peer.compactBlocks.set(hash, block);
@ -3348,7 +3348,7 @@ Pool.prototype.getBlock = function getBlock(peer, hashes) {
if (peer.destroyed)
throw new Error('Peer is destroyed (getdata).');
let now = util.ms();
let now = Date.now();
const items = [];
for (const hash of hashes) {
@ -3392,7 +3392,7 @@ Pool.prototype.getTX = function getTX(peer, hashes) {
if (peer.destroyed)
throw new Error('Peer is destroyed (getdata).');
let now = util.ms();
let now = Date.now();
const items = [];
@ -3729,7 +3729,7 @@ PoolOptions.prototype.fromOptions = function fromOptions(options) {
}
if (options.port != null) {
assert(util.isU16(options.port));
assert((options.port & 0xffff) === options.port);
this.port = options.port;
this.publicPort = options.port;
}
@ -3740,7 +3740,7 @@ PoolOptions.prototype.fromOptions = function fromOptions(options) {
}
if (options.publicPort != null) {
assert(util.isU16(options.publicPort));
assert((options.publicPort & 0xff) === options.publicPort);
this.publicPort = options.publicPort;
}
@ -3901,12 +3901,12 @@ PoolOptions.prototype.fromOptions = function fromOptions(options) {
this.listen = false;
if (options.services != null) {
assert(util.isU32(options.services));
assert((options.services >>> 0) === options.services);
this.services = options.services;
}
if (options.requiredServices != null) {
assert(util.isU32(options.requiredServices));
assert((options.requiredServices >>> 0) === options.requiredServices);
this.requiredServices = options.requiredServices;
}
@ -4347,7 +4347,7 @@ function NonceList() {
NonceList.prototype.alloc = function alloc(hostname) {
for (;;) {
const nonce = util.nonce();
const nonce = common.nonce();
const key = nonce.toString('hex');
if (this.map.has(key))

View File

@ -9,7 +9,6 @@
const assert = require('assert');
const EventEmitter = require('events');
const bsock = require('bsock');
const util = require('../utils/util');
const digest = require('bcrypto/lib/digest');
const BufferWriter = require('../utils/writer');
@ -126,7 +125,7 @@ ProxySocket.prototype.connect = function connect(port, host) {
const pow = bw.render();
util.log(
console.log(
'Solving proof of work to create socket (%d, %s) -- please wait.',
port, host);
@ -136,7 +135,7 @@ ProxySocket.prototype.connect = function connect(port, host) {
pow.writeUInt32LE(nonce, 0, true);
} while (digest.hash256(pow).compare(this.target) > 0);
util.log('Solved proof of work: %d', nonce);
console.log('Solved proof of work: %d', nonce);
}
this.socket.fire('tcp connect', port, host, nonce);

View File

@ -13,7 +13,7 @@
const assert = require('assert');
const EventEmitter = require('events');
const net = require('net');
const util = require('../utils/util');
const {format} = require('util');
const IP = require('../utils/ip');
const StaticWriter = require('../utils/staticwriter');
const BufferReader = require('../utils/reader');
@ -55,7 +55,16 @@ SOCKS.states = {
RESOLVE_DONE: 7
};
SOCKS.statesByVal = util.reverse(SOCKS.states);
SOCKS.statesByVal = [
'INIT',
'CONNECT',
'HANDSHAKE',
'AUTH',
'PROXY',
'PROXY_DONE',
'RESOLVE',
'RESOLVE_DONE'
];
SOCKS.errors = [
'',
@ -80,7 +89,7 @@ SOCKS.prototype.error = function error(err) {
return;
}
const msg = util.fmt.apply(util, arguments);
const msg = format.apply(null, arguments);
this.emit('error', new Error(msg));
this.destroy();
};

View File

@ -10,7 +10,7 @@ const assert = require('assert');
const Path = require('path');
const os = require('os');
const fs = require('../utils/fs');
const util = require('../utils/util');
const {fromFloat} = require('../utils/fixed');
const HOME = os.homedir ? os.homedir() : '/';
/**
@ -416,7 +416,7 @@ Config.prototype.fixed = function fixed(key, exp, fallback) {
return fallback;
try {
return util.fromFloat(value, exp || 0);
return fromFloat(value, exp || 0);
} catch (e) {
throw new Error(`${fmt(key)} must be a fixed number.`);
}
@ -955,7 +955,7 @@ Config.prototype.parseEnv = function parseEnv(env) {
assert(typeof value === 'string');
if (!util.startsWith(key, prefix))
if (key.indexOf(prefix) === 0)
continue;
key = key.substring(prefix.length);

View File

@ -7,11 +7,26 @@
'use strict';
const assert = require('assert');
const {format, inspect} = require('util');
const fs = require('../utils/fs');
const util = require('../utils/util');
const co = require('../utils/co');
const Lock = require('../utils/lock');
/*
* Constants
*/
const inspectOptions = {
showHidden: false,
depth: 20,
colors: false,
customInspect: true,
showProxy: false,
maxArrayLength: Infinity,
breakLength: 60
};
/**
* Basic stdout and file logger.
* @alias module:node.Logger
@ -382,6 +397,24 @@ Logger.prototype.setLevel = function setLevel(name) {
this.level = level;
};
/**
* Format log.
* @param {Array} args
* @param {Boolean} colors
* @returns {String}
*/
Logger.prototype.fmt = function fmt(args, colors) {
if (args.length > 0) {
const [obj] = args;
if (obj && typeof obj === 'object') {
inspectOptions.colors = colors;
return inspect(obj, inspectOptions);
}
}
return format(...args);
};
/**
* Output a log to the `error` log level.
* @param {String|Object|Error} err
@ -545,7 +578,7 @@ Logger.prototype.writeConsole = function writeConsole(level, module, args) {
: console.log(msg, args[0]);
}
msg += util.format(args, false);
msg += this.fmt(args, false);
if (level === Logger.levels.ERROR) {
console.error(msg);
@ -570,7 +603,7 @@ Logger.prototype.writeConsole = function writeConsole(level, module, args) {
if (module)
msg += `(${module}) `;
msg += util.format(args, this.colors);
msg += this.fmt(args, this.colors);
msg += '\n';
return level === Logger.levels.ERROR
@ -601,7 +634,7 @@ Logger.prototype.writeStream = function writeStream(level, module, args) {
if (module)
msg += `(${module}) `;
msg += util.format(args, false);
msg += this.fmt(args, false);
msg += '\n';
this.stream.write(msg);
@ -638,13 +671,40 @@ Logger.prototype.logError = function logError(level, module, err) {
}
};
/**
* Get the current memory usage.
* @returns {Object}
*/
Logger.prototype.memoryUsage = function memoryUsage() {
if (!process.memoryUsage) {
return {
total: 0,
jsHeap: 0,
jsHeapTotal: 0,
nativeHeap: 0,
external: 0
};
}
const mem = process.memoryUsage();
return {
total: Math.floor(mem.rss / (1 << 20)),
jsHeap: Math.floor(mem.heapUsed / (1 << 20)),
jsHeapTotal: Math.floor(mem.heapTotal / (1 << 20)),
nativeHeap: Math.floor((mem.rss - mem.heapTotal) / (1 << 20)),
external: Math.floor(mem.external / (1 << 20))
};
};
/**
* Log the current memory usage.
* @param {String|null} module
*/
Logger.prototype.memory = function memory(module) {
const mem = util.memoryUsage();
const mem = this.memoryUsage();
this.log(Logger.levels.DEBUG, module, [
'Memory: rss=%dmb, js-heap=%d/%dmb native-heap=%dmb',
@ -842,6 +902,15 @@ LoggerContext.prototype.logError = function logError(level, err) {
this.logger.logError(level, this.module, err);
};
/**
* Get the current memory usage.
* @returns {Object}
*/
LoggerContext.prototype.memoryUsage = function memoryUsage() {
return this.logger.memoryUsage();
};
/**
* Log the current memory usage.
*/

View File

@ -57,12 +57,12 @@ function AbstractBlock() {
AbstractBlock.prototype.parseOptions = function parseOptions(options) {
assert(options, 'Block data is required.');
assert(util.isU32(options.version));
assert((options.version >>> 0) === options.version);
assert(typeof options.prevBlock === 'string');
assert(typeof options.merkleRoot === 'string');
assert(util.isU32(options.time));
assert(util.isU32(options.bits));
assert(util.isU32(options.nonce));
assert((options.time >>> 0) === options.time);
assert((options.bits >>> 0) === options.bits);
assert((options.nonce >>> 0) === 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.isU32(json.version));
assert((json.version >>> 0) === json.version);
assert(typeof json.prevBlock === 'string');
assert(typeof json.merkleRoot === 'string');
assert(util.isU32(json.time));
assert(util.isU32(json.bits));
assert(util.isU32(json.nonce));
assert((json.time >>> 0) === json.time);
assert((json.bits >>> 0) === json.bits);
assert((json.nonce >>> 0) === json.nonce);
this.version = json.version;
this.prevBlock = util.revHex(json.prevBlock);

View File

@ -10,7 +10,6 @@
const assert = require('assert');
const Network = require('../protocol/network');
const encoding = require('../utils/encoding');
const util = require('../utils/util');
const digest = require('bcrypto/lib/digest');
const BufferReader = require('../utils/reader');
const StaticWriter = require('../utils/staticwriter');
@ -55,7 +54,13 @@ Address.types = {
* @const {RevMap}
*/
Address.typesByVal = util.reverse(Address.types);
Address.typesByVal = [
null,
null,
'PUBKEYHASH',
'SCRIPTHASH',
'WITNESS'
];
/**
* Inject properties from options object.
@ -581,8 +586,8 @@ Address.prototype.fromHash = function fromHash(hash, type, version) {
version = -1;
assert(Buffer.isBuffer(hash));
assert(util.isU8(type));
assert(util.isI8(version));
assert((type >>> 0) === type);
assert((version | 0) === version);
assert(type >= Address.types.PUBKEYHASH && type <= Address.types.WITNESS,
'Not a valid address type.');

View File

@ -539,7 +539,7 @@ Block.prototype.format = function format(view, height) {
size: this.getSize(),
virtualSize: this.getVirtualSize(),
date: util.date(this.time),
version: util.hex32(this.version),
version: this.version.toString(16),
prevBlock: util.revHex(this.prevBlock),
merkleRoot: util.revHex(this.merkleRoot),
commitmentHash: commitmentHash

View File

@ -61,13 +61,15 @@ Coin.prototype.fromOptions = function fromOptions(options) {
assert(options, 'Coin data is required.');
if (options.version != null) {
assert(util.isU32(options.version), 'Version must be a uint32.');
assert((options.version >>> 0) === options.version,
'Version must be a uint32.');
this.version = options.version;
}
if (options.height != null) {
if (options.height !== -1) {
assert(util.isU32(options.height), 'Height must be a uint32.');
assert((options.height >>> 0) === options.height,
'Height must be a uint32.');
this.height = options.height;
} else {
this.height = -1;
@ -75,7 +77,8 @@ Coin.prototype.fromOptions = function fromOptions(options) {
}
if (options.value != null) {
assert(util.isU64(options.value), 'Value must be a uint64.');
assert(Number.isSafeInteger(options.value) && options.value >= 0,
'Value must be a uint64.');
this.value = options.value;
}
@ -94,7 +97,7 @@ Coin.prototype.fromOptions = function fromOptions(options) {
}
if (options.index != null) {
assert(util.isU32(options.index), 'Index must be a uint32.');
assert((options.index >>> 0) === options.index, 'Index must be a uint32.');
this.index = options.index;
}
@ -262,10 +265,11 @@ Coin.prototype.getJSON = function getJSON(network, minimal) {
Coin.prototype.fromJSON = function fromJSON(json) {
assert(json, 'Coin data required.');
assert(util.isU32(json.version), 'Version must be a uint32.');
assert(json.height === -1 || util.isU32(json.height),
assert((json.version >>> 0) === json.version, 'Version must be a uint32.');
assert(json.height === -1 || (json.height >>> 0) === json.height,
'Height must be a uint32.');
assert(util.isU64(json.value), 'Value must be a uint64.');
assert(Number.isSafeInteger(json.value) && json.value >= 0,
'Value must be a uint64.');
assert(typeof json.coinbase === 'boolean', 'Coinbase must be a boolean.');
this.version = json.version;
@ -277,7 +281,7 @@ Coin.prototype.fromJSON = function fromJSON(json) {
if (json.hash != null) {
assert(typeof json.hash === 'string', 'Hash must be a string.');
assert(json.hash.length === 64, 'Hash must be a string.');
assert(util.isU32(json.index), 'Index must be a uint32.');
assert((json.index >>> 0) === json.index, 'Index must be a uint32.');
this.hash = util.revHex(json.hash);
this.index = json.index;
}

View File

@ -250,7 +250,7 @@ Headers.prototype.format = function format(view, height) {
hash: this.rhash(),
height: height != null ? height : -1,
date: util.date(this.time),
version: util.hex32(this.version),
version: this.version.toString(16),
prevBlock: util.revHex(this.prevBlock),
merkleRoot: util.revHex(this.merkleRoot),
time: this.time,

View File

@ -8,7 +8,6 @@
'use strict';
const assert = require('assert');
const util = require('../utils/util');
const Network = require('../protocol/network');
const Script = require('../script/script');
const Witness = require('../script/witness');
@ -55,7 +54,8 @@ Input.prototype.fromOptions = function fromOptions(options) {
this.script.fromOptions(options.script);
if (options.sequence != null) {
assert(util.isU32(options.sequence), 'Sequence must be a uint32.');
assert((options.sequence >>> 0) === options.sequence,
'Sequence must be a uint32.');
this.sequence = options.sequence;
}
@ -333,7 +333,7 @@ Input.prototype.getJSON = function getJSON(network, coin) {
Input.prototype.fromJSON = function fromJSON(json) {
assert(json, 'Input data is required.');
assert(util.isU32(json.sequence), 'Sequence must be a uint32.');
assert((json.sequence >>> 0) === json.sequence, 'Sequence must be a uint32.');
this.prevout.fromJSON(json.prevout);
this.script.fromJSON(json.script);
this.witness.fromJSON(json.witness);

View File

@ -40,10 +40,10 @@ InvItem.types = {
TX: 1,
BLOCK: 2,
FILTERED_BLOCK: 3,
CMPCT_BLOCK: 4,
WITNESS_TX: 1 | (1 << 30),
WITNESS_BLOCK: 2 | (1 << 30),
WITNESS_FILTERED_BLOCK: 3 | (1 << 30),
CMPCT_BLOCK: 4
WITNESS_FILTERED_BLOCK: 3 | (1 << 30)
};
/**
@ -51,7 +51,16 @@ InvItem.types = {
* @const {RevMap}
*/
InvItem.typesByVal = util.reverse(InvItem.types);
InvItem.typesByVal = {
0: 'ERROR',
1: 'TX',
2: 'BLOCK',
3: 'FILTERED_BLOCK',
4: 'CMPCT_BLOCK',
[1 | (1 << 30)]: 'WITNESS_TX',
[2 | (1 << 30)]: 'WITNESS_BLOCK',
[3 | (1 << 30)]: 'WITNESS_FILTERED_BLOCK'
};
/**
* Witness bit for inv types.

View File

@ -57,7 +57,7 @@ MerkleBlock.prototype.fromOptions = function fromOptions(options) {
assert(options, 'MerkleBlock data is required.');
assert(Array.isArray(options.hashes));
assert(Buffer.isBuffer(options.flags));
assert(util.isU32(options.totalTX));
assert((options.totalTX >>> 0) === options.totalTX);
if (options.hashes) {
for (let hash of options.hashes) {
@ -74,7 +74,7 @@ MerkleBlock.prototype.fromOptions = function fromOptions(options) {
}
if (options.totalTX != null) {
assert(util.isU32(options.totalTX));
assert((options.totalTX >>> 0) === options.totalTX);
this.totalTX = options.totalTX;
}
@ -302,7 +302,7 @@ MerkleBlock.prototype.format = function format(view, height) {
hash: this.rhash(),
height: height != null ? height : -1,
date: util.date(this.time),
version: util.hex32(this.version),
version: this.version.toString(16),
prevBlock: util.revHex(this.prevBlock),
merkleRoot: util.revHex(this.merkleRoot),
time: this.time,
@ -468,7 +468,7 @@ MerkleBlock.prototype.fromJSON = function fromJSON(json) {
assert(json, 'MerkleBlock data is required.');
assert(Array.isArray(json.hashes));
assert(typeof json.flags === 'string');
assert(util.isU32(json.totalTX));
assert((json.totalTX >>> 0) === json.totalTX);
this.parseJSON(json);

View File

@ -8,7 +8,6 @@
'use strict';
const assert = require('assert');
const util = require('../utils/util');
const Script = require('../script/script');
const TX = require('./tx');
const Input = require('./input');
@ -66,7 +65,8 @@ Object.setPrototypeOf(MTX.prototype, TX.prototype);
MTX.prototype.fromOptions = function fromOptions(options) {
if (options.version != null) {
assert(util.isU32(options.version), 'Version must a be uint32.');
assert((options.version >>> 0) === options.version,
'Version must a be uint32.');
this.version = options.version;
}
@ -83,13 +83,14 @@ MTX.prototype.fromOptions = function fromOptions(options) {
}
if (options.locktime != null) {
assert(util.isU32(options.locktime), 'Locktime must be a uint32.');
assert((options.locktime >>> 0) === options.locktime,
'Locktime must be a uint32.');
this.locktime = options.locktime;
}
if (options.changeIndex != null) {
if (options.changeIndex !== -1) {
assert(util.isU32(options.changeIndex),
assert((options.changeIndex >>> 0) === options.changeIndex,
'Change index must be a uint32.');
this.changeIndex = options.changeIndex;
} else {
@ -221,12 +222,10 @@ MTX.prototype.addTX = function addTX(tx, index, height) {
MTX.prototype.addOutput = function addOutput(script, value) {
let output;
if (value != null) {
assert(util.isU64(value), 'Value must be a uint64.');
if (value != null)
output = Output.fromScript(script, value);
} else {
else
output = Output.fromOptions(script);
}
this.outputs.push(output);
@ -1378,8 +1377,8 @@ MTX.prototype.sortMembers = function sortMembers() {
MTX.prototype.avoidFeeSniping = function avoidFeeSniping(height) {
assert(typeof height === 'number', 'Must pass in height.');
if (util.random(0, 10) === 0) {
height -= util.random(0, 100);
if ((Math.random() * 10 | 0) === 0) {
height -= Math.random() * 100 | 0;
if (height < 0)
height = 0;
@ -1394,7 +1393,7 @@ MTX.prototype.avoidFeeSniping = function avoidFeeSniping(height) {
*/
MTX.prototype.setLocktime = function setLocktime(locktime) {
assert(util.isU32(locktime), 'Locktime must be a uint32.');
assert((locktime >>> 0) === locktime, 'Locktime must be a uint32.');
assert(this.inputs.length > 0, 'Cannot set sequence with no inputs.');
for (const input of this.inputs) {
@ -1416,7 +1415,7 @@ MTX.prototype.setSequence = function setSequence(index, locktime, seconds) {
const input = this.inputs[index];
assert(input, 'Input does not exist.');
assert(util.isU32(locktime), 'Locktime must be a uint32.');
assert((locktime >>> 0) === locktime, 'Locktime must be a uint32.');
this.version = 2;
@ -1619,7 +1618,7 @@ CoinSelector.prototype.fromOptions = function fromOptions(options) {
if (options.subtractFee != null) {
if (typeof options.subtractFee === 'number') {
assert(util.isInt(options.subtractFee));
assert(Number.isSafeInteger(options.subtractFee));
assert(options.subtractFee >= -1);
this.subtractIndex = options.subtractFee;
this.subtractFee = this.subtractIndex !== -1;
@ -1630,43 +1629,44 @@ CoinSelector.prototype.fromOptions = function fromOptions(options) {
}
if (options.subtractIndex != null) {
assert(util.isInt(options.subtractIndex));
assert(Number.isSafeInteger(options.subtractIndex));
assert(options.subtractIndex >= -1);
this.subtractIndex = options.subtractIndex;
this.subtractFee = this.subtractIndex !== -1;
}
if (options.height != null) {
assert(util.isInt(options.height));
assert(Number.isSafeInteger(options.height));
assert(options.height >= -1);
this.height = options.height;
}
if (options.confirmations != null) {
assert(util.isInt(options.confirmations));
assert(Number.isSafeInteger(options.confirmations));
assert(options.confirmations >= -1);
this.depth = options.confirmations;
}
if (options.depth != null) {
assert(util.isInt(options.depth));
assert(Number.isSafeInteger(options.depth));
assert(options.depth >= -1);
this.depth = options.depth;
}
if (options.hardFee != null) {
assert(util.isInt(options.hardFee));
assert(Number.isSafeInteger(options.hardFee));
assert(options.hardFee >= -1);
this.hardFee = options.hardFee;
}
if (options.rate != null) {
assert(util.isU64(options.rate));
assert(Number.isSafeInteger(options.rate));
assert(options.rate >= 0);
this.rate = options.rate;
}
if (options.maxFee != null) {
assert(util.isInt(options.maxFee));
assert(Number.isSafeInteger(options.maxFee));
assert(options.maxFee >= -1);
this.maxFee = options.maxFee;
}

View File

@ -439,9 +439,9 @@ NetAddress.prototype.toJSON = function toJSON() {
*/
NetAddress.prototype.fromJSON = function fromJSON(json) {
assert(util.isU16(json.port));
assert(util.isU32(json.services));
assert(util.isU32(json.time));
assert((json.port & 0xffff) === json.port);
assert((json.services >>> 0) === json.services);
assert((json.time >>> 0) === json.time);
this.raw = IP.toBuffer(json.host);
this.host = json.host;
this.port = json.port;

View File

@ -31,7 +31,7 @@ function Outpoint(hash, index) {
if (hash != null) {
assert(typeof hash === 'string', 'Hash must be a string.');
assert(util.isU32(index), 'Index must be a uint32.');
assert((index >>> 0) === index, 'Index must be a uint32.');
this.hash = hash;
this.index = index;
}
@ -46,7 +46,7 @@ function Outpoint(hash, index) {
Outpoint.prototype.fromOptions = function fromOptions(options) {
assert(options, 'Outpoint data is required.');
assert(typeof options.hash === 'string', 'Hash must be a string.');
assert(util.isU32(options.index), 'Index must be a uint32.');
assert((options.index >>> 0) === options.index, 'Index must be a uint32.');
this.hash = options.hash;
this.index = options.index;
return this;
@ -95,7 +95,7 @@ Outpoint.prototype.equals = function equals(prevout) {
Outpoint.prototype.compare = function compare(prevout) {
assert(Outpoint.isOutpoint(prevout));
const cmp = util.strcmp(this.txid(), prevout.txid());
const cmp = strcmp(this.txid(), prevout.txid());
if (cmp !== 0)
return cmp;
@ -245,7 +245,7 @@ Outpoint.fromRaw = function fromRaw(data) {
Outpoint.prototype.fromJSON = function fromJSON(json) {
assert(json, 'Outpoint data is required.');
assert(typeof json.hash === 'string', 'Hash must be a string.');
assert(util.isU32(json.index), 'Index must be a uint32.');
assert((json.index >>> 0) === json.index, 'Index must be a uint32.');
this.hash = util.revHex(json.hash);
this.index = json.index;
return this;
@ -337,6 +337,29 @@ Outpoint.isOutpoint = function isOutpoint(obj) {
return obj instanceof Outpoint;
};
/*
* Helpers
*/
function strcmp(a, b) {
const len = Math.min(a.length, b.length);
for (let i = 0; i < len; i++) {
if (a[i] < b[i])
return -1;
if (a[i] > b[i])
return 1;
}
if (a.length < b.length)
return -1;
if (a.length > b.length)
return 1;
return 0;
}
/*
* Expose
*/

View File

@ -8,7 +8,6 @@
'use strict';
const assert = require('assert');
const util = require('../utils/util');
const Amount = require('../btc/amount');
const Network = require('../protocol/network');
const Address = require('../primitives/address');
@ -48,7 +47,8 @@ Output.prototype.fromOptions = function fromOptions(options) {
assert(options, 'Output data is required.');
if (options.value) {
assert(util.isU64(options.value), 'Value must be a uint64.');
assert(Number.isSafeInteger(options.value) && options.value >= 0,
'Value must be a uint64.');
this.value = options.value;
}
@ -87,7 +87,7 @@ Output.prototype.fromScript = function fromScript(script, value) {
script = Script.fromAddress(script);
assert(script instanceof Script, 'Script must be a Script.');
assert(util.isU64(value), 'Value must be a uint64.');
assert(Number.isSafeInteger(value) && value >= 0, 'Value must be a uint64.');
this.script = script;
this.value = value;
@ -278,7 +278,8 @@ Output.prototype.isDust = function isDust(rate) {
Output.prototype.fromJSON = function fromJSON(json) {
assert(json, 'Output data is required.');
assert(util.isU64(json.value), 'Value must be a uint64.');
assert(Number.isSafeInteger(json.value) && json.value >= 0,
'Value must be a uint64.');
this.value = json.value;
this.script.fromJSON(json.script);
return this;

View File

@ -8,10 +8,10 @@
'use strict';
const assert = require('assert');
const util = require('../utils/util');
const encoding = require('../utils/encoding');
const digest = require('bcrypto/lib/digest');
const secp256k1 = require('bcrypto/lib/secp256k1');
const util = require('../utils/util');
const encoding = require('../utils/encoding');
const Amount = require('../btc/amount');
const Network = require('../protocol/network');
const Script = require('../script/script');
@ -80,7 +80,8 @@ TX.prototype.fromOptions = function fromOptions(options) {
assert(options, 'TX data is required.');
if (options.version != null) {
assert(util.isU32(options.version), 'Version must be a uint32.');
assert((options.version >>> 0) === options.version,
'Version must be a uint32.');
this.version = options.version;
}
@ -97,7 +98,8 @@ TX.prototype.fromOptions = function fromOptions(options) {
}
if (options.locktime != null) {
assert(util.isU32(options.locktime), 'Locktime must be a uint32.');
assert((options.locktime >>> 0) === options.locktime,
'Locktime must be a uint32.');
this.locktime = options.locktime;
}
@ -2194,10 +2196,10 @@ TX.prototype.getJSON = function getJSON(network, view, entry, index) {
TX.prototype.fromJSON = function fromJSON(json) {
assert(json, 'TX data is required.');
assert(util.isU32(json.version), 'Version must be a uint32.');
assert((json.version >>> 0) === json.version, 'Version must be a uint32.');
assert(Array.isArray(json.inputs), 'Inputs must be an array.');
assert(Array.isArray(json.outputs), 'Outputs must be an array.');
assert(util.isU32(json.locktime), 'Locktime must be a uint32.');
assert((json.locktime >>> 0) === json.locktime, 'Locktime must be a uint32.');
this.version = json.version;

View File

@ -47,12 +47,12 @@ TXMeta.prototype.fromOptions = function fromOptions(options) {
}
if (options.mtime != null) {
assert(util.isU32(options.mtime));
assert((options.mtime >>> 0) === options.mtime);
this.mtime = options.mtime;
}
if (options.height != null) {
assert(util.isInt(options.height));
assert(Number.isSafeInteger(options.height));
this.height = options.height;
}
@ -62,12 +62,12 @@ TXMeta.prototype.fromOptions = function fromOptions(options) {
}
if (options.time != null) {
assert(util.isU32(options.time));
assert((options.time >>> 0) === options.time);
this.time = options.time;
}
if (options.index != null) {
assert(util.isInt(options.index));
assert(Number.isSafeInteger(options.index));
this.index = options.index;
}
@ -174,11 +174,11 @@ TXMeta.prototype.getJSON = function getJSON(network, view, chainHeight) {
TXMeta.prototype.fromJSON = function fromJSON(json) {
this.tx.fromJSON(json);
assert(util.isU32(json.mtime));
assert(util.isInt(json.height));
assert((json.mtime >>> 0) === json.mtime);
assert(Number.isSafeInteger(json.height));
assert(!json.block || typeof json.block === 'string');
assert(util.isU32(json.time));
assert(util.isInt(json.index));
assert((json.time >>> 0) === json.time);
assert(Number.isSafeInteger(json.index));
this.mtime = json.mtime;
this.height = json.height;

View File

@ -8,7 +8,7 @@
'use strict';
const assert = require('assert');
const util = require('../utils/util');
const binary = require('../utils/binary');
const networks = require('./networks');
const consensus = require('./consensus');
const TimeData = require('./timedata');
@ -115,7 +115,7 @@ Network.prototype._init = function _init() {
*/
Network.prototype.byBit = function byBit(bit) {
const index = util.binarySearch(this.deploys, bit, cmpBit);
const index = binary.search(this.deploys, bit, cmpBit);
if (index === -1)
return null;

View File

@ -9,6 +9,7 @@
const EventEmitter = require('events');
const util = require('../utils/util');
const binary = require('../utils/binary');
/**
* An object which handles "adjusted time". This may not
@ -59,7 +60,7 @@ TimeData.prototype.add = function add(id, time) {
this.known.set(id, sample);
util.binaryInsert(this.samples, sample, compare);
binary.insert(this.samples, sample, compare);
this.emit('sample', sample, this.samples.length);
@ -126,7 +127,7 @@ TimeData.prototype.local = function local(time) {
*/
TimeData.prototype.ms = function ms() {
return util.ms() + this.offset * 1000;
return Date.now() + this.offset * 1000;
};
/*

View File

@ -9,7 +9,6 @@
const assert = require('assert');
const ScriptNum = require('./scriptnum');
const util = require('../utils/util');
const common = require('./common');
const BufferReader = require('../utils/reader');
const StaticWriter = require('../utils/staticwriter');
@ -268,7 +267,7 @@ Opcode.prototype.toSymbol = function toSymbol() {
const symbol = common.opcodesByVal[this.value];
if (!symbol)
return `0x${util.hex8(this.value)}`;
return `0x${hex8(this.value)}`;
return symbol;
};
@ -366,7 +365,7 @@ Opcode.prototype.toFormat = function toFormat() {
// Direct push
if (!symbol) {
const size = util.hex8(this.value);
const size = hex8(this.value);
return `0x${size} 0x${data}`;
}
@ -385,7 +384,7 @@ Opcode.prototype.toFormat = function toFormat() {
return symbol;
// Unknown opcodes
const value = util.hex8(this.value);
const value = hex8(this.value);
return `0x${value}`;
};
@ -492,7 +491,7 @@ Opcode.fromString = function fromString(str, enc) {
*/
Opcode.fromSmall = function fromSmall(num) {
assert(util.isU8(num) && num >= 0 && num <= 16);
assert((num & 0xff) === num && num >= 0 && num <= 16);
return Opcode.fromOp(num === 0 ? 0 : num + 0x50);
};
@ -514,7 +513,7 @@ Opcode.fromNum = function fromNum(num) {
*/
Opcode.fromInt = function fromInt(num) {
assert(util.isInt(num));
assert(Number.isSafeInteger(num));
if (num === 0)
return Opcode.fromOp(opcodes.OP_0);
@ -551,10 +550,10 @@ Opcode.fromSymbol = function fromSymbol(name) {
assert(typeof name === 'string');
assert(name.length > 0);
if (!util.isUpperCase(name))
if (name.charCodeAt(0) & 32)
name = name.toUpperCase();
if (!util.startsWith(name, 'OP_'))
if (!/^OP_/.test(name))
name = `OP_${name}`;
const op = common.opcodes[name];
@ -562,12 +561,12 @@ Opcode.fromSymbol = function fromSymbol(name) {
if (op != null)
return Opcode.fromOp(op);
assert(util.startsWith(name, 'OP_0X'), 'Unknown opcode.');
assert(/^OP_0X/.test(name), 'Unknown opcode.');
assert(name.length === 7, 'Unknown opcode.');
const value = parseInt(name.substring(5), 16);
assert(util.isU8(value), 'Unknown opcode.');
assert((value & 0xff) === value, 'Unknown opcode.');
return Opcode.fromOp(value);
};
@ -668,6 +667,16 @@ Opcode.isOpcode = function isOpcode(obj) {
return obj instanceof Opcode;
};
/*
* Helpers
*/
function hex8(num) {
if (num <= 0x0f)
return '0' + num.toString(16);
return num.toString(16);
}
/*
* Fill Cache
*/

View File

@ -8,7 +8,6 @@
'use strict';
const assert = require('assert');
const util = require('../utils/util');
const common = require('./common');
const scriptTypes = common.types;
@ -29,7 +28,7 @@ function Program(version, data) {
if (!(this instanceof Program))
return new Program(version, data);
assert(util.isU8(version));
assert((version & 0xff) === version);
assert(version >= 0 && version <= 16);
assert(Buffer.isBuffer(data));
assert(data.length >= 2 && data.length <= 40);

View File

@ -8,11 +8,11 @@
'use strict';
const assert = require('assert');
const consensus = require('../protocol/consensus');
const policy = require('../protocol/policy');
const util = require('../utils/util');
const digest = require('bcrypto/lib/digest');
const merkle = require('bcrypto/lib/merkle');
const secp256k1 = require('bcrypto/lib/secp256k1');
const consensus = require('../protocol/consensus');
const policy = require('../protocol/policy');
const BufferWriter = require('../utils/writer');
const BufferReader = require('../utils/reader');
const StaticWriter = require('../utils/staticwriter');
@ -23,7 +23,6 @@ const ScriptError = require('./scripterror');
const ScriptNum = require('./scriptnum');
const common = require('./common');
const encoding = require('../utils/encoding');
const secp256k1 = require('bcrypto/lib/secp256k1');
const Address = require('../primitives/address');
const opcodes = common.opcodes;
const scriptTypes = common.types;
@ -1513,7 +1512,7 @@ Script.fromPubkeyhash = function fromPubkeyhash(hash) {
*/
Script.prototype.fromMultisig = function fromMultisig(m, n, keys) {
assert(util.isU8(m) && util.isU8(n));
assert((m & 0xff) === m && (n & 0xff) === n);
assert(Array.isArray(keys));
assert(keys.length === n, '`n` keys are required for multisig.');
assert(m >= 1 && m <= n);
@ -1614,7 +1613,7 @@ Script.fromNulldata = function fromNulldata(flags) {
*/
Script.prototype.fromProgram = function fromProgram(version, data) {
assert(util.isU8(version) && version >= 0 && version <= 16);
assert((version & 0xff) === version && version >= 0 && version <= 16);
assert(Buffer.isBuffer(data) && data.length >= 2 && data.length <= 40);
this.raw = Buffer.allocUnsafe(2 + data.length);
@ -3082,10 +3081,10 @@ Script.prototype.fromString = function fromString(code) {
for (const item of items) {
let symbol = item;
if (!util.isUpperCase(symbol))
if (symbol.charCodeAt(0) & 32)
symbol = symbol.toUpperCase();
if (!util.startsWith(symbol, 'OP_'))
if (!/^OP_/.test(symbol))
symbol = `OP_${symbol}`;
const value = opcodes[symbol];

View File

@ -7,7 +7,6 @@
'use strict';
const assert = require('assert');
const util = require('../utils/util');
const secp256k1 = require('bcrypto/lib/secp256k1');
/**
@ -27,7 +26,7 @@ function SigCache(size) {
if (size == null)
size = 10000;
assert(util.isU32(size));
assert((size >>> 0) === size);
this.size = size;
this.keys = [];
@ -40,7 +39,7 @@ function SigCache(size) {
*/
SigCache.prototype.resize = function resize(size) {
assert(util.isU32(size));
assert((size >>> 0) === size);
this.size = size;
this.keys.length = 0;

View File

@ -8,7 +8,6 @@
'use strict';
const assert = require('assert');
const util = require('../utils/util');
const Script = require('./script');
const common = require('./common');
const encoding = require('../utils/encoding');

View File

@ -150,3 +150,14 @@ exports.decode = function decode(str) {
if (native)
exports.decode = native.fromBase58;
/**
* Test whether a string is base58 (note that you
* may get a false positive on a hex string).
* @param {String?} str
* @returns {Boolean}
*/
exports.isBase58 = function isBase58(str) {
return typeof str === 'string' && /^[1-9A-Za-z]+$/.test(str);
};

View File

@ -312,6 +312,27 @@ function decode(str) {
if (native)
decode = native.fromBech32;
/**
* Test whether a string is bech32 (note that
* this doesn't guarantee address is bech32).
* @param {String?} str
* @returns {Boolean}
*/
function isBech32(str) {
if (typeof str !== 'string')
return false;
if (str.toUpperCase() !== str && str.toLowerCase() !== str)
return false;
if (str.length < 8 || str.length > 90)
return false;
// it's unlikely any network will have hrp other than a-z symbols.
return /^[a-zA-Z]{1,3}1[qpzry9x8gf2tvdw0s3jn54khce6mua7l]+$/i.test(str);
}
/**
* AddrResult
* @constructor
@ -339,3 +360,4 @@ exports.serialize = serialize;
exports.convert = convert;
exports.encode = encode;
exports.decode = decode;
exports.isBech32 = isBech32;

85
lib/utils/binary.js Normal file
View File

@ -0,0 +1,85 @@
/*!
* binary.js - binary search utils for bcoin
* Copyright (c) 2014-2015, Fedor Indutny (MIT License)
* Copyright (c) 2014-2017, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
/**
* Perform a binary search on a sorted array.
* @param {Array} items
* @param {Object} key
* @param {Function} compare
* @param {Boolean?} insert
* @returns {Number} Index.
*/
exports.search = function search(items, key, compare, insert) {
let start = 0;
let end = items.length - 1;
while (start <= end) {
const pos = (start + end) >>> 1;
const cmp = compare(items[pos], key);
if (cmp === 0)
return pos;
if (cmp < 0)
start = pos + 1;
else
end = pos - 1;
}
if (!insert)
return -1;
return start;
};
/**
* Perform a binary insert on a sorted array.
* @param {Array} items
* @param {Object} item
* @param {Function} compare
* @returns {Number} index
*/
exports.insert = function insert(items, item, compare, uniq) {
const i = exports.search(items, item, compare, true);
if (uniq && i < items.length) {
if (compare(items[i], item) === 0)
return -1;
}
if (i === 0)
items.unshift(item);
else if (i === items.length)
items.push(item);
else
items.splice(i, 0, item);
return i;
};
/**
* Perform a binary removal on a sorted array.
* @param {Array} items
* @param {Object} item
* @param {Function} compare
* @returns {Boolean}
*/
exports.remove = function remove(items, item, compare) {
const i = exports.search(items, item, compare, false);
if (i === -1)
return false;
items.splice(i, 1);
return true;
};

View File

@ -1,165 +0,0 @@
/*!
* enforce.js - type enforcement for bcoin
* Copyright (c) 2014-2017, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
const util = require('./util');
function enforce(value, name, type, func) {
if (!value) {
if (!func)
func = enforce;
if (name && !type)
throwError(name, func);
if (!name)
name = 'value';
throwError(`'${name}' must be a(n) ${type}.`, func);
}
}
function throwError(msg, func) {
const error = new TypeError(msg);
if (Error.captureStackTrace && func)
Error.captureStackTrace(error, func);
throw error;
}
enforce.none = function none(value, name) {
enforce(value == null, name, 'object', none);
};
enforce.nul = function nul(value, name) {
enforce(value === null, name, 'object', nul);
};
enforce.undef = function undef(value, name) {
enforce(value === undefined, name, 'object', undef);
};
enforce.str = function str(value, name) {
enforce(typeof value === 'string', name, 'string', str);
};
enforce.bool = function bool(value, name) {
enforce(typeof value === 'boolean', name, 'boolean', bool);
};
enforce.num = function num(value, name) {
enforce(util.isNumber(value), name, 'number', num);
};
enforce.obj = function obj(v, name) {
enforce(v && typeof v === 'object' && !Array.isArray(v), name, 'object', obj);
};
enforce.array = function array(value, name) {
enforce(Array.isArray(value), name, 'object', array);
};
enforce.func = function func(value, name) {
enforce(typeof value === 'function', name, 'function', func);
};
enforce.error = function error(value, name) {
enforce(value instanceof Error, name, 'object', error);
};
enforce.regexp = function regexp(value, name) {
enforce(value && typeof value.exec === 'function' , name, 'object', regexp);
};
enforce.buf = function buf(value, name) {
enforce(Buffer.isBuffer(value), name, 'buffer', buf);
};
enforce.len = function len(value, length, name) {
if ((typeof value !== 'string' && !value) || value.length !== length) {
if (!name)
name = 'value';
throwError(`'${name}' must have a length of ${length}.`, len);
}
};
enforce.instance = function instance(obj, parent, name) {
if (!(obj instanceof parent)) {
if (!name)
name = 'value';
throwError(`'${name}' must be an instance of ${parent.name}.`, instance);
}
};
enforce.uint = function uint(value, name) {
enforce(util.isUInt(value), name, 'uint', uint);
};
enforce.int = function int(value, name) {
enforce(util.isInt(value), name, 'int', int);
};
enforce.u8 = function u8(value, name) {
enforce(util.isU8(value), name, 'uint8', u8);
};
enforce.u16 = function u16(value, name) {
enforce(util.isU16(value), name, 'uint16', u16);
};
enforce.u32 = function u32(value, name) {
enforce(util.isU32(value), name, 'uint32', u32);
};
enforce.u64 = function u64(value, name) {
enforce(util.isU64(value), name, 'uint64', u64);
};
enforce.i8 = function i8(value, name) {
enforce(util.isI8(value), name, 'int8', i8);
};
enforce.i16 = function i16(value, name) {
enforce(util.isI16(value), name, 'int16', i16);
};
enforce.i32 = function i32(value, name) {
enforce(util.isI32(value), name, 'int32', i32);
};
enforce.i64 = function i64(value, name) {
enforce(util.isI64(value), name, 'int64', i64);
};
enforce.ufloat = function ufloat(value, name) {
enforce(util.isUfloat(value), name, 'positive float', ufloat);
};
enforce.float = function float(value, name) {
enforce(util.isFloat(value), name, 'float', float);
};
enforce.ascii = function ascii(value, name) {
enforce(util.isAscii(value), name, 'ascii string', ascii);
};
enforce.hex = function hex(value, name) {
enforce(util.isHex(value), name, 'hex string', hex);
};
enforce.hex160 = function hex160(value, name) {
enforce(util.isHex160(value), name, '160 bit hex string', hex160);
};
enforce.hex256 = function hex256(value, name) {
enforce(util.isHex256(value), name, '256 bit hex string', hex256);
};
enforce.base58 = function base58(value, name) {
enforce(util.isBase58(value), name, 'base58 string', base58);
};
module.exports = enforce;

216
lib/utils/fixed.js Normal file
View File

@ -0,0 +1,216 @@
/*!
* fixed.js - fixed number parsing
* Copyright (c) 2017, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
const assert = require('assert');
/**
* Convert int to fixed number string and reduce by a
* power of ten (uses no floating point arithmetic).
* @param {Number} num
* @param {Number} exp - Number of decimal places.
* @returns {String} Fixed number string.
*/
exports.encode = function encode(num, exp) {
assert(Number.isSafeInteger(num), 'Invalid integer value.');
let sign = '';
if (num < 0) {
num = -num;
sign = '-';
}
const mult = pow10(exp);
let lo = num % mult;
let hi = (num - lo) / mult;
lo = lo.toString(10);
hi = hi.toString(10);
while (lo.length < exp)
lo = '0' + lo;
lo = lo.replace(/0+$/, '');
assert(lo.length <= exp, 'Invalid integer value.');
if (lo.length === 0)
lo = '0';
if (exp === 0)
return `${sign}${hi}`;
return `${sign}${hi}.${lo}`;
};
/**
* Parse a fixed number string and multiply by a
* power of ten (uses no floating point arithmetic).
* @param {String} str
* @param {Number} exp - Number of decimal places.
* @returns {Number} Integer.
*/
exports.decode = function decode(str, exp) {
assert(typeof str === 'string');
assert(str.length <= 32, 'Fixed number string too large.');
let sign = 1;
if (str.length > 0 && str[0] === '-') {
str = str.substring(1);
sign = -1;
}
let hi = str;
let lo = '0';
const index = str.indexOf('.');
if (index !== -1) {
hi = str.substring(0, index);
lo = str.substring(index + 1);
}
hi = hi.replace(/^0+/, '');
lo = lo.replace(/0+$/, '');
assert(hi.length <= 16 - exp,
'Fixed number string exceeds 2^53-1.');
assert(lo.length <= exp,
'Too many decimal places in fixed number string.');
if (hi.length === 0)
hi = '0';
while (lo.length < exp)
lo += '0';
if (lo.length === 0)
lo = '0';
assert(/^\d+$/.test(hi) && /^\d+$/.test(lo),
'Non-numeric characters in fixed number string.');
hi = parseInt(hi, 10);
lo = parseInt(lo, 10);
const mult = pow10(exp);
const maxLo = modSafe(mult);
const maxHi = divSafe(mult);
assert(hi < maxHi || (hi === maxHi && lo <= maxLo),
'Fixed number string exceeds 2^53-1.');
return sign * (hi * mult + lo);
};
/**
* Convert int to float and reduce by a power
* of ten (uses no floating point arithmetic).
* @param {Number} num
* @param {Number} exp - Number of decimal places.
* @returns {Number} Double float.
*/
exports.toFloat = function toFloat(num, exp) {
return parseFloat(exports.encode(num, exp));
};
/**
* Parse a double float number and multiply by a
* power of ten (uses no floating point arithmetic).
* @param {Number} num
* @param {Number} exp - Number of decimal places.
* @returns {Number} Integer.
*/
exports.fromFloat = function fromFloat(num, exp) {
assert(typeof num === 'number' && isFinite(num));
assert(Number.isSafeInteger(exp));
return exports.decode(num.toFixed(exp), exp);
};
/*
* Helpers
*/
function pow10(exp) {
switch (exp) {
case 0:
return 1;
case 1:
return 10;
case 2:
return 100;
case 3:
return 1000;
case 4:
return 10000;
case 5:
return 100000;
case 6:
return 1000000;
case 7:
return 10000000;
case 8:
return 100000000;
}
throw new Error('Exponent is too large.');
}
function modSafe(mod) {
switch (mod) {
case 1:
return 0;
case 10:
return 1;
case 100:
return 91;
case 1000:
return 991;
case 10000:
return 991;
case 100000:
return 40991;
case 1000000:
return 740991;
case 10000000:
return 4740991;
case 100000000:
return 54740991;
}
throw new Error('Exponent is too large.');
}
function divSafe(div) {
switch (div) {
case 1:
return 9007199254740991;
case 10:
return 900719925474099;
case 100:
return 90071992547409;
case 1000:
return 9007199254740;
case 10000:
return 900719925474;
case 100000:
return 90071992547;
case 1000000:
return 9007199254;
case 10000000:
return 900719925;
case 100000000:
return 90071992;
}
throw new Error('Exponent is too large.');
}

500
lib/utils/hashwriter.js Normal file
View File

@ -0,0 +1,500 @@
/*!
* staticwriter.js - buffer writer for bcoin
* Copyright (c) 2014-2017, Christopher Jeffrey (MIT License).
* https://github.com/bcoin-org/bcoin
*/
'use strict';
const assert = require('assert');
const encoding = require('./encoding');
const POOL0 = Buffer.allocUnsafe(0);
const POOL8 = Buffer.allocUnsafe(1);
const POOL16 = Buffer.allocUnsafe(2);
const POOL24 = Buffer.allocUnsafe(3);
const POOL32 = Buffer.allocUnsafe(4);
const POOL40 = Buffer.allocUnsafe(5);
const POOL48 = Buffer.allocUnsafe(6);
const POOL56 = Buffer.allocUnsafe(7);
const POOL64 = Buffer.allocUnsafe(8);
const POOL72 = Buffer.allocUnsafe(9);
const POOL256 = Buffer.allocUnsafe(32);
const poolBySize = [
POOL0,
POOL8,
POOL16,
POOL24,
POOL32,
POOL40,
POOL48,
POOL56,
POOL64,
POOL72
];
/**
* Statically allocated buffer writer.
* @alias module:utils.HashWriter
* @constructor
* @param {Number} size
*/
function HashWriter(Hash, ...args) {
if (!(this instanceof HashWriter))
return new HashWriter(Hash, ...args);
this.ctx = new Hash().init(...args);
}
/**
* Allocate and render the final buffer.
* @returns {Buffer} Rendered buffer.
*/
HashWriter.prototype.init = function init(...args) {
return this.ctx.init(...args);
};
/**
* Allocate and render the final buffer.
* @returns {Buffer} Rendered buffer.
*/
HashWriter.prototype.update = function update(data) {
return this.ctx.update(data);
};
/**
* Allocate and render the final buffer.
* @returns {Buffer} Rendered buffer.
*/
HashWriter.prototype.final = function final() {
return this.ctx.final();
};
/**
* Get size of data written so far.
* @returns {Number}
*/
HashWriter.prototype.getSize = function getSize() {
assert(false);
};
/**
* Seek to relative offset.
* @param {Number} offset
*/
HashWriter.prototype.seek = function seek(offset) {
assert(false);
};
/**
* Destroy the buffer writer.
*/
HashWriter.prototype.destroy = function destroy() {
assert(false);
};
/**
* Write uint8.
* @param {Number} value
*/
HashWriter.prototype.writeU8 = function writeU8(value) {
POOL8.writeUInt8(value, 0, true);
this.ctx.update(POOL8);
};
/**
* Write uint16le.
* @param {Number} value
*/
HashWriter.prototype.writeU16 = function writeU16(value) {
POOL16.writeUInt16LE(value, 0, true);
this.ctx.update(POOL16);
};
/**
* Write uint16be.
* @param {Number} value
*/
HashWriter.prototype.writeU16BE = function writeU16BE(value) {
POOL16.writeUInt16BE(value, 0, true);
this.ctx.update(POOL16);
};
/**
* Write uint32le.
* @param {Number} value
*/
HashWriter.prototype.writeU32 = function writeU32(value) {
POOL32.writeUInt32LE(value, 0, true);
this.ctx.update(POOL32);
};
/**
* Write uint32be.
* @param {Number} value
*/
HashWriter.prototype.writeU32BE = function writeU32BE(value) {
POOL32.writeUInt32BE(value, 0, true);
this.ctx.update(POOL32);
};
/**
* Write uint64le.
* @param {Number} value
*/
HashWriter.prototype.writeU64 = function writeU64(value) {
encoding.writeU64(POOL64, value, 0);
this.ctx.update(POOL64);
};
/**
* Write uint64be.
* @param {Number} value
*/
HashWriter.prototype.writeU64BE = function writeU64BE(value) {
encoding.writeU64BE(POOL64, value, 0);
this.ctx.update(POOL64);
};
/**
* Write uint64le.
* @param {U64} value
*/
HashWriter.prototype.writeU64N = function writeU64N(value) {
encoding.writeU64N(POOL64, value, 0);
this.ctx.update(POOL64);
};
/**
* Write uint64be.
* @param {U64} value
*/
HashWriter.prototype.writeU64BEN = function writeU64BEN(value) {
encoding.writeU64BEN(POOL64, value, 0);
this.ctx.update(POOL64);
};
/**
* Write int8.
* @param {Number} value
*/
HashWriter.prototype.writeI8 = function writeI8(value) {
POOL8.writeInt8(value, 0, true);
this.ctx.update(POOL8);
};
/**
* Write int16le.
* @param {Number} value
*/
HashWriter.prototype.writeI16 = function writeI16(value) {
POOL16.writeInt16LE(value, 0, true);
this.ctx.update(POOL16);
};
/**
* Write int16be.
* @param {Number} value
*/
HashWriter.prototype.writeI16BE = function writeI16BE(value) {
POOL16.writeInt16BE(value, 0, true);
this.ctx.update(POOL16);
};
/**
* Write int32le.
* @param {Number} value
*/
HashWriter.prototype.writeI32 = function writeI32(value) {
POOL32.writeInt32LE(value, 0, true);
this.ctx.update(POOL32);
};
/**
* Write int32be.
* @param {Number} value
*/
HashWriter.prototype.writeI32BE = function writeI32BE(value) {
POOL32.writeInt32BE(value, 0, true);
this.ctx.update(POOL32);
};
/**
* Write int64le.
* @param {Number} value
*/
HashWriter.prototype.writeI64 = function writeI64(value) {
encoding.writeI64(POOL64, value, 0);
this.ctx.update(POOL64);
};
/**
* Write int64be.
* @param {Number} value
*/
HashWriter.prototype.writeI64BE = function writeI64BE(value) {
encoding.writeI64BE(POOL64, value, 0);
this.ctx.update(POOL64);
};
/**
* Write int64le.
* @param {I64} value
*/
HashWriter.prototype.writeI64N = function writeI64N(value) {
encoding.writeI64N(POOL64, value, 0);
this.ctx.update(POOL64);
};
/**
* Write int64be.
* @param {I64} value
*/
HashWriter.prototype.writeI64BEN = function writeI64BEN(value) {
encoding.writeI64BEN(POOL64, value, 0);
this.ctx.update(POOL64);
};
/**
* Write float le.
* @param {Number} value
*/
HashWriter.prototype.writeFloat = function writeFloat(value) {
POOL32.writeFloatLE(value, 0, true);
this.ctx.update(POOL32);
};
/**
* Write float be.
* @param {Number} value
*/
HashWriter.prototype.writeFloatBE = function writeFloatBE(value) {
POOL32.writeFloatBE(value, 0, true);
this.ctx.update(POOL32);
};
/**
* Write double le.
* @param {Number} value
*/
HashWriter.prototype.writeDouble = function writeDouble(value) {
POOL64.writeDoubleLE(value, 0, true);
this.ctx.update(POOL64);
};
/**
* Write double be.
* @param {Number} value
*/
HashWriter.prototype.writeDoubleBE = function writeDoubleBE(value) {
POOL64.writeDoubleBE(value, 0, true);
this.ctx.update(POOL64);
};
/**
* Write a varint.
* @param {Number} value
*/
HashWriter.prototype.writeVarint = function writeVarint(value) {
const size = encoding.sizeVarint(value);
const pool = poolBySize[size];
encoding.writeVarint(pool, value, 0);
this.ctx.update(pool);
};
/**
* Write a varint.
* @param {U64} value
*/
HashWriter.prototype.writeVarintN = function writeVarintN(value) {
const size = encoding.sizeVarintN(value);
const pool = poolBySize[size];
encoding.writeVarintN(pool, value, 0);
this.ctx.update(pool);
};
/**
* Write a varint (type 2).
* @param {Number} value
*/
HashWriter.prototype.writeVarint2 = function writeVarint2(value) {
const size = encoding.sizeVarint2(value);
const pool = poolBySize[size];
encoding.writeVarint2(pool, value, 0);
this.ctx.update(pool);
};
/**
* Write a varint (type 2).
* @param {U64} value
*/
HashWriter.prototype.writeVarint2N = function writeVarint2N(value) {
const size = encoding.sizeVarint2N(value);
const pool = poolBySize[size];
encoding.writeVarint2N(pool, value, 0);
this.ctx.update(pool);
};
/**
* Write bytes.
* @param {Buffer} value
*/
HashWriter.prototype.writeBytes = function writeBytes(value) {
this.ctx.update(value);
};
/**
* Write bytes with a varint length before them.
* @param {Buffer} value
*/
HashWriter.prototype.writeVarBytes = function writeVarBytes(value) {
this.writeVarint(value.length);
this.writeBytes(value);
};
/**
* Copy bytes.
* @param {Buffer} value
* @param {Number} start
* @param {Number} end
*/
HashWriter.prototype.copy = function copy(value, start, end) {
this.ctx.update(value.slice(start, end));
};
/**
* Write string to buffer.
* @param {String} value
* @param {String?} enc - Any buffer-supported encoding.
*/
HashWriter.prototype.writeString = function writeString(value, enc) {
if (value.length === 0)
return;
if (typeof value === 'string')
value = Buffer.from(value, enc);
this.ctx.update(value);
};
/**
* Write a 32 byte hash.
* @param {Hash} value
*/
HashWriter.prototype.writeHash = function writeHash(value) {
if (typeof value !== 'string') {
assert(value.length === 32);
this.writeBytes(value);
return;
}
assert(value.length === 64);
POOL256.write(value, 0, 'hex');
this.ctx.update(POOL256);
};
/**
* Write a string with a varint length before it.
* @param {String}
* @param {String?} enc - Any buffer-supported encoding.
*/
HashWriter.prototype.writeVarString = function writeVarString(value, enc) {
if (value.length === 0) {
this.writeVarint(0);
return;
}
const size = Buffer.byteLength(value, enc);
this.writeVarint(size);
this.ctx.update(value, enc);
};
/**
* Write a null-terminated string.
* @param {String|Buffer}
* @param {String?} enc - Any buffer-supported encoding.
*/
HashWriter.prototype.writeNullString = function writeNullString(value, enc) {
this.writeString(value, enc);
this.writeU8(0);
};
/**
* Calculate and write a checksum for the data written so far.
*/
HashWriter.prototype.writeChecksum = function writeChecksum() {
assert(false);
};
/**
* Fill N bytes with value.
* @param {Number} value
* @param {Number} size
*/
HashWriter.prototype.fill = function fill(value, size) {
assert(size >= 0);
if (size === 0)
return;
if (size <= 32) {
const data = POOL256.slice(0, size);
data.fill(value);
this.ctx.update(data);
return;
}
const data = Buffer.allocUnsafe(size);
data.fill(value);
this.ctx.update(data);
};
/*
* Expose
*/
module.exports = HashWriter;

View File

@ -19,6 +19,7 @@ exports.Bloom = require('./bloom');
exports.co = require('./co');
exports.encoding = require('./encoding');
exports.enforce = require('./enforce');
exports.fixed = require('./fixed');
exports.fs = require('./fs');
exports.GCSFilter = require('./gcs');
exports.Heap = require('./heap');

View File

@ -8,7 +8,6 @@
'use strict';
const assert = require('assert');
const nodeUtil = require('util');
/**
* @exports utils/util
@ -16,367 +15,6 @@ const nodeUtil = require('util');
const util = exports;
/*
* Constants
*/
const inspectOptions = {
showHidden: false,
depth: 20,
colors: false,
customInspect: true,
showProxy: false,
maxArrayLength: Infinity,
breakLength: 60
};
/**
* Test whether a number is Number,
* finite, and below MAX_SAFE_INTEGER.
* @param {Number?} value
* @returns {Boolean}
*/
util.isNumber = function isNumber(value) {
return typeof value === 'number'
&& isFinite(value)
&& value >= -Number.MAX_SAFE_INTEGER
&& value <= Number.MAX_SAFE_INTEGER;
};
/**
* Test whether an object is an int.
* @param {Number?} value
* @returns {Boolean}
*/
util.isInt = function isInt(value) {
return Number.isSafeInteger(value);
};
/**
* Test whether an object is a uint.
* @param {Number?} value
* @returns {Boolean}
*/
util.isUint = function isUint(value) {
return util.isInt(value) && value >= 0;
};
/**
* Test whether a number is a float.
* @param {Number?} value
* @returns {Boolean}
*/
util.isFloat = function isFloat(value) {
return typeof value === 'number' && isFinite(value);
};
/**
* Test whether a number is a positive float.
* @param {Number?} value
* @returns {Boolean}
*/
util.isUfloat = function isUfloat(value) {
return util.isFloat(value) && value >= 0;
};
/**
* Test whether an object is an int8.
* @param {Number?} value
* @returns {Boolean}
*/
util.isI8 = function isI8(value) {
return (value | 0) === value && value >= -0x80 && value <= 0x7f;
};
/**
* Test whether an object is an int16.
* @param {Number?} value
* @returns {Boolean}
*/
util.isI16 = function isI16(value) {
return (value | 0) === value && value >= -0x8000 && value <= 0x7fff;
};
/**
* Test whether an object is an int32.
* @param {Number?} value
* @returns {Boolean}
*/
util.isI32 = function isI32(value) {
return (value | 0) === value;
};
/**
* Test whether an object is a int53.
* @param {Number?} value
* @returns {Boolean}
*/
util.isI64 = function isI64(value) {
return util.isInt(value);
};
/**
* Test whether an object is a uint8.
* @param {Number?} value
* @returns {Boolean}
*/
util.isU8 = function isU8(value) {
return (value & 0xff) === value;
};
/**
* Test whether an object is a uint16.
* @param {Number?} value
* @returns {Boolean}
*/
util.isU16 = function isU16(value) {
return (value & 0xffff) === value;
};
/**
* Test whether an object is a uint32.
* @param {Number?} value
* @returns {Boolean}
*/
util.isU32 = function isU32(value) {
return (value >>> 0) === value;
};
/**
* Test whether an object is a uint53.
* @param {Number?} value
* @returns {Boolean}
*/
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 bech32 (note that
* this doesn't guarantee address is bech32).
* @param {String?} str
* @returns {Boolean}
*/
util.isBech32 = function isBech32(str) {
if (typeof str !== 'string')
return false;
if (str.toUpperCase() !== str && str.toLowerCase() !== str)
return false;
if (str.length < 8 || str.length > 90)
return false;
// it's unlikely any network will have hrp other than a-z symbols.
return /^[a-z]{2}1[qpzry9x8gf2tvdw0s3jn54khce6mua7l]+$/i.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 str.length % 2 === 0 && /^[0-9A-Fa-f]+$/.test(str);
};
/**
* Test whether an object is a 160 bit hash (hex string).
* @param {String?} hash
* @returns {Boolean}
*/
util.isHex160 = function isHex160(hash) {
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?} hash
* @returns {Boolean}
*/
util.isHex256 = function isHex256(hash) {
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;
};
/**
* util.inspect() with 20 levels of depth.
* @param {Object|String} obj
* @param {Boolean?} color
* @return {String}
*/
util.inspectify = function inspectify(obj, color) {
if (typeof obj === 'string')
return obj;
inspectOptions.colors = color !== false;
return nodeUtil.inspect(obj, inspectOptions);
};
/**
* Format a string.
* @function
* @param {...String} args
* @returns {String}
*/
util.fmt = nodeUtil.format;
/**
* Format a string.
* @param {Array} args
* @param {Boolean?} color
* @return {String}
*/
util.format = function format(args, color) {
if (args.length > 0 && args[0] && typeof args[0] === 'object') {
if (color == null)
color = Boolean(process.stdout && process.stdout.isTTY);
return util.inspectify(args[0], color);
}
return util.fmt(...args);
};
/**
* Write a message to stdout (console in browser).
* @param {Object|String} obj
* @param {...String} args
*/
util.log = function log(...args) {
if (!process.stdout) {
let msg;
if (args.length > 0) {
msg = typeof args[0] !== 'object'
? util.fmt(...args)
: args[0];
}
console.log(msg);
return;
}
const msg = util.format(args);
process.stdout.write(msg + '\n');
};
/**
* Write a message to stderr (console in browser).
* @param {Object|String} obj
* @param {...String} args
*/
util.error = function error(...args) {
if (!process.stderr) {
let msg;
if (args.length > 0) {
msg = typeof args[0] !== 'object'
? util.fmt(...args)
: args[0];
}
console.error(msg);
return;
}
const msg = util.format(args);
process.stderr.write(msg + '\n');
};
/**
* Return hrtime (shim for browser).
* @param {Array} time
@ -385,7 +23,7 @@ util.error = function error(...args) {
util.hrtime = function hrtime(time) {
if (!process.hrtime) {
const now = util.ms();
const now = Date.now();
if (time) {
const [hi, lo] = time;
@ -418,16 +56,7 @@ util.hrtime = function hrtime(time) {
*/
util.now = function now() {
return Math.floor(util.ms() / 1000);
};
/**
* Get current time in unix time (milliseconds).
* @returns {Number}
*/
util.ms = function ms() {
return Date.now();
return Math.floor(Date.now() / 1000);
};
/**
@ -456,208 +85,6 @@ util.time = function time(date) {
return new Date(date) / 1000 | 0;
};
/**
* Get random range.
* @param {Number} min
* @param {Number} max
* @returns {Number}
*/
util.random = function random(min, max) {
return Math.floor(Math.random() * (max - min)) + min;
};
/**
* Create a 32 or 64 bit nonce.
* @param {Number} size
* @returns {Buffer}
*/
util.nonce = function nonce(size) {
let n, data;
if (!size)
size = 8;
switch (size) {
case 8:
data = Buffer.allocUnsafe(8);
n = util.random(0, 0x100000000);
data.writeUInt32LE(n, 0, true);
n = util.random(0, 0x100000000);
data.writeUInt32LE(n, 4, true);
break;
case 4:
data = Buffer.allocUnsafe(4);
n = util.random(0, 0x100000000);
data.writeUInt32LE(n, 0, true);
break;
default:
assert(false, 'Bad nonce size.');
break;
}
return data;
};
/**
* String comparator (memcmp + length comparison).
* @param {Buffer} a
* @param {Buffer} b
* @returns {Number} -1, 1, or 0.
*/
util.strcmp = function strcmp(a, b) {
const len = Math.min(a.length, b.length);
for (let i = 0; i < len; i++) {
if (a[i] < b[i])
return -1;
if (a[i] > b[i])
return 1;
}
if (a.length < b.length)
return -1;
if (a.length > b.length)
return 1;
return 0;
};
/**
* Convert bytes to mb.
* @param {Number} size
* @returns {Number} mb
*/
util.mb = function mb(size) {
return Math.floor(size / 1024 / 1024);
};
/**
* Convert a number to a padded uint8
* string (3 digits in decimal).
* @param {Number} num
* @returns {String} Padded number.
*/
util.pad8 = function pad8(num) {
assert(typeof num === 'number');
assert(num >= 0);
num = num.toString(10);
switch (num.length) {
case 1:
return '00' + num;
case 2:
return '0' + num;
case 3:
return num;
}
throw new Error('Number too big.');
};
/**
* Convert a number to a padded uint32
* string (10 digits in decimal).
* @param {Number} num
* @returns {String} Padded number.
*/
util.pad32 = function pad32(num) {
assert(typeof num === 'number');
assert(num >= 0);
num = num.toString(10);
switch (num.length) {
case 1:
return '000000000' + num;
case 2:
return '00000000' + num;
case 3:
return '0000000' + num;
case 4:
return '000000' + num;
case 5:
return '00000' + num;
case 6:
return '0000' + num;
case 7:
return '000' + num;
case 8:
return '00' + num;
case 9:
return '0' + num;
case 10:
return num;
}
throw new Error('Number too big.');
};
/**
* Convert a number to a padded uint8
* string (2 digits in hex).
* @param {Number} num
* @returns {String} Padded number.
*/
util.hex8 = function hex8(num) {
assert(typeof num === 'number');
assert(num >= 0);
num = num.toString(16);
switch (num.length) {
case 1:
return '0' + num;
case 2:
return num;
}
throw new Error('Number too big.');
};
/**
* Convert a number to a padded uint32
* string (8 digits in hex).
* @param {Number} num
* @returns {String} Padded number.
*/
util.hex32 = function hex32(num) {
assert(typeof num === 'number');
assert(num >= 0);
num = num.toString(16);
switch (num.length) {
case 1:
return '0000000' + num;
case 2:
return '000000' + num;
case 3:
return '00000' + num;
case 4:
return '0000' + num;
case 5:
return '000' + num;
case 6:
return '00' + num;
case 7:
return '0' + num;
case 8:
return num;
}
throw new Error('Number too big.');
};
/**
* Reverse a hex-string (used because of
* bitcoind's affinity for uint256le).
@ -677,346 +104,3 @@ util.revHex = function revHex(data) {
return out;
};
/**
* Perform a binary search on a sorted array.
* @param {Array} items
* @param {Object} key
* @param {Function} compare
* @param {Boolean?} insert
* @returns {Number} Index.
*/
util.binarySearch = function binarySearch(items, key, compare, insert) {
let start = 0;
let end = items.length - 1;
while (start <= end) {
const pos = (start + end) >>> 1;
const cmp = compare(items[pos], key);
if (cmp === 0)
return pos;
if (cmp < 0)
start = pos + 1;
else
end = pos - 1;
}
if (!insert)
return -1;
return start;
};
/**
* Perform a binary insert on a sorted array.
* @param {Array} items
* @param {Object} item
* @param {Function} compare
* @returns {Number} index
*/
util.binaryInsert = function binaryInsert(items, item, compare, uniq) {
const i = util.binarySearch(items, item, compare, true);
if (uniq && i < items.length) {
if (compare(items[i], item) === 0)
return -1;
}
if (i === 0)
items.unshift(item);
else if (i === items.length)
items.push(item);
else
items.splice(i, 0, item);
return i;
};
/**
* Perform a binary removal on a sorted array.
* @param {Array} items
* @param {Object} item
* @param {Function} compare
* @returns {Boolean}
*/
util.binaryRemove = function binaryRemove(items, item, compare) {
const i = util.binarySearch(items, item, compare, false);
if (i === -1)
return false;
items.splice(i, 1);
return true;
};
/**
* Quick test to see if a string is uppercase.
* @param {String} str
* @returns {Boolean}
*/
util.isUpperCase = function isUpperCase(str) {
assert(typeof str === 'string');
if (str.length === 0)
return false;
return (str.charCodeAt(0) & 32) === 0;
};
/**
* Test to see if a string starts with a prefix.
* @param {String} str
* @param {String} prefix
* @returns {Boolean}
*/
util.startsWith = function startsWith(str, prefix) {
assert(typeof str === 'string');
if (!str.startsWith)
return str.indexOf(prefix) === 0;
return str.startsWith(prefix);
};
/**
* Get memory usage info.
* @returns {Object}
*/
util.memoryUsage = function memoryUsage() {
if (!process.memoryUsage) {
return {
total: 0,
jsHeap: 0,
jsHeapTotal: 0,
nativeHeap: 0,
external: 0
};
}
const mem = process.memoryUsage();
return {
total: util.mb(mem.rss),
jsHeap: util.mb(mem.heapUsed),
jsHeapTotal: util.mb(mem.heapTotal),
nativeHeap: util.mb(mem.rss - mem.heapTotal),
external: util.mb(mem.external)
};
};
/**
* Convert int to fixed number string and reduce by a
* power of ten (uses no floating point arithmetic).
* @param {Number} num
* @param {Number} exp - Number of decimal places.
* @returns {String} Fixed number string.
*/
util.toFixed = function toFixed(num, exp) {
assert(typeof num === 'number');
assert(Number.isSafeInteger(num), 'Invalid integer value.');
let sign = '';
if (num < 0) {
num = -num;
sign = '-';
}
const mult = pow10(exp);
let lo = num % mult;
let hi = (num - lo) / mult;
lo = lo.toString(10);
hi = hi.toString(10);
while (lo.length < exp)
lo = '0' + lo;
lo = lo.replace(/0+$/, '');
assert(lo.length <= exp, 'Invalid integer value.');
if (lo.length === 0)
lo = '0';
if (exp === 0)
return `${sign}${hi}`;
return `${sign}${hi}.${lo}`;
};
/**
* Parse a fixed number string and multiply by a
* power of ten (uses no floating point arithmetic).
* @param {String} str
* @param {Number} exp - Number of decimal places.
* @returns {Number} Integer.
*/
util.fromFixed = function fromFixed(str, exp) {
assert(typeof str === 'string');
assert(str.length <= 32, 'Fixed number string too large.');
let sign = 1;
if (str.length > 0 && str[0] === '-') {
str = str.substring(1);
sign = -1;
}
let hi = str;
let lo = '0';
const index = str.indexOf('.');
if (index !== -1) {
hi = str.substring(0, index);
lo = str.substring(index + 1);
}
hi = hi.replace(/^0+/, '');
lo = lo.replace(/0+$/, '');
assert(hi.length <= 16 - exp,
'Fixed number string exceeds 2^53-1.');
assert(lo.length <= exp,
'Too many decimal places in fixed number string.');
if (hi.length === 0)
hi = '0';
while (lo.length < exp)
lo += '0';
if (lo.length === 0)
lo = '0';
assert(/^\d+$/.test(hi) && /^\d+$/.test(lo),
'Non-numeric characters in fixed number string.');
hi = parseInt(hi, 10);
lo = parseInt(lo, 10);
const mult = pow10(exp);
const maxLo = modSafe(mult);
const maxHi = divSafe(mult);
assert(hi < maxHi || (hi === maxHi && lo <= maxLo),
'Fixed number string exceeds 2^53-1.');
return sign * (hi * mult + lo);
};
/**
* Convert int to float and reduce by a power
* of ten (uses no floating point arithmetic).
* @param {Number} num
* @param {Number} exp - Number of decimal places.
* @returns {Number} Double float.
*/
util.toFloat = function toFloat(num, exp) {
return Number(util.toFixed(num, exp));
};
/**
* Parse a double float number and multiply by a
* power of ten (uses no floating point arithmetic).
* @param {Number} num
* @param {Number} exp - Number of decimal places.
* @returns {Number} Integer.
*/
util.fromFloat = function fromFloat(num, exp) {
assert(typeof num === 'number' && isFinite(num));
assert(Number.isSafeInteger(exp));
return util.fromFixed(num.toFixed(exp), exp);
};
/*
* Helpers
*/
function pow10(exp) {
switch (exp) {
case 0:
return 1;
case 1:
return 10;
case 2:
return 100;
case 3:
return 1000;
case 4:
return 10000;
case 5:
return 100000;
case 6:
return 1000000;
case 7:
return 10000000;
case 8:
return 100000000;
}
throw new Error('Exponent is too large.');
}
function modSafe(mod) {
switch (mod) {
case 1:
return 0;
case 10:
return 1;
case 100:
return 91;
case 1000:
return 991;
case 10000:
return 991;
case 100000:
return 40991;
case 1000000:
return 740991;
case 10000000:
return 4740991;
case 100000000:
return 54740991;
}
throw new Error('Exponent is too large.');
}
function divSafe(div) {
switch (div) {
case 1:
return 9007199254740991;
case 10:
return 900719925474099;
case 100:
return 90071992547409;
case 1000:
return 9007199254740;
case 10000:
return 900719925474;
case 100000:
return 90071992547;
case 1000000:
return 9007199254;
case 10000000:
return 900719925;
case 100000000:
return 90071992;
}
throw new Error('Exponent is too large.');
}

View File

@ -7,7 +7,7 @@
'use strict';
const assert = require('assert');
const util = require('../utils/util');
const {fromFloat} = require('../utils/fixed');
/**
* Validator
@ -286,7 +286,7 @@ Validator.prototype.fixed = function fixed(key, exp, fallback) {
return fallback;
try {
return util.fromFloat(value, exp || 0);
return fromFloat(value, exp || 0);
} catch (e) {
throw new ValidationError(key, 'fixed number');
}

View File

@ -6,8 +6,8 @@
'use strict';
const util = require('../utils/util');
const assert = require('assert');
const binary = require('../utils/binary');
const BufferReader = require('../utils/reader');
const StaticWriter = require('../utils/staticwriter');
const encoding = require('../utils/encoding');
@ -99,10 +99,11 @@ Account.typesByVal = {
Account.prototype.fromOptions = function fromOptions(options) {
assert(options, 'Options are required.');
assert(util.isU32(options.wid));
assert((options.wid >>> 0) === options.wid);
assert(common.isName(options.id), 'Bad Wallet ID.');
assert(HD.isHD(options.accountKey), 'Account key is required.');
assert(util.isU32(options.accountIndex), 'Account index is required.');
assert((options.accountIndex >>> 0) === options.accountIndex,
'Account index is required.');
this.wid = options.wid;
this.id = options.id;
@ -139,37 +140,37 @@ Account.prototype.fromOptions = function fromOptions(options) {
}
if (options.m != null) {
assert(util.isU8(options.m));
assert((options.m & 0xff) === options.m);
this.m = options.m;
}
if (options.n != null) {
assert(util.isU8(options.n));
assert((options.n & 0xff) === options.n);
this.n = options.n;
}
if (options.accountIndex != null) {
assert(util.isU32(options.accountIndex));
assert((options.accountIndex >>> 0) === options.accountIndex);
this.accountIndex = options.accountIndex;
}
if (options.receiveDepth != null) {
assert(util.isU32(options.receiveDepth));
assert((options.receiveDepth >>> 0) === options.receiveDepth);
this.receiveDepth = options.receiveDepth;
}
if (options.changeDepth != null) {
assert(util.isU32(options.changeDepth));
assert((options.changeDepth >>> 0) === options.changeDepth);
this.changeDepth = options.changeDepth;
}
if (options.nestedDepth != null) {
assert(util.isU32(options.nestedDepth));
assert((options.nestedDepth >>> 0) === options.nestedDepth);
this.nestedDepth = options.nestedDepth;
}
if (options.lookahead != null) {
assert(util.isU32(options.lookahead));
assert((options.lookahead >>> 0) === options.lookahead);
assert(options.lookahead >= 0);
assert(options.lookahead <= Account.MAX_LOOKAHEAD);
this.lookahead = options.lookahead;
@ -262,13 +263,13 @@ Account.prototype.pushKey = function pushKey(key) {
if (key.equals(this.accountKey))
throw new Error('Cannot add own key.');
const index = util.binaryInsert(this.keys, key, cmp, true);
const index = binary.insert(this.keys, key, cmp, true);
if (index === -1)
return false;
if (this.keys.length > this.n - 1) {
util.binaryRemove(this.keys, key, cmp);
binary.remove(this.keys, key, cmp);
throw new Error('Cannot add more keys.');
}
@ -299,7 +300,7 @@ Account.prototype.spliceKey = function spliceKey(key) {
if (this.keys.length === this.n - 1)
throw new Error('Cannot remove key.');
return util.binaryRemove(this.keys, key, cmp);
return binary.remove(this.keys, key, cmp);
};
/**

View File

@ -7,6 +7,7 @@
'use strict';
const assert = require('assert');
const {NodeClient} = require('bclient');
const TX = require('../primitives/tx');
const digest = require('bcrypto/lib/digest');

View File

@ -10,7 +10,6 @@
const assert = require('assert');
const path = require('path');
const {Server} = require('bweb');
const util = require('../utils/util');
const base58 = require('../utils/base58');
const MTX = require('../primitives/mtx');
const Outpoint = require('../primitives/outpoint');
@ -132,12 +131,17 @@ class HTTPServer extends Server {
return;
}
if (!token) {
res.json(403);
return;
}
let wallet;
try {
wallet = await this.wdb.auth(id, token);
} catch (err) {
this.logger.info('Auth failure for %s: %s.', id, err.message);
res.error(403, err);
res.json(403);
return;
}
@ -1007,8 +1011,6 @@ class HTTPOptions {
'API key must be a string.');
assert(options.apiKey.length <= 255,
'API key must be under 255 bytes.');
assert(util.isAscii(options.apiKey),
'API key must be ASCII.');
this.apiKey = options.apiKey;
this.apiHash = digest.hash256(Buffer.from(this.apiKey, 'ascii'));
}
@ -1036,7 +1038,8 @@ class HTTPOptions {
}
if (options.port != null) {
assert(util.isU16(options.port), 'Port must be a number.');
assert((options.port & 0xffff) === options.port,
'Port must be a number.');
this.port = options.port;
}

View File

@ -7,8 +7,6 @@
'use strict';
const assert = require('assert');
const util = require('../utils/util');
const pad32 = util.pad32;
const layouts = exports;
layouts.walletdb = {
@ -23,7 +21,7 @@ layouts.walletdb = {
},
P: function P(wid, hash) {
assert(typeof hash === 'string');
return 'p' + pad32(wid) + hash;
return 'p' + hex32(wid) + hash;
},
Pp: function Pp(key) {
assert(typeof key === 'string');
@ -31,18 +29,18 @@ layouts.walletdb = {
},
r: function r(wid, index, hash) {
assert(typeof hash === 'string');
return 'r' + pad32(wid) + pad32(index) + hash;
return 'r' + hex32(wid) + hex32(index) + hash;
},
rr: function rr(key) {
assert(typeof key === 'string');
return key.slice(21);
},
w: function w(wid) {
return 'w' + pad32(wid);
return 'w' + hex32(wid);
},
ww: function ww(key) {
assert(typeof key === 'string');
return parseInt(key.slice(1), 10);
return parseInt(key.slice(1), 16);
},
l: function l(id) {
assert(typeof id === 'string');
@ -53,36 +51,36 @@ layouts.walletdb = {
return key.slice(1);
},
a: function a(wid, index) {
return 'a' + pad32(wid) + pad32(index);
return 'a' + hex32(wid) + hex32(index);
},
i: function i(wid, name) {
assert(typeof name === 'string');
return 'i' + pad32(wid) + name;
return 'i' + hex32(wid) + name;
},
ii: function ii(key) {
assert(typeof key === 'string');
return [parseInt(key.slice(1, 11), 10), key.slice(11)];
return [parseInt(key.slice(1, 9), 16), key.slice(9)];
},
n: function n(wid, index) {
return 'n' + pad32(wid) + pad32(index);
return 'n' + hex32(wid) + hex32(index);
},
R: 'R',
h: function h(height) {
return 'h' + pad32(height);
return 'h' + hex32(height);
},
b: function b(height) {
return 'b' + pad32(height);
return 'b' + hex32(height);
},
bb: function bb(key) {
assert(typeof key === 'string');
return parseInt(key.slice(1), 10);
return parseInt(key.slice(1), 16);
},
o: function o(hash, index) {
assert(typeof hash === 'string');
return 'o' + hash + pad32(index);
return 'o' + hash + hex32(index);
},
oo: function oo(key) {
return [key.slice(1, 65), parseInt(key.slice(65), 10)];
return [key.slice(1, 65), parseInt(key.slice(65), 16)];
},
T: function T(hash) {
assert(typeof hash === 'string');
@ -96,55 +94,55 @@ layouts.walletdb = {
layouts.txdb = {
binary: false,
prefix: function prefix(wid) {
return 't' + pad32(wid);
return 't' + hex32(wid);
},
R: 'R',
r: function r(acct) {
assert(typeof acct === 'number');
return 'r' + pad32(acct);
return 'r' + hex32(acct);
},
rr: function rr(key) {
assert(typeof key === 'string');
return parseInt(key.slice(1), 10);
return parseInt(key.slice(1), 16);
},
hi: function hi(ch, hash, index) {
assert(typeof hash === 'string');
return ch + hash + pad32(index);
return ch + hash + hex32(index);
},
hii: function hii(key) {
assert(typeof key === 'string');
return [key.slice(1, 65), parseInt(key.slice(65), 10)];
return [key.slice(1, 65), parseInt(key.slice(65), 16)];
},
ih: function ih(ch, index, hash) {
assert(typeof hash === 'string');
return ch + pad32(index) + hash;
return ch + hex32(index) + hash;
},
ihh: function ihh(key) {
assert(typeof key === 'string');
return [parseInt(key.slice(1, 11), 10), key.slice(11)];
return [parseInt(key.slice(1, 9), 16), key.slice(9)];
},
iih: function iih(ch, index, num, hash) {
assert(typeof hash === 'string');
return ch + pad32(index) + pad32(num) + hash;
return ch + hex32(index) + hex32(num) + hash;
},
iihh: function iihh(key) {
assert(typeof key === 'string');
return [
parseInt(key.slice(1, 11), 10),
parseInt(key.slice(11, 21), 10),
key.slice(21)
parseInt(key.slice(1, 9), 16),
parseInt(key.slice(9, 17), 16),
key.slice(17)
];
},
ihi: function ihi(ch, index, hash, num) {
assert(typeof hash === 'string');
return ch + pad32(index) + hash + pad32(num);
return ch + hex32(index) + hash + hex32(num);
},
ihii: function ihii(key) {
assert(typeof key === 'string');
return [
parseInt(key.slice(1, 11), 10),
key.slice(11, 75),
parseInt(key.slice(75), 10)
parseInt(key.slice(1, 9), 16),
key.slice(9, 73),
parseInt(key.slice(73), 16)
];
},
ha: function ha(ch, hash) {
@ -234,10 +232,38 @@ layouts.txdb = {
return this.ihii(key);
},
b: function b(height) {
return 'b' + pad32(height);
return 'b' + hex32(height);
},
bb: function bb(key) {
assert(typeof key === 'string');
return parseInt(key.slice(1), 10);
return parseInt(key.slice(1), 16);
}
};
function hex32(num) {
assert(typeof num === 'number');
assert(num >= 0);
num = num.toString(16);
switch (num.length) {
case 1:
return '0000000' + num;
case 2:
return '000000' + num;
case 3:
return '00000' + num;
case 4:
return '0000' + num;
case 5:
return '000' + num;
case 6:
return '00' + num;
case 7:
return '0' + num;
case 8:
return num;
}
throw new Error('Number too big.');
}

View File

@ -134,22 +134,22 @@ MasterKey.prototype.fromOptions = function fromOptions(options) {
}
if (options.rounds != null) {
assert(util.isU32(options.rounds));
assert((options.rounds >>> 0) === options.rounds);
this.N = options.rounds;
}
if (options.N != null) {
assert(util.isU32(options.N));
assert((options.N >>> 0) === options.N);
this.N = options.N;
}
if (options.r != null) {
assert(util.isU32(options.r));
assert((options.r >>> 0) === options.r);
this.r = options.r;
}
if (options.p != null) {
assert(util.isU32(options.p));
assert((options.p >>> 0) === options.p);
this.p = options.p;
}

View File

@ -8,6 +8,7 @@
const assert = require('assert');
const bweb = require('bweb');
const {format} = require('util');
const fs = require('../utils/fs');
const util = require('../utils/util');
const digest = require('bcrypto/lib/digest');
@ -101,13 +102,13 @@ class RPC extends RPCBase {
case 'RPCError':
return err.code;
case 'ValidationError':
return errors.TYPE_ERROR;
return errs.TYPE_ERROR;
case 'EncodingError':
return errors.DESERIALIZATION_ERROR;
return errs.DESERIALIZATION_ERROR;
case 'FundingError':
return errors.WALLET_INSUFFICIENT_FUNDS;
return errs.WALLET_INSUFFICIENT_FUNDS;
default:
return errors.INTERNAL_ERROR;
return errs.INTERNAL_ERROR;
}
}
@ -312,11 +313,11 @@ class RPC extends RPCBase {
const time = util.date();
const out = [
util.fmt('# Wallet Dump created by Bcoin %s', pkg.version),
util.fmt('# * Created on %s', time),
util.fmt('# * Best block at time of backup was %d (%s).',
format('# Wallet Dump created by Bcoin %s', pkg.version),
format('# * Created on %s', time),
format('# * Best block at time of backup was %d (%s).',
tip.height, util.revHex(tip.hash)),
util.fmt('# * File: %s', file),
format('# * File: %s', file),
''
];
@ -335,7 +336,7 @@ class RPC extends RPCBase {
if (ring.branch === 1)
fmt = '%s %s change=1 addr=%s';
const str = util.fmt(fmt, ring.toSecret(this.network), time, addr);
const str = format(fmt, ring.toSecret(this.network), time, addr);
out.push(str);
}
@ -1470,8 +1471,11 @@ class RPC extends RPCBase {
if (help || (wallet.master.encrypted && args.length !== 0))
throw new RPCError(errs.MISC_ERROR, 'walletlock');
if (!wallet.master.encrypted)
throw new RPCError(errs.WALLET_WRONG_ENC_STATE, 'Wallet is not encrypted.');
if (!wallet.master.encrypted) {
throw new RPCError(
errs.WALLET_WRONG_ENC_STATE,
'Wallet is not encrypted.');
}
await wallet.lock();
@ -1490,8 +1494,11 @@ class RPC extends RPCBase {
const old = valid.str(0, '');
const passphrase = valid.str(1, '');
if (!wallet.master.encrypted)
throw new RPCError(errs.WALLET_WRONG_ENC_STATE, 'Wallet is not encrypted.');
if (!wallet.master.encrypted) {
throw new RPCError(
errs.WALLET_WRONG_ENC_STATE,
'Wallet is not encrypted.');
}
if (old.length < 1 || passphrase.length < 1)
throw new RPCError(errs.INVALID_PARAMETER, 'Invalid parameter');
@ -1512,8 +1519,11 @@ class RPC extends RPCBase {
'walletpassphrase "passphrase" timeout');
}
if (!wallet.master.encrypted)
throw new RPCError(errs.WALLET_WRONG_ENC_STATE, 'Wallet is not encrypted.');
if (!wallet.master.encrypted) {
throw new RPCError(
errs.WALLET_WRONG_ENC_STATE,
'Wallet is not encrypted.');
}
if (passphrase.length < 1)
throw new RPCError(errs.INVALID_PARAMETER, 'Invalid parameter');
@ -1604,7 +1614,7 @@ class RPC extends RPCBase {
if (help || args.length !== 0)
throw new RPCError(errs.MISC_ERROR, 'getmemoryinfo');
return util.memoryUsage();
return this.logger.memoryUsage();
}
async setLogLevel(args, help) {

View File

@ -2064,7 +2064,7 @@ TXDB.prototype.getAccountBalance = async function getAccountBalance(acct) {
*/
TXDB.prototype.zap = async function zap(acct, age) {
assert(util.isU32(age));
assert((age >>> 0) === age);
const now = util.now();

View File

@ -10,7 +10,6 @@
const assert = require('assert');
const EventEmitter = require('events');
const Network = require('../protocol/network');
const util = require('../utils/util');
const encoding = require('../utils/encoding');
const Lock = require('../utils/lock');
const digest = require('bcrypto/lib/digest');
@ -115,7 +114,7 @@ Wallet.prototype.fromOptions = function fromOptions(options) {
this.master.fromKey(key, mnemonic, this.network);
if (options.wid != null) {
assert(util.isU32(options.wid));
assert((options.wid >>> 0) === options.wid);
this.wid = options.wid;
}
@ -135,7 +134,7 @@ Wallet.prototype.fromOptions = function fromOptions(options) {
}
if (options.accountDepth != null) {
assert(util.isU32(options.accountDepth));
assert((options.accountDepth >>> 0) === options.accountDepth);
this.accountDepth = options.accountDepth;
}
@ -146,7 +145,7 @@ Wallet.prototype.fromOptions = function fromOptions(options) {
}
if (options.tokenDepth != null) {
assert(util.isU32(options.tokenDepth));
assert((options.tokenDepth >>> 0) === options.tokenDepth);
this.tokenDepth = options.tokenDepth;
}
@ -1388,7 +1387,7 @@ Wallet.prototype._send = async function _send(options, passphrase) {
*/
Wallet.prototype.increaseFee = async function increaseFee(hash, rate, passphrase) {
assert(util.isU32(rate), 'Rate must be a number.');
assert((rate >>> 0) === rate, 'Rate must be a number.');
const wtx = await this.getTX(hash);

View File

@ -430,7 +430,7 @@ WalletDB.prototype.scan = async function scan(height) {
if (height == null)
height = this.state.startHeight;
assert(util.isU32(height), 'WDB: Must pass in a height.');
assert((height >>> 0) === height, 'WDB: Must pass in a height.');
await this.rollback(height);
@ -851,7 +851,7 @@ WalletDB.prototype.renameAccount = function renameAccount(b, account, name) {
/**
* Get a wallet with token auth first.
* @param {WalletID} wid
* @param {String|Buffer} token
* @param {Buffer} token
* @returns {Promise} - Returns {@link Wallet}.
*/
@ -861,12 +861,6 @@ WalletDB.prototype.auth = async function auth(wid, token) {
if (!wallet)
return null;
if (typeof token === 'string') {
if (!util.isHex256(token))
throw new Error('WDB: Authentication error.');
token = Buffer.from(token, 'hex');
}
// Compare in constant time:
if (!ccmp(token, wallet.token))
throw new Error('WDB: Authentication error.');
@ -2082,7 +2076,7 @@ WalletOptions.prototype.fromOptions = function fromOptions(options) {
}
if (options.feeRate != null) {
assert(util.isU64(options.feeRate));
assert((options.feeRate >>> 0) === options.feeRate);
this.feeRate = options.feeRate;
}
@ -2103,12 +2097,12 @@ WalletOptions.prototype.fromOptions = function fromOptions(options) {
}
if (options.maxFiles != null) {
assert(util.isU32(options.maxFiles));
assert((options.maxFiles >>> 0) === options.maxFiles);
this.maxFiles = options.maxFiles;
}
if (options.cacheSize != null) {
assert(util.isU64(options.cacheSize));
assert(Number.isSafeInteger(options.cacheSize) && options.cacheSize >= 0);
this.cacheSize = options.cacheSize;
}

View File

@ -9,7 +9,7 @@
const assert = require('assert');
const EventEmitter = require('events');
const util = require('../utils/util');
const {format} = require('util');
const Network = require('../protocol/network');
const jobs = require('./jobs');
const Parser = require('./parser');
@ -132,8 +132,8 @@ Master.prototype.destroy = function destroy() {
* @param {...String} args
*/
Master.prototype.log = function log(...items) {
const text = util.format(items, this.color);
Master.prototype.log = function log() {
const text = format.apply(null, arguments);
this.send(new packets.LogPacket(text));
};

View File

@ -8,10 +8,6 @@
'use strict';
const Master = require('./master');
const util = require('../utils/util');
const server = new Master();
util.log = server.log.bind(server);
util.error = util.log;
server.listen();

View File

@ -12,7 +12,6 @@
const assert = require('assert');
const EventEmitter = require('events');
const os = require('os');
const util = require('../utils/util');
const co = require('../utils/co');
const Network = require('../protocol/network');
const Child = require('./child');
@ -68,13 +67,13 @@ WorkerPool.prototype.set = function set(options) {
}
if (options.size != null) {
assert(util.isU32(options.size));
assert((options.size >>> 0) === options.size);
assert(options.size > 0);
this.size = options.size;
}
if (options.timeout != null) {
assert(util.isInt(options.timeout));
assert(Number.isSafeInteger(options.timeout));
assert(options.timeout >= -1);
this.timeout = options.timeout;
}

View File

@ -52,7 +52,7 @@ function Coins(options) {
Coins.prototype.fromOptions = function fromOptions(options) {
if (options.version != null) {
assert(util.isU32(options.version));
assert((options.version >>> 0) === options.version);
this.version = options.version;
}
@ -62,7 +62,7 @@ Coins.prototype.fromOptions = function fromOptions(options) {
}
if (options.height != null) {
assert(util.isInt(options.height));
assert(Number.isSafeInteger(options.height));
this.height = options.height;
}

View File

@ -54,7 +54,7 @@ function Coins(options) {
Coins.prototype.fromOptions = function fromOptions(options) {
if (options.version != null) {
assert(util.isU32(options.version));
assert((options.version >>> 0) === options.version);
this.version = options.version;
}
@ -64,7 +64,7 @@ Coins.prototype.fromOptions = function fromOptions(options) {
}
if (options.height != null) {
assert(util.isInt(options.height));
assert(Number.isSafeInteger(options.height));
this.height = options.height;
}

View File

@ -1,6 +1,5 @@
'use strict';
const util = require('../lib/utils/util');
const Script = require('../lib/script/script');
const Stack = require('../lib/script/stack');
const Witness = require('../lib/script/witness');
@ -21,7 +20,7 @@ try {
}
if (consensus)
util.log('Running against bitcoinconsensus...');
console.log('Running against bitcoinconsensus...');
const MANDATORY = flags.MANDATORY_VERIFY_FLAGS | flags.VERIFY_WITNESS;
const STANDARD = flags.STANDARD_VERIFY_FLAGS;
@ -39,13 +38,13 @@ function assertConsensus(tx, output, flags, code) {
const err = verifyConsensus(tx, 0, output, 0, flags);
if (err !== code) {
util.log('bitcoinconsensus mismatch!');
util.log(`${err} (bitcoin core) !== ${code} (bcoin)`);
util.log(tx);
util.log(output);
util.log(flags);
util.log('TX: %s', tx.toRaw().toString('hex'));
util.log('Output Script: %s', output.toRaw().toString('hex'));
console.log('bitcoinconsensus mismatch!');
console.log(`${err} (bitcoin core) !== ${code} (bcoin)`);
console.log(tx);
console.log(output);
console.log(flags);
console.log('TX: %s', tx.toRaw().toString('hex'));
console.log('Output Script: %s', output.toRaw().toString('hex'));
}
}
@ -59,7 +58,7 @@ function randomKey() {
const x = secp256k1.generatePrivateKey();
const y = secp256k1.generatePrivateKey();
if (util.random(0, 2) === 0) {
if (rand(0, 2) === 0) {
const p = Buffer.from([2 | (y[y.length - 1] & 1)]);
return Buffer.concat([p, x]);
}
@ -70,28 +69,28 @@ function randomKey() {
function randomOutpoint() {
const hash = random.randomBytes(32).toString('hex');
return new Outpoint(hash, util.random(0, 0xffffffff));
return new Outpoint(hash, rand(0, 0xffffffff));
}
function randomInput() {
const input = Input.fromOutpoint(randomOutpoint());
if (util.random(0, 5) === 0)
input.sequence = util.random(0, 0xffffffff);
if (rand(0, 5) === 0)
input.sequence = rand(0, 0xffffffff);
return input;
}
function randomOutput() {
return Output.fromScript(randomScript(), util.random(0, 1e8));
return Output.fromScript(randomScript(), rand(0, 1e8));
}
function randomTX() {
const tx = new TX();
const inputs = util.random(1, 5);
const outputs = util.random(0, 5);
const inputs = rand(1, 5);
const outputs = rand(0, 5);
tx.version = util.random(0, 0xffffffff);
tx.version = rand(0, 0xffffffff);
for (let i = 0; i < inputs; i++)
tx.inputs.push(randomInput());
@ -99,8 +98,8 @@ function randomTX() {
for (let i = 0; i < outputs; i++)
tx.outputs.push(randomOutput());
if (util.random(0, 5) === 0)
tx.locktime = util.random(0, 0xffffffff);
if (rand(0, 5) === 0)
tx.locktime = rand(0, 0xffffffff);
tx.refresh();
@ -108,11 +107,11 @@ function randomTX() {
}
function randomWitness(redeem) {
const size = util.random(1, 100);
const size = rand(1, 100);
const witness = new Witness();
for (let i = 0; i < size; i++) {
const len = util.random(0, 100);
const len = rand(0, 100);
witness.push(random.randomBytes(len));
}
@ -125,11 +124,11 @@ function randomWitness(redeem) {
}
function randomInputScript(redeem) {
const size = util.random(1, 100);
const size = rand(1, 100);
const script = new Script();
for (let i = 0; i < size; i++) {
const len = util.random(0, 100);
const len = rand(0, 100);
script.pushData(random.randomBytes(len));
}
@ -140,7 +139,7 @@ function randomInputScript(redeem) {
}
function randomOutputScript() {
const size = util.random(1, 10000);
const size = rand(1, 10000);
return Script.fromRaw(random.randomBytes(size));
}
@ -165,7 +164,7 @@ function isPushOnly(script) {
}
function randomPubkey() {
const len = util.random(0, 2) === 0 ? 33 : 65;
const len = rand(0, 2) === 0 ? 33 : 65;
return Script.fromPubkey(random.randomBytes(len));
}
@ -174,12 +173,12 @@ function randomPubkeyhash() {
}
function randomMultisig() {
const n = util.random(1, 16);
const m = util.random(1, n);
const n = rand(1, 16);
const m = rand(1, n);
const keys = [];
for (let i = 0; i < n; i++) {
const len = util.random(0, 2) === 0 ? 33 : 65;
const len = rand(0, 2) === 0 ? 33 : 65;
keys.push(random.randomBytes(len));
}
@ -199,13 +198,13 @@ function randomWitnessScripthash() {
}
function randomProgram() {
const version = util.random(0, 16);
const size = util.random(2, 41);
const version = rand(0, 16);
const size = rand(2, 41);
return Script.fromProgram(version, random.randomBytes(size));
}
function randomRedeem() {
switch (util.random(0, 5)) {
switch (rand(0, 5)) {
case 0:
return randomPubkey();
case 1:
@ -221,7 +220,7 @@ function randomRedeem() {
}
function randomScript() {
switch (util.random(0, 7)) {
switch (rand(0, 7)) {
case 0:
return randomPubkey();
case 1:
@ -299,7 +298,7 @@ function randomWitnessNestedContext() {
}
function randomContext() {
switch (util.random(0, 6)) {
switch (rand(0, 6)) {
case 0:
return randomPubkeyContext();
case 1:
@ -322,7 +321,7 @@ function fuzzSimple(flags) {
for (;;) {
if (++total % 1000 === 0)
util.log('Fuzzed %d scripts.', total);
console.log('Fuzzed %d scripts.', total);
if (total % 500 === 0)
tx = randomTX();
@ -357,16 +356,16 @@ function fuzzSimple(flags) {
if (isPushOnly(output))
continue;
util.log('Produced valid scripts:');
console.log('Produced valid scripts:');
util.log('Input:');
util.log(input);
console.log('Input:');
console.log(input);
util.log('Output:');
util.log(output);
console.log('Output:');
console.log(output);
util.log('Stack:');
util.log(stack);
console.log('Stack:');
console.log(stack);
break;
}
@ -378,7 +377,7 @@ function fuzzVerify(flags) {
for (;;) {
if (++total % 1000 === 0)
util.log('Fuzzed %d scripts.', total);
console.log('Fuzzed %d scripts.', total);
if (total % 500 === 0)
tx = randomTX();
@ -415,16 +414,16 @@ function fuzzVerify(flags) {
if (isPushOnly(output))
continue;
util.log('Produced valid scripts:');
console.log('Produced valid scripts:');
util.log('Input:');
util.log(input);
console.log('Input:');
console.log(input);
util.log('Witness:');
util.log(witness);
console.log('Witness:');
console.log(witness);
util.log('Output:');
util.log(output);
console.log('Output:');
console.log(output);
break;
}
@ -436,7 +435,7 @@ function fuzzLess(flags) {
for (;;) {
if (++total % 1000 === 0)
util.log('Fuzzed %d scripts.', total);
console.log('Fuzzed %d scripts.', total);
if (total % 500 === 0)
tx = randomTX();
@ -469,20 +468,20 @@ function fuzzLess(flags) {
assertConsensus(tx, ctx.output, flags, 'OK');
util.log('Produced valid scripts:');
console.log('Produced valid scripts:');
util.log('Input:');
util.log(ctx.input);
console.log('Input:');
console.log(ctx.input);
util.log('Witness:');
util.log(ctx.witness);
console.log('Witness:');
console.log(ctx.witness);
util.log('Output:');
util.log(ctx.output);
console.log('Output:');
console.log(ctx.output);
if (ctx.redeem) {
util.log('Redeem:');
util.log(ctx.redeem);
console.log('Redeem:');
console.log(ctx.redeem);
}
break;
@ -505,13 +504,17 @@ function main() {
fuzzLess(flags);
break;
default:
util.log('Please select a mode:');
util.log('simple, verify, less');
util.log('Optional `--standard` flag.');
console.log('Please select a mode:');
console.log('simple, verify, less');
console.log('Optional `--standard` flag.');
break;
}
}
function rand(min, max) {
return Math.floor(Math.random() * (max - min)) + min;
}
randomKey;
randomSignature;

View File

@ -1,6 +1,5 @@
'use strict';
const util = require('../lib/utils/util');
const consensus = require('../lib/protocol/consensus');
const encoding = require('../lib/utils/encoding');
const TX = require('../lib/primitives/tx');
@ -106,31 +105,31 @@ const btcd = createGenesisBlock({
nonce: 2
});
util.log(main);
util.log('');
util.log(testnet);
util.log('');
util.log(regtest);
util.log('');
util.log(segnet3);
util.log('');
util.log(segnet4);
util.log('');
util.log('');
util.log('main hash: %s', main.rhash());
util.log('main raw: %s', main.toRaw().toString('hex'));
util.log('');
util.log('testnet hash: %s', testnet.rhash());
util.log('testnet raw: %s', testnet.toRaw().toString('hex'));
util.log('');
util.log('regtest hash: %s', regtest.rhash());
util.log('regtest raw: %s', regtest.toRaw().toString('hex'));
util.log('');
util.log('segnet3 hash: %s', segnet3.rhash());
util.log('segnet3 raw: %s', segnet3.toRaw().toString('hex'));
util.log('');
util.log('segnet4 hash: %s', segnet4.rhash());
util.log('segnet4 raw: %s', segnet4.toRaw().toString('hex'));
util.log('');
util.log('btcd simnet hash: %s', btcd.rhash());
util.log('btcd simnet raw: %s', btcd.toRaw().toString('hex'));
console.log(main);
console.log('');
console.log(testnet);
console.log('');
console.log(regtest);
console.log('');
console.log(segnet3);
console.log('');
console.log(segnet4);
console.log('');
console.log('');
console.log('main hash: %s', main.rhash());
console.log('main raw: %s', main.toRaw().toString('hex'));
console.log('');
console.log('testnet hash: %s', testnet.rhash());
console.log('testnet raw: %s', testnet.toRaw().toString('hex'));
console.log('');
console.log('regtest hash: %s', regtest.rhash());
console.log('regtest raw: %s', regtest.toRaw().toString('hex'));
console.log('');
console.log('segnet3 hash: %s', segnet3.rhash());
console.log('segnet3 raw: %s', segnet3.toRaw().toString('hex'));
console.log('');
console.log('segnet4 hash: %s', segnet4.rhash());
console.log('segnet4 raw: %s', segnet4.toRaw().toString('hex'));
console.log('');
console.log('btcd simnet hash: %s', btcd.rhash());
console.log('btcd simnet raw: %s', btcd.toRaw().toString('hex'));

View File

@ -104,6 +104,16 @@ const invalidAddresses = [
'tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3pjxtptv'
];
const validBech32Tests = [
'BC1QW508D6QEJXTDG4Y5R3ZARVARY0C5XW7KV8F3T4',
'tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7',
'bc1pw508d6qejxtdg4y5r3zarvary0c5xw7kw50'
+ '8d6qejxtdg4y5r3zarvary0c5xw7k7grplx',
'BC1SW50QA3JX3S',
'bc1zw508d6qejxtdg4y5r3zarvaryvg6kdaj',
'tb1qqqqqp399et2xygdj5xreqhjjvcmzhxw4aywxecjdzew6hylgvsesrxh6hy'
];
function fromAddress(hrp, addr) {
const dec = bech32.decode(addr);
@ -216,4 +226,10 @@ describe('Bech32', function() {
assert.throws(() => Address.fromBech32(addr, 'testnet'));
});
}
it('should validate bech32 addresses based only on string data', () => {
for (const bech32addr of validBech32Tests) {
assert.strictEqual(bech32.isBech32(bech32addr), true);
}
});
});

View File

@ -11,7 +11,6 @@ const Address = require('../lib/primitives/address');
const Script = require('../lib/script/script');
const Outpoint = require('../lib/primitives/outpoint');
const MTX = require('../lib/primitives/mtx');
const HTTP = require('../lib/http');
const FullNode = require('../lib/node/fullnode');
const pkg = require('../lib/pkg');
const Network = require('../lib/protocol/network');
@ -221,7 +220,7 @@ describe('HTTP', function() {
sizelimit: 1000000,
longpollid:
'0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206'
+ '0000000000',
+ '00000000',
submitold: false,
coinbaseaux: { flags: '6d696e65642062792062636f696e' },
coinbasevalue: 5000000000,

View File

@ -498,7 +498,7 @@ describe('Node', function() {
sigoplimit: 80000,
sizelimit: 4000000,
weightlimit: 4000000,
longpollid: node.chain.tip.rhash() + '0000000000',
longpollid: node.chain.tip.rhash() + '00000000',
submitold: false,
coinbaseaux: { flags: '6d696e65642062792062636f696e' },
coinbasevalue: 1250000000,

View File

@ -51,7 +51,7 @@ describe('Protocol', function() {
time: network.now(),
remote: new NetAddress(),
local: new NetAddress(),
nonce: util.nonce(),
nonce: Buffer.allocUnsafe(8),
agent: agent,
height: 0,
noRelay: false
@ -70,7 +70,7 @@ describe('Protocol', function() {
time: network.now(),
remote: new NetAddress(),
local: new NetAddress(),
nonce: util.nonce(),
nonce: Buffer.allocUnsafe(8),
agent: agent,
height: 10,
noRelay: true

View File

@ -9,8 +9,8 @@ const Witness = require('../lib/script/witness');
const Stack = require('../lib/script/stack');
const Opcode = require('../lib/script/opcode');
const TX = require('../lib/primitives/tx');
const util = require('../lib/utils/util');
const encoding = require('../lib/utils/encoding');
const {fromFloat} = require('../lib/utils/fixed');
const scripts = require('./data/script-tests.json');
@ -39,7 +39,7 @@ function parseScriptTest(data) {
let value = 0;
if (witArr.length > 0)
value = util.fromFloat(witArr.pop(), 8);
value = fromFloat(witArr.pop(), 8);
const witness = Witness.fromString(witArr);
const input = Script.fromString(inpHex);

View File

@ -3,6 +3,7 @@
'use strict';
const {inspect} = require('util');
const assert = require('./util/assert');
const util = require('../lib/utils/util');
const encoding = require('../lib/utils/encoding');
@ -90,7 +91,7 @@ function parseTXTest(data) {
flags: flags,
view: view,
comments: coin
? util.inspectify(coin.script, false)
? inspect(coin.script)
: 'coinbase',
data: data
};

View File

@ -9,7 +9,7 @@ const base58 = require('../lib/utils/base58');
const encoding = require('../lib/utils/encoding');
const Amount = require('../lib/btc/amount');
const Validator = require('../lib/utils/validator');
const util = require('../lib/utils/util');
const fixed = require('../lib/utils/fixed');
const base58Tests = [
['', ''],
@ -32,16 +32,6 @@ const base58Tests = [
['00000000000000000000', '1111111111']
];
const validBech32Tests = [
'BC1QW508D6QEJXTDG4Y5R3ZARVARY0C5XW7KV8F3T4',
'tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7',
'bc1pw508d6qejxtdg4y5r3zarvary0c5xw7kw50'
+ '8d6qejxtdg4y5r3zarvary0c5xw7k7grplx',
'BC1SW50QA3JX3S',
'bc1zw508d6qejxtdg4y5r3zarvaryvg6kdaj',
'tb1qqqqqp399et2xygdj5xreqhjjvcmzhxw4aywxecjdzew6hylgvsesrxh6hy'
];
const unsigned = [
new U64('ffeeffee', 16),
new U64('001fffeeffeeffee', 16),
@ -122,10 +112,10 @@ describe('Utils', function() {
assert.strictEqual(parseFloat('0.15645647') * 1e8, 15645646.999999998);
assert.strictEqual(15645647 / 1e8, 0.15645647);
assert.strictEqual(util.fromFixed('0.15645647', 8), 15645647);
assert.strictEqual(util.toFixed(15645647, 8), '0.15645647');
assert.strictEqual(util.fromFloat(0.15645647, 8), 15645647);
assert.strictEqual(util.toFloat(15645647, 8), 0.15645647);
assert.strictEqual(fixed.decode('0.15645647', 8), 15645647);
assert.strictEqual(fixed.encode(15645647, 8), '0.15645647');
assert.strictEqual(fixed.fromFloat(0.15645647, 8), 15645647);
assert.strictEqual(fixed.toFloat(15645647, 8), 0.15645647);
});
it('should write/read new varints', () => {
@ -254,10 +244,4 @@ describe('Utils', function() {
assert.strictEqual(validator.bool('shouldBeTrue'), true);
assert.strictEqual(validator.bool('shouldBeFalse'), false);
});
it('should validate bech32 addresses based only on string data', () => {
for (const bech32addr of validBech32Tests) {
assert.strictEqual(util.isBech32(bech32addr), true);
}
});
});