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

View File

@ -32,12 +32,12 @@ function Chain(node, options) {
if (this.options.debug)
bcoin.debug = this.options.debug;
this.db = new bcoin.chaindb(this);
this.node = node;
this.request = new utils.RequestCache();
this.loading = false;
this.node = node;
this.mempool = node.mempool;
this.blockdb = node.blockdb;
this.db = new bcoin.chaindb(node, this);
this.busy = false;
this.jobs = [];
this.pending = [];
@ -132,17 +132,6 @@ Chain.prototype._init = function _init() {
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;
utils.debug('Chain is loading.');

View File

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

View File

@ -60,7 +60,10 @@ HTTPServer.prototype._init = function _init() {
});
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

View File

@ -28,17 +28,6 @@ function Fullnode(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;
Fullnode.global = this;
@ -50,35 +39,52 @@ utils.inherits(Fullnode, bcoin.node);
Fullnode.prototype._init = function _init() {
var self = this;
var pending = 3;
this.loading = true;
// BlockDB and Mempool need to be instantiated
// first because the chain needs access to them.
// BlockDB technically needs access to the
// chain, but that's only once it's being
// used for tx retrieval.
this.blockdb = new bcoin.blockdb(this, {
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, {
preload: false
});
// Pool needs access to the chain.
this.pool = new bcoin.pool(this, {
witness: this.network.type === 'segnet',
spv: false
});
this.miner = new bcoin.miner(this, this.options.miner);
this.walletdb = new bcoin.walletdb(this, this.options.walletdb);
// Miner needs access to the mempool.
this.miner = new bcoin.miner(this, {
address: this.options.payoutAddress,
coinbaseFlags: this.options.coinbaseFlags
});
if (this.options.http && bcoin.http) {
this.http = new bcoin.http(this, this.options.http);
this.http.listen(this.options.http.port || 8080);
}
// WalletDB needs access to the network type.
this.walletdb = new bcoin.walletdb(this, {
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) {
self.emit('error', err);
});
@ -87,15 +93,23 @@ Fullnode.prototype._init = function _init() {
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) {
self.walletdb.ownTX(tx, function(err, input, output) {
if (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) {
self.emit('block', block);
block.txs.forEach(function(tx) {
@ -107,7 +121,17 @@ Fullnode.prototype._init = function _init() {
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) {
self.wallets.forEach(function(wallet) {
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)
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;
self.emit('load');
this.chain.once('load', function() {
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;
if (this.options.debug)
if (this.options.debug != null)
bcoin.debug = this.options.debug;
if (this.options.debugFile != null)
bcoin.debugFile = this.options.debugFile;
if (this.options.network)
network.set(this.options.network);
@ -40,6 +43,7 @@ function Node(options) {
this.pool = null;
this.chain = null;
this.miner = null;
this.profiler = null;
this.wallets = [];
Node.global = this;

View File

@ -30,12 +30,6 @@ function Pool(node, options) {
this.options = options;
if (options.debug)
bcoin.debug = this.options.debug;
if (options.network)
network.set(options.network);
options.spv = options.spv !== false;
if (options.type === 'spv')
@ -48,6 +42,7 @@ function Pool(node, options) {
? (!options.spv ? true : false)
: options.relay;
this.network = node.network;
this.originalSeeds = (options.seeds || network.seeds).map(utils.parseHost);
this.setSeeds([]);
@ -152,6 +147,13 @@ function Pool(node, options) {
this.loading = true;
if (!this.chain.loading) {
this.loading = false;
this.emit('load');
this._init();
return;
}
this.chain.once('load', function() {
self.loading = false;
self.emit('load');
@ -1222,6 +1224,13 @@ Pool.prototype.addWallet = function addWallet(wallet, callback) {
if (this.loading)
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)
return false;
@ -1238,9 +1247,6 @@ Pool.prototype.addWallet = function addWallet(wallet, callback) {
self.sendTX(tx);
});
if (!self.options.spv)
return callback();
if (self._pendingSearch)
return callback();
@ -1259,82 +1265,42 @@ Pool.prototype.addWallet = function addWallet(wallet, callback) {
};
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);
if (i == -1)
return;
this.wallets.splice(i, 1);
this.unwatchWallet(wallet);
};
Pool.prototype.watchAddress = function watchAddress(address) {
if (address.script) {
// For the redeem script hash in outputs:
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());
address = bcoin.address.parse(address);
this.watch(address.hash);
};
Pool.prototype.unwatchAddress = function unwatchAddress(address) {
if (addres.script) {
// For the redeem script hash in p2sh outputs:
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());
address = bcoin.address.parse(address);
this.unwatch(address.hash);
};
Pool.prototype.watchWallet = function watchWallet(wallet) {
var self = this;
wallet.addresses.forEach(function(address) {
Object.keys(wallet.addressMap).forEach(function(address) {
this.watchAddress(address);
}, 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) {
wallet.addresses.forEach(function(address) {
Object.keys(wallet.addressMap).forEach(function(address) {
this.unwatchAddress(address);
}, 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) {

View File

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