indexer: check that blocks are connected

There was a rare case that a block could be incorrectly added to
the indexer if the indexer was disabled during a reorg to a height
that matched the height that was expected, and the `sync` method
for the indexer wasn't called that would detect the reorg.
This commit is contained in:
Braydon Fuller 2019-04-23 15:55:56 -07:00
parent cede31d86f
commit ed06c2184d
No known key found for this signature in database
GPG Key ID: F24F232D108B3AD4
2 changed files with 127 additions and 0 deletions

View File

@ -286,9 +286,20 @@ class Indexer extends EventEmitter {
// instead of reading that information again.
if (meta && block && view) {
if (meta.height === this.height + 1) {
// Make sure that the block is connected to
// the indexer chain.
const prev = await this.getBlockMeta(this.height);
if (prev.hash.compare(block.prevBlock) !== 0)
return false;
await this._addBlock(meta, block, view);
return true;
} else if (meta.height === this.height) {
// Make sure that this is the current block.
const current = await this.getBlockMeta(this.height);
if (current.hash.compare(block.hash()) !== 0)
return false;
await this._removeBlock(meta, block, view);
return true;
}

View File

@ -119,6 +119,122 @@ describe('Indexer', function() {
});
describe('Unit', function() {
it('should connect block', async () => {
const indexer = new AddrIndexer({
blocks: {},
chain: {}
});
indexer.height = 9;
indexer.getBlockMeta = (height) => {
return {
hash: Buffer.alloc(32, 0x00),
height: height
};
};
let called = false;
indexer._addBlock = async () => {
called = true;
};
const meta = {height: 10};
const block = {prevBlock: Buffer.alloc(32, 0x00)};
const view = {};
const connected = await indexer._syncBlock(meta, block, view);
assert.equal(connected, true);
assert.equal(called, true);
});
it('should not connect block', async () => {
const indexer = new AddrIndexer({
blocks: {},
chain: {}
});
indexer.height = 9;
indexer.getBlockMeta = (height) => {
return {
hash: Buffer.alloc(32, 0x02),
height: height
};
};
let called = false;
indexer._addBlock = async () => {
called = true;
};
const meta = {height: 10};
const block = {prevBlock: Buffer.alloc(32, 0x01)};
const view = {};
const connected = await indexer._syncBlock(meta, block, view);
assert.equal(connected, false);
assert.equal(called, false);
});
it('should disconnect block', async () => {
const indexer = new AddrIndexer({
blocks: {},
chain: {}
});
indexer.height = 9;
indexer.getBlockMeta = (height) => {
return {
hash: Buffer.alloc(32, 0x00),
height: height
};
};
let called = false;
indexer._removeBlock = async () => {
called = true;
};
const meta = {height: 9};
const block = {hash: () => Buffer.alloc(32, 0x00)};
const view = {};
const connected = await indexer._syncBlock(meta, block, view);
assert.equal(connected, true);
assert.equal(called, true);
});
it('should not disconnect block', async () => {
const indexer = new AddrIndexer({
blocks: {},
chain: {}
});
indexer.height = 9;
indexer.getBlockMeta = (height) => {
return {
hash: Buffer.alloc(32, 0x01),
height: height
};
};
let called = false;
indexer._removeBlock = async () => {
called = true;
};
const meta = {height: 9};
const block = {hash: () => Buffer.alloc(32, 0x02)};
const view = {};
const connected = await indexer._syncBlock(meta, block, view);
assert.equal(connected, false);
assert.equal(called, false);
});
it('should not index transaction w/ invalid address', async () => {
const indexer = new AddrIndexer({
blocks: {},