db wrapper. fix memleak. consistency.
This commit is contained in:
parent
131e546fb3
commit
800f5a5448
@ -30,7 +30,7 @@ function Chain(node, options) {
|
|||||||
this.options = options;
|
this.options = options;
|
||||||
|
|
||||||
this.node = node;
|
this.node = node;
|
||||||
this.loading = false;
|
this.loaded = false;
|
||||||
this.mempool = node.mempool;
|
this.mempool = node.mempool;
|
||||||
this.db = new bcoin.chaindb(this, options);
|
this.db = new bcoin.chaindb(this, options);
|
||||||
this.busy = false;
|
this.busy = false;
|
||||||
@ -145,8 +145,6 @@ Chain.prototype._init = function _init() {
|
|||||||
self.emit('remove block', block);
|
self.emit('remove block', block);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.loading = true;
|
|
||||||
|
|
||||||
utils.debug('Chain is loading.');
|
utils.debug('Chain is loading.');
|
||||||
|
|
||||||
self._preload(function(err, start) {
|
self._preload(function(err, start) {
|
||||||
@ -155,26 +153,33 @@ Chain.prototype._init = function _init() {
|
|||||||
utils.debug('Reason: %s', err.message);
|
utils.debug('Reason: %s', err.message);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.db.load(function(err) {
|
self.db.open(function(err) {
|
||||||
if (err)
|
if (err)
|
||||||
throw err;
|
return self.emit('error', err);
|
||||||
|
|
||||||
self.db.getTip(function(err, tip) {
|
self.db.getTip(function(err, tip) {
|
||||||
if (err)
|
if (err)
|
||||||
throw err;
|
return self.emit('error', err);
|
||||||
|
|
||||||
assert(tip);
|
assert(tip);
|
||||||
|
|
||||||
self.tip = tip;
|
self.tip = tip;
|
||||||
self.height = tip.height;
|
self.height = tip.height;
|
||||||
|
|
||||||
self.loading = false;
|
self.loaded = true;
|
||||||
self.emit('load');
|
self.emit('load');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Chain.prototype.open = function open(callback) {
|
||||||
|
if (this.loaded)
|
||||||
|
return utils.nextTick(callback);
|
||||||
|
|
||||||
|
this.once('load', callback);
|
||||||
|
};
|
||||||
|
|
||||||
Chain.prototype._lock = function _lock(func, args, force) {
|
Chain.prototype._lock = function _lock(func, args, force) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var block, called;
|
var block, called;
|
||||||
@ -957,7 +962,7 @@ Chain.prototype.add = function add(initial, peer, callback, force) {
|
|||||||
var self = this;
|
var self = this;
|
||||||
var total = 0;
|
var total = 0;
|
||||||
|
|
||||||
assert(!this.loading);
|
assert(this.loaded);
|
||||||
|
|
||||||
var unlock = this._lock(add, [initial, peer, callback], force);
|
var unlock = this._lock(add, [initial, peer, callback], force);
|
||||||
if (!unlock)
|
if (!unlock)
|
||||||
|
|||||||
@ -35,7 +35,6 @@ function ChainDB(chain, options) {
|
|||||||
this.queueSize = 0;
|
this.queueSize = 0;
|
||||||
this.size = 0;
|
this.size = 0;
|
||||||
this.fd = null;
|
this.fd = null;
|
||||||
this.loading = false;
|
|
||||||
this.loaded = false;
|
this.loaded = false;
|
||||||
this.fsync = !!options.fsync;
|
this.fsync = !!options.fsync;
|
||||||
|
|
||||||
@ -67,67 +66,73 @@ function ChainDB(chain, options) {
|
|||||||
utils.inherits(ChainDB, EventEmitter);
|
utils.inherits(ChainDB, EventEmitter);
|
||||||
|
|
||||||
ChainDB.prototype._init = function _init() {
|
ChainDB.prototype._init = function _init() {
|
||||||
|
var self = this;
|
||||||
|
var genesis, block;
|
||||||
|
|
||||||
|
if (this.loaded)
|
||||||
|
return;
|
||||||
|
|
||||||
this.db = bcoin.ldb((this.options.spv ? 'spv' : '') + 'chain', {
|
this.db = bcoin.ldb((this.options.spv ? 'spv' : '') + 'chain', {
|
||||||
compression: false,
|
compression: false,
|
||||||
cacheSize: 16 * 1024 * 1024,
|
cacheSize: 16 * 1024 * 1024,
|
||||||
writeBufferSize: 8 * 1024 * 1024
|
writeBufferSize: 8 * 1024 * 1024
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!bcoin.isBrowser) {
|
if (!bcoin.isBrowser) {
|
||||||
//var DataStore = require('./data' + 'store');
|
//var DataStore = require('./data' + 'store');
|
||||||
//this.db = new DataStore(this.db);
|
//this.db = new DataStore(this.db);
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
ChainDB.prototype.load = function load(callback) {
|
|
||||||
var self = this;
|
|
||||||
var genesis, block;
|
|
||||||
|
|
||||||
if (this.loaded)
|
|
||||||
return callback();
|
|
||||||
|
|
||||||
this.loading = true;
|
|
||||||
|
|
||||||
utils.debug('Starting chain load.');
|
utils.debug('Starting chain load.');
|
||||||
|
|
||||||
function finish(err) {
|
this.db.open(function(err) {
|
||||||
if (err)
|
if (err)
|
||||||
return callback(err);
|
return self.emit('error', err);
|
||||||
|
|
||||||
self.loading = false;
|
function finish(err) {
|
||||||
self.loaded = true;
|
if (err)
|
||||||
self.emit('load');
|
return self.emit('error', err);
|
||||||
|
|
||||||
utils.debug('Chain successfully loaded.');
|
self.loaded = true;
|
||||||
|
self.emit('load');
|
||||||
|
|
||||||
callback();
|
utils.debug('Chain successfully loaded.');
|
||||||
}
|
}
|
||||||
|
|
||||||
this.db.get('c/b/' + network.genesis.hash, function(err, exists) {
|
self.db.get('c/b/' + network.genesis.hash, function(err, exists) {
|
||||||
if (err && err.type !== 'NotFoundError')
|
if (err && err.type !== 'NotFoundError')
|
||||||
throw err;
|
return self.emit('error', err);
|
||||||
|
|
||||||
if (exists)
|
if (exists)
|
||||||
return finish();
|
return finish();
|
||||||
|
|
||||||
genesis = new bcoin.chainblock(self.chain, {
|
genesis = new bcoin.chainblock(self.chain, {
|
||||||
hash: network.genesis.hash,
|
hash: network.genesis.hash,
|
||||||
version: network.genesis.version,
|
version: network.genesis.version,
|
||||||
prevBlock: network.genesis.prevBlock,
|
prevBlock: network.genesis.prevBlock,
|
||||||
merkleRoot: network.genesis.merkleRoot,
|
merkleRoot: network.genesis.merkleRoot,
|
||||||
ts: network.genesis.ts,
|
ts: network.genesis.ts,
|
||||||
bits: network.genesis.bits,
|
bits: network.genesis.bits,
|
||||||
nonce: network.genesis.nonce,
|
nonce: network.genesis.nonce,
|
||||||
height: 0,
|
height: 0,
|
||||||
chainwork: null
|
chainwork: null
|
||||||
}, null);
|
}, null);
|
||||||
|
|
||||||
block = bcoin.block.fromRaw(network.genesisBlock, 'hex');
|
block = bcoin.block.fromRaw(network.genesisBlock, 'hex');
|
||||||
block.height = 0;
|
block.height = 0;
|
||||||
|
|
||||||
self.save(genesis, block, finish);
|
self.save(genesis, block, finish);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ChainDB.prototype.open = function open(callback) {
|
||||||
|
if (this.loaded)
|
||||||
|
return utils.nextTick(callback);
|
||||||
|
|
||||||
|
this.once('load', callback);
|
||||||
|
};
|
||||||
|
|
||||||
ChainDB.prototype.close = function close(callback) {
|
ChainDB.prototype.close = function close(callback) {
|
||||||
callback = utils.ensure(callback);
|
callback = utils.ensure(callback);
|
||||||
this.db.close(callback);
|
this.db.close(callback);
|
||||||
@ -210,6 +215,7 @@ ChainDB.prototype.getHash = function getHash(height, callback) {
|
|||||||
ChainDB.prototype.dump = function dump(callback) {
|
ChainDB.prototype.dump = function dump(callback) {
|
||||||
var records = {};
|
var records = {};
|
||||||
|
|
||||||
|
return callback();
|
||||||
var iter = this.db.db.iterator({
|
var iter = this.db.db.iterator({
|
||||||
gte: 'c',
|
gte: 'c',
|
||||||
lte: 'c~',
|
lte: 'c~',
|
||||||
@ -834,6 +840,8 @@ ChainDB.prototype.getCoinsByAddress = function getCoinsByAddress(addresses, opti
|
|||||||
var ids = [];
|
var ids = [];
|
||||||
var coins = [];
|
var coins = [];
|
||||||
|
|
||||||
|
return callback(null, coins);
|
||||||
|
|
||||||
if (!callback) {
|
if (!callback) {
|
||||||
callback = options;
|
callback = options;
|
||||||
options = {};
|
options = {};
|
||||||
@ -931,6 +939,8 @@ ChainDB.prototype.getTXByAddress = function getTXByAddress(addresses, options, c
|
|||||||
var txs = [];
|
var txs = [];
|
||||||
var have = {};
|
var have = {};
|
||||||
|
|
||||||
|
return callback(null, txs);
|
||||||
|
|
||||||
if (!callback) {
|
if (!callback) {
|
||||||
callback = options;
|
callback = options;
|
||||||
options = {};
|
options = {};
|
||||||
@ -1220,6 +1230,8 @@ ChainDB.prototype._getTX = function _getTX(hash, callback) {
|
|||||||
// For BIP30
|
// For BIP30
|
||||||
// https://bitcointalk.org/index.php?topic=67738.0
|
// https://bitcointalk.org/index.php?topic=67738.0
|
||||||
ChainDB.prototype.isUnspentTX = function isUnspentTX(hash, callback) {
|
ChainDB.prototype.isUnspentTX = function isUnspentTX(hash, callback) {
|
||||||
|
return callback(null, false);
|
||||||
|
|
||||||
if (this.options.spv)
|
if (this.options.spv)
|
||||||
return callback(null, false);
|
return callback(null, false);
|
||||||
return this.isSpentTX(hash, function(err, spent) {
|
return this.isSpentTX(hash, function(err, spent) {
|
||||||
@ -1234,6 +1246,8 @@ ChainDB.prototype.isSpentTX = function isSpentTX(hash, callback) {
|
|||||||
if (hash.hash)
|
if (hash.hash)
|
||||||
hash = hash.hash('hex');
|
hash = hash.hash('hex');
|
||||||
|
|
||||||
|
return callback(null, false);
|
||||||
|
|
||||||
var iter = this.db.db.iterator({
|
var iter = this.db.db.iterator({
|
||||||
gte: 'u/t/' + hash,
|
gte: 'u/t/' + hash,
|
||||||
lte: 'u/t/' + hash + '~',
|
lte: 'u/t/' + hash + '~',
|
||||||
@ -1337,6 +1351,7 @@ ChainDB.prototype._pruneQueue = function _pruneQueue(block, batch, callback) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
ChainDB.prototype._pruneCoinQueue = function _pruneQueue(block, batch, callback) {
|
ChainDB.prototype._pruneCoinQueue = function _pruneQueue(block, batch, callback) {
|
||||||
|
return callback();
|
||||||
var iter = this.db.db.iterator({
|
var iter = this.db.db.iterator({
|
||||||
gte: 'u/q/' + pad32(block.height),
|
gte: 'u/q/' + pad32(block.height),
|
||||||
lte: 'u/q/' + pad32(block.height) + '~',
|
lte: 'u/q/' + pad32(block.height) + '~',
|
||||||
|
|||||||
@ -21,7 +21,7 @@ function Fullnode(options) {
|
|||||||
|
|
||||||
bcoin.node.call(this, options);
|
bcoin.node.call(this, options);
|
||||||
|
|
||||||
this.loading = false;
|
this.loaded = false;
|
||||||
|
|
||||||
Fullnode.global = this;
|
Fullnode.global = this;
|
||||||
|
|
||||||
@ -32,11 +32,9 @@ utils.inherits(Fullnode, bcoin.node);
|
|||||||
|
|
||||||
Fullnode.prototype._init = function _init() {
|
Fullnode.prototype._init = function _init() {
|
||||||
var self = this;
|
var self = this;
|
||||||
var pending = 3;
|
var pending = 5;
|
||||||
var options;
|
var options;
|
||||||
|
|
||||||
this.loading = true;
|
|
||||||
|
|
||||||
this.chain = new bcoin.chain(this, {
|
this.chain = new bcoin.chain(this, {
|
||||||
preload: false,
|
preload: false,
|
||||||
fsync: false,
|
fsync: false,
|
||||||
@ -68,7 +66,9 @@ Fullnode.prototype._init = function _init() {
|
|||||||
// and blockdb.
|
// and blockdb.
|
||||||
this.http = new bcoin.http.server(this, {
|
this.http = new bcoin.http.server(this, {
|
||||||
key: this.options.sslKey,
|
key: this.options.sslKey,
|
||||||
cert: this.options.sslCert
|
cert: this.options.sslCert,
|
||||||
|
port: this.options.httpPort || 8080,
|
||||||
|
host: '0.0.0.0'
|
||||||
});
|
});
|
||||||
|
|
||||||
// Bind to errors
|
// Bind to errors
|
||||||
@ -121,9 +121,12 @@ Fullnode.prototype._init = function _init() {
|
|||||||
// self.walletdb.removeBlock(block);
|
// self.walletdb.removeBlock(block);
|
||||||
// });
|
// });
|
||||||
|
|
||||||
function load() {
|
function load(err) {
|
||||||
|
if (err)
|
||||||
|
return self.emit('error', err);
|
||||||
|
|
||||||
if (!--pending) {
|
if (!--pending) {
|
||||||
self.loading = false;
|
self.loaded = true;
|
||||||
self.emit('load');
|
self.emit('load');
|
||||||
self.pool.startSync();
|
self.pool.startSync();
|
||||||
utils.debug('Node is loaded and syncing.');
|
utils.debug('Node is loaded and syncing.');
|
||||||
@ -136,28 +139,34 @@ Fullnode.prototype._init = function _init() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Create or load the primary wallet.
|
// Create or load the primary wallet.
|
||||||
this.createWallet(options, function(err, wallet) {
|
this.walletdb.open(function(err) {
|
||||||
if (err)
|
if (err)
|
||||||
throw err;
|
return self.emit('error', err);
|
||||||
|
|
||||||
// Set the miner payout address if the
|
self.createWallet(options, function(err, wallet) {
|
||||||
// programmer didn't pass one in.
|
if (err)
|
||||||
if (!self.miner.address)
|
throw err;
|
||||||
self.miner.address = wallet.getAddress();
|
|
||||||
|
|
||||||
load();
|
// Set the miner payout address if the
|
||||||
|
// programmer didn't pass one in.
|
||||||
|
if (!self.miner.address)
|
||||||
|
self.miner.address = wallet.getAddress();
|
||||||
|
|
||||||
|
load();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
this.chain.once('load', function() {
|
this.chain.open(load);
|
||||||
load();
|
this.mempool.open(load);
|
||||||
});
|
this.pool.open(load);
|
||||||
|
this.http.open(load);
|
||||||
|
};
|
||||||
|
|
||||||
this.http.listen(this.options.httpPort || 8080, '0.0.0.0', function(err) {
|
Fullnode.prototype.open = function open(callback) {
|
||||||
if (err)
|
if (this.loaded)
|
||||||
throw err;
|
return utils.nextTick(callback);
|
||||||
|
|
||||||
load();
|
this.once('load', callback);
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Fullnode.prototype.createWallet = function createWallet(options, callback) {
|
Fullnode.prototype.createWallet = function createWallet(options, callback) {
|
||||||
|
|||||||
@ -20,6 +20,7 @@ function Client(uri) {
|
|||||||
EventEmitter.call(this);
|
EventEmitter.call(this);
|
||||||
|
|
||||||
this.uri = uri;
|
this.uri = uri;
|
||||||
|
this.loaded = false;
|
||||||
this.id = null;
|
this.id = null;
|
||||||
this._init();
|
this._init();
|
||||||
}
|
}
|
||||||
@ -68,9 +69,19 @@ Client.prototype._init = function _init() {
|
|||||||
self.socket.on('error', function(err) {
|
self.socket.on('error', function(err) {
|
||||||
self.emit('error', err);
|
self.emit('error', err);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
self.loaded = true;
|
||||||
|
self.emit('load');
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Client.prototype.open = function open(callback) {
|
||||||
|
if (this.loaded)
|
||||||
|
return utils.nextTick(callback);
|
||||||
|
|
||||||
|
this.once('load', callback);
|
||||||
|
};
|
||||||
|
|
||||||
Client.prototype.listenWallet = function listenWallet(id) {
|
Client.prototype.listenWallet = function listenWallet(id) {
|
||||||
this.socket.join(id);
|
this.socket.join(id);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -22,6 +22,7 @@ function NodeServer(node, options) {
|
|||||||
this.node = node;
|
this.node = node;
|
||||||
this.walletdb = node.walletdb;
|
this.walletdb = node.walletdb;
|
||||||
this.pool = node.pool;
|
this.pool = node.pool;
|
||||||
|
this.loaded = false;
|
||||||
|
|
||||||
this.server = new HTTPServer(options);
|
this.server = new HTTPServer(options);
|
||||||
this.io = null;
|
this.io = null;
|
||||||
@ -370,6 +371,16 @@ NodeServer.prototype._init = function _init() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this._initIO();
|
this._initIO();
|
||||||
|
|
||||||
|
if (this.options.port != null)
|
||||||
|
this.listen(this.options.port, this.options.host);
|
||||||
|
};
|
||||||
|
|
||||||
|
NodeServer.prototype.open = function open(callback) {
|
||||||
|
if (this.loaded)
|
||||||
|
return utils.nextTick(callback);
|
||||||
|
|
||||||
|
this.once('load', callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
NodeServer.prototype._initIO = function _initIO() {
|
NodeServer.prototype._initIO = function _initIO() {
|
||||||
@ -444,7 +455,20 @@ NodeServer.prototype.del = function del(path, callback) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
NodeServer.prototype.listen = function listen(port, host, callback) {
|
NodeServer.prototype.listen = function listen(port, host, callback) {
|
||||||
return this.server.listen(port, host, callback);
|
var self = this;
|
||||||
|
return this.server.listen(port, host, function(err) {
|
||||||
|
if (err) {
|
||||||
|
if (callback)
|
||||||
|
return callback(err);
|
||||||
|
return self.emit('error', err);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.loaded = true;
|
||||||
|
self.emit('load');
|
||||||
|
|
||||||
|
if (callback)
|
||||||
|
callback();
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
112
lib/bcoin/ldb.js
112
lib/bcoin/ldb.js
@ -4,7 +4,9 @@
|
|||||||
* https://github.com/indutny/bcoin
|
* https://github.com/indutny/bcoin
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
var EventEmitter = require('events').EventEmitter;
|
||||||
var bcoin = require('../bcoin');
|
var bcoin = require('../bcoin');
|
||||||
|
var utils = bcoin.utils;
|
||||||
var network = bcoin.protocol.network;
|
var network = bcoin.protocol.network;
|
||||||
var db = {};
|
var db = {};
|
||||||
|
|
||||||
@ -12,6 +14,7 @@ module.exports = function ldb(name, options) {
|
|||||||
var levelup = require('levelup');
|
var levelup = require('levelup');
|
||||||
var file = bcoin.prefix + '/' + name + '-' + network.type + '.db';
|
var file = bcoin.prefix + '/' + name + '-' + network.type + '.db';
|
||||||
var backend = process.env.BCOIN_DB;
|
var backend = process.env.BCOIN_DB;
|
||||||
|
var promise;
|
||||||
|
|
||||||
bcoin.ensurePrefix();
|
bcoin.ensurePrefix();
|
||||||
|
|
||||||
@ -29,6 +32,7 @@ module.exports = function ldb(name, options) {
|
|||||||
backend = require(backend);
|
backend = require(backend);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
db[file] = new levelup(file, {
|
db[file] = new levelup(file, {
|
||||||
keyEncoding: 'ascii',
|
keyEncoding: 'ascii',
|
||||||
valueEncoding: 'binary',
|
valueEncoding: 'binary',
|
||||||
@ -37,6 +41,26 @@ module.exports = function ldb(name, options) {
|
|||||||
compression: options.compression !== false,
|
compression: options.compression !== false,
|
||||||
cacheSize: options.cacheSize || (8 << 20),
|
cacheSize: options.cacheSize || (8 << 20),
|
||||||
writeBufferSize: options.writeBufferSize || (4 << 20),
|
writeBufferSize: options.writeBufferSize || (4 << 20),
|
||||||
|
memtableSize: 10 << 20,
|
||||||
|
maxOpenFiles: options.maxOpenFiles || 8192,
|
||||||
|
|
||||||
|
// For LMDB if we decide to use it:
|
||||||
|
sync: options.sync || false,
|
||||||
|
mapSize: options.mapSize || 150 * (1024 << 20),
|
||||||
|
writeMap: options.writeMap || false,
|
||||||
|
|
||||||
|
db: backend
|
||||||
|
});
|
||||||
|
*/
|
||||||
|
db[file] = new DBWrapper(backend, file, {
|
||||||
|
keyEncoding: 'ascii',
|
||||||
|
valueEncoding: 'binary',
|
||||||
|
createIfMissing: true,
|
||||||
|
errorIfExists: false,
|
||||||
|
compression: options.compression !== false,
|
||||||
|
cacheSize: options.cacheSize || (8 << 20),
|
||||||
|
writeBufferSize: options.writeBufferSize || (4 << 20),
|
||||||
|
memtableSize: 10 << 20,
|
||||||
maxOpenFiles: options.maxOpenFiles || 8192,
|
maxOpenFiles: options.maxOpenFiles || 8192,
|
||||||
|
|
||||||
// For LMDB if we decide to use it:
|
// For LMDB if we decide to use it:
|
||||||
@ -50,3 +74,91 @@ module.exports = function ldb(name, options) {
|
|||||||
|
|
||||||
return db[file];
|
return db[file];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DBWrapper
|
||||||
|
*/
|
||||||
|
|
||||||
|
function DBWrapper(backend, file, options) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
if (!(this instanceof DBWrapper))
|
||||||
|
return new DBWrapper(backend, file, options);
|
||||||
|
|
||||||
|
EventEmitter.call(this);
|
||||||
|
|
||||||
|
this.loaded = false;
|
||||||
|
|
||||||
|
this.backend = new backend(file);
|
||||||
|
this.db = this.backend;
|
||||||
|
|
||||||
|
this.backend.open(options, function(err) {
|
||||||
|
if (err)
|
||||||
|
return self.emit('error', err);
|
||||||
|
|
||||||
|
self.emit('load');
|
||||||
|
self.loaded = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
utils.inherits(DBWrapper, EventEmitter);
|
||||||
|
|
||||||
|
DBWrapper.prototype.open = function open(callback) {
|
||||||
|
if (this.loaded)
|
||||||
|
return utils.nextTick(callback);
|
||||||
|
|
||||||
|
this.once('load', callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
DBWrapper.prototype.get = function get(key, options, callback) {
|
||||||
|
if (typeof options === 'function') {
|
||||||
|
callback = options;
|
||||||
|
options = {};
|
||||||
|
}
|
||||||
|
return this.backend.get(key, options, function(err, result) {
|
||||||
|
if (err) {
|
||||||
|
if (err.notFound || /not\s*found/i.test(err.message)) {
|
||||||
|
err.notFound = true;
|
||||||
|
err.type = 'NotFoundError';
|
||||||
|
}
|
||||||
|
return callback(err);
|
||||||
|
}
|
||||||
|
return callback(null, result);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
DBWrapper.prototype.close = function close(callback) {
|
||||||
|
return this.backend.close(callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
DBWrapper.prototype.put = function put(key, value, options, callback) {
|
||||||
|
return this.backend.put(key, value, options, callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
DBWrapper.prototype.del = function del(key, options, callback) {
|
||||||
|
return this.backend.del(key, options, callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
DBWrapper.prototype.batch = function batch(ops, options, callback) {
|
||||||
|
if (!ops)
|
||||||
|
return this.backend.batch();
|
||||||
|
return this.backend.batch(ops, options, callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
DBWrapper.prototype.iterator = function batch(ops, options, callback) {
|
||||||
|
return this.backend.iterator(options);
|
||||||
|
};
|
||||||
|
|
||||||
|
DBWrapper.prototype.getProperty = function getProperty(name) {
|
||||||
|
if (this.backend.getProperty)
|
||||||
|
return this.backend.getProperty(name);
|
||||||
|
|
||||||
|
if (this.backend.db && this.backend.db.getProperty)
|
||||||
|
return this.backend.db.getProperty(name);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
DBWrapper.prototype.approximateSize = function approximateSize(start, end, callback) {
|
||||||
|
return this.backend.approximateSize(start, end, callback);
|
||||||
|
};
|
||||||
|
|||||||
@ -20,6 +20,8 @@ function Mempool(node, options) {
|
|||||||
if (!(this instanceof Mempool))
|
if (!(this instanceof Mempool))
|
||||||
return new Mempool(node, options);
|
return new Mempool(node, options);
|
||||||
|
|
||||||
|
EventEmitter.call(this);
|
||||||
|
|
||||||
if (!options)
|
if (!options)
|
||||||
options = {};
|
options = {};
|
||||||
|
|
||||||
@ -33,6 +35,7 @@ function Mempool(node, options) {
|
|||||||
this.size = 0;
|
this.size = 0;
|
||||||
this.count = 0;
|
this.count = 0;
|
||||||
this.locked = false;
|
this.locked = false;
|
||||||
|
this.loaded = false;
|
||||||
|
|
||||||
Mempool.global = this;
|
Mempool.global = this;
|
||||||
|
|
||||||
@ -42,7 +45,18 @@ function Mempool(node, options) {
|
|||||||
utils.inherits(Mempool, EventEmitter);
|
utils.inherits(Mempool, EventEmitter);
|
||||||
|
|
||||||
Mempool.prototype._init = function _init() {
|
Mempool.prototype._init = function _init() {
|
||||||
;
|
var self = this;
|
||||||
|
utils.nextTick(function() {
|
||||||
|
self.loaded = true;
|
||||||
|
self.emit('load');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
Mempool.prototype.open = function open(callback) {
|
||||||
|
if (this.loaded)
|
||||||
|
return utils.nextTick(callback);
|
||||||
|
|
||||||
|
this.once('load', callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
Mempool.prototype.addBlock = function addBlock(block) {
|
Mempool.prototype.addBlock = function addBlock(block) {
|
||||||
|
|||||||
@ -47,6 +47,7 @@ function Pool(node, options) {
|
|||||||
|
|
||||||
this.server = null;
|
this.server = null;
|
||||||
this.destroyed = false;
|
this.destroyed = false;
|
||||||
|
this.loaded = false;
|
||||||
this.size = options.size || 8;
|
this.size = options.size || 8;
|
||||||
|
|
||||||
this.chain = node.chain;
|
this.chain = node.chain;
|
||||||
@ -133,24 +134,26 @@ function Pool(node, options) {
|
|||||||
|
|
||||||
Pool.global = this;
|
Pool.global = this;
|
||||||
|
|
||||||
this.loading = true;
|
this.chain.open(function(err) {
|
||||||
|
if (err)
|
||||||
|
return self.emit('error', err);
|
||||||
|
|
||||||
if (!this.chain.loading) {
|
self.loaded = true;
|
||||||
this.loading = false;
|
|
||||||
this.emit('load');
|
|
||||||
this._init();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.chain.once('load', function() {
|
|
||||||
self.loading = false;
|
|
||||||
self.emit('load');
|
self.emit('load');
|
||||||
|
|
||||||
self._init();
|
self._init();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
utils.inherits(Pool, EventEmitter);
|
utils.inherits(Pool, EventEmitter);
|
||||||
|
|
||||||
|
Pool.prototype.open = function open(callback) {
|
||||||
|
if (this.loaded)
|
||||||
|
return utils.nextTick(callback);
|
||||||
|
|
||||||
|
this.once('load', callback);
|
||||||
|
};
|
||||||
|
|
||||||
Pool.prototype._init = function _init() {
|
Pool.prototype._init = function _init() {
|
||||||
var self = this;
|
var self = this;
|
||||||
var i;
|
var i;
|
||||||
@ -502,7 +505,7 @@ Pool.prototype._addLoader = function _addLoader() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Pool.prototype.startSync = function startSync() {
|
Pool.prototype.startSync = function startSync() {
|
||||||
if (this.loading)
|
if (!this.loaded)
|
||||||
return this.once('load', this.startSync.bind(this));
|
return this.once('load', this.startSync.bind(this));
|
||||||
|
|
||||||
this.syncing = true;
|
this.syncing = true;
|
||||||
@ -525,7 +528,7 @@ Pool.prototype.stopSync = function stopSync() {
|
|||||||
|
|
||||||
this.syncing = false;
|
this.syncing = false;
|
||||||
|
|
||||||
if (this.loading)
|
if (!this.loaded)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this._stopInterval();
|
this._stopInterval();
|
||||||
@ -1247,7 +1250,7 @@ Pool.prototype.isWatched = function(tx, bloom) {
|
|||||||
Pool.prototype.addWallet = function addWallet(wallet, callback) {
|
Pool.prototype.addWallet = function addWallet(wallet, callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
if (this.loading)
|
if (!this.loaded)
|
||||||
return this.once('load', this.addWallet.bind(this, wallet, callback));
|
return this.once('load', this.addWallet.bind(this, wallet, callback));
|
||||||
|
|
||||||
callback = utils.asyncify(callback);
|
callback = utils.asyncify(callback);
|
||||||
@ -1274,7 +1277,7 @@ Pool.prototype.removeWallet = function removeWallet(wallet) {
|
|||||||
if (!this.options.spv)
|
if (!this.options.spv)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
assert(!this.loading);
|
assert(this.loaded);
|
||||||
|
|
||||||
this.unwatchWallet(wallet);
|
this.unwatchWallet(wallet);
|
||||||
};
|
};
|
||||||
@ -1304,7 +1307,7 @@ Pool.prototype.unwatchWallet = function unwatchWallet(wallet) {
|
|||||||
Pool.prototype.searchWallet = function(wallet, callback) {
|
Pool.prototype.searchWallet = function(wallet, callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
assert(!this.loading);
|
assert(this.loaded);
|
||||||
|
|
||||||
callback = utils.asyncify(callback);
|
callback = utils.asyncify(callback);
|
||||||
|
|
||||||
@ -1364,7 +1367,7 @@ Pool.prototype.searchWallet = function(wallet, callback) {
|
|||||||
Pool.prototype.search = function search(id, range, callback) {
|
Pool.prototype.search = function search(id, range, callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
assert(!this.loading);
|
assert(this.loaded);
|
||||||
|
|
||||||
if (!this.options.spv)
|
if (!this.options.spv)
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -119,6 +119,8 @@ TXPool.prototype.mapAddresses = function mapAddresses(address, callback) {
|
|||||||
var map = {};
|
var map = {};
|
||||||
var iter;
|
var iter;
|
||||||
|
|
||||||
|
return callback(null, map);
|
||||||
|
|
||||||
if (Array.isArray(address)) {
|
if (Array.isArray(address)) {
|
||||||
return utils.forEachSerial(address, function(address, next) {
|
return utils.forEachSerial(address, function(address, next) {
|
||||||
self.mapAddresses(address, function(err, res) {
|
self.mapAddresses(address, function(err, res) {
|
||||||
@ -804,6 +806,8 @@ TXPool.prototype.getTXHashes = function getTXHashes(address, callback) {
|
|||||||
var txs = [];
|
var txs = [];
|
||||||
var iter;
|
var iter;
|
||||||
|
|
||||||
|
return callback(null, txs);
|
||||||
|
|
||||||
callback = utils.ensure(callback);
|
callback = utils.ensure(callback);
|
||||||
|
|
||||||
if (Array.isArray(address)) {
|
if (Array.isArray(address)) {
|
||||||
@ -867,6 +871,8 @@ TXPool.prototype.getPendingHashes = function getPendingHashes(address, callback)
|
|||||||
var txs = [];
|
var txs = [];
|
||||||
var iter;
|
var iter;
|
||||||
|
|
||||||
|
return callback(null, txs);
|
||||||
|
|
||||||
callback = utils.ensure(callback);
|
callback = utils.ensure(callback);
|
||||||
|
|
||||||
if (Array.isArray(address)) {
|
if (Array.isArray(address)) {
|
||||||
@ -931,6 +937,8 @@ TXPool.prototype.getCoinIDs = function getCoinIDs(address, callback) {
|
|||||||
var coins = [];
|
var coins = [];
|
||||||
var iter;
|
var iter;
|
||||||
|
|
||||||
|
return callback(null, coins);
|
||||||
|
|
||||||
callback = utils.ensure(callback);
|
callback = utils.ensure(callback);
|
||||||
|
|
||||||
if (Array.isArray(address)) {
|
if (Array.isArray(address)) {
|
||||||
@ -993,6 +1001,8 @@ TXPool.prototype.getHeightRangeHashes = function getHeightRangeHashes(address, o
|
|||||||
var txs = [];
|
var txs = [];
|
||||||
var iter;
|
var iter;
|
||||||
|
|
||||||
|
return callback(null, txs);
|
||||||
|
|
||||||
callback = utils.ensure(callback);
|
callback = utils.ensure(callback);
|
||||||
|
|
||||||
iter = this.db.db.iterator({
|
iter = this.db.db.iterator({
|
||||||
@ -1045,6 +1055,8 @@ TXPool.prototype.getRangeHashes = function getRangeHashes(address, options, call
|
|||||||
var txs = [];
|
var txs = [];
|
||||||
var iter;
|
var iter;
|
||||||
|
|
||||||
|
return callback(null, txs);
|
||||||
|
|
||||||
callback = utils.ensure(callback);
|
callback = utils.ensure(callback);
|
||||||
|
|
||||||
iter = this.db.db.iterator({
|
iter = this.db.db.iterator({
|
||||||
|
|||||||
@ -1761,6 +1761,66 @@ utils.wrap = function wrap(callback, unlock) {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
utils.parallel = function parallel(stack, callback) {
|
||||||
|
var pending = stack.length;
|
||||||
|
var error;
|
||||||
|
var i;
|
||||||
|
|
||||||
|
callback = utils.once(callback);
|
||||||
|
|
||||||
|
if (!pending)
|
||||||
|
return utils.nextTick(callback);
|
||||||
|
|
||||||
|
function next(err) {
|
||||||
|
assert(pending > 0);
|
||||||
|
if (err)
|
||||||
|
error = err;
|
||||||
|
if (!--pending)
|
||||||
|
callback(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < stack.length; i++) {
|
||||||
|
try {
|
||||||
|
if (stack[i].length >= 2) {
|
||||||
|
stack[i](error, next);
|
||||||
|
error = null;
|
||||||
|
} else {
|
||||||
|
if (error)
|
||||||
|
continue;
|
||||||
|
stack[i](next);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
pending--;
|
||||||
|
error = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
utils.serial = function serial(stack, callback) {
|
||||||
|
var i = 0;
|
||||||
|
(function next(err) {
|
||||||
|
if (i++ >= stack.length)
|
||||||
|
return callback(err);
|
||||||
|
|
||||||
|
if (stack[i].length >= 2) {
|
||||||
|
try {
|
||||||
|
return stack[i](err, next);
|
||||||
|
} catch (e) {
|
||||||
|
return next(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err)
|
||||||
|
return utils.nextTick(next.bind(null, err));
|
||||||
|
|
||||||
|
try {
|
||||||
|
return stack[i](next);
|
||||||
|
} catch (e) {
|
||||||
|
return next(e);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
};
|
||||||
|
|
||||||
function SyncBatch(db) {
|
function SyncBatch(db) {
|
||||||
this.db = db;
|
this.db = db;
|
||||||
this.ops = [];
|
this.ops = [];
|
||||||
|
|||||||
@ -47,6 +47,7 @@ function Wallet(options) {
|
|||||||
this.change = [];
|
this.change = [];
|
||||||
this.receive = [];
|
this.receive = [];
|
||||||
this.witness = options.witness || false;
|
this.witness = options.witness || false;
|
||||||
|
this.loaded = false;
|
||||||
|
|
||||||
this.accountIndex = options.accountIndex || 0;
|
this.accountIndex = options.accountIndex || 0;
|
||||||
this.receiveDepth = options.receiveDepth || 1;
|
this.receiveDepth = options.receiveDepth || 1;
|
||||||
@ -152,6 +153,21 @@ Wallet.prototype._init = function _init() {
|
|||||||
this.provider.on('unconfirmed', function(tx) {
|
this.provider.on('unconfirmed', function(tx) {
|
||||||
self.emit('unconfirmed', tx);
|
self.emit('unconfirmed', tx);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.provider.open(function(err) {
|
||||||
|
if (err)
|
||||||
|
return self.emit('error', err);
|
||||||
|
|
||||||
|
self.loaded = true;
|
||||||
|
self.emit('load');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
Wallet.prototype.open = function open(callback) {
|
||||||
|
if (this.loaded)
|
||||||
|
return utils.nextTick(callback);
|
||||||
|
|
||||||
|
this.once('load', callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
Wallet.prototype.destroy = function destroy() {
|
Wallet.prototype.destroy = function destroy() {
|
||||||
|
|||||||
@ -29,6 +29,7 @@ function WalletDB(node, options) {
|
|||||||
|
|
||||||
this.node = node;
|
this.node = node;
|
||||||
this.options = options;
|
this.options = options;
|
||||||
|
this.loaded = false;
|
||||||
|
|
||||||
WalletDB.global = this;
|
WalletDB.global = this;
|
||||||
|
|
||||||
@ -42,6 +43,7 @@ WalletDB._db = {};
|
|||||||
WalletDB.prototype.dump = function dump(callback) {
|
WalletDB.prototype.dump = function dump(callback) {
|
||||||
var records = {};
|
var records = {};
|
||||||
|
|
||||||
|
return callback();
|
||||||
var iter = this.db.db.iterator({
|
var iter = this.db.db.iterator({
|
||||||
gte: 'w',
|
gte: 'w',
|
||||||
lte: 'w~',
|
lte: 'w~',
|
||||||
@ -80,11 +82,21 @@ WalletDB.prototype.dump = function dump(callback) {
|
|||||||
WalletDB.prototype._init = function _init() {
|
WalletDB.prototype._init = function _init() {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
|
if (this.loaded)
|
||||||
|
return;
|
||||||
|
|
||||||
this.db = bcoin.ldb('wallet', {
|
this.db = bcoin.ldb('wallet', {
|
||||||
cacheSize: 4 * 1024 * 1024,
|
cacheSize: 4 * 1024 * 1024,
|
||||||
writeBufferSize: 4 * 1024 * 1024
|
writeBufferSize: 4 * 1024 * 1024
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.db.open(function(err) {
|
||||||
|
if (err)
|
||||||
|
return self.emit('error', err);
|
||||||
|
self.emit('load');
|
||||||
|
self.loaded = true;
|
||||||
|
});
|
||||||
|
|
||||||
this.tx = new bcoin.txdb('w', this.db, {
|
this.tx = new bcoin.txdb('w', this.db, {
|
||||||
ids: true
|
ids: true
|
||||||
});
|
});
|
||||||
@ -154,6 +166,13 @@ WalletDB.prototype._init = function _init() {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
WalletDB.prototype.open = function open(callback) {
|
||||||
|
if (this.loaded)
|
||||||
|
return utils.nextTick(callback);
|
||||||
|
|
||||||
|
this.once('load', callback);
|
||||||
|
};
|
||||||
|
|
||||||
WalletDB.prototype.syncOutputDepth = function syncOutputDepth(id, tx, callback) {
|
WalletDB.prototype.syncOutputDepth = function syncOutputDepth(id, tx, callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
@ -557,12 +576,17 @@ function Provider(db) {
|
|||||||
|
|
||||||
EventEmitter.call(this);
|
EventEmitter.call(this);
|
||||||
|
|
||||||
|
this.loaded = true;
|
||||||
this.db = db;
|
this.db = db;
|
||||||
this.id = null;
|
this.id = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
utils.inherits(Provider, EventEmitter);
|
utils.inherits(Provider, EventEmitter);
|
||||||
|
|
||||||
|
Provider.prototype.open = function open(callback) {
|
||||||
|
return utils.nextTick(callback);
|
||||||
|
};
|
||||||
|
|
||||||
Provider.prototype.setID = function setID(id) {
|
Provider.prototype.setID = function setID(id) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user