chaindb.
This commit is contained in:
parent
2c861aff82
commit
8f85f0b5c9
@ -16,11 +16,11 @@ var pad32 = utils.pad32;
|
||||
* BlockDB
|
||||
*/
|
||||
|
||||
function BlockDB(node, options) {
|
||||
function BlockDB(options, db) {
|
||||
var self = this;
|
||||
|
||||
if (!(this instanceof BlockDB))
|
||||
return new BlockDB(node, options);
|
||||
return new BlockDB(options);
|
||||
|
||||
EventEmitter.call(this);
|
||||
|
||||
@ -32,12 +32,7 @@ function BlockDB(node, options) {
|
||||
this.keepBlocks = options.keepBlocks || 288;
|
||||
this.prune = !!options.prune;
|
||||
|
||||
this.node = node;
|
||||
|
||||
this.db = bcoin.ldb('block', {
|
||||
cacheSize: 16 * 1024 * 1024,
|
||||
writeBufferSize: 8 * 1024 * 1024
|
||||
});
|
||||
this.db = db;
|
||||
}
|
||||
|
||||
utils.inherits(BlockDB, EventEmitter);
|
||||
@ -52,9 +47,8 @@ BlockDB.prototype.close = function close(callback) {
|
||||
});
|
||||
};
|
||||
|
||||
BlockDB.prototype.saveBlock = function saveBlock(block, callback) {
|
||||
BlockDB.prototype.saveBlock = function saveBlock(block, batch, callback) {
|
||||
var self = this;
|
||||
var batch = this.batch();
|
||||
|
||||
batch.put('b/b/' + block.hash('hex'), block.toCompact());
|
||||
|
||||
@ -62,7 +56,9 @@ BlockDB.prototype.saveBlock = function saveBlock(block, callback) {
|
||||
batch.put('t/t/' + tx.hash('hex'), tx.toExtended());
|
||||
});
|
||||
|
||||
self.connectBlock(block, function(err) {
|
||||
self.connectBlock(block, batch, callback);
|
||||
return;
|
||||
self.connectBlock(block, batch, function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
@ -72,40 +68,36 @@ BlockDB.prototype.saveBlock = function saveBlock(block, callback) {
|
||||
// Check for now-fully-spent txs. Try to remove
|
||||
// them or queue them up for future deletion if
|
||||
// it is currently unsafe to remove them.
|
||||
self._pruneBlock(block, function(err) {
|
||||
self._pruneBlock(block, batch, function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
return callback(null, block);
|
||||
});
|
||||
}, batch);
|
||||
});
|
||||
};
|
||||
|
||||
BlockDB.prototype.removeBlock = function removeBlock(hash, callback) {
|
||||
BlockDB.prototype.removeBlock = function removeBlock(hash, batch, callback) {
|
||||
var self = this;
|
||||
|
||||
this._getTXBlock(hash, function(err, block) {
|
||||
var batch;
|
||||
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
if (!block)
|
||||
return callback();
|
||||
|
||||
batch = self.batch();
|
||||
|
||||
batch.del('b/b/' + block.hash('hex'));
|
||||
|
||||
block.txs.forEach(function(tx, i) {
|
||||
batch.del('t/t/' + tx.hash('hex'));
|
||||
});
|
||||
|
||||
self.disconnectBlock(block, callback, batch);
|
||||
self.disconnectBlock(block, batch, callback);
|
||||
});
|
||||
};
|
||||
|
||||
BlockDB.prototype.connectBlock = function connectBlock(block, callback, batch) {
|
||||
BlockDB.prototype.connectBlock = function connectBlock(block, batch, callback) {
|
||||
var self = this;
|
||||
|
||||
this._getCoinBlock(block, function(err, block) {
|
||||
@ -114,19 +106,8 @@ BlockDB.prototype.connectBlock = function connectBlock(block, callback, batch) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
if (!block) {
|
||||
assert(!batch);
|
||||
if (!block)
|
||||
return callback();
|
||||
}
|
||||
|
||||
if (!batch)
|
||||
batch = self.batch();
|
||||
|
||||
batch.put('b/h/' + pad32(block.height), block.hash());
|
||||
|
||||
height = new Buffer(4);
|
||||
utils.writeU32(height, block.height, 0);
|
||||
batch.put('b/t', height);
|
||||
|
||||
block.txs.forEach(function(tx, i) {
|
||||
var hash = tx.hash('hex');
|
||||
@ -178,40 +159,25 @@ BlockDB.prototype.connectBlock = function connectBlock(block, callback, batch) {
|
||||
});
|
||||
});
|
||||
|
||||
batch.write(function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
self.emit('save block', block);
|
||||
return callback(null, block);
|
||||
});
|
||||
self.emit('add block', block);
|
||||
|
||||
return callback(null, block);
|
||||
});
|
||||
};
|
||||
|
||||
BlockDB.prototype.disconnectBlock = function disconnectBlock(hash, callback, batch) {
|
||||
BlockDB.prototype.disconnectBlock = function disconnectBlock(hash, batch, callback) {
|
||||
var self = this;
|
||||
|
||||
this._getTXBlock(hash, function(err, block) {
|
||||
var height;
|
||||
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
if (!block) {
|
||||
assert(!batch);
|
||||
if (!block)
|
||||
return callback();
|
||||
}
|
||||
|
||||
if (!batch)
|
||||
batch = self.batch();
|
||||
|
||||
if (typeof hash === 'string')
|
||||
assert(block.hash('hex') === hash);
|
||||
|
||||
height = new Buffer(4);
|
||||
utils.writeU32(height, block.height - 1, 0);
|
||||
batch.put('b/t', height);
|
||||
batch.del('b/h/' + pad32(block.height));
|
||||
|
||||
block.txs.forEach(function(tx, i) {
|
||||
var hash = tx.hash('hex');
|
||||
var uniq = {};
|
||||
@ -265,12 +231,8 @@ BlockDB.prototype.disconnectBlock = function disconnectBlock(hash, callback, bat
|
||||
});
|
||||
});
|
||||
|
||||
batch.write(function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
self.emit('remove block', block);
|
||||
return callback(null, block);
|
||||
});
|
||||
self.emit('remove block', block);
|
||||
return callback(null, block);
|
||||
});
|
||||
};
|
||||
|
||||
@ -692,7 +654,7 @@ BlockDB.prototype._getHash = function _getHash(height, callback) {
|
||||
if (typeof height === 'string')
|
||||
return callback(null, height);
|
||||
|
||||
this.db.get('b/h/' + pad32(height), function(err, hash) {
|
||||
this.db.get('c/h/' + pad32(height), function(err, hash) {
|
||||
if (err && err.type !== 'NotFoundError')
|
||||
return callback(err);
|
||||
if (!hash)
|
||||
@ -806,6 +768,10 @@ BlockDB.prototype.isUnspentTX = function isUnspentTX(hash, callback) {
|
||||
BlockDB.prototype.isSpentTX = function isSpentTX(hash, callback) {
|
||||
var spent = true;
|
||||
|
||||
// Important!
|
||||
if (hash.hash)
|
||||
hash = hash.hash('hex');
|
||||
|
||||
var iter = this.db.db.iterator({
|
||||
gte: 'u/t/' + hash,
|
||||
lte: 'u/t/' + hash + '~',
|
||||
@ -828,7 +794,8 @@ BlockDB.prototype.isSpentTX = function isSpentTX(hash, callback) {
|
||||
|
||||
spent = false;
|
||||
|
||||
next();
|
||||
// IMPORTANT!
|
||||
iter.end(done);
|
||||
});
|
||||
})();
|
||||
|
||||
@ -864,72 +831,9 @@ BlockDB.prototype.isSpent = function isSpent(hash, index, callback) {
|
||||
});
|
||||
};
|
||||
|
||||
BlockDB.prototype.getHeight = function getHeight(callback) {
|
||||
BlockDB.prototype._pruneBlock = function _pruneBlock(block, batch, callback) {
|
||||
var self = this;
|
||||
|
||||
return this.db.get('b/t', function(err, height) {
|
||||
if (err && err.type !== 'NotFoundError')
|
||||
return callback(err);
|
||||
|
||||
if (!height)
|
||||
return callback(null, -1);
|
||||
|
||||
return callback(null, utils.readU32(height, 0));
|
||||
});
|
||||
};
|
||||
|
||||
BlockDB.prototype.getTipHash = function getTipHash(callback) {
|
||||
return this.getHeight(function(err, height) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
if (height === -1)
|
||||
return callback();
|
||||
|
||||
return self.db.get('b/h/' + pad32(height), function(err, hash) {
|
||||
if (err && err.type !== 'NotFoundError')
|
||||
return callback(err);
|
||||
|
||||
if (!hash)
|
||||
return callback();
|
||||
|
||||
return callback(null, utils.toHex(hash));
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
BlockDB.prototype.reset = function reset(height, callback, emit) {
|
||||
var self = this;
|
||||
this.getHeight(function(err, currentHeight) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
if (currentHeight < height)
|
||||
return callback(new Error('Cannot reset to height ' + height));
|
||||
|
||||
(function next() {
|
||||
if (currentHeight === height)
|
||||
return callback();
|
||||
|
||||
self.removeBlock(currentHeight, function(err, block) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
// Emit the blocks we removed.
|
||||
if (emit && block)
|
||||
emit(block);
|
||||
|
||||
currentHeight--;
|
||||
next();
|
||||
});
|
||||
})();
|
||||
});
|
||||
};
|
||||
|
||||
BlockDB.prototype._pruneBlock = function _pruneBlock(block, callback) {
|
||||
var self = this;
|
||||
var batch = this.batch();
|
||||
|
||||
// For much more aggressive pruning, we could delete
|
||||
// the block headers 288 blocks before this one here as well.
|
||||
|
||||
@ -942,7 +846,7 @@ BlockDB.prototype._pruneBlock = function _pruneBlock(block, callback) {
|
||||
self._pruneQueue(block, batch, function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
return batch.write(callback);
|
||||
return callback();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
@ -34,8 +34,7 @@ function Chain(node, options) {
|
||||
this.node = node;
|
||||
this.loading = false;
|
||||
this.mempool = node.mempool;
|
||||
this.blockdb = node.blockdb;
|
||||
this.db = new bcoin.chaindb(node, this, options);
|
||||
this.db = new bcoin.chaindb(this, options);
|
||||
this.busy = false;
|
||||
this.jobs = [];
|
||||
this.pending = [];
|
||||
@ -132,41 +131,47 @@ Chain.prototype._init = function _init() {
|
||||
utils.debug('Warning: %d (%dmb) orphans cleared!', count, utils.mb(size));
|
||||
});
|
||||
|
||||
this.db.on('add entry', function(entry) {
|
||||
self.emit('add entry', entry);
|
||||
});
|
||||
|
||||
this.db.on('remove entry', function(entry) {
|
||||
self.emit('remove entry', entry);
|
||||
});
|
||||
|
||||
this.db.on('add block', function(block) {
|
||||
self.emit('add block', block);
|
||||
});
|
||||
|
||||
this.db.on('remove block', function(block) {
|
||||
self.emit('remove block', block);
|
||||
});
|
||||
|
||||
this.loading = true;
|
||||
|
||||
utils.debug('Chain is loading.');
|
||||
|
||||
this._ensureGenesis(function(err) {
|
||||
if (err)
|
||||
throw err;
|
||||
self._preload(function(err, start) {
|
||||
if (err) {
|
||||
utils.debug('Preloading chain failed.');
|
||||
utils.debug('Reason: %s', err.message);
|
||||
}
|
||||
|
||||
self._preload(function(err, start) {
|
||||
if (err) {
|
||||
utils.debug('Preloading chain failed.');
|
||||
utils.debug('Reason: %s', err.message);
|
||||
}
|
||||
self.db.load(function(err) {
|
||||
if (err)
|
||||
throw err;
|
||||
|
||||
self.db.load(function(err) {
|
||||
self.db.getTip(function(err, tip) {
|
||||
if (err)
|
||||
throw err;
|
||||
|
||||
self._syncHeight(function(err) {
|
||||
if (err)
|
||||
throw err;
|
||||
assert(tip);
|
||||
|
||||
self.db.getTip(function(err, tip) {
|
||||
if (err)
|
||||
throw err;
|
||||
self.tip = tip;
|
||||
self.height = tip.height;
|
||||
|
||||
assert(tip);
|
||||
|
||||
self.tip = tip;
|
||||
self.height = tip.height;
|
||||
|
||||
self.loading = false;
|
||||
self.emit('load');
|
||||
});
|
||||
});
|
||||
self.loading = false;
|
||||
self.emit('load');
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -230,37 +235,6 @@ Chain.prototype._lock = function _lock(func, args, force) {
|
||||
};
|
||||
};
|
||||
|
||||
Chain.prototype._ensureGenesis = function _ensureGenesis(callback) {
|
||||
var self = this;
|
||||
|
||||
callback = utils.asyncify(callback);
|
||||
|
||||
if (!this.blockdb)
|
||||
return callback();
|
||||
|
||||
self.blockdb.hasBlock(network.genesis.hash, function(err, result) {
|
||||
var genesis;
|
||||
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
if (result)
|
||||
return callback();
|
||||
|
||||
utils.debug('BlockDB does not have genesis block. Adding.');
|
||||
|
||||
genesis = bcoin.block.fromRaw(network.genesisBlock, 'hex');
|
||||
genesis.height = 0;
|
||||
|
||||
self.blockdb.saveBlock(genesis, function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
return callback();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// Stream headers from electrum.org for quickly
|
||||
// preloading the chain. Electrum.org stores
|
||||
// headers in the standard block header format,
|
||||
@ -398,24 +372,6 @@ Chain.prototype._preload = function _preload(callback) {
|
||||
});
|
||||
};
|
||||
|
||||
Chain.prototype._saveBlock = function _saveBlock(block, callback) {
|
||||
var self = this;
|
||||
|
||||
if (!this.blockdb)
|
||||
return utils.nextTick(callback);
|
||||
|
||||
this.blockdb.saveBlock(block, callback);
|
||||
};
|
||||
|
||||
Chain.prototype._removeBlock = function _removeBlock(tip, callback) {
|
||||
var self = this;
|
||||
|
||||
if (!this.blockdb)
|
||||
return utils.nextTick(callback);
|
||||
|
||||
this.blockdb.removeBlock(tip, callback);
|
||||
};
|
||||
|
||||
Chain.prototype._verifyContext = function _verifyContext(block, prev, callback) {
|
||||
var self = this;
|
||||
|
||||
@ -605,18 +561,18 @@ Chain.prototype._checkDuplicates = function _checkDuplicates(block, prev, callba
|
||||
var self = this;
|
||||
var height = prev.height + 1;
|
||||
|
||||
if (!this.blockdb || block.type !== 'block')
|
||||
if (this.options.spv || block.type !== 'block')
|
||||
return callback(null, true);
|
||||
|
||||
if (block.isGenesis())
|
||||
return callback(null, true);
|
||||
|
||||
// Check all transactions
|
||||
utils.every(block.txs, function(tx, next) {
|
||||
utils.everySerial(block.txs, function(tx, next) {
|
||||
var hash = tx.hash('hex');
|
||||
|
||||
// BIP30 - Ensure there are no duplicate txids
|
||||
self.blockdb.isUnspentTX(hash, function(err, result) {
|
||||
self.db.isUnspentTX(hash, function(err, result) {
|
||||
if (err)
|
||||
return next(err);
|
||||
|
||||
@ -639,7 +595,7 @@ Chain.prototype._checkInputs = function _checkInputs(block, prev, flags, callbac
|
||||
var height = prev.height + 1;
|
||||
var scriptCheck = true;
|
||||
|
||||
if (!this.blockdb || block.type !== 'block')
|
||||
if (this.options.spv || block.type !== 'block')
|
||||
return callback(null, true);
|
||||
|
||||
if (block.isGenesis())
|
||||
@ -652,13 +608,14 @@ Chain.prototype._checkInputs = function _checkInputs(block, prev, flags, callbac
|
||||
scriptCheck = false;
|
||||
}
|
||||
|
||||
this.blockdb.fillBlock(block, function(err) {
|
||||
this.db.fillBlock(block, function(err) {
|
||||
var i, j, input, hash;
|
||||
var sigops = 0;
|
||||
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
|
||||
// Check all transactions
|
||||
for (i = 0; i < block.txs.length; i++) {
|
||||
tx = block.txs[i];
|
||||
@ -827,36 +784,8 @@ Chain.prototype._reorganize = function _reorganize(entry, callback) {
|
||||
assert(entries.length > 0);
|
||||
|
||||
utils.forEachSerial(entries, function(entry, next) {
|
||||
self.db.disconnect(entry, function(err) {
|
||||
if (err)
|
||||
return next(err);
|
||||
|
||||
self.emit('remove entry', entry);
|
||||
|
||||
next();
|
||||
});
|
||||
}, function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
if (!self.blockdb)
|
||||
return callback();
|
||||
|
||||
utils.forEachSerial(entries, function(entry, next) {
|
||||
self.blockdb.disconnectBlock(entry.hash, function(err, block) {
|
||||
if (err)
|
||||
return next(err);
|
||||
|
||||
self.emit('remove block', block);
|
||||
|
||||
next();
|
||||
});
|
||||
}, function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
return callback();
|
||||
});
|
||||
});
|
||||
self.db.disconnect(entry, next);
|
||||
}, callback);
|
||||
}
|
||||
}
|
||||
|
||||
@ -885,39 +814,8 @@ Chain.prototype._reorganize = function _reorganize(entry, callback) {
|
||||
assert(entries.length > 0);
|
||||
|
||||
utils.forEachSerial(entries, function(entry, next) {
|
||||
self.db.connect(entry, function(err) {
|
||||
if (err)
|
||||
return next(err);
|
||||
|
||||
self.emit('add entry', entry);
|
||||
|
||||
return next();
|
||||
});
|
||||
}, function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
if (!self.blockdb)
|
||||
return callback();
|
||||
|
||||
utils.forEachSerial(entries, function(err, entry) {
|
||||
self.blockdb.connectBlock(entry.hash, function(err, block) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
assert(block);
|
||||
|
||||
self.emit('add block', block);
|
||||
|
||||
next();
|
||||
});
|
||||
}, function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
return callback();
|
||||
});
|
||||
});
|
||||
self.db.connect(entry, next);
|
||||
}, callback);
|
||||
}
|
||||
}
|
||||
|
||||
@ -951,11 +849,8 @@ Chain.prototype._setBestChain = function _setBestChain(entry, block, callback) {
|
||||
|
||||
// Start fsyncing writes once we're no
|
||||
// longer dealing with historical data.
|
||||
if (this.isFull()) {
|
||||
if (this.isFull())
|
||||
this.db.fsync = true;
|
||||
if (this.blockdb)
|
||||
this.blockdb.fsync = true;
|
||||
}
|
||||
|
||||
if (!this.tip) {
|
||||
if (entry.hash !== network.genesis.hash)
|
||||
@ -972,19 +867,14 @@ Chain.prototype._setBestChain = function _setBestChain(entry, block, callback) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
self._saveBlock(block, function(err) {
|
||||
self.db.save(entry, block, function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
self.db.save(entry, function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
self.tip = entry;
|
||||
self.height = entry.height;
|
||||
|
||||
self.tip = entry;
|
||||
self.height = entry.height;
|
||||
|
||||
return callback();
|
||||
});
|
||||
return callback();
|
||||
});
|
||||
}
|
||||
};
|
||||
@ -1014,74 +904,7 @@ Chain.prototype.reset = function reset(height, callback, force) {
|
||||
if (err)
|
||||
return done(err);
|
||||
|
||||
if (!self.blockdb)
|
||||
return done();
|
||||
|
||||
self.blockdb.reset(height, function(err) {
|
||||
if (err)
|
||||
return done(err);
|
||||
|
||||
return done();
|
||||
}, function(block) {
|
||||
self.emit('remove block', block);
|
||||
});
|
||||
}, function(entry) {
|
||||
self.emit('remove entry', entry);
|
||||
});
|
||||
};
|
||||
|
||||
Chain.prototype._syncHeight = function _syncHeight(callback, force) {
|
||||
var self = this;
|
||||
var chainHeight;
|
||||
|
||||
var unlock = this._lock(_syncHeight, [callback], force);
|
||||
if (!unlock)
|
||||
return;
|
||||
|
||||
callback = utils.ensure(callback);
|
||||
|
||||
function done(err, result) {
|
||||
unlock();
|
||||
callback(err, result);
|
||||
}
|
||||
|
||||
this.db.getChainHeight(function(err, chainHeight) {
|
||||
if (err)
|
||||
return done(err);
|
||||
|
||||
if (chainHeight == null || chainHeight < 0)
|
||||
return done(new Error('Bad chain height.'));
|
||||
|
||||
if (!self.blockdb)
|
||||
return done();
|
||||
|
||||
self.blockdb.getHeight(function(err, blockHeight) {
|
||||
if (err)
|
||||
return done(err);
|
||||
|
||||
if (blockHeight < 0)
|
||||
return done(new Error('Bad block height.'));
|
||||
|
||||
if (blockHeight === chainHeight)
|
||||
return done();
|
||||
|
||||
utils.debug('ChainDB and BlockDB are out of sync.');
|
||||
|
||||
if (blockHeight < chainHeight) {
|
||||
utils.debug('ChainDB is higher than BlockDB. Syncing...');
|
||||
return self.db.reset(blockHeight, done);
|
||||
}
|
||||
|
||||
if (blockHeight > chainHeight) {
|
||||
utils.debug('BlockDB is higher than ChainDB. Syncing...');
|
||||
self.blockdb.reset(chainHeight, function(err) {
|
||||
if (err)
|
||||
return done(err);
|
||||
|
||||
return done();
|
||||
});
|
||||
}
|
||||
});
|
||||
return done();
|
||||
});
|
||||
};
|
||||
|
||||
@ -1290,6 +1113,13 @@ Chain.prototype.add = function add(initial, peer, callback, force) {
|
||||
}
|
||||
}
|
||||
|
||||
// Update the block height
|
||||
// IMPORTANT!!!!!
|
||||
block.height = height;
|
||||
block.txs.forEach(function(tx) {
|
||||
tx.height = height;
|
||||
});
|
||||
|
||||
// Do "contextual" verification on our block
|
||||
// now that we're certain its previous
|
||||
// block is in the chain.
|
||||
@ -1326,12 +1156,6 @@ Chain.prototype.add = function add(initial, peer, callback, force) {
|
||||
if (entry.chainwork.cmp(self.tip.chainwork) <= 0)
|
||||
return done();
|
||||
|
||||
// Update the block height
|
||||
block.height = entry.height;
|
||||
block.txs.forEach(function(tx) {
|
||||
tx.height = entry.height;
|
||||
});
|
||||
|
||||
// Attempt to add block to the chain index.
|
||||
self._setBestChain(entry, block, function(err) {
|
||||
if (err)
|
||||
@ -1347,8 +1171,6 @@ Chain.prototype.add = function add(initial, peer, callback, force) {
|
||||
if (block.hash('hex') !== initial.hash('hex'))
|
||||
self.emit('resolved', block, entry, peer);
|
||||
|
||||
self.emit('add block', block);
|
||||
|
||||
// No orphan chain.
|
||||
if (!self.orphan.map[hash])
|
||||
return done();
|
||||
|
||||
1066
lib/bcoin/chaindb.js
1066
lib/bcoin/chaindb.js
File diff suppressed because it is too large
Load Diff
@ -41,13 +41,10 @@ Fullnode.prototype._init = function _init() {
|
||||
|
||||
this.loading = true;
|
||||
|
||||
// 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.chain = new bcoin.chain(this, {
|
||||
preload: false,
|
||||
fsync: false,
|
||||
prune: true
|
||||
prune: false
|
||||
});
|
||||
|
||||
// Mempool needs access to blockdb.
|
||||
@ -55,12 +52,6 @@ Fullnode.prototype._init = function _init() {
|
||||
rbf: false
|
||||
});
|
||||
|
||||
// Chain needs access to blockdb.
|
||||
this.chain = new bcoin.chain(this, {
|
||||
preload: false,
|
||||
fsync: false
|
||||
});
|
||||
|
||||
// Pool needs access to the chain.
|
||||
this.pool = new bcoin.pool(this, {
|
||||
witness: this.network.type === 'segnet',
|
||||
@ -206,11 +197,11 @@ Fullnode.prototype.scanWallet = function scanWallet(wallet, callback) {
|
||||
};
|
||||
|
||||
Fullnode.prototype.getBlock = function getBlock(hash, callback) {
|
||||
this.blockdb.getBlock(hash, callback);
|
||||
this.chain.db.getBlock(hash, callback);
|
||||
};
|
||||
|
||||
Fullnode.prototype.getFullBlock = function getFullBlock(hash, callback) {
|
||||
this.blockdb.getFullBlock(hash, callback);
|
||||
this.chain.db.getFullBlock(hash, callback);
|
||||
};
|
||||
|
||||
Fullnode.prototype.getCoin = function getCoin(hash, index, callback) {
|
||||
@ -226,7 +217,7 @@ Fullnode.prototype.getCoin = function getCoin(hash, index, callback) {
|
||||
if (this.mempool.isSpent(hash, index))
|
||||
return callback(null, null);
|
||||
|
||||
this.blockdb.getCoin(hash, index, function(err, coin) {
|
||||
this.chain.db.getCoin(hash, index, function(err, coin) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
@ -245,7 +236,7 @@ Fullnode.prototype.getCoinByAddress = function getCoinByAddress(addresses, callb
|
||||
|
||||
mempool = this.mempool.getCoinsByAddress(addresses);
|
||||
|
||||
this.blockdb.getCoinsByAddress(addresses, function(err, coins) {
|
||||
this.chain.db.getCoinsByAddress(addresses, function(err, coins) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
@ -267,7 +258,7 @@ Fullnode.prototype.getTX = function getTX(hash, callback) {
|
||||
if (tx)
|
||||
return callback(null, tx);
|
||||
|
||||
this.blockdb.getTX(hash, function(err, tx) {
|
||||
this.chain.db.getTX(hash, function(err, tx) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
@ -286,7 +277,7 @@ Fullnode.prototype.isSpent = function isSpent(hash, index, callback) {
|
||||
if (this.mempool.isSpent(hash, index))
|
||||
return callback(null, true);
|
||||
|
||||
this.blockdb.isSpent(hash, index, callback);
|
||||
this.chain.db.isSpent(hash, index, callback);
|
||||
};
|
||||
|
||||
Fullnode.prototype.getTXByAddress = function getTXByAddress(addresses, callback) {
|
||||
@ -297,7 +288,7 @@ Fullnode.prototype.getTXByAddress = function getTXByAddress(addresses, callback)
|
||||
|
||||
mempool = this.mempool.getTXByAddress(addresses);
|
||||
|
||||
this.blockdb.getTXByAddress(addresses, function(err, txs) {
|
||||
this.chain.db.getTXByAddress(addresses, function(err, txs) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
@ -311,7 +302,7 @@ Fullnode.prototype.fillCoin = function fillCoin(tx, callback) {
|
||||
if (this.mempool.fillCoin(tx))
|
||||
return callback();
|
||||
|
||||
this.blockdb.fillCoin(tx, callback);
|
||||
this.chain.db.fillCoin(tx, callback);
|
||||
};
|
||||
|
||||
Fullnode.prototype.fillTX = function fillTX(tx, callback) {
|
||||
@ -320,7 +311,7 @@ Fullnode.prototype.fillTX = function fillTX(tx, callback) {
|
||||
if (this.mempool.fillTX(tx))
|
||||
return callback();
|
||||
|
||||
this.blockdb.fillTX(tx, callback);
|
||||
this.chain.db.fillTX(tx, callback);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -27,7 +27,7 @@ function Mempool(node, options) {
|
||||
|
||||
this.options = options;
|
||||
this.node = node;
|
||||
this.blockdb = node.blockdb;
|
||||
this.chain = node.chain;
|
||||
|
||||
this.txs = {};
|
||||
this.spent = {};
|
||||
@ -214,7 +214,7 @@ Mempool.prototype.addTX = function addTX(tx, peer, callback) {
|
||||
|
||||
this._lockTX(tx);
|
||||
|
||||
this.blockdb.fillCoin(tx, function(err) {
|
||||
this.chain.fillCoin(tx, function(err) {
|
||||
var i, input, dup, height, ts, priority;
|
||||
|
||||
self._unlockTX(tx);
|
||||
|
||||
@ -1495,7 +1495,7 @@ utils.forEach = function forEach(arr, iter, callback) {
|
||||
utils.forRangeSerial = function forRangeSerial(from, to, iter, callback) {
|
||||
var called = false;
|
||||
|
||||
callback = utils.asyncify(callback);
|
||||
callback = utils.ensure(callback);
|
||||
|
||||
(function next(err) {
|
||||
assert(!called);
|
||||
@ -1518,7 +1518,7 @@ utils.forEachSerial = function forEachSerial(arr, iter, callback) {
|
||||
var i = 0;
|
||||
var called = false;
|
||||
|
||||
callback = utils.asyncify(callback);
|
||||
callback = utils.ensure(callback);
|
||||
|
||||
(function next(err) {
|
||||
var item;
|
||||
@ -1571,7 +1571,7 @@ utils.everySerial = function everySerial(arr, iter, callback) {
|
||||
var i = 0;
|
||||
var called = false;
|
||||
|
||||
callback = utils.asyncify(callback);
|
||||
callback = utils.ensure(callback);
|
||||
|
||||
(function next(err, res) {
|
||||
var item;
|
||||
@ -1580,7 +1580,7 @@ utils.everySerial = function everySerial(arr, iter, callback) {
|
||||
called = true;
|
||||
return callback(err);
|
||||
}
|
||||
if (!result) {
|
||||
if (!res) {
|
||||
called = true;
|
||||
return callback(null, false);
|
||||
}
|
||||
@ -1593,7 +1593,7 @@ utils.everySerial = function everySerial(arr, iter, callback) {
|
||||
utils.nextTick(function() {
|
||||
iter(item, next, i - 1);
|
||||
});
|
||||
})();
|
||||
})(null, true);
|
||||
};
|
||||
|
||||
utils.mb = function mb(size) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user