UNPKG

bitcore-node

Version:

A blockchain indexing node with extended capabilities using bitcore

307 lines 14.5 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); const chai_1 = require("chai"); const mongodb_1 = require("mongodb"); const sinon = __importStar(require("sinon")); const block_1 = require("../../../src/models/block"); const coin_1 = require("../../../src/models/coin"); const transaction_1 = require("../../../src/models/transaction"); const chain_state_1 = require("../../../src/providers/chain-state"); const storage_1 = require("../../../src/services/storage"); const test_block_1 = require("../../data/test-block"); const helpers_1 = require("../../helpers"); const index_js_1 = require("../../helpers/index.js"); const unit_1 = require("../../helpers/unit"); describe('Block Model', function () { before(unit_1.unitBeforeHelper); after(unit_1.unitAfterHelper); let addBlockParams = { chain: 'BTC', network: 'regtest', block: test_block_1.TEST_BLOCK, height: 1355, initialSyncComplete: false, processed: true }; describe('addBlock', () => { let sandbox; beforeEach(() => { sandbox = sinon.sandbox.create(); }); afterEach(() => { sandbox.restore(); }); it('should be able to add a block', async () => { let newBlock = Object.assign({ save: () => Promise.resolve() }, block_1.BitcoinBlockStorage, addBlockParams); (0, helpers_1.mockStorage)(newBlock); sandbox.stub(block_1.BitcoinBlockStorage, 'handleReorg').resolves(); sandbox.stub(transaction_1.TransactionStorage, 'batchImport').resolves(); const result = await block_1.BitcoinBlockStorage.addBlock(addBlockParams); (0, chai_1.expect)(result); }); }); describe('BlockModel find options', () => { it('should be able to create query options', () => { const id = new mongodb_1.ObjectID(); const { query, options } = storage_1.Storage.getFindOptions(block_1.BitcoinBlockStorage, { since: id, paging: '_id', limit: 100, direction: -1 }); (0, chai_1.expect)(options.limit).to.be.eq(100); (0, chai_1.expect)(query._id).to.be.deep.eq({ $lt: id }); (0, chai_1.expect)(options.sort).to.be.deep.eq({ _id: -1 }); }); it('should default to descending', () => { const id = new mongodb_1.ObjectID(); const { query, options } = storage_1.Storage.getFindOptions(block_1.BitcoinBlockStorage, { since: id, paging: '_id', limit: 100 }); (0, chai_1.expect)(options.sort).to.be.deep.eq({ _id: -1 }); (0, chai_1.expect)(options.limit).to.be.eq(100); (0, chai_1.expect)(query._id).to.be.deep.eq({ $lt: id }); }); it('should allow ascending', () => { const id = new mongodb_1.ObjectID(); const { query, options } = storage_1.Storage.getFindOptions(block_1.BitcoinBlockStorage, { since: id, paging: '_id', limit: 100, direction: 1 }); (0, chai_1.expect)(options.sort).to.be.deep.eq({ _id: 1 }); (0, chai_1.expect)(options.limit).to.be.eq(100); (0, chai_1.expect)(query._id).to.be.deep.eq({ $gt: id }); }); }); describe('getLocalTip', () => { let sandbox; beforeEach(() => { sandbox = sinon.sandbox.create(); }); afterEach(() => { sandbox.restore(); }); it('should return the new tip', async () => { let newBlock = Object.assign({ save: () => Promise.resolve() }, block_1.BitcoinBlockStorage, addBlockParams); (0, helpers_1.mockStorage)(newBlock); const params = { chain: 'BTC', network: 'regtest' }; const result = await chain_state_1.ChainStateProvider.getLocalTip(params); (0, chai_1.expect)(result.height).to.deep.equal(addBlockParams.height); (0, chai_1.expect)(result.chain).to.deep.equal(addBlockParams.chain); (0, chai_1.expect)(result.network).to.deep.equal(addBlockParams.network); }); }); describe('getPoolInfo', () => { xit('should return pool info given a coinbase string'); }); describe('getLocatorHashes', () => { let sandbox; beforeEach(() => { sandbox = sinon.sandbox.create(); }); afterEach(() => { sandbox.restore(); }); it('should return 65 zeros if there are no processed blocks for the chain and network', async () => { const params = { chain: 'BTC', network: 'regtest' }; const result = await chain_state_1.ChainStateProvider.getLocatorHashes(params); (0, chai_1.expect)(result).to.deep.equal([Array(65).join('0')]); }); }); describe('handleReorg', () => { let sandbox; beforeEach(() => { sandbox = sinon.sandbox.create(); }); afterEach(() => { sandbox.restore(); }); it('should return if localTip hash equals the previous hash', async () => { Object.assign(block_1.BitcoinBlockStorage.collection, (0, index_js_1.mockCollection)(null)); Object.assign(transaction_1.TransactionStorage.collection, (0, index_js_1.mockCollection)(null)); Object.assign(coin_1.CoinStorage.collection, (0, index_js_1.mockCollection)(null)); let blockModelRemoveSpy = block_1.BitcoinBlockStorage.collection.deleteMany; let transactionModelRemoveSpy = transaction_1.TransactionStorage.collection.deleteMany; let coinModelRemoveSpy = coin_1.CoinStorage.collection.deleteMany; let coinModelUpdateSpy = coin_1.CoinStorage.collection.updateMany; const params = { header: { prevHash: '3420349f63d96f257d56dd970f6b9079af9cf2784c267a13b1ac339d47031fe9', hash: '64bfb3eda276ae4ae5b64d9e36c9c0b629bc767fb7ae66f9d55d2c5c8103a929', time: 1526756523, version: 536870912, merkleRoot: '08e23107e8449f02568d37d37aa76e840e55bbb5f100ed8ad257af303db88c08', bits: parseInt('207fffff', 16), nonce: 2 }, chain: 'BTC', network: 'regtest' }; await block_1.BitcoinBlockStorage.handleReorg(params); (0, chai_1.expect)(blockModelRemoveSpy.notCalled).to.be.true; (0, chai_1.expect)(transactionModelRemoveSpy.notCalled).to.be.true; (0, chai_1.expect)(coinModelRemoveSpy.notCalled).to.be.true; (0, chai_1.expect)(coinModelUpdateSpy.notCalled).to.be.true; }); it('should return if localTip height is zero', async () => { let blockModelRemoveSpy = block_1.BitcoinBlockStorage.collection.deleteMany; let transactionModelRemoveSpy = transaction_1.TransactionStorage.collection.deleteMany; let coinModelRemoveSpy = coin_1.CoinStorage.collection.deleteMany; let coinModelUpdateSpy = coin_1.CoinStorage.collection.updateMany; let blockMethodParams = { chain: 'BTC', network: 'regtest', block: test_block_1.TEST_BLOCK, height: 1355 }; let params = Object.assign(block_1.BitcoinBlockStorage, blockMethodParams); await block_1.BitcoinBlockStorage.handleReorg(params); (0, chai_1.expect)(blockModelRemoveSpy.notCalled).to.be.true; (0, chai_1.expect)(transactionModelRemoveSpy.notCalled).to.be.true; (0, chai_1.expect)(coinModelRemoveSpy.notCalled).to.be.true; (0, chai_1.expect)(coinModelUpdateSpy.notCalled).to.be.true; }); it('should call blockModel deleteMany', async () => { (0, helpers_1.mockStorage)({ height: 1, previousBlockHash: '3420349f63d96f257d56dd970f6b9079af9cf2784c267a13b1ac339d47031fe9' }); let blockMethodParams = { chain: 'BTC', network: 'regtest', block: test_block_1.TEST_BLOCK, height: 1355 }; let params = Object.assign(block_1.BitcoinBlockStorage, blockMethodParams); const removeSpy = block_1.BitcoinBlockStorage.collection.deleteMany; await block_1.BitcoinBlockStorage.handleReorg(params); (0, chai_1.expect)(removeSpy.called).to.be.true; }); it('should call transactionModel deleteMany', async () => { (0, helpers_1.mockStorage)({ height: 1, previousBlockHash: '3420349f63d96f257d56dd970f6b9079af9cf2784c267a13b1ac339d47031fe9' }); let blockMethodParams = { chain: 'BTC', network: 'regtest', block: test_block_1.TEST_BLOCK, height: 1355 }; let params = Object.assign(block_1.BitcoinBlockStorage, blockMethodParams); const removeSpy = transaction_1.TransactionStorage.collection.deleteMany; await block_1.BitcoinBlockStorage.handleReorg(params); (0, chai_1.expect)(removeSpy.called).to.be.true; }); it('should call coinModel deleteMany', async () => { (0, helpers_1.mockStorage)({ height: 1, previousBlockHash: '3420349f63d96f257d56dd970f6b9079af9cf2784c267a13b1ac339d47031fe9' }); let blockMethodParams = { chain: 'BTC', network: 'regtest', block: test_block_1.TEST_BLOCK, height: 1355 }; let params = Object.assign(block_1.BitcoinBlockStorage, blockMethodParams); const collectionSpy = storage_1.Storage.db.collection; const removeSpy = coin_1.CoinStorage.collection.deleteMany; await block_1.BitcoinBlockStorage.handleReorg(params); (0, chai_1.expect)(collectionSpy.calledOnceWith('coins')); (0, chai_1.expect)(removeSpy.callCount).to.eq(3); }); it('should call coinModel update', async () => { (0, helpers_1.mockStorage)({ height: 1, previousBlockHash: '3420349f63d96f257d56dd970f6b9079af9cf2784c267a13b1ac339d47031fe9' }); let blockMethodParams = { chain: 'BTC', network: 'regtest', block: test_block_1.TEST_BLOCK, height: 1355 }; let params = Object.assign(block_1.BitcoinBlockStorage, blockMethodParams); const collectionSpy = storage_1.Storage.db.collection; const updateSpy = coin_1.CoinStorage.collection.updateMany; await block_1.BitcoinBlockStorage.handleReorg(params); (0, chai_1.expect)(collectionSpy.calledOnceWith('coins')); (0, chai_1.expect)(updateSpy.called).to.be.true; }); }); describe('_apiTransform', () => { it('should return the transform object with block values', () => { const block = { chain: 'BTC', network: 'mainnet', height: 1, hash: 'abcd', version: 1, merkleRoot: 'deff', time: new Date(), timeNormalized: new Date(), nonce: 1, previousBlockHash: 'aabb', nextBlockHash: 'bbcc', transactionCount: 1, size: 255, bits: 256, reward: 5000000000, processed: true }; const result = block_1.BitcoinBlockStorage._apiTransform(block, { object: true }); (0, chai_1.expect)(result.hash).to.be.equal(block.hash); (0, chai_1.expect)(result.height).to.be.equal(block.height); (0, chai_1.expect)(result.version).to.be.equal(block.version); (0, chai_1.expect)(result.size).to.be.equal(block.size); (0, chai_1.expect)(result.merkleRoot).to.be.equal(block.merkleRoot); (0, chai_1.expect)(result.time).to.equal(block.time); (0, chai_1.expect)(result.timeNormalized).to.equal(block.timeNormalized); (0, chai_1.expect)(result.nonce).to.be.equal(block.nonce); (0, chai_1.expect)(result.bits).to.be.equal(block.bits); (0, chai_1.expect)(result.previousBlockHash).to.be.equal(block.previousBlockHash); (0, chai_1.expect)(result.nextBlockHash).to.be.equal(block.nextBlockHash); (0, chai_1.expect)(result.transactionCount).to.be.equal(block.transactionCount); (0, chai_1.expect)(result).to.not.have.property('processed'); }); }); }); //# sourceMappingURL=block.spec.js.map