refactor: style for const/let and returns.
This commit is contained in:
parent
6f3988e861
commit
55cf07a871
@ -1,16 +1,17 @@
|
||||
{
|
||||
"extends": "eslint:recommended",
|
||||
"env": {
|
||||
"browser": true,
|
||||
"es6": true,
|
||||
"node": true,
|
||||
"mocha": true
|
||||
"mocha": true,
|
||||
"node": true
|
||||
},
|
||||
"extends": "eslint:recommended",
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 8
|
||||
},
|
||||
"rules": {
|
||||
"strict": 2,
|
||||
"consistent-return": "off",
|
||||
"func-name-matching": "off",
|
||||
"indent": ["error", 2, {
|
||||
"SwitchCase": 1,
|
||||
"CallExpression": {
|
||||
@ -18,28 +19,37 @@
|
||||
},
|
||||
"ArrayExpression": "off"
|
||||
}],
|
||||
"handle-callback-err": "off",
|
||||
"linebreak-style": ["error", "unix"],
|
||||
"quotes": ["error", "single"],
|
||||
"semi": ["error", "always"],
|
||||
"no-console": 0,
|
||||
"no-buffer-constructor": "error",
|
||||
"no-console": "off",
|
||||
"no-cond-assign": "off",
|
||||
"no-extra-semi": "off",
|
||||
"no-fallthrough": "off",
|
||||
"no-func-assign": "off",
|
||||
"no-param-reassign": "off",
|
||||
"no-shadow-restricted-names": "error",
|
||||
"no-tabs": "error",
|
||||
"no-unused-vars": ["error", {
|
||||
"vars": "all",
|
||||
"args": "none",
|
||||
"ignoreRestSiblings": false
|
||||
}],
|
||||
"no-func-assign": 0,
|
||||
"no-cond-assign": 0,
|
||||
"no-unreachable": 0,
|
||||
"no-fallthrough": 0,
|
||||
"no-useless-escape": 0,
|
||||
"no-unsafe-finally": 0,
|
||||
"no-extra-semi": 0,
|
||||
"handle-callback-err": 0,
|
||||
"no-buffer-constructor": 2,
|
||||
"no-tabs": 2,
|
||||
"no-use-before-define": ["error", {
|
||||
"functions": false,
|
||||
"classes": false
|
||||
}],
|
||||
"no-unreachable": "off",
|
||||
"no-useless-escape": "off",
|
||||
"no-unsafe-finally": "off",
|
||||
"no-var": "error",
|
||||
"prefer-const": ["error", {
|
||||
"destructuring": "all",
|
||||
"ignoreReadBeforeAssign": true
|
||||
}]
|
||||
}],
|
||||
"quotes": ["error", "single"],
|
||||
"semi": ["error", "always"],
|
||||
"strict": "error",
|
||||
"valid-jsdoc": "error"
|
||||
}
|
||||
}
|
||||
|
||||
@ -19,6 +19,7 @@ const btx = { tx: block.txs[397], view: new CoinView() };
|
||||
const tx3 = parseTX('../test/data/tx3.hex');
|
||||
const hex = fs.readFileSync(`${__dirname}/../test/data/wtx.hex`, 'utf8');
|
||||
const raw = Buffer.from(hex.trim(), 'hex');
|
||||
const tx = TX.fromRaw(raw);
|
||||
|
||||
{
|
||||
const tx = json.txs[397];
|
||||
@ -153,25 +154,25 @@ for (let i = 0; i < 100; i++) {
|
||||
});
|
||||
}
|
||||
|
||||
const tx = mtx.toTX();
|
||||
const tx2 = mtx.toTX();
|
||||
|
||||
{
|
||||
const end = bench('input hashes');
|
||||
for (let i = 0; i < 1000; i++)
|
||||
tx.getInputHashes(null, 'hex');
|
||||
tx2.getInputHashes(null, 'hex');
|
||||
end(1000);
|
||||
}
|
||||
|
||||
{
|
||||
const end = bench('output hashes');
|
||||
for (let i = 0; i < 1000; i++)
|
||||
tx.getOutputHashes('hex');
|
||||
tx2.getOutputHashes('hex');
|
||||
end(1000);
|
||||
}
|
||||
|
||||
{
|
||||
const end = bench('all hashes');
|
||||
for (let i = 0; i < 1000; i++)
|
||||
tx.getHashes(null, 'hex');
|
||||
tx2.getHashes(null, 'hex');
|
||||
end(1000);
|
||||
}
|
||||
|
||||
@ -24,6 +24,7 @@ const walletdb = new WalletDB({
|
||||
|
||||
const wallet = await walletdb.create();
|
||||
const addrs = [];
|
||||
let tx;
|
||||
|
||||
// Accounts
|
||||
{
|
||||
@ -65,7 +66,7 @@ const walletdb = new WalletDB({
|
||||
mtx.addOutput(addrs[(i + 1) % addrs.length], 50460);
|
||||
mtx.addOutput(addrs[(i + 2) % addrs.length], 50460);
|
||||
mtx.addOutput(addrs[(i + 3) % addrs.length], 50460);
|
||||
const tx = mtx.toTX();
|
||||
tx = mtx.toTX();
|
||||
|
||||
jobs.push(walletdb.addTX(tx));
|
||||
}
|
||||
@ -88,7 +89,7 @@ const walletdb = new WalletDB({
|
||||
mtx.addOutput(addrs[(i + 1) % addrs.length], 50460);
|
||||
mtx.addOutput(addrs[(i + 2) % addrs.length], 50460);
|
||||
mtx.addOutput(addrs[(i + 3) % addrs.length], 50460);
|
||||
const tx = mtx.toTX();
|
||||
tx = mtx.toTX();
|
||||
|
||||
jobs.push(walletdb.addTX(tx));
|
||||
}
|
||||
|
||||
9
bin/node
9
bin/node
@ -19,10 +19,9 @@ if (process.argv.indexOf('--version') !== -1
|
||||
throw new Error('Could not exit.');
|
||||
}
|
||||
|
||||
const bcoin = require('../');
|
||||
const plugin = require('../lib/wallet/plugin');
|
||||
const FullNode = require('../lib/node/fullnode');
|
||||
|
||||
const node = new bcoin.fullnode({
|
||||
const node = new FullNode({
|
||||
config: true,
|
||||
argv: true,
|
||||
env: true,
|
||||
@ -37,8 +36,10 @@ const node = new bcoin.fullnode({
|
||||
});
|
||||
|
||||
// Temporary hack
|
||||
if (!node.config.bool('no-wallet') && !node.has('walletdb'))
|
||||
if (!node.config.bool('no-wallet') && !node.has('walletdb')) {
|
||||
const plugin = require('../lib/wallet/plugin');
|
||||
node.use(plugin);
|
||||
}
|
||||
|
||||
process.on('unhandledRejection', (err, promise) => {
|
||||
throw err;
|
||||
|
||||
14
bin/spvnode
14
bin/spvnode
@ -5,11 +5,11 @@
|
||||
process.title = 'bcoin';
|
||||
|
||||
const assert = require('assert');
|
||||
const bcoin = require('../');
|
||||
const plugin = require('../lib/wallet/plugin');
|
||||
const util = bcoin.util;
|
||||
const SPVNode = require('../lib/node/spvnode');
|
||||
const util = require('../lib/utils/util');
|
||||
const Outpoint = require('../lib/primitives/outpoint');
|
||||
|
||||
const node = bcoin.spvnode({
|
||||
const node = SPVNode({
|
||||
config: true,
|
||||
argv: true,
|
||||
env: true,
|
||||
@ -24,8 +24,10 @@ const node = bcoin.spvnode({
|
||||
});
|
||||
|
||||
// Temporary hack
|
||||
if (!node.has('walletdb'))
|
||||
if (!node.has('walletdb')) {
|
||||
const plugin = require('../lib/wallet/plugin');
|
||||
node.use(plugin);
|
||||
}
|
||||
|
||||
process.on('unhandledRejection', (err, promise) => {
|
||||
throw err;
|
||||
@ -38,7 +40,7 @@ process.on('unhandledRejection', (err, promise) => {
|
||||
|
||||
if (node.config.bool('test')) {
|
||||
node.pool.watchAddress('1VayNert3x1KzbpzMGt2qdqrAThiRovi8');
|
||||
node.pool.watchOutpoint(new bcoin.outpoint());
|
||||
node.pool.watchOutpoint(new Outpoint());
|
||||
node.on('block', (block) => {
|
||||
assert(block.txs.length >= 1);
|
||||
if (block.txs.length > 1)
|
||||
|
||||
@ -141,7 +141,7 @@ PaymentDetails.prototype.getData = function getData(enc) {
|
||||
let data = this.merchantData;
|
||||
|
||||
if (!data)
|
||||
return;
|
||||
return null;
|
||||
|
||||
if (!enc)
|
||||
return data;
|
||||
|
||||
@ -92,6 +92,8 @@ x509.getSubjectOID = function getSubjectOID(cert, oid) {
|
||||
if (entry.type === oid)
|
||||
return entry.value;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -350,7 +350,7 @@ Chain.prototype.verify = async function verify(block, prev, flags) {
|
||||
}
|
||||
|
||||
// Check the commitment hash for segwit.
|
||||
let commit = null;
|
||||
let commit;
|
||||
if (state.hasWitness()) {
|
||||
commit = block.getCommitmentHash();
|
||||
if (commit) {
|
||||
@ -581,11 +581,12 @@ Chain.prototype.verifyDuplicates = async function verifyDuplicates(block, prev,
|
||||
*/
|
||||
|
||||
Chain.prototype.verifyInputs = async function verifyInputs(block, prev, state) {
|
||||
const view = new CoinView();
|
||||
|
||||
if (this.options.spv)
|
||||
return view;
|
||||
|
||||
const interval = this.network.halvingInterval;
|
||||
const view = new CoinView();
|
||||
const height = prev.height + 1;
|
||||
const historical = prev.isHistorical();
|
||||
const jobs = [];
|
||||
@ -1598,7 +1599,7 @@ Chain.prototype.resolveOrphan = function resolveOrphan(hash) {
|
||||
const orphan = this.orphanPrev.get(hash);
|
||||
|
||||
if (!orphan)
|
||||
return;
|
||||
return null;
|
||||
|
||||
return this.removeOrphan(orphan);
|
||||
};
|
||||
@ -1626,8 +1627,8 @@ Chain.prototype.purgeOrphans = function purgeOrphans() {
|
||||
|
||||
Chain.prototype.limitOrphans = function limitOrphans() {
|
||||
const now = util.now();
|
||||
let oldest = null;
|
||||
|
||||
let oldest;
|
||||
for (const orphan of this.orphanMap.values()) {
|
||||
if (now < orphan.time + 60 * 60) {
|
||||
if (!oldest || orphan.time < oldest.time)
|
||||
@ -1896,9 +1897,9 @@ Chain.prototype._getLocator = async function getLocator(start) {
|
||||
hash = await this.db.getHash(height);
|
||||
assert(hash);
|
||||
} else {
|
||||
const entry = await entry.getAncestor(height);
|
||||
assert(entry);
|
||||
hash = entry.hash;
|
||||
const ancestor = await entry.getAncestor(height);
|
||||
assert(ancestor);
|
||||
hash = ancestor.hash;
|
||||
}
|
||||
|
||||
hashes.push(hash);
|
||||
|
||||
@ -309,7 +309,7 @@ ChainDB.prototype.getHash = async function getHash(height) {
|
||||
assert(typeof height === 'number');
|
||||
|
||||
if (height < 0)
|
||||
return;
|
||||
return null;
|
||||
|
||||
const entry = this.cacheHeight.get(height);
|
||||
|
||||
@ -319,7 +319,7 @@ ChainDB.prototype.getHash = async function getHash(height) {
|
||||
const hash = await this.db.get(layout.H(height));
|
||||
|
||||
if (!hash)
|
||||
return;
|
||||
return null;
|
||||
|
||||
return hash.toString('hex');
|
||||
};
|
||||
@ -335,26 +335,25 @@ ChainDB.prototype.getEntryByHeight = async function getEntryByHeight(height) {
|
||||
assert(typeof height === 'number');
|
||||
|
||||
if (height < 0)
|
||||
return;
|
||||
return null;
|
||||
|
||||
const cache = this.cacheHeight.get(height);
|
||||
|
||||
if (cache)
|
||||
return cache;
|
||||
|
||||
let hash = await this.db.get(layout.H(height));
|
||||
const data = await this.db.get(layout.H(height));
|
||||
|
||||
if (!hash)
|
||||
return;
|
||||
if (!data)
|
||||
return null;
|
||||
|
||||
hash = hash.toString('hex');
|
||||
const hash = data.toString('hex');
|
||||
|
||||
const state = this.chain.state;
|
||||
|
||||
const entry = await this.getEntryByHash(hash);
|
||||
|
||||
if (!entry)
|
||||
return;
|
||||
return null;
|
||||
|
||||
// By the time getEntry has completed,
|
||||
// a reorg may have occurred. This entry
|
||||
@ -376,7 +375,7 @@ ChainDB.prototype.getEntryByHash = async function getEntryByHash(hash) {
|
||||
assert(typeof hash === 'string');
|
||||
|
||||
if (hash === encoding.NULL_HASH)
|
||||
return;
|
||||
return null;
|
||||
|
||||
const cache = this.cacheHash.get(hash);
|
||||
|
||||
@ -386,7 +385,7 @@ ChainDB.prototype.getEntryByHash = async function getEntryByHash(hash) {
|
||||
const raw = await this.db.get(layout.e(hash));
|
||||
|
||||
if (!raw)
|
||||
return;
|
||||
return null;
|
||||
|
||||
const entry = ChainEntry.fromRaw(this.chain, raw);
|
||||
|
||||
@ -441,7 +440,7 @@ ChainDB.prototype.getState = async function getState() {
|
||||
const data = await this.db.get(layout.R);
|
||||
|
||||
if (!data)
|
||||
return;
|
||||
return null;
|
||||
|
||||
return ChainState.fromRaw(data);
|
||||
};
|
||||
@ -472,7 +471,7 @@ ChainDB.prototype.getFlags = async function getFlags() {
|
||||
const data = await this.db.get(layout.O);
|
||||
|
||||
if (!data)
|
||||
return;
|
||||
return null;
|
||||
|
||||
return ChainFlags.fromRaw(data);
|
||||
};
|
||||
@ -717,10 +716,11 @@ ChainDB.prototype.prune = async function prune(tip) {
|
||||
if (flags.prune)
|
||||
throw new Error('Chain is already pruned.');
|
||||
|
||||
const height = await this.getHeight(tip);
|
||||
|
||||
if (height <= pruneAfter + keepBlocks)
|
||||
return false;
|
||||
|
||||
const height = await this.getHeight(tip);
|
||||
const start = pruneAfter + 1;
|
||||
const end = height - keepBlocks;
|
||||
const batch = this.db.batch();
|
||||
@ -765,7 +765,7 @@ ChainDB.prototype.getNextHash = async function getNextHash(hash) {
|
||||
const data = await this.db.get(layout.n(hash));
|
||||
|
||||
if (!data)
|
||||
return;
|
||||
return null;
|
||||
|
||||
return data.toString('hex');
|
||||
};
|
||||
@ -788,12 +788,12 @@ ChainDB.prototype.isMainChain = async function isMainChain(hash) {
|
||||
if (hash === encoding.NULL_HASH)
|
||||
return false;
|
||||
|
||||
let entry = this.cacheHash.get(hash);
|
||||
const cacheHash = this.cacheHash.get(hash);
|
||||
|
||||
if (entry) {
|
||||
entry = this.cacheHeight.get(entry.height);
|
||||
if (entry)
|
||||
return entry.hash === hash;
|
||||
if (cacheHash) {
|
||||
const cacheHeight = this.cacheHeight.get(cacheHash.height);
|
||||
if (cacheHeight)
|
||||
return cacheHeight.hash === hash;
|
||||
}
|
||||
|
||||
if (await this.getNextHash(hash))
|
||||
@ -838,7 +838,7 @@ ChainDB.prototype.getTips = function getTips() {
|
||||
|
||||
ChainDB.prototype.readCoin = async function readCoin(prevout) {
|
||||
if (this.options.spv)
|
||||
return;
|
||||
return null;
|
||||
|
||||
const {hash, index} = prevout;
|
||||
const key = prevout.toKey();
|
||||
@ -852,7 +852,7 @@ ChainDB.prototype.readCoin = async function readCoin(prevout) {
|
||||
const raw = await this.db.get(layout.c(hash, index));
|
||||
|
||||
if (!raw)
|
||||
return;
|
||||
return null;
|
||||
|
||||
if (state === this.state)
|
||||
this.coinCache.set(key, raw);
|
||||
@ -873,7 +873,7 @@ ChainDB.prototype.getCoin = async function getCoin(hash, index) {
|
||||
const coin = await this.readCoin(prevout);
|
||||
|
||||
if (!coin)
|
||||
return;
|
||||
return null;
|
||||
|
||||
return coin.toCoin(prevout);
|
||||
};
|
||||
@ -971,7 +971,7 @@ ChainDB.prototype.getBlock = async function getBlock(hash) {
|
||||
const data = await this.getRawBlock(hash);
|
||||
|
||||
if (!data)
|
||||
return;
|
||||
return null;
|
||||
|
||||
return Block.fromRaw(data);
|
||||
};
|
||||
@ -985,12 +985,12 @@ ChainDB.prototype.getBlock = async function getBlock(hash) {
|
||||
|
||||
ChainDB.prototype.getRawBlock = async function getRawBlock(block) {
|
||||
if (this.options.spv)
|
||||
return;
|
||||
return null;
|
||||
|
||||
const hash = await this.getHash(block);
|
||||
|
||||
if (!hash)
|
||||
return;
|
||||
return null;
|
||||
|
||||
return await this.db.get(layout.b(hash));
|
||||
};
|
||||
@ -1033,12 +1033,12 @@ ChainDB.prototype.getBlockView = async function getBlockView(block) {
|
||||
|
||||
ChainDB.prototype.getMeta = async function getMeta(hash) {
|
||||
if (!this.options.indexTX)
|
||||
return;
|
||||
return null;
|
||||
|
||||
const data = await this.db.get(layout.t(hash));
|
||||
|
||||
if (!data)
|
||||
return;
|
||||
return null;
|
||||
|
||||
return TXMeta.fromRaw(data);
|
||||
};
|
||||
@ -1052,8 +1052,10 @@ ChainDB.prototype.getMeta = async function getMeta(hash) {
|
||||
|
||||
ChainDB.prototype.getTX = async function getTX(hash) {
|
||||
const meta = await this.getMeta(hash);
|
||||
|
||||
if (!meta)
|
||||
return;
|
||||
return null;
|
||||
|
||||
return meta.tx;
|
||||
};
|
||||
|
||||
@ -1064,7 +1066,7 @@ ChainDB.prototype.getTX = async function getTX(hash) {
|
||||
|
||||
ChainDB.prototype.hasTX = function hasTX(hash) {
|
||||
if (!this.options.indexTX)
|
||||
return Promise.resolve();
|
||||
return Promise.resolve(false);
|
||||
|
||||
return this.db.has(layout.t(hash));
|
||||
};
|
||||
@ -1077,14 +1079,14 @@ ChainDB.prototype.hasTX = function hasTX(hash) {
|
||||
*/
|
||||
|
||||
ChainDB.prototype.getCoinsByAddress = async function getCoinsByAddress(addrs) {
|
||||
const coins = [];
|
||||
|
||||
if (!this.options.indexAddress)
|
||||
return coins;
|
||||
return [];
|
||||
|
||||
if (!Array.isArray(addrs))
|
||||
addrs = [addrs];
|
||||
|
||||
const coins = [];
|
||||
|
||||
for (const addr of addrs) {
|
||||
const hash = Address.getHash(addr);
|
||||
|
||||
@ -1112,11 +1114,11 @@ ChainDB.prototype.getCoinsByAddress = async function getCoinsByAddress(addrs) {
|
||||
*/
|
||||
|
||||
ChainDB.prototype.getHashesByAddress = async function getHashesByAddress(addrs) {
|
||||
const hashes = Object.create(null);
|
||||
|
||||
if (!this.options.indexTX || !this.options.indexAddress)
|
||||
return [];
|
||||
|
||||
const hashes = Object.create(null);
|
||||
|
||||
for (const addr of addrs) {
|
||||
const hash = Address.getHash(addr);
|
||||
|
||||
@ -1158,15 +1160,14 @@ ChainDB.prototype.getTXByAddress = async function getTXByAddress(addrs) {
|
||||
*/
|
||||
|
||||
ChainDB.prototype.getMetaByAddress = async function getTXByAddress(addrs) {
|
||||
const txs = [];
|
||||
|
||||
if (!this.options.indexTX || !this.options.indexAddress)
|
||||
return txs;
|
||||
return [];
|
||||
|
||||
if (!Array.isArray(addrs))
|
||||
addrs = [addrs];
|
||||
|
||||
const hashes = await this.getHashesByAddress(addrs);
|
||||
const txs = [];
|
||||
|
||||
for (const hash of hashes) {
|
||||
const tx = await this.getMeta(hash);
|
||||
@ -1638,7 +1639,7 @@ ChainDB.prototype.saveBlock = async function saveBlock(entry, block, view) {
|
||||
|
||||
ChainDB.prototype.removeBlock = async function removeBlock(entry) {
|
||||
if (this.options.spv)
|
||||
return;
|
||||
return new CoinView();
|
||||
|
||||
const block = await this.getBlock(entry.hash);
|
||||
|
||||
@ -1734,10 +1735,11 @@ ChainDB.prototype.connectBlock = async function connectBlock(entry, block, view)
|
||||
*/
|
||||
|
||||
ChainDB.prototype.disconnectBlock = async function disconnectBlock(entry, block) {
|
||||
const view = new CoinView();
|
||||
|
||||
if (this.options.spv)
|
||||
return view;
|
||||
|
||||
const view = new CoinView();
|
||||
const hash = block.hash();
|
||||
const undo = await this.getUndoCoins(hash);
|
||||
|
||||
|
||||
@ -130,8 +130,10 @@ ChainEntry.fromOptions = function fromOptions(chain, options, prev) {
|
||||
|
||||
ChainEntry.prototype.getProof = function getProof() {
|
||||
const target = consensus.fromCompact(this.bits);
|
||||
|
||||
if (target.isNeg() || target.cmpn(0) === 0)
|
||||
return new BN(0);
|
||||
|
||||
return ChainEntry.MAX_CHAINWORK.div(target.iaddn(1));
|
||||
};
|
||||
|
||||
@ -194,7 +196,7 @@ ChainEntry.prototype.isMainChain = async function isMainChain() {
|
||||
|
||||
ChainEntry.prototype.getAncestor = async function getAncestor(height) {
|
||||
if (height < 0)
|
||||
return;
|
||||
return null;
|
||||
|
||||
assert(height >= 0);
|
||||
assert(height <= this.height);
|
||||
@ -237,8 +239,10 @@ ChainEntry.prototype.getPrevCache = function getPrevCache() {
|
||||
|
||||
ChainEntry.prototype.getNext = async function getNext() {
|
||||
const hash = await this.chain.db.getNextHash(this.hash);
|
||||
|
||||
if (!hash)
|
||||
return;
|
||||
return null;
|
||||
|
||||
return await this.chain.db.getEntry(hash);
|
||||
};
|
||||
|
||||
@ -252,11 +256,11 @@ ChainEntry.prototype.getNextEntry = async function getNextEntry() {
|
||||
const entry = await this.chain.db.getEntry(this.height + 1);
|
||||
|
||||
if (!entry)
|
||||
return;
|
||||
return null;
|
||||
|
||||
// Not on main chain.
|
||||
if (entry.prevBlock !== this.hash)
|
||||
return;
|
||||
return null;
|
||||
|
||||
return entry;
|
||||
};
|
||||
|
||||
@ -75,10 +75,9 @@ const layout = {
|
||||
return key.slice(1, 65);
|
||||
},
|
||||
Cc: function Cc(key) {
|
||||
let hash, index;
|
||||
|
||||
assert(typeof key === 'string');
|
||||
|
||||
let hash, index;
|
||||
if (key.length === 139) {
|
||||
hash = key.slice(65, 129);
|
||||
index = +key.slice(129);
|
||||
|
||||
@ -76,11 +76,11 @@ const layout = {
|
||||
},
|
||||
T: function T(addr, hash) {
|
||||
let len = addr.length;
|
||||
let key;
|
||||
|
||||
if (typeof addr === 'string')
|
||||
len /= 2;
|
||||
|
||||
let key;
|
||||
if (len === 32) {
|
||||
key = Buffer.allocUnsafe(65);
|
||||
key[0] = 0xab; // W + T
|
||||
@ -99,13 +99,13 @@ const layout = {
|
||||
},
|
||||
C: function C(addr, hash, index) {
|
||||
let len = addr.length;
|
||||
let key;
|
||||
|
||||
assert(typeof index === 'number');
|
||||
|
||||
if (typeof addr === 'string')
|
||||
len /= 2;
|
||||
|
||||
let key;
|
||||
if (len === 32) {
|
||||
key = Buffer.allocUnsafe(69);
|
||||
key[0] = 0x9a; // W + C
|
||||
@ -130,10 +130,9 @@ const layout = {
|
||||
return key.toString('hex', 1, 33);
|
||||
},
|
||||
Cc: function Cc(key) {
|
||||
let hash, index;
|
||||
|
||||
assert(Buffer.isBuffer(key));
|
||||
|
||||
let hash, index;
|
||||
if (key.length === 69) {
|
||||
hash = key.toString('hex', 33, 65);
|
||||
index = key.readUInt32BE(65, 0);
|
||||
@ -165,7 +164,7 @@ function write(data, str, off) {
|
||||
if (Buffer.isBuffer(str))
|
||||
return str.copy(data, off);
|
||||
assert(typeof str === 'string');
|
||||
data.write(str, off, 'hex');
|
||||
return data.write(str, off, 'hex');
|
||||
}
|
||||
|
||||
function pair(prefix, hash) {
|
||||
|
||||
@ -334,6 +334,10 @@ function decompressKey(key) {
|
||||
return out;
|
||||
}
|
||||
|
||||
// Make eslint happy.
|
||||
compressValue;
|
||||
decompressValue;
|
||||
|
||||
/*
|
||||
* Expose
|
||||
*/
|
||||
|
||||
@ -123,8 +123,7 @@ AEAD.prototype.auth = function auth(data) {
|
||||
|
||||
AEAD.prototype.finish = function finish() {
|
||||
const len = Buffer.allocUnsafe(16);
|
||||
let lo = 0;
|
||||
let hi = 0;
|
||||
let lo, hi;
|
||||
|
||||
// The RFC says these are supposed to be
|
||||
// uint32le, but their own fucking test
|
||||
|
||||
@ -8,6 +8,8 @@
|
||||
* Entered into the public domain by Vincent Rijmen.
|
||||
*/
|
||||
|
||||
/* eslint no-use-before-define: "off" */
|
||||
|
||||
'use strict';
|
||||
|
||||
const assert = require('assert');
|
||||
|
||||
@ -6,6 +6,8 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
const assert = require('assert');
|
||||
|
||||
/**
|
||||
* memcmp in constant time (can only return true or false).
|
||||
* This protects us against timing attacks when
|
||||
@ -19,11 +21,8 @@
|
||||
*/
|
||||
|
||||
module.exports = function ccmp(a, b) {
|
||||
if (!Buffer.isBuffer(a))
|
||||
return false;
|
||||
|
||||
if (!Buffer.isBuffer(b))
|
||||
return false;
|
||||
assert(Buffer.isBuffer(a));
|
||||
assert(Buffer.isBuffer(b));
|
||||
|
||||
if (b.length === 0)
|
||||
return a.length === 0;
|
||||
|
||||
@ -95,12 +95,12 @@ HmacDRBG.prototype.update = function update(seed) {
|
||||
};
|
||||
|
||||
HmacDRBG.prototype.generate = function generate(len) {
|
||||
const data = Buffer.allocUnsafe(len);
|
||||
let pos = 0;
|
||||
|
||||
if (this.rounds > RESEED_INTERVAL)
|
||||
throw new Error('Reseed is required.');
|
||||
|
||||
const data = Buffer.allocUnsafe(len);
|
||||
let pos = 0;
|
||||
|
||||
while (pos < len) {
|
||||
this.V = digest.hmac(HASH_ALG, this.V, this.K);
|
||||
this.V.copy(data, pos);
|
||||
|
||||
@ -155,15 +155,21 @@ Poly1305.prototype.update = function update(data) {
|
||||
// handle leftover
|
||||
if (this.leftover) {
|
||||
let want = 16 - this.leftover;
|
||||
|
||||
if (want > bytes)
|
||||
want = bytes;
|
||||
|
||||
for (let i = 0; i < want; i++)
|
||||
this.buffer[this.leftover + i] = data[m + i];
|
||||
|
||||
bytes -= want;
|
||||
m += want;
|
||||
|
||||
this.leftover += want;
|
||||
|
||||
if (this.leftover < 16)
|
||||
return;
|
||||
|
||||
this.blocks(this.buffer, 16, 0);
|
||||
this.leftover = 0;
|
||||
}
|
||||
@ -262,8 +268,10 @@ Poly1305.prototype.finish = function finish() {
|
||||
// zero out the state
|
||||
for (let i = 0; i < 10; i++)
|
||||
this.h[i] = 0;
|
||||
|
||||
for (let i = 0; i < 10; i++)
|
||||
this.r[i] = 0;
|
||||
|
||||
for (let i = 0; i < 8; i++)
|
||||
this.pad[i] = 0;
|
||||
|
||||
|
||||
@ -101,12 +101,12 @@ schnorr.sign = function sign(msg, key, pubNonce) {
|
||||
const prv = new BN(key);
|
||||
const drbg = schnorr.drbg(msg, key, pubNonce);
|
||||
const len = curve.n.byteLength();
|
||||
let pn = null;
|
||||
let sig = null;
|
||||
|
||||
let pn;
|
||||
if (pubNonce)
|
||||
pn = curve.decodePoint(pubNonce);
|
||||
|
||||
let sig;
|
||||
while (!sig) {
|
||||
const k = new BN(drbg.generate(len));
|
||||
sig = schnorr.trySign(msg, prv, k, pn);
|
||||
@ -210,8 +210,7 @@ schnorr.recover = function recover(signature, msg) {
|
||||
|
||||
schnorr.combineSigs = function combineSigs(sigs) {
|
||||
let s = new BN(0);
|
||||
let r = null;
|
||||
let last = null;
|
||||
let r, last;
|
||||
|
||||
for (let i = 0; i < sigs.length; i++) {
|
||||
const sig = new Signature(sigs[i]);
|
||||
@ -325,8 +324,8 @@ schnorr.drbg = function drbg(msg, priv, data) {
|
||||
schnorr.generateNoncePair = function generateNoncePair(msg, priv, data) {
|
||||
const drbg = schnorr.drbg(msg, priv, data);
|
||||
const len = curve.n.byteLength();
|
||||
let k;
|
||||
|
||||
let k;
|
||||
for (;;) {
|
||||
k = new BN(drbg.generate(len));
|
||||
|
||||
|
||||
@ -146,7 +146,7 @@ ec.recover = function recover(msg, sig, j, compress) {
|
||||
try {
|
||||
point = secp256k1.recoverPubKey(msg, sig, j);
|
||||
} catch (e) {
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
|
||||
return Buffer.from(point.encode('array', compress));
|
||||
@ -191,7 +191,8 @@ ec.verify = function verify(msg, sig, key) {
|
||||
|
||||
ec.publicKeyVerify = function publicKeyVerify(key) {
|
||||
try {
|
||||
return secp256k1.keyPair({ pub: key }).validate();
|
||||
const pub = secp256k1.keyPair({ pub: key });
|
||||
return pub.validate();
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
@ -324,13 +325,14 @@ function normalizeLength(sig) {
|
||||
|
||||
function getLength(buf, p) {
|
||||
const initial = buf[p.place++];
|
||||
const len = initial & 0xf;
|
||||
let off = p.place;
|
||||
let val = 0;
|
||||
|
||||
if (!(initial & 0x80))
|
||||
return initial;
|
||||
|
||||
const len = initial & 0xf;
|
||||
let off = p.place;
|
||||
let val = 0;
|
||||
|
||||
for (let i = 0; i < len; i++, off++) {
|
||||
val <<= 8;
|
||||
val |= buf[off];
|
||||
|
||||
@ -127,13 +127,13 @@ ec.recover = function recover(msg, sig, j, compress) {
|
||||
try {
|
||||
sig = secp256k1.signatureImport(sig);
|
||||
} catch (e) {
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
key = secp256k1.recover(msg, sig, j, compress);
|
||||
} catch (e) {
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
|
||||
return key;
|
||||
@ -195,13 +195,11 @@ ec.privateKeyVerify = function privateKeyVerify(key) {
|
||||
*/
|
||||
|
||||
ec.sign = function sign(msg, key) {
|
||||
let sig;
|
||||
|
||||
assert(Buffer.isBuffer(msg));
|
||||
assert(Buffer.isBuffer(key));
|
||||
|
||||
// Sign message
|
||||
sig = secp256k1.sign(msg, key);
|
||||
let sig = secp256k1.sign(msg, key);
|
||||
|
||||
// Ensure low S value
|
||||
sig = secp256k1.signatureNormalize(sig.signature);
|
||||
@ -239,10 +237,10 @@ ec.toDER = function toDER(sig) {
|
||||
*/
|
||||
|
||||
ec.isLowS = function isLowS(sig) {
|
||||
let rs, s;
|
||||
let s;
|
||||
|
||||
try {
|
||||
rs = secp256k1.signatureImport(sig);
|
||||
const rs = secp256k1.signatureImport(sig);
|
||||
s = rs.slice(32, 64);
|
||||
} catch (e) {
|
||||
return false;
|
||||
|
||||
@ -167,6 +167,7 @@ SHA256.prototype._finish = function _finish(out) {
|
||||
*/
|
||||
|
||||
SHA256.prototype.transform = function transform(chunk, pos) {
|
||||
const w = this.w;
|
||||
let a = this.s[0];
|
||||
let b = this.s[1];
|
||||
let c = this.s[2];
|
||||
@ -175,7 +176,6 @@ SHA256.prototype.transform = function transform(chunk, pos) {
|
||||
let f = this.s[5];
|
||||
let g = this.s[6];
|
||||
let h = this.s[7];
|
||||
const w = this.w;
|
||||
let i = 0;
|
||||
|
||||
for (; i < 16; i++)
|
||||
@ -185,13 +185,11 @@ SHA256.prototype.transform = function transform(chunk, pos) {
|
||||
w[i] = sigma1(w[i - 2]) + w[i - 7] + sigma0(w[i - 15]) + w[i - 16];
|
||||
|
||||
for (i = 0; i < 64; i++) {
|
||||
let t1, t2;
|
||||
|
||||
t1 = h + Sigma1(e);
|
||||
let t1 = h + Sigma1(e);
|
||||
t1 += Ch(e, f, g);
|
||||
t1 += K[i] + w[i];
|
||||
|
||||
t2 = Sigma0(a);
|
||||
let t2 = Sigma0(a);
|
||||
t2 += Maj(a, b, c);
|
||||
|
||||
h = g;
|
||||
|
||||
@ -33,7 +33,6 @@ function siphash24(data, key, shift) {
|
||||
const f1 = U64(0, 0xff);
|
||||
const k0 = U64.fromRaw(key, 0);
|
||||
const k1 = U64.fromRaw(key, 8);
|
||||
let p = 0;
|
||||
|
||||
// Init
|
||||
const v0 = c0.ixor(k0);
|
||||
@ -42,6 +41,7 @@ function siphash24(data, key, shift) {
|
||||
const v3 = c3.ixor(k1);
|
||||
|
||||
// Blocks
|
||||
let p = 0;
|
||||
for (let i = 0; i < blocks; i++) {
|
||||
const d = U64.fromRaw(data, p);
|
||||
p += 8;
|
||||
|
||||
@ -271,7 +271,7 @@ LowlevelUp.prototype.get = function get(key) {
|
||||
this.binding.get(key, (err, result) => {
|
||||
if (err) {
|
||||
if (isNotFound(err)) {
|
||||
resolve();
|
||||
resolve(null);
|
||||
return;
|
||||
}
|
||||
reject(err);
|
||||
|
||||
@ -45,7 +45,7 @@ MemDB.prototype.search = function search(key) {
|
||||
const node = this.tree.search(key);
|
||||
|
||||
if (!node)
|
||||
return;
|
||||
return undefined;
|
||||
|
||||
return node.value;
|
||||
};
|
||||
@ -449,13 +449,13 @@ Iterator.prototype.init = function init() {
|
||||
Iterator.prototype.next = function next(callback) {
|
||||
const options = this.options;
|
||||
const iter = this.iter;
|
||||
let key, value, result;
|
||||
|
||||
if (!this.iter) {
|
||||
setImmediate(() => callback(new Error('Cannot call next.')));
|
||||
return;
|
||||
}
|
||||
|
||||
let result;
|
||||
if (options.reverse) {
|
||||
result = iter.prev();
|
||||
|
||||
@ -499,8 +499,8 @@ Iterator.prototype.next = function next(callback) {
|
||||
this.total += 1;
|
||||
}
|
||||
|
||||
key = iter.key;
|
||||
value = iter.value;
|
||||
let key = iter.key;
|
||||
let value = iter.value;
|
||||
|
||||
if (!options.keys)
|
||||
key = DUMMY;
|
||||
|
||||
@ -65,13 +65,12 @@ common.cache = new LRU(500);
|
||||
*/
|
||||
|
||||
common.parsePath = function parsePath(path, max) {
|
||||
const parts = path.split('/');
|
||||
const root = parts.shift();
|
||||
const result = [];
|
||||
|
||||
if (max == null)
|
||||
max = common.MAX_INDEX;
|
||||
|
||||
const parts = path.split('/');
|
||||
const root = parts.shift();
|
||||
|
||||
if (root !== 'm'
|
||||
&& root !== 'M'
|
||||
&& root !== 'm\''
|
||||
@ -79,6 +78,8 @@ common.parsePath = function parsePath(path, max) {
|
||||
throw new Error('Bad path root.');
|
||||
}
|
||||
|
||||
const result = [];
|
||||
|
||||
for (let index of parts) {
|
||||
const hardened = index[index.length - 1] === '\'';
|
||||
|
||||
|
||||
@ -177,11 +177,6 @@ Mnemonic.prototype.getPhrase = function getPhrase() {
|
||||
if (this.phrase)
|
||||
return this.phrase;
|
||||
|
||||
let phrase = [];
|
||||
const wordlist = Mnemonic.getWordlist(this.language);
|
||||
|
||||
const ent = this.getEntropy();
|
||||
|
||||
// Include the first `ENT / 32` bits
|
||||
// of the hash (the checksum).
|
||||
const bits = this.bits + (this.bits / 32);
|
||||
@ -189,12 +184,16 @@ Mnemonic.prototype.getPhrase = function getPhrase() {
|
||||
// Append the hash to the entropy to
|
||||
// make things easy when grabbing
|
||||
// the checksum bits.
|
||||
const ent = this.getEntropy();
|
||||
const entropy = Buffer.allocUnsafe(Math.ceil(bits / 8));
|
||||
ent.copy(entropy, 0);
|
||||
digest.sha256(ent).copy(entropy, ent.length);
|
||||
|
||||
// Build the mnemonic by reading
|
||||
// 11 bit indexes from the entropy.
|
||||
const wordlist = Mnemonic.getWordlist(this.language);
|
||||
|
||||
let phrase = [];
|
||||
for (let i = 0; i < bits / 11; i++) {
|
||||
let index = 0;
|
||||
for (let j = 0; j < 11; j++) {
|
||||
|
||||
@ -413,11 +413,9 @@ HDPrivateKey.prototype.equal = function equal(obj) {
|
||||
*/
|
||||
|
||||
HDPrivateKey.prototype.compare = function compare(key) {
|
||||
let cmp;
|
||||
|
||||
assert(HDPrivateKey.isHDPrivateKey(key));
|
||||
|
||||
cmp = this.depth - key.depth;
|
||||
let cmp = this.depth - key.depth;
|
||||
|
||||
if (cmp !== 0)
|
||||
return cmp;
|
||||
|
||||
@ -335,11 +335,9 @@ HDPublicKey.prototype.equal = function equal(obj) {
|
||||
*/
|
||||
|
||||
HDPublicKey.prototype.compare = function compare(key) {
|
||||
let cmp;
|
||||
|
||||
assert(HDPublicKey.isHDPublicKey(key));
|
||||
|
||||
cmp = this.depth - key.depth;
|
||||
let cmp = this.depth - key.depth;
|
||||
|
||||
if (cmp !== 0)
|
||||
return cmp;
|
||||
|
||||
@ -186,16 +186,22 @@ HTTPBase.prototype.basicAuth = function basicAuth(options) {
|
||||
let realm = options.realm;
|
||||
|
||||
if (user) {
|
||||
if (typeof user === 'string')
|
||||
if (typeof user === 'string') {
|
||||
assert(user.length <= 255, 'Username too long.');
|
||||
user = Buffer.from(user, 'utf8');
|
||||
}
|
||||
assert(Buffer.isBuffer(user));
|
||||
assert(user.length <= 255, 'Username too long.');
|
||||
user = digest.hash256(user);
|
||||
}
|
||||
|
||||
if (typeof pass === 'string')
|
||||
if (typeof pass === 'string') {
|
||||
assert(pass.length <= 255, 'Password too long.');
|
||||
pass = Buffer.from(pass, 'utf8');
|
||||
}
|
||||
|
||||
assert(Buffer.isBuffer(pass));
|
||||
assert(pass.length <= 255, 'Password too long.');
|
||||
pass = digest.hash256(pass);
|
||||
|
||||
if (!realm)
|
||||
@ -215,6 +221,9 @@ HTTPBase.prototype.basicAuth = function basicAuth(options) {
|
||||
if (!hdr)
|
||||
return fail(res);
|
||||
|
||||
if (hdr.length > 1000)
|
||||
return fail(res);
|
||||
|
||||
const parts = hdr.split(' ');
|
||||
|
||||
if (parts.length !== 2)
|
||||
@ -230,6 +239,9 @@ HTTPBase.prototype.basicAuth = function basicAuth(options) {
|
||||
const password = items.join(':');
|
||||
|
||||
if (user) {
|
||||
if (username.length > 255)
|
||||
return fail(res);
|
||||
|
||||
const raw = Buffer.from(username, 'utf8');
|
||||
const hash = digest.hash256(raw);
|
||||
|
||||
@ -237,6 +249,9 @@ HTTPBase.prototype.basicAuth = function basicAuth(options) {
|
||||
return fail(res);
|
||||
}
|
||||
|
||||
if (password.length > 255)
|
||||
return fail(res);
|
||||
|
||||
const raw = Buffer.from(password, 'utf8');
|
||||
const hash = digest.hash256(raw);
|
||||
|
||||
@ -345,7 +360,9 @@ HTTPBase.prototype._readBody = function _readBody(req, enc, options, resolve, re
|
||||
reject(new Error('Request body timed out.'));
|
||||
}, options.timeout);
|
||||
|
||||
let cleanup = () => {
|
||||
/* eslint no-use-before-define: "off" */
|
||||
|
||||
const cleanup = () => {
|
||||
req.removeListener('data', onData);
|
||||
req.removeListener('error', onError);
|
||||
req.removeListener('end', onEnd);
|
||||
@ -356,7 +373,7 @@ HTTPBase.prototype._readBody = function _readBody(req, enc, options, resolve, re
|
||||
}
|
||||
};
|
||||
|
||||
let onData = (data) => {
|
||||
const onData = (data) => {
|
||||
total += data.length;
|
||||
hasData = true;
|
||||
|
||||
@ -368,12 +385,12 @@ HTTPBase.prototype._readBody = function _readBody(req, enc, options, resolve, re
|
||||
body += decode.write(data);
|
||||
};
|
||||
|
||||
let onError = (err) => {
|
||||
const onError = (err) => {
|
||||
cleanup();
|
||||
reject(err);
|
||||
};
|
||||
|
||||
let onEnd = () => {
|
||||
const onEnd = () => {
|
||||
cleanup();
|
||||
|
||||
if (hasData) {
|
||||
@ -493,11 +510,10 @@ HTTPBase.prototype.handleHooks = async function handleHooks(req, res) {
|
||||
*/
|
||||
|
||||
HTTPBase.prototype._initSockets = function _initSockets() {
|
||||
let IOServer;
|
||||
|
||||
if (!this.config.sockets)
|
||||
return;
|
||||
|
||||
let IOServer;
|
||||
try {
|
||||
IOServer = require('socket.io');
|
||||
} catch (e) {
|
||||
@ -608,12 +624,13 @@ HTTPBase.prototype.removeSocket = function removeSocket(socket) {
|
||||
*/
|
||||
|
||||
HTTPBase.prototype.joinChannel = function joinChannel(socket, name) {
|
||||
let list = this.channels.get(name);
|
||||
let item = socket.channels.get(name);
|
||||
|
||||
if (item)
|
||||
return;
|
||||
|
||||
let list = this.channels.get(name);
|
||||
|
||||
if (!list) {
|
||||
list = new List();
|
||||
this.channels.set(name, list);
|
||||
@ -633,12 +650,13 @@ HTTPBase.prototype.joinChannel = function joinChannel(socket, name) {
|
||||
*/
|
||||
|
||||
HTTPBase.prototype.leaveChannel = function leaveChannel(socket, name) {
|
||||
const list = this.channels.get(name);
|
||||
const item = socket.channels.get(name);
|
||||
|
||||
if (!item)
|
||||
return;
|
||||
|
||||
const list = this.channels.get(name);
|
||||
|
||||
assert(list);
|
||||
assert(list.remove(item));
|
||||
|
||||
@ -658,7 +676,7 @@ HTTPBase.prototype.channel = function channel(name) {
|
||||
const list = this.channels.get(name);
|
||||
|
||||
if (!list)
|
||||
return;
|
||||
return null;
|
||||
|
||||
assert(list.size > 0);
|
||||
|
||||
@ -1088,7 +1106,7 @@ Route.prototype.match = function _match(pathname) {
|
||||
const match = this.regex.exec(pathname);
|
||||
|
||||
if (!match)
|
||||
return;
|
||||
return null;
|
||||
|
||||
const params = Object.create(null);
|
||||
|
||||
@ -1135,7 +1153,7 @@ function Routes() {
|
||||
|
||||
Routes.prototype.getHandlers = function getHandlers(method) {
|
||||
if (!method)
|
||||
return;
|
||||
return null;
|
||||
|
||||
method = method.toUpperCase();
|
||||
|
||||
@ -1149,7 +1167,7 @@ Routes.prototype.getHandlers = function getHandlers(method) {
|
||||
case 'DELETE':
|
||||
return this.del;
|
||||
default:
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
@ -1535,13 +1553,14 @@ WebSocket.prototype.init = function init() {
|
||||
WebSocket.prototype.onevent = async function onevent(packet) {
|
||||
const args = (packet.data || []).slice();
|
||||
const type = args.shift() || '';
|
||||
let ack, result;
|
||||
|
||||
let ack;
|
||||
if (typeof args[args.length - 1] === 'function')
|
||||
ack = args.pop();
|
||||
else
|
||||
ack = this.socket.ack(packet.id);
|
||||
|
||||
let result;
|
||||
try {
|
||||
result = await this.fire(type, args);
|
||||
} catch (e) {
|
||||
@ -1568,7 +1587,7 @@ WebSocket.prototype.fire = async function fire(type, args) {
|
||||
const handler = this.hooks[type];
|
||||
|
||||
if (!handler)
|
||||
return;
|
||||
return undefined;
|
||||
|
||||
return await handler.call(this.context, args);
|
||||
};
|
||||
@ -1617,8 +1636,8 @@ function parsePairs(str, limit) {
|
||||
|
||||
for (const pair of parts) {
|
||||
const index = pair.indexOf('=');
|
||||
let key, value;
|
||||
|
||||
let key, value;
|
||||
if (index === -1) {
|
||||
key = pair;
|
||||
value = '';
|
||||
|
||||
@ -195,14 +195,13 @@ HTTPClient.prototype.onDisconnect = function onDisconnect() {
|
||||
*/
|
||||
|
||||
HTTPClient.prototype._request = async function _request(method, endpoint, json) {
|
||||
let query;
|
||||
|
||||
if (this.token) {
|
||||
if (!json)
|
||||
json = {};
|
||||
json.token = this.token;
|
||||
}
|
||||
|
||||
let query;
|
||||
if (json && method === 'get') {
|
||||
query = json;
|
||||
json = null;
|
||||
@ -221,7 +220,7 @@ HTTPClient.prototype._request = async function _request(method, endpoint, json)
|
||||
});
|
||||
|
||||
if (res.statusCode === 404)
|
||||
return;
|
||||
return null;
|
||||
|
||||
if (res.statusCode === 401)
|
||||
throw new Error('Unauthorized (bad API key).');
|
||||
@ -457,22 +456,6 @@ HTTPClient.prototype.leave = function leave(id) {
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Listen for events on all wallets.
|
||||
*/
|
||||
|
||||
HTTPClient.prototype.all = function all(token) {
|
||||
return this.join('!all', token);
|
||||
};
|
||||
|
||||
/**
|
||||
* Unlisten for events on all wallets.
|
||||
*/
|
||||
|
||||
HTTPClient.prototype.none = function none() {
|
||||
return this.leave('!all');
|
||||
};
|
||||
|
||||
/**
|
||||
* Get list of all wallet IDs.
|
||||
* @returns {Promise}
|
||||
@ -974,7 +957,7 @@ HTTPClient.prototype.createNested = function createNested(id, options) {
|
||||
|
||||
function toHex(obj) {
|
||||
if (!obj)
|
||||
return;
|
||||
return null;
|
||||
|
||||
if (obj.toRaw)
|
||||
obj = obj.toRaw();
|
||||
|
||||
@ -424,8 +424,6 @@ Request.prototype.finish = function finish(err) {
|
||||
};
|
||||
|
||||
Request.prototype._onResponse = function _onResponse(response) {
|
||||
let type = response.headers['content-type'];
|
||||
const length = response.headers['content-length'];
|
||||
const location = response.headers['location'];
|
||||
|
||||
if (location) {
|
||||
@ -440,13 +438,16 @@ Request.prototype._onResponse = function _onResponse(response) {
|
||||
return;
|
||||
}
|
||||
|
||||
type = parseType(type);
|
||||
const contentType = response.headers['content-type'];
|
||||
const type = parseType(contentType);
|
||||
|
||||
if (!this.options.isExpected(type)) {
|
||||
this.finish(new Error('Wrong content-type for response.'));
|
||||
return;
|
||||
}
|
||||
|
||||
const length = response.headers['content-length'];
|
||||
|
||||
if (this.options.isOverflow(length)) {
|
||||
this.finish(new Error('Response exceeded limit.'));
|
||||
return;
|
||||
|
||||
470
lib/http/rpc.js
470
lib/http/rpc.js
File diff suppressed because it is too large
Load Diff
@ -112,8 +112,6 @@ RPCBase.prototype.call = async function call(body, query) {
|
||||
}
|
||||
|
||||
for (const cmd of cmds) {
|
||||
let result;
|
||||
|
||||
if (!cmd || typeof cmd !== 'object') {
|
||||
out.push({
|
||||
result: null,
|
||||
@ -183,6 +181,7 @@ RPCBase.prototype.call = async function call(body, query) {
|
||||
cmd.method = 'getworklp';
|
||||
}
|
||||
|
||||
let result;
|
||||
try {
|
||||
result = await this.execute(cmd);
|
||||
} catch (err) {
|
||||
|
||||
@ -143,12 +143,12 @@ HTTPServer.prototype.initRouter = function initRouter() {
|
||||
this.get('/coin/address/:address', async (req, res) => {
|
||||
const valid = req.valid();
|
||||
const address = valid.str('address');
|
||||
const result = [];
|
||||
|
||||
enforce(address, 'Address is required.');
|
||||
enforce(!this.chain.options.spv, 'Cannot get coins in SPV mode.');
|
||||
|
||||
const coins = await this.node.getCoinsByAddress(address);
|
||||
const result = [];
|
||||
|
||||
for (const coin of coins)
|
||||
result.push(coin.getJSON(this.network));
|
||||
@ -180,12 +180,12 @@ HTTPServer.prototype.initRouter = function initRouter() {
|
||||
this.post('/coin/address', async (req, res) => {
|
||||
const valid = req.valid();
|
||||
const address = valid.array('addresses');
|
||||
const result = [];
|
||||
|
||||
enforce(address, 'Address is required.');
|
||||
enforce(!this.chain.options.spv, 'Cannot get coins in SPV mode.');
|
||||
|
||||
const coins = await this.node.getCoinsByAddress(address);
|
||||
const result = [];
|
||||
|
||||
for (const coin of coins)
|
||||
result.push(coin.getJSON(this.network));
|
||||
@ -217,12 +217,12 @@ HTTPServer.prototype.initRouter = function initRouter() {
|
||||
this.get('/tx/address/:address', async (req, res) => {
|
||||
const valid = req.valid();
|
||||
const address = valid.str('address');
|
||||
const result = [];
|
||||
|
||||
enforce(address, 'Address is required.');
|
||||
enforce(!this.chain.options.spv, 'Cannot get TX in SPV mode.');
|
||||
|
||||
const metas = await this.node.getMetaByAddress(address);
|
||||
const result = [];
|
||||
|
||||
for (const meta of metas) {
|
||||
const view = await this.node.getMetaView(meta);
|
||||
@ -236,12 +236,12 @@ HTTPServer.prototype.initRouter = function initRouter() {
|
||||
this.post('/tx/address', async (req, res) => {
|
||||
const valid = req.valid();
|
||||
const address = valid.array('address');
|
||||
const result = [];
|
||||
|
||||
enforce(address, 'Address is required.');
|
||||
enforce(!this.chain.options.spv, 'Cannot get TX in SPV mode.');
|
||||
|
||||
const metas = await this.node.getMetaByAddress(address);
|
||||
const result = [];
|
||||
|
||||
for (const meta of metas) {
|
||||
const view = await this.node.getMetaView(meta);
|
||||
@ -285,11 +285,10 @@ HTTPServer.prototype.initRouter = function initRouter() {
|
||||
|
||||
// Mempool snapshot
|
||||
this.get('/mempool', async (req, res) => {
|
||||
const result = [];
|
||||
|
||||
enforce(this.mempool, 'No mempool available.');
|
||||
|
||||
const hashes = this.mempool.getSnapshot();
|
||||
const result = [];
|
||||
|
||||
for (const hash of hashes)
|
||||
result.push(util.revHex(hash));
|
||||
@ -361,16 +360,21 @@ HTTPServer.prototype.initSockets = function initSockets() {
|
||||
|
||||
HTTPServer.prototype.handleSocket = function handleSocket(socket) {
|
||||
socket.hook('auth', (args) => {
|
||||
const valid = new Validator([args]);
|
||||
const hash = this.options.apiHash;
|
||||
const key = valid.str(0);
|
||||
|
||||
if (socket.auth)
|
||||
throw new Error('Already authed.');
|
||||
|
||||
if (!this.options.noAuth) {
|
||||
if (!ccmp(hash256(key), hash))
|
||||
throw new Error('Bad key.');
|
||||
const valid = new Validator([args]);
|
||||
const key = valid.str(0, '');
|
||||
|
||||
if (key.length > 255)
|
||||
throw new Error('Invalid API key.');
|
||||
|
||||
const data = Buffer.from(key, 'utf8');
|
||||
const hash = digest.hash256(data);
|
||||
|
||||
if (!ccmp(hash, this.options.apiHash))
|
||||
throw new Error('Invalid API key.');
|
||||
}
|
||||
|
||||
socket.auth = true;
|
||||
@ -593,10 +597,10 @@ HTTPServer.prototype.bindChain = function bindChain() {
|
||||
*/
|
||||
|
||||
HTTPServer.prototype.filterBlock = function filterBlock(socket, block) {
|
||||
const txs = [];
|
||||
|
||||
if (!socket.filter)
|
||||
return txs;
|
||||
return [];
|
||||
|
||||
const txs = [];
|
||||
|
||||
for (const tx of block.txs) {
|
||||
if (this.filterTX(socket, tx))
|
||||
@ -615,11 +619,11 @@ HTTPServer.prototype.filterBlock = function filterBlock(socket, block) {
|
||||
*/
|
||||
|
||||
HTTPServer.prototype.filterTX = function filterTX(socket, tx) {
|
||||
let found = false;
|
||||
|
||||
if (!socket.filter)
|
||||
return false;
|
||||
|
||||
let found = false;
|
||||
|
||||
for (let i = 0; i < tx.outputs.length; i++) {
|
||||
const output = tx.outputs[i];
|
||||
const hash = output.getHash();
|
||||
@ -697,7 +701,7 @@ function HTTPOptions(options) {
|
||||
this.logger = null;
|
||||
this.node = null;
|
||||
this.apiKey = base58.encode(random.randomBytes(20));
|
||||
this.apiHash = hash256(this.apiKey);
|
||||
this.apiHash = digest.hash256(Buffer.from(this.apiKey, 'utf8'));
|
||||
this.noAuth = false;
|
||||
|
||||
this.prefix = null;
|
||||
@ -736,10 +740,10 @@ HTTPOptions.prototype.fromOptions = function fromOptions(options) {
|
||||
if (options.apiKey != null) {
|
||||
assert(typeof options.apiKey === 'string',
|
||||
'API key must be a string.');
|
||||
assert(options.apiKey.length <= 200,
|
||||
'API key must be under 200 bytes.');
|
||||
assert(options.apiKey.length <= 255,
|
||||
'API key must be under 256 bytes.');
|
||||
this.apiKey = options.apiKey;
|
||||
this.apiHash = hash256(this.apiKey);
|
||||
this.apiHash = digest.hash256(Buffer.from(this.apiKey, 'utf8'));
|
||||
}
|
||||
|
||||
if (options.noAuth != null) {
|
||||
@ -804,16 +808,6 @@ HTTPOptions.fromOptions = function fromOptions(options) {
|
||||
* Helpers
|
||||
*/
|
||||
|
||||
function hash256(data) {
|
||||
if (typeof data !== 'string')
|
||||
return Buffer.alloc(0);
|
||||
|
||||
if (data.length > 200)
|
||||
return Buffer.alloc(0);
|
||||
|
||||
return digest.hash256(Buffer.from(data, 'utf8'));
|
||||
}
|
||||
|
||||
function enforce(value, msg) {
|
||||
if (!value) {
|
||||
const err = new Error(msg);
|
||||
|
||||
@ -447,14 +447,16 @@ PolicyEstimator.VERSION = 0;
|
||||
PolicyEstimator.prototype.init = function init() {
|
||||
const minFee = this.minTrackedFee;
|
||||
const minPri = this.minTrackedPri;
|
||||
|
||||
const fee = [];
|
||||
const priority = [];
|
||||
|
||||
for (let b = minFee; b <= MAX_FEERATE; b *= FEE_SPACING)
|
||||
fee.push(b);
|
||||
|
||||
fee.push(INF_FEERATE);
|
||||
|
||||
const priority = [];
|
||||
|
||||
for (let b = minPri; b <= MAX_PRIORITY; b *= PRI_SPACING)
|
||||
priority.push(b);
|
||||
|
||||
@ -694,7 +696,7 @@ PolicyEstimator.prototype.estimateFee = function estimateFee(target, smart) {
|
||||
'Too many confirmations for estimate.');
|
||||
|
||||
if (!smart) {
|
||||
rate = this.feeStats.estimateMedian(
|
||||
const rate = this.feeStats.estimateMedian(
|
||||
target, SUFFICIENT_FEETXS, MIN_SUCCESS_PCT,
|
||||
true, this.bestHeight);
|
||||
|
||||
|
||||
@ -41,7 +41,7 @@ function write(data, str, off) {
|
||||
if (Buffer.isBuffer(str))
|
||||
return str.copy(data, off);
|
||||
assert(typeof str === 'string');
|
||||
data.write(str, off, 'hex');
|
||||
return data.write(str, off, 'hex');
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@ -105,8 +105,6 @@ util.inherits(Mempool, AsyncObject);
|
||||
*/
|
||||
|
||||
Mempool.prototype._open = async function open() {
|
||||
const size = (this.options.maxSize / 1024).toFixed(2);
|
||||
|
||||
await this.chain.open();
|
||||
await this.cache.open();
|
||||
|
||||
@ -143,6 +141,8 @@ Mempool.prototype._open = async function open() {
|
||||
|
||||
this.tip = this.chain.tip.hash;
|
||||
|
||||
const size = (this.options.maxSize / 1024).toFixed(2);
|
||||
|
||||
this.logger.info('Mempool loaded (maxsize=%dkb).', size);
|
||||
};
|
||||
|
||||
@ -361,12 +361,13 @@ Mempool.prototype._reset = async function reset() {
|
||||
|
||||
Mempool.prototype.limitSize = function limitSize(added) {
|
||||
const maxSize = this.options.maxSize;
|
||||
const threshold = maxSize - (maxSize / 10);
|
||||
const expiryTime = this.options.expiryTime;
|
||||
|
||||
if (this.size <= maxSize)
|
||||
return false;
|
||||
|
||||
const threshold = maxSize - (maxSize / 10);
|
||||
const expiryTime = this.options.expiryTime;
|
||||
|
||||
const now = util.now();
|
||||
let start = util.hrtime();
|
||||
const queue = new Heap(cmpRate);
|
||||
@ -431,8 +432,10 @@ Mempool.prototype.limitSize = function limitSize(added) {
|
||||
|
||||
Mempool.prototype.getTX = function getTX(hash) {
|
||||
const entry = this.map.get(hash);
|
||||
|
||||
if (!entry)
|
||||
return;
|
||||
return null;
|
||||
|
||||
return entry.tx;
|
||||
};
|
||||
|
||||
@ -457,13 +460,13 @@ Mempool.prototype.getCoin = function getCoin(hash, index) {
|
||||
const entry = this.map.get(hash);
|
||||
|
||||
if (!entry)
|
||||
return;
|
||||
return null;
|
||||
|
||||
if (this.isSpent(hash, index))
|
||||
return;
|
||||
return null;
|
||||
|
||||
if (index >= entry.tx.outputs.length)
|
||||
return;
|
||||
return null;
|
||||
|
||||
return Coin.fromTX(entry.tx, index, -1);
|
||||
};
|
||||
@ -507,7 +510,7 @@ Mempool.prototype.getSpentTX = function getSpentTX(hash, index) {
|
||||
const entry = this.spents.get(key);
|
||||
|
||||
if (!entry)
|
||||
return;
|
||||
return null;
|
||||
|
||||
return entry.tx;
|
||||
};
|
||||
@ -519,11 +522,11 @@ Mempool.prototype.getSpentTX = function getSpentTX(hash, index) {
|
||||
*/
|
||||
|
||||
Mempool.prototype.getCoinsByAddress = function getCoinsByAddress(addrs) {
|
||||
const out = [];
|
||||
|
||||
if (!Array.isArray(addrs))
|
||||
addrs = [addrs];
|
||||
|
||||
const out = [];
|
||||
|
||||
for (const addr of addrs) {
|
||||
const hash = Address.getHash(addr, 'hex');
|
||||
const coins = this.coinIndex.get(hash);
|
||||
@ -542,11 +545,11 @@ Mempool.prototype.getCoinsByAddress = function getCoinsByAddress(addrs) {
|
||||
*/
|
||||
|
||||
Mempool.prototype.getTXByAddress = function getTXByAddress(addrs) {
|
||||
const out = [];
|
||||
|
||||
if (!Array.isArray(addrs))
|
||||
addrs = [addrs];
|
||||
|
||||
const out = [];
|
||||
|
||||
for (const addr of addrs) {
|
||||
const hash = Address.getHash(addr, 'hex');
|
||||
const txs = this.txIndex.get(hash);
|
||||
@ -565,11 +568,11 @@ Mempool.prototype.getTXByAddress = function getTXByAddress(addrs) {
|
||||
*/
|
||||
|
||||
Mempool.prototype.getMetaByAddress = function getMetaByAddress(addrs) {
|
||||
const out = [];
|
||||
|
||||
if (!Array.isArray(addrs))
|
||||
addrs = [addrs];
|
||||
|
||||
const out = [];
|
||||
|
||||
for (const addr of addrs) {
|
||||
const hash = Address.getHash(addr, 'hex');
|
||||
const txs = this.txIndex.getMeta(hash);
|
||||
@ -591,7 +594,7 @@ Mempool.prototype.getMeta = function getMeta(hash) {
|
||||
const entry = this.getEntry(hash);
|
||||
|
||||
if (!entry)
|
||||
return;
|
||||
return null;
|
||||
|
||||
const meta = TXMeta.fromTX(entry.tx);
|
||||
meta.mtime = entry.time;
|
||||
@ -685,11 +688,10 @@ Mempool.prototype.addTX = async function addTX(tx, id) {
|
||||
*/
|
||||
|
||||
Mempool.prototype._addTX = async function _addTX(tx, id) {
|
||||
let missing;
|
||||
|
||||
if (id == null)
|
||||
id = -1;
|
||||
|
||||
let missing;
|
||||
try {
|
||||
missing = await this.insertTX(tx, id);
|
||||
} catch (err) {
|
||||
@ -859,7 +861,6 @@ Mempool.prototype.insertTX = async function insertTX(tx, id) {
|
||||
Mempool.prototype.verify = async function verify(entry, view) {
|
||||
const height = this.chain.height + 1;
|
||||
const lockFlags = common.lockFlags.STANDARD_LOCKTIME_FLAGS;
|
||||
let flags = Script.flags.STANDARD_VERIFY_FLAGS;
|
||||
const tx = entry.tx;
|
||||
|
||||
// Verify sequence locks.
|
||||
@ -949,6 +950,7 @@ Mempool.prototype.verify = async function verify(entry, view) {
|
||||
throw new VerifyError(tx, 'invalid', reason, score);
|
||||
|
||||
// Script verification.
|
||||
let flags = Script.flags.STANDARD_VERIFY_FLAGS;
|
||||
try {
|
||||
await this.verifyInputs(tx, view, flags);
|
||||
} catch (err) {
|
||||
@ -1414,8 +1416,6 @@ Mempool.prototype.hasOrphan = function hasOrphan(hash) {
|
||||
*/
|
||||
|
||||
Mempool.prototype.storeOrphan = function storeOrphan(tx, missing, id) {
|
||||
const hash = tx.hash('hex');
|
||||
|
||||
if (tx.getWeight() > policy.MAX_TX_WEIGHT) {
|
||||
this.logger.debug('Ignoring large orphan: %s', tx.txid());
|
||||
if (!tx.hasWitness())
|
||||
@ -1436,6 +1436,8 @@ Mempool.prototype.storeOrphan = function storeOrphan(tx, missing, id) {
|
||||
|
||||
this.limitOrphans();
|
||||
|
||||
const hash = tx.hash('hex');
|
||||
|
||||
for (const prev of missing) {
|
||||
if (!this.waiting.has(prev))
|
||||
this.waiting.set(prev, new Set());
|
||||
@ -1510,13 +1512,14 @@ Mempool.prototype.handleOrphans = async function handleOrphans(parent) {
|
||||
Mempool.prototype.resolveOrphans = function resolveOrphans(parent) {
|
||||
const hash = parent.hash('hex');
|
||||
const set = this.waiting.get(hash);
|
||||
const resolved = [];
|
||||
|
||||
if (!set)
|
||||
return resolved;
|
||||
return [];
|
||||
|
||||
assert(set.size > 0);
|
||||
|
||||
const resolved = [];
|
||||
|
||||
for (const orphanHash of set.keys()) {
|
||||
const orphan = this.getOrphan(orphanHash);
|
||||
|
||||
@ -1541,11 +1544,11 @@ Mempool.prototype.resolveOrphans = function resolveOrphans(parent) {
|
||||
|
||||
Mempool.prototype.removeOrphan = function removeOrphan(hash) {
|
||||
const orphan = this.getOrphan(hash);
|
||||
let tx;
|
||||
|
||||
if (!orphan)
|
||||
return false;
|
||||
|
||||
let tx;
|
||||
try {
|
||||
tx = orphan.toTX();
|
||||
} catch (e) {
|
||||
@ -1553,7 +1556,7 @@ Mempool.prototype.removeOrphan = function removeOrphan(hash) {
|
||||
this.logger.warning('%s %s',
|
||||
'Warning: possible memory corruption.',
|
||||
'Orphan failed deserialization.');
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const prev of tx.getPrevout()) {
|
||||
@ -1587,8 +1590,8 @@ Mempool.prototype.limitOrphans = function limitOrphans() {
|
||||
return false;
|
||||
|
||||
let index = random.randomRange(0, this.orphans.size);
|
||||
let hash = null;
|
||||
|
||||
let hash;
|
||||
for (hash of this.orphans.keys()) {
|
||||
if (index === 0)
|
||||
break;
|
||||
@ -1690,7 +1693,7 @@ Mempool.prototype.findMissing = function findMissing(tx, view) {
|
||||
}
|
||||
|
||||
if (missing.length === 0)
|
||||
return;
|
||||
return null;
|
||||
|
||||
return missing;
|
||||
};
|
||||
@ -2115,10 +2118,11 @@ TXIndex.prototype.reset = function reset() {
|
||||
|
||||
TXIndex.prototype.get = function get(addr) {
|
||||
const items = this.index.get(addr);
|
||||
const out = [];
|
||||
|
||||
if (!items)
|
||||
return out;
|
||||
return [];
|
||||
|
||||
const out = [];
|
||||
|
||||
for (const entry of items.values())
|
||||
out.push(entry.tx);
|
||||
@ -2128,10 +2132,11 @@ TXIndex.prototype.get = function get(addr) {
|
||||
|
||||
TXIndex.prototype.getMeta = function getMeta(addr) {
|
||||
const items = this.index.get(addr);
|
||||
const out = [];
|
||||
|
||||
if (!items)
|
||||
return out;
|
||||
return [];
|
||||
|
||||
const out = [];
|
||||
|
||||
for (const entry of items.values()) {
|
||||
const meta = TXMeta.fromTX(entry.tx);
|
||||
@ -2207,10 +2212,11 @@ CoinIndex.prototype.reset = function reset() {
|
||||
|
||||
CoinIndex.prototype.get = function get(addr) {
|
||||
const items = this.index.get(addr);
|
||||
const out = [];
|
||||
|
||||
if (!items)
|
||||
return out;
|
||||
return [];
|
||||
|
||||
const out = [];
|
||||
|
||||
for (const coin of items.values())
|
||||
out.push(coin.toCoin());
|
||||
@ -2332,18 +2338,18 @@ MempoolCache.prototype.getTip = async function getTip() {
|
||||
const hash = await this.db.get(layout.R);
|
||||
|
||||
if (!hash)
|
||||
return;
|
||||
return null;
|
||||
|
||||
return hash.toString('hex');
|
||||
};
|
||||
|
||||
MempoolCache.prototype.getFees = async function getFees() {
|
||||
const data = await this.db.get(layout.F);
|
||||
let fees;
|
||||
|
||||
if (!data)
|
||||
return;
|
||||
return null;
|
||||
|
||||
let fees;
|
||||
try {
|
||||
fees = Fees.fromRaw(data);
|
||||
} catch (e) {
|
||||
|
||||
@ -97,8 +97,8 @@ MempoolEntry.prototype.fromTX = function fromTX(tx, view, height) {
|
||||
const size = tx.getSigopsSize(sigops);
|
||||
const priority = tx.getPriority(view, height, size);
|
||||
const fee = tx.getFee(view);
|
||||
let dependencies = false;
|
||||
|
||||
let dependencies = false;
|
||||
for (const {prevout} of tx.inputs) {
|
||||
if (view.getHeight(prevout) === -1) {
|
||||
dependencies = true;
|
||||
|
||||
@ -128,8 +128,7 @@ CPUMiner.prototype._start = async function start() {
|
||||
if (this.stopping)
|
||||
break;
|
||||
|
||||
let block = null;
|
||||
|
||||
let block;
|
||||
try {
|
||||
block = await this.mineAsync(this.job);
|
||||
} catch (e) {
|
||||
@ -145,8 +144,7 @@ CPUMiner.prototype._start = async function start() {
|
||||
if (!block)
|
||||
continue;
|
||||
|
||||
let entry = null;
|
||||
|
||||
let entry;
|
||||
try {
|
||||
entry = await this.chain.add(block);
|
||||
} catch (e) {
|
||||
@ -295,6 +293,7 @@ CPUMiner.prototype.findNonce = function findNonce(job) {
|
||||
const data = job.getHeader();
|
||||
const target = job.attempt.target;
|
||||
const interval = CPUMiner.INTERVAL;
|
||||
|
||||
let min = 0;
|
||||
let max = interval;
|
||||
let nonce;
|
||||
@ -322,16 +321,17 @@ CPUMiner.prototype.findNonce = function findNonce(job) {
|
||||
*/
|
||||
|
||||
CPUMiner.prototype.findNonceAsync = async function findNonceAsync(job) {
|
||||
if (!this.workers)
|
||||
return this.findNonce(job);
|
||||
|
||||
const data = job.getHeader();
|
||||
const target = job.attempt.target;
|
||||
const interval = CPUMiner.INTERVAL;
|
||||
|
||||
let min = 0;
|
||||
let max = interval;
|
||||
let nonce;
|
||||
|
||||
if (!this.workers)
|
||||
return this.findNonce(job);
|
||||
|
||||
while (max <= 0xffffffff) {
|
||||
nonce = await this.workers.mine(data, target, min, max);
|
||||
|
||||
@ -357,10 +357,9 @@ CPUMiner.prototype.findNonceAsync = async function findNonceAsync(job) {
|
||||
*/
|
||||
|
||||
CPUMiner.prototype.mine = function mine(job) {
|
||||
let nonce;
|
||||
|
||||
job.start = util.now();
|
||||
|
||||
let nonce;
|
||||
for (;;) {
|
||||
nonce = this.findNonce(job);
|
||||
|
||||
@ -394,7 +393,7 @@ CPUMiner.prototype.mineAsync = async function mineAsync(job) {
|
||||
break;
|
||||
|
||||
if (job.destroyed)
|
||||
return;
|
||||
return null;
|
||||
|
||||
job.updateNonce();
|
||||
|
||||
|
||||
@ -259,7 +259,7 @@ Miner.prototype.assemble = function assemble(attempt) {
|
||||
|
||||
if (!this.mempool) {
|
||||
attempt.refresh();
|
||||
return [];
|
||||
return;
|
||||
}
|
||||
|
||||
assert(this.mempool.tip === this.chain.tip.hash,
|
||||
|
||||
@ -178,7 +178,7 @@ BIP150.prototype.reply = function reply(data) {
|
||||
if (this.isAuthed()) {
|
||||
this.auth = true;
|
||||
this.emit('auth');
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
|
||||
assert(this.outbound, 'No challenge received before reply on inbound.');
|
||||
@ -321,6 +321,8 @@ BIP150.prototype.findAuthorized = function findAuthorized(hash) {
|
||||
if (ccmp(msg, hash))
|
||||
return key;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -630,12 +632,11 @@ AuthDB.prototype.lookup = async function lookup() {
|
||||
*/
|
||||
|
||||
AuthDB.prototype.populate = async function populate(addr, key) {
|
||||
let hosts;
|
||||
|
||||
assert(addr.type === IP.types.DNS, 'Resolved host passed.');
|
||||
|
||||
this.logger.info('Resolving authorized hosts from: %s.', addr.host);
|
||||
|
||||
let hosts;
|
||||
try {
|
||||
hosts = await this.resolve(addr.host);
|
||||
} catch (e) {
|
||||
@ -665,8 +666,8 @@ AuthDB.prototype.readKnown = async function readKnown() {
|
||||
return;
|
||||
|
||||
const file = path.join(this.prefix, 'known-peers');
|
||||
let text;
|
||||
|
||||
let text;
|
||||
try {
|
||||
text = await fs.readFile(file, 'utf8');
|
||||
} catch (e) {
|
||||
@ -702,8 +703,8 @@ AuthDB.prototype.parseKnown = function parseKnown(text) {
|
||||
continue;
|
||||
|
||||
const hostname = parts[0].trim().split(',');
|
||||
let host, ip;
|
||||
|
||||
let host, ip;
|
||||
if (hostname.length >= 2) {
|
||||
host = hostname[0];
|
||||
ip = hostname[1];
|
||||
@ -742,8 +743,8 @@ AuthDB.prototype.readAuth = async function readAuth() {
|
||||
return;
|
||||
|
||||
const file = path.join(this.prefix, 'authorized-peers');
|
||||
let text;
|
||||
|
||||
let text;
|
||||
try {
|
||||
text = await fs.readFile(file, 'utf8');
|
||||
} catch (e) {
|
||||
|
||||
@ -300,7 +300,7 @@ CompactBlock.prototype.fillMempool = function fillMempool(witness, mempool) {
|
||||
if (this.count === this.totalTX)
|
||||
return true;
|
||||
|
||||
const have = new Set();
|
||||
const set = new Set();
|
||||
|
||||
for (const {tx} of mempool.map.values()) {
|
||||
let hash = tx.hash();
|
||||
@ -314,7 +314,7 @@ CompactBlock.prototype.fillMempool = function fillMempool(witness, mempool) {
|
||||
if (index == null)
|
||||
continue;
|
||||
|
||||
if (have.has(index)) {
|
||||
if (set.has(index)) {
|
||||
// Siphash collision, just request it.
|
||||
this.available[index] = null;
|
||||
this.count--;
|
||||
@ -322,7 +322,7 @@ CompactBlock.prototype.fillMempool = function fillMempool(witness, mempool) {
|
||||
}
|
||||
|
||||
this.available[index] = tx;
|
||||
have.add(index);
|
||||
set.add(index);
|
||||
this.count++;
|
||||
|
||||
// We actually may have a siphash collision
|
||||
@ -619,7 +619,6 @@ TXRequest.prototype.fromReader = function fromReader(br) {
|
||||
this.hash = br.readHash('hex');
|
||||
|
||||
const count = br.readVarint();
|
||||
let offset = 0;
|
||||
|
||||
for (let i = 0; i < count; i++) {
|
||||
const index = br.readVarint();
|
||||
@ -627,6 +626,8 @@ TXRequest.prototype.fromReader = function fromReader(br) {
|
||||
this.indexes.push(index);
|
||||
}
|
||||
|
||||
let offset = 0;
|
||||
|
||||
for (let i = 0; i < count; i++) {
|
||||
let index = this.indexes[i];
|
||||
index += offset;
|
||||
|
||||
@ -22,34 +22,24 @@ const external = exports;
|
||||
*/
|
||||
|
||||
external.getIPv4 = async function getIPv4() {
|
||||
let res = null;
|
||||
|
||||
try {
|
||||
res = await request({
|
||||
const res = await request({
|
||||
method: 'GET',
|
||||
uri: 'http://ipv4.icanhazip.com',
|
||||
expect: 'txt',
|
||||
timeout: 2000
|
||||
});
|
||||
} catch (e) {
|
||||
return await external.getIPv42();
|
||||
}
|
||||
|
||||
let ip = null;
|
||||
|
||||
try {
|
||||
const str = res.body.trim();
|
||||
const raw = IP.toBuffer(str);
|
||||
|
||||
if (!IP.isIPv4(raw))
|
||||
throw new Error('Could not find IPv4.');
|
||||
|
||||
ip = IP.toString(raw);
|
||||
return IP.toString(raw);
|
||||
} catch (e) {
|
||||
return await external.getIPv42();
|
||||
}
|
||||
|
||||
return ip;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -403,9 +403,7 @@ HostList.prototype.isBanned = function isBanned(host) {
|
||||
*/
|
||||
|
||||
HostList.prototype.getHost = function getHost() {
|
||||
const now = this.network.now();
|
||||
let buckets = null;
|
||||
let factor = 1;
|
||||
|
||||
if (this.totalFresh > 0)
|
||||
buckets = this.fresh;
|
||||
@ -416,7 +414,10 @@ HostList.prototype.getHost = function getHost() {
|
||||
}
|
||||
|
||||
if (!buckets)
|
||||
return;
|
||||
return null;
|
||||
|
||||
const now = this.network.now();
|
||||
let factor = 1;
|
||||
|
||||
for (;;) {
|
||||
let index = util.random(0, buckets.length);
|
||||
@ -653,7 +654,7 @@ HostList.prototype.remove = function remove(hostname) {
|
||||
const entry = this.map.get(hostname);
|
||||
|
||||
if (!entry)
|
||||
return;
|
||||
return null;
|
||||
|
||||
if (entry.used) {
|
||||
let head = entry;
|
||||
@ -832,7 +833,7 @@ HostList.prototype.addSeed = function addSeed(host) {
|
||||
if (ip.type === IP.types.DNS) {
|
||||
// Defer for resolution.
|
||||
this.dnsSeeds.push(ip);
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
|
||||
const addr = NetAddress.fromHost(ip.host, ip.port, this.network);
|
||||
@ -854,7 +855,7 @@ HostList.prototype.addNode = function addNode(host) {
|
||||
if (ip.type === IP.types.DNS) {
|
||||
// Defer for resolution.
|
||||
this.dnsNodes.push(ip);
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
|
||||
const addr = NetAddress.fromHost(ip.host, ip.port, this.network);
|
||||
|
||||
@ -102,8 +102,7 @@ Parser.prototype.parse = function parse(data) {
|
||||
return;
|
||||
}
|
||||
|
||||
let payload = null;
|
||||
|
||||
let payload;
|
||||
try {
|
||||
payload = this.parsePayload(this.header.cmd, data);
|
||||
} catch (e) {
|
||||
|
||||
@ -511,10 +511,12 @@ Peer.prototype._open = async function open() {
|
||||
Peer.prototype.initConnect = function initConnect() {
|
||||
if (this.connected) {
|
||||
assert(!this.outbound);
|
||||
return;
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
/* eslint no-use-before-define: "off" */
|
||||
|
||||
const cleanup = () => {
|
||||
if (this.connectTimeout != null) {
|
||||
clearTimeout(this.connectTimeout);
|
||||
@ -703,8 +705,6 @@ Peer.prototype.finalize = async function finalize() {
|
||||
*/
|
||||
|
||||
Peer.prototype.announceBlock = function announceBlock(blocks) {
|
||||
const inv = [];
|
||||
|
||||
if (!this.handshake)
|
||||
return;
|
||||
|
||||
@ -714,6 +714,8 @@ Peer.prototype.announceBlock = function announceBlock(blocks) {
|
||||
if (!Array.isArray(blocks))
|
||||
blocks = [blocks];
|
||||
|
||||
const inv = [];
|
||||
|
||||
for (const block of blocks) {
|
||||
assert(block instanceof Block);
|
||||
|
||||
@ -753,8 +755,6 @@ Peer.prototype.announceBlock = function announceBlock(blocks) {
|
||||
*/
|
||||
|
||||
Peer.prototype.announceTX = function announceTX(txs) {
|
||||
const inv = [];
|
||||
|
||||
if (!this.handshake)
|
||||
return;
|
||||
|
||||
@ -769,6 +769,8 @@ Peer.prototype.announceTX = function announceTX(txs) {
|
||||
if (!Array.isArray(txs))
|
||||
txs = [txs];
|
||||
|
||||
const inv = [];
|
||||
|
||||
for (const tx of txs) {
|
||||
assert(tx instanceof TX);
|
||||
|
||||
@ -830,20 +832,21 @@ Peer.prototype.queueInv = function queueInv(items) {
|
||||
*/
|
||||
|
||||
Peer.prototype.flushInv = function flushInv() {
|
||||
const queue = this.invQueue.slice();
|
||||
const items = [];
|
||||
|
||||
if (this.destroyed)
|
||||
return;
|
||||
|
||||
const queue = this.invQueue;
|
||||
|
||||
if (queue.length === 0)
|
||||
return;
|
||||
|
||||
this.invQueue.length = 0;
|
||||
this.invQueue = [];
|
||||
|
||||
this.logger.spam('Serving %d inv items to %s.',
|
||||
queue.length, this.hostname());
|
||||
|
||||
const items = [];
|
||||
|
||||
for (const item of queue) {
|
||||
if (!this.invFilter.added(item.hash, 'hex'))
|
||||
continue;
|
||||
@ -1336,7 +1339,7 @@ Peer.prototype.maybeTimeout = function maybeTimeout() {
|
||||
|
||||
Peer.prototype.request = function request(type, timeout) {
|
||||
if (this.destroyed)
|
||||
return;
|
||||
return null;
|
||||
|
||||
let entry = this.responseMap.get(type);
|
||||
|
||||
@ -1361,7 +1364,7 @@ Peer.prototype.response = function response(type, payload) {
|
||||
const entry = this.responseMap.get(type);
|
||||
|
||||
if (!entry)
|
||||
return;
|
||||
return null;
|
||||
|
||||
this.responseMap.delete(type);
|
||||
|
||||
@ -1989,12 +1992,12 @@ Peer.prototype.handleAuthPropose = async function handleAuthPropose(packet) {
|
||||
|
||||
Peer.prototype.sendGetHeaders = function sendGetHeaders(locator, stop) {
|
||||
const packet = new packets.GetHeadersPacket(locator, stop);
|
||||
let hash = null;
|
||||
let end = null;
|
||||
|
||||
let hash = null;
|
||||
if (packet.locator.length > 0)
|
||||
hash = util.revHex(packet.locator[0]);
|
||||
|
||||
let end = null;
|
||||
if (stop)
|
||||
end = util.revHex(stop);
|
||||
|
||||
@ -2017,12 +2020,12 @@ Peer.prototype.sendGetHeaders = function sendGetHeaders(locator, stop) {
|
||||
|
||||
Peer.prototype.sendGetBlocks = function getBlocks(locator, stop) {
|
||||
const packet = new packets.GetBlocksPacket(locator, stop);
|
||||
let hash = null;
|
||||
let end = null;
|
||||
|
||||
let hash = null;
|
||||
if (packet.locator.length > 0)
|
||||
hash = util.revHex(packet.locator[0]);
|
||||
|
||||
let end = null;
|
||||
if (stop)
|
||||
end = util.revHex(stop);
|
||||
|
||||
|
||||
@ -463,15 +463,14 @@ Pool.prototype.discoverGateway = async function discoverGateway() {
|
||||
|
||||
// Pointless if we're not listening.
|
||||
if (!this.options.listen)
|
||||
return;
|
||||
return false;
|
||||
|
||||
// UPNP is always optional, since
|
||||
// it's likely to not work anyway.
|
||||
if (!this.options.upnp)
|
||||
return;
|
||||
|
||||
let wan = null;
|
||||
return false;
|
||||
|
||||
let wan;
|
||||
try {
|
||||
this.logger.debug('Discovering internet gateway (upnp).');
|
||||
wan = await UPNP.discover();
|
||||
@ -481,8 +480,7 @@ Pool.prototype.discoverGateway = async function discoverGateway() {
|
||||
return false;
|
||||
}
|
||||
|
||||
let host = null;
|
||||
|
||||
let host;
|
||||
try {
|
||||
host = await wan.getExternalIP();
|
||||
} catch (e) {
|
||||
@ -523,7 +521,6 @@ Pool.prototype.discoverSeeds = async function discoverSeeds(checkPeers) {
|
||||
const size = this.hosts.size();
|
||||
|
||||
let total = 0;
|
||||
|
||||
for (let peer = this.peers.head(); peer; peer = peer.next) {
|
||||
if (!peer.outbound)
|
||||
continue;
|
||||
@ -569,8 +566,7 @@ Pool.prototype.discoverExternal = async function discoverExternal() {
|
||||
if (this.hosts.local.size > 0)
|
||||
return;
|
||||
|
||||
let host4 = null;
|
||||
|
||||
let host4;
|
||||
try {
|
||||
host4 = await external.getIPv4();
|
||||
} catch (e) {
|
||||
@ -581,8 +577,7 @@ Pool.prototype.discoverExternal = async function discoverExternal() {
|
||||
if (host4 && this.hosts.addLocal(host4, port, scores.HTTP))
|
||||
this.logger.info('External IPv4 found (http): %s.', host4);
|
||||
|
||||
let host6 = null;
|
||||
|
||||
let host6;
|
||||
try {
|
||||
host6 = await external.getIPv6();
|
||||
} catch (e) {
|
||||
@ -767,8 +762,7 @@ Pool.prototype.resync = async function resync(force) {
|
||||
if (!this.syncing)
|
||||
return;
|
||||
|
||||
let locator = null;
|
||||
|
||||
let locator;
|
||||
try {
|
||||
locator = await this.chain.getLocator();
|
||||
} catch (e) {
|
||||
@ -834,8 +828,7 @@ Pool.prototype.sendSync = async function sendSync(peer) {
|
||||
peer.syncing = true;
|
||||
peer.blockTime = util.ms();
|
||||
|
||||
let locator = null;
|
||||
|
||||
let locator;
|
||||
try {
|
||||
locator = await this.chain.getLocator();
|
||||
} catch (e) {
|
||||
@ -1000,13 +993,13 @@ Pool.prototype.getBroadcasted = function getBroadcasted(peer, item) {
|
||||
const entry = this.invMap.get(item.hash);
|
||||
|
||||
if (!entry)
|
||||
return;
|
||||
return null;
|
||||
|
||||
if (type !== entry.type) {
|
||||
this.logger.debug(
|
||||
'Peer requested item with the wrong type (%s).',
|
||||
peer.hostname());
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
|
||||
this.logger.debug(
|
||||
@ -1037,19 +1030,19 @@ Pool.prototype.getItem = async function getItem(peer, item) {
|
||||
return entry;
|
||||
|
||||
if (this.options.selfish)
|
||||
return;
|
||||
return null;
|
||||
|
||||
if (item.isTX()) {
|
||||
if (!this.mempool)
|
||||
return;
|
||||
return null;
|
||||
return this.mempool.getTX(item.hash);
|
||||
}
|
||||
|
||||
if (this.chain.options.spv)
|
||||
return;
|
||||
return null;
|
||||
|
||||
if (this.chain.options.prune)
|
||||
return;
|
||||
return null;
|
||||
|
||||
return await this.chain.db.getBlock(item.hash);
|
||||
};
|
||||
@ -1683,8 +1676,6 @@ Pool.prototype._handleInv = async function handleInv(peer, packet) {
|
||||
*/
|
||||
|
||||
Pool.prototype.handleBlockInv = async function handleBlockInv(peer, hashes) {
|
||||
const items = [];
|
||||
|
||||
assert(hashes.length > 0);
|
||||
|
||||
if (!this.syncing)
|
||||
@ -1712,7 +1703,8 @@ Pool.prototype.handleBlockInv = async function handleBlockInv(peer, hashes) {
|
||||
hashes.length,
|
||||
peer.hostname());
|
||||
|
||||
let exists = null;
|
||||
const items = [];
|
||||
let exists;
|
||||
|
||||
for (let i = 0; i < hashes.length; i++) {
|
||||
const hash = hashes[i];
|
||||
@ -1968,8 +1960,6 @@ Pool.prototype.handleNotFound = async function handleNotFound(peer, packet) {
|
||||
*/
|
||||
|
||||
Pool.prototype.handleGetBlocks = async function handleGetBlocks(peer, packet) {
|
||||
const blocks = [];
|
||||
|
||||
if (!this.chain.synced)
|
||||
return;
|
||||
|
||||
@ -1987,6 +1977,8 @@ Pool.prototype.handleGetBlocks = async function handleGetBlocks(peer, packet) {
|
||||
if (hash)
|
||||
hash = await this.chain.db.getNextHash(hash);
|
||||
|
||||
const blocks = [];
|
||||
|
||||
while (hash) {
|
||||
blocks.push(new InvItem(invTypes.BLOCK, hash));
|
||||
|
||||
@ -2025,8 +2017,7 @@ Pool.prototype.handleGetHeaders = async function handleGetHeaders(peer, packet)
|
||||
if (this.chain.options.prune)
|
||||
return;
|
||||
|
||||
let hash = null;
|
||||
|
||||
let hash;
|
||||
if (packet.locator.length > 0) {
|
||||
hash = await this.chain.findLocator(packet.locator);
|
||||
if (hash)
|
||||
@ -2035,8 +2026,7 @@ Pool.prototype.handleGetHeaders = async function handleGetHeaders(peer, packet)
|
||||
hash = packet.stop;
|
||||
}
|
||||
|
||||
let entry = null;
|
||||
|
||||
let entry;
|
||||
if (hash)
|
||||
entry = await this.chain.db.getEntry(hash);
|
||||
|
||||
@ -2270,8 +2260,7 @@ Pool.prototype._addBlock = async function addBlock(peer, block, flags) {
|
||||
|
||||
peer.blockTime = util.ms();
|
||||
|
||||
let entry = null;
|
||||
|
||||
let entry;
|
||||
try {
|
||||
entry = await this.chain.add(block, flags, peer.id);
|
||||
} catch (err) {
|
||||
@ -2535,8 +2524,7 @@ Pool.prototype._handleTX = async function handleTX(peer, packet) {
|
||||
return;
|
||||
}
|
||||
|
||||
let missing = null;
|
||||
|
||||
let missing;
|
||||
try {
|
||||
missing = await this.mempool.addTX(tx, peer.id);
|
||||
} catch (err) {
|
||||
@ -2594,8 +2582,6 @@ Pool.prototype.handleReject = async function handleReject(peer, packet) {
|
||||
*/
|
||||
|
||||
Pool.prototype.handleMempool = async function handleMempool(peer, packet) {
|
||||
const items = [];
|
||||
|
||||
if (!this.mempool)
|
||||
return;
|
||||
|
||||
@ -2613,6 +2599,8 @@ Pool.prototype.handleMempool = async function handleMempool(peer, packet) {
|
||||
return;
|
||||
}
|
||||
|
||||
const items = [];
|
||||
|
||||
for (const hash of this.mempool.map.keys())
|
||||
items.push(new InvItem(invTypes.TX, hash));
|
||||
|
||||
@ -2775,7 +2763,6 @@ Pool.prototype.handleCmpctBlock = async function handleCmpctBlock(peer, packet)
|
||||
const block = packet.block;
|
||||
const hash = block.hash('hex');
|
||||
const witness = peer.compactWitness;
|
||||
const flags = chainCommon.flags.VERIFY_BODY;
|
||||
|
||||
if (!this.syncing)
|
||||
return;
|
||||
@ -2862,6 +2849,7 @@ Pool.prototype.handleCmpctBlock = async function handleCmpctBlock(peer, packet)
|
||||
this.logger.debug(
|
||||
'Received full compact block %s (%s).',
|
||||
block.rhash(), peer.hostname());
|
||||
const flags = chainCommon.flags.VERIFY_BODY;
|
||||
await this.addBlock(peer, block.toBlock(), flags);
|
||||
return;
|
||||
}
|
||||
@ -3080,9 +3068,6 @@ Pool.prototype.addInbound = function addInbound(socket) {
|
||||
*/
|
||||
|
||||
Pool.prototype.getHost = function getHost() {
|
||||
const services = this.options.getRequiredServices();
|
||||
const now = this.network.now();
|
||||
|
||||
for (const addr of this.hosts.nodes) {
|
||||
if (this.peers.has(addr.hostname))
|
||||
continue;
|
||||
@ -3090,6 +3075,9 @@ Pool.prototype.getHost = function getHost() {
|
||||
return addr;
|
||||
}
|
||||
|
||||
const services = this.options.getRequiredServices();
|
||||
const now = this.network.now();
|
||||
|
||||
for (let i = 0; i < 100; i++) {
|
||||
const entry = this.hosts.getHost();
|
||||
|
||||
@ -3121,6 +3109,8 @@ Pool.prototype.getHost = function getHost() {
|
||||
|
||||
return entry.addr;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -4389,20 +4379,20 @@ function NonceList() {
|
||||
}
|
||||
|
||||
NonceList.prototype.alloc = function alloc(hostname) {
|
||||
let nonce, key;
|
||||
|
||||
for (;;) {
|
||||
nonce = util.nonce();
|
||||
key = nonce.toString('hex');
|
||||
if (!this.map.has(key)) {
|
||||
this.map.set(key, hostname);
|
||||
assert(!this.hosts.has(hostname));
|
||||
this.hosts.set(hostname, key);
|
||||
break;
|
||||
}
|
||||
}
|
||||
const nonce = util.nonce();
|
||||
const key = nonce.toString('hex');
|
||||
|
||||
return nonce;
|
||||
if (this.map.has(key))
|
||||
continue;
|
||||
|
||||
this.map.set(key, hostname);
|
||||
|
||||
assert(!this.hosts.has(hostname));
|
||||
this.hosts.set(hostname, key);
|
||||
|
||||
return nonce;
|
||||
}
|
||||
};
|
||||
|
||||
NonceList.prototype.has = function has(nonce) {
|
||||
|
||||
@ -101,8 +101,6 @@ ProxySocket.prototype._init = function _init() {
|
||||
};
|
||||
|
||||
ProxySocket.prototype.connect = function connect(port, host) {
|
||||
let nonce = 0;
|
||||
|
||||
this.remoteAddress = host;
|
||||
this.remotePort = port;
|
||||
|
||||
@ -116,14 +114,17 @@ ProxySocket.prototype.connect = function connect(port, host) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.info.pow) {
|
||||
let pow = new BufferWriter();
|
||||
let nonce = 0;
|
||||
|
||||
pow.writeU32(nonce);
|
||||
pow.writeBytes(this.snonce);
|
||||
pow.writeU32(port);
|
||||
pow.writeString(host, 'ascii');
|
||||
pow = pow.render();
|
||||
if (this.info.pow) {
|
||||
const bw = new BufferWriter();
|
||||
|
||||
bw.writeU32(nonce);
|
||||
bw.writeBytes(this.snonce);
|
||||
bw.writeU32(port);
|
||||
bw.writeString(host, 'ascii');
|
||||
|
||||
const pow = bw.render();
|
||||
|
||||
util.log(
|
||||
'Solving proof of work to create socket (%d, %s) -- please wait.',
|
||||
|
||||
@ -428,8 +428,7 @@ SOCKS.prototype.handleProxy = function handleProxy(data) {
|
||||
return;
|
||||
}
|
||||
|
||||
let addr = null;
|
||||
|
||||
let addr;
|
||||
try {
|
||||
addr = parseAddr(data, 3);
|
||||
} catch (e) {
|
||||
@ -487,8 +486,7 @@ SOCKS.prototype.handleResolve = function handleResolve(data) {
|
||||
return;
|
||||
}
|
||||
|
||||
let addr = null;
|
||||
|
||||
let addr;
|
||||
try {
|
||||
addr = parseAddr(data, 3);
|
||||
} catch (e) {
|
||||
@ -569,8 +567,7 @@ Proxy.prototype.connect = async function connect(port, host) {
|
||||
destPort: port
|
||||
};
|
||||
|
||||
let socket = null;
|
||||
|
||||
let socket;
|
||||
try {
|
||||
socket = await SOCKS.proxy(options);
|
||||
} catch (e) {
|
||||
@ -708,9 +705,7 @@ function parseAddr(data, offset) {
|
||||
br.seek(offset);
|
||||
|
||||
const type = br.readU8();
|
||||
|
||||
let host = null;
|
||||
let port = 0;
|
||||
let host, port;
|
||||
|
||||
switch (type) {
|
||||
case 0x01: {
|
||||
|
||||
@ -191,8 +191,7 @@ UPNP.prototype.handleMsg = async function handleMsg(msg) {
|
||||
if (!this.socket)
|
||||
return;
|
||||
|
||||
let headers = null;
|
||||
|
||||
let headers;
|
||||
try {
|
||||
headers = UPNP.parseHeader(msg);
|
||||
} catch (e) {
|
||||
@ -271,7 +270,7 @@ UPNP.parseHeader = function parseHeader(str) {
|
||||
const index = line.indexOf(':');
|
||||
|
||||
if (index === -1) {
|
||||
left = line.toLowerCase();
|
||||
const left = line.toLowerCase();
|
||||
headers[left] = '';
|
||||
continue;
|
||||
}
|
||||
@ -615,6 +614,8 @@ XMLElement.prototype.find = function find(name) {
|
||||
if (child)
|
||||
return child;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -649,6 +650,8 @@ function findService(services, name) {
|
||||
if (service.serviceType === name)
|
||||
return service;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function extractServices(services, targets) {
|
||||
@ -657,13 +660,15 @@ function extractServices(services, targets) {
|
||||
if (service)
|
||||
return service;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function findIP(el) {
|
||||
const child = el.find('NewExternalIPAddress');
|
||||
|
||||
if (!child)
|
||||
return;
|
||||
return null;
|
||||
|
||||
return IP.normalize(child.text);
|
||||
}
|
||||
@ -672,7 +677,7 @@ function findError(el) {
|
||||
const child = el.find('UPnPError');
|
||||
|
||||
if (!child)
|
||||
return;
|
||||
return null;
|
||||
|
||||
let code = -1;
|
||||
const ccode = child.find('errorCode');
|
||||
|
||||
@ -702,8 +702,7 @@ Config.prototype.parseArg = function parseArg(argv) {
|
||||
|
||||
assert(Array.isArray(argv));
|
||||
|
||||
let key = null;
|
||||
|
||||
let key;
|
||||
for (let i = 2; i < argv.length; i++) {
|
||||
let arg = argv[i];
|
||||
let value, alias, equals;
|
||||
|
||||
@ -379,16 +379,16 @@ FullNode.prototype.getBlock = function getBlock(hash) {
|
||||
* @returns {Promise} - Returns {@link Coin}.
|
||||
*/
|
||||
|
||||
FullNode.prototype.getCoin = function getCoin(hash, index) {
|
||||
FullNode.prototype.getCoin = async function getCoin(hash, index) {
|
||||
const coin = this.mempool.getCoin(hash, index);
|
||||
|
||||
if (coin)
|
||||
return Promise.resolve(coin);
|
||||
return coin;
|
||||
|
||||
if (this.mempool.isSpent(hash, index))
|
||||
return Promise.resolve();
|
||||
return null;
|
||||
|
||||
return this.chain.db.getCoin(hash, index);
|
||||
return await this.chain.db.getCoin(hash, index);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -483,8 +483,10 @@ FullNode.prototype.getTXByAddress = async function getTXByAddress(addrs) {
|
||||
|
||||
FullNode.prototype.getTX = async function getTX(hash) {
|
||||
const mtx = await this.getMeta(hash);
|
||||
|
||||
if (!mtx)
|
||||
return;
|
||||
return null;
|
||||
|
||||
return mtx.tx;
|
||||
};
|
||||
|
||||
|
||||
@ -253,8 +253,6 @@ Logger.prototype._close = async function close() {
|
||||
*/
|
||||
|
||||
Logger.prototype.truncate = async function truncate() {
|
||||
const maxSize = Logger.MAX_FILE_SIZE;
|
||||
|
||||
if (!this.filename)
|
||||
return;
|
||||
|
||||
@ -263,8 +261,7 @@ Logger.prototype.truncate = async function truncate() {
|
||||
|
||||
assert(!this.stream);
|
||||
|
||||
let stat = null;
|
||||
|
||||
let stat;
|
||||
try {
|
||||
stat = await fs.stat(this.filename);
|
||||
} catch (e) {
|
||||
@ -273,6 +270,8 @@ Logger.prototype.truncate = async function truncate() {
|
||||
throw e;
|
||||
}
|
||||
|
||||
const maxSize = Logger.MAX_FILE_SIZE;
|
||||
|
||||
if (stat.size <= maxSize + (maxSize / 10))
|
||||
return;
|
||||
|
||||
@ -390,11 +389,11 @@ Logger.prototype.setLevel = function setLevel(name) {
|
||||
*/
|
||||
|
||||
Logger.prototype.error = function error(...args) {
|
||||
const err = args[0];
|
||||
|
||||
if (this.level < Logger.levels.ERROR)
|
||||
return;
|
||||
|
||||
const err = args[0];
|
||||
|
||||
if (err instanceof Error)
|
||||
return this.logError(Logger.levels.ERROR, null, err);
|
||||
|
||||
@ -408,11 +407,11 @@ Logger.prototype.error = function error(...args) {
|
||||
*/
|
||||
|
||||
Logger.prototype.warning = function warning(...args) {
|
||||
const err = args[0];
|
||||
|
||||
if (this.level < Logger.levels.WARNING)
|
||||
return;
|
||||
|
||||
const err = args[0];
|
||||
|
||||
if (err instanceof Error)
|
||||
return this.logError(Logger.levels.WARNING, null, err);
|
||||
|
||||
@ -426,11 +425,11 @@ Logger.prototype.warning = function warning(...args) {
|
||||
*/
|
||||
|
||||
Logger.prototype.info = function info(...args) {
|
||||
const err = args[0];
|
||||
|
||||
if (this.level < Logger.levels.INFO)
|
||||
return;
|
||||
|
||||
const err = args[0];
|
||||
|
||||
if (err instanceof Error)
|
||||
return this.logError(Logger.levels.INFO, null, err);
|
||||
|
||||
@ -444,11 +443,11 @@ Logger.prototype.info = function info(...args) {
|
||||
*/
|
||||
|
||||
Logger.prototype.debug = function debug(...args) {
|
||||
const err = args[0];
|
||||
|
||||
if (this.level < Logger.levels.DEBUG)
|
||||
return;
|
||||
|
||||
const err = args[0];
|
||||
|
||||
if (err instanceof Error)
|
||||
return this.logError(Logger.levels.DEBUG, null, err);
|
||||
|
||||
@ -462,11 +461,11 @@ Logger.prototype.debug = function debug(...args) {
|
||||
*/
|
||||
|
||||
Logger.prototype.spam = function spam(...args) {
|
||||
const err = args[0];
|
||||
|
||||
if (this.level < Logger.levels.SPAM)
|
||||
return;
|
||||
|
||||
const err = args[0];
|
||||
|
||||
if (err instanceof Error)
|
||||
return this.logError(Logger.levels.SPAM, null, err);
|
||||
|
||||
@ -518,7 +517,6 @@ Logger.prototype.context = function _context(module) {
|
||||
|
||||
Logger.prototype.writeConsole = function writeConsole(level, module, args) {
|
||||
const name = Logger.levelsByVal[level];
|
||||
let msg = '';
|
||||
|
||||
assert(name, 'Invalid log level.');
|
||||
|
||||
@ -526,7 +524,7 @@ Logger.prototype.writeConsole = function writeConsole(level, module, args) {
|
||||
return;
|
||||
|
||||
if (!process.stdout) {
|
||||
msg += `[${name}] `;
|
||||
let msg = `[${name}] `;
|
||||
|
||||
if (module)
|
||||
msg += `(${module}) `;
|
||||
@ -544,13 +542,15 @@ Logger.prototype.writeConsole = function writeConsole(level, module, args) {
|
||||
: console.log(msg);
|
||||
}
|
||||
|
||||
let msg;
|
||||
|
||||
if (this.colors) {
|
||||
const color = Logger.styles[level];
|
||||
assert(color);
|
||||
|
||||
msg += `\x1b[${color}m[${name}]\x1b[m `;
|
||||
msg = `\x1b[${color}m[${name}]\x1b[m `;
|
||||
} else {
|
||||
msg += `[${name}] `;
|
||||
msg = `[${name}] `;
|
||||
}
|
||||
|
||||
if (module)
|
||||
@ -573,7 +573,6 @@ Logger.prototype.writeConsole = function writeConsole(level, module, args) {
|
||||
|
||||
Logger.prototype.writeStream = function writeStream(level, module, args) {
|
||||
const name = Logger.prefixByVal[level];
|
||||
let msg = '';
|
||||
|
||||
assert(name, 'Invalid log level.');
|
||||
|
||||
@ -583,7 +582,7 @@ Logger.prototype.writeStream = function writeStream(level, module, args) {
|
||||
if (this.closing)
|
||||
return;
|
||||
|
||||
msg += `[${name}:${util.date()}] `;
|
||||
let msg = `[${name}:${util.date()}] `;
|
||||
|
||||
if (module)
|
||||
msg += `(${module}) `;
|
||||
@ -703,11 +702,11 @@ LoggerContext.prototype.setLevel = function setLevel(name) {
|
||||
*/
|
||||
|
||||
LoggerContext.prototype.error = function error(...args) {
|
||||
const err = args[0];
|
||||
|
||||
if (this.logger.level < Logger.levels.ERROR)
|
||||
return;
|
||||
|
||||
const err = args[0];
|
||||
|
||||
if (err instanceof Error)
|
||||
return this.logError(Logger.levels.ERROR, err);
|
||||
|
||||
@ -721,11 +720,11 @@ LoggerContext.prototype.error = function error(...args) {
|
||||
*/
|
||||
|
||||
LoggerContext.prototype.warning = function warning(...args) {
|
||||
const err = args[0];
|
||||
|
||||
if (this.logger.level < Logger.levels.WARNING)
|
||||
return;
|
||||
|
||||
const err = args[0];
|
||||
|
||||
if (err instanceof Error)
|
||||
return this.logError(Logger.levels.WARNING, err);
|
||||
|
||||
@ -739,11 +738,11 @@ LoggerContext.prototype.warning = function warning(...args) {
|
||||
*/
|
||||
|
||||
LoggerContext.prototype.info = function info(...args) {
|
||||
const err = args[0];
|
||||
|
||||
if (this.logger.level < Logger.levels.INFO)
|
||||
return;
|
||||
|
||||
const err = args[0];
|
||||
|
||||
if (err instanceof Error)
|
||||
return this.logError(Logger.levels.INFO, err);
|
||||
|
||||
@ -757,11 +756,11 @@ LoggerContext.prototype.info = function info(...args) {
|
||||
*/
|
||||
|
||||
LoggerContext.prototype.debug = function debug(...args) {
|
||||
const err = args[0];
|
||||
|
||||
if (this.logger.level < Logger.levels.DEBUG)
|
||||
return;
|
||||
|
||||
const err = args[0];
|
||||
|
||||
if (err instanceof Error)
|
||||
return this.logError(Logger.levels.DEBUG, err);
|
||||
|
||||
@ -775,11 +774,11 @@ LoggerContext.prototype.debug = function debug(...args) {
|
||||
*/
|
||||
|
||||
LoggerContext.prototype.spam = function spam(...args) {
|
||||
const err = args[0];
|
||||
|
||||
if (this.logger.level < Logger.levels.SPAM)
|
||||
return;
|
||||
|
||||
const err = args[0];
|
||||
|
||||
if (err instanceof Error)
|
||||
return this.logError(Logger.levels.SPAM, err);
|
||||
|
||||
@ -839,12 +838,9 @@ Logger.global = new Logger();
|
||||
|
||||
function openStream(filename) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const stream = fs.createWriteStream(filename, { flags: 'a' });
|
||||
/* eslint no-use-before-define: "off" */
|
||||
|
||||
const cleanup = () => {
|
||||
stream.removeListener('error', onError);
|
||||
stream.removeListener('open', onOpen);
|
||||
};
|
||||
const stream = fs.createWriteStream(filename, { flags: 'a' });
|
||||
|
||||
const onError = (err) => {
|
||||
try {
|
||||
@ -861,6 +857,11 @@ function openStream(filename) {
|
||||
resolve(stream);
|
||||
};
|
||||
|
||||
const cleanup = () => {
|
||||
stream.removeListener('error', onError);
|
||||
stream.removeListener('open', onOpen);
|
||||
};
|
||||
|
||||
stream.once('error', onError);
|
||||
stream.once('open', onOpen);
|
||||
});
|
||||
@ -868,10 +869,7 @@ function openStream(filename) {
|
||||
|
||||
function closeStream(stream) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const cleanup = () => {
|
||||
stream.removeListener('error', onError);
|
||||
stream.removeListener('close', onClose);
|
||||
};
|
||||
/* eslint no-use-before-define: "off" */
|
||||
|
||||
const onError = (err) => {
|
||||
cleanup();
|
||||
@ -883,6 +881,11 @@ function closeStream(stream) {
|
||||
resolve(stream);
|
||||
};
|
||||
|
||||
const cleanup = () => {
|
||||
stream.removeListener('error', onError);
|
||||
stream.removeListener('close', onClose);
|
||||
};
|
||||
|
||||
stream.removeAllListeners('error');
|
||||
stream.removeAllListeners('close');
|
||||
stream.once('error', onError);
|
||||
|
||||
@ -352,7 +352,7 @@ Node.prototype.get = function get(name) {
|
||||
return this.http;
|
||||
}
|
||||
|
||||
return this.plugins[name];
|
||||
return this.plugins[name] || null;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -460,6 +460,8 @@ Address.prototype.fromScript = function fromScript(script) {
|
||||
this.version = -1;
|
||||
return this;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -484,6 +486,8 @@ Address.prototype.fromWitness = function fromWitness(witness) {
|
||||
this.version = 0;
|
||||
return this;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -506,6 +510,8 @@ Address.prototype.fromInputScript = function fromInputScript(script) {
|
||||
this.version = -1;
|
||||
return this;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -824,11 +830,11 @@ Address.prototype.isUnknown = function isUnknown() {
|
||||
*/
|
||||
|
||||
Address.getHash = function getHash(data, enc, network) {
|
||||
let hash;
|
||||
|
||||
if (!data)
|
||||
throw new Error('Object is not an address.');
|
||||
|
||||
let hash;
|
||||
|
||||
if (typeof data === 'string') {
|
||||
if (data.length === 40 || data.length === 64)
|
||||
return enc === 'hex' ? data : Buffer.from(data, 'hex');
|
||||
|
||||
@ -379,7 +379,7 @@ Block.prototype.getCommitmentHash = function getCommitmentHash(enc) {
|
||||
return null;
|
||||
|
||||
const coinbase = this.txs[0];
|
||||
let hash = null;
|
||||
let hash;
|
||||
|
||||
for (let i = coinbase.outputs.length - 1; i >= 0; i--) {
|
||||
const output = coinbase.outputs[i];
|
||||
|
||||
@ -123,7 +123,7 @@ Input.prototype.getType = function getType(coin) {
|
||||
|
||||
Input.prototype.getRedeem = function getRedeem(coin) {
|
||||
if (this.isCoinbase())
|
||||
return;
|
||||
return null;
|
||||
|
||||
if (!coin) {
|
||||
if (this.witness.isScripthashInput())
|
||||
@ -132,7 +132,7 @@ Input.prototype.getRedeem = function getRedeem(coin) {
|
||||
if (this.script.isScripthashInput())
|
||||
return this.script.getRedeem();
|
||||
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
|
||||
let prev = coin.script;
|
||||
@ -159,12 +159,12 @@ Input.prototype.getRedeem = function getRedeem(coin) {
|
||||
|
||||
Input.prototype.getSubtype = function getSubtype(coin) {
|
||||
if (this.isCoinbase())
|
||||
return;
|
||||
return null;
|
||||
|
||||
const redeem = this.getRedeem(coin);
|
||||
|
||||
if (!redeem)
|
||||
return;
|
||||
return null;
|
||||
|
||||
const type = redeem.getType();
|
||||
|
||||
@ -181,7 +181,7 @@ Input.prototype.getSubtype = function getSubtype(coin) {
|
||||
|
||||
Input.prototype.getAddress = function getAddress(coin) {
|
||||
if (this.isCoinbase())
|
||||
return;
|
||||
return null;
|
||||
|
||||
if (coin)
|
||||
return coin.getAddress();
|
||||
@ -202,7 +202,7 @@ Input.prototype.getHash = function getHash(enc) {
|
||||
const addr = this.getAddress();
|
||||
|
||||
if (!addr)
|
||||
return;
|
||||
return null;
|
||||
|
||||
return addr.getHash(enc);
|
||||
};
|
||||
@ -284,10 +284,9 @@ Input.prototype.toJSON = function toJSON(network, coin) {
|
||||
*/
|
||||
|
||||
Input.prototype.getJSON = function getJSON(network, coin) {
|
||||
let addr;
|
||||
|
||||
network = Network.get(network);
|
||||
|
||||
let addr;
|
||||
if (!coin) {
|
||||
addr = this.getAddress();
|
||||
if (addr)
|
||||
|
||||
@ -58,13 +58,11 @@ function KeyRing(options, network) {
|
||||
*/
|
||||
|
||||
KeyRing.prototype.fromOptions = function fromOptions(options, network) {
|
||||
let key = toKey(options);
|
||||
const script = options.script;
|
||||
const compressed = options.compressed;
|
||||
|
||||
if (!network)
|
||||
network = options.network;
|
||||
|
||||
let key = toKey(options);
|
||||
|
||||
if (Buffer.isBuffer(key))
|
||||
return this.fromKey(key, network);
|
||||
|
||||
@ -86,10 +84,13 @@ KeyRing.prototype.fromOptions = function fromOptions(options, network) {
|
||||
this.nested = options.nested;
|
||||
}
|
||||
|
||||
if (script)
|
||||
return this.fromScript(key, script, compressed, network);
|
||||
const script = options.script;
|
||||
const compress = options.compressed;
|
||||
|
||||
this.fromKey(key, compressed, network);
|
||||
if (script)
|
||||
return this.fromScript(key, script, compress, network);
|
||||
|
||||
return this.fromKey(key, compress, network);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -121,22 +122,22 @@ KeyRing.prototype.refresh = function refresh() {
|
||||
* Inject data from private key.
|
||||
* @private
|
||||
* @param {Buffer} key
|
||||
* @param {Boolean?} compressed
|
||||
* @param {Boolean?} compress
|
||||
* @param {(NetworkType|Network)?} network
|
||||
*/
|
||||
|
||||
KeyRing.prototype.fromPrivate = function fromPrivate(key, compressed, network) {
|
||||
KeyRing.prototype.fromPrivate = function fromPrivate(key, compress, network) {
|
||||
assert(Buffer.isBuffer(key), 'Private key must be a buffer.');
|
||||
assert(secp256k1.privateKeyVerify(key), 'Not a valid private key.');
|
||||
|
||||
if (typeof compressed !== 'boolean') {
|
||||
network = compressed;
|
||||
compressed = null;
|
||||
if (typeof compress !== 'boolean') {
|
||||
network = compress;
|
||||
compress = null;
|
||||
}
|
||||
|
||||
this.network = Network.get(network);
|
||||
this.privateKey = key;
|
||||
this.publicKey = secp256k1.publicKeyCreate(key, compressed !== false);
|
||||
this.publicKey = secp256k1.publicKeyCreate(key, compress !== false);
|
||||
|
||||
return this;
|
||||
};
|
||||
@ -144,13 +145,13 @@ KeyRing.prototype.fromPrivate = function fromPrivate(key, compressed, network) {
|
||||
/**
|
||||
* Instantiate keyring from a private key.
|
||||
* @param {Buffer} key
|
||||
* @param {Boolean?} compressed
|
||||
* @param {Boolean?} compress
|
||||
* @param {(NetworkType|Network)?} network
|
||||
* @returns {KeyRing}
|
||||
*/
|
||||
|
||||
KeyRing.fromPrivate = function fromPrivate(key, compressed, network) {
|
||||
return new KeyRing().fromPrivate(key, compressed, network);
|
||||
KeyRing.fromPrivate = function fromPrivate(key, compress, network) {
|
||||
return new KeyRing().fromPrivate(key, compress, network);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -171,29 +172,31 @@ KeyRing.prototype.fromPublic = function fromPublic(key, network) {
|
||||
/**
|
||||
* Generate a keyring.
|
||||
* @private
|
||||
* @param {Boolean?} compress
|
||||
* @param {(Network|NetworkType)?} network
|
||||
* @returns {KeyRing}
|
||||
*/
|
||||
|
||||
KeyRing.prototype.generate = function generate(compressed, network) {
|
||||
if (typeof compressed !== 'boolean') {
|
||||
network = compressed;
|
||||
compressed = null;
|
||||
KeyRing.prototype.generate = function generate(compress, network) {
|
||||
if (typeof compress !== 'boolean') {
|
||||
network = compress;
|
||||
compress = null;
|
||||
}
|
||||
|
||||
const key = secp256k1.generatePrivateKey();
|
||||
|
||||
return this.fromKey(key, compressed, network);
|
||||
return this.fromKey(key, compress, network);
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate a keyring.
|
||||
* @param {Boolean?} compress
|
||||
* @param {(Network|NetworkType)?} network
|
||||
* @returns {KeyRing}
|
||||
*/
|
||||
|
||||
KeyRing.generate = function generate(compressed, network) {
|
||||
return new KeyRing().generate(compressed, network);
|
||||
KeyRing.generate = function generate(compress, network) {
|
||||
return new KeyRing().generate(compress, network);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -211,19 +214,20 @@ KeyRing.fromPublic = function fromPublic(key, network) {
|
||||
* Inject data from public key.
|
||||
* @private
|
||||
* @param {Buffer} privateKey
|
||||
* @param {Boolean?} compress
|
||||
* @param {(NetworkType|Network)?} network
|
||||
*/
|
||||
|
||||
KeyRing.prototype.fromKey = function fromKey(key, compressed, network) {
|
||||
KeyRing.prototype.fromKey = function fromKey(key, compress, network) {
|
||||
assert(Buffer.isBuffer(key), 'Key must be a buffer.');
|
||||
|
||||
if (typeof compressed !== 'boolean') {
|
||||
network = compressed;
|
||||
compressed = null;
|
||||
if (typeof compress !== 'boolean') {
|
||||
network = compress;
|
||||
compress = null;
|
||||
}
|
||||
|
||||
if (key.length === 32)
|
||||
return this.fromPrivate(key, compressed !== false, network);
|
||||
return this.fromPrivate(key, compress !== false, network);
|
||||
|
||||
return this.fromPublic(key, network);
|
||||
};
|
||||
@ -231,12 +235,13 @@ KeyRing.prototype.fromKey = function fromKey(key, compressed, network) {
|
||||
/**
|
||||
* Instantiate keyring from a public key.
|
||||
* @param {Buffer} publicKey
|
||||
* @param {Boolean?} compress
|
||||
* @param {(NetworkType|Network)?} network
|
||||
* @returns {KeyRing}
|
||||
*/
|
||||
|
||||
KeyRing.fromKey = function fromKey(key, compressed, network) {
|
||||
return new KeyRing().fromKey(key, compressed, network);
|
||||
KeyRing.fromKey = function fromKey(key, compress, network) {
|
||||
return new KeyRing().fromKey(key, compress, network);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -244,18 +249,19 @@ KeyRing.fromKey = function fromKey(key, compressed, network) {
|
||||
* @private
|
||||
* @param {Buffer} key
|
||||
* @param {Script} script
|
||||
* @param {Boolean?} compress
|
||||
* @param {(NetworkType|Network)?} network
|
||||
*/
|
||||
|
||||
KeyRing.prototype.fromScript = function fromScript(key, script, compressed, network) {
|
||||
KeyRing.prototype.fromScript = function fromScript(key, script, compress, network) {
|
||||
assert(script instanceof Script, 'Non-script passed into KeyRing.');
|
||||
|
||||
if (typeof compressed !== 'boolean') {
|
||||
network = compressed;
|
||||
compressed = null;
|
||||
if (typeof compress !== 'boolean') {
|
||||
network = compress;
|
||||
compress = null;
|
||||
}
|
||||
|
||||
this.fromKey(key, compressed, network);
|
||||
this.fromKey(key, compress, network);
|
||||
this.script = script;
|
||||
|
||||
return this;
|
||||
@ -265,12 +271,13 @@ KeyRing.prototype.fromScript = function fromScript(key, script, compressed, netw
|
||||
* Instantiate keyring from script.
|
||||
* @param {Buffer} key
|
||||
* @param {Script} script
|
||||
* @param {Boolean?} compress
|
||||
* @param {(NetworkType|Network)?} network
|
||||
* @returns {KeyRing}
|
||||
*/
|
||||
|
||||
KeyRing.fromScript = function fromScript(key, script, compressed, network) {
|
||||
return new KeyRing().fromScript(key, script, compressed, network);
|
||||
KeyRing.fromScript = function fromScript(key, script, compress, network) {
|
||||
return new KeyRing().fromScript(key, script, compress, network);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -336,16 +343,16 @@ KeyRing.prototype.fromSecret = function fromSecret(data, network) {
|
||||
|
||||
const key = br.readBytes(32);
|
||||
|
||||
let compressed = false;
|
||||
let compress = false;
|
||||
|
||||
if (br.left() > 4) {
|
||||
assert(br.readU8() === 1, 'Bad compression flag.');
|
||||
compressed = true;
|
||||
compress = true;
|
||||
}
|
||||
|
||||
br.verifyChecksum();
|
||||
|
||||
return this.fromPrivate(key, compressed, network);
|
||||
return this.fromPrivate(key, compress, network);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -367,7 +374,7 @@ KeyRing.fromSecret = function fromSecret(data, network) {
|
||||
|
||||
KeyRing.prototype.getPrivateKey = function getPrivateKey(enc) {
|
||||
if (!this.privateKey)
|
||||
return;
|
||||
return null;
|
||||
|
||||
if (enc === 'base58')
|
||||
return this.toSecret();
|
||||
@ -410,7 +417,7 @@ KeyRing.prototype.getScript = function getScript() {
|
||||
|
||||
KeyRing.prototype.getProgram = function getProgram() {
|
||||
if (!this.witness)
|
||||
return;
|
||||
return null;
|
||||
|
||||
if (!this._program) {
|
||||
let program;
|
||||
@ -436,7 +443,7 @@ KeyRing.prototype.getProgram = function getProgram() {
|
||||
|
||||
KeyRing.prototype.getNestedHash = function getNestedHash(enc) {
|
||||
if (!this.witness)
|
||||
return;
|
||||
return null;
|
||||
|
||||
if (!this._nestedHash)
|
||||
this._nestedHash = this.getProgram().hash160();
|
||||
@ -454,7 +461,7 @@ KeyRing.prototype.getNestedHash = function getNestedHash(enc) {
|
||||
|
||||
KeyRing.prototype.getNestedAddress = function getNestedAddress(enc) {
|
||||
if (!this.witness)
|
||||
return;
|
||||
return null;
|
||||
|
||||
if (!this._nestedAddress) {
|
||||
const hash = this.getNestedHash();
|
||||
@ -491,7 +498,7 @@ KeyRing.prototype.getScriptHash = function getScriptHash(enc) {
|
||||
|
||||
KeyRing.prototype.getScriptHash160 = function getScriptHash256(enc) {
|
||||
if (!this.script)
|
||||
return;
|
||||
return null;
|
||||
|
||||
if (!this._scriptHash160)
|
||||
this._scriptHash160 = this.script.hash160();
|
||||
@ -509,7 +516,7 @@ KeyRing.prototype.getScriptHash160 = function getScriptHash256(enc) {
|
||||
|
||||
KeyRing.prototype.getScriptHash256 = function getScriptHash256(enc) {
|
||||
if (!this.script)
|
||||
return;
|
||||
return null;
|
||||
|
||||
if (!this._scriptHash256)
|
||||
this._scriptHash256 = this.script.sha256();
|
||||
@ -527,7 +534,7 @@ KeyRing.prototype.getScriptHash256 = function getScriptHash256(enc) {
|
||||
|
||||
KeyRing.prototype.getScriptAddress = function getScriptAddress(enc) {
|
||||
if (!this.script)
|
||||
return;
|
||||
return null;
|
||||
|
||||
if (!this._scriptAddress) {
|
||||
let addr;
|
||||
@ -602,8 +609,10 @@ KeyRing.prototype.getKeyAddress = function getKeyAddress(enc) {
|
||||
KeyRing.prototype.getHash = function getHash(enc) {
|
||||
if (this.nested)
|
||||
return this.getNestedHash(enc);
|
||||
|
||||
if (this.script)
|
||||
return this.getScriptHash(enc);
|
||||
|
||||
return this.getKeyHash(enc);
|
||||
};
|
||||
|
||||
@ -616,8 +625,10 @@ KeyRing.prototype.getHash = function getHash(enc) {
|
||||
KeyRing.prototype.getAddress = function getAddress(enc) {
|
||||
if (this.nested)
|
||||
return this.getNestedAddress(enc);
|
||||
|
||||
if (this.script)
|
||||
return this.getScriptAddress(enc);
|
||||
|
||||
return this.getKeyAddress(enc);
|
||||
};
|
||||
|
||||
@ -885,9 +896,9 @@ KeyRing.prototype.fromReader = function fromReader(br, network) {
|
||||
const key = br.readVarBytes();
|
||||
|
||||
if (key.length === 32) {
|
||||
const compressed = br.readU8() === 1;
|
||||
const compress = br.readU8() === 1;
|
||||
this.privateKey = key;
|
||||
this.publicKey = secp256k1.publicKeyCreate(key, compressed);
|
||||
this.publicKey = secp256k1.publicKeyCreate(key, compress);
|
||||
} else {
|
||||
this.publicKey = key;
|
||||
assert(secp256k1.publicKeyVerify(key), 'Invalid public key.');
|
||||
|
||||
@ -109,25 +109,24 @@ MemBlock.prototype.getCoinbaseHeight = function getCoinbaseHeight() {
|
||||
|
||||
MemBlock.prototype.parseCoinbaseHeight = function parseCoinbaseHeight() {
|
||||
const br = new BufferReader(this._raw, true);
|
||||
let count;
|
||||
|
||||
br.seek(80);
|
||||
|
||||
count = br.readVarint();
|
||||
const txCount = br.readVarint();
|
||||
|
||||
if (count === 0)
|
||||
if (txCount === 0)
|
||||
return -1;
|
||||
|
||||
br.seek(4);
|
||||
|
||||
count = br.readVarint();
|
||||
let inCount = br.readVarint();
|
||||
|
||||
if (count === 0) {
|
||||
if (inCount === 0) {
|
||||
if (br.readU8() !== 0)
|
||||
count = br.readVarint();
|
||||
inCount = br.readVarint();
|
||||
}
|
||||
|
||||
if (count === 0)
|
||||
if (inCount === 0)
|
||||
return -1;
|
||||
|
||||
br.seek(36);
|
||||
|
||||
@ -228,7 +228,7 @@ MerkleBlock.prototype.extractTree = function extractTree() {
|
||||
}
|
||||
|
||||
const left = traverse(height - 1, pos * 2);
|
||||
let right = null;
|
||||
let right;
|
||||
|
||||
if (pos * 2 + 1 < width(height - 1)) {
|
||||
right = traverse(height - 1, pos * 2 + 1);
|
||||
@ -563,7 +563,7 @@ MerkleBlock.fromMatches = function fromMatches(block, matches) {
|
||||
return leaves[pos];
|
||||
|
||||
const left = hash(height - 1, pos * 2, leaves);
|
||||
let right = null;
|
||||
let right;
|
||||
|
||||
if (pos * 2 + 1 < width(height - 1))
|
||||
right = hash(height - 1, pos * 2 + 1, leaves);
|
||||
|
||||
@ -733,22 +733,12 @@ MTX.prototype.signVector = function signVector(prev, vector, sig, ring) {
|
||||
|
||||
// Multisig
|
||||
if (prev.isMultisig()) {
|
||||
const keys = [];
|
||||
|
||||
// Grab `m` value (number of sigs required).
|
||||
const m = prev.getSmall(0);
|
||||
if (vector.getSmall(0) !== 0)
|
||||
throw new Error('Input has not been templated.');
|
||||
|
||||
// Grab `n` value (number of keys).
|
||||
const n = prev.getSmall(prev.length - 2);
|
||||
|
||||
// Grab the redeem script's keys to figure
|
||||
// out where our key should go.
|
||||
for (let i = 1; i < prev.length - 2; i++)
|
||||
keys.push(prev.get(i));
|
||||
|
||||
if (vector.getSmall(0) !== 0)
|
||||
throw new Error('Input has not been templated.');
|
||||
|
||||
// Too many signature slots. Abort.
|
||||
if (vector.length - 1 > n)
|
||||
return false;
|
||||
@ -760,6 +750,9 @@ MTX.prototype.signVector = function signVector(prev, vector, sig, ring) {
|
||||
total++;
|
||||
}
|
||||
|
||||
// Grab `m` value (number of sigs required).
|
||||
const m = prev.getSmall(0);
|
||||
|
||||
// Signatures are already finalized.
|
||||
if (total === m && vector.length - 1 === m)
|
||||
return true;
|
||||
@ -769,6 +762,12 @@ MTX.prototype.signVector = function signVector(prev, vector, sig, ring) {
|
||||
while (vector.length - 1 < n)
|
||||
vector.push(opcodes.OP_0);
|
||||
|
||||
// Grab the redeem script's keys to figure
|
||||
// out where our key should go.
|
||||
const keys = [];
|
||||
for (let i = 1; i < prev.length - 2; i++)
|
||||
keys.push(prev.get(i));
|
||||
|
||||
// Find the key index so we can place
|
||||
// the signature in the same index.
|
||||
let keyIndex = util.indexOf(keys, ring.publicKey);
|
||||
@ -919,17 +918,17 @@ MTX.prototype.isVectorSigned = function isVectorSigned(prev, vector) {
|
||||
// Grab `m` value (number of required sigs).
|
||||
const m = prev.getSmall(0);
|
||||
|
||||
// Ensure we have the correct number
|
||||
// of required signatures.
|
||||
if (vector.length - 1 !== m)
|
||||
return false;
|
||||
|
||||
// Ensure all members are signatures.
|
||||
for (let i = 1; i < vector.length; i++) {
|
||||
if (!Script.isSignature(vector.get(i)))
|
||||
return false;
|
||||
}
|
||||
|
||||
// Ensure we have the correct number
|
||||
// of required signatures.
|
||||
if (vector.length - 1 !== m)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1839,8 +1838,10 @@ function sortRandom(a, b) {
|
||||
function sortValue(a, b) {
|
||||
if (a.height === -1 && b.height !== -1)
|
||||
return 1;
|
||||
|
||||
if (a.height !== -1 && b.height === -1)
|
||||
return -1;
|
||||
|
||||
return b.value - a.value;
|
||||
}
|
||||
|
||||
|
||||
@ -144,8 +144,10 @@ Output.prototype.getAddress = function getAddress() {
|
||||
|
||||
Output.prototype.getHash = function getHash(enc) {
|
||||
const addr = this.getAddress();
|
||||
|
||||
if (!addr)
|
||||
return;
|
||||
return null;
|
||||
|
||||
return addr.getHash(enc);
|
||||
};
|
||||
|
||||
@ -204,12 +206,11 @@ Output.prototype.getJSON = function getJSON(network) {
|
||||
|
||||
Output.prototype.getDustThreshold = function getDustThreshold(rate) {
|
||||
const scale = consensus.WITNESS_SCALE_FACTOR;
|
||||
let size;
|
||||
|
||||
if (this.script.isUnspendable())
|
||||
return 0;
|
||||
|
||||
size = this.getSize();
|
||||
let size = this.getSize();
|
||||
|
||||
if (this.script.isProgram()) {
|
||||
// 75% segwit discount applied to script size.
|
||||
|
||||
@ -303,7 +303,6 @@ TX.prototype.frame = function frame() {
|
||||
}
|
||||
|
||||
let raw;
|
||||
|
||||
if (this.hasWitness())
|
||||
raw = this.frameWitness();
|
||||
else
|
||||
@ -1116,14 +1115,13 @@ TX.prototype.getAddresses = function getAddresses(view) {
|
||||
*/
|
||||
|
||||
TX.prototype.getInputHashes = function getInputHashes(view, enc) {
|
||||
const hashes = [];
|
||||
|
||||
if (enc === 'hex') {
|
||||
const [, table] = this._getInputAddresses(view);
|
||||
return Object.keys(table);
|
||||
}
|
||||
|
||||
const addrs = this.getInputAddresses(view);
|
||||
const hashes = [];
|
||||
|
||||
for (const addr of addrs)
|
||||
hashes.push(addr.getHash());
|
||||
@ -1137,14 +1135,13 @@ TX.prototype.getInputHashes = function getInputHashes(view, enc) {
|
||||
*/
|
||||
|
||||
TX.prototype.getOutputHashes = function getOutputHashes(enc) {
|
||||
const hashes = [];
|
||||
|
||||
if (enc === 'hex') {
|
||||
const [, table] = this._getOutputAddresses();
|
||||
return Object.keys(table);
|
||||
}
|
||||
|
||||
const addrs = this.getOutputAddresses();
|
||||
const hashes = [];
|
||||
|
||||
for (const addr of addrs)
|
||||
hashes.push(addr.getHash());
|
||||
@ -1159,14 +1156,13 @@ TX.prototype.getOutputHashes = function getOutputHashes(enc) {
|
||||
*/
|
||||
|
||||
TX.prototype.getHashes = function getHashes(view, enc) {
|
||||
const hashes = [];
|
||||
|
||||
if (enc === 'hex') {
|
||||
const [, table] = this._getAddresses(view);
|
||||
return Object.keys(table);
|
||||
}
|
||||
|
||||
const addrs = this.getAddresses(view);
|
||||
const hashes = [];
|
||||
|
||||
for (const addr of addrs)
|
||||
hashes.push(addr.getHash());
|
||||
@ -1407,9 +1403,6 @@ TX.prototype.isSane = function isSane() {
|
||||
*/
|
||||
|
||||
TX.prototype.checkSanity = function checkSanity() {
|
||||
const prevout = new Set();
|
||||
let total = 0;
|
||||
|
||||
if (this.inputs.length === 0)
|
||||
return [false, 'bad-txns-vin-empty', 100];
|
||||
|
||||
@ -1419,6 +1412,8 @@ TX.prototype.checkSanity = function checkSanity() {
|
||||
if (this.getBaseSize() > consensus.MAX_BLOCK_SIZE)
|
||||
return [false, 'bad-txns-oversize', 100];
|
||||
|
||||
let total = 0;
|
||||
|
||||
for (const output of this.outputs) {
|
||||
if (output.value < 0)
|
||||
return [false, 'bad-txns-vout-negative', 100];
|
||||
@ -1432,10 +1427,14 @@ TX.prototype.checkSanity = function checkSanity() {
|
||||
return [false, 'bad-txns-txouttotal-toolarge', 100];
|
||||
}
|
||||
|
||||
const prevout = new Set();
|
||||
|
||||
for (const input of this.inputs) {
|
||||
const key = input.prevout.toKey();
|
||||
|
||||
if (prevout.has(key))
|
||||
return [false, 'bad-txns-inputs-duplicate', 100];
|
||||
|
||||
prevout.add(key);
|
||||
}
|
||||
|
||||
@ -1479,8 +1478,6 @@ TX.prototype.isStandard = function isStandard() {
|
||||
*/
|
||||
|
||||
TX.prototype.checkStandard = function checkStandard() {
|
||||
let nulldata = 0;
|
||||
|
||||
if (this.version < 1 || this.version > policy.MAX_TX_VERSION)
|
||||
return [false, 'version', 0];
|
||||
|
||||
@ -1495,6 +1492,8 @@ TX.prototype.checkStandard = function checkStandard() {
|
||||
return [false, 'scriptsig-not-pushonly', 0];
|
||||
}
|
||||
|
||||
let nulldata = 0;
|
||||
|
||||
for (const output of this.outputs) {
|
||||
if (!output.script.isStandard())
|
||||
return [false, 'scriptpubkey', 0];
|
||||
@ -1706,10 +1705,10 @@ TX.prototype.verifyInputs = function verifyInputs(view, height) {
|
||||
*/
|
||||
|
||||
TX.prototype.checkInputs = function checkInputs(view, height) {
|
||||
let total = 0;
|
||||
|
||||
assert(typeof height === 'number');
|
||||
|
||||
let total = 0;
|
||||
|
||||
for (const {prevout} of this.inputs) {
|
||||
let coin = view.getEntry(prevout);
|
||||
|
||||
@ -1781,16 +1780,16 @@ TX.prototype.getModifiedSize = function getModifiedSize(size) {
|
||||
*/
|
||||
|
||||
TX.prototype.getPriority = function getPriority(view, height, size) {
|
||||
let sum = 0;
|
||||
|
||||
assert(typeof height === 'number', 'Must pass in height.');
|
||||
|
||||
if (this.isCoinbase())
|
||||
return sum;
|
||||
return 0;
|
||||
|
||||
if (size == null)
|
||||
size = this.getVirtualSize();
|
||||
|
||||
let sum = 0;
|
||||
|
||||
for (const {prevout} of this.inputs) {
|
||||
const coin = view.getOutput(prevout);
|
||||
|
||||
@ -1818,10 +1817,10 @@ TX.prototype.getPriority = function getPriority(view, height, size) {
|
||||
*/
|
||||
|
||||
TX.prototype.getChainValue = function getChainValue(view) {
|
||||
let value = 0;
|
||||
|
||||
if (this.isCoinbase())
|
||||
return value;
|
||||
return 0;
|
||||
|
||||
let value = 0;
|
||||
|
||||
for (const {prevout} of this.inputs) {
|
||||
const coin = view.getOutput(prevout);
|
||||
@ -1829,9 +1828,9 @@ TX.prototype.getChainValue = function getChainValue(view) {
|
||||
if (!coin)
|
||||
continue;
|
||||
|
||||
const coinHeight = view.getHeight(prevout);
|
||||
const height = view.getHeight(prevout);
|
||||
|
||||
if (coinHeight === -1)
|
||||
if (height === -1)
|
||||
continue;
|
||||
|
||||
value += coin.value;
|
||||
@ -1917,11 +1916,11 @@ TX.prototype.getRate = function getRate(view, size) {
|
||||
*/
|
||||
|
||||
TX.prototype.getPrevout = function getPrevout() {
|
||||
const prevout = Object.create(null);
|
||||
|
||||
if (this.isCoinbase())
|
||||
return [];
|
||||
|
||||
const prevout = Object.create(null);
|
||||
|
||||
for (const input of this.inputs)
|
||||
prevout[input.prevout.hash] = true;
|
||||
|
||||
|
||||
@ -116,8 +116,10 @@ Network.prototype._init = function _init() {
|
||||
|
||||
Network.prototype.byBit = function byBit(bit) {
|
||||
const index = util.binarySearch(this.deploys, bit, cmpBit);
|
||||
|
||||
if (index === -1)
|
||||
return null;
|
||||
|
||||
return this.deploys[index];
|
||||
};
|
||||
|
||||
|
||||
@ -217,8 +217,6 @@ exports.BLOCK_PRIORITY_THRESHOLD = exports.FREE_THRESHOLD;
|
||||
*/
|
||||
|
||||
exports.getMinFee = function getMinFee(size, rate) {
|
||||
let fee;
|
||||
|
||||
if (rate == null)
|
||||
rate = exports.MIN_RELAY;
|
||||
|
||||
@ -228,7 +226,7 @@ exports.getMinFee = function getMinFee(size, rate) {
|
||||
if (size === 0)
|
||||
return 0;
|
||||
|
||||
fee = Math.floor(rate * size / 1000);
|
||||
let fee = Math.floor(rate * size / 1000);
|
||||
|
||||
if (fee === 0 && rate > 0)
|
||||
fee = rate;
|
||||
@ -246,8 +244,6 @@ exports.getMinFee = function getMinFee(size, rate) {
|
||||
*/
|
||||
|
||||
exports.getRoundFee = function getRoundFee(size, rate) {
|
||||
let fee;
|
||||
|
||||
if (rate == null)
|
||||
rate = exports.MIN_RELAY;
|
||||
|
||||
@ -257,7 +253,7 @@ exports.getRoundFee = function getRoundFee(size, rate) {
|
||||
if (size === 0)
|
||||
return 0;
|
||||
|
||||
fee = rate * Math.ceil(size / 1000);
|
||||
let fee = rate * Math.ceil(size / 1000);
|
||||
|
||||
if (fee === 0 && rate > 0)
|
||||
fee = rate;
|
||||
|
||||
@ -49,14 +49,14 @@ util.inherits(TimeData, EventEmitter);
|
||||
*/
|
||||
|
||||
TimeData.prototype.add = function add(id, time) {
|
||||
const sample = time - util.now();
|
||||
|
||||
if (this.samples.length >= this.limit)
|
||||
return;
|
||||
|
||||
if (this.known.has(id))
|
||||
return;
|
||||
|
||||
const sample = time - util.now();
|
||||
|
||||
this.known.set(id, sample);
|
||||
|
||||
util.binaryInsert(this.samples, sample, compare);
|
||||
|
||||
@ -555,50 +555,49 @@ exports.formatCode = function formatCode(code) {
|
||||
const out = [];
|
||||
|
||||
for (const op of code) {
|
||||
const data = op.data;
|
||||
let value = op.value;
|
||||
if (op.data) {
|
||||
// Direct push
|
||||
if (!exports.opcodesByVal[op.value]) {
|
||||
let size = op.value.toString(16);
|
||||
if (size.length < 2)
|
||||
size = '0' + size;
|
||||
out.push(`0x${size} 0x${op.data.toString('hex')}`);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (data) {
|
||||
let size = data.length.toString(16);
|
||||
// Pushdatas
|
||||
const symbol = exports.opcodesByVal[op.value];
|
||||
|
||||
let size = op.data.length.toString(16);
|
||||
|
||||
while (size.length % 2 !== 0)
|
||||
size = '0' + size;
|
||||
|
||||
if (!exports.opcodesByVal[value]) {
|
||||
value = value.toString(16);
|
||||
if (value.length < 2)
|
||||
value = '0' + value;
|
||||
value = `0x${value} 0x${data.toString('hex')}`;
|
||||
out.push(value);
|
||||
continue;
|
||||
}
|
||||
out.push(`${symbol} 0x${size} 0x${op.data.toString('hex')}`);
|
||||
|
||||
value = exports.opcodesByVal[value];
|
||||
value = `${value} 0x${size} 0x${data.toString('hex')}`;
|
||||
out.push(value);
|
||||
continue;
|
||||
}
|
||||
|
||||
assert(typeof value === 'number');
|
||||
|
||||
if (exports.opcodesByVal[value]) {
|
||||
value = exports.opcodesByVal[value];
|
||||
out.push(value);
|
||||
// Opcodes
|
||||
if (exports.opcodesByVal[op.value]) {
|
||||
const symbol = exports.opcodesByVal[op.value];
|
||||
out.push(symbol);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (value === -1) {
|
||||
// Bad push
|
||||
if (op.value === -1) {
|
||||
out.push('OP_INVALIDOPCODE');
|
||||
break;
|
||||
}
|
||||
|
||||
value = value.toString(16);
|
||||
// Unknown opcodes
|
||||
let symbol = op.value.toString(16);
|
||||
|
||||
if (value.length < 2)
|
||||
value = '0' + value;
|
||||
if (symbol.length < 2)
|
||||
symbol = '0' + symbol;
|
||||
|
||||
value = `0x${value}`;
|
||||
out.push(value);
|
||||
out.push(`0x${symbol}`);
|
||||
}
|
||||
|
||||
return out.join(' ');
|
||||
@ -646,29 +645,28 @@ exports.formatItem = function formatItem(data, decode) {
|
||||
*/
|
||||
|
||||
exports.formatASM = function formatASM(code, decode) {
|
||||
if (code.length > 0) {
|
||||
if (code[0].value === exports.opcodes.OP_RETURN)
|
||||
decode = false;
|
||||
}
|
||||
|
||||
const out = [];
|
||||
|
||||
if (code.length > 0 && code[0].value === exports.opcodes.OP_RETURN)
|
||||
decode = false;
|
||||
|
||||
for (const op of code) {
|
||||
let data = op.data;
|
||||
let value = op.value;
|
||||
|
||||
if (value === -1) {
|
||||
if (op.value === -1) {
|
||||
out.push('[error]');
|
||||
break;
|
||||
}
|
||||
|
||||
if (data) {
|
||||
data = exports.formatItem(data, decode);
|
||||
if (op.data) {
|
||||
const data = exports.formatItem(op.data, decode);
|
||||
out.push(data);
|
||||
continue;
|
||||
}
|
||||
|
||||
value = exports.opcodesByVal[value] || 'OP_UNKNOWN';
|
||||
const symbol = exports.opcodesByVal[op.value] || 'OP_UNKNOWN';
|
||||
|
||||
out.push(value);
|
||||
out.push(symbol);
|
||||
}
|
||||
|
||||
return out.join(' ');
|
||||
|
||||
@ -186,7 +186,6 @@ Opcode.prototype.getSize = function getSize() {
|
||||
|
||||
Opcode.prototype.fromReader = function fromReader(br) {
|
||||
const op = br.readU8();
|
||||
let size;
|
||||
|
||||
if (op >= 0x01 && op <= 0x4b) {
|
||||
if (br.left() < op) {
|
||||
@ -199,6 +198,8 @@ Opcode.prototype.fromReader = function fromReader(br) {
|
||||
return this;
|
||||
}
|
||||
|
||||
let size;
|
||||
|
||||
switch (op) {
|
||||
case opcodes.OP_PUSHDATA1:
|
||||
if (br.left() < 1) {
|
||||
|
||||
@ -411,11 +411,11 @@ Script.fromJSON = function fromJSON(json) {
|
||||
*/
|
||||
|
||||
Script.prototype.getSubscript = function getSubscript(lastSep) {
|
||||
const code = [];
|
||||
|
||||
if (lastSep === 0)
|
||||
return this.clone();
|
||||
|
||||
const code = [];
|
||||
|
||||
for (let i = lastSep; i < this.code.length; i++) {
|
||||
const op = this.code[i];
|
||||
|
||||
@ -483,25 +483,26 @@ Script.prototype.removeSeparators = function removeSeparators() {
|
||||
*/
|
||||
|
||||
Script.prototype.execute = function execute(stack, flags, tx, index, value, version) {
|
||||
const state = [];
|
||||
const alt = [];
|
||||
let lastSep = 0;
|
||||
let opCount = 0;
|
||||
let negate = 0;
|
||||
let minimal = false;
|
||||
|
||||
if (flags == null)
|
||||
flags = Script.flags.STANDARD_VERIFY_FLAGS;
|
||||
|
||||
if (version == null)
|
||||
version = 0;
|
||||
|
||||
if (flags & Script.flags.VERIFY_MINIMALDATA)
|
||||
minimal = true;
|
||||
|
||||
if (this.getSize() > consensus.MAX_SCRIPT_SIZE)
|
||||
throw new ScriptError('SCRIPT_SIZE');
|
||||
|
||||
const state = [];
|
||||
const alt = [];
|
||||
|
||||
let lastSep = 0;
|
||||
let opCount = 0;
|
||||
let negate = 0;
|
||||
let minimal = false;
|
||||
|
||||
if (flags & Script.flags.VERIFY_MINIMALDATA)
|
||||
minimal = true;
|
||||
|
||||
for (let ip = 0; ip < this.code.length; ip++) {
|
||||
const op = this.code[ip];
|
||||
|
||||
@ -1667,15 +1668,15 @@ Script.fromCommitment = function fromCommitment(hash, flags) {
|
||||
|
||||
Script.prototype.getRedeem = function getRedeem() {
|
||||
if (this.code.length === 0)
|
||||
return;
|
||||
return null;
|
||||
|
||||
if (!this.isPushOnly())
|
||||
return;
|
||||
return null;
|
||||
|
||||
const redeem = this.code[this.code.length - 1];
|
||||
|
||||
if (!redeem.data)
|
||||
return;
|
||||
return null;
|
||||
|
||||
return Script.fromRaw(redeem.data);
|
||||
};
|
||||
@ -1987,7 +1988,7 @@ Script.prototype.isCommitment = function isCommitment() {
|
||||
|
||||
Script.prototype.getCommitmentHash = function getCommitmentHash() {
|
||||
if (!this.isCommitment())
|
||||
return;
|
||||
return null;
|
||||
|
||||
return this.raw.slice(6, 38);
|
||||
};
|
||||
@ -2021,7 +2022,7 @@ Script.prototype.isProgram = function isProgram() {
|
||||
|
||||
Script.prototype.toProgram = function toProgram() {
|
||||
if (!this.isProgram())
|
||||
return;
|
||||
return null;
|
||||
|
||||
const version = common.getSmall(this.raw[0]);
|
||||
const data = this.raw.slice(2);
|
||||
@ -2671,12 +2672,11 @@ Script.prototype.fromString = function fromString(code) {
|
||||
if (code.length === 0)
|
||||
return this;
|
||||
|
||||
code = code.split(/\s+/);
|
||||
|
||||
const items = code.split(/\s+/);
|
||||
const bw = new BufferWriter();
|
||||
|
||||
for (let op of code) {
|
||||
let symbol = op;
|
||||
for (const item of items) {
|
||||
let symbol = item;
|
||||
|
||||
if (!util.isUpperCase(symbol))
|
||||
symbol = symbol.toUpperCase();
|
||||
@ -2684,29 +2684,37 @@ Script.prototype.fromString = function fromString(code) {
|
||||
if (!util.startsWith(symbol, 'OP_'))
|
||||
symbol = `OP_${symbol}`;
|
||||
|
||||
if (opcodes[symbol] == null) {
|
||||
if (op[0] === '\'') {
|
||||
assert(op[op.length - 1] === '\'', 'Unknown opcode.');
|
||||
op = op.slice(1, -1);
|
||||
op = Opcode.fromString(op);
|
||||
const value = opcodes[symbol];
|
||||
|
||||
if (value == null) {
|
||||
if (item[0] === '\'') {
|
||||
assert(item[item.length - 1] === '\'', 'Unknown opcode.');
|
||||
const str = item.slice(1, -1);
|
||||
const op = Opcode.fromString(str);
|
||||
bw.writeBytes(op.toRaw());
|
||||
continue;
|
||||
}
|
||||
if (/^-?\d+$/.test(op)) {
|
||||
op = new BN(op, 10);
|
||||
op = Opcode.fromNumber(op);
|
||||
|
||||
if (/^-?\d+$/.test(item)) {
|
||||
const num = new BN(item, 10);
|
||||
const op = Opcode.fromNumber(num);
|
||||
bw.writeBytes(op.toRaw());
|
||||
continue;
|
||||
}
|
||||
assert(op.indexOf('0x') === 0, 'Unknown opcode.');
|
||||
op = op.substring(2);
|
||||
assert(util.isHex(op), 'Unknown opcode.');
|
||||
op = Buffer.from(op, 'hex');
|
||||
bw.writeBytes(op);
|
||||
|
||||
assert(item.indexOf('0x') === 0, 'Unknown opcode.');
|
||||
|
||||
const str = item.substring(2);
|
||||
const data = Buffer.from(str, 'hex');
|
||||
|
||||
assert(data.length === str.length / 2, 'Unknown opcode.');
|
||||
|
||||
bw.writeBytes(data);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
bw.writeU8(opcodes[symbol]);
|
||||
bw.writeU8(value);
|
||||
}
|
||||
|
||||
return this.fromRaw(bw.render());
|
||||
@ -2738,8 +2746,6 @@ Script.fromString = function fromString(code) {
|
||||
*/
|
||||
|
||||
Script.verify = function verify(input, witness, output, tx, i, value, flags) {
|
||||
let hadWitness = false;
|
||||
|
||||
if (flags == null)
|
||||
flags = Script.flags.STANDARD_VERIFY_FLAGS;
|
||||
|
||||
@ -2766,6 +2772,8 @@ Script.verify = function verify(input, witness, output, tx, i, value, flags) {
|
||||
if (stack.length === 0 || !Script.bool(stack.top(-1)))
|
||||
throw new ScriptError('EVAL_FALSE');
|
||||
|
||||
let hadWitness = false;
|
||||
|
||||
if ((flags & Script.flags.VERIFY_WITNESS) && output.isProgram()) {
|
||||
hadWitness = true;
|
||||
|
||||
@ -2852,12 +2860,13 @@ Script.verify = function verify(input, witness, output, tx, i, value, flags) {
|
||||
|
||||
Script.verifyProgram = function verifyProgram(witness, output, flags, tx, i, value) {
|
||||
const program = output.toProgram();
|
||||
const stack = witness.toStack();
|
||||
let redeem;
|
||||
|
||||
assert(program, 'verifyProgram called on non-witness-program.');
|
||||
assert((flags & Script.flags.VERIFY_WITNESS) !== 0);
|
||||
|
||||
const stack = witness.toStack();
|
||||
let redeem;
|
||||
|
||||
if (program.version === 0) {
|
||||
if (program.data.length === 32) {
|
||||
if (stack.length === 0)
|
||||
@ -2923,11 +2932,6 @@ Script.verifyProgram = function verifyProgram(witness, output, flags, tx, i, val
|
||||
*/
|
||||
|
||||
Script.verifyMast = function verifyMast(program, stack, output, flags, tx, i, value) {
|
||||
let mastRoot = new BufferWriter();
|
||||
let scriptRoot = new BufferWriter();
|
||||
let scripts = new BufferWriter();
|
||||
let version = 0;
|
||||
|
||||
assert(program.version === 1);
|
||||
assert((flags & Script.flags.VERIFY_MAST) !== 0);
|
||||
|
||||
@ -2943,11 +2947,14 @@ Script.verifyMast = function verifyMast(program, stack, output, flags, tx, i, va
|
||||
throw new ScriptError('INVALID_MAST_STACK');
|
||||
|
||||
let ops = subscripts;
|
||||
let scriptRoot = new BufferWriter();
|
||||
scriptRoot.writeU8(subscripts);
|
||||
|
||||
if (metadata[metadata.length - 1] === 0x00)
|
||||
throw new ScriptError('INVALID_MAST_STACK');
|
||||
|
||||
let version = 0;
|
||||
|
||||
for (let j = 1; j < metadata.length; j++)
|
||||
version |= metadata[i] << 8 * (j - 1);
|
||||
|
||||
@ -2959,6 +2966,7 @@ Script.verifyMast = function verifyMast(program, stack, output, flags, tx, i, va
|
||||
throw new ScriptError('DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM');
|
||||
}
|
||||
|
||||
let mastRoot = new BufferWriter();
|
||||
mastRoot.writeU32(version);
|
||||
|
||||
const pathdata = stack.top(-2);
|
||||
@ -3004,6 +3012,7 @@ Script.verifyMast = function verifyMast(program, stack, output, flags, tx, i, va
|
||||
throw new ScriptError('INVALID_MAST_STACK');
|
||||
}
|
||||
|
||||
let scripts = new BufferWriter();
|
||||
scripts.writeBytes(output.raw);
|
||||
|
||||
for (let j = 0; j < subscripts; j++) {
|
||||
|
||||
@ -162,12 +162,11 @@ ScriptNum.prototype.toJSON = function toJSON() {
|
||||
};
|
||||
|
||||
ScriptNum.prototype.fromString = function fromString(str, base) {
|
||||
let nonzero = 0;
|
||||
let negative = false;
|
||||
|
||||
if (!base)
|
||||
base = 10;
|
||||
|
||||
let negative = false;
|
||||
|
||||
if (str[0] === '-') {
|
||||
assert(str.length > 1, 'Non-numeric string passed.');
|
||||
str = str.substring(1);
|
||||
@ -179,6 +178,7 @@ ScriptNum.prototype.fromString = function fromString(str, base) {
|
||||
this.value = 0;
|
||||
|
||||
if (base === 10 || base === 'dec') {
|
||||
let nonzero = 0;
|
||||
for (let i = 0; i < str.length; i++) {
|
||||
let ch = str[i];
|
||||
|
||||
@ -204,6 +204,7 @@ ScriptNum.prototype.fromString = function fromString(str, base) {
|
||||
}
|
||||
|
||||
if (base === 16 || base === 'hex') {
|
||||
let nonzero = 0;
|
||||
for (let i = 0; i < str.length; i++) {
|
||||
let ch = str[i];
|
||||
|
||||
@ -320,20 +321,20 @@ ScriptNum.fromRaw = function fromRaw(data, minimal, limit) {
|
||||
|
||||
ScriptNum.prototype.toRaw = function toRaw() {
|
||||
let value = this.value;
|
||||
let negative = false;
|
||||
let offset, size;
|
||||
|
||||
// Zeroes are always empty arrays.
|
||||
if (value === 0)
|
||||
return EMPTY_ARRAY;
|
||||
|
||||
// Need to append sign bit.
|
||||
let negative = false;
|
||||
if (value < 0) {
|
||||
negative = true;
|
||||
value = -value;
|
||||
}
|
||||
|
||||
// Gauge buffer size.
|
||||
let offset, size;
|
||||
if (value <= 0xff) {
|
||||
offset = (value & 0x80) ? 1 : 0;
|
||||
size = 1;
|
||||
|
||||
@ -183,7 +183,7 @@ Stack.prototype.remove = function remove(i) {
|
||||
i = this.items.length + i;
|
||||
|
||||
if (i >= this.items.length)
|
||||
return;
|
||||
return undefined;
|
||||
|
||||
return this.items.splice(i, 1)[0];
|
||||
};
|
||||
|
||||
@ -78,13 +78,11 @@ Witness.prototype.__defineSetter__('length', function(length) {
|
||||
Witness.prototype.fromOptions = function fromOptions(options) {
|
||||
assert(options, 'Witness data is required.');
|
||||
|
||||
let items = options.items;
|
||||
if (Array.isArray(options))
|
||||
return this.fromArray(options);
|
||||
|
||||
if (!items)
|
||||
items = options;
|
||||
|
||||
if (items)
|
||||
this.fromArray(items);
|
||||
if (options.items)
|
||||
return this.fromArray(options.items);
|
||||
|
||||
return this;
|
||||
};
|
||||
@ -294,12 +292,12 @@ Witness.prototype.test = function test(filter) {
|
||||
|
||||
Witness.prototype.getRedeem = function getRedeem() {
|
||||
if (this.items.length === 0)
|
||||
return;
|
||||
return null;
|
||||
|
||||
const redeem = this.items[this.items.length - 1];
|
||||
|
||||
if (!redeem)
|
||||
return;
|
||||
return null;
|
||||
|
||||
return Script.fromRaw(redeem);
|
||||
};
|
||||
@ -496,8 +494,10 @@ Witness.prototype.getSmall = function getSmall(i) {
|
||||
|
||||
Witness.prototype.getNumber = function getNumber(i) {
|
||||
const item = this.items[i];
|
||||
|
||||
if (!item || item.length > 5)
|
||||
return;
|
||||
return null;
|
||||
|
||||
return common.num(item, false, 5);
|
||||
};
|
||||
|
||||
@ -509,8 +509,10 @@ Witness.prototype.getNumber = function getNumber(i) {
|
||||
|
||||
Witness.prototype.getString = function getString(i) {
|
||||
const item = this.items[i];
|
||||
|
||||
if (!item)
|
||||
return;
|
||||
return null;
|
||||
|
||||
return item.toString('utf8');
|
||||
};
|
||||
|
||||
|
||||
@ -123,8 +123,10 @@ ASN1.readSeq = function readSeq(br) {
|
||||
|
||||
ASN1.implicit = function implicit(br, type) {
|
||||
const tag = ASN1.readTag(br);
|
||||
|
||||
if (tag.type !== type)
|
||||
throw new Error(`Unexpected tag: ${tag.type}.`);
|
||||
|
||||
return tag;
|
||||
};
|
||||
|
||||
@ -138,10 +140,12 @@ ASN1.implicit = function implicit(br, type) {
|
||||
ASN1.explicit = function explicit(br, type) {
|
||||
const offset = br.offset;
|
||||
const tag = ASN1.readTag(br);
|
||||
|
||||
if (tag.type !== type) {
|
||||
br.offset = offset;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
@ -158,15 +162,15 @@ ASN1.seq = function seq(br) {
|
||||
/**
|
||||
* Read implicit int.
|
||||
* @param {BufferReader} br
|
||||
* @param {Boolean?} readNum
|
||||
* @param {Boolean?} cast
|
||||
* @returns {Buffer|Number}
|
||||
*/
|
||||
|
||||
ASN1.readInt = function readInt(br, readNum) {
|
||||
ASN1.readInt = function readInt(br, cast) {
|
||||
const tag = ASN1.implicit(br, 0x02);
|
||||
const num = br.readBytes(tag.size);
|
||||
|
||||
if (readNum)
|
||||
if (cast)
|
||||
return num.readUIntBE(0, num.length);
|
||||
|
||||
return num;
|
||||
@ -183,6 +187,7 @@ ASN1.readInt = function readInt(br, readNum) {
|
||||
ASN1.readExplicitInt = function readExplicitInt(br, type, readNum) {
|
||||
if (!ASN1.explicit(br, type))
|
||||
return -1;
|
||||
|
||||
return ASN1.readInt(br, readNum);
|
||||
};
|
||||
|
||||
@ -210,7 +215,7 @@ ASN1.readString = function readString(br) {
|
||||
switch (tag.type) {
|
||||
case 0x03: { // bitstr
|
||||
const str = br.readBytes(tag.size);
|
||||
return ASN1.alignBitstr(str);
|
||||
return ASN1.alignBitstr(str).toString('utf8');
|
||||
}
|
||||
// Note:
|
||||
// Fuck all these.
|
||||
|
||||
@ -183,7 +183,7 @@ AsyncEmitter.prototype.listeners = function listeners(type) {
|
||||
const listeners = this._events[type];
|
||||
|
||||
if (!listeners)
|
||||
return result;
|
||||
return [];
|
||||
|
||||
const result = [];
|
||||
|
||||
@ -236,7 +236,7 @@ AsyncEmitter.prototype.emit = function emit(type) {
|
||||
return;
|
||||
}
|
||||
|
||||
let args = null;
|
||||
let args;
|
||||
|
||||
for (let i = 0; i < listeners.length; i++) {
|
||||
const listener = listeners[i];
|
||||
@ -299,7 +299,7 @@ AsyncEmitter.prototype.fire = async function fire(type) {
|
||||
return;
|
||||
}
|
||||
|
||||
let args = null;
|
||||
let args;
|
||||
|
||||
for (let i = 0; i < listeners.length; i++) {
|
||||
const listener = listeners[i];
|
||||
|
||||
@ -197,7 +197,7 @@ AsyncObject.prototype.fireHook = async function fireHook(type) {
|
||||
if (!listeners || listeners.length === 0)
|
||||
return;
|
||||
|
||||
let args = null;
|
||||
let args;
|
||||
|
||||
for (const handler of listeners) {
|
||||
switch (arguments.length) {
|
||||
|
||||
@ -27,10 +27,9 @@ exports.encode = function encode(data) {
|
||||
let str = '';
|
||||
let mode = 0;
|
||||
let left = 0;
|
||||
let i, ch;
|
||||
|
||||
for (i = 0; i < data.length; i++) {
|
||||
ch = data[i];
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
const ch = data[i];
|
||||
switch (mode) {
|
||||
case 0:
|
||||
str += base32[ch >>> 3];
|
||||
@ -64,7 +63,7 @@ exports.encode = function encode(data) {
|
||||
|
||||
if (mode > 0) {
|
||||
str += base32[left];
|
||||
for (i = 0; i < padding[mode]; i++)
|
||||
for (let i = 0; i < padding[mode]; i++)
|
||||
str += '=';
|
||||
}
|
||||
|
||||
@ -82,10 +81,10 @@ exports.decode = function decode(str) {
|
||||
let mode = 0;
|
||||
let left = 0;
|
||||
let j = 0;
|
||||
let i, ch;
|
||||
let i;
|
||||
|
||||
for (i = 0; i < str.length; i++) {
|
||||
ch = unbase32[str[i]];
|
||||
const ch = unbase32[str[i]];
|
||||
|
||||
if (ch == null)
|
||||
break;
|
||||
|
||||
@ -74,7 +74,6 @@ function polymod(pre) {
|
||||
*/
|
||||
|
||||
function serialize(hrp, data) {
|
||||
let str = '';
|
||||
let chk = 1;
|
||||
let i;
|
||||
|
||||
@ -92,6 +91,8 @@ function serialize(hrp, data) {
|
||||
|
||||
chk = polymod(chk);
|
||||
|
||||
let str = '';
|
||||
|
||||
for (let i = 0; i < hrp.length; i++) {
|
||||
const ch = hrp.charCodeAt(i);
|
||||
chk = polymod(chk) ^ (ch & 0x1f);
|
||||
|
||||
@ -262,8 +262,8 @@ Bloom.fromRate = function fromRate(items, rate, update) {
|
||||
assert(typeof rate === 'number', '`rate` must be a number.');
|
||||
assert(rate >= 0 && rate <= 1, '`rate` must be between 0.0 and 1.0.');
|
||||
|
||||
let size = (-1 / LN2SQUARED * items * Math.log(rate)) | 0;
|
||||
size = Math.max(8, size);
|
||||
const bits = (-1 / LN2SQUARED * items * Math.log(rate)) | 0;
|
||||
const size = Math.max(8, bits);
|
||||
|
||||
if (update !== -1) {
|
||||
assert(size <= Bloom.MAX_BLOOM_FILTER_SIZE * 8,
|
||||
|
||||
@ -21,6 +21,8 @@ const assert = require('assert');
|
||||
|
||||
function exec(gen) {
|
||||
return new Promise((resolve, reject) => {
|
||||
/* eslint no-use-before-define: "off" */
|
||||
|
||||
const step = (value, rejection) => {
|
||||
let next;
|
||||
|
||||
|
||||
@ -899,12 +899,12 @@ encoding.readVarint2BN = function readVarint2BN(data, off) {
|
||||
*/
|
||||
|
||||
encoding.writeVarint2BN = function writeVarint2BN(dst, num, off) {
|
||||
const tmp = [];
|
||||
let len = 0;
|
||||
|
||||
if (num.bitLength() <= 53)
|
||||
return encoding.writeVarint2(dst, num.toNumber());
|
||||
|
||||
const tmp = [];
|
||||
let len = 0;
|
||||
|
||||
for (;;) {
|
||||
tmp[len] = (num.words[0] & 0x7f) | (len ? 0x80 : 0x00);
|
||||
if (num.cmpn(0x7f) <= 0)
|
||||
@ -929,13 +929,13 @@ encoding.writeVarint2BN = function writeVarint2BN(dst, num, off) {
|
||||
*/
|
||||
|
||||
encoding.sizeVarint2BN = function sizeVarint2BN(num) {
|
||||
let size = 0;
|
||||
|
||||
if (num.bitLength() <= 53)
|
||||
return encoding.sizeVarint(num.toNumber());
|
||||
|
||||
num = num.clone();
|
||||
|
||||
let size = 0;
|
||||
|
||||
for (;;) {
|
||||
size++;
|
||||
if (num.cmpn(0x7f) <= 0)
|
||||
|
||||
@ -85,11 +85,11 @@ exports.writeFile = co.promisify(fs.writeFile);
|
||||
exports.writeFileSync = fs.writeFileSync;
|
||||
|
||||
exports.mkdirpSync = function mkdirpSync(dir, mode) {
|
||||
let [path, parts] = getParts(dir);
|
||||
|
||||
if (mode == null)
|
||||
mode = 0o750;
|
||||
|
||||
let [path, parts] = getParts(dir);
|
||||
|
||||
for (const part of parts) {
|
||||
path += part;
|
||||
|
||||
@ -109,11 +109,11 @@ exports.mkdirpSync = function mkdirpSync(dir, mode) {
|
||||
};
|
||||
|
||||
exports.mkdirp = async function mkdirp(dir, mode) {
|
||||
let [path, parts] = getParts(dir);
|
||||
|
||||
if (mode == null)
|
||||
mode = 0o750;
|
||||
|
||||
let [path, parts] = getParts(dir);
|
||||
|
||||
for (const part of parts) {
|
||||
path += part;
|
||||
|
||||
@ -138,6 +138,7 @@ function getParts(path) {
|
||||
path = path.replace(/\/+\.?$/, '');
|
||||
|
||||
const parts = path.split(/\/+/);
|
||||
|
||||
let root = '';
|
||||
|
||||
if (process.platform === 'win32') {
|
||||
|
||||
@ -63,12 +63,11 @@ GCSFilter.prototype.match = function match(key, data) {
|
||||
};
|
||||
|
||||
GCSFilter.prototype.matchAny = function matchAny(key, items) {
|
||||
assert(items.length > 0);
|
||||
|
||||
const br = new BitReader(this.data);
|
||||
const last1 = new Int64(0);
|
||||
const values = [];
|
||||
let i, last2;
|
||||
|
||||
assert(items.length > 0);
|
||||
|
||||
for (const item of items) {
|
||||
const hash = siphash(item, key).imod(this.m);
|
||||
@ -77,8 +76,8 @@ GCSFilter.prototype.matchAny = function matchAny(key, items) {
|
||||
|
||||
values.sort(compare);
|
||||
|
||||
last2 = values[0];
|
||||
i = 1;
|
||||
let last2 = values[0];
|
||||
let i = 1;
|
||||
|
||||
for (;;) {
|
||||
const cmp = last1.cmp(last2);
|
||||
@ -160,10 +159,6 @@ GCSFilter.prototype.toRaw = function toRaw() {
|
||||
};
|
||||
|
||||
GCSFilter.prototype.fromItems = function fromItems(P, key, items) {
|
||||
const bw = new BitWriter();
|
||||
let last = new Int64(0);
|
||||
const values = [];
|
||||
|
||||
assert(typeof P === 'number' && isFinite(P));
|
||||
assert(P >= 0 && P <= 32);
|
||||
|
||||
@ -178,6 +173,8 @@ GCSFilter.prototype.fromItems = function fromItems(P, key, items) {
|
||||
this.p = P;
|
||||
this.m = Int64(this.n).ishln(this.p);
|
||||
|
||||
const values = [];
|
||||
|
||||
for (const item of items) {
|
||||
assert(Buffer.isBuffer(item));
|
||||
const hash = siphash(item, key).imod(this.m);
|
||||
@ -186,6 +183,9 @@ GCSFilter.prototype.fromItems = function fromItems(P, key, items) {
|
||||
|
||||
values.sort(compare);
|
||||
|
||||
const bw = new BitWriter();
|
||||
let last = new Int64(0);
|
||||
|
||||
for (const hash of values) {
|
||||
const rem = hash.sub(last).imaskn(this.p);
|
||||
const value = hash.sub(last).isub(rem).ishrn(this.p);
|
||||
@ -439,8 +439,6 @@ BitReader.prototype.readBit = function readBit() {
|
||||
};
|
||||
|
||||
BitReader.prototype.readByte = function readByte() {
|
||||
let ch;
|
||||
|
||||
if (this.pos >= this.stream.length)
|
||||
throw new Error('EOF');
|
||||
|
||||
@ -454,12 +452,12 @@ BitReader.prototype.readByte = function readByte() {
|
||||
}
|
||||
|
||||
if (this.remain === 8) {
|
||||
ch = this.stream[this.pos];
|
||||
const ch = this.stream[this.pos];
|
||||
this.pos += 1;
|
||||
return ch;
|
||||
}
|
||||
|
||||
ch = this.stream[this.pos] & ((1 << this.remain) - 1);
|
||||
let ch = this.stream[this.pos] & ((1 << this.remain) - 1);
|
||||
ch <<= 8 - this.remain;
|
||||
|
||||
this.pos += 1;
|
||||
@ -473,11 +471,11 @@ BitReader.prototype.readByte = function readByte() {
|
||||
};
|
||||
|
||||
BitReader.prototype.readBits = function readBits(count) {
|
||||
let num = 0;
|
||||
|
||||
assert(count >= 0);
|
||||
assert(count <= 32);
|
||||
|
||||
let num = 0;
|
||||
|
||||
while (count >= 8) {
|
||||
num <<= 8;
|
||||
num |= this.readByte();
|
||||
@ -494,11 +492,11 @@ BitReader.prototype.readBits = function readBits(count) {
|
||||
};
|
||||
|
||||
BitReader.prototype.readBits64 = function readBits(count) {
|
||||
const num = new Int64();
|
||||
|
||||
assert(count >= 0);
|
||||
assert(count <= 64);
|
||||
|
||||
const num = new Int64();
|
||||
|
||||
if (count > 32) {
|
||||
num.hi = this.readBits(count - 32);
|
||||
num.lo = this.readBits(32);
|
||||
|
||||
@ -80,7 +80,7 @@ Heap.prototype.insert = function insert(item) {
|
||||
|
||||
Heap.prototype.shift = function shift() {
|
||||
if (this.items.length === 0)
|
||||
return;
|
||||
return null;
|
||||
|
||||
const n = this.items.length - 1;
|
||||
|
||||
@ -98,12 +98,12 @@ Heap.prototype.shift = function shift() {
|
||||
|
||||
Heap.prototype.remove = function remove(i) {
|
||||
if (this.items.length === 0)
|
||||
return;
|
||||
return null;
|
||||
|
||||
const n = this.items.length - 1;
|
||||
|
||||
if (i < 0 || i > n)
|
||||
return;
|
||||
return null;
|
||||
|
||||
if (n !== i) {
|
||||
this.swap(i, n);
|
||||
|
||||
@ -269,10 +269,10 @@ IP.isMapped = function isMapped(raw) {
|
||||
*/
|
||||
|
||||
IP.toBuffer = function toBuffer(str) {
|
||||
const raw = Buffer.allocUnsafe(16);
|
||||
|
||||
assert(typeof str === 'string');
|
||||
|
||||
const raw = Buffer.allocUnsafe(16);
|
||||
|
||||
if (IP.isV4String(str)) {
|
||||
raw.fill(0);
|
||||
raw[10] = 0xff;
|
||||
@ -329,8 +329,6 @@ IP.parseV4 = function parseV4(str, raw, offset) {
|
||||
IP.parseV6 = function parseV6(str, raw, offset) {
|
||||
const parts = str.split(':');
|
||||
let missing = 8 - parts.length;
|
||||
const start = offset;
|
||||
let colon = false;
|
||||
|
||||
assert(parts.length >= 2, 'Not an IPv6 address.');
|
||||
|
||||
@ -339,6 +337,9 @@ IP.parseV6 = function parseV6(str, raw, offset) {
|
||||
missing--;
|
||||
}
|
||||
|
||||
const start = offset;
|
||||
let colon = false;
|
||||
|
||||
for (let i = 0; i < parts.length; i++) {
|
||||
let word = parts[i];
|
||||
|
||||
@ -855,13 +856,13 @@ IP.getReachability = function getReachability(src, dest) {
|
||||
const IPV6_STRONG = 5;
|
||||
const PRIVATE = 6;
|
||||
|
||||
if (!IP.isRoutable(src))
|
||||
return UNREACHABLE;
|
||||
|
||||
const srcNet = IP.getNetwork(src);
|
||||
const destNet = IP.getNetwork(dest);
|
||||
const types = IP.types;
|
||||
|
||||
if (!IP.isRoutable(src))
|
||||
return UNREACHABLE;
|
||||
|
||||
switch (destNet) {
|
||||
case types.IPV4:
|
||||
switch (srcNet) {
|
||||
@ -958,16 +959,7 @@ IP.hasPrefix = function hasPrefix(raw, prefix) {
|
||||
IP.isEqual = function isEqual(a, b) {
|
||||
assert(a.length === 16);
|
||||
assert(b.length === 16);
|
||||
|
||||
if (a.compare)
|
||||
return a.compare(b) === 0;
|
||||
|
||||
for (let i = 0; i < a.length; i++) {
|
||||
if (a[i] !== b[i])
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return a.equals(b);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -994,7 +986,6 @@ IP.getInterfaces = function _getInterfaces(name, family) {
|
||||
continue;
|
||||
|
||||
let raw;
|
||||
|
||||
try {
|
||||
raw = IP.toBuffer(details.address);
|
||||
} catch (e) {
|
||||
|
||||
@ -55,7 +55,7 @@ List.prototype.shift = function shift() {
|
||||
const item = this.head;
|
||||
|
||||
if (!item)
|
||||
return;
|
||||
return null;
|
||||
|
||||
this.remove(item);
|
||||
|
||||
@ -91,7 +91,7 @@ List.prototype.pop = function pop() {
|
||||
const item = this.tail;
|
||||
|
||||
if (!item)
|
||||
return;
|
||||
return null;
|
||||
|
||||
this.remove(item);
|
||||
|
||||
|
||||
@ -174,10 +174,10 @@ Lock.prototype.destroy = function destroy() {
|
||||
|
||||
this.destroyed = true;
|
||||
|
||||
const jobs = this.jobs.slice();
|
||||
const jobs = this.jobs;
|
||||
|
||||
this.busy = false;
|
||||
this.jobs.length = 0;
|
||||
this.jobs = [];
|
||||
this.map.clear();
|
||||
this.current = null;
|
||||
|
||||
|
||||
@ -62,7 +62,6 @@ LRU.prototype._compact = function _compact() {
|
||||
return;
|
||||
|
||||
let item, next;
|
||||
|
||||
for (item = this.head; item; item = next) {
|
||||
if (this.size <= this.capacity)
|
||||
break;
|
||||
@ -150,14 +149,14 @@ LRU.prototype.set = function set(key, value) {
|
||||
|
||||
LRU.prototype.get = function get(key) {
|
||||
if (this.capacity === 0)
|
||||
return;
|
||||
return null;
|
||||
|
||||
key = key + '';
|
||||
|
||||
const item = this.map.get(key);
|
||||
|
||||
if (!item)
|
||||
return;
|
||||
return null;
|
||||
|
||||
this._removeList(item);
|
||||
this._appendList(item);
|
||||
@ -185,7 +184,7 @@ LRU.prototype.has = function get(key) {
|
||||
|
||||
LRU.prototype.remove = function remove(key) {
|
||||
if (this.capacity === 0)
|
||||
return;
|
||||
return false;
|
||||
|
||||
key = key + '';
|
||||
|
||||
|
||||
@ -132,10 +132,10 @@ MappedLock.prototype.unlock = function unlock(key) {
|
||||
*/
|
||||
|
||||
MappedLock.prototype.destroy = function destroy() {
|
||||
const map = this.jobs;
|
||||
|
||||
assert(!this.destroyed, 'Lock is already destroyed.');
|
||||
|
||||
const map = this.jobs;
|
||||
|
||||
this.destroyed = true;
|
||||
|
||||
this.jobs = new Map();
|
||||
|
||||
@ -72,14 +72,14 @@ function mul32(a, b) {
|
||||
const blo = b & 0xffff;
|
||||
const ahi = a >>> 16;
|
||||
const bhi = b >>> 16;
|
||||
let r, lo, hi;
|
||||
|
||||
lo = alo * blo;
|
||||
hi = (ahi * blo + bhi * alo) & 0xffff;
|
||||
let lo = alo * blo;
|
||||
let hi = (ahi * blo + bhi * alo) & 0xffff;
|
||||
|
||||
hi += lo >>> 16;
|
||||
lo &= 0xffff;
|
||||
r = (hi << 16) | lo;
|
||||
|
||||
let r = (hi << 16) | lo;
|
||||
|
||||
if (r < 0)
|
||||
r += 0x100000000;
|
||||
|
||||
@ -22,41 +22,56 @@ const PEM = exports;
|
||||
*/
|
||||
|
||||
PEM.parse = function parse(pem) {
|
||||
let buf = '';
|
||||
const chunks = [];
|
||||
let s, tag, type;
|
||||
let chunk = '';
|
||||
let tag;
|
||||
|
||||
while (pem.length) {
|
||||
if (s = /^-----BEGIN ([^\-]+)-----/.exec(pem)) {
|
||||
pem = pem.substring(s[0].length);
|
||||
tag = s[1];
|
||||
let m;
|
||||
|
||||
if (m = /^-----BEGIN ([^\-]+)-----/.exec(pem)) {
|
||||
pem = pem.substring(m[0].length);
|
||||
tag = m[1];
|
||||
continue;
|
||||
}
|
||||
if (s = /^-----END ([^\-]+)-----/.exec(pem)) {
|
||||
pem = pem.substring(s[0].length);
|
||||
assert(tag === s[1], 'Tag mismatch.');
|
||||
buf = Buffer.from(buf, 'base64');
|
||||
type = tag.split(' ')[0].toLowerCase();
|
||||
chunks.push({ tag: tag, type: type, data: buf });
|
||||
buf = '';
|
||||
|
||||
if (m = /^-----END ([^\-]+)-----/.exec(pem)) {
|
||||
pem = pem.substring(m[0].length);
|
||||
|
||||
assert(tag === m[1], 'Tag mismatch.');
|
||||
|
||||
const type = tag.split(' ')[0].toLowerCase();
|
||||
const data = Buffer.from(chunk, 'base64');
|
||||
|
||||
chunks.push({
|
||||
tag: tag,
|
||||
type: type,
|
||||
data: data
|
||||
});
|
||||
|
||||
chunk = '';
|
||||
tag = null;
|
||||
|
||||
continue;
|
||||
}
|
||||
if (s = /^[a-zA-Z0-9\+=\/]+/.exec(pem)) {
|
||||
pem = pem.substring(s[0].length);
|
||||
buf += s[0];
|
||||
|
||||
if (m = /^[a-zA-Z0-9\+=\/]+/.exec(pem)) {
|
||||
pem = pem.substring(m[0].length);
|
||||
chunk += m[0];
|
||||
continue;
|
||||
}
|
||||
if (s = /^\s+/.exec(pem)) {
|
||||
pem = pem.substring(s[0].length);
|
||||
|
||||
if (m = /^\s+/.exec(pem)) {
|
||||
pem = pem.substring(m[0].length);
|
||||
continue;
|
||||
}
|
||||
|
||||
throw new Error('PEM parse error.');
|
||||
}
|
||||
|
||||
assert(chunks.length !== 0, 'PEM parse error.');
|
||||
assert(!tag, 'Un-ended tag.');
|
||||
assert(buf.length === 0, 'Trailing data.');
|
||||
assert(chunk.length === 0, 'Trailing data.');
|
||||
|
||||
return chunks;
|
||||
};
|
||||
@ -72,13 +87,16 @@ PEM.decode = function decode(pem) {
|
||||
const chunks = PEM.parse(pem);
|
||||
const body = chunks[0];
|
||||
const extra = chunks[1];
|
||||
let params, alg;
|
||||
|
||||
let params = null;
|
||||
|
||||
if (extra) {
|
||||
if (extra.tag.indexOf('PARAMETERS') !== -1)
|
||||
params = extra.data;
|
||||
}
|
||||
|
||||
let alg = null;
|
||||
|
||||
switch (body.type) {
|
||||
case 'dsa':
|
||||
alg = 'dsa';
|
||||
@ -121,6 +139,6 @@ PEM.encode = function encode(der, type, suffix) {
|
||||
|
||||
return ''
|
||||
+ `-----BEGIN ${type}-----\n`
|
||||
+ `${pem}`
|
||||
+ pem
|
||||
+ `-----END ${type}-----\n`;
|
||||
};
|
||||
|
||||
@ -46,41 +46,56 @@ ProtoReader.prototype.readVarint = function _readVarint() {
|
||||
|
||||
ProtoReader.prototype.readFieldValue = function readFieldValue(tag, opt) {
|
||||
const field = this.readField(tag, opt);
|
||||
|
||||
if (!field)
|
||||
return -1;
|
||||
|
||||
assert(field.value != null);
|
||||
|
||||
return field.value;
|
||||
};
|
||||
|
||||
ProtoReader.prototype.readFieldU64 = function readFieldU64(tag, opt) {
|
||||
const field = this.readField(tag, opt);
|
||||
|
||||
if (!field)
|
||||
return -1;
|
||||
|
||||
assert(field.type === wireType.VARINT || field.type === wireType.FIXED64);
|
||||
|
||||
return field.value;
|
||||
};
|
||||
|
||||
ProtoReader.prototype.readFieldU32 = function readFieldU32(tag, opt) {
|
||||
const field = this.readField(tag, opt);
|
||||
|
||||
if (!field)
|
||||
return -1;
|
||||
|
||||
assert(field.type === wireType.VARINT || field.type === wireType.FIXED32);
|
||||
|
||||
return field.value;
|
||||
};
|
||||
|
||||
ProtoReader.prototype.readFieldBytes = function readFieldBytes(tag, opt) {
|
||||
const field = this.readField(tag, opt);
|
||||
|
||||
if (!field)
|
||||
return null;
|
||||
|
||||
assert(field.data);
|
||||
|
||||
return field.data;
|
||||
};
|
||||
|
||||
ProtoReader.prototype.readFieldString = function readFieldString(tag, opt, enc) {
|
||||
const field = this.readField(tag, opt);
|
||||
|
||||
if (!field)
|
||||
return null;
|
||||
|
||||
assert(field.data);
|
||||
|
||||
return field.data.toString(enc || 'utf8');
|
||||
};
|
||||
|
||||
|
||||
@ -44,44 +44,50 @@ util.inherits(ProtoWriter, BufferWriter);
|
||||
|
||||
ProtoWriter.prototype.writeVarint = function _writeVarint(num) {
|
||||
const size = sizeVarint(num);
|
||||
let value;
|
||||
|
||||
// Avoid an extra allocation until
|
||||
// we make bufferwriter more hackable.
|
||||
// More insanity here...
|
||||
switch (size) {
|
||||
case 6:
|
||||
value = slipVarint(num);
|
||||
case 6: {
|
||||
const value = slipVarint(num);
|
||||
this.writeU32BE(value / 0x10000 | 0);
|
||||
this.writeU16BE(value & 0xffff);
|
||||
break;
|
||||
case 5:
|
||||
value = slipVarint(num);
|
||||
}
|
||||
case 5: {
|
||||
const value = slipVarint(num);
|
||||
this.writeU32BE(value / 0x100 | 0);
|
||||
this.writeU8(value & 0xff);
|
||||
break;
|
||||
case 4:
|
||||
value = slipVarint(num);
|
||||
}
|
||||
case 4: {
|
||||
const value = slipVarint(num);
|
||||
this.writeU32BE(value);
|
||||
break;
|
||||
case 3:
|
||||
value = slipVarint(num);
|
||||
}
|
||||
case 3: {
|
||||
const value = slipVarint(num);
|
||||
this.writeU16BE(value >> 8);
|
||||
this.writeU8(value & 0xff);
|
||||
break;
|
||||
case 2:
|
||||
value = slipVarint(num);
|
||||
}
|
||||
case 2: {
|
||||
const value = slipVarint(num);
|
||||
this.writeU16BE(value);
|
||||
break;
|
||||
case 1:
|
||||
value = slipVarint(num);
|
||||
}
|
||||
case 1: {
|
||||
const value = slipVarint(num);
|
||||
this.writeU8(value);
|
||||
break;
|
||||
default:
|
||||
value = Buffer.allocUnsafe(size);
|
||||
}
|
||||
default: {
|
||||
const value = Buffer.allocUnsafe(size);
|
||||
writeVarint(value, num, 0);
|
||||
this.writeBytes(value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -119,13 +125,11 @@ ProtoWriter.prototype.writeFieldString = function writeFieldString(tag, data, en
|
||||
*/
|
||||
|
||||
function writeVarint(data, num, off) {
|
||||
let ch;
|
||||
|
||||
assert(util.isSafeInteger(num), 'Number exceeds 2^53-1.');
|
||||
|
||||
do {
|
||||
assert(off < data.length);
|
||||
ch = num & 0x7f;
|
||||
let ch = num & 0x7f;
|
||||
num -= num % 0x80;
|
||||
num /= 0x80;
|
||||
if (num !== 0)
|
||||
@ -138,15 +142,14 @@ function writeVarint(data, num, off) {
|
||||
};
|
||||
|
||||
function slipVarint(num) {
|
||||
assert(util.isSafeInteger(num), 'Number exceeds 2^53-1.');
|
||||
|
||||
let data = 0;
|
||||
let size = 0;
|
||||
let ch;
|
||||
|
||||
assert(util.isSafeInteger(num), 'Number exceeds 2^53-1.');
|
||||
|
||||
do {
|
||||
assert(size < 7);
|
||||
ch = num & 0x7f;
|
||||
let ch = num & 0x7f;
|
||||
num -= num % 0x80;
|
||||
num /= 0x80;
|
||||
if (num !== 0)
|
||||
@ -160,10 +163,10 @@ function slipVarint(num) {
|
||||
}
|
||||
|
||||
function sizeVarint(num) {
|
||||
let size = 0;
|
||||
|
||||
assert(util.isSafeInteger(num), 'Number exceeds 2^53-1.');
|
||||
|
||||
let size = 0;
|
||||
|
||||
do {
|
||||
num -= num % 0x80;
|
||||
num /= 0x80;
|
||||
|
||||
@ -58,6 +58,8 @@ RBT.prototype.search = function search(key) {
|
||||
else
|
||||
current = current.right;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -118,13 +120,11 @@ RBT.prototype.insert = function insert(key, value) {
|
||||
*/
|
||||
|
||||
RBT.prototype.insertFixup = function insertFixup(x) {
|
||||
let y;
|
||||
|
||||
x.color = RED;
|
||||
|
||||
while (x !== this.root && x.parent.color === RED) {
|
||||
if (x.parent === x.parent.parent.left) {
|
||||
y = x.parent.parent.right;
|
||||
const y = x.parent.parent.right;
|
||||
if (!y.isNull() && y.color === RED) {
|
||||
x.parent.color = BLACK;
|
||||
y.color = BLACK;
|
||||
@ -140,7 +140,7 @@ RBT.prototype.insertFixup = function insertFixup(x) {
|
||||
this.rotr(x.parent.parent);
|
||||
}
|
||||
} else {
|
||||
y = x.parent.parent.left;
|
||||
const y = x.parent.parent.left;
|
||||
if (!y.isNull() && y.color === RED) {
|
||||
x.parent.color = BLACK;
|
||||
y.color = BLACK;
|
||||
@ -183,6 +183,8 @@ RBT.prototype.remove = function remove(key) {
|
||||
else
|
||||
current = current.right;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -225,11 +227,9 @@ RBT.prototype.removeNode = function removeNode(z) {
|
||||
*/
|
||||
|
||||
RBT.prototype.removeFixup = function removeFixup(x) {
|
||||
let w;
|
||||
|
||||
while (x !== this.root && x.color === BLACK) {
|
||||
if (x === x.parent.left) {
|
||||
w = x.parent.right;
|
||||
let w = x.parent.right;
|
||||
|
||||
if (w.color === RED) {
|
||||
w.color = BLACK;
|
||||
@ -255,7 +255,7 @@ RBT.prototype.removeFixup = function removeFixup(x) {
|
||||
x = this.root;
|
||||
}
|
||||
} else {
|
||||
w = x.parent.left;
|
||||
let w = x.parent.left;
|
||||
|
||||
if (w.color === RED) {
|
||||
w.color = BLACK;
|
||||
@ -294,6 +294,7 @@ RBT.prototype.removeFixup = function removeFixup(x) {
|
||||
|
||||
RBT.prototype.rotl = function rotl(x) {
|
||||
const y = x.right;
|
||||
|
||||
x.right = y.left;
|
||||
|
||||
if (!y.left.isNull())
|
||||
@ -322,6 +323,7 @@ RBT.prototype.rotl = function rotl(x) {
|
||||
|
||||
RBT.prototype.rotr = function rotr(x) {
|
||||
const y = x.left;
|
||||
|
||||
x.left = y.right;
|
||||
|
||||
if (!y.right.isNull())
|
||||
@ -352,8 +354,10 @@ RBT.prototype.rotr = function rotr(x) {
|
||||
RBT.prototype.min = function min(z) {
|
||||
if (z.isNull())
|
||||
return z;
|
||||
|
||||
while (!z.left.isNull())
|
||||
z = z.left;
|
||||
|
||||
return z;
|
||||
};
|
||||
|
||||
@ -367,8 +371,10 @@ RBT.prototype.min = function min(z) {
|
||||
RBT.prototype.max = function max(z) {
|
||||
if (z.isNull())
|
||||
return z;
|
||||
|
||||
while (!z.right.isNull())
|
||||
z = z.right;
|
||||
|
||||
return z;
|
||||
};
|
||||
|
||||
@ -380,18 +386,21 @@ RBT.prototype.max = function max(z) {
|
||||
*/
|
||||
|
||||
RBT.prototype.successor = function successor(x) {
|
||||
let y;
|
||||
if (!x.right.isNull()) {
|
||||
x = x.right;
|
||||
|
||||
while (!x.left.isNull())
|
||||
x = x.left;
|
||||
|
||||
return x;
|
||||
}
|
||||
y = x.parent;
|
||||
|
||||
let y = x.parent;
|
||||
while (!y.isNull() && x === y.right) {
|
||||
x = y;
|
||||
y = y.parent;
|
||||
}
|
||||
|
||||
return y;
|
||||
};
|
||||
|
||||
@ -403,18 +412,21 @@ RBT.prototype.successor = function successor(x) {
|
||||
*/
|
||||
|
||||
RBT.prototype.predecessor = function predecessor(x) {
|
||||
let y;
|
||||
if (!x.left.isNull()) {
|
||||
x = x.left;
|
||||
|
||||
while (!x.right.isNull())
|
||||
x = x.right;
|
||||
|
||||
return x;
|
||||
}
|
||||
y = x.parent;
|
||||
|
||||
let y = x.parent;
|
||||
while (!y.isNull() && x === y.left) {
|
||||
x = y;
|
||||
y = y.parent;
|
||||
}
|
||||
|
||||
return y;
|
||||
};
|
||||
|
||||
@ -425,14 +437,18 @@ RBT.prototype.predecessor = function predecessor(x) {
|
||||
*/
|
||||
|
||||
RBT.prototype.clone = function clone() {
|
||||
let current = this.root;
|
||||
if (this.root.isNull())
|
||||
return SENTINEL;
|
||||
|
||||
const stack = [];
|
||||
|
||||
let current = this.root;
|
||||
let left = true;
|
||||
let parent, copy, snapshot;
|
||||
let parent, snapshot;
|
||||
|
||||
for (;;) {
|
||||
if (!current.isNull()) {
|
||||
copy = current.clone();
|
||||
const copy = current.clone();
|
||||
|
||||
if (parent)
|
||||
copy.parent = parent;
|
||||
@ -465,6 +481,8 @@ RBT.prototype.clone = function clone() {
|
||||
current = current.right;
|
||||
}
|
||||
|
||||
assert(snapshot);
|
||||
|
||||
return snapshot;
|
||||
};
|
||||
|
||||
@ -475,12 +493,10 @@ RBT.prototype.clone = function clone() {
|
||||
*/
|
||||
|
||||
RBT.prototype.snapshot = function snapshot() {
|
||||
let node = SENTINEL;
|
||||
|
||||
if (this.root.isNull())
|
||||
return node;
|
||||
return SENTINEL;
|
||||
|
||||
node = this.root.clone();
|
||||
const node = this.root.clone();
|
||||
|
||||
copyLeft(node, node.left);
|
||||
copyRight(node, node.right);
|
||||
@ -607,11 +623,11 @@ Iterator.prototype.seek = function seek(key) {
|
||||
*/
|
||||
|
||||
Iterator.prototype.seekMin = function seekMin(key) {
|
||||
assert(key != null, 'No key passed to seek.');
|
||||
|
||||
let root = this.current;
|
||||
let current = SENTINEL;
|
||||
|
||||
assert(key != null, 'No key passed to seek.');
|
||||
|
||||
while (!root.isNull()) {
|
||||
const cmp = this.tree.compare(root.key, key);
|
||||
|
||||
@ -639,11 +655,11 @@ Iterator.prototype.seekMin = function seekMin(key) {
|
||||
*/
|
||||
|
||||
Iterator.prototype.seekMax = function seekMax(key) {
|
||||
assert(key != null, 'No key passed to seek.');
|
||||
|
||||
let root = this.current;
|
||||
let current = SENTINEL;
|
||||
|
||||
assert(key != null, 'No key passed to seek.');
|
||||
|
||||
while (!root.isNull()) {
|
||||
const cmp = this.tree.compare(root.key, key);
|
||||
|
||||
|
||||
@ -60,6 +60,7 @@ RollingFilter.prototype.fromRate = function fromRate(items, rate) {
|
||||
const limit = (items + 1) / 2 | 0;
|
||||
|
||||
const max = limit * 3;
|
||||
|
||||
let size = -1 * n * max / Math.log(1.0 - Math.exp(logRate / n));
|
||||
size = Math.ceil(size);
|
||||
|
||||
@ -161,19 +162,16 @@ RollingFilter.prototype.add = function add(val, enc) {
|
||||
const hash = this.hash(val, i);
|
||||
const bits = hash & 0x3f;
|
||||
const pos = (hash >>> 6) % this.items;
|
||||
let pos1 = (pos & ~1) * 8;
|
||||
let pos2 = (pos | 1) * 8;
|
||||
const pos1 = (pos & ~1) * 8;
|
||||
const pos2 = (pos | 1) * 8;
|
||||
const bit = bits % 8;
|
||||
const oct = (bits - bit) / 8;
|
||||
|
||||
pos1 += oct;
|
||||
pos2 += oct;
|
||||
this.filter[pos1 + oct] &= ~(1 << bit);
|
||||
this.filter[pos1 + oct] |= (this.generation & 1) << bit;
|
||||
|
||||
this.filter[pos1] &= ~(1 << bit);
|
||||
this.filter[pos1] |= (this.generation & 1) << bit;
|
||||
|
||||
this.filter[pos2] &= ~(1 << bit);
|
||||
this.filter[pos2] |= (this.generation >>> 1) << bit;
|
||||
this.filter[pos2 + oct] &= ~(1 << bit);
|
||||
this.filter[pos2 + oct] |= (this.generation >>> 1) << bit;
|
||||
}
|
||||
};
|
||||
|
||||
@ -193,20 +191,17 @@ RollingFilter.prototype.test = function test(val, enc) {
|
||||
|
||||
for (let i = 0; i < this.n; i++) {
|
||||
const hash = this.hash(val, i);
|
||||
let bits = hash & 0x3f;
|
||||
const bits = hash & 0x3f;
|
||||
const pos = (hash >>> 6) % this.items;
|
||||
let pos1 = (pos & ~1) * 8;
|
||||
let pos2 = (pos | 1) * 8;
|
||||
const pos1 = (pos & ~1) * 8;
|
||||
const pos2 = (pos | 1) * 8;
|
||||
const bit = bits % 8;
|
||||
const oct = (bits - bit) / 8;
|
||||
|
||||
pos1 += oct;
|
||||
pos2 += oct;
|
||||
const bit1 = (this.filter[pos1 + oct] >>> bit) & 1;
|
||||
const bit2 = (this.filter[pos2 + oct] >>> bit) & 1;
|
||||
|
||||
bits = (this.filter[pos1] >>> bit) & 1;
|
||||
bits |= (this.filter[pos2] >>> bit) & 1;
|
||||
|
||||
if (bits === 0)
|
||||
if ((bit1 | bit2) === 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@ -38,12 +38,12 @@ const inspectOptions = {
|
||||
|
||||
util.hrtime = function hrtime(time) {
|
||||
if (!process.hrtime) {
|
||||
let now = util.ms();
|
||||
const now = util.ms();
|
||||
|
||||
if (time) {
|
||||
time = time[0] * 1000 + time[1] / 1e6;
|
||||
now -= time;
|
||||
return now;
|
||||
const [hi, lo] = time;
|
||||
const start = hi * 1000 + lo / 1e6;
|
||||
return now - start;
|
||||
}
|
||||
|
||||
const ms = now % 1000;
|
||||
@ -53,8 +53,8 @@ util.hrtime = function hrtime(time) {
|
||||
}
|
||||
|
||||
if (time) {
|
||||
const elapsed = process.hrtime(time);
|
||||
return elapsed[0] * 1000 + elapsed[1] / 1e6;
|
||||
const [hi, lo] = process.hrtime(time);
|
||||
return hi * 1000 + lo / 1e6;
|
||||
}
|
||||
|
||||
return process.hrtime();
|
||||
@ -519,7 +519,9 @@ util.indexOf = function indexOf(items, data) {
|
||||
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
const item = items[i];
|
||||
|
||||
assert(Buffer.isBuffer(item));
|
||||
|
||||
if (item.equals(data))
|
||||
return i;
|
||||
}
|
||||
@ -537,7 +539,9 @@ util.indexOf = function indexOf(items, data) {
|
||||
util.pad8 = function pad8(num) {
|
||||
assert(typeof num === 'number');
|
||||
assert(num >= 0);
|
||||
|
||||
num = num + '';
|
||||
|
||||
switch (num.length) {
|
||||
case 1:
|
||||
return '00' + num;
|
||||
@ -546,6 +550,7 @@ util.pad8 = function pad8(num) {
|
||||
case 3:
|
||||
return num;
|
||||
}
|
||||
|
||||
assert(false);
|
||||
};
|
||||
|
||||
@ -559,7 +564,9 @@ util.pad8 = function pad8(num) {
|
||||
util.pad32 = function pad32(num) {
|
||||
assert(typeof num === 'number');
|
||||
assert(num >= 0);
|
||||
|
||||
num = num + '';
|
||||
|
||||
switch (num.length) {
|
||||
case 1:
|
||||
return '000000000' + num;
|
||||
@ -581,9 +588,9 @@ util.pad32 = function pad32(num) {
|
||||
return '0' + num;
|
||||
case 10:
|
||||
return num;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
|
||||
assert(false);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -596,15 +603,17 @@ util.pad32 = function pad32(num) {
|
||||
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;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
|
||||
assert(false);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -617,7 +626,9 @@ util.hex8 = function hex8(num) {
|
||||
util.hex32 = function hex32(num) {
|
||||
assert(typeof num === 'number');
|
||||
assert(num >= 0);
|
||||
|
||||
num = num.toString(16);
|
||||
|
||||
switch (num.length) {
|
||||
case 1:
|
||||
return '0000000' + num;
|
||||
@ -635,9 +646,9 @@ util.hex32 = function hex32(num) {
|
||||
return '0' + num;
|
||||
case 8:
|
||||
return num;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
|
||||
assert(false);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -439,8 +439,9 @@ Validator.prototype.bool = function bool(key, fallback) {
|
||||
if (value === null)
|
||||
return fallback;
|
||||
|
||||
// bitcoin core mixes semantics of truthiness amoung rpc methods
|
||||
// most "verbose" parameters are bools, but getrawtransaction is 1/0
|
||||
// Bitcoin Core mixes semantics of truthiness
|
||||
// amoung rpc methods most "verbose" parameters
|
||||
// are bools, but getrawtransaction is 1/0.
|
||||
if (value === 1)
|
||||
return true;
|
||||
|
||||
|
||||
@ -344,9 +344,8 @@ Account.prototype.spliceKey = function spliceKey(key) {
|
||||
|
||||
Account.prototype.addSharedKey = async function addSharedKey(key) {
|
||||
const result = this.pushKey(key);
|
||||
const exists = await this._hasDuplicate();
|
||||
|
||||
if (exists) {
|
||||
if (await this.hasDuplicate()) {
|
||||
this.spliceKey(key);
|
||||
throw new Error('Cannot add a key from another account.');
|
||||
}
|
||||
@ -363,7 +362,7 @@ Account.prototype.addSharedKey = async function addSharedKey(key) {
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
Account.prototype._hasDuplicate = function _hasDuplicate() {
|
||||
Account.prototype.hasDuplicate = function hasDuplicate() {
|
||||
if (this.keys.length !== this.n - 1)
|
||||
return false;
|
||||
|
||||
@ -511,15 +510,13 @@ Account.prototype.derivePath = function derivePath(path, master) {
|
||||
if (path.encrypted) {
|
||||
data = master.decipher(data, path.hash);
|
||||
if (!data)
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
|
||||
const ring = WalletKey.fromImport(this, data);
|
||||
|
||||
return ring;
|
||||
return WalletKey.fromImport(this, data);
|
||||
}
|
||||
case Path.types.ADDRESS: {
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
default: {
|
||||
assert(false, 'Bad key type.');
|
||||
@ -538,8 +535,8 @@ Account.prototype.deriveKey = function deriveKey(branch, index, master) {
|
||||
assert(typeof branch === 'number');
|
||||
|
||||
const keys = [];
|
||||
let key;
|
||||
|
||||
let key;
|
||||
if (master && master.key && !this.watchOnly) {
|
||||
key = master.key.deriveBIP44(this.accountIndex);
|
||||
key = key.derive(branch).derive(index);
|
||||
@ -555,9 +552,9 @@ Account.prototype.deriveKey = function deriveKey(branch, index, master) {
|
||||
case Account.types.MULTISIG:
|
||||
keys.push(key.publicKey);
|
||||
|
||||
for (let shared of this.keys) {
|
||||
shared = shared.derive(branch).derive(index);
|
||||
keys.push(shared.publicKey);
|
||||
for (const shared of this.keys) {
|
||||
const key = shared.derive(branch).derive(index);
|
||||
keys.push(key.publicKey);
|
||||
}
|
||||
|
||||
ring.script = Script.fromMultisig(this.m, this.n, keys);
|
||||
@ -800,7 +797,7 @@ Account.prototype.getAddress = function getAddress(enc) {
|
||||
|
||||
Account.prototype.getReceive = function getReceive(enc) {
|
||||
if (!this.receive)
|
||||
return;
|
||||
return null;
|
||||
return this.receive.getAddress(enc);
|
||||
};
|
||||
|
||||
@ -812,7 +809,8 @@ Account.prototype.getReceive = function getReceive(enc) {
|
||||
|
||||
Account.prototype.getChange = function getChange(enc) {
|
||||
if (!this.change)
|
||||
return;
|
||||
return null;
|
||||
|
||||
return this.change.getAddress(enc);
|
||||
};
|
||||
|
||||
@ -824,7 +822,8 @@ Account.prototype.getChange = function getChange(enc) {
|
||||
|
||||
Account.prototype.getNested = function getNested(enc) {
|
||||
if (!this.nested)
|
||||
return;
|
||||
return null;
|
||||
|
||||
return this.nested.getAddress(enc);
|
||||
};
|
||||
|
||||
@ -1004,8 +1003,8 @@ Account.isAccount = function isAccount(obj) {
|
||||
* Helpers
|
||||
*/
|
||||
|
||||
function cmp(key1, key2) {
|
||||
return key1.compare(key2);
|
||||
function cmp(a, b) {
|
||||
return a.compare(b);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@ -82,21 +82,21 @@ common.sortCoins = function sortCoins(coins) {
|
||||
|
||||
common.sortDeps = function sortDeps(txs) {
|
||||
const map = new Map();
|
||||
const depMap = new Map();
|
||||
const depCount = new Map();
|
||||
const result = [];
|
||||
const top = [];
|
||||
|
||||
for (const tx of txs) {
|
||||
const hash = tx.hash('hex');
|
||||
map.set(hash, tx);
|
||||
}
|
||||
|
||||
for (const [hash, tx] of map) {
|
||||
let hasDeps = false;
|
||||
const depMap = new Map();
|
||||
const depCount = new Map();
|
||||
const top = [];
|
||||
|
||||
for (const [hash, tx] of map) {
|
||||
depCount.set(hash, 0);
|
||||
|
||||
let hasDeps = false;
|
||||
|
||||
for (const input of tx.inputs) {
|
||||
const prev = input.prevout.hash;
|
||||
|
||||
@ -119,6 +119,8 @@ common.sortDeps = function sortDeps(txs) {
|
||||
top.push(tx);
|
||||
}
|
||||
|
||||
const result = [];
|
||||
|
||||
for (const tx of top) {
|
||||
const hash = tx.hash('hex');
|
||||
const deps = depMap.get(hash);
|
||||
|
||||
@ -134,8 +134,7 @@ HTTPServer.prototype.initRouter = function initRouter() {
|
||||
return;
|
||||
}
|
||||
|
||||
let wallet = null;
|
||||
|
||||
let wallet;
|
||||
try {
|
||||
wallet = await this.walletdb.auth(id, token);
|
||||
} catch (err) {
|
||||
@ -315,8 +314,11 @@ HTTPServer.prototype.initRouter = function initRouter() {
|
||||
const valid = req.valid();
|
||||
const old = valid.str('old');
|
||||
const new_ = valid.str('new');
|
||||
|
||||
enforce(old || new_, 'Passphrase is required.');
|
||||
|
||||
await req.wallet.setPassphrase(old, new_);
|
||||
|
||||
res.send(200, { success: true });
|
||||
});
|
||||
|
||||
@ -325,8 +327,11 @@ HTTPServer.prototype.initRouter = function initRouter() {
|
||||
const valid = req.valid();
|
||||
const passphrase = valid.str('passphrase');
|
||||
const timeout = valid.u32('timeout');
|
||||
|
||||
enforce(passphrase, 'Passphrase is required.');
|
||||
|
||||
await req.wallet.unlock(passphrase, timeout);
|
||||
|
||||
res.send(200, { success: true });
|
||||
});
|
||||
|
||||
@ -392,11 +397,11 @@ HTTPServer.prototype.initRouter = function initRouter() {
|
||||
|
||||
for (const output of outputs) {
|
||||
const valid = new Validator([output]);
|
||||
let script = null;
|
||||
|
||||
let script;
|
||||
if (valid.has('script')) {
|
||||
script = valid.buf('script');
|
||||
script = Script.fromRaw(script);
|
||||
const raw = valid.buf('script');
|
||||
script = Script.fromRaw(raw);
|
||||
}
|
||||
|
||||
options.outputs.push({
|
||||
@ -431,11 +436,11 @@ HTTPServer.prototype.initRouter = function initRouter() {
|
||||
|
||||
for (const output of outputs) {
|
||||
const valid = new Validator([output]);
|
||||
let script = null;
|
||||
|
||||
let script;
|
||||
if (valid.has('script')) {
|
||||
script = valid.buf('script');
|
||||
script = Script.fromRaw(script);
|
||||
const raw = valid.buf('script');
|
||||
script = Script.fromRaw(raw);
|
||||
}
|
||||
|
||||
options.outputs.push({
|
||||
@ -448,6 +453,7 @@ HTTPServer.prototype.initRouter = function initRouter() {
|
||||
const tx = await req.wallet.createTX(options);
|
||||
|
||||
await req.wallet.sign(tx, passphrase);
|
||||
|
||||
res.send(200, tx.getJSON(this.network));
|
||||
});
|
||||
|
||||
@ -471,8 +477,11 @@ HTTPServer.prototype.initRouter = function initRouter() {
|
||||
const valid = req.valid();
|
||||
const acct = valid.str('account');
|
||||
const age = valid.u32('age');
|
||||
|
||||
enforce(age, 'Age is required.');
|
||||
|
||||
await req.wallet.zap(acct, age);
|
||||
|
||||
res.send(200, { success: true });
|
||||
});
|
||||
|
||||
@ -480,8 +489,11 @@ HTTPServer.prototype.initRouter = function initRouter() {
|
||||
this.del('/:id/tx/:hash', async (req, res) => {
|
||||
const valid = req.valid();
|
||||
const hash = valid.hash('hash');
|
||||
|
||||
enforce(hash, 'Hash is required.');
|
||||
|
||||
await req.wallet.abandon(hash);
|
||||
|
||||
res.send(200, { success: true });
|
||||
});
|
||||
|
||||
@ -513,8 +525,11 @@ HTTPServer.prototype.initRouter = function initRouter() {
|
||||
const valid = req.valid();
|
||||
const acct = valid.str('account');
|
||||
const key = valid.str('accountKey');
|
||||
|
||||
enforce(key, 'Key is required.');
|
||||
|
||||
await req.wallet.addSharedKey(acct, key);
|
||||
|
||||
res.send(200, { success: true });
|
||||
});
|
||||
|
||||
@ -523,8 +538,11 @@ HTTPServer.prototype.initRouter = function initRouter() {
|
||||
const valid = req.valid();
|
||||
const acct = valid.str('account');
|
||||
const key = valid.str('accountKey');
|
||||
|
||||
enforce(key, 'Key is required.');
|
||||
|
||||
await req.wallet.removeSharedKey(acct, key);
|
||||
|
||||
res.send(200, { success: true });
|
||||
});
|
||||
|
||||
@ -568,6 +586,7 @@ HTTPServer.prototype.initRouter = function initRouter() {
|
||||
const valid = req.valid();
|
||||
const acct = valid.str('account');
|
||||
const address = await req.wallet.createReceive(acct);
|
||||
|
||||
res.send(200, address.toJSON());
|
||||
});
|
||||
|
||||
@ -576,6 +595,7 @@ HTTPServer.prototype.initRouter = function initRouter() {
|
||||
const valid = req.valid();
|
||||
const acct = valid.str('account');
|
||||
const address = await req.wallet.createChange(acct);
|
||||
|
||||
res.send(200, address.toJSON());
|
||||
});
|
||||
|
||||
@ -584,6 +604,7 @@ HTTPServer.prototype.initRouter = function initRouter() {
|
||||
const valid = req.valid();
|
||||
const acct = valid.str('account');
|
||||
const address = await req.wallet.createNested(acct);
|
||||
|
||||
res.send(200, address.toJSON());
|
||||
});
|
||||
|
||||
@ -787,48 +808,36 @@ HTTPServer.prototype.initSockets = function initSockets() {
|
||||
|
||||
this.walletdb.on('tx', (id, tx, details) => {
|
||||
const json = details.toJSON();
|
||||
const channel = 'w:' + id;
|
||||
this.to(channel, 'wallet tx', json);
|
||||
this.to('!all', 'wallet tx', id, json);
|
||||
this.to(`w:${id}`, 'wallet tx', json);
|
||||
});
|
||||
|
||||
this.walletdb.on('confirmed', (id, tx, details) => {
|
||||
const json = details.toJSON();
|
||||
const channel = 'w:' + id;
|
||||
this.to(channel, 'wallet confirmed', json);
|
||||
this.to('!all', 'wallet confirmed', id, json);
|
||||
this.to(`w:${id}`, 'wallet confirmed', json);
|
||||
});
|
||||
|
||||
this.walletdb.on('unconfirmed', (id, tx, details) => {
|
||||
const json = details.toJSON();
|
||||
const channel = 'w:' + id;
|
||||
this.to(channel, 'wallet unconfirmed', json);
|
||||
this.to('!all', 'wallet unconfirmed', id, json);
|
||||
this.to(`w:${id}`, 'wallet unconfirmed', json);
|
||||
});
|
||||
|
||||
this.walletdb.on('conflict', (id, tx, details) => {
|
||||
const json = details.toJSON();
|
||||
const channel = 'w:' + id;
|
||||
this.to(channel, 'wallet conflict', json);
|
||||
this.to('!all', 'wallet conflict', id, json);
|
||||
this.to(`w:${id}`, 'wallet conflict', json);
|
||||
});
|
||||
|
||||
this.walletdb.on('balance', (id, balance) => {
|
||||
const json = balance.toJSON();
|
||||
const channel = 'w:' + id;
|
||||
this.to(channel, 'wallet balance', json);
|
||||
this.to('!all', 'wallet balance', id, json);
|
||||
this.to(`w:${id}`, 'wallet balance', json);
|
||||
});
|
||||
|
||||
this.walletdb.on('address', (id, receive) => {
|
||||
const channel = 'w:' + id;
|
||||
const json = [];
|
||||
|
||||
for (const addr of receive)
|
||||
json.push(addr.toJSON());
|
||||
|
||||
this.to(channel, 'wallet address', json);
|
||||
this.to('!all', 'wallet address', id, json);
|
||||
this.to(`w:${id}`, 'wallet address', json);
|
||||
});
|
||||
};
|
||||
|
||||
@ -840,16 +849,21 @@ HTTPServer.prototype.initSockets = function initSockets() {
|
||||
|
||||
HTTPServer.prototype.handleSocket = function handleSocket(socket) {
|
||||
socket.hook('wallet auth', (args) => {
|
||||
const valid = new Validator([args]);
|
||||
const key = valid.str(0);
|
||||
|
||||
if (socket.auth)
|
||||
throw new Error('Already authed.');
|
||||
|
||||
if (!this.options.noAuth) {
|
||||
const hash = hash256(key);
|
||||
const valid = new Validator([args]);
|
||||
const key = valid.str(0);
|
||||
|
||||
if (key.length > 255)
|
||||
throw new Error('Invalid API key.');
|
||||
|
||||
const data = Buffer.from(key, 'utf8');
|
||||
const hash = digest.hash256(data);
|
||||
|
||||
if (!ccmp(hash, this.options.apiHash))
|
||||
throw new Error('Bad key.');
|
||||
throw new Error('Invalid API key.');
|
||||
}
|
||||
|
||||
socket.auth = true;
|
||||
@ -873,21 +887,19 @@ HTTPServer.prototype.handleAuth = function handleAuth(socket) {
|
||||
const valid = new Validator([args]);
|
||||
const id = valid.str(0, '');
|
||||
const token = valid.buf(1);
|
||||
const channel = 'w:' + id;
|
||||
|
||||
if (!id)
|
||||
throw new Error('Invalid parameter.');
|
||||
|
||||
if (!this.options.walletAuth) {
|
||||
socket.join(channel);
|
||||
socket.join(`w:${id}`);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!token)
|
||||
throw new Error('Invalid parameter.');
|
||||
|
||||
let wallet = null;
|
||||
|
||||
let wallet;
|
||||
try {
|
||||
wallet = await this.walletdb.auth(id, token);
|
||||
} catch (e) {
|
||||
@ -900,7 +912,7 @@ HTTPServer.prototype.handleAuth = function handleAuth(socket) {
|
||||
|
||||
this.logger.info('Successful wallet auth for %s.', id);
|
||||
|
||||
socket.join(channel);
|
||||
socket.join(`w:${id}`);
|
||||
|
||||
return null;
|
||||
});
|
||||
@ -908,12 +920,11 @@ HTTPServer.prototype.handleAuth = function handleAuth(socket) {
|
||||
socket.hook('wallet leave', (args) => {
|
||||
const valid = new Validator([args]);
|
||||
const id = valid.str(0, '');
|
||||
const channel = 'w:' + id;
|
||||
|
||||
if (!id)
|
||||
throw new Error('Invalid parameter.');
|
||||
|
||||
socket.leave(channel);
|
||||
socket.leave(`w:${id}`);
|
||||
|
||||
return null;
|
||||
});
|
||||
@ -934,7 +945,7 @@ function HTTPOptions(options) {
|
||||
this.logger = null;
|
||||
this.walletdb = null;
|
||||
this.apiKey = base58.encode(random.randomBytes(20));
|
||||
this.apiHash = hash256(this.apiKey);
|
||||
this.apiHash = digest.hash256(Buffer.from(this.apiKey, 'utf8'));
|
||||
this.serviceHash = this.apiHash;
|
||||
this.noAuth = false;
|
||||
this.walletAuth = false;
|
||||
@ -977,7 +988,7 @@ HTTPOptions.prototype.fromOptions = function fromOptions(options) {
|
||||
assert(options.apiKey.length <= 200,
|
||||
'API key must be under 200 bytes.');
|
||||
this.apiKey = options.apiKey;
|
||||
this.apiHash = hash256(this.apiKey);
|
||||
this.apiHash = digest.hash256(Buffer.from(this.apiKey, 'utf8'));
|
||||
}
|
||||
|
||||
if (options.noAuth != null) {
|
||||
@ -1047,16 +1058,6 @@ HTTPOptions.fromOptions = function fromOptions(options) {
|
||||
* Helpers
|
||||
*/
|
||||
|
||||
function hash256(data) {
|
||||
if (typeof data !== 'string')
|
||||
return Buffer.alloc(0);
|
||||
|
||||
if (data.length > 200)
|
||||
return Buffer.alloc(0);
|
||||
|
||||
return digest.hash256(Buffer.from(data, 'utf8'));
|
||||
}
|
||||
|
||||
function enforce(value, msg) {
|
||||
if (!value) {
|
||||
const err = new Error(msg);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user