chain refactoring.

This commit is contained in:
Christopher Jeffrey 2016-03-30 04:50:29 -07:00
parent b352bfbe3d
commit 9f88173881
3 changed files with 68 additions and 38 deletions

View File

@ -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);

View File

@ -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();

View File

@ -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'));