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';
|
'use strict';
|
||||||
|
|
||||||
const Config = require('../lib/node/config');
|
const Config = require('../lib/node/config');
|
||||||
const util = require('../lib/utils/util');
|
|
||||||
const {NodeClient, WalletClient} = require('bclient');
|
const {NodeClient, WalletClient} = require('bclient');
|
||||||
|
|
||||||
const ports = {
|
const ports = {
|
||||||
@ -178,9 +177,9 @@ CLI.prototype.getWallet = async function getWallet() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
CLI.prototype.getTX = async function getTX() {
|
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);
|
const txs = await this.client.getTXByAddress(hash);
|
||||||
this.log(txs);
|
this.log(txs);
|
||||||
return;
|
return;
|
||||||
@ -197,7 +196,7 @@ CLI.prototype.getTX = async function getTX() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
CLI.prototype.getBlock = async function getBlock() {
|
CLI.prototype.getBlock = async function getBlock() {
|
||||||
let hash = this.config.str(0);
|
let hash = this.config.str(0, '');
|
||||||
|
|
||||||
if (hash.length !== 64)
|
if (hash.length !== 64)
|
||||||
hash = parseInt(hash, 10);
|
hash = parseInt(hash, 10);
|
||||||
@ -213,10 +212,10 @@ CLI.prototype.getBlock = async function getBlock() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
CLI.prototype.getCoin = async function getCoin() {
|
CLI.prototype.getCoin = async function getCoin() {
|
||||||
const hash = this.config.str(0);
|
const hash = this.config.str(0, '');
|
||||||
const index = this.config.uint(1);
|
const index = this.config.uint(1);
|
||||||
|
|
||||||
if (util.isBase58(hash) || util.isBech32(hash)) {
|
if (hash.length !== 64) {
|
||||||
const coins = await this.client.getCoinsByAddress(hash);
|
const coins = await this.client.getCoinsByAddress(hash);
|
||||||
this.log(coins);
|
this.log(coins);
|
||||||
return;
|
return;
|
||||||
@ -471,19 +470,15 @@ CLI.prototype.importKey = async function importKey() {
|
|||||||
if (!key)
|
if (!key)
|
||||||
throw new Error('No key for import.');
|
throw new Error('No key for import.');
|
||||||
|
|
||||||
if (util.isBase58(key)) {
|
if (key.length === 66 || key.length === 130) {
|
||||||
await this.wallet.importPrivate(account, key, passphrase);
|
|
||||||
this.log('Imported private key.');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (util.isHex(key)) {
|
|
||||||
await this.wallet.importPublic(account, key);
|
await this.wallet.importPublic(account, key);
|
||||||
this.log('Imported public key.');
|
this.log('Imported public key.');
|
||||||
return;
|
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() {
|
CLI.prototype.importAddress = async function importAddress() {
|
||||||
|
|||||||
@ -6,7 +6,6 @@ process.title = 'bcoin';
|
|||||||
|
|
||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
const SPVNode = require('../lib/node/spvnode');
|
const SPVNode = require('../lib/node/spvnode');
|
||||||
const util = require('../lib/utils/util');
|
|
||||||
const Outpoint = require('../lib/primitives/outpoint');
|
const Outpoint = require('../lib/primitives/outpoint');
|
||||||
|
|
||||||
const node = SPVNode({
|
const node = SPVNode({
|
||||||
@ -44,7 +43,7 @@ process.on('unhandledRejection', (err, promise) => {
|
|||||||
node.on('block', (block) => {
|
node.on('block', (block) => {
|
||||||
assert(block.txs.length >= 1);
|
assert(block.txs.length >= 1);
|
||||||
if (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) {
|
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';
|
floating.style.display = 'block';
|
||||||
}
|
}
|
||||||
|
|
||||||
logger = new bcoin.logger({ level: 'debug', console: true });
|
logger = new bcoin.logger({ level: 'debug', console: true });
|
||||||
logger.writeConsole = function(level, module, args) {
|
logger.writeConsole = function(level, module, args) {
|
||||||
var name = bcoin.logger.levelsByVal[level];
|
var name = bcoin.logger.levelsByVal[level];
|
||||||
var msg = util.format(args, false);
|
var msg = this.fmt(args, false);
|
||||||
if (++scrollback > 1000) {
|
if (++scrollback > 1000) {
|
||||||
log.innerHTML = '';
|
log.innerHTML = '';
|
||||||
scrollback = 1;
|
scrollback = 1;
|
||||||
|
|||||||
@ -4,7 +4,6 @@ const assert = require('assert');
|
|||||||
const net = require('net');
|
const net = require('net');
|
||||||
const EventEmitter = require('events');
|
const EventEmitter = require('events');
|
||||||
const bsock = require('bsock');
|
const bsock = require('bsock');
|
||||||
const util = require('../lib/utils/util');
|
|
||||||
const digest = require('bcrypto/lib/digest');
|
const digest = require('bcrypto/lib/digest');
|
||||||
const IP = require('../lib/utils/ip');
|
const IP = require('../lib/utils/ip');
|
||||||
const BufferWriter = require('../lib/utils/writer');
|
const BufferWriter = require('../lib/utils/writer');
|
||||||
@ -76,7 +75,7 @@ WSProxy.prototype.handleConnect = function handleConnect(ws, port, host, nonce)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!util.isU16(port)
|
if ((port & 0xffff) !== port
|
||||||
|| typeof host !== 'string'
|
|| typeof host !== 'string'
|
||||||
|| host.length === 0) {
|
|| host.length === 0) {
|
||||||
this.log('Client gave bad arguments (%s).', state.host);
|
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 (this.pow) {
|
||||||
if (!util.isU32(nonce)) {
|
if ((nonce >>> 0) !== nonce) {
|
||||||
this.log('Client did not solve proof of work (%s).', state.host);
|
this.log('Client did not solve proof of work (%s).', state.host);
|
||||||
ws.fire('tcp close');
|
ws.fire('tcp close');
|
||||||
ws.destroy();
|
ws.destroy();
|
||||||
@ -228,7 +227,7 @@ WSProxy.prototype.attach = function attach(server) {
|
|||||||
function SocketState(server, socket) {
|
function SocketState(server, socket) {
|
||||||
this.pow = server.pow;
|
this.pow = server.pow;
|
||||||
this.target = server.target;
|
this.target = server.target;
|
||||||
this.snonce = util.nonce();
|
this.snonce = nonce();
|
||||||
this.socket = null;
|
this.socket = null;
|
||||||
this.host = IP.normalize(socket.conn.remoteAddress);
|
this.host = IP.normalize(socket.conn.remoteAddress);
|
||||||
this.remoteHost = null;
|
this.remoteHost = null;
|
||||||
@ -248,4 +247,11 @@ SocketState.prototype.connect = function connect(port, host) {
|
|||||||
return this.socket;
|
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;
|
module.exports = WSProxy;
|
||||||
|
|||||||
@ -64,12 +64,12 @@ PaymentDetails.prototype.fromOptions = function fromOptions(options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (options.time != null) {
|
if (options.time != null) {
|
||||||
assert(util.isInt(options.time));
|
assert(Number.isSafeInteger(options.time));
|
||||||
this.time = options.time;
|
this.time = options.time;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.expires != null) {
|
if (options.expires != null) {
|
||||||
assert(util.isInt(options.expires));
|
assert(Number.isSafeInteger(options.expires));
|
||||||
this.expires = options.expires;
|
this.expires = options.expires;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -7,10 +7,9 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
const util = require('../utils/util');
|
|
||||||
const digest = require('bcrypto/lib/digest');
|
const digest = require('bcrypto/lib/digest');
|
||||||
|
const PEM = require('bcrypto/lib/utils/pem');
|
||||||
const x509 = require('./x509');
|
const x509 = require('./x509');
|
||||||
const PEM = require('../utils/pem');
|
|
||||||
const ProtoReader = require('../utils/protoreader');
|
const ProtoReader = require('../utils/protoreader');
|
||||||
const ProtoWriter = require('../utils/protowriter');
|
const ProtoWriter = require('../utils/protowriter');
|
||||||
const PaymentDetails = require('./paymentdetails');
|
const PaymentDetails = require('./paymentdetails');
|
||||||
@ -50,7 +49,7 @@ function PaymentRequest(options) {
|
|||||||
|
|
||||||
PaymentRequest.prototype.fromOptions = function fromOptions(options) {
|
PaymentRequest.prototype.fromOptions = function fromOptions(options) {
|
||||||
if (options.version != null) {
|
if (options.version != null) {
|
||||||
assert(util.isInt(options.version));
|
assert((options.version | 0) === options.version);
|
||||||
this.version = options.version;
|
this.version = options.version;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -7,8 +7,8 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
const ASN1 = require('../utils/asn1');
|
const ASN1 = require('bcrypto/lib/utils/asn1');
|
||||||
const PEM = require('../utils/pem');
|
const PEM = require('bcrypto/lib/utils/pem');
|
||||||
const util = require('../utils/util');
|
const util = require('../utils/util');
|
||||||
const digest = require('bcrypto/lib/digest');
|
const digest = require('bcrypto/lib/digest');
|
||||||
const pk = require('./pk');
|
const pk = require('./pk');
|
||||||
|
|||||||
@ -1071,7 +1071,7 @@ Chain.prototype.setBestChain = async function setBestChain(entry, block, prev, f
|
|||||||
if (entry.hasUnknown(this.network)) {
|
if (entry.hasUnknown(this.network)) {
|
||||||
this.logger.warning(
|
this.logger.warning(
|
||||||
'Unknown version bits in block %d: %s.',
|
'Unknown version bits in block %d: %s.',
|
||||||
entry.height, util.hex32(entry.version));
|
entry.height, entry.version.toString(16));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, everything is in order.
|
// Otherwise, everything is in order.
|
||||||
@ -1136,7 +1136,7 @@ Chain.prototype.saveAlternate = async function saveAlternate(entry, block, prev,
|
|||||||
if (entry.hasUnknown(this.network)) {
|
if (entry.hasUnknown(this.network)) {
|
||||||
this.logger.warning(
|
this.logger.warning(
|
||||||
'Unknown version bits in block %d: %s.',
|
'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);
|
await this.db.save(entry, block);
|
||||||
@ -1549,7 +1549,7 @@ Chain.prototype.logStatus = function logStatus(start, block, entry) {
|
|||||||
|
|
||||||
if (this.db.coinCache.capacity > 0) {
|
if (this.db.coinCache.capacity > 0) {
|
||||||
this.logger.debug('Coin Cache: size=%dmb, items=%d.',
|
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) {
|
if (options.maxFiles != null) {
|
||||||
assert(util.isU32(options.maxFiles));
|
assert((options.maxFiles >>> 0) === options.maxFiles);
|
||||||
this.maxFiles = options.maxFiles;
|
this.maxFiles = options.maxFiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.cacheSize != null) {
|
if (options.cacheSize != null) {
|
||||||
assert(util.isU64(options.cacheSize));
|
assert(Number.isSafeInteger(options.cacheSize));
|
||||||
|
assert(options.cacheSize >= 0);
|
||||||
this.cacheSize = options.cacheSize;
|
this.cacheSize = options.cacheSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2792,17 +2793,17 @@ ChainOptions.prototype.fromOptions = function fromOptions(options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (options.coinCache != null) {
|
if (options.coinCache != null) {
|
||||||
assert(util.isU64(options.coinCache));
|
assert((options.coinCache >>> 0) === options.coinCache);
|
||||||
this.coinCache = options.coinCache;
|
this.coinCache = options.coinCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.entryCache != null) {
|
if (options.entryCache != null) {
|
||||||
assert(util.isU32(options.entryCache));
|
assert((options.entryCache >>> 0) === options.entryCache);
|
||||||
this.entryCache = options.entryCache;
|
this.entryCache = options.entryCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.maxOrphans != null) {
|
if (options.maxOrphans != null) {
|
||||||
assert(util.isU32(options.maxOrphans));
|
assert((options.maxOrphans >>> 0) === options.maxOrphans);
|
||||||
this.maxOrphans = options.maxOrphans;
|
this.maxOrphans = options.maxOrphans;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -76,13 +76,13 @@ ChainEntry.MAX_CHAINWORK = new BN(1).ushln(256);
|
|||||||
ChainEntry.prototype.fromOptions = function fromOptions(options) {
|
ChainEntry.prototype.fromOptions = function fromOptions(options) {
|
||||||
assert(options, 'Block data is required.');
|
assert(options, 'Block data is required.');
|
||||||
assert(typeof options.hash === 'string');
|
assert(typeof options.hash === 'string');
|
||||||
assert(util.isU32(options.version));
|
assert((options.version >>> 0) === options.version);
|
||||||
assert(typeof options.prevBlock === 'string');
|
assert(typeof options.prevBlock === 'string');
|
||||||
assert(typeof options.merkleRoot === 'string');
|
assert(typeof options.merkleRoot === 'string');
|
||||||
assert(util.isU32(options.time));
|
assert((options.time >>> 0) === options.time);
|
||||||
assert(util.isU32(options.bits));
|
assert((options.bits >>> 0) === options.bits);
|
||||||
assert(util.isU32(options.nonce));
|
assert((options.nonce >>> 0) === options.nonce);
|
||||||
assert(util.isU32(options.height));
|
assert((options.height >>> 0) === options.height);
|
||||||
assert(!options.chainwork || BN.isBN(options.chainwork));
|
assert(!options.chainwork || BN.isBN(options.chainwork));
|
||||||
|
|
||||||
this.hash = options.hash;
|
this.hash = options.hash;
|
||||||
@ -298,12 +298,12 @@ ChainEntry.prototype.toJSON = function toJSON() {
|
|||||||
ChainEntry.prototype.fromJSON = function fromJSON(json) {
|
ChainEntry.prototype.fromJSON = function fromJSON(json) {
|
||||||
assert(json, 'Block data is required.');
|
assert(json, 'Block data is required.');
|
||||||
assert(typeof json.hash === 'string');
|
assert(typeof json.hash === 'string');
|
||||||
assert(util.isU32(json.version));
|
assert((json.version >>> 0) === json.version);
|
||||||
assert(typeof json.prevBlock === 'string');
|
assert(typeof json.prevBlock === 'string');
|
||||||
assert(typeof json.merkleRoot === 'string');
|
assert(typeof json.merkleRoot === 'string');
|
||||||
assert(util.isU32(json.time));
|
assert((json.time >>> 0) === json.time);
|
||||||
assert(util.isU32(json.bits));
|
assert((json.bits >>> 0) === json.bits);
|
||||||
assert(util.isU32(json.nonce));
|
assert((json.nonce >>> 0) === json.nonce);
|
||||||
assert(typeof json.chainwork === 'string');
|
assert(typeof json.chainwork === 'string');
|
||||||
|
|
||||||
this.hash = util.revHex(json.hash);
|
this.hash = util.revHex(json.hash);
|
||||||
@ -354,7 +354,7 @@ ChainEntry.prototype.toInv = function toInv() {
|
|||||||
|
|
||||||
ChainEntry.prototype.inspect = function inspect() {
|
ChainEntry.prototype.inspect = function inspect() {
|
||||||
const json = this.toJSON();
|
const json = this.toJSON();
|
||||||
json.version = util.hex32(json.version);
|
json.version = json.version.toString(16);
|
||||||
return json;
|
return json;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -7,9 +7,6 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
const util = require('../utils/util');
|
|
||||||
const pad8 = util.pad8;
|
|
||||||
const pad32 = util.pad32;
|
|
||||||
|
|
||||||
const layout = {
|
const layout = {
|
||||||
binary: false,
|
binary: false,
|
||||||
@ -23,7 +20,7 @@ const layout = {
|
|||||||
return 'h' + hex(hash);
|
return 'h' + hex(hash);
|
||||||
},
|
},
|
||||||
H: function H(height) {
|
H: function H(height) {
|
||||||
return 'H' + pad32(height);
|
return 'H' + hex32(height);
|
||||||
},
|
},
|
||||||
n: function n(hash) {
|
n: function n(hash) {
|
||||||
return 'n' + hex(hash);
|
return 'n' + hex(hash);
|
||||||
@ -38,18 +35,18 @@ const layout = {
|
|||||||
return 't' + hex(hash);
|
return 't' + hex(hash);
|
||||||
},
|
},
|
||||||
c: function c(hash, index) {
|
c: function c(hash, index) {
|
||||||
return 'c' + hex(hash) + pad32(index);
|
return 'c' + hex(hash) + hex32(index);
|
||||||
},
|
},
|
||||||
u: function u(hash) {
|
u: function u(hash) {
|
||||||
return 'u' + hex(hash);
|
return 'u' + hex(hash);
|
||||||
},
|
},
|
||||||
v: function v(bit, hash) {
|
v: function v(bit, hash) {
|
||||||
return 'v' + pad8(bit) + hex(hash);
|
return 'v' + hex8(bit) + hex(hash);
|
||||||
},
|
},
|
||||||
vv: function vv(key) {
|
vv: function vv(key) {
|
||||||
assert(typeof key === 'string');
|
assert(typeof key === 'string');
|
||||||
assert(key.length === 36);
|
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) {
|
T: function T(addr, hash) {
|
||||||
addr = hex(addr);
|
addr = hex(addr);
|
||||||
@ -64,10 +61,10 @@ const layout = {
|
|||||||
addr = hex(addr);
|
addr = hex(addr);
|
||||||
|
|
||||||
if (addr.length === 64)
|
if (addr.length === 64)
|
||||||
return 'X' + addr + hex(hash) + pad32(index);
|
return 'X' + addr + hex(hash) + hex32(index);
|
||||||
|
|
||||||
assert(addr.length === 40);
|
assert(addr.length === 40);
|
||||||
return 'C' + addr + hex(hash) + pad32(index);
|
return 'C' + addr + hex(hash) + hex32(index);
|
||||||
},
|
},
|
||||||
pp: function pp(key) {
|
pp: function pp(key) {
|
||||||
assert(typeof key === 'string');
|
assert(typeof key === 'string');
|
||||||
@ -78,12 +75,12 @@ const layout = {
|
|||||||
assert(typeof key === 'string');
|
assert(typeof key === 'string');
|
||||||
|
|
||||||
let hash, index;
|
let hash, index;
|
||||||
if (key.length === 139) {
|
if (key.length === 137) {
|
||||||
hash = key.slice(65, 129);
|
hash = key.slice(65, 129);
|
||||||
index = parseInt(key.slice(129), 10);
|
index = parseInt(key.slice(129), 16);
|
||||||
} else if (key.length === 115) {
|
} else if (key.length === 113) {
|
||||||
hash = key.slice(41, 105);
|
hash = key.slice(41, 105);
|
||||||
index = parseInt(key.slice(105), 10);
|
index = parseInt(key.slice(105), 16);
|
||||||
} else {
|
} else {
|
||||||
assert(false);
|
assert(false);
|
||||||
}
|
}
|
||||||
@ -112,6 +109,47 @@ function hex(hash) {
|
|||||||
return 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
|
* Expose
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -7,7 +7,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
const util = require('../utils/util');
|
const fixed = require('../utils/fixed');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a bitcoin amount (satoshis internally).
|
* Represents a bitcoin amount (satoshis internally).
|
||||||
@ -138,7 +138,7 @@ Amount.prototype.toString = function toString() {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Amount.prototype.fromValue = function fromValue(value) {
|
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;
|
this.value = value;
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
@ -335,8 +335,8 @@ Amount.value = function value(str) {
|
|||||||
|
|
||||||
Amount.encode = function encode(value, exp, num) {
|
Amount.encode = function encode(value, exp, num) {
|
||||||
if (num)
|
if (num)
|
||||||
return util.toFloat(value, exp);
|
return fixed.toFloat(value, exp);
|
||||||
return util.toFixed(value, exp);
|
return fixed.encode(value, exp);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -349,8 +349,8 @@ Amount.encode = function encode(value, exp, num) {
|
|||||||
|
|
||||||
Amount.decode = function decode(value, exp) {
|
Amount.decode = function decode(value, exp) {
|
||||||
if (typeof value === 'number')
|
if (typeof value === 'number')
|
||||||
return util.fromFloat(value, exp);
|
return fixed.fromFloat(value, exp);
|
||||||
return util.fromFixed(value, exp);
|
return fixed.decode(value, exp);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@ -7,7 +7,6 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
const util = require('../utils/util');
|
|
||||||
const Address = require('../primitives/address');
|
const Address = require('../primitives/address');
|
||||||
const Amount = require('./amount');
|
const Amount = require('./amount');
|
||||||
|
|
||||||
@ -52,7 +51,8 @@ URI.prototype.fromOptions = function fromOptions(options) {
|
|||||||
this.address.fromOptions(options.address);
|
this.address.fromOptions(options.address);
|
||||||
|
|
||||||
if (options.amount != null) {
|
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;
|
this.amount = options.amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -7,7 +7,6 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
const util = require('../utils/util');
|
|
||||||
const digest = require('bcrypto/lib/digest');
|
const digest = require('bcrypto/lib/digest');
|
||||||
const cleanse = require('bcrypto/lib/cleanse');
|
const cleanse = require('bcrypto/lib/cleanse');
|
||||||
const random = require('bcrypto/lib/random');
|
const random = require('bcrypto/lib/random');
|
||||||
@ -84,7 +83,7 @@ Mnemonic.prototype.fromOptions = function fromOptions(options) {
|
|||||||
options = { phrase: options };
|
options = { phrase: options };
|
||||||
|
|
||||||
if (options.bits != null) {
|
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.MIN_ENTROPY);
|
||||||
assert(options.bits <= common.MAX_ENTROPY);
|
assert(options.bits <= common.MAX_ENTROPY);
|
||||||
assert(options.bits % 32 === 0);
|
assert(options.bits % 32 === 0);
|
||||||
@ -403,7 +402,8 @@ Mnemonic.prototype.toJSON = function toJSON() {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Mnemonic.prototype.fromJSON = function fromJSON(json) {
|
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.language === 'string');
|
||||||
assert(typeof json.entropy === 'string');
|
assert(typeof json.entropy === 'string');
|
||||||
assert(typeof json.phrase === 'string');
|
assert(typeof json.phrase === 'string');
|
||||||
|
|||||||
@ -7,7 +7,6 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
const util = require('../utils/util');
|
|
||||||
const digest = require('bcrypto/lib/digest');
|
const digest = require('bcrypto/lib/digest');
|
||||||
const cleanse = require('bcrypto/lib/cleanse');
|
const cleanse = require('bcrypto/lib/cleanse');
|
||||||
const random = require('bcrypto/lib/random');
|
const random = require('bcrypto/lib/random');
|
||||||
@ -72,9 +71,9 @@ function HDPrivateKey(options) {
|
|||||||
|
|
||||||
HDPrivateKey.prototype.fromOptions = function fromOptions(options) {
|
HDPrivateKey.prototype.fromOptions = function fromOptions(options) {
|
||||||
assert(options, 'No options for HD private key.');
|
assert(options, 'No options for HD private key.');
|
||||||
assert(util.isU8(options.depth));
|
assert((options.depth & 0xff) === options.depth);
|
||||||
assert(util.isU32(options.parentFingerPrint));
|
assert((options.parentFingerPrint >>> 0) === options.parentFingerPrint);
|
||||||
assert(util.isU32(options.childIndex));
|
assert((options.childIndex >>> 0) === options.childIndex);
|
||||||
assert(Buffer.isBuffer(options.chainCode));
|
assert(Buffer.isBuffer(options.chainCode));
|
||||||
assert(Buffer.isBuffer(options.privateKey));
|
assert(Buffer.isBuffer(options.privateKey));
|
||||||
|
|
||||||
@ -250,9 +249,9 @@ HDPrivateKey.prototype.getID = function getID(index) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
HDPrivateKey.prototype.deriveAccount = function deriveAccount(purpose, type, account) {
|
HDPrivateKey.prototype.deriveAccount = function deriveAccount(purpose, type, account) {
|
||||||
assert(util.isU32(purpose), 'Purpose must be a number.');
|
assert((purpose >>> 0) === purpose, 'Purpose must be a number.');
|
||||||
assert(util.isU32(type), 'Account index must be a number.');
|
assert((type >>> 0) === type, 'Account index must be a number.');
|
||||||
assert(util.isU32(account), 'Account index must be a number.');
|
assert((account >>> 0) === account, 'Account index must be a number.');
|
||||||
assert(this.isMaster(), 'Cannot derive account index.');
|
assert(this.isMaster(), 'Cannot derive account index.');
|
||||||
return this
|
return this
|
||||||
.derive(purpose, true)
|
.derive(purpose, true)
|
||||||
|
|||||||
@ -7,7 +7,6 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
const util = require('../utils/util');
|
|
||||||
const digest = require('bcrypto/lib/digest');
|
const digest = require('bcrypto/lib/digest');
|
||||||
const cleanse = require('bcrypto/lib/cleanse');
|
const cleanse = require('bcrypto/lib/cleanse');
|
||||||
const secp256k1 = require('bcrypto/lib/secp256k1');
|
const secp256k1 = require('bcrypto/lib/secp256k1');
|
||||||
@ -60,9 +59,9 @@ function HDPublicKey(options) {
|
|||||||
|
|
||||||
HDPublicKey.prototype.fromOptions = function fromOptions(options) {
|
HDPublicKey.prototype.fromOptions = function fromOptions(options) {
|
||||||
assert(options, 'No options for HDPublicKey');
|
assert(options, 'No options for HDPublicKey');
|
||||||
assert(util.isU8(options.depth));
|
assert((options.depth & 0xff) === options.depth);
|
||||||
assert(util.isU32(options.parentFingerPrint));
|
assert((options.parentFingerPrint >>> 0) === options.parentFingerPrint);
|
||||||
assert(util.isU32(options.childIndex));
|
assert((options.childIndex >>> 0) === options.childIndex);
|
||||||
assert(Buffer.isBuffer(options.chainCode));
|
assert(Buffer.isBuffer(options.chainCode));
|
||||||
assert(Buffer.isBuffer(options.publicKey));
|
assert(Buffer.isBuffer(options.publicKey));
|
||||||
|
|
||||||
@ -211,9 +210,9 @@ HDPublicKey.prototype.getID = function getID(index) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
HDPublicKey.prototype.deriveAccount = function deriveAccount(purpose, type, account) {
|
HDPublicKey.prototype.deriveAccount = function deriveAccount(purpose, type, account) {
|
||||||
assert(util.isU32(purpose));
|
assert((purpose >>> 0) === purpose);
|
||||||
assert(util.isU32(type));
|
assert((type >>> 0) === type);
|
||||||
assert(util.isU32(account));
|
assert((account >>> 0) === account);
|
||||||
assert(this.isAccount(account), 'Cannot derive account index.');
|
assert(this.isAccount(account), 'Cannot derive account index.');
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -121,11 +121,11 @@ class RPC extends RPCBase {
|
|||||||
case 'RPCError':
|
case 'RPCError':
|
||||||
return err.code;
|
return err.code;
|
||||||
case 'ValidationError':
|
case 'ValidationError':
|
||||||
return errors.TYPE_ERROR;
|
return errs.TYPE_ERROR;
|
||||||
case 'EncodingError':
|
case 'EncodingError':
|
||||||
return errors.DESERIALIZATION_ERROR;
|
return errs.DESERIALIZATION_ERROR;
|
||||||
default:
|
default:
|
||||||
return errors.INTERNAL_ERROR;
|
return errs.INTERNAL_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -307,7 +307,7 @@ class RPC extends RPCBase {
|
|||||||
version: pkg.version,
|
version: pkg.version,
|
||||||
subversion: this.pool.options.agent,
|
subversion: this.pool.options.agent,
|
||||||
protocolversion: this.pool.options.version,
|
protocolversion: this.pool.options.version,
|
||||||
localservices: util.hex32(this.pool.options.services),
|
localservices: hex32(this.pool.options.services),
|
||||||
localrelay: !this.pool.options.noRelay,
|
localrelay: !this.pool.options.noRelay,
|
||||||
timeoffset: this.network.time.offset,
|
timeoffset: this.network.time.offset,
|
||||||
networkactive: this.pool.connected,
|
networkactive: this.pool.connected,
|
||||||
@ -446,7 +446,7 @@ class RPC extends RPCBase {
|
|||||||
return {
|
return {
|
||||||
totalbytesrecv: recv,
|
totalbytesrecv: recv,
|
||||||
totalbytessent: sent,
|
totalbytessent: sent,
|
||||||
timemillis: util.ms()
|
timemillis: Date.now()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -474,13 +474,13 @@ class RPC extends RPCBase {
|
|||||||
addrlocal: !peer.local.isNull()
|
addrlocal: !peer.local.isNull()
|
||||||
? peer.local.hostname
|
? peer.local.hostname
|
||||||
: undefined,
|
: undefined,
|
||||||
services: util.hex32(peer.services),
|
services: hex32(peer.services),
|
||||||
relaytxes: !peer.noRelay,
|
relaytxes: !peer.noRelay,
|
||||||
lastsend: peer.lastSend / 1000 | 0,
|
lastsend: peer.lastSend / 1000 | 0,
|
||||||
lastrecv: peer.lastRecv / 1000 | 0,
|
lastrecv: peer.lastRecv / 1000 | 0,
|
||||||
bytessent: peer.socket.bytesWritten,
|
bytessent: peer.socket.bytesWritten,
|
||||||
bytesrecv: peer.socket.bytesRead,
|
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,
|
timeoffset: offset,
|
||||||
pingtime: peer.lastPong !== -1
|
pingtime: peer.lastPong !== -1
|
||||||
? (peer.lastPong - peer.lastPing) / 1000
|
? (peer.lastPong - peer.lastPing) / 1000
|
||||||
@ -626,8 +626,10 @@ class RPC extends RPCBase {
|
|||||||
if (this.chain.options.spv)
|
if (this.chain.options.spv)
|
||||||
throw new RPCError(errs.MISC_ERROR, 'Block not available (spv mode)');
|
throw new RPCError(errs.MISC_ERROR, 'Block not available (spv mode)');
|
||||||
|
|
||||||
if (this.chain.options.prune)
|
if (this.chain.options.prune) {
|
||||||
throw new RPCError(errs.MISC_ERROR, 'Block not available (pruned data)');
|
throw new RPCError(errs.MISC_ERROR,
|
||||||
|
'Block not available (pruned data)');
|
||||||
|
}
|
||||||
|
|
||||||
throw new RPCError(errs.MISC_ERROR, 'Can\'t read block from disk');
|
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)
|
if (this.chain.options.spv)
|
||||||
throw new RPCError(errs.MISC_ERROR, 'Block not available (spv mode)');
|
throw new RPCError(errs.MISC_ERROR, 'Block not available (spv mode)');
|
||||||
|
|
||||||
if (this.chain.options.prune)
|
if (this.chain.options.prune) {
|
||||||
throw new RPCError(errs.MISC_ERROR, 'Block not available (pruned data)');
|
throw new RPCError(errs.MISC_ERROR,
|
||||||
|
'Block not available (pruned data)');
|
||||||
|
}
|
||||||
|
|
||||||
throw new RPCError(errs.DATABASE_ERROR, 'Can\'t read block from disk');
|
throw new RPCError(errs.DATABASE_ERROR, 'Can\'t read block from disk');
|
||||||
}
|
}
|
||||||
@ -798,8 +802,10 @@ class RPC extends RPCBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getMempoolDescendants(args, help) {
|
async getMempoolDescendants(args, help) {
|
||||||
if (help || args.length < 1 || args.length > 2)
|
if (help || args.length < 1 || args.length > 2) {
|
||||||
throw new RPCError(errs.MISC_ERROR, 'getmempooldescendants txid (verbose)');
|
throw new RPCError(errs.MISC_ERROR,
|
||||||
|
'getmempooldescendants txid (verbose)');
|
||||||
|
}
|
||||||
|
|
||||||
const valid = new Validator(args);
|
const valid = new Validator(args);
|
||||||
const hash = valid.rhash(0);
|
const hash = valid.rhash(0);
|
||||||
@ -876,8 +882,10 @@ class RPC extends RPCBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getTXOut(args, help) {
|
async getTXOut(args, help) {
|
||||||
if (help || args.length < 2 || args.length > 3)
|
if (help || args.length < 2 || args.length > 3) {
|
||||||
throw new RPCError(errs.MISC_ERROR, 'gettxout "txid" n ( includemempool )');
|
throw new RPCError(errs.MISC_ERROR,
|
||||||
|
'gettxout "txid" n ( includemempool )');
|
||||||
|
}
|
||||||
|
|
||||||
const valid = new Validator(args);
|
const valid = new Validator(args);
|
||||||
const hash = valid.rhash(0);
|
const hash = valid.rhash(0);
|
||||||
@ -1018,8 +1026,10 @@ class RPC extends RPCBase {
|
|||||||
if (help || args.length !== 0)
|
if (help || args.length !== 0)
|
||||||
throw new RPCError(errs.MISC_ERROR, 'gettxoutsetinfo');
|
throw new RPCError(errs.MISC_ERROR, 'gettxoutsetinfo');
|
||||||
|
|
||||||
if (this.chain.options.spv)
|
if (this.chain.options.spv) {
|
||||||
throw new RPCError(errs.MISC_ERROR, 'Chainstate not available (SPV mode).');
|
throw new RPCError(errs.MISC_ERROR,
|
||||||
|
'Chainstate not available (SPV mode).');
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
height: this.chain.height,
|
height: this.chain.height,
|
||||||
@ -1053,8 +1063,10 @@ class RPC extends RPCBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async verifyChain(args, help) {
|
async verifyChain(args, help) {
|
||||||
if (help || args.length > 2)
|
if (help || args.length > 2) {
|
||||||
throw new RPCError(errs.MISC_ERROR, 'verifychain ( checklevel numblocks )');
|
throw new RPCError(errs.MISC_ERROR,
|
||||||
|
'verifychain ( checklevel numblocks )');
|
||||||
|
}
|
||||||
|
|
||||||
const valid = new Validator(args);
|
const valid = new Validator(args);
|
||||||
const level = valid.u32(0);
|
const level = valid.u32(0);
|
||||||
@ -1451,7 +1463,7 @@ class RPC extends RPCBase {
|
|||||||
height: attempt.height,
|
height: attempt.height,
|
||||||
previousblockhash: util.revHex(attempt.prevBlock),
|
previousblockhash: util.revHex(attempt.prevBlock),
|
||||||
target: util.revHex(attempt.target.toString('hex')),
|
target: util.revHex(attempt.target.toString('hex')),
|
||||||
bits: util.hex32(attempt.bits),
|
bits: hex32(attempt.bits),
|
||||||
noncerange: '00000000ffffffff',
|
noncerange: '00000000ffffffff',
|
||||||
curtime: attempt.time,
|
curtime: attempt.time,
|
||||||
mintime: attempt.mtp + 1,
|
mintime: attempt.mtp + 1,
|
||||||
@ -1460,7 +1472,7 @@ class RPC extends RPCBase {
|
|||||||
sigoplimit: consensus.MAX_BLOCK_SIGOPS_COST / scale | 0,
|
sigoplimit: consensus.MAX_BLOCK_SIGOPS_COST / scale | 0,
|
||||||
sizelimit: consensus.MAX_BLOCK_SIZE,
|
sizelimit: consensus.MAX_BLOCK_SIZE,
|
||||||
weightlimit: undefined,
|
weightlimit: undefined,
|
||||||
longpollid: this.chain.tip.rhash() + util.pad32(this.totalTX()),
|
longpollid: this.chain.tip.rhash() + hex32(this.totalTX()),
|
||||||
submitold: false,
|
submitold: false,
|
||||||
coinbaseaux: {
|
coinbaseaux: {
|
||||||
flags: attempt.coinbaseFlags.toString('hex')
|
flags: attempt.coinbaseFlags.toString('hex')
|
||||||
@ -1817,8 +1829,10 @@ class RPC extends RPCBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getRawTransaction(args, help) {
|
async getRawTransaction(args, help) {
|
||||||
if (help || args.length < 1 || args.length > 2)
|
if (help || args.length < 1 || args.length > 2) {
|
||||||
throw new RPCError(errs.MISC_ERROR, 'getrawtransaction "txid" ( verbose )');
|
throw new RPCError(errs.MISC_ERROR,
|
||||||
|
'getrawtransaction "txid" ( verbose )');
|
||||||
|
}
|
||||||
|
|
||||||
const valid = new Validator(args);
|
const valid = new Validator(args);
|
||||||
const hash = valid.rhash(0);
|
const hash = valid.rhash(0);
|
||||||
@ -1985,8 +1999,10 @@ class RPC extends RPCBase {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
async createMultisig(args, help) {
|
async createMultisig(args, help) {
|
||||||
if (help || args.length < 2 || args.length > 2)
|
if (help || args.length < 2 || args.length > 2) {
|
||||||
throw new RPCError(errs.MISC_ERROR, 'createmultisig nrequired ["key",...]');
|
throw new RPCError(errs.MISC_ERROR,
|
||||||
|
'createmultisig nrequired ["key",...]');
|
||||||
|
}
|
||||||
|
|
||||||
const valid = new Validator(args);
|
const valid = new Validator(args);
|
||||||
const keys = valid.array(1, []);
|
const keys = valid.array(1, []);
|
||||||
@ -2012,8 +2028,10 @@ class RPC extends RPCBase {
|
|||||||
|
|
||||||
const script = Script.fromMultisig(m, n, keys);
|
const script = Script.fromMultisig(m, n, keys);
|
||||||
|
|
||||||
if (script.getSize() > consensus.MAX_SCRIPT_PUSH)
|
if (script.getSize() > consensus.MAX_SCRIPT_PUSH) {
|
||||||
throw new RPCError(errs.VERIFY_ERROR, 'Redeem script exceeds size limit.');
|
throw new RPCError(errs.VERIFY_ERROR,
|
||||||
|
'Redeem script exceeds size limit.');
|
||||||
|
}
|
||||||
|
|
||||||
const addr = script.getAddress();
|
const addr = script.getAddress();
|
||||||
|
|
||||||
@ -2239,7 +2257,7 @@ class RPC extends RPCBase {
|
|||||||
if (help || args.length !== 0)
|
if (help || args.length !== 0)
|
||||||
throw new RPCError(errs.MISC_ERROR, 'getmemoryinfo');
|
throw new RPCError(errs.MISC_ERROR, 'getmemoryinfo');
|
||||||
|
|
||||||
return util.memoryUsage();
|
return this.logger.memoryUsage();
|
||||||
}
|
}
|
||||||
|
|
||||||
async setLogLevel(args, help) {
|
async setLogLevel(args, help) {
|
||||||
@ -2259,13 +2277,13 @@ class RPC extends RPCBase {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
async handleLongpoll(lpid) {
|
async handleLongpoll(lpid) {
|
||||||
if (lpid.length !== 74)
|
if (lpid.length !== 72)
|
||||||
throw new RPCError(errs.INVALID_PARAMETER, 'Invalid longpoll ID.');
|
throw new RPCError(errs.INVALID_PARAMETER, 'Invalid longpoll ID.');
|
||||||
|
|
||||||
const watched = lpid.slice(0, 64);
|
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.');
|
throw new RPCError(errs.INVALID_PARAMETER, 'Invalid longpoll ID.');
|
||||||
|
|
||||||
const hash = util.revHex(watched);
|
const hash = util.revHex(watched);
|
||||||
@ -2680,7 +2698,7 @@ class RPC extends RPCBase {
|
|||||||
confirmations: this.chain.height - entry.height + 1,
|
confirmations: this.chain.height - entry.height + 1,
|
||||||
height: entry.height,
|
height: entry.height,
|
||||||
version: entry.version,
|
version: entry.version,
|
||||||
versionHex: util.hex32(entry.version),
|
versionHex: hex32(entry.version),
|
||||||
merkleroot: util.revHex(entry.merkleRoot),
|
merkleroot: util.revHex(entry.merkleRoot),
|
||||||
time: entry.time,
|
time: entry.time,
|
||||||
mediantime: mtp,
|
mediantime: mtp,
|
||||||
@ -2716,7 +2734,7 @@ class RPC extends RPCBase {
|
|||||||
weight: block.getWeight(),
|
weight: block.getWeight(),
|
||||||
height: entry.height,
|
height: entry.height,
|
||||||
version: entry.version,
|
version: entry.version,
|
||||||
versionHex: util.hex32(entry.version),
|
versionHex: hex32(entry.version),
|
||||||
merkleroot: util.revHex(entry.merkleRoot),
|
merkleroot: util.revHex(entry.merkleRoot),
|
||||||
coinbase: block.txs[0].inputs[0].script.toJSON(),
|
coinbase: block.txs[0].inputs[0].script.toJSON(),
|
||||||
tx: txs,
|
tx: txs,
|
||||||
@ -2825,6 +2843,19 @@ function toDifficulty(bits) {
|
|||||||
return diff;
|
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
|
* Expose
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -140,7 +140,7 @@ class HTTPServer extends Server {
|
|||||||
adjusted: this.network.now(),
|
adjusted: this.network.now(),
|
||||||
offset: this.network.time.offset
|
offset: this.network.time.offset
|
||||||
},
|
},
|
||||||
memory: util.memoryUsage()
|
memory: this.logger.memoryUsage()
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -715,8 +715,6 @@ class HTTPOptions {
|
|||||||
'API key must be a string.');
|
'API key must be a string.');
|
||||||
assert(options.apiKey.length <= 255,
|
assert(options.apiKey.length <= 255,
|
||||||
'API key must be under 256 bytes.');
|
'API key must be under 256 bytes.');
|
||||||
assert(util.isAscii(options.apiKey),
|
|
||||||
'API key must be ascii.');
|
|
||||||
this.apiKey = options.apiKey;
|
this.apiKey = options.apiKey;
|
||||||
this.apiHash = digest.hash256(Buffer.from(this.apiKey, 'ascii'));
|
this.apiHash = digest.hash256(Buffer.from(this.apiKey, 'ascii'));
|
||||||
}
|
}
|
||||||
@ -739,7 +737,8 @@ class HTTPOptions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (options.port != null) {
|
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;
|
this.port = options.port;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
const util = require('../utils/util');
|
const util = require('../utils/util');
|
||||||
|
const binary = require('../utils/binary');
|
||||||
const consensus = require('../protocol/consensus');
|
const consensus = require('../protocol/consensus');
|
||||||
const policy = require('../protocol/policy');
|
const policy = require('../protocol/policy');
|
||||||
const BufferReader = require('../utils/reader');
|
const BufferReader = require('../utils/reader');
|
||||||
@ -691,7 +692,7 @@ PolicyEstimator.prototype.estimateFee = function estimateFee(target, smart) {
|
|||||||
if (smart == null)
|
if (smart == null)
|
||||||
smart = true;
|
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,
|
assert(target <= this.feeStats.maxConfirms,
|
||||||
'Too many confirmations for estimate.');
|
'Too many confirmations for estimate.');
|
||||||
|
|
||||||
@ -735,7 +736,7 @@ PolicyEstimator.prototype.estimatePriority = function estimatePriority(target, s
|
|||||||
if (smart == null)
|
if (smart == null)
|
||||||
smart = true;
|
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,
|
assert(target <= this.priStats.maxConfirms,
|
||||||
'Too many confirmations for estimate.');
|
'Too many confirmations for estimate.');
|
||||||
|
|
||||||
@ -856,12 +857,12 @@ function DoubleMap() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
DoubleMap.prototype.insert = function insert(key, value) {
|
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]);
|
this.buckets.splice(i, 0, [key, value]);
|
||||||
};
|
};
|
||||||
|
|
||||||
DoubleMap.prototype.search = function search(key) {
|
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.');
|
assert(this.buckets.length !== 0, 'Cannot search.');
|
||||||
return this.buckets[i][1];
|
return this.buckets[i][1];
|
||||||
};
|
};
|
||||||
|
|||||||
@ -2035,7 +2035,7 @@ MempoolOptions.prototype.fromOptions = function fromOptions(options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (options.limitFreeRelay != null) {
|
if (options.limitFreeRelay != null) {
|
||||||
assert(util.isU32(options.limitFreeRelay));
|
assert((options.limitFreeRelay >>> 0) === options.limitFreeRelay);
|
||||||
this.limitFreeRelay = options.limitFreeRelay;
|
this.limitFreeRelay = options.limitFreeRelay;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2070,27 +2070,27 @@ MempoolOptions.prototype.fromOptions = function fromOptions(options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (options.maxSize != null) {
|
if (options.maxSize != null) {
|
||||||
assert(util.isU64(options.maxSize));
|
assert((options.maxSize >>> 0) === options.maxSize);
|
||||||
this.maxSize = options.maxSize;
|
this.maxSize = options.maxSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.maxOrphans != null) {
|
if (options.maxOrphans != null) {
|
||||||
assert(util.isU32(options.maxOrphans));
|
assert((options.maxOrphans >>> 0) === options.maxOrphans);
|
||||||
this.maxOrphans = options.maxOrphans;
|
this.maxOrphans = options.maxOrphans;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.maxAncestors != null) {
|
if (options.maxAncestors != null) {
|
||||||
assert(util.isU32(options.maxAncestors));
|
assert((options.maxAncestors >>> 0) === options.maxAncestors);
|
||||||
this.maxAncestors = options.maxAncestors;
|
this.maxAncestors = options.maxAncestors;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.expiryTime != null) {
|
if (options.expiryTime != null) {
|
||||||
assert(util.isU32(options.expiryTime));
|
assert((options.expiryTime >>> 0) === options.expiryTime);
|
||||||
this.expiryTime = options.expiryTime;
|
this.expiryTime = options.expiryTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.minRelay != null) {
|
if (options.minRelay != null) {
|
||||||
assert(util.isU64(options.minRelay));
|
assert((options.minRelay >>> 0) === options.minRelay);
|
||||||
this.minRelay = options.minRelay;
|
this.minRelay = options.minRelay;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2111,12 +2111,13 @@ MempoolOptions.prototype.fromOptions = function fromOptions(options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (options.maxFiles != null) {
|
if (options.maxFiles != null) {
|
||||||
assert(util.isU32(options.maxFiles));
|
assert((options.maxFiles >>> 0) === options.maxFiles);
|
||||||
this.maxFiles = options.maxFiles;
|
this.maxFiles = options.maxFiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.cacheSize != null) {
|
if (options.cacheSize != null) {
|
||||||
assert(util.isU64(options.cacheSize));
|
assert(Number.isSafeInteger(options.cacheSize));
|
||||||
|
assert(options.cacheSize >= 0);
|
||||||
this.cacheSize = options.cacheSize;
|
this.cacheSize = options.cacheSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -8,7 +8,6 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
const util = require('../utils/util');
|
|
||||||
const Heap = require('../utils/heap');
|
const Heap = require('../utils/heap');
|
||||||
const AsyncObject = require('../utils/asyncobject');
|
const AsyncObject = require('../utils/asyncobject');
|
||||||
const Amount = require('../btc/amount');
|
const Amount = require('../btc/amount');
|
||||||
@ -429,7 +428,7 @@ MinerOptions.prototype.fromOptions = function fromOptions(options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (options.version != null) {
|
if (options.version != null) {
|
||||||
assert(util.isInt(options.version));
|
assert((options.version >>> 0) === options.version);
|
||||||
this.version = options.version;
|
this.version = options.version;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -463,41 +462,41 @@ MinerOptions.prototype.fromOptions = function fromOptions(options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (options.minWeight != null) {
|
if (options.minWeight != null) {
|
||||||
assert(util.isU32(options.minWeight));
|
assert((options.minWeight >>> 0) === options.minWeight);
|
||||||
this.minWeight = options.minWeight;
|
this.minWeight = options.minWeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.maxWeight != null) {
|
if (options.maxWeight != null) {
|
||||||
assert(util.isU32(options.maxWeight));
|
assert((options.maxWeight >>> 0) === options.maxWeight);
|
||||||
assert(options.maxWeight <= consensus.MAX_BLOCK_WEIGHT,
|
assert(options.maxWeight <= consensus.MAX_BLOCK_WEIGHT,
|
||||||
'Max weight must be below MAX_BLOCK_WEIGHT');
|
'Max weight must be below MAX_BLOCK_WEIGHT');
|
||||||
this.maxWeight = options.maxWeight;
|
this.maxWeight = options.maxWeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.maxSigops != null) {
|
if (options.maxSigops != null) {
|
||||||
assert(util.isU32(options.maxSigops));
|
assert((options.maxSigops >>> 0) === options.maxSigops);
|
||||||
assert(options.maxSigops <= consensus.MAX_BLOCK_SIGOPS_COST,
|
assert(options.maxSigops <= consensus.MAX_BLOCK_SIGOPS_COST,
|
||||||
'Max sigops must be below MAX_BLOCK_SIGOPS_COST');
|
'Max sigops must be below MAX_BLOCK_SIGOPS_COST');
|
||||||
this.maxSigops = options.maxSigops;
|
this.maxSigops = options.maxSigops;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.priorityWeight != null) {
|
if (options.priorityWeight != null) {
|
||||||
assert(util.isU32(options.priorityWeight));
|
assert((options.priorityWeight >>> 0) === options.priorityWeight);
|
||||||
this.priorityWeight = options.priorityWeight;
|
this.priorityWeight = options.priorityWeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.priorityThreshold != null) {
|
if (options.priorityThreshold != null) {
|
||||||
assert(util.isU32(options.priorityThreshold));
|
assert((options.priorityThreshold >>> 0) === options.priorityThreshold);
|
||||||
this.priorityThreshold = options.priorityThreshold;
|
this.priorityThreshold = options.priorityThreshold;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.reservedWeight != null) {
|
if (options.reservedWeight != null) {
|
||||||
assert(util.isU32(options.reservedWeight));
|
assert((options.reservedWeight >>> 0) === options.reservedWeight);
|
||||||
this.reservedWeight = options.reservedWeight;
|
this.reservedWeight = options.reservedWeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.reservedSigops != null) {
|
if (options.reservedSigops != null) {
|
||||||
assert(util.isU32(options.reservedSigops));
|
assert((options.reservedSigops >>> 0) === options.reservedSigops);
|
||||||
this.reservedSigops = options.reservedSigops;
|
this.reservedSigops = options.reservedSigops;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -246,7 +246,9 @@ BlockTemplate.prototype.createCoinbase = function createCoinbase(hash) {
|
|||||||
input.script.pushData(encoding.ZERO_HASH160);
|
input.script.pushData(encoding.ZERO_HASH160);
|
||||||
|
|
||||||
// Smaller nonce for good measure.
|
// 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
|
// Extra nonce: incremented when
|
||||||
// the nonce overflows.
|
// the nonce overflows.
|
||||||
|
|||||||
@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
const EventEmitter = require('events');
|
const EventEmitter = require('events');
|
||||||
|
const {format} = require('util');
|
||||||
const util = require('../utils/util');
|
const util = require('../utils/util');
|
||||||
const co = require('../utils/co');
|
const co = require('../utils/co');
|
||||||
const hash256 = require('bcrypto/lib/hash256');
|
const hash256 = require('bcrypto/lib/hash256');
|
||||||
@ -350,7 +351,7 @@ BIP151.MAX_MESSAGE = 12 * 1000 * 1000;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
BIP151.prototype.error = function error() {
|
BIP151.prototype.error = function error() {
|
||||||
const msg = util.fmt.apply(util, arguments);
|
const msg = format.apply(null, arguments);
|
||||||
this.emit('error', new Error(msg));
|
this.emit('error', new Error(msg));
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -700,7 +701,7 @@ BIP151.prototype.parse = function parse(data) {
|
|||||||
// Note that 6 is the minimum size:
|
// Note that 6 is the minimum size:
|
||||||
// varint-cmdlen(1) str-cmd(1) u32-size(4) payload(0)
|
// varint-cmdlen(1) str-cmd(1) u32-size(4) payload(0)
|
||||||
if (size < 6 || size > BIP151.MAX_MESSAGE) {
|
if (size < 6 || size > BIP151.MAX_MESSAGE) {
|
||||||
this.error('Bad packet size: %d.', util.mb(size));
|
this.error('Bad packet size: %d.', size);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -11,7 +11,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
const util = require('../utils/util');
|
|
||||||
const BufferReader = require('../utils/reader');
|
const BufferReader = require('../utils/reader');
|
||||||
const StaticWriter = require('../utils/staticwriter');
|
const StaticWriter = require('../utils/staticwriter');
|
||||||
const encoding = require('../utils/encoding');
|
const encoding = require('../utils/encoding');
|
||||||
@ -22,6 +21,7 @@ const AbstractBlock = require('../primitives/abstractblock');
|
|||||||
const TX = require('../primitives/tx');
|
const TX = require('../primitives/tx');
|
||||||
const Headers = require('../primitives/headers');
|
const Headers = require('../primitives/headers');
|
||||||
const Block = require('../primitives/block');
|
const Block = require('../primitives/block');
|
||||||
|
const common = require('./common');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a compact block (bip152): `cmpctblock` packet.
|
* Represents a compact block (bip152): `cmpctblock` packet.
|
||||||
@ -494,7 +494,7 @@ CompactBlock.prototype.fromBlock = function fromBlock(block, witness, nonce) {
|
|||||||
this._hhash = block._hhash;
|
this._hhash = block._hhash;
|
||||||
|
|
||||||
if (!nonce)
|
if (!nonce)
|
||||||
nonce = util.nonce();
|
nonce = common.nonce();
|
||||||
|
|
||||||
this.keyNonce = nonce;
|
this.keyNonce = nonce;
|
||||||
this.sipKey = this.getKey();
|
this.sipKey = this.getKey();
|
||||||
|
|||||||
@ -159,3 +159,15 @@ exports.BAN_TIME = 24 * 60 * 60;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
exports.BAN_SCORE = 100;
|
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;
|
buckets = this.fresh;
|
||||||
|
|
||||||
if (this.totalUsed > 0) {
|
if (this.totalUsed > 0) {
|
||||||
if (this.totalFresh === 0 || util.random(0, 2) === 0)
|
if (this.totalFresh === 0 || random(2) === 0)
|
||||||
buckets = this.used;
|
buckets = this.used;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -420,13 +420,13 @@ HostList.prototype.getHost = function getHost() {
|
|||||||
let factor = 1;
|
let factor = 1;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
let index = util.random(0, buckets.length);
|
let index = random(buckets.length);
|
||||||
const bucket = buckets[index];
|
const bucket = buckets[index];
|
||||||
|
|
||||||
if (bucket.size === 0)
|
if (bucket.size === 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
index = util.random(0, bucket.size);
|
index = random(bucket.size);
|
||||||
|
|
||||||
let entry;
|
let entry;
|
||||||
if (buckets === this.used) {
|
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))
|
if (num < factor * entry.chance(now) * (1 << 30))
|
||||||
return entry;
|
return entry;
|
||||||
@ -541,7 +541,7 @@ HostList.prototype.add = function add(addr, src) {
|
|||||||
for (let i = 0; i < entry.refCount; i++)
|
for (let i = 0; i < entry.refCount; i++)
|
||||||
factor *= 2;
|
factor *= 2;
|
||||||
|
|
||||||
if (util.random(0, factor) !== 0)
|
if (random(factor) !== 0)
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
if (this.isFull())
|
if (this.isFull())
|
||||||
@ -1374,12 +1374,13 @@ HostEntry.prototype.fromJSON = function fromJSON(json, network) {
|
|||||||
assert(json.services.length > 0);
|
assert(json.services.length > 0);
|
||||||
assert(json.services.length <= 32);
|
assert(json.services.length <= 32);
|
||||||
const services = parseInt(json.services, 2);
|
const services = parseInt(json.services, 2);
|
||||||
assert(util.isU32(services));
|
assert((services >>> 0) === services);
|
||||||
this.addr.services = services;
|
this.addr.services = services;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (json.time != null) {
|
if (json.time != null) {
|
||||||
assert(util.isU64(json.time));
|
assert(Number.isSafeInteger(json.time));
|
||||||
|
assert(json.time >= 0);
|
||||||
this.addr.time = json.time;
|
this.addr.time = json.time;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1389,17 +1390,19 @@ HostEntry.prototype.fromJSON = function fromJSON(json, network) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (json.attempts != null) {
|
if (json.attempts != null) {
|
||||||
assert(util.isU64(json.attempts));
|
assert((json.attempts >>> 0) === json.attempts);
|
||||||
this.attempts = json.attempts;
|
this.attempts = json.attempts;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (json.lastSuccess != null) {
|
if (json.lastSuccess != null) {
|
||||||
assert(util.isU64(json.lastSuccess));
|
assert(Number.isSafeInteger(json.lastSuccess));
|
||||||
|
assert(json.lastSuccess >= 0);
|
||||||
this.lastSuccess = json.lastSuccess;
|
this.lastSuccess = json.lastSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (json.lastAttempt != null) {
|
if (json.lastAttempt != null) {
|
||||||
assert(util.isU64(json.lastAttempt));
|
assert(Number.isSafeInteger(json.lastAttempt));
|
||||||
|
assert(json.lastAttempt >= 0);
|
||||||
this.lastAttempt = json.lastAttempt;
|
this.lastAttempt = json.lastAttempt;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1594,6 +1597,10 @@ function concat32(left, right) {
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function random(max) {
|
||||||
|
return Math.floor(Math.random() * max);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Expose
|
* Expose
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -67,8 +67,8 @@ exports.types = {
|
|||||||
AUTHPROPOSE: 30,
|
AUTHPROPOSE: 30,
|
||||||
UNKNOWN: 31,
|
UNKNOWN: 31,
|
||||||
// Internal
|
// Internal
|
||||||
INTERNAL: 100,
|
INTERNAL: 32,
|
||||||
DATA: 101
|
DATA: 33
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -77,7 +77,43 @@ exports.types = {
|
|||||||
* @default
|
* @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
|
* Base Packet
|
||||||
@ -1462,9 +1498,9 @@ RejectPacket.codes = {
|
|||||||
CHECKPOINT: 0x43,
|
CHECKPOINT: 0x43,
|
||||||
// Internal codes (NOT FOR USE ON NETWORK)
|
// Internal codes (NOT FOR USE ON NETWORK)
|
||||||
INTERNAL: 0x100,
|
INTERNAL: 0x100,
|
||||||
HIGHFEE: 0x100,
|
HIGHFEE: 0x101,
|
||||||
ALREADYKNOWN: 0x101,
|
ALREADYKNOWN: 0x102,
|
||||||
CONFLICT: 0x102
|
CONFLICT: 0x103
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1472,7 +1508,21 @@ RejectPacket.codes = {
|
|||||||
* @const {RevMap}
|
* @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.cmd = 'reject';
|
||||||
RejectPacket.prototype.type = exports.types.REJECT;
|
RejectPacket.prototype.type = exports.types.REJECT;
|
||||||
|
|||||||
@ -11,8 +11,8 @@
|
|||||||
|
|
||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
const EventEmitter = require('events');
|
const EventEmitter = require('events');
|
||||||
|
const {format} = require('util');
|
||||||
const Network = require('../protocol/network');
|
const Network = require('../protocol/network');
|
||||||
const util = require('../utils/util');
|
|
||||||
const digest = require('bcrypto/lib/digest');
|
const digest = require('bcrypto/lib/digest');
|
||||||
const common = require('./common');
|
const common = require('./common');
|
||||||
const packets = require('./packets');
|
const packets = require('./packets');
|
||||||
@ -49,7 +49,7 @@ Object.setPrototypeOf(Parser.prototype, EventEmitter.prototype);
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Parser.prototype.error = function error() {
|
Parser.prototype.error = function error() {
|
||||||
const msg = util.fmt.apply(util, arguments);
|
const msg = format.apply(null, arguments);
|
||||||
this.emit('error', new Error(msg));
|
this.emit('error', new Error(msg));
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -100,7 +100,7 @@ Parser.prototype.parse = function parse(data) {
|
|||||||
if (checksum !== this.header.checksum) {
|
if (checksum !== this.header.checksum) {
|
||||||
this.waiting = 24;
|
this.waiting = 24;
|
||||||
this.header = null;
|
this.header = null;
|
||||||
this.error('Invalid checksum: %s.', util.hex32(checksum));
|
this.error('Invalid checksum: %s.', checksum.toString(16));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,7 +130,7 @@ Parser.prototype.parseHeader = function parseHeader(data) {
|
|||||||
const magic = data.readUInt32LE(0, true);
|
const magic = data.readUInt32LE(0, true);
|
||||||
|
|
||||||
if (magic !== this.network.magic) {
|
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;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,7 +149,7 @@ Parser.prototype.parseHeader = function parseHeader(data) {
|
|||||||
|
|
||||||
if (size > common.MAX_MESSAGE) {
|
if (size > common.MAX_MESSAGE) {
|
||||||
this.waiting = 24;
|
this.waiting = 24;
|
||||||
this.error('Packet length too large: %dmb.', util.mb(size));
|
this.error('Packet length too large: %d.', size);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
const EventEmitter = require('events');
|
const EventEmitter = require('events');
|
||||||
|
const {format} = require('util');
|
||||||
const util = require('../utils/util');
|
const util = require('../utils/util');
|
||||||
const co = require('../utils/co');
|
const co = require('../utils/co');
|
||||||
const Parser = require('./parser');
|
const Parser = require('./parser');
|
||||||
@ -400,7 +401,7 @@ Peer.prototype.bind = function bind(socket) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.socket.on('data', (chunk) => {
|
this.socket.on('data', (chunk) => {
|
||||||
this.lastRecv = util.ms();
|
this.lastRecv = Date.now();
|
||||||
this.feedParser(chunk);
|
this.feedParser(chunk);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -418,7 +419,7 @@ Peer.prototype.accept = function accept(socket) {
|
|||||||
|
|
||||||
this.address = NetAddress.fromSocket(socket, this.network);
|
this.address = NetAddress.fromSocket(socket, this.network);
|
||||||
this.address.services = 0;
|
this.address.services = 0;
|
||||||
this.time = util.ms();
|
this.time = Date.now();
|
||||||
this.outbound = false;
|
this.outbound = false;
|
||||||
this.connected = true;
|
this.connected = true;
|
||||||
|
|
||||||
@ -530,7 +531,7 @@ Peer.prototype.initConnect = function initConnect() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
this.socket.once('connect', () => {
|
this.socket.once('connect', () => {
|
||||||
this.time = util.ms();
|
this.time = Date.now();
|
||||||
this.connected = true;
|
this.connected = true;
|
||||||
this.emit('connect');
|
this.emit('connect');
|
||||||
|
|
||||||
@ -981,8 +982,8 @@ Peer.prototype.sendPing = function sendPing() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.lastPing = util.ms();
|
this.lastPing = Date.now();
|
||||||
this.challenge = util.nonce();
|
this.challenge = common.nonce();
|
||||||
|
|
||||||
this.send(new packets.PingPacket(this.challenge));
|
this.send(new packets.PingPacket(this.challenge));
|
||||||
};
|
};
|
||||||
@ -1085,7 +1086,7 @@ Peer.prototype.write = function write(data) {
|
|||||||
if (this.destroyed)
|
if (this.destroyed)
|
||||||
throw new Error('Peer is destroyed (write).');
|
throw new Error('Peer is destroyed (write).');
|
||||||
|
|
||||||
this.lastSend = util.ms();
|
this.lastSend = Date.now();
|
||||||
|
|
||||||
if (this.socket.write(data) === false)
|
if (this.socket.write(data) === false)
|
||||||
this.needsDrain(data.length);
|
this.needsDrain(data.length);
|
||||||
@ -1176,7 +1177,7 @@ Peer.prototype.needsDrain = function needsDrain(size) {
|
|||||||
if (this.drainSize >= Peer.DRAIN_MAX) {
|
if (this.drainSize >= Peer.DRAIN_MAX) {
|
||||||
this.logger.warning(
|
this.logger.warning(
|
||||||
'Peer is not reading: %dmb buffered (%s).',
|
'Peer is not reading: %dmb buffered (%s).',
|
||||||
util.mb(this.drainSize),
|
this.drainSize / (1 << 20),
|
||||||
this.hostname());
|
this.hostname());
|
||||||
this.error('Peer stalled (drain).');
|
this.error('Peer stalled (drain).');
|
||||||
this.destroy();
|
this.destroy();
|
||||||
@ -1243,7 +1244,7 @@ Peer.prototype.fulfill = function fulfill(packet) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Peer.prototype.maybeTimeout = function maybeTimeout() {
|
Peer.prototype.maybeTimeout = function maybeTimeout() {
|
||||||
const now = util.ms();
|
const now = Date.now();
|
||||||
|
|
||||||
for (const [key, entry] of this.responseMap) {
|
for (const [key, entry] of this.responseMap) {
|
||||||
if (now > entry.timeout) {
|
if (now > entry.timeout) {
|
||||||
@ -1403,7 +1404,7 @@ Peer.prototype.error = function error(err) {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (typeof err === 'string') {
|
if (typeof err === 'string') {
|
||||||
const msg = util.fmt.apply(util, arguments);
|
const msg = format.apply(null, arguments);
|
||||||
err = new Error(msg);
|
err = new Error(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1748,7 +1749,7 @@ Peer.prototype.handlePing = async function handlePing(packet) {
|
|||||||
|
|
||||||
Peer.prototype.handlePong = async function handlePong(packet) {
|
Peer.prototype.handlePong = async function handlePong(packet) {
|
||||||
const nonce = packet.nonce;
|
const nonce = packet.nonce;
|
||||||
const now = util.ms();
|
const now = Date.now();
|
||||||
|
|
||||||
if (!this.challenge) {
|
if (!this.challenge) {
|
||||||
this.logger.debug('Peer sent an unsolicited pong (%s).', this.hostname());
|
this.logger.debug('Peer sent an unsolicited pong (%s).', this.hostname());
|
||||||
@ -2398,7 +2399,7 @@ PeerOptions.hasWitness = function hasWitness() {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
PeerOptions.createNonce = function createNonce(hostname) {
|
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) {
|
RequestEntry.prototype.setTimeout = function setTimeout(timeout) {
|
||||||
this.timeout = util.ms() + timeout;
|
this.timeout = Date.now() + timeout;
|
||||||
};
|
};
|
||||||
|
|
||||||
RequestEntry.prototype.reject = function reject(err) {
|
RequestEntry.prototype.reject = function reject(err) {
|
||||||
|
|||||||
@ -813,7 +813,7 @@ Pool.prototype.sendSync = async function sendSync(peer) {
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
peer.syncing = true;
|
peer.syncing = true;
|
||||||
peer.blockTime = util.ms();
|
peer.blockTime = Date.now();
|
||||||
|
|
||||||
let locator;
|
let locator;
|
||||||
try {
|
try {
|
||||||
@ -847,7 +847,7 @@ Pool.prototype.sendLocator = function sendLocator(locator, peer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
peer.syncing = true;
|
peer.syncing = true;
|
||||||
peer.blockTime = util.ms();
|
peer.blockTime = Date.now();
|
||||||
|
|
||||||
if (this.checkpoints) {
|
if (this.checkpoints) {
|
||||||
peer.sendGetHeaders(locator, this.headerTip.hash);
|
peer.sendGetHeaders(locator, this.headerTip.hash);
|
||||||
@ -2136,7 +2136,7 @@ Pool.prototype._handleHeaders = async function _handleHeaders(peer, packet) {
|
|||||||
|
|
||||||
// If we received a valid header
|
// If we received a valid header
|
||||||
// chain, consider this a "block".
|
// chain, consider this a "block".
|
||||||
peer.blockTime = util.ms();
|
peer.blockTime = Date.now();
|
||||||
|
|
||||||
// Request the blocks we just added.
|
// Request the blocks we just added.
|
||||||
if (checkpoint) {
|
if (checkpoint) {
|
||||||
@ -2226,7 +2226,7 @@ Pool.prototype._addBlock = async function _addBlock(peer, block, flags) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
peer.blockTime = util.ms();
|
peer.blockTime = Date.now();
|
||||||
|
|
||||||
let entry;
|
let entry;
|
||||||
try {
|
try {
|
||||||
@ -2689,7 +2689,7 @@ Pool.prototype._handleMerkleBlock = async function _handleMerkleBlock(peer, pack
|
|||||||
}
|
}
|
||||||
|
|
||||||
peer.merkleBlock = block;
|
peer.merkleBlock = block;
|
||||||
peer.merkleTime = util.ms();
|
peer.merkleTime = Date.now();
|
||||||
peer.merkleMatches = tree.matches.length;
|
peer.merkleMatches = tree.matches.length;
|
||||||
peer.merkleMap = new Set();
|
peer.merkleMap = new Set();
|
||||||
};
|
};
|
||||||
@ -2772,7 +2772,7 @@ Pool.prototype.handleCmpctBlock = async function handleCmpctBlock(peer, packet)
|
|||||||
peer.destroy();
|
peer.destroy();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
peer.blockMap.set(hash, util.ms());
|
peer.blockMap.set(hash, Date.now());
|
||||||
assert(!this.blockMap.has(hash));
|
assert(!this.blockMap.has(hash));
|
||||||
this.blockMap.add(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));
|
assert(!peer.compactBlocks.has(hash));
|
||||||
peer.compactBlocks.set(hash, block);
|
peer.compactBlocks.set(hash, block);
|
||||||
@ -3348,7 +3348,7 @@ Pool.prototype.getBlock = function getBlock(peer, hashes) {
|
|||||||
if (peer.destroyed)
|
if (peer.destroyed)
|
||||||
throw new Error('Peer is destroyed (getdata).');
|
throw new Error('Peer is destroyed (getdata).');
|
||||||
|
|
||||||
let now = util.ms();
|
let now = Date.now();
|
||||||
const items = [];
|
const items = [];
|
||||||
|
|
||||||
for (const hash of hashes) {
|
for (const hash of hashes) {
|
||||||
@ -3392,7 +3392,7 @@ Pool.prototype.getTX = function getTX(peer, hashes) {
|
|||||||
if (peer.destroyed)
|
if (peer.destroyed)
|
||||||
throw new Error('Peer is destroyed (getdata).');
|
throw new Error('Peer is destroyed (getdata).');
|
||||||
|
|
||||||
let now = util.ms();
|
let now = Date.now();
|
||||||
|
|
||||||
const items = [];
|
const items = [];
|
||||||
|
|
||||||
@ -3729,7 +3729,7 @@ PoolOptions.prototype.fromOptions = function fromOptions(options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (options.port != null) {
|
if (options.port != null) {
|
||||||
assert(util.isU16(options.port));
|
assert((options.port & 0xffff) === options.port);
|
||||||
this.port = options.port;
|
this.port = options.port;
|
||||||
this.publicPort = options.port;
|
this.publicPort = options.port;
|
||||||
}
|
}
|
||||||
@ -3740,7 +3740,7 @@ PoolOptions.prototype.fromOptions = function fromOptions(options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (options.publicPort != null) {
|
if (options.publicPort != null) {
|
||||||
assert(util.isU16(options.publicPort));
|
assert((options.publicPort & 0xff) === options.publicPort);
|
||||||
this.publicPort = options.publicPort;
|
this.publicPort = options.publicPort;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3901,12 +3901,12 @@ PoolOptions.prototype.fromOptions = function fromOptions(options) {
|
|||||||
this.listen = false;
|
this.listen = false;
|
||||||
|
|
||||||
if (options.services != null) {
|
if (options.services != null) {
|
||||||
assert(util.isU32(options.services));
|
assert((options.services >>> 0) === options.services);
|
||||||
this.services = options.services;
|
this.services = options.services;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.requiredServices != null) {
|
if (options.requiredServices != null) {
|
||||||
assert(util.isU32(options.requiredServices));
|
assert((options.requiredServices >>> 0) === options.requiredServices);
|
||||||
this.requiredServices = options.requiredServices;
|
this.requiredServices = options.requiredServices;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4347,7 +4347,7 @@ function NonceList() {
|
|||||||
|
|
||||||
NonceList.prototype.alloc = function alloc(hostname) {
|
NonceList.prototype.alloc = function alloc(hostname) {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
const nonce = util.nonce();
|
const nonce = common.nonce();
|
||||||
const key = nonce.toString('hex');
|
const key = nonce.toString('hex');
|
||||||
|
|
||||||
if (this.map.has(key))
|
if (this.map.has(key))
|
||||||
|
|||||||
@ -9,7 +9,6 @@
|
|||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
const EventEmitter = require('events');
|
const EventEmitter = require('events');
|
||||||
const bsock = require('bsock');
|
const bsock = require('bsock');
|
||||||
const util = require('../utils/util');
|
|
||||||
const digest = require('bcrypto/lib/digest');
|
const digest = require('bcrypto/lib/digest');
|
||||||
const BufferWriter = require('../utils/writer');
|
const BufferWriter = require('../utils/writer');
|
||||||
|
|
||||||
@ -126,7 +125,7 @@ ProxySocket.prototype.connect = function connect(port, host) {
|
|||||||
|
|
||||||
const pow = bw.render();
|
const pow = bw.render();
|
||||||
|
|
||||||
util.log(
|
console.log(
|
||||||
'Solving proof of work to create socket (%d, %s) -- please wait.',
|
'Solving proof of work to create socket (%d, %s) -- please wait.',
|
||||||
port, host);
|
port, host);
|
||||||
|
|
||||||
@ -136,7 +135,7 @@ ProxySocket.prototype.connect = function connect(port, host) {
|
|||||||
pow.writeUInt32LE(nonce, 0, true);
|
pow.writeUInt32LE(nonce, 0, true);
|
||||||
} while (digest.hash256(pow).compare(this.target) > 0);
|
} 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);
|
this.socket.fire('tcp connect', port, host, nonce);
|
||||||
|
|||||||
@ -13,7 +13,7 @@
|
|||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
const EventEmitter = require('events');
|
const EventEmitter = require('events');
|
||||||
const net = require('net');
|
const net = require('net');
|
||||||
const util = require('../utils/util');
|
const {format} = require('util');
|
||||||
const IP = require('../utils/ip');
|
const IP = require('../utils/ip');
|
||||||
const StaticWriter = require('../utils/staticwriter');
|
const StaticWriter = require('../utils/staticwriter');
|
||||||
const BufferReader = require('../utils/reader');
|
const BufferReader = require('../utils/reader');
|
||||||
@ -55,7 +55,16 @@ SOCKS.states = {
|
|||||||
RESOLVE_DONE: 7
|
RESOLVE_DONE: 7
|
||||||
};
|
};
|
||||||
|
|
||||||
SOCKS.statesByVal = util.reverse(SOCKS.states);
|
SOCKS.statesByVal = [
|
||||||
|
'INIT',
|
||||||
|
'CONNECT',
|
||||||
|
'HANDSHAKE',
|
||||||
|
'AUTH',
|
||||||
|
'PROXY',
|
||||||
|
'PROXY_DONE',
|
||||||
|
'RESOLVE',
|
||||||
|
'RESOLVE_DONE'
|
||||||
|
];
|
||||||
|
|
||||||
SOCKS.errors = [
|
SOCKS.errors = [
|
||||||
'',
|
'',
|
||||||
@ -80,7 +89,7 @@ SOCKS.prototype.error = function error(err) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const msg = util.fmt.apply(util, arguments);
|
const msg = format.apply(null, arguments);
|
||||||
this.emit('error', new Error(msg));
|
this.emit('error', new Error(msg));
|
||||||
this.destroy();
|
this.destroy();
|
||||||
};
|
};
|
||||||
|
|||||||
@ -10,7 +10,7 @@ const assert = require('assert');
|
|||||||
const Path = require('path');
|
const Path = require('path');
|
||||||
const os = require('os');
|
const os = require('os');
|
||||||
const fs = require('../utils/fs');
|
const fs = require('../utils/fs');
|
||||||
const util = require('../utils/util');
|
const {fromFloat} = require('../utils/fixed');
|
||||||
const HOME = os.homedir ? os.homedir() : '/';
|
const HOME = os.homedir ? os.homedir() : '/';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -416,7 +416,7 @@ Config.prototype.fixed = function fixed(key, exp, fallback) {
|
|||||||
return fallback;
|
return fallback;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return util.fromFloat(value, exp || 0);
|
return fromFloat(value, exp || 0);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
throw new Error(`${fmt(key)} must be a fixed number.`);
|
throw new Error(`${fmt(key)} must be a fixed number.`);
|
||||||
}
|
}
|
||||||
@ -955,7 +955,7 @@ Config.prototype.parseEnv = function parseEnv(env) {
|
|||||||
|
|
||||||
assert(typeof value === 'string');
|
assert(typeof value === 'string');
|
||||||
|
|
||||||
if (!util.startsWith(key, prefix))
|
if (key.indexOf(prefix) === 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
key = key.substring(prefix.length);
|
key = key.substring(prefix.length);
|
||||||
|
|||||||
@ -7,11 +7,26 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
|
const {format, inspect} = require('util');
|
||||||
const fs = require('../utils/fs');
|
const fs = require('../utils/fs');
|
||||||
const util = require('../utils/util');
|
const util = require('../utils/util');
|
||||||
const co = require('../utils/co');
|
const co = require('../utils/co');
|
||||||
const Lock = require('../utils/lock');
|
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.
|
* Basic stdout and file logger.
|
||||||
* @alias module:node.Logger
|
* @alias module:node.Logger
|
||||||
@ -382,6 +397,24 @@ Logger.prototype.setLevel = function setLevel(name) {
|
|||||||
this.level = level;
|
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.
|
* Output a log to the `error` log level.
|
||||||
* @param {String|Object|Error} err
|
* @param {String|Object|Error} err
|
||||||
@ -545,7 +578,7 @@ Logger.prototype.writeConsole = function writeConsole(level, module, args) {
|
|||||||
: console.log(msg, args[0]);
|
: console.log(msg, args[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
msg += util.format(args, false);
|
msg += this.fmt(args, false);
|
||||||
|
|
||||||
if (level === Logger.levels.ERROR) {
|
if (level === Logger.levels.ERROR) {
|
||||||
console.error(msg);
|
console.error(msg);
|
||||||
@ -570,7 +603,7 @@ Logger.prototype.writeConsole = function writeConsole(level, module, args) {
|
|||||||
if (module)
|
if (module)
|
||||||
msg += `(${module}) `;
|
msg += `(${module}) `;
|
||||||
|
|
||||||
msg += util.format(args, this.colors);
|
msg += this.fmt(args, this.colors);
|
||||||
msg += '\n';
|
msg += '\n';
|
||||||
|
|
||||||
return level === Logger.levels.ERROR
|
return level === Logger.levels.ERROR
|
||||||
@ -601,7 +634,7 @@ Logger.prototype.writeStream = function writeStream(level, module, args) {
|
|||||||
if (module)
|
if (module)
|
||||||
msg += `(${module}) `;
|
msg += `(${module}) `;
|
||||||
|
|
||||||
msg += util.format(args, false);
|
msg += this.fmt(args, false);
|
||||||
msg += '\n';
|
msg += '\n';
|
||||||
|
|
||||||
this.stream.write(msg);
|
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.
|
* Log the current memory usage.
|
||||||
* @param {String|null} module
|
* @param {String|null} module
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Logger.prototype.memory = function memory(module) {
|
Logger.prototype.memory = function memory(module) {
|
||||||
const mem = util.memoryUsage();
|
const mem = this.memoryUsage();
|
||||||
|
|
||||||
this.log(Logger.levels.DEBUG, module, [
|
this.log(Logger.levels.DEBUG, module, [
|
||||||
'Memory: rss=%dmb, js-heap=%d/%dmb native-heap=%dmb',
|
'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);
|
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.
|
* Log the current memory usage.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -57,12 +57,12 @@ function AbstractBlock() {
|
|||||||
|
|
||||||
AbstractBlock.prototype.parseOptions = function parseOptions(options) {
|
AbstractBlock.prototype.parseOptions = function parseOptions(options) {
|
||||||
assert(options, 'Block data is required.');
|
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.prevBlock === 'string');
|
||||||
assert(typeof options.merkleRoot === 'string');
|
assert(typeof options.merkleRoot === 'string');
|
||||||
assert(util.isU32(options.time));
|
assert((options.time >>> 0) === options.time);
|
||||||
assert(util.isU32(options.bits));
|
assert((options.bits >>> 0) === options.bits);
|
||||||
assert(util.isU32(options.nonce));
|
assert((options.nonce >>> 0) === options.nonce);
|
||||||
|
|
||||||
this.version = options.version;
|
this.version = options.version;
|
||||||
this.prevBlock = options.prevBlock;
|
this.prevBlock = options.prevBlock;
|
||||||
@ -85,12 +85,12 @@ AbstractBlock.prototype.parseOptions = function parseOptions(options) {
|
|||||||
|
|
||||||
AbstractBlock.prototype.parseJSON = function parseJSON(json) {
|
AbstractBlock.prototype.parseJSON = function parseJSON(json) {
|
||||||
assert(json, 'Block data is required.');
|
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.prevBlock === 'string');
|
||||||
assert(typeof json.merkleRoot === 'string');
|
assert(typeof json.merkleRoot === 'string');
|
||||||
assert(util.isU32(json.time));
|
assert((json.time >>> 0) === json.time);
|
||||||
assert(util.isU32(json.bits));
|
assert((json.bits >>> 0) === json.bits);
|
||||||
assert(util.isU32(json.nonce));
|
assert((json.nonce >>> 0) === json.nonce);
|
||||||
|
|
||||||
this.version = json.version;
|
this.version = json.version;
|
||||||
this.prevBlock = util.revHex(json.prevBlock);
|
this.prevBlock = util.revHex(json.prevBlock);
|
||||||
|
|||||||
@ -10,7 +10,6 @@
|
|||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
const Network = require('../protocol/network');
|
const Network = require('../protocol/network');
|
||||||
const encoding = require('../utils/encoding');
|
const encoding = require('../utils/encoding');
|
||||||
const util = require('../utils/util');
|
|
||||||
const digest = require('bcrypto/lib/digest');
|
const digest = require('bcrypto/lib/digest');
|
||||||
const BufferReader = require('../utils/reader');
|
const BufferReader = require('../utils/reader');
|
||||||
const StaticWriter = require('../utils/staticwriter');
|
const StaticWriter = require('../utils/staticwriter');
|
||||||
@ -55,7 +54,13 @@ Address.types = {
|
|||||||
* @const {RevMap}
|
* @const {RevMap}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Address.typesByVal = util.reverse(Address.types);
|
Address.typesByVal = [
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
'PUBKEYHASH',
|
||||||
|
'SCRIPTHASH',
|
||||||
|
'WITNESS'
|
||||||
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from options object.
|
* Inject properties from options object.
|
||||||
@ -581,8 +586,8 @@ Address.prototype.fromHash = function fromHash(hash, type, version) {
|
|||||||
version = -1;
|
version = -1;
|
||||||
|
|
||||||
assert(Buffer.isBuffer(hash));
|
assert(Buffer.isBuffer(hash));
|
||||||
assert(util.isU8(type));
|
assert((type >>> 0) === type);
|
||||||
assert(util.isI8(version));
|
assert((version | 0) === version);
|
||||||
|
|
||||||
assert(type >= Address.types.PUBKEYHASH && type <= Address.types.WITNESS,
|
assert(type >= Address.types.PUBKEYHASH && type <= Address.types.WITNESS,
|
||||||
'Not a valid address type.');
|
'Not a valid address type.');
|
||||||
|
|||||||
@ -539,7 +539,7 @@ Block.prototype.format = function format(view, height) {
|
|||||||
size: this.getSize(),
|
size: this.getSize(),
|
||||||
virtualSize: this.getVirtualSize(),
|
virtualSize: this.getVirtualSize(),
|
||||||
date: util.date(this.time),
|
date: util.date(this.time),
|
||||||
version: util.hex32(this.version),
|
version: this.version.toString(16),
|
||||||
prevBlock: util.revHex(this.prevBlock),
|
prevBlock: util.revHex(this.prevBlock),
|
||||||
merkleRoot: util.revHex(this.merkleRoot),
|
merkleRoot: util.revHex(this.merkleRoot),
|
||||||
commitmentHash: commitmentHash
|
commitmentHash: commitmentHash
|
||||||
|
|||||||
@ -61,13 +61,15 @@ Coin.prototype.fromOptions = function fromOptions(options) {
|
|||||||
assert(options, 'Coin data is required.');
|
assert(options, 'Coin data is required.');
|
||||||
|
|
||||||
if (options.version != null) {
|
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;
|
this.version = options.version;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.height != null) {
|
if (options.height != null) {
|
||||||
if (options.height !== -1) {
|
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;
|
this.height = options.height;
|
||||||
} else {
|
} else {
|
||||||
this.height = -1;
|
this.height = -1;
|
||||||
@ -75,7 +77,8 @@ Coin.prototype.fromOptions = function fromOptions(options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (options.value != null) {
|
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;
|
this.value = options.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,7 +97,7 @@ Coin.prototype.fromOptions = function fromOptions(options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (options.index != null) {
|
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;
|
this.index = options.index;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -262,10 +265,11 @@ Coin.prototype.getJSON = function getJSON(network, minimal) {
|
|||||||
|
|
||||||
Coin.prototype.fromJSON = function fromJSON(json) {
|
Coin.prototype.fromJSON = function fromJSON(json) {
|
||||||
assert(json, 'Coin data required.');
|
assert(json, 'Coin data required.');
|
||||||
assert(util.isU32(json.version), 'Version must be a uint32.');
|
assert((json.version >>> 0) === json.version, 'Version must be a uint32.');
|
||||||
assert(json.height === -1 || util.isU32(json.height),
|
assert(json.height === -1 || (json.height >>> 0) === json.height,
|
||||||
'Height must be a uint32.');
|
'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.');
|
assert(typeof json.coinbase === 'boolean', 'Coinbase must be a boolean.');
|
||||||
|
|
||||||
this.version = json.version;
|
this.version = json.version;
|
||||||
@ -277,7 +281,7 @@ Coin.prototype.fromJSON = function fromJSON(json) {
|
|||||||
if (json.hash != null) {
|
if (json.hash != null) {
|
||||||
assert(typeof json.hash === 'string', 'Hash must be a string.');
|
assert(typeof json.hash === 'string', 'Hash must be a string.');
|
||||||
assert(json.hash.length === 64, '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.hash = util.revHex(json.hash);
|
||||||
this.index = json.index;
|
this.index = json.index;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -250,7 +250,7 @@ Headers.prototype.format = function format(view, height) {
|
|||||||
hash: this.rhash(),
|
hash: this.rhash(),
|
||||||
height: height != null ? height : -1,
|
height: height != null ? height : -1,
|
||||||
date: util.date(this.time),
|
date: util.date(this.time),
|
||||||
version: util.hex32(this.version),
|
version: this.version.toString(16),
|
||||||
prevBlock: util.revHex(this.prevBlock),
|
prevBlock: util.revHex(this.prevBlock),
|
||||||
merkleRoot: util.revHex(this.merkleRoot),
|
merkleRoot: util.revHex(this.merkleRoot),
|
||||||
time: this.time,
|
time: this.time,
|
||||||
|
|||||||
@ -8,7 +8,6 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
const util = require('../utils/util');
|
|
||||||
const Network = require('../protocol/network');
|
const Network = require('../protocol/network');
|
||||||
const Script = require('../script/script');
|
const Script = require('../script/script');
|
||||||
const Witness = require('../script/witness');
|
const Witness = require('../script/witness');
|
||||||
@ -55,7 +54,8 @@ Input.prototype.fromOptions = function fromOptions(options) {
|
|||||||
this.script.fromOptions(options.script);
|
this.script.fromOptions(options.script);
|
||||||
|
|
||||||
if (options.sequence != null) {
|
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;
|
this.sequence = options.sequence;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -333,7 +333,7 @@ Input.prototype.getJSON = function getJSON(network, coin) {
|
|||||||
|
|
||||||
Input.prototype.fromJSON = function fromJSON(json) {
|
Input.prototype.fromJSON = function fromJSON(json) {
|
||||||
assert(json, 'Input data is required.');
|
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.prevout.fromJSON(json.prevout);
|
||||||
this.script.fromJSON(json.script);
|
this.script.fromJSON(json.script);
|
||||||
this.witness.fromJSON(json.witness);
|
this.witness.fromJSON(json.witness);
|
||||||
|
|||||||
@ -40,10 +40,10 @@ InvItem.types = {
|
|||||||
TX: 1,
|
TX: 1,
|
||||||
BLOCK: 2,
|
BLOCK: 2,
|
||||||
FILTERED_BLOCK: 3,
|
FILTERED_BLOCK: 3,
|
||||||
|
CMPCT_BLOCK: 4,
|
||||||
WITNESS_TX: 1 | (1 << 30),
|
WITNESS_TX: 1 | (1 << 30),
|
||||||
WITNESS_BLOCK: 2 | (1 << 30),
|
WITNESS_BLOCK: 2 | (1 << 30),
|
||||||
WITNESS_FILTERED_BLOCK: 3 | (1 << 30),
|
WITNESS_FILTERED_BLOCK: 3 | (1 << 30)
|
||||||
CMPCT_BLOCK: 4
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -51,7 +51,16 @@ InvItem.types = {
|
|||||||
* @const {RevMap}
|
* @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.
|
* Witness bit for inv types.
|
||||||
|
|||||||
@ -57,7 +57,7 @@ MerkleBlock.prototype.fromOptions = function fromOptions(options) {
|
|||||||
assert(options, 'MerkleBlock data is required.');
|
assert(options, 'MerkleBlock data is required.');
|
||||||
assert(Array.isArray(options.hashes));
|
assert(Array.isArray(options.hashes));
|
||||||
assert(Buffer.isBuffer(options.flags));
|
assert(Buffer.isBuffer(options.flags));
|
||||||
assert(util.isU32(options.totalTX));
|
assert((options.totalTX >>> 0) === options.totalTX);
|
||||||
|
|
||||||
if (options.hashes) {
|
if (options.hashes) {
|
||||||
for (let hash of options.hashes) {
|
for (let hash of options.hashes) {
|
||||||
@ -74,7 +74,7 @@ MerkleBlock.prototype.fromOptions = function fromOptions(options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (options.totalTX != null) {
|
if (options.totalTX != null) {
|
||||||
assert(util.isU32(options.totalTX));
|
assert((options.totalTX >>> 0) === options.totalTX);
|
||||||
this.totalTX = options.totalTX;
|
this.totalTX = options.totalTX;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -302,7 +302,7 @@ MerkleBlock.prototype.format = function format(view, height) {
|
|||||||
hash: this.rhash(),
|
hash: this.rhash(),
|
||||||
height: height != null ? height : -1,
|
height: height != null ? height : -1,
|
||||||
date: util.date(this.time),
|
date: util.date(this.time),
|
||||||
version: util.hex32(this.version),
|
version: this.version.toString(16),
|
||||||
prevBlock: util.revHex(this.prevBlock),
|
prevBlock: util.revHex(this.prevBlock),
|
||||||
merkleRoot: util.revHex(this.merkleRoot),
|
merkleRoot: util.revHex(this.merkleRoot),
|
||||||
time: this.time,
|
time: this.time,
|
||||||
@ -468,7 +468,7 @@ MerkleBlock.prototype.fromJSON = function fromJSON(json) {
|
|||||||
assert(json, 'MerkleBlock data is required.');
|
assert(json, 'MerkleBlock data is required.');
|
||||||
assert(Array.isArray(json.hashes));
|
assert(Array.isArray(json.hashes));
|
||||||
assert(typeof json.flags === 'string');
|
assert(typeof json.flags === 'string');
|
||||||
assert(util.isU32(json.totalTX));
|
assert((json.totalTX >>> 0) === json.totalTX);
|
||||||
|
|
||||||
this.parseJSON(json);
|
this.parseJSON(json);
|
||||||
|
|
||||||
|
|||||||
@ -8,7 +8,6 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
const util = require('../utils/util');
|
|
||||||
const Script = require('../script/script');
|
const Script = require('../script/script');
|
||||||
const TX = require('./tx');
|
const TX = require('./tx');
|
||||||
const Input = require('./input');
|
const Input = require('./input');
|
||||||
@ -66,7 +65,8 @@ Object.setPrototypeOf(MTX.prototype, TX.prototype);
|
|||||||
|
|
||||||
MTX.prototype.fromOptions = function fromOptions(options) {
|
MTX.prototype.fromOptions = function fromOptions(options) {
|
||||||
if (options.version != null) {
|
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;
|
this.version = options.version;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,13 +83,14 @@ MTX.prototype.fromOptions = function fromOptions(options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (options.locktime != null) {
|
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;
|
this.locktime = options.locktime;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.changeIndex != null) {
|
if (options.changeIndex != null) {
|
||||||
if (options.changeIndex !== -1) {
|
if (options.changeIndex !== -1) {
|
||||||
assert(util.isU32(options.changeIndex),
|
assert((options.changeIndex >>> 0) === options.changeIndex,
|
||||||
'Change index must be a uint32.');
|
'Change index must be a uint32.');
|
||||||
this.changeIndex = options.changeIndex;
|
this.changeIndex = options.changeIndex;
|
||||||
} else {
|
} else {
|
||||||
@ -221,12 +222,10 @@ MTX.prototype.addTX = function addTX(tx, index, height) {
|
|||||||
MTX.prototype.addOutput = function addOutput(script, value) {
|
MTX.prototype.addOutput = function addOutput(script, value) {
|
||||||
let output;
|
let output;
|
||||||
|
|
||||||
if (value != null) {
|
if (value != null)
|
||||||
assert(util.isU64(value), 'Value must be a uint64.');
|
|
||||||
output = Output.fromScript(script, value);
|
output = Output.fromScript(script, value);
|
||||||
} else {
|
else
|
||||||
output = Output.fromOptions(script);
|
output = Output.fromOptions(script);
|
||||||
}
|
|
||||||
|
|
||||||
this.outputs.push(output);
|
this.outputs.push(output);
|
||||||
|
|
||||||
@ -1378,8 +1377,8 @@ MTX.prototype.sortMembers = function sortMembers() {
|
|||||||
MTX.prototype.avoidFeeSniping = function avoidFeeSniping(height) {
|
MTX.prototype.avoidFeeSniping = function avoidFeeSniping(height) {
|
||||||
assert(typeof height === 'number', 'Must pass in height.');
|
assert(typeof height === 'number', 'Must pass in height.');
|
||||||
|
|
||||||
if (util.random(0, 10) === 0) {
|
if ((Math.random() * 10 | 0) === 0) {
|
||||||
height -= util.random(0, 100);
|
height -= Math.random() * 100 | 0;
|
||||||
|
|
||||||
if (height < 0)
|
if (height < 0)
|
||||||
height = 0;
|
height = 0;
|
||||||
@ -1394,7 +1393,7 @@ MTX.prototype.avoidFeeSniping = function avoidFeeSniping(height) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
MTX.prototype.setLocktime = function setLocktime(locktime) {
|
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.');
|
assert(this.inputs.length > 0, 'Cannot set sequence with no inputs.');
|
||||||
|
|
||||||
for (const input of this.inputs) {
|
for (const input of this.inputs) {
|
||||||
@ -1416,7 +1415,7 @@ MTX.prototype.setSequence = function setSequence(index, locktime, seconds) {
|
|||||||
const input = this.inputs[index];
|
const input = this.inputs[index];
|
||||||
|
|
||||||
assert(input, 'Input does not exist.');
|
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;
|
this.version = 2;
|
||||||
|
|
||||||
@ -1619,7 +1618,7 @@ CoinSelector.prototype.fromOptions = function fromOptions(options) {
|
|||||||
|
|
||||||
if (options.subtractFee != null) {
|
if (options.subtractFee != null) {
|
||||||
if (typeof options.subtractFee === 'number') {
|
if (typeof options.subtractFee === 'number') {
|
||||||
assert(util.isInt(options.subtractFee));
|
assert(Number.isSafeInteger(options.subtractFee));
|
||||||
assert(options.subtractFee >= -1);
|
assert(options.subtractFee >= -1);
|
||||||
this.subtractIndex = options.subtractFee;
|
this.subtractIndex = options.subtractFee;
|
||||||
this.subtractFee = this.subtractIndex !== -1;
|
this.subtractFee = this.subtractIndex !== -1;
|
||||||
@ -1630,43 +1629,44 @@ CoinSelector.prototype.fromOptions = function fromOptions(options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (options.subtractIndex != null) {
|
if (options.subtractIndex != null) {
|
||||||
assert(util.isInt(options.subtractIndex));
|
assert(Number.isSafeInteger(options.subtractIndex));
|
||||||
assert(options.subtractIndex >= -1);
|
assert(options.subtractIndex >= -1);
|
||||||
this.subtractIndex = options.subtractIndex;
|
this.subtractIndex = options.subtractIndex;
|
||||||
this.subtractFee = this.subtractIndex !== -1;
|
this.subtractFee = this.subtractIndex !== -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.height != null) {
|
if (options.height != null) {
|
||||||
assert(util.isInt(options.height));
|
assert(Number.isSafeInteger(options.height));
|
||||||
assert(options.height >= -1);
|
assert(options.height >= -1);
|
||||||
this.height = options.height;
|
this.height = options.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.confirmations != null) {
|
if (options.confirmations != null) {
|
||||||
assert(util.isInt(options.confirmations));
|
assert(Number.isSafeInteger(options.confirmations));
|
||||||
assert(options.confirmations >= -1);
|
assert(options.confirmations >= -1);
|
||||||
this.depth = options.confirmations;
|
this.depth = options.confirmations;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.depth != null) {
|
if (options.depth != null) {
|
||||||
assert(util.isInt(options.depth));
|
assert(Number.isSafeInteger(options.depth));
|
||||||
assert(options.depth >= -1);
|
assert(options.depth >= -1);
|
||||||
this.depth = options.depth;
|
this.depth = options.depth;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.hardFee != null) {
|
if (options.hardFee != null) {
|
||||||
assert(util.isInt(options.hardFee));
|
assert(Number.isSafeInteger(options.hardFee));
|
||||||
assert(options.hardFee >= -1);
|
assert(options.hardFee >= -1);
|
||||||
this.hardFee = options.hardFee;
|
this.hardFee = options.hardFee;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.rate != null) {
|
if (options.rate != null) {
|
||||||
assert(util.isU64(options.rate));
|
assert(Number.isSafeInteger(options.rate));
|
||||||
|
assert(options.rate >= 0);
|
||||||
this.rate = options.rate;
|
this.rate = options.rate;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.maxFee != null) {
|
if (options.maxFee != null) {
|
||||||
assert(util.isInt(options.maxFee));
|
assert(Number.isSafeInteger(options.maxFee));
|
||||||
assert(options.maxFee >= -1);
|
assert(options.maxFee >= -1);
|
||||||
this.maxFee = options.maxFee;
|
this.maxFee = options.maxFee;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -439,9 +439,9 @@ NetAddress.prototype.toJSON = function toJSON() {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
NetAddress.prototype.fromJSON = function fromJSON(json) {
|
NetAddress.prototype.fromJSON = function fromJSON(json) {
|
||||||
assert(util.isU16(json.port));
|
assert((json.port & 0xffff) === json.port);
|
||||||
assert(util.isU32(json.services));
|
assert((json.services >>> 0) === json.services);
|
||||||
assert(util.isU32(json.time));
|
assert((json.time >>> 0) === json.time);
|
||||||
this.raw = IP.toBuffer(json.host);
|
this.raw = IP.toBuffer(json.host);
|
||||||
this.host = json.host;
|
this.host = json.host;
|
||||||
this.port = json.port;
|
this.port = json.port;
|
||||||
|
|||||||
@ -31,7 +31,7 @@ function Outpoint(hash, index) {
|
|||||||
|
|
||||||
if (hash != null) {
|
if (hash != null) {
|
||||||
assert(typeof hash === 'string', 'Hash must be a string.');
|
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.hash = hash;
|
||||||
this.index = index;
|
this.index = index;
|
||||||
}
|
}
|
||||||
@ -46,7 +46,7 @@ function Outpoint(hash, index) {
|
|||||||
Outpoint.prototype.fromOptions = function fromOptions(options) {
|
Outpoint.prototype.fromOptions = function fromOptions(options) {
|
||||||
assert(options, 'Outpoint data is required.');
|
assert(options, 'Outpoint data is required.');
|
||||||
assert(typeof options.hash === 'string', 'Hash must be a string.');
|
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.hash = options.hash;
|
||||||
this.index = options.index;
|
this.index = options.index;
|
||||||
return this;
|
return this;
|
||||||
@ -95,7 +95,7 @@ Outpoint.prototype.equals = function equals(prevout) {
|
|||||||
Outpoint.prototype.compare = function compare(prevout) {
|
Outpoint.prototype.compare = function compare(prevout) {
|
||||||
assert(Outpoint.isOutpoint(prevout));
|
assert(Outpoint.isOutpoint(prevout));
|
||||||
|
|
||||||
const cmp = util.strcmp(this.txid(), prevout.txid());
|
const cmp = strcmp(this.txid(), prevout.txid());
|
||||||
|
|
||||||
if (cmp !== 0)
|
if (cmp !== 0)
|
||||||
return cmp;
|
return cmp;
|
||||||
@ -245,7 +245,7 @@ Outpoint.fromRaw = function fromRaw(data) {
|
|||||||
Outpoint.prototype.fromJSON = function fromJSON(json) {
|
Outpoint.prototype.fromJSON = function fromJSON(json) {
|
||||||
assert(json, 'Outpoint data is required.');
|
assert(json, 'Outpoint data is required.');
|
||||||
assert(typeof json.hash === 'string', 'Hash must be a string.');
|
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.hash = util.revHex(json.hash);
|
||||||
this.index = json.index;
|
this.index = json.index;
|
||||||
return this;
|
return this;
|
||||||
@ -337,6 +337,29 @@ Outpoint.isOutpoint = function isOutpoint(obj) {
|
|||||||
return obj instanceof Outpoint;
|
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
|
* Expose
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -8,7 +8,6 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
const util = require('../utils/util');
|
|
||||||
const Amount = require('../btc/amount');
|
const Amount = require('../btc/amount');
|
||||||
const Network = require('../protocol/network');
|
const Network = require('../protocol/network');
|
||||||
const Address = require('../primitives/address');
|
const Address = require('../primitives/address');
|
||||||
@ -48,7 +47,8 @@ Output.prototype.fromOptions = function fromOptions(options) {
|
|||||||
assert(options, 'Output data is required.');
|
assert(options, 'Output data is required.');
|
||||||
|
|
||||||
if (options.value) {
|
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;
|
this.value = options.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,7 +87,7 @@ Output.prototype.fromScript = function fromScript(script, value) {
|
|||||||
script = Script.fromAddress(script);
|
script = Script.fromAddress(script);
|
||||||
|
|
||||||
assert(script instanceof Script, 'Script must be a 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.script = script;
|
||||||
this.value = value;
|
this.value = value;
|
||||||
@ -278,7 +278,8 @@ Output.prototype.isDust = function isDust(rate) {
|
|||||||
|
|
||||||
Output.prototype.fromJSON = function fromJSON(json) {
|
Output.prototype.fromJSON = function fromJSON(json) {
|
||||||
assert(json, 'Output data is required.');
|
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.value = json.value;
|
||||||
this.script.fromJSON(json.script);
|
this.script.fromJSON(json.script);
|
||||||
return this;
|
return this;
|
||||||
|
|||||||
@ -8,10 +8,10 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
const util = require('../utils/util');
|
|
||||||
const encoding = require('../utils/encoding');
|
|
||||||
const digest = require('bcrypto/lib/digest');
|
const digest = require('bcrypto/lib/digest');
|
||||||
const secp256k1 = require('bcrypto/lib/secp256k1');
|
const secp256k1 = require('bcrypto/lib/secp256k1');
|
||||||
|
const util = require('../utils/util');
|
||||||
|
const encoding = require('../utils/encoding');
|
||||||
const Amount = require('../btc/amount');
|
const Amount = require('../btc/amount');
|
||||||
const Network = require('../protocol/network');
|
const Network = require('../protocol/network');
|
||||||
const Script = require('../script/script');
|
const Script = require('../script/script');
|
||||||
@ -80,7 +80,8 @@ TX.prototype.fromOptions = function fromOptions(options) {
|
|||||||
assert(options, 'TX data is required.');
|
assert(options, 'TX data is required.');
|
||||||
|
|
||||||
if (options.version != null) {
|
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;
|
this.version = options.version;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,7 +98,8 @@ TX.prototype.fromOptions = function fromOptions(options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (options.locktime != null) {
|
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;
|
this.locktime = options.locktime;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2194,10 +2196,10 @@ TX.prototype.getJSON = function getJSON(network, view, entry, index) {
|
|||||||
|
|
||||||
TX.prototype.fromJSON = function fromJSON(json) {
|
TX.prototype.fromJSON = function fromJSON(json) {
|
||||||
assert(json, 'TX data is required.');
|
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.inputs), 'Inputs must be an array.');
|
||||||
assert(Array.isArray(json.outputs), 'Outputs 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;
|
this.version = json.version;
|
||||||
|
|
||||||
|
|||||||
@ -47,12 +47,12 @@ TXMeta.prototype.fromOptions = function fromOptions(options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (options.mtime != null) {
|
if (options.mtime != null) {
|
||||||
assert(util.isU32(options.mtime));
|
assert((options.mtime >>> 0) === options.mtime);
|
||||||
this.mtime = options.mtime;
|
this.mtime = options.mtime;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.height != null) {
|
if (options.height != null) {
|
||||||
assert(util.isInt(options.height));
|
assert(Number.isSafeInteger(options.height));
|
||||||
this.height = options.height;
|
this.height = options.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,12 +62,12 @@ TXMeta.prototype.fromOptions = function fromOptions(options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (options.time != null) {
|
if (options.time != null) {
|
||||||
assert(util.isU32(options.time));
|
assert((options.time >>> 0) === options.time);
|
||||||
this.time = options.time;
|
this.time = options.time;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.index != null) {
|
if (options.index != null) {
|
||||||
assert(util.isInt(options.index));
|
assert(Number.isSafeInteger(options.index));
|
||||||
this.index = options.index;
|
this.index = options.index;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,11 +174,11 @@ TXMeta.prototype.getJSON = function getJSON(network, view, chainHeight) {
|
|||||||
TXMeta.prototype.fromJSON = function fromJSON(json) {
|
TXMeta.prototype.fromJSON = function fromJSON(json) {
|
||||||
this.tx.fromJSON(json);
|
this.tx.fromJSON(json);
|
||||||
|
|
||||||
assert(util.isU32(json.mtime));
|
assert((json.mtime >>> 0) === json.mtime);
|
||||||
assert(util.isInt(json.height));
|
assert(Number.isSafeInteger(json.height));
|
||||||
assert(!json.block || typeof json.block === 'string');
|
assert(!json.block || typeof json.block === 'string');
|
||||||
assert(util.isU32(json.time));
|
assert((json.time >>> 0) === json.time);
|
||||||
assert(util.isInt(json.index));
|
assert(Number.isSafeInteger(json.index));
|
||||||
|
|
||||||
this.mtime = json.mtime;
|
this.mtime = json.mtime;
|
||||||
this.height = json.height;
|
this.height = json.height;
|
||||||
|
|||||||
@ -8,7 +8,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
const util = require('../utils/util');
|
const binary = require('../utils/binary');
|
||||||
const networks = require('./networks');
|
const networks = require('./networks');
|
||||||
const consensus = require('./consensus');
|
const consensus = require('./consensus');
|
||||||
const TimeData = require('./timedata');
|
const TimeData = require('./timedata');
|
||||||
@ -115,7 +115,7 @@ Network.prototype._init = function _init() {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Network.prototype.byBit = function byBit(bit) {
|
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)
|
if (index === -1)
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
const EventEmitter = require('events');
|
const EventEmitter = require('events');
|
||||||
const util = require('../utils/util');
|
const util = require('../utils/util');
|
||||||
|
const binary = require('../utils/binary');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An object which handles "adjusted time". This may not
|
* 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);
|
this.known.set(id, sample);
|
||||||
|
|
||||||
util.binaryInsert(this.samples, sample, compare);
|
binary.insert(this.samples, sample, compare);
|
||||||
|
|
||||||
this.emit('sample', sample, this.samples.length);
|
this.emit('sample', sample, this.samples.length);
|
||||||
|
|
||||||
@ -126,7 +127,7 @@ TimeData.prototype.local = function local(time) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
TimeData.prototype.ms = function ms() {
|
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 assert = require('assert');
|
||||||
const ScriptNum = require('./scriptnum');
|
const ScriptNum = require('./scriptnum');
|
||||||
const util = require('../utils/util');
|
|
||||||
const common = require('./common');
|
const common = require('./common');
|
||||||
const BufferReader = require('../utils/reader');
|
const BufferReader = require('../utils/reader');
|
||||||
const StaticWriter = require('../utils/staticwriter');
|
const StaticWriter = require('../utils/staticwriter');
|
||||||
@ -268,7 +267,7 @@ Opcode.prototype.toSymbol = function toSymbol() {
|
|||||||
const symbol = common.opcodesByVal[this.value];
|
const symbol = common.opcodesByVal[this.value];
|
||||||
|
|
||||||
if (!symbol)
|
if (!symbol)
|
||||||
return `0x${util.hex8(this.value)}`;
|
return `0x${hex8(this.value)}`;
|
||||||
|
|
||||||
return symbol;
|
return symbol;
|
||||||
};
|
};
|
||||||
@ -366,7 +365,7 @@ Opcode.prototype.toFormat = function toFormat() {
|
|||||||
|
|
||||||
// Direct push
|
// Direct push
|
||||||
if (!symbol) {
|
if (!symbol) {
|
||||||
const size = util.hex8(this.value);
|
const size = hex8(this.value);
|
||||||
return `0x${size} 0x${data}`;
|
return `0x${size} 0x${data}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -385,7 +384,7 @@ Opcode.prototype.toFormat = function toFormat() {
|
|||||||
return symbol;
|
return symbol;
|
||||||
|
|
||||||
// Unknown opcodes
|
// Unknown opcodes
|
||||||
const value = util.hex8(this.value);
|
const value = hex8(this.value);
|
||||||
|
|
||||||
return `0x${value}`;
|
return `0x${value}`;
|
||||||
};
|
};
|
||||||
@ -492,7 +491,7 @@ Opcode.fromString = function fromString(str, enc) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Opcode.fromSmall = function fromSmall(num) {
|
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);
|
return Opcode.fromOp(num === 0 ? 0 : num + 0x50);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -514,7 +513,7 @@ Opcode.fromNum = function fromNum(num) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Opcode.fromInt = function fromInt(num) {
|
Opcode.fromInt = function fromInt(num) {
|
||||||
assert(util.isInt(num));
|
assert(Number.isSafeInteger(num));
|
||||||
|
|
||||||
if (num === 0)
|
if (num === 0)
|
||||||
return Opcode.fromOp(opcodes.OP_0);
|
return Opcode.fromOp(opcodes.OP_0);
|
||||||
@ -551,10 +550,10 @@ Opcode.fromSymbol = function fromSymbol(name) {
|
|||||||
assert(typeof name === 'string');
|
assert(typeof name === 'string');
|
||||||
assert(name.length > 0);
|
assert(name.length > 0);
|
||||||
|
|
||||||
if (!util.isUpperCase(name))
|
if (name.charCodeAt(0) & 32)
|
||||||
name = name.toUpperCase();
|
name = name.toUpperCase();
|
||||||
|
|
||||||
if (!util.startsWith(name, 'OP_'))
|
if (!/^OP_/.test(name))
|
||||||
name = `OP_${name}`;
|
name = `OP_${name}`;
|
||||||
|
|
||||||
const op = common.opcodes[name];
|
const op = common.opcodes[name];
|
||||||
@ -562,12 +561,12 @@ Opcode.fromSymbol = function fromSymbol(name) {
|
|||||||
if (op != null)
|
if (op != null)
|
||||||
return Opcode.fromOp(op);
|
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.');
|
assert(name.length === 7, 'Unknown opcode.');
|
||||||
|
|
||||||
const value = parseInt(name.substring(5), 16);
|
const value = parseInt(name.substring(5), 16);
|
||||||
|
|
||||||
assert(util.isU8(value), 'Unknown opcode.');
|
assert((value & 0xff) === value, 'Unknown opcode.');
|
||||||
|
|
||||||
return Opcode.fromOp(value);
|
return Opcode.fromOp(value);
|
||||||
};
|
};
|
||||||
@ -668,6 +667,16 @@ Opcode.isOpcode = function isOpcode(obj) {
|
|||||||
return obj instanceof Opcode;
|
return obj instanceof Opcode;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Helpers
|
||||||
|
*/
|
||||||
|
|
||||||
|
function hex8(num) {
|
||||||
|
if (num <= 0x0f)
|
||||||
|
return '0' + num.toString(16);
|
||||||
|
return num.toString(16);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Fill Cache
|
* Fill Cache
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -8,7 +8,6 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
const util = require('../utils/util');
|
|
||||||
const common = require('./common');
|
const common = require('./common');
|
||||||
const scriptTypes = common.types;
|
const scriptTypes = common.types;
|
||||||
|
|
||||||
@ -29,7 +28,7 @@ function Program(version, data) {
|
|||||||
if (!(this instanceof Program))
|
if (!(this instanceof Program))
|
||||||
return new Program(version, data);
|
return new Program(version, data);
|
||||||
|
|
||||||
assert(util.isU8(version));
|
assert((version & 0xff) === version);
|
||||||
assert(version >= 0 && version <= 16);
|
assert(version >= 0 && version <= 16);
|
||||||
assert(Buffer.isBuffer(data));
|
assert(Buffer.isBuffer(data));
|
||||||
assert(data.length >= 2 && data.length <= 40);
|
assert(data.length >= 2 && data.length <= 40);
|
||||||
|
|||||||
@ -8,11 +8,11 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const assert = require('assert');
|
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 digest = require('bcrypto/lib/digest');
|
||||||
const merkle = require('bcrypto/lib/merkle');
|
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 BufferWriter = require('../utils/writer');
|
||||||
const BufferReader = require('../utils/reader');
|
const BufferReader = require('../utils/reader');
|
||||||
const StaticWriter = require('../utils/staticwriter');
|
const StaticWriter = require('../utils/staticwriter');
|
||||||
@ -23,7 +23,6 @@ const ScriptError = require('./scripterror');
|
|||||||
const ScriptNum = require('./scriptnum');
|
const ScriptNum = require('./scriptnum');
|
||||||
const common = require('./common');
|
const common = require('./common');
|
||||||
const encoding = require('../utils/encoding');
|
const encoding = require('../utils/encoding');
|
||||||
const secp256k1 = require('bcrypto/lib/secp256k1');
|
|
||||||
const Address = require('../primitives/address');
|
const Address = require('../primitives/address');
|
||||||
const opcodes = common.opcodes;
|
const opcodes = common.opcodes;
|
||||||
const scriptTypes = common.types;
|
const scriptTypes = common.types;
|
||||||
@ -1513,7 +1512,7 @@ Script.fromPubkeyhash = function fromPubkeyhash(hash) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Script.prototype.fromMultisig = function fromMultisig(m, n, keys) {
|
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(Array.isArray(keys));
|
||||||
assert(keys.length === n, '`n` keys are required for multisig.');
|
assert(keys.length === n, '`n` keys are required for multisig.');
|
||||||
assert(m >= 1 && m <= n);
|
assert(m >= 1 && m <= n);
|
||||||
@ -1614,7 +1613,7 @@ Script.fromNulldata = function fromNulldata(flags) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Script.prototype.fromProgram = function fromProgram(version, data) {
|
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);
|
assert(Buffer.isBuffer(data) && data.length >= 2 && data.length <= 40);
|
||||||
|
|
||||||
this.raw = Buffer.allocUnsafe(2 + data.length);
|
this.raw = Buffer.allocUnsafe(2 + data.length);
|
||||||
@ -3082,10 +3081,10 @@ Script.prototype.fromString = function fromString(code) {
|
|||||||
for (const item of items) {
|
for (const item of items) {
|
||||||
let symbol = item;
|
let symbol = item;
|
||||||
|
|
||||||
if (!util.isUpperCase(symbol))
|
if (symbol.charCodeAt(0) & 32)
|
||||||
symbol = symbol.toUpperCase();
|
symbol = symbol.toUpperCase();
|
||||||
|
|
||||||
if (!util.startsWith(symbol, 'OP_'))
|
if (!/^OP_/.test(symbol))
|
||||||
symbol = `OP_${symbol}`;
|
symbol = `OP_${symbol}`;
|
||||||
|
|
||||||
const value = opcodes[symbol];
|
const value = opcodes[symbol];
|
||||||
|
|||||||
@ -7,7 +7,6 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
const util = require('../utils/util');
|
|
||||||
const secp256k1 = require('bcrypto/lib/secp256k1');
|
const secp256k1 = require('bcrypto/lib/secp256k1');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -27,7 +26,7 @@ function SigCache(size) {
|
|||||||
if (size == null)
|
if (size == null)
|
||||||
size = 10000;
|
size = 10000;
|
||||||
|
|
||||||
assert(util.isU32(size));
|
assert((size >>> 0) === size);
|
||||||
|
|
||||||
this.size = size;
|
this.size = size;
|
||||||
this.keys = [];
|
this.keys = [];
|
||||||
@ -40,7 +39,7 @@ function SigCache(size) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
SigCache.prototype.resize = function resize(size) {
|
SigCache.prototype.resize = function resize(size) {
|
||||||
assert(util.isU32(size));
|
assert((size >>> 0) === size);
|
||||||
|
|
||||||
this.size = size;
|
this.size = size;
|
||||||
this.keys.length = 0;
|
this.keys.length = 0;
|
||||||
|
|||||||
@ -8,7 +8,6 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
const util = require('../utils/util');
|
|
||||||
const Script = require('./script');
|
const Script = require('./script');
|
||||||
const common = require('./common');
|
const common = require('./common');
|
||||||
const encoding = require('../utils/encoding');
|
const encoding = require('../utils/encoding');
|
||||||
|
|||||||
@ -150,3 +150,14 @@ exports.decode = function decode(str) {
|
|||||||
|
|
||||||
if (native)
|
if (native)
|
||||||
exports.decode = native.fromBase58;
|
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)
|
if (native)
|
||||||
decode = native.fromBech32;
|
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
|
* AddrResult
|
||||||
* @constructor
|
* @constructor
|
||||||
@ -339,3 +360,4 @@ exports.serialize = serialize;
|
|||||||
exports.convert = convert;
|
exports.convert = convert;
|
||||||
exports.encode = encode;
|
exports.encode = encode;
|
||||||
exports.decode = decode;
|
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.co = require('./co');
|
||||||
exports.encoding = require('./encoding');
|
exports.encoding = require('./encoding');
|
||||||
exports.enforce = require('./enforce');
|
exports.enforce = require('./enforce');
|
||||||
|
exports.fixed = require('./fixed');
|
||||||
exports.fs = require('./fs');
|
exports.fs = require('./fs');
|
||||||
exports.GCSFilter = require('./gcs');
|
exports.GCSFilter = require('./gcs');
|
||||||
exports.Heap = require('./heap');
|
exports.Heap = require('./heap');
|
||||||
|
|||||||
@ -8,7 +8,6 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
const nodeUtil = require('util');
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @exports utils/util
|
* @exports utils/util
|
||||||
@ -16,367 +15,6 @@ const nodeUtil = require('util');
|
|||||||
|
|
||||||
const util = exports;
|
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).
|
* Return hrtime (shim for browser).
|
||||||
* @param {Array} time
|
* @param {Array} time
|
||||||
@ -385,7 +23,7 @@ util.error = function error(...args) {
|
|||||||
|
|
||||||
util.hrtime = function hrtime(time) {
|
util.hrtime = function hrtime(time) {
|
||||||
if (!process.hrtime) {
|
if (!process.hrtime) {
|
||||||
const now = util.ms();
|
const now = Date.now();
|
||||||
|
|
||||||
if (time) {
|
if (time) {
|
||||||
const [hi, lo] = time;
|
const [hi, lo] = time;
|
||||||
@ -418,16 +56,7 @@ util.hrtime = function hrtime(time) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
util.now = function now() {
|
util.now = function now() {
|
||||||
return Math.floor(util.ms() / 1000);
|
return Math.floor(Date.now() / 1000);
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get current time in unix time (milliseconds).
|
|
||||||
* @returns {Number}
|
|
||||||
*/
|
|
||||||
|
|
||||||
util.ms = function ms() {
|
|
||||||
return Date.now();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -456,208 +85,6 @@ util.time = function time(date) {
|
|||||||
return new Date(date) / 1000 | 0;
|
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
|
* Reverse a hex-string (used because of
|
||||||
* bitcoind's affinity for uint256le).
|
* bitcoind's affinity for uint256le).
|
||||||
@ -677,346 +104,3 @@ util.revHex = function revHex(data) {
|
|||||||
|
|
||||||
return out;
|
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';
|
'use strict';
|
||||||
|
|
||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
const util = require('../utils/util');
|
const {fromFloat} = require('../utils/fixed');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validator
|
* Validator
|
||||||
@ -286,7 +286,7 @@ Validator.prototype.fixed = function fixed(key, exp, fallback) {
|
|||||||
return fallback;
|
return fallback;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return util.fromFloat(value, exp || 0);
|
return fromFloat(value, exp || 0);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
throw new ValidationError(key, 'fixed number');
|
throw new ValidationError(key, 'fixed number');
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,8 +6,8 @@
|
|||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const util = require('../utils/util');
|
|
||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
|
const binary = require('../utils/binary');
|
||||||
const BufferReader = require('../utils/reader');
|
const BufferReader = require('../utils/reader');
|
||||||
const StaticWriter = require('../utils/staticwriter');
|
const StaticWriter = require('../utils/staticwriter');
|
||||||
const encoding = require('../utils/encoding');
|
const encoding = require('../utils/encoding');
|
||||||
@ -99,10 +99,11 @@ Account.typesByVal = {
|
|||||||
|
|
||||||
Account.prototype.fromOptions = function fromOptions(options) {
|
Account.prototype.fromOptions = function fromOptions(options) {
|
||||||
assert(options, 'Options are required.');
|
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(common.isName(options.id), 'Bad Wallet ID.');
|
||||||
assert(HD.isHD(options.accountKey), 'Account key is required.');
|
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.wid = options.wid;
|
||||||
this.id = options.id;
|
this.id = options.id;
|
||||||
@ -139,37 +140,37 @@ Account.prototype.fromOptions = function fromOptions(options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (options.m != null) {
|
if (options.m != null) {
|
||||||
assert(util.isU8(options.m));
|
assert((options.m & 0xff) === options.m);
|
||||||
this.m = options.m;
|
this.m = options.m;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.n != null) {
|
if (options.n != null) {
|
||||||
assert(util.isU8(options.n));
|
assert((options.n & 0xff) === options.n);
|
||||||
this.n = options.n;
|
this.n = options.n;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.accountIndex != null) {
|
if (options.accountIndex != null) {
|
||||||
assert(util.isU32(options.accountIndex));
|
assert((options.accountIndex >>> 0) === options.accountIndex);
|
||||||
this.accountIndex = options.accountIndex;
|
this.accountIndex = options.accountIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.receiveDepth != null) {
|
if (options.receiveDepth != null) {
|
||||||
assert(util.isU32(options.receiveDepth));
|
assert((options.receiveDepth >>> 0) === options.receiveDepth);
|
||||||
this.receiveDepth = options.receiveDepth;
|
this.receiveDepth = options.receiveDepth;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.changeDepth != null) {
|
if (options.changeDepth != null) {
|
||||||
assert(util.isU32(options.changeDepth));
|
assert((options.changeDepth >>> 0) === options.changeDepth);
|
||||||
this.changeDepth = options.changeDepth;
|
this.changeDepth = options.changeDepth;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.nestedDepth != null) {
|
if (options.nestedDepth != null) {
|
||||||
assert(util.isU32(options.nestedDepth));
|
assert((options.nestedDepth >>> 0) === options.nestedDepth);
|
||||||
this.nestedDepth = options.nestedDepth;
|
this.nestedDepth = options.nestedDepth;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.lookahead != null) {
|
if (options.lookahead != null) {
|
||||||
assert(util.isU32(options.lookahead));
|
assert((options.lookahead >>> 0) === options.lookahead);
|
||||||
assert(options.lookahead >= 0);
|
assert(options.lookahead >= 0);
|
||||||
assert(options.lookahead <= Account.MAX_LOOKAHEAD);
|
assert(options.lookahead <= Account.MAX_LOOKAHEAD);
|
||||||
this.lookahead = options.lookahead;
|
this.lookahead = options.lookahead;
|
||||||
@ -262,13 +263,13 @@ Account.prototype.pushKey = function pushKey(key) {
|
|||||||
if (key.equals(this.accountKey))
|
if (key.equals(this.accountKey))
|
||||||
throw new Error('Cannot add own key.');
|
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)
|
if (index === -1)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (this.keys.length > this.n - 1) {
|
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.');
|
throw new Error('Cannot add more keys.');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -299,7 +300,7 @@ Account.prototype.spliceKey = function spliceKey(key) {
|
|||||||
if (this.keys.length === this.n - 1)
|
if (this.keys.length === this.n - 1)
|
||||||
throw new Error('Cannot remove key.');
|
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';
|
'use strict';
|
||||||
|
|
||||||
|
const assert = require('assert');
|
||||||
const {NodeClient} = require('bclient');
|
const {NodeClient} = require('bclient');
|
||||||
const TX = require('../primitives/tx');
|
const TX = require('../primitives/tx');
|
||||||
const digest = require('bcrypto/lib/digest');
|
const digest = require('bcrypto/lib/digest');
|
||||||
|
|||||||
@ -10,7 +10,6 @@
|
|||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const {Server} = require('bweb');
|
const {Server} = require('bweb');
|
||||||
const util = require('../utils/util');
|
|
||||||
const base58 = require('../utils/base58');
|
const base58 = require('../utils/base58');
|
||||||
const MTX = require('../primitives/mtx');
|
const MTX = require('../primitives/mtx');
|
||||||
const Outpoint = require('../primitives/outpoint');
|
const Outpoint = require('../primitives/outpoint');
|
||||||
@ -132,12 +131,17 @@ class HTTPServer extends Server {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!token) {
|
||||||
|
res.json(403);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let wallet;
|
let wallet;
|
||||||
try {
|
try {
|
||||||
wallet = await this.wdb.auth(id, token);
|
wallet = await this.wdb.auth(id, token);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this.logger.info('Auth failure for %s: %s.', id, err.message);
|
this.logger.info('Auth failure for %s: %s.', id, err.message);
|
||||||
res.error(403, err);
|
res.json(403);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1007,8 +1011,6 @@ class HTTPOptions {
|
|||||||
'API key must be a string.');
|
'API key must be a string.');
|
||||||
assert(options.apiKey.length <= 255,
|
assert(options.apiKey.length <= 255,
|
||||||
'API key must be under 255 bytes.');
|
'API key must be under 255 bytes.');
|
||||||
assert(util.isAscii(options.apiKey),
|
|
||||||
'API key must be ASCII.');
|
|
||||||
this.apiKey = options.apiKey;
|
this.apiKey = options.apiKey;
|
||||||
this.apiHash = digest.hash256(Buffer.from(this.apiKey, 'ascii'));
|
this.apiHash = digest.hash256(Buffer.from(this.apiKey, 'ascii'));
|
||||||
}
|
}
|
||||||
@ -1036,7 +1038,8 @@ class HTTPOptions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (options.port != null) {
|
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;
|
this.port = options.port;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -7,8 +7,6 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
const util = require('../utils/util');
|
|
||||||
const pad32 = util.pad32;
|
|
||||||
const layouts = exports;
|
const layouts = exports;
|
||||||
|
|
||||||
layouts.walletdb = {
|
layouts.walletdb = {
|
||||||
@ -23,7 +21,7 @@ layouts.walletdb = {
|
|||||||
},
|
},
|
||||||
P: function P(wid, hash) {
|
P: function P(wid, hash) {
|
||||||
assert(typeof hash === 'string');
|
assert(typeof hash === 'string');
|
||||||
return 'p' + pad32(wid) + hash;
|
return 'p' + hex32(wid) + hash;
|
||||||
},
|
},
|
||||||
Pp: function Pp(key) {
|
Pp: function Pp(key) {
|
||||||
assert(typeof key === 'string');
|
assert(typeof key === 'string');
|
||||||
@ -31,18 +29,18 @@ layouts.walletdb = {
|
|||||||
},
|
},
|
||||||
r: function r(wid, index, hash) {
|
r: function r(wid, index, hash) {
|
||||||
assert(typeof hash === 'string');
|
assert(typeof hash === 'string');
|
||||||
return 'r' + pad32(wid) + pad32(index) + hash;
|
return 'r' + hex32(wid) + hex32(index) + hash;
|
||||||
},
|
},
|
||||||
rr: function rr(key) {
|
rr: function rr(key) {
|
||||||
assert(typeof key === 'string');
|
assert(typeof key === 'string');
|
||||||
return key.slice(21);
|
return key.slice(21);
|
||||||
},
|
},
|
||||||
w: function w(wid) {
|
w: function w(wid) {
|
||||||
return 'w' + pad32(wid);
|
return 'w' + hex32(wid);
|
||||||
},
|
},
|
||||||
ww: function ww(key) {
|
ww: function ww(key) {
|
||||||
assert(typeof key === 'string');
|
assert(typeof key === 'string');
|
||||||
return parseInt(key.slice(1), 10);
|
return parseInt(key.slice(1), 16);
|
||||||
},
|
},
|
||||||
l: function l(id) {
|
l: function l(id) {
|
||||||
assert(typeof id === 'string');
|
assert(typeof id === 'string');
|
||||||
@ -53,36 +51,36 @@ layouts.walletdb = {
|
|||||||
return key.slice(1);
|
return key.slice(1);
|
||||||
},
|
},
|
||||||
a: function a(wid, index) {
|
a: function a(wid, index) {
|
||||||
return 'a' + pad32(wid) + pad32(index);
|
return 'a' + hex32(wid) + hex32(index);
|
||||||
},
|
},
|
||||||
i: function i(wid, name) {
|
i: function i(wid, name) {
|
||||||
assert(typeof name === 'string');
|
assert(typeof name === 'string');
|
||||||
return 'i' + pad32(wid) + name;
|
return 'i' + hex32(wid) + name;
|
||||||
},
|
},
|
||||||
ii: function ii(key) {
|
ii: function ii(key) {
|
||||||
assert(typeof key === 'string');
|
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) {
|
n: function n(wid, index) {
|
||||||
return 'n' + pad32(wid) + pad32(index);
|
return 'n' + hex32(wid) + hex32(index);
|
||||||
},
|
},
|
||||||
R: 'R',
|
R: 'R',
|
||||||
h: function h(height) {
|
h: function h(height) {
|
||||||
return 'h' + pad32(height);
|
return 'h' + hex32(height);
|
||||||
},
|
},
|
||||||
b: function b(height) {
|
b: function b(height) {
|
||||||
return 'b' + pad32(height);
|
return 'b' + hex32(height);
|
||||||
},
|
},
|
||||||
bb: function bb(key) {
|
bb: function bb(key) {
|
||||||
assert(typeof key === 'string');
|
assert(typeof key === 'string');
|
||||||
return parseInt(key.slice(1), 10);
|
return parseInt(key.slice(1), 16);
|
||||||
},
|
},
|
||||||
o: function o(hash, index) {
|
o: function o(hash, index) {
|
||||||
assert(typeof hash === 'string');
|
assert(typeof hash === 'string');
|
||||||
return 'o' + hash + pad32(index);
|
return 'o' + hash + hex32(index);
|
||||||
},
|
},
|
||||||
oo: function oo(key) {
|
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) {
|
T: function T(hash) {
|
||||||
assert(typeof hash === 'string');
|
assert(typeof hash === 'string');
|
||||||
@ -96,55 +94,55 @@ layouts.walletdb = {
|
|||||||
layouts.txdb = {
|
layouts.txdb = {
|
||||||
binary: false,
|
binary: false,
|
||||||
prefix: function prefix(wid) {
|
prefix: function prefix(wid) {
|
||||||
return 't' + pad32(wid);
|
return 't' + hex32(wid);
|
||||||
},
|
},
|
||||||
R: 'R',
|
R: 'R',
|
||||||
r: function r(acct) {
|
r: function r(acct) {
|
||||||
assert(typeof acct === 'number');
|
assert(typeof acct === 'number');
|
||||||
return 'r' + pad32(acct);
|
return 'r' + hex32(acct);
|
||||||
},
|
},
|
||||||
rr: function rr(key) {
|
rr: function rr(key) {
|
||||||
assert(typeof key === 'string');
|
assert(typeof key === 'string');
|
||||||
return parseInt(key.slice(1), 10);
|
return parseInt(key.slice(1), 16);
|
||||||
},
|
},
|
||||||
hi: function hi(ch, hash, index) {
|
hi: function hi(ch, hash, index) {
|
||||||
assert(typeof hash === 'string');
|
assert(typeof hash === 'string');
|
||||||
return ch + hash + pad32(index);
|
return ch + hash + hex32(index);
|
||||||
},
|
},
|
||||||
hii: function hii(key) {
|
hii: function hii(key) {
|
||||||
assert(typeof key === 'string');
|
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) {
|
ih: function ih(ch, index, hash) {
|
||||||
assert(typeof hash === 'string');
|
assert(typeof hash === 'string');
|
||||||
return ch + pad32(index) + hash;
|
return ch + hex32(index) + hash;
|
||||||
},
|
},
|
||||||
ihh: function ihh(key) {
|
ihh: function ihh(key) {
|
||||||
assert(typeof key === 'string');
|
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) {
|
iih: function iih(ch, index, num, hash) {
|
||||||
assert(typeof hash === 'string');
|
assert(typeof hash === 'string');
|
||||||
return ch + pad32(index) + pad32(num) + hash;
|
return ch + hex32(index) + hex32(num) + hash;
|
||||||
},
|
},
|
||||||
iihh: function iihh(key) {
|
iihh: function iihh(key) {
|
||||||
assert(typeof key === 'string');
|
assert(typeof key === 'string');
|
||||||
return [
|
return [
|
||||||
parseInt(key.slice(1, 11), 10),
|
parseInt(key.slice(1, 9), 16),
|
||||||
parseInt(key.slice(11, 21), 10),
|
parseInt(key.slice(9, 17), 16),
|
||||||
key.slice(21)
|
key.slice(17)
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
ihi: function ihi(ch, index, hash, num) {
|
ihi: function ihi(ch, index, hash, num) {
|
||||||
assert(typeof hash === 'string');
|
assert(typeof hash === 'string');
|
||||||
return ch + pad32(index) + hash + pad32(num);
|
return ch + hex32(index) + hash + hex32(num);
|
||||||
},
|
},
|
||||||
ihii: function ihii(key) {
|
ihii: function ihii(key) {
|
||||||
assert(typeof key === 'string');
|
assert(typeof key === 'string');
|
||||||
return [
|
return [
|
||||||
parseInt(key.slice(1, 11), 10),
|
parseInt(key.slice(1, 9), 16),
|
||||||
key.slice(11, 75),
|
key.slice(9, 73),
|
||||||
parseInt(key.slice(75), 10)
|
parseInt(key.slice(73), 16)
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
ha: function ha(ch, hash) {
|
ha: function ha(ch, hash) {
|
||||||
@ -234,10 +232,38 @@ layouts.txdb = {
|
|||||||
return this.ihii(key);
|
return this.ihii(key);
|
||||||
},
|
},
|
||||||
b: function b(height) {
|
b: function b(height) {
|
||||||
return 'b' + pad32(height);
|
return 'b' + hex32(height);
|
||||||
},
|
},
|
||||||
bb: function bb(key) {
|
bb: function bb(key) {
|
||||||
assert(typeof key === 'string');
|
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) {
|
if (options.rounds != null) {
|
||||||
assert(util.isU32(options.rounds));
|
assert((options.rounds >>> 0) === options.rounds);
|
||||||
this.N = options.rounds;
|
this.N = options.rounds;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.N != null) {
|
if (options.N != null) {
|
||||||
assert(util.isU32(options.N));
|
assert((options.N >>> 0) === options.N);
|
||||||
this.N = options.N;
|
this.N = options.N;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.r != null) {
|
if (options.r != null) {
|
||||||
assert(util.isU32(options.r));
|
assert((options.r >>> 0) === options.r);
|
||||||
this.r = options.r;
|
this.r = options.r;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.p != null) {
|
if (options.p != null) {
|
||||||
assert(util.isU32(options.p));
|
assert((options.p >>> 0) === options.p);
|
||||||
this.p = options.p;
|
this.p = options.p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
const bweb = require('bweb');
|
const bweb = require('bweb');
|
||||||
|
const {format} = require('util');
|
||||||
const fs = require('../utils/fs');
|
const fs = require('../utils/fs');
|
||||||
const util = require('../utils/util');
|
const util = require('../utils/util');
|
||||||
const digest = require('bcrypto/lib/digest');
|
const digest = require('bcrypto/lib/digest');
|
||||||
@ -101,13 +102,13 @@ class RPC extends RPCBase {
|
|||||||
case 'RPCError':
|
case 'RPCError':
|
||||||
return err.code;
|
return err.code;
|
||||||
case 'ValidationError':
|
case 'ValidationError':
|
||||||
return errors.TYPE_ERROR;
|
return errs.TYPE_ERROR;
|
||||||
case 'EncodingError':
|
case 'EncodingError':
|
||||||
return errors.DESERIALIZATION_ERROR;
|
return errs.DESERIALIZATION_ERROR;
|
||||||
case 'FundingError':
|
case 'FundingError':
|
||||||
return errors.WALLET_INSUFFICIENT_FUNDS;
|
return errs.WALLET_INSUFFICIENT_FUNDS;
|
||||||
default:
|
default:
|
||||||
return errors.INTERNAL_ERROR;
|
return errs.INTERNAL_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -312,11 +313,11 @@ class RPC extends RPCBase {
|
|||||||
const time = util.date();
|
const time = util.date();
|
||||||
|
|
||||||
const out = [
|
const out = [
|
||||||
util.fmt('# Wallet Dump created by Bcoin %s', pkg.version),
|
format('# Wallet Dump created by Bcoin %s', pkg.version),
|
||||||
util.fmt('# * Created on %s', time),
|
format('# * Created on %s', time),
|
||||||
util.fmt('# * Best block at time of backup was %d (%s).',
|
format('# * Best block at time of backup was %d (%s).',
|
||||||
tip.height, util.revHex(tip.hash)),
|
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)
|
if (ring.branch === 1)
|
||||||
fmt = '%s %s change=1 addr=%s';
|
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);
|
out.push(str);
|
||||||
}
|
}
|
||||||
@ -1470,8 +1471,11 @@ class RPC extends RPCBase {
|
|||||||
if (help || (wallet.master.encrypted && args.length !== 0))
|
if (help || (wallet.master.encrypted && args.length !== 0))
|
||||||
throw new RPCError(errs.MISC_ERROR, 'walletlock');
|
throw new RPCError(errs.MISC_ERROR, 'walletlock');
|
||||||
|
|
||||||
if (!wallet.master.encrypted)
|
if (!wallet.master.encrypted) {
|
||||||
throw new RPCError(errs.WALLET_WRONG_ENC_STATE, 'Wallet is not encrypted.');
|
throw new RPCError(
|
||||||
|
errs.WALLET_WRONG_ENC_STATE,
|
||||||
|
'Wallet is not encrypted.');
|
||||||
|
}
|
||||||
|
|
||||||
await wallet.lock();
|
await wallet.lock();
|
||||||
|
|
||||||
@ -1490,8 +1494,11 @@ class RPC extends RPCBase {
|
|||||||
const old = valid.str(0, '');
|
const old = valid.str(0, '');
|
||||||
const passphrase = valid.str(1, '');
|
const passphrase = valid.str(1, '');
|
||||||
|
|
||||||
if (!wallet.master.encrypted)
|
if (!wallet.master.encrypted) {
|
||||||
throw new RPCError(errs.WALLET_WRONG_ENC_STATE, 'Wallet is not encrypted.');
|
throw new RPCError(
|
||||||
|
errs.WALLET_WRONG_ENC_STATE,
|
||||||
|
'Wallet is not encrypted.');
|
||||||
|
}
|
||||||
|
|
||||||
if (old.length < 1 || passphrase.length < 1)
|
if (old.length < 1 || passphrase.length < 1)
|
||||||
throw new RPCError(errs.INVALID_PARAMETER, 'Invalid parameter');
|
throw new RPCError(errs.INVALID_PARAMETER, 'Invalid parameter');
|
||||||
@ -1512,8 +1519,11 @@ class RPC extends RPCBase {
|
|||||||
'walletpassphrase "passphrase" timeout');
|
'walletpassphrase "passphrase" timeout');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!wallet.master.encrypted)
|
if (!wallet.master.encrypted) {
|
||||||
throw new RPCError(errs.WALLET_WRONG_ENC_STATE, 'Wallet is not encrypted.');
|
throw new RPCError(
|
||||||
|
errs.WALLET_WRONG_ENC_STATE,
|
||||||
|
'Wallet is not encrypted.');
|
||||||
|
}
|
||||||
|
|
||||||
if (passphrase.length < 1)
|
if (passphrase.length < 1)
|
||||||
throw new RPCError(errs.INVALID_PARAMETER, 'Invalid parameter');
|
throw new RPCError(errs.INVALID_PARAMETER, 'Invalid parameter');
|
||||||
@ -1604,7 +1614,7 @@ class RPC extends RPCBase {
|
|||||||
if (help || args.length !== 0)
|
if (help || args.length !== 0)
|
||||||
throw new RPCError(errs.MISC_ERROR, 'getmemoryinfo');
|
throw new RPCError(errs.MISC_ERROR, 'getmemoryinfo');
|
||||||
|
|
||||||
return util.memoryUsage();
|
return this.logger.memoryUsage();
|
||||||
}
|
}
|
||||||
|
|
||||||
async setLogLevel(args, help) {
|
async setLogLevel(args, help) {
|
||||||
|
|||||||
@ -2064,7 +2064,7 @@ TXDB.prototype.getAccountBalance = async function getAccountBalance(acct) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
TXDB.prototype.zap = async function zap(acct, age) {
|
TXDB.prototype.zap = async function zap(acct, age) {
|
||||||
assert(util.isU32(age));
|
assert((age >>> 0) === age);
|
||||||
|
|
||||||
const now = util.now();
|
const now = util.now();
|
||||||
|
|
||||||
|
|||||||
@ -10,7 +10,6 @@
|
|||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
const EventEmitter = require('events');
|
const EventEmitter = require('events');
|
||||||
const Network = require('../protocol/network');
|
const Network = require('../protocol/network');
|
||||||
const util = require('../utils/util');
|
|
||||||
const encoding = require('../utils/encoding');
|
const encoding = require('../utils/encoding');
|
||||||
const Lock = require('../utils/lock');
|
const Lock = require('../utils/lock');
|
||||||
const digest = require('bcrypto/lib/digest');
|
const digest = require('bcrypto/lib/digest');
|
||||||
@ -115,7 +114,7 @@ Wallet.prototype.fromOptions = function fromOptions(options) {
|
|||||||
this.master.fromKey(key, mnemonic, this.network);
|
this.master.fromKey(key, mnemonic, this.network);
|
||||||
|
|
||||||
if (options.wid != null) {
|
if (options.wid != null) {
|
||||||
assert(util.isU32(options.wid));
|
assert((options.wid >>> 0) === options.wid);
|
||||||
this.wid = options.wid;
|
this.wid = options.wid;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,7 +134,7 @@ Wallet.prototype.fromOptions = function fromOptions(options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (options.accountDepth != null) {
|
if (options.accountDepth != null) {
|
||||||
assert(util.isU32(options.accountDepth));
|
assert((options.accountDepth >>> 0) === options.accountDepth);
|
||||||
this.accountDepth = options.accountDepth;
|
this.accountDepth = options.accountDepth;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,7 +145,7 @@ Wallet.prototype.fromOptions = function fromOptions(options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (options.tokenDepth != null) {
|
if (options.tokenDepth != null) {
|
||||||
assert(util.isU32(options.tokenDepth));
|
assert((options.tokenDepth >>> 0) === options.tokenDepth);
|
||||||
this.tokenDepth = 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) {
|
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);
|
const wtx = await this.getTX(hash);
|
||||||
|
|
||||||
|
|||||||
@ -430,7 +430,7 @@ WalletDB.prototype.scan = async function scan(height) {
|
|||||||
if (height == null)
|
if (height == null)
|
||||||
height = this.state.startHeight;
|
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);
|
await this.rollback(height);
|
||||||
|
|
||||||
@ -851,7 +851,7 @@ WalletDB.prototype.renameAccount = function renameAccount(b, account, name) {
|
|||||||
/**
|
/**
|
||||||
* Get a wallet with token auth first.
|
* Get a wallet with token auth first.
|
||||||
* @param {WalletID} wid
|
* @param {WalletID} wid
|
||||||
* @param {String|Buffer} token
|
* @param {Buffer} token
|
||||||
* @returns {Promise} - Returns {@link Wallet}.
|
* @returns {Promise} - Returns {@link Wallet}.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -861,12 +861,6 @@ WalletDB.prototype.auth = async function auth(wid, token) {
|
|||||||
if (!wallet)
|
if (!wallet)
|
||||||
return null;
|
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:
|
// Compare in constant time:
|
||||||
if (!ccmp(token, wallet.token))
|
if (!ccmp(token, wallet.token))
|
||||||
throw new Error('WDB: Authentication error.');
|
throw new Error('WDB: Authentication error.');
|
||||||
@ -2082,7 +2076,7 @@ WalletOptions.prototype.fromOptions = function fromOptions(options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (options.feeRate != null) {
|
if (options.feeRate != null) {
|
||||||
assert(util.isU64(options.feeRate));
|
assert((options.feeRate >>> 0) === options.feeRate);
|
||||||
this.feeRate = options.feeRate;
|
this.feeRate = options.feeRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2103,12 +2097,12 @@ WalletOptions.prototype.fromOptions = function fromOptions(options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (options.maxFiles != null) {
|
if (options.maxFiles != null) {
|
||||||
assert(util.isU32(options.maxFiles));
|
assert((options.maxFiles >>> 0) === options.maxFiles);
|
||||||
this.maxFiles = options.maxFiles;
|
this.maxFiles = options.maxFiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.cacheSize != null) {
|
if (options.cacheSize != null) {
|
||||||
assert(util.isU64(options.cacheSize));
|
assert(Number.isSafeInteger(options.cacheSize) && options.cacheSize >= 0);
|
||||||
this.cacheSize = options.cacheSize;
|
this.cacheSize = options.cacheSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
const EventEmitter = require('events');
|
const EventEmitter = require('events');
|
||||||
const util = require('../utils/util');
|
const {format} = require('util');
|
||||||
const Network = require('../protocol/network');
|
const Network = require('../protocol/network');
|
||||||
const jobs = require('./jobs');
|
const jobs = require('./jobs');
|
||||||
const Parser = require('./parser');
|
const Parser = require('./parser');
|
||||||
@ -132,8 +132,8 @@ Master.prototype.destroy = function destroy() {
|
|||||||
* @param {...String} args
|
* @param {...String} args
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Master.prototype.log = function log(...items) {
|
Master.prototype.log = function log() {
|
||||||
const text = util.format(items, this.color);
|
const text = format.apply(null, arguments);
|
||||||
this.send(new packets.LogPacket(text));
|
this.send(new packets.LogPacket(text));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -8,10 +8,6 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const Master = require('./master');
|
const Master = require('./master');
|
||||||
const util = require('../utils/util');
|
|
||||||
const server = new Master();
|
const server = new Master();
|
||||||
|
|
||||||
util.log = server.log.bind(server);
|
|
||||||
util.error = util.log;
|
|
||||||
|
|
||||||
server.listen();
|
server.listen();
|
||||||
|
|||||||
@ -12,7 +12,6 @@
|
|||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
const EventEmitter = require('events');
|
const EventEmitter = require('events');
|
||||||
const os = require('os');
|
const os = require('os');
|
||||||
const util = require('../utils/util');
|
|
||||||
const co = require('../utils/co');
|
const co = require('../utils/co');
|
||||||
const Network = require('../protocol/network');
|
const Network = require('../protocol/network');
|
||||||
const Child = require('./child');
|
const Child = require('./child');
|
||||||
@ -68,13 +67,13 @@ WorkerPool.prototype.set = function set(options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (options.size != null) {
|
if (options.size != null) {
|
||||||
assert(util.isU32(options.size));
|
assert((options.size >>> 0) === options.size);
|
||||||
assert(options.size > 0);
|
assert(options.size > 0);
|
||||||
this.size = options.size;
|
this.size = options.size;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.timeout != null) {
|
if (options.timeout != null) {
|
||||||
assert(util.isInt(options.timeout));
|
assert(Number.isSafeInteger(options.timeout));
|
||||||
assert(options.timeout >= -1);
|
assert(options.timeout >= -1);
|
||||||
this.timeout = options.timeout;
|
this.timeout = options.timeout;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -52,7 +52,7 @@ function Coins(options) {
|
|||||||
|
|
||||||
Coins.prototype.fromOptions = function fromOptions(options) {
|
Coins.prototype.fromOptions = function fromOptions(options) {
|
||||||
if (options.version != null) {
|
if (options.version != null) {
|
||||||
assert(util.isU32(options.version));
|
assert((options.version >>> 0) === options.version);
|
||||||
this.version = options.version;
|
this.version = options.version;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,7 +62,7 @@ Coins.prototype.fromOptions = function fromOptions(options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (options.height != null) {
|
if (options.height != null) {
|
||||||
assert(util.isInt(options.height));
|
assert(Number.isSafeInteger(options.height));
|
||||||
this.height = options.height;
|
this.height = options.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -54,7 +54,7 @@ function Coins(options) {
|
|||||||
|
|
||||||
Coins.prototype.fromOptions = function fromOptions(options) {
|
Coins.prototype.fromOptions = function fromOptions(options) {
|
||||||
if (options.version != null) {
|
if (options.version != null) {
|
||||||
assert(util.isU32(options.version));
|
assert((options.version >>> 0) === options.version);
|
||||||
this.version = options.version;
|
this.version = options.version;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,7 +64,7 @@ Coins.prototype.fromOptions = function fromOptions(options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (options.height != null) {
|
if (options.height != null) {
|
||||||
assert(util.isInt(options.height));
|
assert(Number.isSafeInteger(options.height));
|
||||||
this.height = options.height;
|
this.height = options.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
127
scripts/fuzz.js
127
scripts/fuzz.js
@ -1,6 +1,5 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const util = require('../lib/utils/util');
|
|
||||||
const Script = require('../lib/script/script');
|
const Script = require('../lib/script/script');
|
||||||
const Stack = require('../lib/script/stack');
|
const Stack = require('../lib/script/stack');
|
||||||
const Witness = require('../lib/script/witness');
|
const Witness = require('../lib/script/witness');
|
||||||
@ -21,7 +20,7 @@ try {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (consensus)
|
if (consensus)
|
||||||
util.log('Running against bitcoinconsensus...');
|
console.log('Running against bitcoinconsensus...');
|
||||||
|
|
||||||
const MANDATORY = flags.MANDATORY_VERIFY_FLAGS | flags.VERIFY_WITNESS;
|
const MANDATORY = flags.MANDATORY_VERIFY_FLAGS | flags.VERIFY_WITNESS;
|
||||||
const STANDARD = flags.STANDARD_VERIFY_FLAGS;
|
const STANDARD = flags.STANDARD_VERIFY_FLAGS;
|
||||||
@ -39,13 +38,13 @@ function assertConsensus(tx, output, flags, code) {
|
|||||||
const err = verifyConsensus(tx, 0, output, 0, flags);
|
const err = verifyConsensus(tx, 0, output, 0, flags);
|
||||||
|
|
||||||
if (err !== code) {
|
if (err !== code) {
|
||||||
util.log('bitcoinconsensus mismatch!');
|
console.log('bitcoinconsensus mismatch!');
|
||||||
util.log(`${err} (bitcoin core) !== ${code} (bcoin)`);
|
console.log(`${err} (bitcoin core) !== ${code} (bcoin)`);
|
||||||
util.log(tx);
|
console.log(tx);
|
||||||
util.log(output);
|
console.log(output);
|
||||||
util.log(flags);
|
console.log(flags);
|
||||||
util.log('TX: %s', tx.toRaw().toString('hex'));
|
console.log('TX: %s', tx.toRaw().toString('hex'));
|
||||||
util.log('Output Script: %s', output.toRaw().toString('hex'));
|
console.log('Output Script: %s', output.toRaw().toString('hex'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,7 +58,7 @@ function randomKey() {
|
|||||||
const x = secp256k1.generatePrivateKey();
|
const x = secp256k1.generatePrivateKey();
|
||||||
const y = 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)]);
|
const p = Buffer.from([2 | (y[y.length - 1] & 1)]);
|
||||||
return Buffer.concat([p, x]);
|
return Buffer.concat([p, x]);
|
||||||
}
|
}
|
||||||
@ -70,28 +69,28 @@ function randomKey() {
|
|||||||
|
|
||||||
function randomOutpoint() {
|
function randomOutpoint() {
|
||||||
const hash = random.randomBytes(32).toString('hex');
|
const hash = random.randomBytes(32).toString('hex');
|
||||||
return new Outpoint(hash, util.random(0, 0xffffffff));
|
return new Outpoint(hash, rand(0, 0xffffffff));
|
||||||
}
|
}
|
||||||
|
|
||||||
function randomInput() {
|
function randomInput() {
|
||||||
const input = Input.fromOutpoint(randomOutpoint());
|
const input = Input.fromOutpoint(randomOutpoint());
|
||||||
|
|
||||||
if (util.random(0, 5) === 0)
|
if (rand(0, 5) === 0)
|
||||||
input.sequence = util.random(0, 0xffffffff);
|
input.sequence = rand(0, 0xffffffff);
|
||||||
|
|
||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
|
|
||||||
function randomOutput() {
|
function randomOutput() {
|
||||||
return Output.fromScript(randomScript(), util.random(0, 1e8));
|
return Output.fromScript(randomScript(), rand(0, 1e8));
|
||||||
}
|
}
|
||||||
|
|
||||||
function randomTX() {
|
function randomTX() {
|
||||||
const tx = new TX();
|
const tx = new TX();
|
||||||
const inputs = util.random(1, 5);
|
const inputs = rand(1, 5);
|
||||||
const outputs = util.random(0, 5);
|
const outputs = rand(0, 5);
|
||||||
|
|
||||||
tx.version = util.random(0, 0xffffffff);
|
tx.version = rand(0, 0xffffffff);
|
||||||
|
|
||||||
for (let i = 0; i < inputs; i++)
|
for (let i = 0; i < inputs; i++)
|
||||||
tx.inputs.push(randomInput());
|
tx.inputs.push(randomInput());
|
||||||
@ -99,8 +98,8 @@ function randomTX() {
|
|||||||
for (let i = 0; i < outputs; i++)
|
for (let i = 0; i < outputs; i++)
|
||||||
tx.outputs.push(randomOutput());
|
tx.outputs.push(randomOutput());
|
||||||
|
|
||||||
if (util.random(0, 5) === 0)
|
if (rand(0, 5) === 0)
|
||||||
tx.locktime = util.random(0, 0xffffffff);
|
tx.locktime = rand(0, 0xffffffff);
|
||||||
|
|
||||||
tx.refresh();
|
tx.refresh();
|
||||||
|
|
||||||
@ -108,11 +107,11 @@ function randomTX() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function randomWitness(redeem) {
|
function randomWitness(redeem) {
|
||||||
const size = util.random(1, 100);
|
const size = rand(1, 100);
|
||||||
const witness = new Witness();
|
const witness = new Witness();
|
||||||
|
|
||||||
for (let i = 0; i < size; i++) {
|
for (let i = 0; i < size; i++) {
|
||||||
const len = util.random(0, 100);
|
const len = rand(0, 100);
|
||||||
witness.push(random.randomBytes(len));
|
witness.push(random.randomBytes(len));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,11 +124,11 @@ function randomWitness(redeem) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function randomInputScript(redeem) {
|
function randomInputScript(redeem) {
|
||||||
const size = util.random(1, 100);
|
const size = rand(1, 100);
|
||||||
const script = new Script();
|
const script = new Script();
|
||||||
|
|
||||||
for (let i = 0; i < size; i++) {
|
for (let i = 0; i < size; i++) {
|
||||||
const len = util.random(0, 100);
|
const len = rand(0, 100);
|
||||||
script.pushData(random.randomBytes(len));
|
script.pushData(random.randomBytes(len));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,7 +139,7 @@ function randomInputScript(redeem) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function randomOutputScript() {
|
function randomOutputScript() {
|
||||||
const size = util.random(1, 10000);
|
const size = rand(1, 10000);
|
||||||
return Script.fromRaw(random.randomBytes(size));
|
return Script.fromRaw(random.randomBytes(size));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -165,7 +164,7 @@ function isPushOnly(script) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function randomPubkey() {
|
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));
|
return Script.fromPubkey(random.randomBytes(len));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,12 +173,12 @@ function randomPubkeyhash() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function randomMultisig() {
|
function randomMultisig() {
|
||||||
const n = util.random(1, 16);
|
const n = rand(1, 16);
|
||||||
const m = util.random(1, n);
|
const m = rand(1, n);
|
||||||
const keys = [];
|
const keys = [];
|
||||||
|
|
||||||
for (let i = 0; i < n; i++) {
|
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));
|
keys.push(random.randomBytes(len));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,13 +198,13 @@ function randomWitnessScripthash() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function randomProgram() {
|
function randomProgram() {
|
||||||
const version = util.random(0, 16);
|
const version = rand(0, 16);
|
||||||
const size = util.random(2, 41);
|
const size = rand(2, 41);
|
||||||
return Script.fromProgram(version, random.randomBytes(size));
|
return Script.fromProgram(version, random.randomBytes(size));
|
||||||
}
|
}
|
||||||
|
|
||||||
function randomRedeem() {
|
function randomRedeem() {
|
||||||
switch (util.random(0, 5)) {
|
switch (rand(0, 5)) {
|
||||||
case 0:
|
case 0:
|
||||||
return randomPubkey();
|
return randomPubkey();
|
||||||
case 1:
|
case 1:
|
||||||
@ -221,7 +220,7 @@ function randomRedeem() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function randomScript() {
|
function randomScript() {
|
||||||
switch (util.random(0, 7)) {
|
switch (rand(0, 7)) {
|
||||||
case 0:
|
case 0:
|
||||||
return randomPubkey();
|
return randomPubkey();
|
||||||
case 1:
|
case 1:
|
||||||
@ -299,7 +298,7 @@ function randomWitnessNestedContext() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function randomContext() {
|
function randomContext() {
|
||||||
switch (util.random(0, 6)) {
|
switch (rand(0, 6)) {
|
||||||
case 0:
|
case 0:
|
||||||
return randomPubkeyContext();
|
return randomPubkeyContext();
|
||||||
case 1:
|
case 1:
|
||||||
@ -322,7 +321,7 @@ function fuzzSimple(flags) {
|
|||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (++total % 1000 === 0)
|
if (++total % 1000 === 0)
|
||||||
util.log('Fuzzed %d scripts.', total);
|
console.log('Fuzzed %d scripts.', total);
|
||||||
|
|
||||||
if (total % 500 === 0)
|
if (total % 500 === 0)
|
||||||
tx = randomTX();
|
tx = randomTX();
|
||||||
@ -357,16 +356,16 @@ function fuzzSimple(flags) {
|
|||||||
if (isPushOnly(output))
|
if (isPushOnly(output))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
util.log('Produced valid scripts:');
|
console.log('Produced valid scripts:');
|
||||||
|
|
||||||
util.log('Input:');
|
console.log('Input:');
|
||||||
util.log(input);
|
console.log(input);
|
||||||
|
|
||||||
util.log('Output:');
|
console.log('Output:');
|
||||||
util.log(output);
|
console.log(output);
|
||||||
|
|
||||||
util.log('Stack:');
|
console.log('Stack:');
|
||||||
util.log(stack);
|
console.log(stack);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -378,7 +377,7 @@ function fuzzVerify(flags) {
|
|||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (++total % 1000 === 0)
|
if (++total % 1000 === 0)
|
||||||
util.log('Fuzzed %d scripts.', total);
|
console.log('Fuzzed %d scripts.', total);
|
||||||
|
|
||||||
if (total % 500 === 0)
|
if (total % 500 === 0)
|
||||||
tx = randomTX();
|
tx = randomTX();
|
||||||
@ -415,16 +414,16 @@ function fuzzVerify(flags) {
|
|||||||
if (isPushOnly(output))
|
if (isPushOnly(output))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
util.log('Produced valid scripts:');
|
console.log('Produced valid scripts:');
|
||||||
|
|
||||||
util.log('Input:');
|
console.log('Input:');
|
||||||
util.log(input);
|
console.log(input);
|
||||||
|
|
||||||
util.log('Witness:');
|
console.log('Witness:');
|
||||||
util.log(witness);
|
console.log(witness);
|
||||||
|
|
||||||
util.log('Output:');
|
console.log('Output:');
|
||||||
util.log(output);
|
console.log(output);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -436,7 +435,7 @@ function fuzzLess(flags) {
|
|||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (++total % 1000 === 0)
|
if (++total % 1000 === 0)
|
||||||
util.log('Fuzzed %d scripts.', total);
|
console.log('Fuzzed %d scripts.', total);
|
||||||
|
|
||||||
if (total % 500 === 0)
|
if (total % 500 === 0)
|
||||||
tx = randomTX();
|
tx = randomTX();
|
||||||
@ -469,20 +468,20 @@ function fuzzLess(flags) {
|
|||||||
|
|
||||||
assertConsensus(tx, ctx.output, flags, 'OK');
|
assertConsensus(tx, ctx.output, flags, 'OK');
|
||||||
|
|
||||||
util.log('Produced valid scripts:');
|
console.log('Produced valid scripts:');
|
||||||
|
|
||||||
util.log('Input:');
|
console.log('Input:');
|
||||||
util.log(ctx.input);
|
console.log(ctx.input);
|
||||||
|
|
||||||
util.log('Witness:');
|
console.log('Witness:');
|
||||||
util.log(ctx.witness);
|
console.log(ctx.witness);
|
||||||
|
|
||||||
util.log('Output:');
|
console.log('Output:');
|
||||||
util.log(ctx.output);
|
console.log(ctx.output);
|
||||||
|
|
||||||
if (ctx.redeem) {
|
if (ctx.redeem) {
|
||||||
util.log('Redeem:');
|
console.log('Redeem:');
|
||||||
util.log(ctx.redeem);
|
console.log(ctx.redeem);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -505,13 +504,17 @@ function main() {
|
|||||||
fuzzLess(flags);
|
fuzzLess(flags);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
util.log('Please select a mode:');
|
console.log('Please select a mode:');
|
||||||
util.log('simple, verify, less');
|
console.log('simple, verify, less');
|
||||||
util.log('Optional `--standard` flag.');
|
console.log('Optional `--standard` flag.');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function rand(min, max) {
|
||||||
|
return Math.floor(Math.random() * (max - min)) + min;
|
||||||
|
}
|
||||||
|
|
||||||
randomKey;
|
randomKey;
|
||||||
randomSignature;
|
randomSignature;
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const util = require('../lib/utils/util');
|
|
||||||
const consensus = require('../lib/protocol/consensus');
|
const consensus = require('../lib/protocol/consensus');
|
||||||
const encoding = require('../lib/utils/encoding');
|
const encoding = require('../lib/utils/encoding');
|
||||||
const TX = require('../lib/primitives/tx');
|
const TX = require('../lib/primitives/tx');
|
||||||
@ -106,31 +105,31 @@ const btcd = createGenesisBlock({
|
|||||||
nonce: 2
|
nonce: 2
|
||||||
});
|
});
|
||||||
|
|
||||||
util.log(main);
|
console.log(main);
|
||||||
util.log('');
|
console.log('');
|
||||||
util.log(testnet);
|
console.log(testnet);
|
||||||
util.log('');
|
console.log('');
|
||||||
util.log(regtest);
|
console.log(regtest);
|
||||||
util.log('');
|
console.log('');
|
||||||
util.log(segnet3);
|
console.log(segnet3);
|
||||||
util.log('');
|
console.log('');
|
||||||
util.log(segnet4);
|
console.log(segnet4);
|
||||||
util.log('');
|
console.log('');
|
||||||
util.log('');
|
console.log('');
|
||||||
util.log('main hash: %s', main.rhash());
|
console.log('main hash: %s', main.rhash());
|
||||||
util.log('main raw: %s', main.toRaw().toString('hex'));
|
console.log('main raw: %s', main.toRaw().toString('hex'));
|
||||||
util.log('');
|
console.log('');
|
||||||
util.log('testnet hash: %s', testnet.rhash());
|
console.log('testnet hash: %s', testnet.rhash());
|
||||||
util.log('testnet raw: %s', testnet.toRaw().toString('hex'));
|
console.log('testnet raw: %s', testnet.toRaw().toString('hex'));
|
||||||
util.log('');
|
console.log('');
|
||||||
util.log('regtest hash: %s', regtest.rhash());
|
console.log('regtest hash: %s', regtest.rhash());
|
||||||
util.log('regtest raw: %s', regtest.toRaw().toString('hex'));
|
console.log('regtest raw: %s', regtest.toRaw().toString('hex'));
|
||||||
util.log('');
|
console.log('');
|
||||||
util.log('segnet3 hash: %s', segnet3.rhash());
|
console.log('segnet3 hash: %s', segnet3.rhash());
|
||||||
util.log('segnet3 raw: %s', segnet3.toRaw().toString('hex'));
|
console.log('segnet3 raw: %s', segnet3.toRaw().toString('hex'));
|
||||||
util.log('');
|
console.log('');
|
||||||
util.log('segnet4 hash: %s', segnet4.rhash());
|
console.log('segnet4 hash: %s', segnet4.rhash());
|
||||||
util.log('segnet4 raw: %s', segnet4.toRaw().toString('hex'));
|
console.log('segnet4 raw: %s', segnet4.toRaw().toString('hex'));
|
||||||
util.log('');
|
console.log('');
|
||||||
util.log('btcd simnet hash: %s', btcd.rhash());
|
console.log('btcd simnet hash: %s', btcd.rhash());
|
||||||
util.log('btcd simnet raw: %s', btcd.toRaw().toString('hex'));
|
console.log('btcd simnet raw: %s', btcd.toRaw().toString('hex'));
|
||||||
|
|||||||
@ -104,6 +104,16 @@ const invalidAddresses = [
|
|||||||
'tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3pjxtptv'
|
'tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3pjxtptv'
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const validBech32Tests = [
|
||||||
|
'BC1QW508D6QEJXTDG4Y5R3ZARVARY0C5XW7KV8F3T4',
|
||||||
|
'tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7',
|
||||||
|
'bc1pw508d6qejxtdg4y5r3zarvary0c5xw7kw50'
|
||||||
|
+ '8d6qejxtdg4y5r3zarvary0c5xw7k7grplx',
|
||||||
|
'BC1SW50QA3JX3S',
|
||||||
|
'bc1zw508d6qejxtdg4y5r3zarvaryvg6kdaj',
|
||||||
|
'tb1qqqqqp399et2xygdj5xreqhjjvcmzhxw4aywxecjdzew6hylgvsesrxh6hy'
|
||||||
|
];
|
||||||
|
|
||||||
function fromAddress(hrp, addr) {
|
function fromAddress(hrp, addr) {
|
||||||
const dec = bech32.decode(addr);
|
const dec = bech32.decode(addr);
|
||||||
|
|
||||||
@ -216,4 +226,10 @@ describe('Bech32', function() {
|
|||||||
assert.throws(() => Address.fromBech32(addr, 'testnet'));
|
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 Script = require('../lib/script/script');
|
||||||
const Outpoint = require('../lib/primitives/outpoint');
|
const Outpoint = require('../lib/primitives/outpoint');
|
||||||
const MTX = require('../lib/primitives/mtx');
|
const MTX = require('../lib/primitives/mtx');
|
||||||
const HTTP = require('../lib/http');
|
|
||||||
const FullNode = require('../lib/node/fullnode');
|
const FullNode = require('../lib/node/fullnode');
|
||||||
const pkg = require('../lib/pkg');
|
const pkg = require('../lib/pkg');
|
||||||
const Network = require('../lib/protocol/network');
|
const Network = require('../lib/protocol/network');
|
||||||
@ -221,7 +220,7 @@ describe('HTTP', function() {
|
|||||||
sizelimit: 1000000,
|
sizelimit: 1000000,
|
||||||
longpollid:
|
longpollid:
|
||||||
'0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206'
|
'0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206'
|
||||||
+ '0000000000',
|
+ '00000000',
|
||||||
submitold: false,
|
submitold: false,
|
||||||
coinbaseaux: { flags: '6d696e65642062792062636f696e' },
|
coinbaseaux: { flags: '6d696e65642062792062636f696e' },
|
||||||
coinbasevalue: 5000000000,
|
coinbasevalue: 5000000000,
|
||||||
|
|||||||
@ -498,7 +498,7 @@ describe('Node', function() {
|
|||||||
sigoplimit: 80000,
|
sigoplimit: 80000,
|
||||||
sizelimit: 4000000,
|
sizelimit: 4000000,
|
||||||
weightlimit: 4000000,
|
weightlimit: 4000000,
|
||||||
longpollid: node.chain.tip.rhash() + '0000000000',
|
longpollid: node.chain.tip.rhash() + '00000000',
|
||||||
submitold: false,
|
submitold: false,
|
||||||
coinbaseaux: { flags: '6d696e65642062792062636f696e' },
|
coinbaseaux: { flags: '6d696e65642062792062636f696e' },
|
||||||
coinbasevalue: 1250000000,
|
coinbasevalue: 1250000000,
|
||||||
|
|||||||
@ -51,7 +51,7 @@ describe('Protocol', function() {
|
|||||||
time: network.now(),
|
time: network.now(),
|
||||||
remote: new NetAddress(),
|
remote: new NetAddress(),
|
||||||
local: new NetAddress(),
|
local: new NetAddress(),
|
||||||
nonce: util.nonce(),
|
nonce: Buffer.allocUnsafe(8),
|
||||||
agent: agent,
|
agent: agent,
|
||||||
height: 0,
|
height: 0,
|
||||||
noRelay: false
|
noRelay: false
|
||||||
@ -70,7 +70,7 @@ describe('Protocol', function() {
|
|||||||
time: network.now(),
|
time: network.now(),
|
||||||
remote: new NetAddress(),
|
remote: new NetAddress(),
|
||||||
local: new NetAddress(),
|
local: new NetAddress(),
|
||||||
nonce: util.nonce(),
|
nonce: Buffer.allocUnsafe(8),
|
||||||
agent: agent,
|
agent: agent,
|
||||||
height: 10,
|
height: 10,
|
||||||
noRelay: true
|
noRelay: true
|
||||||
|
|||||||
@ -9,8 +9,8 @@ const Witness = require('../lib/script/witness');
|
|||||||
const Stack = require('../lib/script/stack');
|
const Stack = require('../lib/script/stack');
|
||||||
const Opcode = require('../lib/script/opcode');
|
const Opcode = require('../lib/script/opcode');
|
||||||
const TX = require('../lib/primitives/tx');
|
const TX = require('../lib/primitives/tx');
|
||||||
const util = require('../lib/utils/util');
|
|
||||||
const encoding = require('../lib/utils/encoding');
|
const encoding = require('../lib/utils/encoding');
|
||||||
|
const {fromFloat} = require('../lib/utils/fixed');
|
||||||
|
|
||||||
const scripts = require('./data/script-tests.json');
|
const scripts = require('./data/script-tests.json');
|
||||||
|
|
||||||
@ -39,7 +39,7 @@ function parseScriptTest(data) {
|
|||||||
|
|
||||||
let value = 0;
|
let value = 0;
|
||||||
if (witArr.length > 0)
|
if (witArr.length > 0)
|
||||||
value = util.fromFloat(witArr.pop(), 8);
|
value = fromFloat(witArr.pop(), 8);
|
||||||
|
|
||||||
const witness = Witness.fromString(witArr);
|
const witness = Witness.fromString(witArr);
|
||||||
const input = Script.fromString(inpHex);
|
const input = Script.fromString(inpHex);
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
const {inspect} = require('util');
|
||||||
const assert = require('./util/assert');
|
const assert = require('./util/assert');
|
||||||
const util = require('../lib/utils/util');
|
const util = require('../lib/utils/util');
|
||||||
const encoding = require('../lib/utils/encoding');
|
const encoding = require('../lib/utils/encoding');
|
||||||
@ -90,7 +91,7 @@ function parseTXTest(data) {
|
|||||||
flags: flags,
|
flags: flags,
|
||||||
view: view,
|
view: view,
|
||||||
comments: coin
|
comments: coin
|
||||||
? util.inspectify(coin.script, false)
|
? inspect(coin.script)
|
||||||
: 'coinbase',
|
: 'coinbase',
|
||||||
data: data
|
data: data
|
||||||
};
|
};
|
||||||
|
|||||||
@ -9,7 +9,7 @@ const base58 = require('../lib/utils/base58');
|
|||||||
const encoding = require('../lib/utils/encoding');
|
const encoding = require('../lib/utils/encoding');
|
||||||
const Amount = require('../lib/btc/amount');
|
const Amount = require('../lib/btc/amount');
|
||||||
const Validator = require('../lib/utils/validator');
|
const Validator = require('../lib/utils/validator');
|
||||||
const util = require('../lib/utils/util');
|
const fixed = require('../lib/utils/fixed');
|
||||||
|
|
||||||
const base58Tests = [
|
const base58Tests = [
|
||||||
['', ''],
|
['', ''],
|
||||||
@ -32,16 +32,6 @@ const base58Tests = [
|
|||||||
['00000000000000000000', '1111111111']
|
['00000000000000000000', '1111111111']
|
||||||
];
|
];
|
||||||
|
|
||||||
const validBech32Tests = [
|
|
||||||
'BC1QW508D6QEJXTDG4Y5R3ZARVARY0C5XW7KV8F3T4',
|
|
||||||
'tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7',
|
|
||||||
'bc1pw508d6qejxtdg4y5r3zarvary0c5xw7kw50'
|
|
||||||
+ '8d6qejxtdg4y5r3zarvary0c5xw7k7grplx',
|
|
||||||
'BC1SW50QA3JX3S',
|
|
||||||
'bc1zw508d6qejxtdg4y5r3zarvaryvg6kdaj',
|
|
||||||
'tb1qqqqqp399et2xygdj5xreqhjjvcmzhxw4aywxecjdzew6hylgvsesrxh6hy'
|
|
||||||
];
|
|
||||||
|
|
||||||
const unsigned = [
|
const unsigned = [
|
||||||
new U64('ffeeffee', 16),
|
new U64('ffeeffee', 16),
|
||||||
new U64('001fffeeffeeffee', 16),
|
new U64('001fffeeffeeffee', 16),
|
||||||
@ -122,10 +112,10 @@ describe('Utils', function() {
|
|||||||
assert.strictEqual(parseFloat('0.15645647') * 1e8, 15645646.999999998);
|
assert.strictEqual(parseFloat('0.15645647') * 1e8, 15645646.999999998);
|
||||||
assert.strictEqual(15645647 / 1e8, 0.15645647);
|
assert.strictEqual(15645647 / 1e8, 0.15645647);
|
||||||
|
|
||||||
assert.strictEqual(util.fromFixed('0.15645647', 8), 15645647);
|
assert.strictEqual(fixed.decode('0.15645647', 8), 15645647);
|
||||||
assert.strictEqual(util.toFixed(15645647, 8), '0.15645647');
|
assert.strictEqual(fixed.encode(15645647, 8), '0.15645647');
|
||||||
assert.strictEqual(util.fromFloat(0.15645647, 8), 15645647);
|
assert.strictEqual(fixed.fromFloat(0.15645647, 8), 15645647);
|
||||||
assert.strictEqual(util.toFloat(15645647, 8), 0.15645647);
|
assert.strictEqual(fixed.toFloat(15645647, 8), 0.15645647);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should write/read new varints', () => {
|
it('should write/read new varints', () => {
|
||||||
@ -254,10 +244,4 @@ describe('Utils', function() {
|
|||||||
assert.strictEqual(validator.bool('shouldBeTrue'), true);
|
assert.strictEqual(validator.bool('shouldBeTrue'), true);
|
||||||
assert.strictEqual(validator.bool('shouldBeFalse'), false);
|
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