bitcore-node
Version:
A blockchain indexing node with extended capabilities using bitcore
250 lines • 11.6 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const chai_1 = require("chai");
const config_1 = __importDefault(require("../../src/config"));
const block_1 = require("../../src/models/block");
const coin_1 = require("../../src/models/coin");
const transaction_1 = require("../../src/models/transaction");
const p2p_1 = require("../../src/modules/bitcoin/p2p");
const VerificationPeer_1 = require("../../src/modules/bitcoin/VerificationPeer");
const rpc_1 = require("../../src/rpc");
const config_2 = require("../../src/services/config");
const utils_1 = require("../../src/utils");
const helpers_1 = require("../helpers");
const integration_1 = require("../helpers/integration");
const chain = 'BTC';
const network = 'regtest';
const address = '2MuYKLUaKCenkEpwPkWUwYpBoDBNA2dgY3t';
const chainConfig = config_1.default.chains[chain][network];
const creds = chainConfig.rpc;
const rpc = new rpc_1.AsyncRPC(creds.username, creds.password, creds.host, creds.port);
async function sendBitcoin() {
try {
await rpc.sendtoaddress(address, 0.1);
console.log('Sending');
}
catch (e) {
// Handle insufficent balance issues
console.log('Generating blocks');
const ourAddress = await rpc.getnewaddress('');
await rpc.call('generatetoaddress', [130, ourAddress]);
await (0, utils_1.wait)(5000);
console.log('Sending after generating');
await rpc.sendtoaddress(address, 0.1);
}
}
function addBlock1() {
return block_1.BitcoinBlockStorage.collection.insertOne({
chain,
network,
height: 8976158,
hash: '0x9997699519d116dfa89256d0f6ebd1737db13adca583dc80dbd533d90083961c',
version: 100,
merkleRoot: 'a2262b524615b6d2f409784ceff898fd46bdde6a584269788c41f26ac4b4919e',
time: new Date(1526326784),
timeNormalized: new Date(1526326784),
transactionCount: 1,
reward: 50,
nonce: 3,
previousBlockHash: '64bfb3eda276ae4ae5b64d9e36c9c0b629bc767fb7ae66f9d55d2c5c8103a929',
nextBlockHash: '0xddae2bf21fb5836dec837671afd7bea1cc49d7111462e803ed3efc10570f1858',
size: 264,
bits: parseInt('207fffff', 16),
processed: true
});
}
function addTx() {
return transaction_1.TransactionStorage.collection.insertOne({
chain,
network,
txid: '0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098',
blockHash: '0x9997699519d116dfa89256d0f6ebd1737db13adca583dc80dbd533d90083961c',
blockHeight: 8976158,
blockTime: new Date('2009-01-09T02:54:25.000Z'),
blockTimeNormalized: new Date('2009-01-09T02:54:25.000Z'),
coinbase: true,
fee: 0,
inputCount: 1,
locktime: 0,
outputCount: 1,
size: 134,
value: 5000000000.0,
wallets: []
});
}
function addCoin() {
return coin_1.CoinStorage.collection.insertOne({
chain,
network,
mintIndex: 0,
mintTxid: '0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098',
address: '12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX',
coinbase: true,
mintHeight: 1,
script: Buffer.from('QQSWtTjoU1GccmoskeYewRYArhOQgTpifGb7i+eUe+Y8Utp1iTeVFdTgpgT4FBeB5iKUchFmv2Iec6gsvyNCyFjurA=='),
spentHeight: -2,
spentTxid: '',
value: 5000000000.0,
wallets: []
});
}
describe('VerificationPeer', function () {
const suite = this;
this.timeout(500000);
before(integration_1.intBeforeHelper);
after(async () => (0, integration_1.intAfterHelper)(suite));
beforeEach(async () => {
await (0, helpers_1.resetDatabase)();
});
it('should not save any mempoool transactions', async () => {
const chainConfig = config_2.Config.chainConfig({ chain, network });
const worker = new VerificationPeer_1.VerificationPeer({ chain, network, chainConfig });
await worker.connect();
const sawTx = new Promise(r => {
worker.events.on('transaction', r);
});
await sendBitcoin();
await sawTx;
const txCount = await transaction_1.TransactionStorage.collection.countDocuments({ chain, network });
(0, chai_1.expect)(txCount).to.be.eq(0);
worker.disconnect();
});
it('should save any mempoool transactions', async () => {
const chainConfig = config_2.Config.chainConfig({ chain, network });
const worker = new p2p_1.BitcoinP2PWorker({ chain, network, chainConfig });
worker.isSyncingNode = true;
worker.isSyncing = true;
await worker.connect();
const sawTx = new Promise(r => {
worker.events.on('transaction', r);
});
await sendBitcoin();
await sawTx;
const txCount = await transaction_1.TransactionStorage.collection.countDocuments({ chain, network });
(0, chai_1.expect)(txCount).to.be.gt(0);
worker.disconnect();
});
it('should detect a fault in a series of blocks', async () => {
const worker = new VerificationPeer_1.VerificationPeer({ chain, network, chainConfig });
await worker.connect();
await addBlock1();
await addTx();
await addCoin();
await block_1.BitcoinBlockStorage.collection.updateOne({ hash: '0x9997699519d116dfa89256d0f6ebd1737db13adca583dc80dbd533d90083961c' }, { $unset: { nextBlockHash: '' } });
const tip = 8976159;
const verified = await worker.validateDataForBlock(8976158, tip, true);
(0, chai_1.expect)(verified.success == false);
(0, chai_1.expect)(verified.errors.length).to.eq(1);
(0, chai_1.expect)(verified.errors[0].type).to.eq('CORRUPTED_BLOCK');
(0, chai_1.expect)(verified.errors[0].payload.txCount).to.eq(1);
(0, chai_1.expect)(verified.errors[0].payload.foundTxs).to.eq(1);
await worker.disconnect();
});
it('should detect a missing transaction', async () => {
const worker = new VerificationPeer_1.VerificationPeer({ chain, network, chainConfig });
await worker.connect();
await addBlock1();
await addCoin();
const tip = 8976159;
const verified = await worker.validateDataForBlock(8976158, tip, true);
(0, chai_1.expect)(verified.success == false);
(0, chai_1.expect)(verified.errors.length).to.eq(1);
(0, chai_1.expect)(verified.errors[0].type).to.eq('CORRUPTED_BLOCK');
(0, chai_1.expect)(verified.errors[0].payload.txCount).to.eq(1);
(0, chai_1.expect)(verified.errors[0].payload.foundTxs).to.eq(0);
await worker.disconnect();
});
it('should detect a dupe transaction', async () => {
const worker = new VerificationPeer_1.VerificationPeer({ chain, network, chainConfig });
await worker.connect();
await addBlock1();
await addTx();
await addTx();
await addCoin();
const tip = 8976159;
const verified = await worker.validateDataForBlock(8976158, tip, true);
(0, chai_1.expect)(verified.success == false);
(0, chai_1.expect)(verified.errors.length).to.eq(2);
(0, chai_1.expect)(verified.errors[0].type).to.eq('CORRUPTED_BLOCK');
(0, chai_1.expect)(verified.errors[0].payload.txCount).to.eq(1);
(0, chai_1.expect)(verified.errors[0].payload.foundTxs).to.eq(2);
(0, chai_1.expect)(verified.errors[1].type).to.eq('DUPE_TRANSACTION');
(0, chai_1.expect)(verified.errors[1].payload.tx.txid).to.eq('0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098');
await worker.disconnect();
});
it('should detect a missing transaction output', async () => {
const worker = new VerificationPeer_1.VerificationPeer({ chain, network, chainConfig });
await worker.connect();
await addBlock1();
await addTx();
const tip = 8976159;
const verified = await worker.validateDataForBlock(8976158, tip, true);
(0, chai_1.expect)(verified.success == false);
(0, chai_1.expect)(verified.errors.length).to.eq(1);
(0, chai_1.expect)(verified.errors[0].type).to.eq('MISSING_COIN_FOR_TXID');
(0, chai_1.expect)(verified.errors[0].payload.txid).to.eq('0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098');
await worker.disconnect();
});
it('should detect a dupe transaction output', async () => {
const worker = new VerificationPeer_1.VerificationPeer({ chain, network, chainConfig });
await worker.connect();
await addBlock1();
await addTx();
await addCoin();
await addCoin();
const tip = 8976159;
const verified = await worker.validateDataForBlock(8976158, tip, true);
(0, chai_1.expect)(verified.success == false);
(0, chai_1.expect)(verified.errors.length).to.eq(1);
(0, chai_1.expect)(verified.errors[0].type).to.eq('DUPE_COIN');
(0, chai_1.expect)(verified.errors[0].payload.coin.mintTxid).to.eq('0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098');
await worker.disconnect();
});
it('should detect a missing block', async () => {
const worker = new VerificationPeer_1.VerificationPeer({ chain, network, chainConfig });
await worker.connect();
await addTx();
await addCoin();
const tip = 8976159;
const verified = await worker.validateDataForBlock(8976158, tip, true);
(0, chai_1.expect)(verified.success == false);
(0, chai_1.expect)(verified.errors.length).to.eq(1);
(0, chai_1.expect)(verified.errors[0].type).to.eq('MISSING_BLOCK');
(0, chai_1.expect)(verified.errors[0].payload.blockNum).to.eq(8976158);
await worker.disconnect();
});
it('should detect a dupe block', async () => {
const worker = new VerificationPeer_1.VerificationPeer({ chain, network, chainConfig });
await worker.connect();
await addBlock1();
await addBlock1();
await addTx();
await addCoin();
const tip = 8976159;
const verified = await worker.validateDataForBlock(8976158, tip, true);
(0, chai_1.expect)(verified.success == false);
(0, chai_1.expect)(verified.errors.length).to.eq(2);
(0, chai_1.expect)(verified.errors[0].type).to.eq('DUPE_BLOCKHEIGHT');
(0, chai_1.expect)(verified.errors[0].payload.blockNum).to.eq(8976158);
(0, chai_1.expect)(verified.errors[1].type).to.eq('DUPE_BLOCKHASH');
(0, chai_1.expect)(verified.errors[1].payload.blockNum).to.eq(8976158);
await worker.disconnect();
});
it('should handle non-linear scanning by ignoring previousBlockHash', async () => {
const worker = new VerificationPeer_1.VerificationPeer({ chain, network, chainConfig });
await worker.connect();
await addBlock1();
await addTx();
await addCoin();
await block_1.BitcoinBlockStorage.collection.updateOne({ hash: '0x9997699519d116dfa89256d0f6ebd1737db13adca583dc80dbd533d90083961c' }, { $set: { previousBlockHash: 'abcdefg' } });
const tip = 8976159;
await worker.validateDataForBlock(8976154, tip, true);
const verified = await worker.validateDataForBlock(8976158, tip, true);
(0, chai_1.expect)(verified.success == true);
await worker.disconnect();
});
});
//# sourceMappingURL=verification.spec.js.map