bcoin: remove dependence on util.js.
This commit is contained in:
parent
1a5782fa06
commit
d0ed214067
23
bin/cli
23
bin/cli
@ -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() {
|
||||
|
||||
@ -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]);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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');
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
};
|
||||
|
||||
|
||||
@ -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
|
||||
*/
|
||||
|
||||
@ -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);
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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');
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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;
|
||||
};
|
||||
|
||||
@ -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
|
||||
*/
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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];
|
||||
};
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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;
|
||||
};
|
||||
|
||||
@ -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
|
||||
*/
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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))
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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();
|
||||
};
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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.
|
||||
*/
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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.');
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
*/
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@ -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
|
||||
*/
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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];
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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');
|
||||
|
||||
@ -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);
|
||||
};
|
||||
|
||||
@ -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
85
lib/utils/binary.js
Normal 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;
|
||||
};
|
||||
@ -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
216
lib/utils/fixed.js
Normal 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
500
lib/utils/hashwriter.js
Normal 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;
|
||||
@ -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');
|
||||
|
||||
@ -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.');
|
||||
}
|
||||
|
||||
@ -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');
|
||||
}
|
||||
|
||||
@ -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);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -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');
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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.');
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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();
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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));
|
||||
};
|
||||
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
127
scripts/fuzz.js
127
scripts/fuzz.js
@ -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;
|
||||
|
||||
|
||||
@ -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'));
|
||||
|
||||
@ -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);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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
|
||||
};
|
||||
|
||||
@ -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);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Loading…
Reference in New Issue
Block a user