chain refactoring.
This commit is contained in:
parent
b352bfbe3d
commit
9f88173881
@ -62,10 +62,28 @@ Chain.prototype._init = function _init() {
|
||||
var self = this;
|
||||
|
||||
// Hook into events for debugging
|
||||
this.on('block', function(block, entry, peer) {
|
||||
// var host = peer ? peer.host : 'unknown';
|
||||
// utils.debug('Block %s (%d) added to chain (%s)',
|
||||
// utils.revHex(entry.hash), entry.height, host);
|
||||
// this.on('block', function(block, entry, peer) {
|
||||
// var host = peer ? peer.host : 'unknown';
|
||||
// utils.debug('Block %s (%d) added to chain (%s)',
|
||||
// utils.revHex(entry.hash), entry.height, host);
|
||||
// });
|
||||
|
||||
this.on('competitor', function(block, entry, peer) {
|
||||
var host = peer ? peer.host : 'unknown';
|
||||
utils.debug('Heads up: Competing chain at height %d:'
|
||||
+ ' tip-height=%d competitor-height=%d'
|
||||
+ ' tip-hash=%s competitor-hash=%s'
|
||||
+ ' tip-chainwork=%s competitor-chainwork=%s'
|
||||
+ ' chainwork-diff=%s (%s)',
|
||||
entry.height,
|
||||
utils.revHex(self.tip.hash),
|
||||
utils.revHex(entry.hash),
|
||||
self.tip.height,
|
||||
entry.height,
|
||||
self.tip.chainwork.toString(),
|
||||
entry.chainwork.toString(),
|
||||
self.tip.chainwork.sub(entry.chainwork).toString(),
|
||||
host);
|
||||
});
|
||||
|
||||
this.on('resolved', function(block, entry, peer) {
|
||||
@ -863,36 +881,14 @@ Chain.prototype._reorganize = function _reorganize(entry, block, callback) {
|
||||
});
|
||||
};
|
||||
|
||||
Chain.prototype._addEntry = function _addEntry(entry, block, callback) {
|
||||
// Set main chain only if chainwork is higher.
|
||||
// Add the block but do _not_ connect the inputs.
|
||||
if (entry.chainwork.cmp(this.tip.chainwork) <= 0) {
|
||||
return this.db.save(entry, block, false, function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
return callback(null, false);
|
||||
});
|
||||
}
|
||||
|
||||
// Attempt to add block to the chain index.
|
||||
return this._setBestChain(entry, block, function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
return callback(null, true);
|
||||
});
|
||||
};
|
||||
|
||||
Chain.prototype._setBestChain = function _setBestChain(entry, block, callback) {
|
||||
var self = this;
|
||||
|
||||
this.lastUpdate = utils.now();
|
||||
|
||||
function done(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
// Save block and connect inputs.
|
||||
self.db.save(entry, block, true, function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
@ -905,20 +901,45 @@ Chain.prototype._setBestChain = function _setBestChain(entry, block, callback) {
|
||||
|
||||
self.emit('tip', entry);
|
||||
|
||||
return callback();
|
||||
// Return true (added to the main chain)
|
||||
return callback(null, true);
|
||||
});
|
||||
}
|
||||
|
||||
// Update the timestamp to
|
||||
// maintain a time delta of blocks.
|
||||
this.lastUpdate = utils.now();
|
||||
|
||||
// We don't have a genesis block yet.
|
||||
if (!this.tip) {
|
||||
if (entry.hash !== network.genesis.hash)
|
||||
return utils.asyncify(callback)(new Error('Bad genesis block.'));
|
||||
|
||||
done();
|
||||
} else if (entry.prevBlock === this.tip.hash) {
|
||||
done();
|
||||
} else {
|
||||
self._reorganize(entry, block, done);
|
||||
return done();
|
||||
}
|
||||
|
||||
// The block is on a side chain if the
|
||||
// chainwork is less than or equal to
|
||||
// our tip's. Add the block but do _not_
|
||||
// connect the inputs.
|
||||
if (entry.chainwork.cmp(this.tip.chainwork) <= 0) {
|
||||
return this.db.save(entry, block, false, function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
// Return false (added to side chain)
|
||||
return callback(null, false);
|
||||
});
|
||||
}
|
||||
|
||||
// Everything is in order.
|
||||
if (entry.prevBlock === this.tip.hash)
|
||||
return done();
|
||||
|
||||
// A higher fork has arrived.
|
||||
// Time to reorganize the chain.
|
||||
utils.debug('WARNING: Reorganizing chain.');
|
||||
return this._reorganize(entry, block, done);
|
||||
};
|
||||
|
||||
Chain.prototype.reset = function reset(height, callback, force) {
|
||||
@ -1214,7 +1235,7 @@ Chain.prototype.add = function add(initial, peer, callback, force) {
|
||||
}, prev);
|
||||
|
||||
// Attempt to add block to the chain index.
|
||||
self._addEntry(entry, block, function(err, mainChain) {
|
||||
self._setBestChain(entry, block, function(err, mainChain) {
|
||||
if (err)
|
||||
return done(err);
|
||||
|
||||
@ -1226,6 +1247,8 @@ Chain.prototype.add = function add(initial, peer, callback, force) {
|
||||
// orphan) only if it is on the main chain.
|
||||
if (mainChain)
|
||||
self.emit('block', block, entry, peer);
|
||||
else
|
||||
self.emit('competitor', block, entry, peer);
|
||||
|
||||
if (block.hash('hex') !== initial.hash('hex'))
|
||||
self.emit('resolved', block, entry, peer);
|
||||
|
||||
@ -242,6 +242,10 @@ ChainBlock.prototype.getMedianTimeAsync = function getMedianTimeAsync(callback)
|
||||
});
|
||||
};
|
||||
|
||||
ChainBlock.prototype.__defineGetter__('rhash', function() {
|
||||
return utils.revHex(this.hash);
|
||||
});
|
||||
|
||||
ChainBlock.prototype.toRaw = function toRaw() {
|
||||
var p = new BufferWriter();
|
||||
|
||||
|
||||
@ -353,7 +353,6 @@ ChainDB.prototype.save = function save(entry, block, connect, callback) {
|
||||
|
||||
batch.put('c/b/' + entry.hash, height);
|
||||
batch.put('c/c/' + entry.hash, entry.toRaw());
|
||||
batch.put('c/n/' + entry.prevBlock, hash);
|
||||
|
||||
this.cacheHash.set(entry.hash, entry);
|
||||
|
||||
@ -367,6 +366,7 @@ ChainDB.prototype.save = function save(entry, block, connect, callback) {
|
||||
|
||||
this.cacheHeight.set(entry.height, entry);
|
||||
|
||||
batch.put('c/n/' + entry.prevBlock, hash);
|
||||
batch.put('c/h/' + pad32(entry.height), hash);
|
||||
batch.put('c/t', hash);
|
||||
|
||||
@ -399,7 +399,7 @@ ChainDB.prototype.getTip = function getTip(callback) {
|
||||
|
||||
ChainDB.prototype.connect = function connect(block, callback) {
|
||||
var self = this;
|
||||
var batch;
|
||||
var batch, hash;
|
||||
|
||||
this._ensureEntry(block, function(err, entry) {
|
||||
if (err)
|
||||
@ -409,9 +409,11 @@ ChainDB.prototype.connect = function connect(block, callback) {
|
||||
return callback();
|
||||
|
||||
batch = self.db.batch();
|
||||
hash = new Buffer(entry.hash, 'hex');
|
||||
|
||||
batch.put('c/h/' + pad32(entry.height), new Buffer(entry.hash, 'hex'));
|
||||
batch.put('c/t', new Buffer(entry.hash, 'hex'));
|
||||
batch.put('c/n/' + entry.prevBlock, hash);
|
||||
batch.put('c/h/' + pad32(entry.height), hash);
|
||||
batch.put('c/t', hash);
|
||||
|
||||
self.cacheHeight.set(entry.height, entry);
|
||||
|
||||
@ -443,6 +445,7 @@ ChainDB.prototype.disconnect = function disconnect(block, callback) {
|
||||
|
||||
batch = self.db.batch();
|
||||
|
||||
batch.del('c/n/' + entry.prevBlock);
|
||||
batch.del('c/h/' + pad32(entry.height));
|
||||
batch.put('c/t', new Buffer(entry.prevBlock, 'hex'));
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user