Skip to content

Commit

Permalink
ci test: sync w bitcoin core
Browse files Browse the repository at this point in the history
  • Loading branch information
pinheadmz committed Apr 28, 2019
1 parent d601b6a commit 1a91a55
Show file tree
Hide file tree
Showing 5 changed files with 224 additions and 1 deletion.
11 changes: 11 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,17 @@ jobs:
- v1-dependencies-{{ checksum "package.json" }}
# fallback to using the latest cache if no exact match is found
- v1-dependencies-
# Install latest bitcoind executable and add to PATH
- run: wget https://bitcoincore.org/bin/bitcoin-core-0.17.1/bitcoin-0.17.1-x86_64-linux-gnu.tar.gz
- run: tar -xvf bitcoin-0.17.1-x86_64-linux-gnu.tar.gz
- run: echo 'export PATH=./bitcoin-0.17.1/bin/:$PATH' >> $BASH_ENV
- run: source $BASH_ENV
# Install bcoin and testing utilities
- run: npm install
- run: npm install eslint istanbul@1.1.0-alpha.1 codecov
# Uncomment the following line to test locally with command:
# circleci local execute --job install
# - run: npm run test-ci
- save_cache:
paths:
- node_modules
Expand All @@ -32,6 +41,8 @@ jobs:
steps:
- attach_workspace:
at: .
- run: echo 'export PATH=./bitcoin-0.17.1/bin/:$PATH' >> $BASH_ENV
- run: source $BASH_ENV
- run:
name: Tests with coverage
command: npm run test-ci
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,11 @@
"lint-ci": "eslint $(cat .eslintfiles)",
"lint-file": "eslint",
"test": "bmocha --reporter spec test/*.js",
"bitcoind-test": "bmocha --reporter spec test/bitcoind-sync/*.js",
"test-browser": "NODE_BACKEND=js bmocha --reporter spec test/*.js",
"test-file": "bmocha --reporter spec",
"test-file-browser": "NODE_BACKEND=js bmocha --reporter spec",
"test-ci": "istanbul cover --report lcovonly node_modules/.bin/bmocha -- --reporter spec test/*-test.js"
"test-ci": "istanbul cover --report lcovonly node_modules/.bin/bmocha -- --reporter spec test/*-test.js test/bitcoind-sync/*-test.js"
},
"browser": {
"./lib/hd/nfkd": "./lib/hd/nfkd-compat.js",
Expand Down
3 changes: 3 additions & 0 deletions test/bitcoind-sync/data/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Ignore everything in this dir except this file
*
!.gitignore
75 changes: 75 additions & 0 deletions test/bitcoind-sync/reorg-chain-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/* eslint-env mocha */
/* eslint prefer-arrow-callback: "off" */

'use strict';

const assert = require('../util/assert');
const NodeFactory = require('../util/nodefactory');

const nodeFactory = new NodeFactory();

describe('Sync bcoin and Core through a reorg', function () {
this.timeout(3 * 60 * 60 * 1000);

it('should keep bcoin in sync with core', async () => {
const core = nodeFactory.createCore();
const bcoin = await nodeFactory.createBcoin();

// Core generates 100 blocks
await new Promise(r => setTimeout(r, 2000));
const blocks = await core.rpc(
'generatetoaddress',
[100, 'mfWxJ45yp2SFn7UciZyNpvDKrzbhyfKrY8']
);

// bcoin connects to Core and syncs
await new Promise(r => setTimeout(r, 5000));
await bcoin.rpc(
'addnode',
[`127.0.0.1:${core.ports.port}`, 'add']
);

// Core prompts a reorg by invalidating an old block
// then building a new chain on top of its parent.
// Mine new blocks to different address.
await new Promise(r => setTimeout(r, 5000));
await core.rpc(
'invalidateblock',
[blocks[blocks.length - 5]]
);
await core.rpc(
'generatetoaddress',
[10, 'mrkZVNDhZufJfCSw4nbXAgSUPqroNRPYto']
);

// Output
await new Promise(r => setTimeout(r, 10000));
const coreinfo = await core.rpc(
'getblockchaininfo',
[]
);
const bcoininfo = await bcoin.rpc(
'getblockchaininfo',
[]
);

console.log('Core: ', coreinfo);
console.log('bcoin: ', bcoininfo);

assert.strictEqual(coreinfo.blocks, bcoininfo.blocks);
assert.strictEqual(coreinfo.headers, bcoininfo.headers);
assert.strictEqual(coreinfo.bestblockhash, bcoininfo.bestblockhash);

// Close
await new Promise(r => setTimeout(r, 5000));
await core.rpc(
'stop',
[]
);
await bcoin.rpc(
'stop',
[]
);
await new Promise(r => setTimeout(r, 5000));
});
});
133 changes: 133 additions & 0 deletions test/util/nodefactory.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
'use strict';

const FullNode = require('../../lib/node/fullnode');
const format = require('blgr/lib/format');

const path = require('path');
const bcurl = require('bcurl');
const cp = require('child_process');

class NodeFactory {
constructor() {
this.count = 0;
}

createDir(index) {
const dataDir = path.join(
__dirname,
`../bitcoind-sync/data/datadir_${index}`
);

cp.spawnSync('rm', ['-rf', dataDir]);
cp.spawnSync('mkdir', [dataDir]);

return dataDir;
}

getPorts(index) {
return {
port: 10000 + index,
rpcport: 20000 + index
};
}

initNode() {
this.count += 1;
const index = this.count;
const dataDir = this.createDir(index);
const ports = this.getPorts(index);
const client = bcurl.client({
password: 'x',
port: ports.rpcport
});

const rpc = function (cmd, args) {
return client.execute('', cmd, args);
};

return {
index,
dataDir,
ports,
rpc
};
}

async createBcoin() {
const {index, dataDir, ports, rpc} = this.initNode();

const node = new FullNode({
network: 'regtest',
workers: true,
logLevel: 'spam',
listen: true,
prefix: `${dataDir}`,
memory: false,
port: ports.port,
httpPort: ports.rpcport,
maxOutbound: 1
});

const printStdout = this.printStdout;
node.logger.logger.writeConsole = function(level, module, args) {
printStdout(index, '[' + module + '] ' + format(args, false));
};

await node.ensure();
await node.open();
await node.connect();
node.startSync();

return {index, dataDir, ports, rpc, node};
}

createCore() {
const {index, dataDir, ports, rpc} = this.initNode();

this.spawnSyncPrint(
index,
'bitcoind',
[
`-datadir=${dataDir}`,
'-regtest',
'-rpcpassword=x',
`-rpcport=${ports.rpcport}`,
`-port=${ports.port}`,
'-debug=net'
],
{stdio: 'pipe'}
);

return {index, dataDir, ports, rpc};
}

spawnSyncPrint(id, cmd, arg, opt) {
const proc = cp.spawn(cmd, arg, opt);

proc.stdout.on('data', (data) => {
this.printStdout(id, data);
});

proc.stderr.on('data', (data) => {
this.printStdout(id, data);
});

proc.on('close', (code) => {
return(code);
});

proc.on('error', (data) => {
this.printStdout(id, data);
});
}

printStdout(index, data) {
const header = `${index}: `;
let str = data.toString();
str = str.replace(/\n/g, `\n${header}`);
str = header + str;
console.log(`\x1b[${31 + index}m%s\x1b[0m`, str);
}
}

module.exports = NodeFactory;

0 comments on commit 1a91a55

Please sign in to comment.