This commit is contained in:
Chris Kleeschulte 2017-06-26 15:28:22 -04:00
parent 73687b36cf
commit 1b77fdf5e4
2 changed files with 58 additions and 33 deletions

View File

@ -265,67 +265,59 @@ BlockService.prototype._blockAlreadyProcessed = function(block) {
BlockService.prototype._mergeBlockIntoChainTips = function(block) {
function getPrevHashChain(keys, hash) {
for(var i = 0; i < keys.length; i++) {
console.log('here');
var key = keys[i];
var searchChain = this._chainTips.get(key);
console.log(searchChain);
var chainIndex = searchChain.indexOf(hash);
if (chainIndex > -1) {
return searchChain.slice(chainIndex);
}
}
}
var prevHash = utils.reverseBufferToString(block.header.prevHash);
var hasChildren = false;
var chain = this._chainTips.get(prevHash);
this._chainTips.del(prevHash);
if (chain) {
chain.unshift(prevHash);
}
var keys = this._chainTips.keys();
// looking for chains where this block is an ancestor of the tip of the chain
for(var i = 0; i < keys.length; i++) {
var key = keys[i];
var searchChain = this._chainTips.get(key);
assert(searchChain.length > 0, 'chain tips collection appears to be invalid');
var chainIndex = searchChain.indexOf(block.hash);
if (chainIndex > -1) {
hasChildren = true;
var newChain = searchChain.concat(chain || getPrevHashChain(keys, prevHash));
this._chainTips.set(key, newChain);
this._chainTips.set(key, searchChain.concat(chain || [prevHash]));
}
}
if (chain && !hasChildren) {
this._chainTips.set(block.hash, chain);
}
this._chainTips.del(prevHash);
if (!chain && !hasChildren) {
// if we have don't have any parents or children in chainTips, then create a new chain with this block
if (!hasChildren && !chain) {
this._chainTips.set(block.hash, getPrevHashChain(keys, prevHash));
var longestChain = [];
for(var j = 0; j < keys.length; j++) {
var key = keys[j];
var searchChain = this._chainTips.get(key);
var chainIndex = searchChain.indexOf(prevHash);
if (chainIndex > -1) {
var chain = searchChain.slice(chainIndex);
if (chain.length > longestChain.length) {
longestChain = chain;
}
}
}
longestChain = longestChain.length <= 1 ? [prevHash] : longestChain;
this._chainTips.set(block.hash, longestChain);
}
console.log(block.hash);
console.log(this._chainTips);
};
BlockService.prototype._onBlock = function(block) {
BlockService.prototype._onBlock = function(block) {
// 1. have we already seen this block?

View File

@ -49,7 +49,7 @@ describe('Block Service', function() {
expect(blockService._chainTips.get('ee')).to.deep.equal(['dd', 'cc', 'bb', 'aa', '00']);
});
it('should merge chain tips where there is a fork (a parent block has more than one child)' , function() {
it('should merge blocks where there is a fork (a parent block has more than one child)' , function() {
var blocks = ['aa','bb','cc','dd','ee'];
var prevBlocks = ['00','aa','aa','cc','dd'];
@ -62,8 +62,41 @@ describe('Block Service', function() {
expect(blockService._chainTips.length).to.equal(2);
expect(blockService._chainTips.get('ee')).to.deep.equal(['dd', 'cc', 'aa', '00']);
expect(blockService._chainTips.get('bb')).to.deep.equal(['aa', '00']);
});
it('should merge blocks where there is a fork (a parent block has more than one child) and blocks are received out of order' , function() {
var blocks = ['cc','aa','bb','ee','dd'];
var prevBlocks = ['aa','00','aa','dd','cc'];
blocks.forEach(function(n, index) {
var block = { header: { prevHash: new Buffer(prevBlocks[index], 'hex') }, hash: n };
blockService._mergeBlockIntoChainTips(block);
});
expect(blockService._chainTips.length).to.equal(2);
expect(blockService._chainTips.get('ee')).to.deep.equal(['dd', 'cc', 'aa', '00']);
expect(blockService._chainTips.get('bb')).to.deep.equal(['aa', '00']);
});
it('should merge blocks where there is a three-way fork (a parent block has more than one child) and blocks are received out of order' , function() {
var blocks = ['cc','aa','bb','ee','dd'];
var prevBlocks = ['aa','00','aa','dd','aa'];
blocks.forEach(function(n, index) {
var block = { header: { prevHash: new Buffer(prevBlocks[index], 'hex') }, hash: n };
blockService._mergeBlockIntoChainTips(block);
});
expect(blockService._chainTips.length).to.equal(3);
expect(blockService._chainTips.get('ee')).to.deep.equal(['dd', 'aa', '00']);
expect(blockService._chainTips.get('bb')).to.deep.equal(['aa', '00']);
expect(blockService._chainTips.get('cc')).to.deep.equal(['aa', '00']);
});
});