bitcore-node
Version:
A blockchain indexing node with extended capabilities using bitcore
307 lines • 14.5 kB
JavaScript
;
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