utils: stop using asyncobject.
This commit is contained in:
parent
cbef19047a
commit
424370bc1f
@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const AsyncObject = require('../utils/asyncobject');
|
const AsyncEmitter = require('../utils/asyncemitter');
|
||||||
const Network = require('../protocol/network');
|
const Network = require('../protocol/network');
|
||||||
const Logger = require('blgr');
|
const Logger = require('blgr');
|
||||||
const ChainDB = require('./chaindb');
|
const ChainDB = require('./chaindb');
|
||||||
@ -65,8 +65,9 @@ function Chain(options) {
|
|||||||
if (!(this instanceof Chain))
|
if (!(this instanceof Chain))
|
||||||
return new Chain(options);
|
return new Chain(options);
|
||||||
|
|
||||||
AsyncObject.call(this);
|
AsyncEmitter.call(this);
|
||||||
|
|
||||||
|
this.opened = false;
|
||||||
this.options = new ChainOptions(options);
|
this.options = new ChainOptions(options);
|
||||||
|
|
||||||
this.network = this.options.network;
|
this.network = this.options.network;
|
||||||
@ -87,7 +88,7 @@ function Chain(options) {
|
|||||||
this.orphanPrev = new Map();
|
this.orphanPrev = new Map();
|
||||||
}
|
}
|
||||||
|
|
||||||
Object.setPrototypeOf(Chain.prototype, AsyncObject.prototype);
|
Object.setPrototypeOf(Chain.prototype, AsyncEmitter.prototype);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Size of set to pick median time from.
|
* Size of set to pick median time from.
|
||||||
@ -99,11 +100,13 @@ Chain.MEDIAN_TIMESPAN = 11;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Open the chain, wait for the database to load.
|
* Open the chain, wait for the database to load.
|
||||||
* @alias Chain#open
|
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Chain.prototype._open = async function _open() {
|
Chain.prototype.open = async function open() {
|
||||||
|
assert(!this.opened, 'Chain is already open.');
|
||||||
|
this.opened = true;
|
||||||
|
|
||||||
this.logger.info('Chain is loading.');
|
this.logger.info('Chain is loading.');
|
||||||
|
|
||||||
if (this.options.checkpoints)
|
if (this.options.checkpoints)
|
||||||
@ -144,11 +147,12 @@ Chain.prototype._open = async function _open() {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Close the chain, wait for the database to close.
|
* Close the chain, wait for the database to close.
|
||||||
* @alias Chain#close
|
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Chain.prototype._close = function _close() {
|
Chain.prototype.close = async function close() {
|
||||||
|
assert(this.opened, 'Chain is not open.');
|
||||||
|
this.opened = false;
|
||||||
return this.db.close();
|
return this.db.close();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -906,7 +910,7 @@ Chain.prototype.reorganize = async function reorganize(competitor) {
|
|||||||
competitor.height
|
competitor.height
|
||||||
);
|
);
|
||||||
|
|
||||||
await this.call('reorganize', tip, competitor);
|
await this.emitAsync('reorganize', tip, competitor);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -943,7 +947,7 @@ Chain.prototype.reorganizeSPV = async function reorganizeSPV(competitor) {
|
|||||||
for (const entry of disconnect) {
|
for (const entry of disconnect) {
|
||||||
const headers = entry.toHeaders();
|
const headers = entry.toHeaders();
|
||||||
const view = new CoinView();
|
const view = new CoinView();
|
||||||
await this.call('disconnect', entry, headers, view);
|
await this.emitAsync('disconnect', entry, headers, view);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.logger.warning(
|
this.logger.warning(
|
||||||
@ -958,7 +962,7 @@ Chain.prototype.reorganizeSPV = async function reorganizeSPV(competitor) {
|
|||||||
'Chain replay from height %d necessary.',
|
'Chain replay from height %d necessary.',
|
||||||
fork.height);
|
fork.height);
|
||||||
|
|
||||||
await this.call('reorganize', tip, competitor);
|
await this.emitAsync('reorganize', tip, competitor);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -986,7 +990,7 @@ Chain.prototype.disconnect = async function disconnect(entry) {
|
|||||||
|
|
||||||
this.emit('tip', prev);
|
this.emit('tip', prev);
|
||||||
|
|
||||||
await this.call('disconnect', entry, block, view);
|
await this.emitAsync('disconnect', entry, block, view);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1036,7 +1040,7 @@ Chain.prototype.reconnect = async function reconnect(entry) {
|
|||||||
this.emit('tip', entry);
|
this.emit('tip', entry);
|
||||||
this.emit('reconnect', entry, block);
|
this.emit('reconnect', entry, block);
|
||||||
|
|
||||||
await this.call('connect', entry, block, view);
|
await this.emitAsync('connect', entry, block, view);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1104,7 +1108,7 @@ Chain.prototype.setBestChain = async function setBestChain(entry, block, prev, f
|
|||||||
this.emit('tip', entry);
|
this.emit('tip', entry);
|
||||||
this.emit('block', block, entry);
|
this.emit('block', block, entry);
|
||||||
|
|
||||||
await this.call('connect', entry, block, view);
|
await this.emitAsync('connect', entry, block, view);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1199,7 +1203,7 @@ Chain.prototype._reset = async function _reset(block, silent) {
|
|||||||
this.emit('tip', tip);
|
this.emit('tip', tip);
|
||||||
|
|
||||||
if (!silent)
|
if (!silent)
|
||||||
await this.call('reset', tip);
|
await this.emitAsync('reset', tip);
|
||||||
|
|
||||||
// Reset the orphan map completely. There may
|
// Reset the orphan map completely. There may
|
||||||
// have been some orphans on a forked chain we
|
// have been some orphans on a forked chain we
|
||||||
|
|||||||
@ -2201,10 +2201,10 @@ function StateCache(network) {
|
|||||||
this.network = network;
|
this.network = network;
|
||||||
this.bits = [];
|
this.bits = [];
|
||||||
this.updates = [];
|
this.updates = [];
|
||||||
this._init();
|
this.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
StateCache.prototype._init = function _init() {
|
StateCache.prototype.init = function init() {
|
||||||
for (let i = 0; i < 32; i++)
|
for (let i = 0; i < 32; i++)
|
||||||
this.bits.push(null);
|
this.bits.push(null);
|
||||||
|
|
||||||
|
|||||||
@ -8,8 +8,8 @@
|
|||||||
|
|
||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
const EventEmitter = require('events');
|
||||||
const BDB = require('bdb');
|
const BDB = require('bdb');
|
||||||
const AsyncObject = require('../utils/asyncobject');
|
|
||||||
const common = require('../blockchain/common');
|
const common = require('../blockchain/common');
|
||||||
const consensus = require('../protocol/consensus');
|
const consensus = require('../protocol/consensus');
|
||||||
const policy = require('../protocol/policy');
|
const policy = require('../protocol/policy');
|
||||||
@ -65,8 +65,9 @@ function Mempool(options) {
|
|||||||
if (!(this instanceof Mempool))
|
if (!(this instanceof Mempool))
|
||||||
return new Mempool(options);
|
return new Mempool(options);
|
||||||
|
|
||||||
AsyncObject.call(this);
|
EventEmitter.call(this);
|
||||||
|
|
||||||
|
this.opened = false;
|
||||||
this.options = new MempoolOptions(options);
|
this.options = new MempoolOptions(options);
|
||||||
|
|
||||||
this.network = this.options.network;
|
this.network = this.options.network;
|
||||||
@ -95,17 +96,17 @@ function Mempool(options) {
|
|||||||
this.txIndex = new TXIndex();
|
this.txIndex = new TXIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
Object.setPrototypeOf(Mempool.prototype, AsyncObject.prototype);
|
Object.setPrototypeOf(Mempool.prototype, EventEmitter.prototype);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open the chain, wait for the database to load.
|
* Open the chain, wait for the database to load.
|
||||||
* @method
|
|
||||||
* @alias Mempool#open
|
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Mempool.prototype._open = async function _open() {
|
Mempool.prototype.open = async function open() {
|
||||||
await this.chain.open();
|
assert(!this.opened, 'Mempool is already open.');
|
||||||
|
this.opened = true;
|
||||||
|
|
||||||
await this.cache.open();
|
await this.cache.open();
|
||||||
|
|
||||||
if (this.options.persistent) {
|
if (this.options.persistent) {
|
||||||
@ -148,12 +149,13 @@ Mempool.prototype._open = async function _open() {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Close the chain, wait for the database to close.
|
* Close the chain, wait for the database to close.
|
||||||
* @alias Mempool#close
|
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Mempool.prototype._close = async function _close() {
|
Mempool.prototype.close = async function close() {
|
||||||
await this.cache.close();
|
assert(this.opened, 'Mempool is not open.');
|
||||||
|
this.opened = false;
|
||||||
|
return this.cache.close();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -8,9 +8,9 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
|
const EventEmitter = require('events');
|
||||||
const util = require('../utils/util');
|
const util = require('../utils/util');
|
||||||
const co = require('../utils/co');
|
const co = require('../utils/co');
|
||||||
const AsyncObject = require('../utils/asyncobject');
|
|
||||||
const mine = require('./mine');
|
const mine = require('./mine');
|
||||||
const Lock = require('../utils/lock');
|
const Lock = require('../utils/lock');
|
||||||
const encoding = require('bbuf/lib/encoding');
|
const encoding = require('bbuf/lib/encoding');
|
||||||
@ -28,8 +28,9 @@ function CPUMiner(miner) {
|
|||||||
if (!(this instanceof CPUMiner))
|
if (!(this instanceof CPUMiner))
|
||||||
return new CPUMiner(miner);
|
return new CPUMiner(miner);
|
||||||
|
|
||||||
AsyncObject.call(this);
|
EventEmitter.call(this);
|
||||||
|
|
||||||
|
this.opened = false;
|
||||||
this.miner = miner;
|
this.miner = miner;
|
||||||
this.network = this.miner.network;
|
this.network = this.miner.network;
|
||||||
this.logger = this.miner.logger.context('cpuminer');
|
this.logger = this.miner.logger.context('cpuminer');
|
||||||
@ -42,10 +43,10 @@ function CPUMiner(miner) {
|
|||||||
this.job = null;
|
this.job = null;
|
||||||
this.stopJob = null;
|
this.stopJob = null;
|
||||||
|
|
||||||
this._init();
|
this.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
Object.setPrototypeOf(CPUMiner.prototype, AsyncObject.prototype);
|
Object.setPrototypeOf(CPUMiner.prototype, EventEmitter.prototype);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Nonce range interval.
|
* Nonce range interval.
|
||||||
@ -60,7 +61,7 @@ CPUMiner.INTERVAL = 0xffffffff / 1500 | 0;
|
|||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CPUMiner.prototype._init = function _init() {
|
CPUMiner.prototype.init = function init() {
|
||||||
this.chain.on('tip', (tip) => {
|
this.chain.on('tip', (tip) => {
|
||||||
if (!this.job)
|
if (!this.job)
|
||||||
return;
|
return;
|
||||||
@ -72,23 +73,23 @@ CPUMiner.prototype._init = function _init() {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Open the miner.
|
* Open the miner.
|
||||||
* @method
|
|
||||||
* @alias module:mining.CPUMiner#open
|
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CPUMiner.prototype._open = async function _open() {
|
CPUMiner.prototype.open = async function open() {
|
||||||
|
assert(!this.opened, 'CPUMiner is already open.');
|
||||||
|
this.opened = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Close the miner.
|
* Close the miner.
|
||||||
* @method
|
|
||||||
* @alias module:mining.CPUMiner#close
|
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CPUMiner.prototype._close = async function _close() {
|
CPUMiner.prototype.close = async function close() {
|
||||||
await this.stop();
|
assert(this.opened, 'CPUMiner is not open.');
|
||||||
|
this.opened = false;
|
||||||
|
return this.stop();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -8,8 +8,8 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
|
const EventEmitter = require('events');
|
||||||
const Heap = require('../utils/heap');
|
const Heap = require('../utils/heap');
|
||||||
const AsyncObject = require('../utils/asyncobject');
|
|
||||||
const Amount = require('../btc/amount');
|
const Amount = require('../btc/amount');
|
||||||
const Address = require('../primitives/address');
|
const Address = require('../primitives/address');
|
||||||
const BlockTemplate = require('./template');
|
const BlockTemplate = require('./template');
|
||||||
@ -30,8 +30,9 @@ function Miner(options) {
|
|||||||
if (!(this instanceof Miner))
|
if (!(this instanceof Miner))
|
||||||
return new Miner(options);
|
return new Miner(options);
|
||||||
|
|
||||||
AsyncObject.call(this);
|
EventEmitter.call(this);
|
||||||
|
|
||||||
|
this.opened = false;
|
||||||
this.options = new MinerOptions(options);
|
this.options = new MinerOptions(options);
|
||||||
this.network = this.options.network;
|
this.network = this.options.network;
|
||||||
this.logger = this.options.logger.context('miner');
|
this.logger = this.options.logger.context('miner');
|
||||||
@ -45,13 +46,10 @@ function Miner(options) {
|
|||||||
this.init();
|
this.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
Object.setPrototypeOf(Miner.prototype, AsyncObject.prototype);
|
Object.setPrototypeOf(Miner.prototype, EventEmitter.prototype);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open the miner, wait for the chain and mempool to load.
|
* Initialize the miner.
|
||||||
* @method
|
|
||||||
* @alias module:mining.Miner#open
|
|
||||||
* @returns {Promise}
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Miner.prototype.init = function init() {
|
Miner.prototype.init = function init() {
|
||||||
@ -62,16 +60,12 @@ Miner.prototype.init = function init() {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Open the miner, wait for the chain and mempool to load.
|
* Open the miner, wait for the chain and mempool to load.
|
||||||
* @method
|
|
||||||
* @alias module:mining.Miner#open
|
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Miner.prototype._open = async function _open() {
|
Miner.prototype.open = async function open() {
|
||||||
await this.chain.open();
|
assert(!this.opened, 'Miner is already open.');
|
||||||
|
this.opened = true;
|
||||||
if (this.mempool)
|
|
||||||
await this.mempool.open();
|
|
||||||
|
|
||||||
await this.cpu.open();
|
await this.cpu.open();
|
||||||
|
|
||||||
@ -84,13 +78,13 @@ Miner.prototype._open = async function _open() {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Close the miner.
|
* Close the miner.
|
||||||
* @method
|
|
||||||
* @alias module:mining.Miner#close
|
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Miner.prototype._close = async function _close() {
|
Miner.prototype.close = async function close() {
|
||||||
await this.cpu.close();
|
assert(this.opened, 'Miner is not open.');
|
||||||
|
this.opened = false;
|
||||||
|
return this.cpu.close();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -15,7 +15,8 @@ const fs = require('bfile');
|
|||||||
const IP = require('binet');
|
const IP = require('binet');
|
||||||
const Logger = require('blgr');
|
const Logger = require('blgr');
|
||||||
const ccmp = require('bcrypto/lib/ccmp');
|
const ccmp = require('bcrypto/lib/ccmp');
|
||||||
const digest = require('bcrypto/lib/digest');
|
const hash160 = require('bcrypto/lib/hash160');
|
||||||
|
const hash256 = require('bcrypto/lib/hash256');
|
||||||
const random = require('bcrypto/lib/random');
|
const random = require('bcrypto/lib/random');
|
||||||
const secp256k1 = require('bcrypto/lib/secp256k1');
|
const secp256k1 = require('bcrypto/lib/secp256k1');
|
||||||
const StaticWriter = require('bbuf/lib/staticwriter');
|
const StaticWriter = require('bbuf/lib/staticwriter');
|
||||||
@ -83,7 +84,7 @@ function BIP150(bip151, host, outbound, db, key) {
|
|||||||
this.timeout = null;
|
this.timeout = null;
|
||||||
this.onAuth = null;
|
this.onAuth = null;
|
||||||
|
|
||||||
this._init();
|
this.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
Object.setPrototypeOf(BIP150.prototype, EventEmitter.prototype);
|
Object.setPrototypeOf(BIP150.prototype, EventEmitter.prototype);
|
||||||
@ -93,7 +94,7 @@ Object.setPrototypeOf(BIP150.prototype, EventEmitter.prototype);
|
|||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
|
|
||||||
BIP150.prototype._init = function _init() {
|
BIP150.prototype.init = function init() {
|
||||||
if (this.outbound)
|
if (this.outbound)
|
||||||
this.peerIdentity = this.db.getKnown(this.hostname);
|
this.peerIdentity = this.db.getKnown(this.hostname);
|
||||||
};
|
};
|
||||||
@ -252,7 +253,7 @@ BIP150.prototype.rekey = function rekey(sid, key, req, res) {
|
|||||||
key.copy(seed, 32);
|
key.copy(seed, 32);
|
||||||
req.copy(seed, 64);
|
req.copy(seed, 64);
|
||||||
res.copy(seed, 97);
|
res.copy(seed, 97);
|
||||||
return digest.hash256(seed);
|
return hash256.digest(seed);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -296,7 +297,7 @@ BIP150.prototype.hash = function hash(sid, ch, key) {
|
|||||||
sid.copy(data, 0);
|
sid.copy(data, 0);
|
||||||
data[32] = ch.charCodeAt(0);
|
data[32] = ch.charCodeAt(0);
|
||||||
key.copy(data, 33);
|
key.copy(data, 33);
|
||||||
return digest.hash256(data);
|
return hash256.digest(data);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -445,8 +446,8 @@ BIP150.address = function address(key) {
|
|||||||
const bw = new StaticWriter(27);
|
const bw = new StaticWriter(27);
|
||||||
bw.writeU8(0x0f);
|
bw.writeU8(0x0f);
|
||||||
bw.writeU16BE(0xff01);
|
bw.writeU16BE(0xff01);
|
||||||
bw.writeBytes(digest.hash160(key));
|
bw.writeBytes(hash160.digest(key));
|
||||||
bw.writeChecksum(digest.hash256);
|
bw.writeChecksum(hash256.digest);
|
||||||
return base58.encode(bw.render());
|
return base58.encode(bw.render());
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -468,7 +469,7 @@ function AuthDB(options) {
|
|||||||
this.known = new Map();
|
this.known = new Map();
|
||||||
this.authorized = [];
|
this.authorized = [];
|
||||||
|
|
||||||
this._init(options);
|
this.init(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -476,7 +477,7 @@ function AuthDB(options) {
|
|||||||
* @param {Object} options
|
* @param {Object} options
|
||||||
*/
|
*/
|
||||||
|
|
||||||
AuthDB.prototype._init = function _init(options) {
|
AuthDB.prototype.init = function init(options) {
|
||||||
if (!options)
|
if (!options)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|||||||
@ -54,7 +54,7 @@ function HostList(options) {
|
|||||||
this.timer = null;
|
this.timer = null;
|
||||||
this.needsFlush = false;
|
this.needsFlush = false;
|
||||||
|
|
||||||
this._init();
|
this.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -133,7 +133,7 @@ HostList.scores = {
|
|||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
|
|
||||||
HostList.prototype._init = function _init() {
|
HostList.prototype.init = function init() {
|
||||||
const options = this.options;
|
const options = this.options;
|
||||||
const scores = HostList.scores;
|
const scores = HostList.scores;
|
||||||
const hosts = IP.getPublic();
|
const hosts = IP.getPublic();
|
||||||
|
|||||||
@ -143,7 +143,7 @@ function Peer(options) {
|
|||||||
this.responseMap = new Map();
|
this.responseMap = new Map();
|
||||||
this.compactBlocks = new Map();
|
this.compactBlocks = new Map();
|
||||||
|
|
||||||
this._init();
|
this.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
Object.setPrototypeOf(Peer.prototype, EventEmitter.prototype);
|
Object.setPrototypeOf(Peer.prototype, EventEmitter.prototype);
|
||||||
@ -262,7 +262,7 @@ Peer.fromOptions = function fromOptions(options) {
|
|||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Peer.prototype._init = function _init() {
|
Peer.prototype.init = function init() {
|
||||||
this.parser.on('packet', async (packet) => {
|
this.parser.on('packet', async (packet) => {
|
||||||
try {
|
try {
|
||||||
await this.readPacket(packet);
|
await this.readPacket(packet);
|
||||||
@ -377,7 +377,7 @@ Peer.prototype.setAuth = function setAuth(db, key) {
|
|||||||
* @param {net.Socket} socket
|
* @param {net.Socket} socket
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Peer.prototype.bind = function bind(socket) {
|
Peer.prototype._bind = function _bind(socket) {
|
||||||
assert(!this.socket);
|
assert(!this.socket);
|
||||||
|
|
||||||
this.socket = socket;
|
this.socket = socket;
|
||||||
@ -422,7 +422,7 @@ Peer.prototype.accept = function accept(socket) {
|
|||||||
this.outbound = false;
|
this.outbound = false;
|
||||||
this.connected = true;
|
this.connected = true;
|
||||||
|
|
||||||
this.bind(socket);
|
this._bind(socket);
|
||||||
|
|
||||||
return socket;
|
return socket;
|
||||||
};
|
};
|
||||||
@ -443,7 +443,7 @@ Peer.prototype.connect = function connect(addr) {
|
|||||||
this.outbound = true;
|
this.outbound = true;
|
||||||
this.connected = false;
|
this.connected = false;
|
||||||
|
|
||||||
this.bind(socket);
|
this._bind(socket);
|
||||||
|
|
||||||
return socket;
|
return socket;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -9,7 +9,6 @@
|
|||||||
|
|
||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
const EventEmitter = require('events');
|
const EventEmitter = require('events');
|
||||||
const AsyncObject = require('../utils/asyncobject');
|
|
||||||
const util = require('../utils/util');
|
const util = require('../utils/util');
|
||||||
const IP = require('binet');
|
const IP = require('binet');
|
||||||
const co = require('../utils/co');
|
const co = require('../utils/co');
|
||||||
@ -29,6 +28,7 @@ const external = require('./external');
|
|||||||
const List = require('../utils/list');
|
const List = require('../utils/list');
|
||||||
const tcp = require('./tcp');
|
const tcp = require('./tcp');
|
||||||
const dns = require('./dns');
|
const dns = require('./dns');
|
||||||
|
const socks = require('./socks');
|
||||||
const HostList = require('./hostlist');
|
const HostList = require('./hostlist');
|
||||||
const UPNP = require('./upnp');
|
const UPNP = require('./upnp');
|
||||||
const InvItem = require('../primitives/invitem');
|
const InvItem = require('../primitives/invitem');
|
||||||
@ -77,8 +77,9 @@ function Pool(options) {
|
|||||||
if (!(this instanceof Pool))
|
if (!(this instanceof Pool))
|
||||||
return new Pool(options);
|
return new Pool(options);
|
||||||
|
|
||||||
AsyncObject.call(this);
|
EventEmitter.call(this);
|
||||||
|
|
||||||
|
this.opened = false;
|
||||||
this.options = new PoolOptions(options);
|
this.options = new PoolOptions(options);
|
||||||
|
|
||||||
this.network = this.options.network;
|
this.network = this.options.network;
|
||||||
@ -117,10 +118,10 @@ function Pool(options) {
|
|||||||
if (!this.options.mempool)
|
if (!this.options.mempool)
|
||||||
this.txFilter = new RollingFilter(50000, 0.000001);
|
this.txFilter = new RollingFilter(50000, 0.000001);
|
||||||
|
|
||||||
this._init();
|
this.init();
|
||||||
};
|
};
|
||||||
|
|
||||||
Object.setPrototypeOf(Pool.prototype, AsyncObject.prototype);
|
Object.setPrototypeOf(Pool.prototype, EventEmitter.prototype);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Discovery interval for UPNP and DNS seeds.
|
* Discovery interval for UPNP and DNS seeds.
|
||||||
@ -135,7 +136,7 @@ Pool.DISCOVERY_INTERVAL = 120000;
|
|||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Pool.prototype._init = function _init() {
|
Pool.prototype.init = function init() {
|
||||||
this.server.on('error', (err) => {
|
this.server.on('error', (err) => {
|
||||||
this.emit('error', err);
|
this.emit('error', err);
|
||||||
});
|
});
|
||||||
@ -206,16 +207,12 @@ Pool.prototype._init = function _init() {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Open the pool, wait for the chain to load.
|
* Open the pool, wait for the chain to load.
|
||||||
* @method
|
|
||||||
* @alias Pool#open
|
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Pool.prototype._open = async function _open() {
|
Pool.prototype.open = async function open() {
|
||||||
if (this.mempool)
|
assert(!this.opened, 'Pool is already open.');
|
||||||
await this.mempool.open();
|
this.opened = true;
|
||||||
else
|
|
||||||
await this.chain.open();
|
|
||||||
|
|
||||||
this.logger.info('Pool loaded (maxpeers=%d).', this.options.maxOutbound);
|
this.logger.info('Pool loaded (maxpeers=%d).', this.options.maxOutbound);
|
||||||
|
|
||||||
@ -228,6 +225,19 @@ Pool.prototype._open = async function _open() {
|
|||||||
this.resetChain();
|
this.resetChain();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close and destroy the pool.
|
||||||
|
* @method
|
||||||
|
* @alias Pool#close
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
|
||||||
|
Pool.prototype.close = async function close() {
|
||||||
|
assert(this.opened, 'Pool is not open.');
|
||||||
|
this.opened = false;
|
||||||
|
return this.disconnect();
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reset header chain.
|
* Reset header chain.
|
||||||
*/
|
*/
|
||||||
@ -253,17 +263,6 @@ Pool.prototype.resetChain = function resetChain() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Close and destroy the pool.
|
|
||||||
* @method
|
|
||||||
* @alias Pool#close
|
|
||||||
* @returns {Promise}
|
|
||||||
*/
|
|
||||||
|
|
||||||
Pool.prototype._close = async function _close() {
|
|
||||||
await this.disconnect();
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Connect to the network.
|
* Connect to the network.
|
||||||
* @method
|
* @method
|
||||||
@ -286,7 +285,7 @@ Pool.prototype.connect = async function connect() {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Pool.prototype._connect = async function _connect() {
|
Pool.prototype._connect = async function _connect() {
|
||||||
assert(this.loaded, 'Pool is not loaded.');
|
assert(this.opened, 'Pool is not opened.');
|
||||||
|
|
||||||
if (this.connected)
|
if (this.connected)
|
||||||
return;
|
return;
|
||||||
@ -329,8 +328,6 @@ Pool.prototype.disconnect = async function disconnect() {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Pool.prototype._disconnect = async function _disconnect() {
|
Pool.prototype._disconnect = async function _disconnect() {
|
||||||
assert(this.loaded, 'Pool is not loaded.');
|
|
||||||
|
|
||||||
if (!this.connected)
|
if (!this.connected)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -606,7 +603,7 @@ Pool.prototype.handleSocket = function handleSocket(socket) {
|
|||||||
|
|
||||||
const host = IP.toHostname(ip, socket.remotePort);
|
const host = IP.toHostname(ip, socket.remotePort);
|
||||||
|
|
||||||
assert(!this.peers.map[host], 'Port collision.');
|
assert(!this.peers.map.has(host), 'Port collision.');
|
||||||
|
|
||||||
this.addInbound(socket);
|
this.addInbound(socket);
|
||||||
};
|
};
|
||||||
@ -618,7 +615,7 @@ Pool.prototype.handleSocket = function handleSocket(socket) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Pool.prototype.addLoader = function addLoader() {
|
Pool.prototype.addLoader = function addLoader() {
|
||||||
if (!this.loaded)
|
if (!this.opened)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
assert(!this.peers.load);
|
assert(!this.peers.load);
|
||||||
@ -657,7 +654,7 @@ Pool.prototype.addLoader = function addLoader() {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Pool.prototype.setLoader = function setLoader(peer) {
|
Pool.prototype.setLoader = function setLoader(peer) {
|
||||||
if (!this.loaded)
|
if (!this.opened)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
assert(peer.outbound);
|
assert(peer.outbound);
|
||||||
@ -677,7 +674,7 @@ Pool.prototype.setLoader = function setLoader(peer) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Pool.prototype.startSync = function startSync() {
|
Pool.prototype.startSync = function startSync() {
|
||||||
if (!this.loaded)
|
if (!this.opened)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
assert(this.connected, 'Pool is not connected!');
|
assert(this.connected, 'Pool is not connected!');
|
||||||
@ -691,7 +688,7 @@ Pool.prototype.startSync = function startSync() {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Pool.prototype.forceSync = function forceSync() {
|
Pool.prototype.forceSync = function forceSync() {
|
||||||
if (!this.loaded)
|
if (!this.opened)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
assert(this.connected, 'Pool is not connected!');
|
assert(this.connected, 'Pool is not connected!');
|
||||||
@ -1409,7 +1406,7 @@ Pool.prototype.handleClose = async function handleClose(peer, connected) {
|
|||||||
|
|
||||||
this.emit('peer close', peer, connected);
|
this.emit('peer close', peer, connected);
|
||||||
|
|
||||||
if (!this.loaded)
|
if (!this.opened)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (this.disconnecting)
|
if (this.disconnecting)
|
||||||
@ -1773,6 +1770,7 @@ Pool.prototype.handleGetData = async function handleGetData(peer, packet) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const notFound = [];
|
const notFound = [];
|
||||||
|
|
||||||
let txs = 0;
|
let txs = 0;
|
||||||
let blocks = 0;
|
let blocks = 0;
|
||||||
let compact = 0;
|
let compact = 0;
|
||||||
@ -3018,7 +3016,7 @@ Pool.prototype.handleUnknown = async function handleUnknown(peer, packet) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Pool.prototype.addInbound = function addInbound(socket) {
|
Pool.prototype.addInbound = function addInbound(socket) {
|
||||||
if (!this.loaded) {
|
if (!this.opened) {
|
||||||
socket.destroy();
|
socket.destroy();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -3088,7 +3086,7 @@ Pool.prototype.getHost = function getHost() {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Pool.prototype.addOutbound = function addOutbound() {
|
Pool.prototype.addOutbound = function addOutbound() {
|
||||||
if (!this.loaded)
|
if (!this.opened)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (this.peers.outbound >= this.options.maxOutbound)
|
if (this.peers.outbound >= this.options.maxOutbound)
|
||||||
@ -3340,7 +3338,7 @@ Pool.prototype.getBlocks = async function getBlocks(peer, tip, stop) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Pool.prototype.getBlock = function getBlock(peer, hashes) {
|
Pool.prototype.getBlock = function getBlock(peer, hashes) {
|
||||||
if (!this.loaded)
|
if (!this.opened)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!peer.handshake)
|
if (!peer.handshake)
|
||||||
@ -3384,7 +3382,7 @@ Pool.prototype.getBlock = function getBlock(peer, hashes) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Pool.prototype.getTX = function getTX(peer, hashes) {
|
Pool.prototype.getTX = function getTX(peer, hashes) {
|
||||||
if (!this.loaded)
|
if (!this.opened)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!peer.handshake)
|
if (!peer.handshake)
|
||||||
@ -4017,7 +4015,10 @@ PoolOptions.prototype.getRate = function getRate(hash) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
PoolOptions.prototype._createSocket = function _createSocket(port, host) {
|
PoolOptions.prototype._createSocket = function _createSocket(port, host) {
|
||||||
return tcp.createSocket(port, host, this.proxy);
|
if (this.proxy)
|
||||||
|
return socks.connect(this.proxy, port, host);
|
||||||
|
|
||||||
|
return tcp.createSocket(port, host);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -4029,7 +4030,7 @@ PoolOptions.prototype._createSocket = function _createSocket(port, host) {
|
|||||||
|
|
||||||
PoolOptions.prototype._resolve = function _resolve(name) {
|
PoolOptions.prototype._resolve = function _resolve(name) {
|
||||||
if (this.onion)
|
if (this.onion)
|
||||||
return dns.lookup(name, this.proxy);
|
return socks.resolve(this.proxy, name);
|
||||||
|
|
||||||
return dns.lookup(name);
|
return dns.lookup(name);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -32,12 +32,12 @@ function ProxySocket(uri) {
|
|||||||
|
|
||||||
this.closed = false;
|
this.closed = false;
|
||||||
|
|
||||||
this._init();
|
this.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
Object.setPrototypeOf(ProxySocket.prototype, EventEmitter.prototype);
|
Object.setPrototypeOf(ProxySocket.prototype, EventEmitter.prototype);
|
||||||
|
|
||||||
ProxySocket.prototype._init = function _init() {
|
ProxySocket.prototype.init = function init() {
|
||||||
this.socket.bind('info', (info) => {
|
this.socket.bind('info', (info) => {
|
||||||
if (this.closed)
|
if (this.closed)
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -15,8 +15,6 @@ const EventEmitter = require('events');
|
|||||||
const net = require('net');
|
const net = require('net');
|
||||||
const {format} = require('util');
|
const {format} = require('util');
|
||||||
const IP = require('binet');
|
const IP = require('binet');
|
||||||
const StaticWriter = require('bbuf/lib/staticwriter');
|
|
||||||
const BufferReader = require('bbuf/lib/reader');
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SOCKS state machine
|
* SOCKS state machine
|
||||||
@ -322,15 +320,13 @@ SOCKS.prototype.sendAuth = function sendAuth() {
|
|||||||
const plen = Buffer.byteLength(pass, 'ascii');
|
const plen = Buffer.byteLength(pass, 'ascii');
|
||||||
const size = 3 + ulen + plen;
|
const size = 3 + ulen + plen;
|
||||||
|
|
||||||
const bw = new StaticWriter(size);
|
const packet = Buffer.allocUnsafe(size);
|
||||||
|
|
||||||
bw.writeU8(0x01);
|
packet[0] = 0x01;
|
||||||
bw.writeU8(ulen);
|
packet[1] = ulen;
|
||||||
bw.writeString(user, 'ascii');
|
packet.write(user, 2, ulen, 'ascii');
|
||||||
bw.writeU8(plen);
|
packet[2 + ulen] = plen;
|
||||||
bw.writeString(pass, 'ascii');
|
packet.write(pass, 2 + ulen, plen, 'ascii');
|
||||||
|
|
||||||
const packet = bw.render();
|
|
||||||
|
|
||||||
this.state = SOCKS.states.AUTH;
|
this.state = SOCKS.states.AUTH;
|
||||||
this.socket.write(packet);
|
this.socket.write(packet);
|
||||||
@ -374,6 +370,7 @@ SOCKS.prototype.auth = function auth() {
|
|||||||
SOCKS.prototype.sendProxy = function sendProxy() {
|
SOCKS.prototype.sendProxy = function sendProxy() {
|
||||||
const host = this.destHost;
|
const host = this.destHost;
|
||||||
const port = this.destPort;
|
const port = this.destPort;
|
||||||
|
|
||||||
let ip, len, type, name;
|
let ip, len, type, name;
|
||||||
|
|
||||||
switch (IP.getStringType(host)) {
|
switch (IP.getStringType(host)) {
|
||||||
@ -396,20 +393,20 @@ SOCKS.prototype.sendProxy = function sendProxy() {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
const bw = new StaticWriter(6 + len);
|
const packet = Buffer.allocUnsafe(6 + len);
|
||||||
|
|
||||||
bw.writeU8(0x05);
|
let off = 0;
|
||||||
bw.writeU8(0x01);
|
|
||||||
bw.writeU8(0x00);
|
packet[off++] = 0x05;
|
||||||
bw.writeU8(type);
|
packet[off++] = 0x01;
|
||||||
|
packet[off++] = 0x00;
|
||||||
|
packet[off++] = type;
|
||||||
|
|
||||||
if (type === 0x03)
|
if (type === 0x03)
|
||||||
bw.writeU8(name.length);
|
packet[off++] = name.length;
|
||||||
|
|
||||||
bw.writeBytes(name);
|
off += name.copy(packet, off);
|
||||||
bw.writeU16BE(port);
|
packet.writeUInt32BE(port, off, true);
|
||||||
|
|
||||||
const packet = bw.render();
|
|
||||||
|
|
||||||
this.state = SOCKS.states.PROXY;
|
this.state = SOCKS.states.PROXY;
|
||||||
this.socket.write(packet);
|
this.socket.write(packet);
|
||||||
@ -457,17 +454,15 @@ SOCKS.prototype.sendResolve = function sendResolve() {
|
|||||||
const name = this.name;
|
const name = this.name;
|
||||||
const len = Buffer.byteLength(name, 'utf8');
|
const len = Buffer.byteLength(name, 'utf8');
|
||||||
|
|
||||||
const bw = new StaticWriter(7 + len);
|
const packet = Buffer.allocUnsafe(7 + len);
|
||||||
|
|
||||||
bw.writeU8(0x05);
|
packet[0] = 0x05;
|
||||||
bw.writeU8(0xf0);
|
packet[1] = 0xf0;
|
||||||
bw.writeU8(0x00);
|
packet[2] = 0x00;
|
||||||
bw.writeU8(0x03);
|
packet[3] = 0x03;
|
||||||
bw.writeU8(len);
|
packet[4] = len;
|
||||||
bw.writeString(name, 'utf8');
|
packet.write(name, 5, len, 'utf8');
|
||||||
bw.writeU16BE(0);
|
packet.writeUInt32BE(0, 5 + len, true);
|
||||||
|
|
||||||
const packet = bw.render();
|
|
||||||
|
|
||||||
this.state = SOCKS.states.RESOLVE;
|
this.state = SOCKS.states.RESOLVE;
|
||||||
this.socket.write(packet);
|
this.socket.write(packet);
|
||||||
@ -705,42 +700,47 @@ function parseProxy(host) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseAddr(data, offset) {
|
function parseAddr(data, off) {
|
||||||
const br = new BufferReader(data);
|
if (data.length - off < 2)
|
||||||
|
|
||||||
if (br.left() < offset + 2)
|
|
||||||
throw new Error('Bad SOCKS address length.');
|
throw new Error('Bad SOCKS address length.');
|
||||||
|
|
||||||
br.seek(offset);
|
const type = data[off];
|
||||||
|
off += 1;
|
||||||
|
|
||||||
const type = br.readU8();
|
|
||||||
let host, port;
|
let host, port;
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 0x01: {
|
case 0x01: {
|
||||||
if (br.left() < 6)
|
if (data.length - off < 6)
|
||||||
throw new Error('Bad SOCKS ipv4 length.');
|
throw new Error('Bad SOCKS ipv4 length.');
|
||||||
|
|
||||||
host = IP.toString(br.readBytes(4));
|
host = IP.toString(data.slice(off, off + 4));
|
||||||
port = br.readU16BE();
|
off += 4;
|
||||||
|
|
||||||
|
port = data.readUInt16BE(off, true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0x03: {
|
case 0x03: {
|
||||||
const len = br.readU8();
|
const len = data[off];
|
||||||
|
off += 1;
|
||||||
|
|
||||||
if (br.left() < len + 2)
|
if (data.length - off < len + 2)
|
||||||
throw new Error('Bad SOCKS domain length.');
|
throw new Error('Bad SOCKS domain length.');
|
||||||
|
|
||||||
host = br.readString(len, 'utf8');
|
host = data.toString('utf8', off, off + len);
|
||||||
port = br.readU16BE();
|
off += len;
|
||||||
|
|
||||||
|
port = data.readUInt16BE(off, true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0x04: {
|
case 0x04: {
|
||||||
if (br.left() < 18)
|
if (data.length - off < 18)
|
||||||
throw new Error('Bad SOCKS ipv6 length.');
|
throw new Error('Bad SOCKS ipv6 length.');
|
||||||
|
|
||||||
host = IP.toString(br.readBytes(16));
|
host = IP.toString(data.slice(off, off + 16));
|
||||||
port = br.readU16BE();
|
off += 16;
|
||||||
|
|
||||||
|
port = data.readUInt16BE(off, true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
@ -748,11 +748,7 @@ function parseAddr(data, offset) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return { type, host, port };
|
||||||
type: type,
|
|
||||||
host: host,
|
|
||||||
port: port
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@ -10,16 +10,14 @@ const assert = require('assert');
|
|||||||
const dgram = require('dgram');
|
const dgram = require('dgram');
|
||||||
const url = require('url');
|
const url = require('url');
|
||||||
const breq = require('breq');
|
const breq = require('breq');
|
||||||
const co = require('../utils/co');
|
|
||||||
const Lock = require('../utils/lock');
|
|
||||||
const IP = require('binet');
|
const IP = require('binet');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* UPNP
|
* UPNP
|
||||||
* @alias module:net.UPNP
|
* @alias module:net.UPNP
|
||||||
* @constructor
|
* @constructor
|
||||||
* @param {String?} host - Multicast IP.
|
* @param {String} [host=239.255.255.250] - Multicast IP.
|
||||||
* @param {Number?} port - Multicast port.
|
* @param {Number} [port=1900] - Multicast port.
|
||||||
* @param {String?} gateway - Gateway name.
|
* @param {String?} gateway - Gateway name.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -30,7 +28,6 @@ function UPNP(host, port, gateway) {
|
|||||||
this.host = host || '239.255.255.250';
|
this.host = host || '239.255.255.250';
|
||||||
this.port = port || 1900;
|
this.port = port || 1900;
|
||||||
this.gateway = gateway || UPNP.INTERNET_GATEWAY;
|
this.gateway = gateway || UPNP.INTERNET_GATEWAY;
|
||||||
this.locker = new Lock();
|
|
||||||
this.timeout = null;
|
this.timeout = null;
|
||||||
this.job = null;
|
this.job = null;
|
||||||
}
|
}
|
||||||
@ -133,25 +130,14 @@ UPNP.prototype.stopTimeout = function stopTimeout() {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Discover gateway.
|
* Discover gateway.
|
||||||
* @returns {Promise} Location string.
|
|
||||||
*/
|
|
||||||
|
|
||||||
UPNP.prototype.discover = async function discover() {
|
|
||||||
const unlock = await this.locker.lock();
|
|
||||||
try {
|
|
||||||
return await this._discover();
|
|
||||||
} finally {
|
|
||||||
unlock();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Discover gateway (without a lock).
|
|
||||||
* @private
|
* @private
|
||||||
* @returns {Promise} Location string.
|
* @returns {Promise} Location string.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
UPNP.prototype._discover = async function _discover() {
|
UPNP.prototype.discover = async function discover() {
|
||||||
|
if (this.job)
|
||||||
|
throw new Error('Job already in progress.');
|
||||||
|
|
||||||
const socket = dgram.createSocket('udp4');
|
const socket = dgram.createSocket('udp4');
|
||||||
|
|
||||||
socket.on('error', (err) => {
|
socket.on('error', (err) => {
|
||||||
@ -175,8 +161,8 @@ UPNP.prototype._discover = async function _discover() {
|
|||||||
|
|
||||||
socket.send(msg, this.port, this.host);
|
socket.send(msg, this.port, this.host);
|
||||||
|
|
||||||
return await new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
this.job = co.job(resolve, reject);
|
this.job = { resolve, reject };
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
const assert = require('assert');
|
||||||
const Chain = require('../blockchain/chain');
|
const Chain = require('../blockchain/chain');
|
||||||
const Fees = require('../mempool/fees');
|
const Fees = require('../mempool/fees');
|
||||||
const Mempool = require('../mempool/mempool');
|
const Mempool = require('../mempool/mempool');
|
||||||
@ -43,6 +44,8 @@ function FullNode(options) {
|
|||||||
|
|
||||||
Node.call(this, 'bcoin', 'bcoin.conf', 'debug.log', options);
|
Node.call(this, 'bcoin', 'bcoin.conf', 'debug.log', options);
|
||||||
|
|
||||||
|
this.opened = false;
|
||||||
|
|
||||||
// SPV flag.
|
// SPV flag.
|
||||||
this.spv = false;
|
this.spv = false;
|
||||||
|
|
||||||
@ -104,6 +107,7 @@ function FullNode(options) {
|
|||||||
identityKey: this.config.buf('identity-key'),
|
identityKey: this.config.buf('identity-key'),
|
||||||
maxOutbound: this.config.uint('max-outbound'),
|
maxOutbound: this.config.uint('max-outbound'),
|
||||||
maxInbound: this.config.uint('max-inbound'),
|
maxInbound: this.config.uint('max-inbound'),
|
||||||
|
createSocket: this.config.func('create-socket'),
|
||||||
proxy: this.config.str('proxy'),
|
proxy: this.config.str('proxy'),
|
||||||
onion: this.config.bool('onion'),
|
onion: this.config.bool('onion'),
|
||||||
upnp: this.config.bool('upnp'),
|
upnp: this.config.bool('upnp'),
|
||||||
@ -151,7 +155,7 @@ function FullNode(options) {
|
|||||||
noAuth: this.config.bool('no-auth')
|
noAuth: this.config.bool('no-auth')
|
||||||
});
|
});
|
||||||
|
|
||||||
this._init();
|
this.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
Object.setPrototypeOf(FullNode.prototype, Node.prototype);
|
Object.setPrototypeOf(FullNode.prototype, Node.prototype);
|
||||||
@ -161,7 +165,7 @@ Object.setPrototypeOf(FullNode.prototype, Node.prototype);
|
|||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
|
|
||||||
FullNode.prototype._init = function _init() {
|
FullNode.prototype.init = function init() {
|
||||||
// Bind to errors
|
// Bind to errors
|
||||||
this.chain.on('error', err => this.error(err));
|
this.chain.on('error', err => this.error(err));
|
||||||
this.mempool.on('error', err => this.error(err));
|
this.mempool.on('error', err => this.error(err));
|
||||||
@ -176,7 +180,7 @@ FullNode.prototype._init = function _init() {
|
|||||||
this.emit('tx', tx);
|
this.emit('tx', tx);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.chain.hook('connect', async (entry, block) => {
|
this.chain.on('connect', async (entry, block) => {
|
||||||
try {
|
try {
|
||||||
await this.mempool._addBlock(entry, block.txs);
|
await this.mempool._addBlock(entry, block.txs);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -186,7 +190,7 @@ FullNode.prototype._init = function _init() {
|
|||||||
this.emit('connect', entry, block);
|
this.emit('connect', entry, block);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.chain.hook('disconnect', async (entry, block) => {
|
this.chain.on('disconnect', async (entry, block) => {
|
||||||
try {
|
try {
|
||||||
await this.mempool._removeBlock(entry, block.txs);
|
await this.mempool._removeBlock(entry, block.txs);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -195,7 +199,7 @@ FullNode.prototype._init = function _init() {
|
|||||||
this.emit('disconnect', entry, block);
|
this.emit('disconnect', entry, block);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.chain.hook('reorganize', async (tip, competitor) => {
|
this.chain.on('reorganize', async (tip, competitor) => {
|
||||||
try {
|
try {
|
||||||
await this.mempool._handleReorg();
|
await this.mempool._handleReorg();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -204,7 +208,7 @@ FullNode.prototype._init = function _init() {
|
|||||||
this.emit('reorganize', tip, competitor);
|
this.emit('reorganize', tip, competitor);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.chain.hook('reset', async (tip) => {
|
this.chain.on('reset', async (tip) => {
|
||||||
try {
|
try {
|
||||||
await this.mempool._reset();
|
await this.mempool._reset();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -223,7 +227,11 @@ FullNode.prototype._init = function _init() {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
FullNode.prototype._open = async function _open() {
|
FullNode.prototype.open = async function open() {
|
||||||
|
assert(!this.opened, 'FullNode is already open.');
|
||||||
|
this.opened = true;
|
||||||
|
|
||||||
|
await this.handlePreopen();
|
||||||
await this.chain.open();
|
await this.chain.open();
|
||||||
await this.mempool.open();
|
await this.mempool.open();
|
||||||
await this.miner.open();
|
await this.miner.open();
|
||||||
@ -231,8 +239,8 @@ FullNode.prototype._open = async function _open() {
|
|||||||
|
|
||||||
await this.openPlugins();
|
await this.openPlugins();
|
||||||
|
|
||||||
if (this.http)
|
await this.http.open();
|
||||||
await this.http.open();
|
await this.handleOpen();
|
||||||
|
|
||||||
this.logger.info('Node is loaded.');
|
this.logger.info('Node is loaded.');
|
||||||
};
|
};
|
||||||
@ -243,9 +251,12 @@ FullNode.prototype._open = async function _open() {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
FullNode.prototype._close = async function _close() {
|
FullNode.prototype.close = async function close() {
|
||||||
if (this.http)
|
assert(this.opened, 'FullNode is not open.');
|
||||||
await this.http.close();
|
this.opened = false;
|
||||||
|
|
||||||
|
await this.handlePreclose();
|
||||||
|
await this.http.close();
|
||||||
|
|
||||||
await this.closePlugins();
|
await this.closePlugins();
|
||||||
|
|
||||||
@ -253,6 +264,7 @@ FullNode.prototype._close = async function _close() {
|
|||||||
await this.miner.close();
|
await this.miner.close();
|
||||||
await this.mempool.close();
|
await this.mempool.close();
|
||||||
await this.chain.close();
|
await this.chain.close();
|
||||||
|
await this.handleClose();
|
||||||
|
|
||||||
this.logger.info('Node is closed.');
|
this.logger.info('Node is closed.');
|
||||||
};
|
};
|
||||||
|
|||||||
@ -8,11 +8,11 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
|
const EventEmitter = require('events');
|
||||||
const fs = require('bfile');
|
const fs = require('bfile');
|
||||||
const Logger = require('blgr');
|
const Logger = require('blgr');
|
||||||
const Config = require('bcfg');
|
const Config = require('bcfg');
|
||||||
const Network = require('../protocol/network');
|
const Network = require('../protocol/network');
|
||||||
const AsyncObject = require('../utils/asyncobject');
|
|
||||||
const WorkerPool = require('../workers/workerpool');
|
const WorkerPool = require('../workers/workerpool');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -28,7 +28,7 @@ function Node(module, config, file, options) {
|
|||||||
if (!(this instanceof Node))
|
if (!(this instanceof Node))
|
||||||
return new Node(module, config, file, options);
|
return new Node(module, config, file, options);
|
||||||
|
|
||||||
AsyncObject.call(this);
|
EventEmitter.call(this);
|
||||||
|
|
||||||
this.config = new Config(module, {
|
this.config = new Config(module, {
|
||||||
suffix: 'network',
|
suffix: 'network',
|
||||||
@ -59,18 +59,18 @@ function Node(module, config, file, options) {
|
|||||||
this.miner = null;
|
this.miner = null;
|
||||||
this.http = null;
|
this.http = null;
|
||||||
|
|
||||||
this.init(file);
|
this._init(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
Object.setPrototypeOf(Node.prototype, AsyncObject.prototype);
|
Object.setPrototypeOf(Node.prototype, EventEmitter.prototype);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize options.
|
* Initialize node.
|
||||||
* @private
|
* @private
|
||||||
* @param {Object} options
|
* @param {Object} options
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Node.prototype.initOptions = function initOptions(file) {
|
Node.prototype._init = function _init(file) {
|
||||||
const config = this.config;
|
const config = this.config;
|
||||||
|
|
||||||
let logger = new Logger();
|
let logger = new Logger();
|
||||||
@ -95,16 +95,6 @@ Node.prototype.initOptions = function initOptions(file) {
|
|||||||
timeout: config.uint('workers-timeout'),
|
timeout: config.uint('workers-timeout'),
|
||||||
file: config.str('worker-file')
|
file: config.str('worker-file')
|
||||||
});
|
});
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize node.
|
|
||||||
* @private
|
|
||||||
* @param {Object} options
|
|
||||||
*/
|
|
||||||
|
|
||||||
Node.prototype.init = function init(file) {
|
|
||||||
this.initOptions(file);
|
|
||||||
|
|
||||||
this.on('error', () => {});
|
this.on('error', () => {});
|
||||||
|
|
||||||
@ -128,11 +118,6 @@ Node.prototype.init = function init(file) {
|
|||||||
}
|
}
|
||||||
this.emit('error', err);
|
this.emit('error', err);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.hook('preopen', () => this.handlePreopen());
|
|
||||||
this.hook('preclose', () => this.handlePreclose());
|
|
||||||
this.hook('open', () => this.handleOpen());
|
|
||||||
this.hook('close', () => this.handleClose());
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -166,17 +151,17 @@ Node.prototype.handlePreopen = async function handlePreopen() {
|
|||||||
await this.logger.open();
|
await this.logger.open();
|
||||||
await this.workers.open();
|
await this.workers.open();
|
||||||
|
|
||||||
this.bind(this.network.time, 'offset', (offset) => {
|
this._bind(this.network.time, 'offset', (offset) => {
|
||||||
this.logger.info('Time offset: %d (%d minutes).', offset, offset / 60 | 0);
|
this.logger.info('Time offset: %d (%d minutes).', offset, offset / 60 | 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.bind(this.network.time, 'sample', (sample, total) => {
|
this._bind(this.network.time, 'sample', (sample, total) => {
|
||||||
this.logger.debug(
|
this.logger.debug(
|
||||||
'Added time data: samples=%d, offset=%d (%d minutes).',
|
'Added time data: samples=%d, offset=%d (%d minutes).',
|
||||||
total, sample, sample / 60 | 0);
|
total, sample, sample / 60 | 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.bind(this.network.time, 'mismatch', () => {
|
this._bind(this.network.time, 'mismatch', () => {
|
||||||
this.logger.warning('Adjusted time mismatch!');
|
this.logger.warning('Adjusted time mismatch!');
|
||||||
this.logger.warning('Please make sure your system clock is correct!');
|
this.logger.warning('Please make sure your system clock is correct!');
|
||||||
});
|
});
|
||||||
@ -229,7 +214,7 @@ Node.prototype.handleClose = async function handleClose() {
|
|||||||
* @param {Function} listener
|
* @param {Function} listener
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Node.prototype.bind = function bind(obj, event, listener) {
|
Node.prototype._bind = function _bind(obj, event, listener) {
|
||||||
this.bound.push([obj, event, listener]);
|
this.bound.push([obj, event, listener]);
|
||||||
obj.on(event, listener);
|
obj.on(event, listener);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
const assert = require('assert');
|
||||||
const Lock = require('../utils/lock');
|
const Lock = require('../utils/lock');
|
||||||
const Chain = require('../blockchain/chain');
|
const Chain = require('../blockchain/chain');
|
||||||
const Pool = require('../net/pool');
|
const Pool = require('../net/pool');
|
||||||
@ -40,6 +41,8 @@ function SPVNode(options) {
|
|||||||
|
|
||||||
Node.call(this, 'bcoin', 'bcoin.conf', 'debug.log', options);
|
Node.call(this, 'bcoin', 'bcoin.conf', 'debug.log', options);
|
||||||
|
|
||||||
|
this.opened = false;
|
||||||
|
|
||||||
// SPV flag.
|
// SPV flag.
|
||||||
this.spv = true;
|
this.spv = true;
|
||||||
|
|
||||||
@ -73,6 +76,7 @@ function SPVNode(options) {
|
|||||||
bip150: this.config.bool('bip150'),
|
bip150: this.config.bool('bip150'),
|
||||||
identityKey: this.config.buf('identity-key'),
|
identityKey: this.config.buf('identity-key'),
|
||||||
maxOutbound: this.config.uint('max-outbound'),
|
maxOutbound: this.config.uint('max-outbound'),
|
||||||
|
createSocket: this.config.func('create-socket'),
|
||||||
persistent: this.config.bool('persistent'),
|
persistent: this.config.bool('persistent'),
|
||||||
selfish: true,
|
selfish: true,
|
||||||
listen: false
|
listen: false
|
||||||
@ -98,7 +102,7 @@ function SPVNode(options) {
|
|||||||
this.scanLock = new Lock();
|
this.scanLock = new Lock();
|
||||||
this.watchLock = new Lock();
|
this.watchLock = new Lock();
|
||||||
|
|
||||||
this._init();
|
this.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
Object.setPrototypeOf(SPVNode.prototype, Node.prototype);
|
Object.setPrototypeOf(SPVNode.prototype, Node.prototype);
|
||||||
@ -108,7 +112,7 @@ Object.setPrototypeOf(SPVNode.prototype, Node.prototype);
|
|||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
|
|
||||||
SPVNode.prototype._init = function _init() {
|
SPVNode.prototype.init = function init() {
|
||||||
// Bind to errors
|
// Bind to errors
|
||||||
this.chain.on('error', err => this.error(err));
|
this.chain.on('error', err => this.error(err));
|
||||||
this.pool.on('error', err => this.error(err));
|
this.pool.on('error', err => this.error(err));
|
||||||
@ -158,36 +162,42 @@ SPVNode.prototype._init = function _init() {
|
|||||||
/**
|
/**
|
||||||
* Open the node and all its child objects,
|
* Open the node and all its child objects,
|
||||||
* wait for the database to load.
|
* wait for the database to load.
|
||||||
* @alias SPVNode#open
|
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
SPVNode.prototype._open = async function _open(callback) {
|
SPVNode.prototype.open = async function open() {
|
||||||
|
assert(!this.opened, 'SPVNode is already open.');
|
||||||
|
this.opened = true;
|
||||||
|
|
||||||
|
await this.handlePreopen();
|
||||||
await this.chain.open();
|
await this.chain.open();
|
||||||
await this.pool.open();
|
await this.pool.open();
|
||||||
|
|
||||||
await this.openPlugins();
|
await this.openPlugins();
|
||||||
|
|
||||||
if (this.http)
|
await this.http.open();
|
||||||
await this.http.open();
|
await this.handleOpen();
|
||||||
|
|
||||||
this.logger.info('Node is loaded.');
|
this.logger.info('Node is loaded.');
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Close the node, wait for the database to close.
|
* Close the node, wait for the database to close.
|
||||||
* @alias SPVNode#close
|
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
SPVNode.prototype._close = async function _close() {
|
SPVNode.prototype.close = async function close() {
|
||||||
if (this.http)
|
assert(this.opened, 'SPVNode is not open.');
|
||||||
await this.http.close();
|
this.opened = false;
|
||||||
|
|
||||||
|
await this.handlePreclose();
|
||||||
|
await this.http.close();
|
||||||
|
|
||||||
await this.closePlugins();
|
await this.closePlugins();
|
||||||
|
|
||||||
await this.pool.close();
|
await this.pool.close();
|
||||||
await this.chain.close();
|
await this.chain.close();
|
||||||
|
await this.handleClose();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -56,7 +56,7 @@ function Network(options) {
|
|||||||
this.requestMempool = options.requestMempool;
|
this.requestMempool = options.requestMempool;
|
||||||
this.time = new TimeData();
|
this.time = new TimeData();
|
||||||
|
|
||||||
this._init();
|
this.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -89,7 +89,7 @@ Network.simnet = null;
|
|||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Network.prototype._init = function _init() {
|
Network.prototype.init = function init() {
|
||||||
let bits = 0;
|
let bits = 0;
|
||||||
|
|
||||||
for (const deployment of this.deploys)
|
for (const deployment of this.deploys)
|
||||||
|
|||||||
@ -209,48 +209,6 @@ AsyncEmitter.prototype.listenerCount = function listenerCount(type) {
|
|||||||
return listeners.length;
|
return listeners.length;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a listener.
|
|
||||||
* @param {String} type
|
|
||||||
* @param {Function} handler
|
|
||||||
*/
|
|
||||||
|
|
||||||
AsyncEmitter.prototype.bind = function bind(type, handler) {
|
|
||||||
return this.on(type, handler);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Emit event.
|
|
||||||
* @param {String} type
|
|
||||||
* @param {...Object} args
|
|
||||||
* @returns {Promise}
|
|
||||||
*/
|
|
||||||
|
|
||||||
AsyncEmitter.prototype.fire = function fire() {
|
|
||||||
return this.emit.apply(this, arguments);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a listener.
|
|
||||||
* @param {String} type
|
|
||||||
* @param {Function} handler
|
|
||||||
*/
|
|
||||||
|
|
||||||
AsyncEmitter.prototype.hook = function hook(type, handler) {
|
|
||||||
return this.on(type, handler);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Emit event.
|
|
||||||
* @param {String} type
|
|
||||||
* @param {...Object} args
|
|
||||||
* @returns {Promise}
|
|
||||||
*/
|
|
||||||
|
|
||||||
AsyncEmitter.prototype.call = function call() {
|
|
||||||
return this.emitAsync.apply(this, arguments);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Emit an event synchronously.
|
* Emit an event synchronously.
|
||||||
* @param {String} type
|
* @param {String} type
|
||||||
@ -306,7 +264,7 @@ AsyncEmitter.prototype._emit = function _emit(type) {
|
|||||||
|
|
||||||
if (listener.once) {
|
if (listener.once) {
|
||||||
listeners.splice(i, 1);
|
listeners.splice(i, 1);
|
||||||
i--;
|
i -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (arguments.length) {
|
switch (arguments.length) {
|
||||||
@ -390,7 +348,7 @@ AsyncEmitter.prototype._emitAsync = async function _emitAsync(type) {
|
|||||||
|
|
||||||
if (listener.once) {
|
if (listener.once) {
|
||||||
listeners.splice(i, 1);
|
listeners.splice(i, 1);
|
||||||
i--;
|
i -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (arguments.length) {
|
switch (arguments.length) {
|
||||||
|
|||||||
@ -1,252 +0,0 @@
|
|||||||
/*!
|
|
||||||
* async.js - async object class for bcoin
|
|
||||||
* Copyright (c) 2016-2017, Christopher Jeffrey (MIT License).
|
|
||||||
* https://github.com/bcoin-org/bcoin
|
|
||||||
*/
|
|
||||||
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
const assert = require('assert');
|
|
||||||
const EventEmitter = require('events');
|
|
||||||
const Lock = require('./lock');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An abstract object that handles state and
|
|
||||||
* provides recallable open and close methods.
|
|
||||||
* @alias module:utils.AsyncObject
|
|
||||||
* @constructor
|
|
||||||
* @property {Boolean} loading
|
|
||||||
* @property {Boolean} closing
|
|
||||||
* @property {Boolean} loaded
|
|
||||||
*/
|
|
||||||
|
|
||||||
function AsyncObject() {
|
|
||||||
assert(this instanceof AsyncObject);
|
|
||||||
|
|
||||||
EventEmitter.call(this);
|
|
||||||
|
|
||||||
this._asyncLock = new Lock();
|
|
||||||
this._hooks = Object.create(null);
|
|
||||||
|
|
||||||
this.loading = false;
|
|
||||||
this.closing = false;
|
|
||||||
this.loaded = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Object.setPrototypeOf(AsyncObject.prototype, EventEmitter.prototype);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Open the object (recallable).
|
|
||||||
* @method
|
|
||||||
* @returns {Promise}
|
|
||||||
*/
|
|
||||||
|
|
||||||
AsyncObject.prototype.open = async function open() {
|
|
||||||
const unlock = await this._asyncLock.lock();
|
|
||||||
try {
|
|
||||||
return await this.__open();
|
|
||||||
} finally {
|
|
||||||
unlock();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Open the object (without a lock).
|
|
||||||
* @method
|
|
||||||
* @private
|
|
||||||
* @returns {Promise}
|
|
||||||
*/
|
|
||||||
|
|
||||||
AsyncObject.prototype.__open = async function __open() {
|
|
||||||
if (this.loaded)
|
|
||||||
return;
|
|
||||||
|
|
||||||
await this.call('preopen');
|
|
||||||
|
|
||||||
this.loading = true;
|
|
||||||
|
|
||||||
try {
|
|
||||||
await this._open();
|
|
||||||
} catch (e) {
|
|
||||||
this.loading = false;
|
|
||||||
this.emit('error', e);
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.loading = false;
|
|
||||||
this.loaded = true;
|
|
||||||
|
|
||||||
await this.call('open');
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Close the object (recallable).
|
|
||||||
* @method
|
|
||||||
* @returns {Promise}
|
|
||||||
*/
|
|
||||||
|
|
||||||
AsyncObject.prototype.close = async function close() {
|
|
||||||
const unlock = await this._asyncLock.lock();
|
|
||||||
try {
|
|
||||||
return await this.__close();
|
|
||||||
} finally {
|
|
||||||
unlock();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Close the object (without a lock).
|
|
||||||
* @method
|
|
||||||
* @private
|
|
||||||
* @returns {Promise}
|
|
||||||
*/
|
|
||||||
|
|
||||||
AsyncObject.prototype.__close = async function __close() {
|
|
||||||
if (!this.loaded)
|
|
||||||
return;
|
|
||||||
|
|
||||||
await this.call('preclose');
|
|
||||||
|
|
||||||
this.closing = true;
|
|
||||||
|
|
||||||
try {
|
|
||||||
await this._close();
|
|
||||||
} catch (e) {
|
|
||||||
this.closing = false;
|
|
||||||
this.emit('error', e);
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.closing = false;
|
|
||||||
this.loaded = false;
|
|
||||||
|
|
||||||
await this.call('close');
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Close the object (recallable).
|
|
||||||
* @method
|
|
||||||
* @returns {Promise}
|
|
||||||
*/
|
|
||||||
|
|
||||||
AsyncObject.prototype.destroy = AsyncObject.prototype.close;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize the object.
|
|
||||||
* @private
|
|
||||||
* @returns {Promise}
|
|
||||||
*/
|
|
||||||
|
|
||||||
AsyncObject.prototype._open = function _open(callback) {
|
|
||||||
throw new Error('Abstract method.');
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Close the object.
|
|
||||||
* @private
|
|
||||||
* @returns {Promise}
|
|
||||||
*/
|
|
||||||
|
|
||||||
AsyncObject.prototype._close = function _close(callback) {
|
|
||||||
throw new Error('Abstract method.');
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a listener.
|
|
||||||
* @param {String} type
|
|
||||||
* @param {Function} handler
|
|
||||||
*/
|
|
||||||
|
|
||||||
AsyncObject.prototype.bind = function bind(type, handler) {
|
|
||||||
return this.on(type, handler);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Emit event.
|
|
||||||
* @param {String} type
|
|
||||||
* @param {...Object} args
|
|
||||||
* @returns {Promise}
|
|
||||||
*/
|
|
||||||
|
|
||||||
AsyncObject.prototype.fire = function fire() {
|
|
||||||
return this.emit.apply(this, arguments);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a hook listener.
|
|
||||||
* @param {String} type
|
|
||||||
* @param {Function} handler
|
|
||||||
*/
|
|
||||||
|
|
||||||
AsyncObject.prototype.hook = function hook(type, handler) {
|
|
||||||
assert(typeof type === 'string', '`type` must be a string.');
|
|
||||||
|
|
||||||
if (!this._hooks[type])
|
|
||||||
this._hooks[type] = [];
|
|
||||||
|
|
||||||
this._hooks[type].push(handler);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Emit events and hooks for type.
|
|
||||||
* @method
|
|
||||||
* @param {String} type
|
|
||||||
* @param {...Object} args
|
|
||||||
* @returns {Promise}
|
|
||||||
*/
|
|
||||||
|
|
||||||
AsyncObject.prototype.call = async function call() {
|
|
||||||
await this.callHook.apply(this, arguments);
|
|
||||||
this.emit.apply(this, arguments);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Emit an asynchronous event (hook).
|
|
||||||
* Wait for promises to resolve.
|
|
||||||
* @method
|
|
||||||
* @param {String} type
|
|
||||||
* @param {...Object} args
|
|
||||||
* @returns {Promise}
|
|
||||||
*/
|
|
||||||
|
|
||||||
AsyncObject.prototype.callHook = async function callHook(type) {
|
|
||||||
assert(typeof type === 'string', '`type` must be a string.');
|
|
||||||
|
|
||||||
const listeners = this._hooks[type];
|
|
||||||
|
|
||||||
if (!listeners || listeners.length === 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
let args;
|
|
||||||
|
|
||||||
for (const handler of listeners) {
|
|
||||||
switch (arguments.length) {
|
|
||||||
case 1:
|
|
||||||
await handler();
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
await handler(arguments[1]);
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
await handler(arguments[1], arguments[2]);
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
await handler(arguments[1], arguments[2], arguments[3]);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if (!args) {
|
|
||||||
args = new Array(arguments.length - 1);
|
|
||||||
for (let i = 1; i < arguments.length; i++)
|
|
||||||
args[i - 1] = arguments[i];
|
|
||||||
}
|
|
||||||
await handler.apply(null, args);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Expose
|
|
||||||
*/
|
|
||||||
|
|
||||||
module.exports = AsyncObject;
|
|
||||||
@ -11,12 +11,10 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
exports.AsyncEmitter = require('./asyncemitter');
|
exports.AsyncEmitter = require('./asyncemitter');
|
||||||
exports.AsyncObject = require('./asyncobject');
|
|
||||||
exports.binary = require('./binary');
|
exports.binary = require('./binary');
|
||||||
exports.co = require('./co');
|
exports.co = require('./co');
|
||||||
exports.enforce = require('./enforce');
|
exports.enforce = require('./enforce');
|
||||||
exports.fixed = require('./fixed');
|
exports.fixed = require('./fixed');
|
||||||
exports.Heap = require('./heap');
|
|
||||||
exports.List = require('./list');
|
exports.List = require('./list');
|
||||||
exports.Lock = require('./lock');
|
exports.Lock = require('./lock');
|
||||||
exports.LRU = require('./lru');
|
exports.LRU = require('./lru');
|
||||||
|
|||||||
@ -6,7 +6,8 @@
|
|||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const AsyncObject = require('../utils/asyncobject');
|
const assert = require('assert');
|
||||||
|
const AsyncEmitter = require('../utils/asyncemitter');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NodeClient
|
* NodeClient
|
||||||
@ -19,47 +20,47 @@ function NodeClient(node) {
|
|||||||
if (!(this instanceof NodeClient))
|
if (!(this instanceof NodeClient))
|
||||||
return new NodeClient(node);
|
return new NodeClient(node);
|
||||||
|
|
||||||
AsyncObject.call(this);
|
AsyncEmitter.call(this);
|
||||||
|
|
||||||
this.node = node;
|
this.node = node;
|
||||||
this.network = node.network;
|
this.network = node.network;
|
||||||
this.filter = null;
|
this.filter = null;
|
||||||
this.listening = false;
|
this.opened = false;
|
||||||
|
|
||||||
this._init();
|
this.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
Object.setPrototypeOf(NodeClient.prototype, AsyncObject.prototype);
|
Object.setPrototypeOf(NodeClient.prototype, AsyncEmitter.prototype);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the client.
|
* Initialize the client.
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
NodeClient.prototype._init = function _init() {
|
NodeClient.prototype.init = function init() {
|
||||||
this.node.on('connect', (entry, block) => {
|
this.node.on('connect', (entry, block) => {
|
||||||
if (!this.listening)
|
if (!this.opened)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.emit('block connect', entry, block.txs);
|
this.emit('block connect', entry, block.txs);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.node.on('disconnect', (entry, block) => {
|
this.node.on('disconnect', (entry, block) => {
|
||||||
if (!this.listening)
|
if (!this.opened)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.emit('block disconnect', entry);
|
this.emit('block disconnect', entry);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.node.on('tx', (tx) => {
|
this.node.on('tx', (tx) => {
|
||||||
if (!this.listening)
|
if (!this.opened)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.emit('tx', tx);
|
this.emit('tx', tx);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.node.on('reset', (tip) => {
|
this.node.on('reset', (tip) => {
|
||||||
if (!this.listening)
|
if (!this.opened)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.emit('chain reset', tip);
|
this.emit('chain reset', tip);
|
||||||
@ -71,8 +72,9 @@ NodeClient.prototype._init = function _init() {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
NodeClient.prototype._open = async function _open(options) {
|
NodeClient.prototype.open = async function open(options) {
|
||||||
this.listening = true;
|
assert(!this.opened, 'NodeClient is already open.');
|
||||||
|
this.opened = true;
|
||||||
setImmediate(() => this.emit('connect'));
|
setImmediate(() => this.emit('connect'));
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -81,11 +83,32 @@ NodeClient.prototype._open = async function _open(options) {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
NodeClient.prototype._close = async function _close() {
|
NodeClient.prototype.close = async function close() {
|
||||||
this.listening = false;
|
assert(this.opened, 'NodeClient is not open.');
|
||||||
|
this.opened = false;
|
||||||
setImmediate(() => this.emit('disconnect'));
|
setImmediate(() => this.emit('disconnect'));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a listener.
|
||||||
|
* @param {String} type
|
||||||
|
* @param {Function} handler
|
||||||
|
*/
|
||||||
|
|
||||||
|
NodeClient.prototype.bind = function bind(type, handler) {
|
||||||
|
return this.on(type, handler);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a listener.
|
||||||
|
* @param {String} type
|
||||||
|
* @param {Function} handler
|
||||||
|
*/
|
||||||
|
|
||||||
|
NodeClient.prototype.hook = function hook(type, handler) {
|
||||||
|
return this.on(type, handler);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get chain tip.
|
* Get chain tip.
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
@ -187,7 +210,7 @@ NodeClient.prototype.getHashes = async function getHashes(start = -1, end = -1)
|
|||||||
|
|
||||||
NodeClient.prototype.rescan = async function rescan(start) {
|
NodeClient.prototype.rescan = async function rescan(start) {
|
||||||
return this.node.chain.scan(start, this.filter, (entry, txs) => {
|
return this.node.chain.scan(start, this.filter, (entry, txs) => {
|
||||||
return this.call('block rescan', entry, txs);
|
return this.emitAsync('block rescan', entry, txs);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
170
lib/wallet/nullclient.js
Normal file
170
lib/wallet/nullclient.js
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
/*!
|
||||||
|
* nullclient.js - node client for bcoin
|
||||||
|
* Copyright (c) 2014-2017, Christopher Jeffrey (MIT License).
|
||||||
|
* https://github.com/bcoin-org/bcoin
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const assert = require('assert');
|
||||||
|
const EventEmitter = require('events');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NullClient
|
||||||
|
* Sort of a fake local client for separation of concerns.
|
||||||
|
* @alias module:node.NullClient
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
|
||||||
|
function NullClient(wdb) {
|
||||||
|
if (!(this instanceof NullClient))
|
||||||
|
return new NullClient(wdb);
|
||||||
|
|
||||||
|
EventEmitter.call(this);
|
||||||
|
|
||||||
|
this.wdb = wdb;
|
||||||
|
this.network = wdb.network;
|
||||||
|
this.opened = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.setPrototypeOf(NullClient.prototype, EventEmitter.prototype);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open the client.
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
|
||||||
|
NullClient.prototype.open = async function open(options) {
|
||||||
|
assert(!this.opened, 'NullClient is already open.');
|
||||||
|
this.opened = true;
|
||||||
|
setImmediate(() => this.emit('connect'));
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close the client.
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
|
||||||
|
NullClient.prototype.close = async function close() {
|
||||||
|
assert(this.opened, 'NullClient is not open.');
|
||||||
|
this.opened = false;
|
||||||
|
setImmediate(() => this.emit('disconnect'));
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a listener.
|
||||||
|
* @param {String} type
|
||||||
|
* @param {Function} handler
|
||||||
|
*/
|
||||||
|
|
||||||
|
NullClient.prototype.bind = function bind(type, handler) {
|
||||||
|
return this.on(type, handler);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a listener.
|
||||||
|
* @param {String} type
|
||||||
|
* @param {Function} handler
|
||||||
|
*/
|
||||||
|
|
||||||
|
NullClient.prototype.hook = function hook(type, handler) {
|
||||||
|
return this.on(type, handler);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get chain tip.
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
|
||||||
|
NullClient.prototype.getTip = async function getTip() {
|
||||||
|
const {hash, height, time} = this.network.genesis;
|
||||||
|
return { hash, height, time };
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get chain entry.
|
||||||
|
* @param {Hash} hash
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
|
||||||
|
NullClient.prototype.getEntry = async function getEntry(hash) {
|
||||||
|
return { hash, height: 0, time: 0 };
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a transaction. Do not wait for promise.
|
||||||
|
* @param {TX} tx
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
|
||||||
|
NullClient.prototype.send = async function send(tx) {
|
||||||
|
this.wdb.emit('send', tx);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set bloom filter.
|
||||||
|
* @param {Bloom} filter
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
|
||||||
|
NullClient.prototype.setFilter = async function setFilter(filter) {
|
||||||
|
this.wdb.emit('set filter', filter);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add data to filter.
|
||||||
|
* @param {Buffer} data
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
|
||||||
|
NullClient.prototype.addFilter = async function addFilter(data) {
|
||||||
|
this.wdb.emit('add filter', data);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset filter.
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
|
||||||
|
NullClient.prototype.resetFilter = async function resetFilter() {
|
||||||
|
this.wdb.emit('reset filter');
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Esimate smart fee.
|
||||||
|
* @param {Number?} blocks
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
|
||||||
|
NullClient.prototype.estimateFee = async function estimateFee(blocks) {
|
||||||
|
return this.network.feeRate;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get hash range.
|
||||||
|
* @param {Number} start
|
||||||
|
* @param {Number} end
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
|
||||||
|
NullClient.prototype.getHashes = async function getHashes(start = -1, end = -1) {
|
||||||
|
return [this.network.genesis.hash];
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rescan for any missed transactions.
|
||||||
|
* @param {Number|Hash} start - Start block.
|
||||||
|
* @param {Bloom} filter
|
||||||
|
* @param {Function} iter - Iterator.
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
|
||||||
|
NullClient.prototype.rescan = async function rescan(start) {
|
||||||
|
;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Expose
|
||||||
|
*/
|
||||||
|
|
||||||
|
module.exports = NullClient;
|
||||||
@ -82,7 +82,7 @@ Plugin.prototype.open = async function open() {
|
|||||||
|
|
||||||
Plugin.prototype.close = async function close() {
|
Plugin.prototype.close = async function close() {
|
||||||
this.rpc.wallet = this.wdb.primary;
|
this.rpc.wallet = this.wdb.primary;
|
||||||
await this.wdb.open();
|
await this.wdb.close();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
const assert = require('assert');
|
||||||
const Node = require('../node/node');
|
const Node = require('../node/node');
|
||||||
const WalletDB = require('./walletdb');
|
const WalletDB = require('./walletdb');
|
||||||
const HTTP = require('./http');
|
const HTTP = require('./http');
|
||||||
@ -24,6 +25,8 @@ function WalletNode(options) {
|
|||||||
|
|
||||||
Node.call(this, 'bcoin', 'wallet.conf', 'wallet.log', options);
|
Node.call(this, 'bcoin', 'wallet.conf', 'wallet.log', options);
|
||||||
|
|
||||||
|
this.opened = false;
|
||||||
|
|
||||||
this.client = new Client({
|
this.client = new Client({
|
||||||
network: this.network,
|
network: this.network,
|
||||||
url: this.config.str('node-url'),
|
url: this.config.str('node-url'),
|
||||||
@ -66,7 +69,7 @@ function WalletNode(options) {
|
|||||||
walletAuth: this.config.bool('wallet-auth')
|
walletAuth: this.config.bool('wallet-auth')
|
||||||
});
|
});
|
||||||
|
|
||||||
this._init();
|
this.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
Object.setPrototypeOf(WalletNode.prototype, Node.prototype);
|
Object.setPrototypeOf(WalletNode.prototype, Node.prototype);
|
||||||
@ -76,7 +79,7 @@ Object.setPrototypeOf(WalletNode.prototype, Node.prototype);
|
|||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
|
|
||||||
WalletNode.prototype._init = function _init() {
|
WalletNode.prototype.init = function init() {
|
||||||
this.wdb.on('error', err => this.error(err));
|
this.wdb.on('error', err => this.error(err));
|
||||||
this.http.on('error', err => this.error(err));
|
this.http.on('error', err => this.error(err));
|
||||||
|
|
||||||
@ -90,8 +93,11 @@ WalletNode.prototype._init = function _init() {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
WalletNode.prototype._open = async function _open(callback) {
|
WalletNode.prototype.open = async function open() {
|
||||||
// await this.client.open();
|
assert(!this.opened, 'WalletNode is already open.');
|
||||||
|
this.opened = true;
|
||||||
|
|
||||||
|
await this.handlePreopen();
|
||||||
await this.wdb.open();
|
await this.wdb.open();
|
||||||
|
|
||||||
this.rpc.wallet = this.wdb.primary;
|
this.rpc.wallet = this.wdb.primary;
|
||||||
@ -99,6 +105,7 @@ WalletNode.prototype._open = async function _open(callback) {
|
|||||||
await this.openPlugins();
|
await this.openPlugins();
|
||||||
|
|
||||||
await this.http.open();
|
await this.http.open();
|
||||||
|
await this.handleOpen();
|
||||||
|
|
||||||
this.logger.info('Wallet node is loaded.');
|
this.logger.info('Wallet node is loaded.');
|
||||||
};
|
};
|
||||||
@ -109,14 +116,19 @@ WalletNode.prototype._open = async function _open(callback) {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
WalletNode.prototype._close = async function _close() {
|
WalletNode.prototype.close = async function close() {
|
||||||
|
assert(this.opened, 'WalletNode is not open.');
|
||||||
|
this.opened = false;
|
||||||
|
|
||||||
|
await this.handlePreclose();
|
||||||
await this.http.close();
|
await this.http.close();
|
||||||
|
|
||||||
await this.closePlugins();
|
await this.closePlugins();
|
||||||
|
|
||||||
this.rpc.wallet = null;
|
this.rpc.wallet = null;
|
||||||
|
|
||||||
await this.wdb.close();
|
await this.wdb.close();
|
||||||
// await this.client.close();
|
await this.handleClose();
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@ -9,24 +9,24 @@
|
|||||||
|
|
||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
const EventEmitter = require('events');
|
||||||
const BDB = require('bdb');
|
const BDB = require('bdb');
|
||||||
const AsyncObject = require('../utils/asyncobject');
|
const Logger = require('blgr');
|
||||||
const Lock = require('../utils/lock');
|
|
||||||
const MappedLock = require('../utils/mappedlock');
|
|
||||||
const encoding = require('bbuf/lib/encoding');
|
const encoding = require('bbuf/lib/encoding');
|
||||||
const ccmp = require('bcrypto/lib/ccmp');
|
const ccmp = require('bcrypto/lib/ccmp');
|
||||||
const aes = require('bcrypto/lib/aes');
|
const aes = require('bcrypto/lib/aes');
|
||||||
|
const BloomFilter = require('bfilter/lib/bloom');
|
||||||
|
const StaticWriter = require('bbuf/lib/staticwriter');
|
||||||
|
const Lock = require('../utils/lock');
|
||||||
|
const MappedLock = require('../utils/mappedlock');
|
||||||
const Network = require('../protocol/network');
|
const Network = require('../protocol/network');
|
||||||
const Path = require('./path');
|
const Path = require('./path');
|
||||||
const common = require('./common');
|
const common = require('./common');
|
||||||
const Wallet = require('./wallet');
|
const Wallet = require('./wallet');
|
||||||
const Account = require('./account');
|
const Account = require('./account');
|
||||||
const BloomFilter = require('bfilter/lib/bloom');
|
|
||||||
const Logger = require('blgr');
|
|
||||||
const Outpoint = require('../primitives/outpoint');
|
const Outpoint = require('../primitives/outpoint');
|
||||||
const layouts = require('./layout');
|
const layouts = require('./layout');
|
||||||
const records = require('./records');
|
const records = require('./records');
|
||||||
const StaticWriter = require('bbuf/lib/staticwriter');
|
|
||||||
const NullClient = require('./nullclient');
|
const NullClient = require('./nullclient');
|
||||||
const layout = layouts.walletdb;
|
const layout = layouts.walletdb;
|
||||||
const ChainState = records.ChainState;
|
const ChainState = records.ChainState;
|
||||||
@ -46,7 +46,7 @@ function WalletDB(options) {
|
|||||||
if (!(this instanceof WalletDB))
|
if (!(this instanceof WalletDB))
|
||||||
return new WalletDB(options);
|
return new WalletDB(options);
|
||||||
|
|
||||||
AsyncObject.call(this);
|
EventEmitter.call(this);
|
||||||
|
|
||||||
this.options = new WalletOptions(options);
|
this.options = new WalletOptions(options);
|
||||||
|
|
||||||
@ -76,10 +76,10 @@ function WalletDB(options) {
|
|||||||
// Address and outpoint filter.
|
// Address and outpoint filter.
|
||||||
this.filter = new BloomFilter();
|
this.filter = new BloomFilter();
|
||||||
|
|
||||||
this._init();
|
this.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
Object.setPrototypeOf(WalletDB.prototype, AsyncObject.prototype);
|
Object.setPrototypeOf(WalletDB.prototype, EventEmitter.prototype);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Database layout.
|
* Database layout.
|
||||||
@ -93,7 +93,7 @@ WalletDB.layout = layout;
|
|||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
|
|
||||||
WalletDB.prototype._init = function _init() {
|
WalletDB.prototype.init = function init() {
|
||||||
let items = 3000000;
|
let items = 3000000;
|
||||||
let flag = -1;
|
let flag = -1;
|
||||||
|
|
||||||
@ -108,7 +108,7 @@ WalletDB.prototype._init = function _init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.filter = BloomFilter.fromRate(items, 0.001, flag);
|
this.filter = BloomFilter.fromRate(items, 0.001, flag);
|
||||||
this.bind();
|
this._bind();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -116,7 +116,7 @@ WalletDB.prototype._init = function _init() {
|
|||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
|
|
||||||
WalletDB.prototype.bind = function bind() {
|
WalletDB.prototype._bind = function _bind() {
|
||||||
this.client.on('error', (err) => {
|
this.client.on('error', (err) => {
|
||||||
this.emit('error', err);
|
this.emit('error', err);
|
||||||
});
|
});
|
||||||
@ -172,11 +172,10 @@ WalletDB.prototype.bind = function bind() {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Open the walletdb, wait for the database to load.
|
* Open the walletdb, wait for the database to load.
|
||||||
* @alias WalletDB#open
|
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
WalletDB.prototype._open = async function _open() {
|
WalletDB.prototype.open = async function open() {
|
||||||
await this.db.open();
|
await this.db.open();
|
||||||
await this.db.checkVersion('V', 7);
|
await this.db.checkVersion('V', 7);
|
||||||
|
|
||||||
@ -209,11 +208,10 @@ WalletDB.prototype._open = async function _open() {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Close the walletdb, wait for the database to close.
|
* Close the walletdb, wait for the database to close.
|
||||||
* @alias WalletDB#close
|
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
WalletDB.prototype._close = async function _close() {
|
WalletDB.prototype.close = async function close() {
|
||||||
await this.disconnect();
|
await this.disconnect();
|
||||||
|
|
||||||
for (const wallet of this.wallets.values()) {
|
for (const wallet of this.wallets.values()) {
|
||||||
|
|||||||
@ -64,6 +64,8 @@ describe('Mempool', function() {
|
|||||||
this.timeout(5000);
|
this.timeout(5000);
|
||||||
|
|
||||||
it('should open mempool', async () => {
|
it('should open mempool', async () => {
|
||||||
|
await workers.open();
|
||||||
|
await chain.open();
|
||||||
await mempool.open();
|
await mempool.open();
|
||||||
chain.state.flags |= Script.flags.VERIFY_WITNESS;
|
chain.state.flags |= Script.flags.VERIFY_WITNESS;
|
||||||
});
|
});
|
||||||
@ -349,5 +351,7 @@ describe('Mempool', function() {
|
|||||||
|
|
||||||
it('should destroy mempool', async () => {
|
it('should destroy mempool', async () => {
|
||||||
await mempool.close();
|
await mempool.close();
|
||||||
|
await chain.close();
|
||||||
|
await workers.close();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user