more node improvements.

This commit is contained in:
Christopher Jeffrey 2016-03-01 03:39:09 -08:00
parent 00b8f8950b
commit 45292df44d
8 changed files with 126 additions and 125 deletions

View File

@ -22,11 +22,6 @@ function BlockDB(node, options) {
if (!(this instanceof BlockDB)) if (!(this instanceof BlockDB))
return new BlockDB(node, options); return new BlockDB(node, options);
if (!(node instanceof bcoin.node)) {
options = node;
node = null;
}
// Some lazy loading // Some lazy loading
levelup = require('levelup'); levelup = require('levelup');
@ -45,7 +40,7 @@ function BlockDB(node, options) {
this.options = options; this.options = options;
this.node = node; this.node = node;
this.data = new BlockData(options); this.data = new BlockData(node, this, options);
this.cache = { this.cache = {
unspent: new bcoin.lru(32 * 1024 * 1024), unspent: new bcoin.lru(32 * 1024 * 1024),
@ -1039,13 +1034,15 @@ BlockDB.prototype._getEntry = function _getEntry(height, callback) {
* BlockData * BlockData
*/ */
function BlockData(options) { function BlockData(node, blockdb, options) {
if (!(this instanceof BlockData)) if (!(this instanceof BlockData))
return new BlockData(options); return new BlockData(node, blockdb, options);
if (!options) if (!options)
options = {}; options = {};
this.node = node;
this.blockdb = blockdb;
this.options = options; this.options = options;
this.file = options.blockFile; this.file = options.blockFile;

View File

@ -32,12 +32,12 @@ function Chain(node, options) {
if (this.options.debug) if (this.options.debug)
bcoin.debug = this.options.debug; bcoin.debug = this.options.debug;
this.db = new bcoin.chaindb(this); this.node = node;
this.request = new utils.RequestCache(); this.request = new utils.RequestCache();
this.loading = false; this.loading = false;
this.node = node;
this.mempool = node.mempool; this.mempool = node.mempool;
this.blockdb = node.blockdb; this.blockdb = node.blockdb;
this.db = new bcoin.chaindb(node, this);
this.busy = false; this.busy = false;
this.jobs = []; this.jobs = [];
this.pending = []; this.pending = [];
@ -132,17 +132,6 @@ Chain.prototype._init = function _init() {
utils.debug('Warning: %d (%dmb) orphans cleared!', count, utils.mb(size)); utils.debug('Warning: %d (%dmb) orphans cleared!', count, utils.mb(size));
}); });
// Update the mempool.
this.on('add block', function(block) {
if (self.mempool)
self.mempool.addBlock(block);
});
this.on('remove block', function(block) {
if (self.mempool)
self.mempool.removeBlock(block);
});
this.loading = true; this.loading = true;
utils.debug('Chain is loading.'); utils.debug('Chain is loading.');

View File

@ -20,9 +20,9 @@ var BLOCK_SIZE = bcoin.chainblock.BLOCK_SIZE;
* ChainDB * ChainDB
*/ */
function ChainDB(chain, options) { function ChainDB(node, chain, options) {
if (!(this instanceof ChainDB)) if (!(this instanceof ChainDB))
return new ChainDB(chain, options); return new ChainDB(node, chain, options);
if (!options) if (!options)
options = {}; options = {};
@ -30,6 +30,8 @@ function ChainDB(chain, options) {
EventEmitter.call(this); EventEmitter.call(this);
this.options = options; this.options = options;
this.node = node;
this.network = node.network;
this.chain = chain; this.chain = chain;
this.file = options.file; this.file = options.file;

View File

@ -60,7 +60,10 @@ HTTPServer.prototype._init = function _init() {
}); });
this.get('/', function(req, res, next, send) { this.get('/', function(req, res, next, send) {
send(200, { version: require('../../package.json').version }); send(200, {
version: require('../../package.json').version,
network: self.node.network.type
});
}); });
// UTXO by address // UTXO by address

View File

@ -28,17 +28,6 @@ function Fullnode(options) {
bcoin.node.call(this, options); bcoin.node.call(this, options);
this.options.http = {};
if (!this.options.wallet)
this.options.wallet = {};
if (!this.options.wallet.id)
this.options.wallet.id = 'primary';
if (!this.options.wallet.passphrase)
this.options.wallet.passphrase = 'node';
this.loading = false; this.loading = false;
Fullnode.global = this; Fullnode.global = this;
@ -50,35 +39,52 @@ utils.inherits(Fullnode, bcoin.node);
Fullnode.prototype._init = function _init() { Fullnode.prototype._init = function _init() {
var self = this; var self = this;
var pending = 3;
this.loading = true; this.loading = true;
// BlockDB and Mempool need to be instantiated // BlockDB technically needs access to the
// first because the chain needs access to them. // chain, but that's only once it's being
// used for tx retrieval.
this.blockdb = new bcoin.blockdb(this, { this.blockdb = new bcoin.blockdb(this, {
cache: false cache: false
}); });
this.mempool = new bcoin.mempool(this); // Mempool needs access to blockdb.
this.mempool = new bcoin.mempool(this, {
rbf: false
});
// Chain is instantiated next. The pool needs it. // Chain needs access to blockdb.
this.chain = new bcoin.chain(this, { this.chain = new bcoin.chain(this, {
preload: false preload: false
}); });
// Pool needs access to the chain.
this.pool = new bcoin.pool(this, { this.pool = new bcoin.pool(this, {
witness: this.network.type === 'segnet', witness: this.network.type === 'segnet',
spv: false spv: false
}); });
this.miner = new bcoin.miner(this, this.options.miner); // Miner needs access to the mempool.
this.walletdb = new bcoin.walletdb(this, this.options.walletdb); this.miner = new bcoin.miner(this, {
address: this.options.payoutAddress,
coinbaseFlags: this.options.coinbaseFlags
});
if (this.options.http && bcoin.http) { // WalletDB needs access to the network type.
this.http = new bcoin.http(this, this.options.http); this.walletdb = new bcoin.walletdb(this, {
this.http.listen(this.options.http.port || 8080); type: this.options.walletdb
} });
// HTTP needs access to the mempool
// and blockdb.
this.http = new bcoin.http(this, {
key: this.options.httpKey,
cert: this.options.httpCert
});
// Bind to errors
this.mempool.on('error', function(err) { this.mempool.on('error', function(err) {
self.emit('error', err); self.emit('error', err);
}); });
@ -87,15 +93,23 @@ Fullnode.prototype._init = function _init() {
self.emit('error', err); self.emit('error', err);
}); });
this.chain.on('error', function(err) {
self.emit('error', err);
});
// Emit events for any TX we see that's
// is relevant to one of our wallets.
this.on('tx', function(tx) { this.on('tx', function(tx) {
self.walletdb.ownTX(tx, function(err, input, output) { self.walletdb.ownTX(tx, function(err, input, output) {
if (err) if (err)
return self.emit('error', err); return self.emit('error', err);
self.emit('own tx', tx, input, output); if (input || output)
self.emit('wallet tx', tx, input || [], output || []);
}); });
}); });
// Emit events for valid blocks and TXs.
this.chain.on('block', function(block) { this.chain.on('block', function(block) {
self.emit('block', block); self.emit('block', block);
block.txs.forEach(function(tx) { block.txs.forEach(function(tx) {
@ -107,7 +121,17 @@ Fullnode.prototype._init = function _init() {
self.emit('tx', tx); self.emit('tx', tx);
}); });
// Handle forks // Update the mempool.
this.chain.on('add block', function(block) {
self.mempool.addBlock(block);
});
this.chain.on('remove block', function(block) {
self.mempool.removeBlock(block);
});
// Handle forks by unconfirming txs
// in our wallets' tx pools.
this.chain.on('remove entry', function(entry) { this.chain.on('remove entry', function(entry) {
self.wallets.forEach(function(wallet) { self.wallets.forEach(function(wallet) {
wallet.tx.getAll().forEach(function(tx) { wallet.tx.getAll().forEach(function(tx) {
@ -117,16 +141,39 @@ Fullnode.prototype._init = function _init() {
}); });
}); });
this.createWallet(this.options.wallet, function(err, wallet) { function load() {
if (!--pending) {
self.loading = false;
self.emit('load');
self.pool.startSync();
utils.debug('Node is loaded and syncing.');
}
}
// Create or load the primary wallet.
this.createWallet({ id: 'primary', passphrase: 'node' }, function(err, wallet) {
if (err) if (err)
throw err; throw err;
self.miner.address = wallet.getAddress(); // Set the miner payout address if the
// programmer didn't pass one in.
if (!self.miner.address)
self.miner.address = wallet.getAddress();
self.pool.startSync(); wallet.on('load', function() {
load();
});
});
self.loading = false; this.chain.once('load', function() {
self.emit('load'); load();
});
this.http.listen(this.options.httpPort || 8080, '0.0.0.0', function(err) {
if (err)
throw err;
load();
}); });
}; };

View File

@ -28,9 +28,12 @@ function Node(options) {
this.options = options; this.options = options;
if (this.options.debug) if (this.options.debug != null)
bcoin.debug = this.options.debug; bcoin.debug = this.options.debug;
if (this.options.debugFile != null)
bcoin.debugFile = this.options.debugFile;
if (this.options.network) if (this.options.network)
network.set(this.options.network); network.set(this.options.network);
@ -40,6 +43,7 @@ function Node(options) {
this.pool = null; this.pool = null;
this.chain = null; this.chain = null;
this.miner = null; this.miner = null;
this.profiler = null;
this.wallets = []; this.wallets = [];
Node.global = this; Node.global = this;

View File

@ -30,12 +30,6 @@ function Pool(node, options) {
this.options = options; this.options = options;
if (options.debug)
bcoin.debug = this.options.debug;
if (options.network)
network.set(options.network);
options.spv = options.spv !== false; options.spv = options.spv !== false;
if (options.type === 'spv') if (options.type === 'spv')
@ -48,6 +42,7 @@ function Pool(node, options) {
? (!options.spv ? true : false) ? (!options.spv ? true : false)
: options.relay; : options.relay;
this.network = node.network;
this.originalSeeds = (options.seeds || network.seeds).map(utils.parseHost); this.originalSeeds = (options.seeds || network.seeds).map(utils.parseHost);
this.setSeeds([]); this.setSeeds([]);
@ -152,6 +147,13 @@ function Pool(node, options) {
this.loading = true; this.loading = true;
if (!this.chain.loading) {
this.loading = false;
this.emit('load');
this._init();
return;
}
this.chain.once('load', function() { this.chain.once('load', function() {
self.loading = false; self.loading = false;
self.emit('load'); self.emit('load');
@ -1222,6 +1224,13 @@ Pool.prototype.addWallet = function addWallet(wallet, callback) {
if (this.loading) if (this.loading)
return this.once('load', this.addWallet.bind(this, wallet, callback)); return this.once('load', this.addWallet.bind(this, wallet, callback));
if (!this.options.spv) {
wallet.getPending().forEach(function(tx) {
self.sendTX(tx);
});
return utils.nextTick(callback);
}
if (this.wallets.indexOf(wallet) !== -1) if (this.wallets.indexOf(wallet) !== -1)
return false; return false;
@ -1238,9 +1247,6 @@ Pool.prototype.addWallet = function addWallet(wallet, callback) {
self.sendTX(tx); self.sendTX(tx);
}); });
if (!self.options.spv)
return callback();
if (self._pendingSearch) if (self._pendingSearch)
return callback(); return callback();
@ -1259,82 +1265,42 @@ Pool.prototype.addWallet = function addWallet(wallet, callback) {
}; };
Pool.prototype.removeWallet = function removeWallet(wallet) { Pool.prototype.removeWallet = function removeWallet(wallet) {
var i = this.wallets.indexOf(wallet); var i;
if (!this.options.spv)
return;
i = this.wallets.indexOf(wallet);
assert(!this.loading); assert(!this.loading);
if (i == -1) if (i == -1)
return; return;
this.wallets.splice(i, 1); this.wallets.splice(i, 1);
this.unwatchWallet(wallet); this.unwatchWallet(wallet);
}; };
Pool.prototype.watchAddress = function watchAddress(address) { Pool.prototype.watchAddress = function watchAddress(address) {
if (address.script) { address = bcoin.address.parse(address);
// For the redeem script hash in outputs: this.watch(address.hash);
this.watch(address.getScriptHash160());
// For the redeem script in inputs:
this.watch(address.getScript());
}
if (address.program) {
// For programs inside P2SH
this.watch(address.getProgramHash());
// For witness scripthash
if (address.script)
this.watch(address.getScriptHash256());
}
// For the pubkey hash in outputs:
this.watch(address.getKeyHash());
// For the pubkey in inputs:
this.watch(address.getPublicKey());
}; };
Pool.prototype.unwatchAddress = function unwatchAddress(address) { Pool.prototype.unwatchAddress = function unwatchAddress(address) {
if (addres.script) { address = bcoin.address.parse(address);
// For the redeem script hash in p2sh outputs: this.unwatch(address.hash);
this.unwatch(address.getScriptHash160());
// For the redeem script in p2sh inputs:
this.unwatch(address.getScript());
}
if (address.program) {
// For programs inside P2SH
this.unwatch(address.getProgramHash());
// For witness scripthash
if (address.script)
this.unwatch(address.getScriptHash256());
}
// For the pubkey hash in p2pk/multisig outputs:
this.unwatch(address.getKeyHash());
// For the pubkey in p2pkh inputs:
this.unwatch(address.getPublicKey());
}; };
Pool.prototype.watchWallet = function watchWallet(wallet) { Pool.prototype.watchWallet = function watchWallet(wallet) {
var self = this; Object.keys(wallet.addressMap).forEach(function(address) {
wallet.addresses.forEach(function(address) {
this.watchAddress(address); this.watchAddress(address);
}, this); }, this);
wallet.on('add address', wallet._poolOnAdd = function(address) {
self.watchAddress(address);
});
wallet.on('remove address', wallet._poolOnRemove = function(address) {
self.unwatchAddress(address);
});
}; };
Pool.prototype.unwatchWallet = function unwatchWallet(wallet) { Pool.prototype.unwatchWallet = function unwatchWallet(wallet) {
wallet.addresses.forEach(function(address) { Object.keys(wallet.addressMap).forEach(function(address) {
this.unwatchAddress(address); this.unwatchAddress(address);
}, this); }, this);
wallet.removeListener('add address', wallet._poolOnAdd);
wallet.removeListener('remove address', wallet._poolOnRemove);
delete wallet._poolOnAdd;
delete wallet._poolOnRemove;
}; };
Pool.prototype.searchWallet = function(ts, height, callback) { Pool.prototype.searchWallet = function(ts, height, callback) {

View File

@ -26,11 +26,6 @@ function WalletDB(node, options) {
if (WalletDB.global) if (WalletDB.global)
return WalletDB.global; return WalletDB.global;
if (!(node instanceof bcoin.node)) {
options = node;
node = null;
}
if (!options) if (!options)
options = {}; options = {};
@ -549,7 +544,7 @@ WalletDB.prototype.ownTX = function ownTX(tx, callback) {
return callback(err); return callback(err);
if (input || output) if (input || output)
return callback(null, input || [], output || []); return callback(null, input, output);
return callback(); return callback();
}); });
@ -560,6 +555,4 @@ WalletDB.prototype.ownTX = function ownTX(tx, callback) {
* Expose * Expose
*/ */
var self = this;
var self = this;
module.exports = WalletDB; module.exports = WalletDB;