diff --git a/lib/indexer/indexer.js b/lib/indexer/indexer.js index 11187771..0628a641 100644 --- a/lib/indexer/indexer.js +++ b/lib/indexer/indexer.js @@ -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; } diff --git a/test/indexer-test.js b/test/indexer-test.js index 61b9acb5..a05dc8c2 100644 --- a/test/indexer-test.js +++ b/test/indexer-test.js @@ -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: {},