Added node reorg integration regtest
This commit is contained in:
parent
06f0593613
commit
9be5db84c9
|
@ -9,6 +9,7 @@ before_install:
|
||||||
- git config --global user.name "BitPay, Inc."
|
- git config --global user.name "BitPay, Inc."
|
||||||
script:
|
script:
|
||||||
- _mocha -R spec integration/regtest.js
|
- _mocha -R spec integration/regtest.js
|
||||||
|
- _mocha -R spec integration/regtest-node.js
|
||||||
- _mocha -R spec --recursive
|
- _mocha -R spec --recursive
|
||||||
cache:
|
cache:
|
||||||
directories:
|
directories:
|
||||||
|
|
|
@ -4,5 +4,3 @@ txindex=1
|
||||||
rpcallowip=127.0.0.1
|
rpcallowip=127.0.0.1
|
||||||
rpcuser=bitcoin
|
rpcuser=bitcoin
|
||||||
rpcpassword=local321
|
rpcpassword=local321
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,157 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
// These tests require bitcoind.js Bitcoin Core bindings to be compiled with
|
||||||
|
// the environment variable BITCOINDJS_ENV=test. This enables the use of regtest
|
||||||
|
// functionality by including the wallet in the build.
|
||||||
|
// To run the tests: $ mocha -R spec integration/regtest.js
|
||||||
|
|
||||||
|
var chainlib = require('chainlib');
|
||||||
|
var log = chainlib.log;
|
||||||
|
|
||||||
|
if (process.env.BITCORENODE_ENV !== 'test') {
|
||||||
|
log.info('Please set the environment variable BITCORENODE_ENV=test and make sure bindings are compiled for testing');
|
||||||
|
process.exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
var chai = require('chai');
|
||||||
|
var bitcore = require('bitcore');
|
||||||
|
var rimraf = require('rimraf');
|
||||||
|
var node;
|
||||||
|
|
||||||
|
var should = chai.should();
|
||||||
|
|
||||||
|
var BitcoinRPC = require('bitcoind-rpc');
|
||||||
|
var BitcoreNode = require('..').Node;
|
||||||
|
var testWIF = 'cSdkPxkAjA4HDr5VHgsebAPDEh9Gyub4HK8UJr2DFGGqKKy4K5sG';
|
||||||
|
var testKey;
|
||||||
|
var client;
|
||||||
|
|
||||||
|
describe('Node Functionality', function() {
|
||||||
|
|
||||||
|
before(function(done) {
|
||||||
|
this.timeout(30000);
|
||||||
|
|
||||||
|
// Add the regtest network
|
||||||
|
bitcore.Networks.remove(bitcore.Networks.testnet);
|
||||||
|
bitcore.Networks.add({
|
||||||
|
name: 'regtest',
|
||||||
|
alias: 'regtest',
|
||||||
|
pubkeyhash: 0x6f,
|
||||||
|
privatekey: 0xef,
|
||||||
|
scripthash: 0xc4,
|
||||||
|
xpubkey: 0x043587cf,
|
||||||
|
xprivkey: 0x04358394,
|
||||||
|
networkMagic: 0xfabfb5da,
|
||||||
|
port: 18444,
|
||||||
|
dnsSeeds: [ ]
|
||||||
|
});
|
||||||
|
|
||||||
|
var datadir = __dirname + '/data';
|
||||||
|
|
||||||
|
testKey = bitcore.PrivateKey(testWIF);
|
||||||
|
|
||||||
|
rimraf(datadir + '/regtest', function(err) {
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
|
||||||
|
var configuration = {
|
||||||
|
datadir: datadir,
|
||||||
|
network: 'regtest'
|
||||||
|
};
|
||||||
|
|
||||||
|
node = new BitcoreNode(configuration);
|
||||||
|
|
||||||
|
node.on('error', function(err) {
|
||||||
|
log.error(err);
|
||||||
|
});
|
||||||
|
|
||||||
|
node.on('ready', function() {
|
||||||
|
|
||||||
|
client = new BitcoinRPC({
|
||||||
|
protocol: 'http',
|
||||||
|
host: '127.0.0.1',
|
||||||
|
port: 18332,
|
||||||
|
user: 'bitcoin',
|
||||||
|
pass: 'local321'
|
||||||
|
});
|
||||||
|
|
||||||
|
node.on('synced', function() {
|
||||||
|
//todo: refactor to remove the event listener
|
||||||
|
if (node.chain.tip.__height === 150) {
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
client.generate(150, function(err, response) {
|
||||||
|
if (err) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
after(function(done) {
|
||||||
|
this.timeout(20000);
|
||||||
|
node.db.bitcoind.stop(function(err, result) {
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('bitcoin core daemon reorgs', function() {
|
||||||
|
|
||||||
|
before(function(done) {
|
||||||
|
client.getBlockCount(function(err, response) {
|
||||||
|
if (err) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
var count = response.result;
|
||||||
|
client.getBlockHash(count, function(err, response) {
|
||||||
|
if (err) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
var blockHash = response.result;
|
||||||
|
client.invalidateBlock(blockHash, function(err, response) {
|
||||||
|
if (err) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
client.getBlockCount(function(err, response) {
|
||||||
|
if (err) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
response.result.should.equal(count - 1);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('will handle a reorganization', function(done) {
|
||||||
|
|
||||||
|
node.db.bitcoind.on('tip', function(height) {
|
||||||
|
height.should.equal(151);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
// We need to add a transaction to the mempool so that the next block will
|
||||||
|
// have a different hash as the hash has been invalidated.
|
||||||
|
client.sendToAddress(testKey.toAddress().toString(), 10, function(err) {
|
||||||
|
if (err) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
client.generate(2, function(err, response) {
|
||||||
|
if (err) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
29
lib/node.js
29
lib/node.js
|
@ -123,8 +123,6 @@ Node.prototype._syncBitcoindAncestor = function(block, done) {
|
||||||
done(err);
|
done(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('getHashes done');
|
|
||||||
|
|
||||||
// Create a hash map for faster lookups
|
// Create a hash map for faster lookups
|
||||||
var currentHashesMap = {};
|
var currentHashesMap = {};
|
||||||
var length = currentHashes.length;
|
var length = currentHashes.length;
|
||||||
|
@ -139,7 +137,6 @@ Node.prototype._syncBitcoindAncestor = function(block, done) {
|
||||||
|
|
||||||
while(ancestorHash && !currentHashesMap[ancestorHash]) {
|
while(ancestorHash && !currentHashesMap[ancestorHash]) {
|
||||||
var blockIndex = self.bitcoind.getBlockIndex(ancestorHash);
|
var blockIndex = self.bitcoind.getBlockIndex(ancestorHash);
|
||||||
console.log(blockIndex);
|
|
||||||
ancestorHash = blockIndex ? blockIndex.prevHash : null;
|
ancestorHash = blockIndex ? blockIndex.prevHash : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,8 +164,9 @@ Node.prototype._syncBitcoindRewind = function(block, done) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
self._syncBitcoindAncestor(block, function(err, ancestorHash) {
|
self._syncBitcoindAncestor(block, function(err, ancestorHash) {
|
||||||
console.log('ancestorHash', ancestorHash);
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
// Rewind the chain to the common ancestor
|
// Rewind the chain to the common ancestor
|
||||||
async.whilst(
|
async.whilst(
|
||||||
function() {
|
function() {
|
||||||
|
@ -196,7 +194,6 @@ Node.prototype._syncBitcoindRewind = function(block, done) {
|
||||||
self.chain.tip = previousTip;
|
self.chain.tip = previousTip;
|
||||||
self.chain.saveMetadata();
|
self.chain.saveMetadata();
|
||||||
self.chain.emit('removeblock', tip);
|
self.chain.emit('removeblock', tip);
|
||||||
console.log('removeblock', tip.hash);
|
|
||||||
removeDone();
|
removeDone();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -216,8 +213,6 @@ Node.prototype._syncBitcoindRewind = function(block, done) {
|
||||||
Node.prototype._syncBitcoind = function() {
|
Node.prototype._syncBitcoind = function() {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
console.log('_syncBitcoind');
|
|
||||||
|
|
||||||
if (self.bitcoindSyncing) {
|
if (self.bitcoindSyncing) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -232,8 +227,6 @@ Node.prototype._syncBitcoind = function() {
|
||||||
var height;
|
var height;
|
||||||
|
|
||||||
async.whilst(function() {
|
async.whilst(function() {
|
||||||
console.log('height', self.chain.tip.__height);
|
|
||||||
console.log('bitcoindHeight', self.bitcoindHeight);
|
|
||||||
height = self.chain.tip.__height;
|
height = self.chain.tip.__height;
|
||||||
return height < self.bitcoindHeight && !self.stopping;
|
return height < self.bitcoindHeight && !self.stopping;
|
||||||
}, function(done) {
|
}, function(done) {
|
||||||
|
@ -243,6 +236,7 @@ Node.prototype._syncBitcoind = function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
var block = self.Block.fromBuffer(blockBuffer);
|
var block = self.Block.fromBuffer(blockBuffer);
|
||||||
|
|
||||||
if (block.prevHash === self.chain.tip.hash) {
|
if (block.prevHash === self.chain.tip.hash) {
|
||||||
|
|
||||||
// This block appends to the current chain tip and we can
|
// This block appends to the current chain tip and we can
|
||||||
|
@ -374,6 +368,10 @@ Node.prototype._loadConsensus = function(config) {
|
||||||
genesisBlock = config.genesis;
|
genesisBlock = config.genesis;
|
||||||
} else if (config.network === 'testnet') {
|
} else if (config.network === 'testnet') {
|
||||||
genesisBlock = genesis.testnet;
|
genesisBlock = genesis.testnet;
|
||||||
|
} else if (config.network === 'regtest') {
|
||||||
|
// initializeBitcoind will set the genesis block later in the chain
|
||||||
|
// todo: we should be able to refactor since the genesis is set later
|
||||||
|
genesisBlock = null;
|
||||||
} else {
|
} else {
|
||||||
genesisBlock = genesis.livenet;
|
genesisBlock = genesis.livenet;
|
||||||
}
|
}
|
||||||
|
@ -404,6 +402,17 @@ Node.prototype._initialize = function() {
|
||||||
// Set the current chain height
|
// Set the current chain height
|
||||||
var info = self.bitcoind.getInfo();
|
var info = self.bitcoind.getInfo();
|
||||||
self.bitcoindHeight = info.blocks;
|
self.bitcoindHeight = info.blocks;
|
||||||
|
|
||||||
|
// Get the genesis block
|
||||||
|
self.bitcoind.getBlock(0, function(err, block) {
|
||||||
|
self.chain.genesis = self.Block.fromBuffer(block);
|
||||||
|
self.db.initialize();
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
this.bitcoind.on('open', function(status) {
|
||||||
|
log.info('Bitcoin Core Daemon Status:', status);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Notify that there is a new tip
|
// Notify that there is a new tip
|
||||||
|
|
Loading…
Reference in New Issue