2015-09-18 11:55:33 -07:00
|
|
|
'use strict';
|
|
|
|
|
2016-04-08 06:56:08 -07:00
|
|
|
// To run the tests: $ mocha -R spec regtest/p2p.js
|
|
|
|
|
2016-04-07 13:22:54 -07:00
|
|
|
var path = require('path');
|
2015-09-18 11:55:33 -07:00
|
|
|
var index = require('..');
|
|
|
|
var log = index.log;
|
|
|
|
|
|
|
|
var p2p = require('bitcore-p2p');
|
|
|
|
var Peer = p2p.Peer;
|
|
|
|
var Messages = p2p.Messages;
|
|
|
|
var chai = require('chai');
|
2015-10-16 21:56:29 -07:00
|
|
|
var bitcore = require('bitcore-lib');
|
2015-09-18 11:55:33 -07:00
|
|
|
var Transaction = bitcore.Transaction;
|
|
|
|
var BN = bitcore.crypto.BN;
|
|
|
|
var async = require('async');
|
|
|
|
var rimraf = require('rimraf');
|
|
|
|
var bitcoind;
|
|
|
|
|
|
|
|
/* jshint unused: false */
|
|
|
|
var should = chai.should();
|
|
|
|
var assert = chai.assert;
|
|
|
|
var sinon = require('sinon');
|
|
|
|
var BitcoinRPC = require('bitcoind-rpc');
|
|
|
|
var transactionData = [];
|
|
|
|
var blockHashes = [];
|
|
|
|
var txs = [];
|
|
|
|
var client;
|
|
|
|
var messages;
|
|
|
|
var peer;
|
|
|
|
var coinbasePrivateKey;
|
|
|
|
var privateKey = bitcore.PrivateKey();
|
|
|
|
var destKey = bitcore.PrivateKey();
|
|
|
|
var BufferUtil = bitcore.util.buffer;
|
|
|
|
var blocks;
|
|
|
|
|
|
|
|
describe('P2P Functionality', function() {
|
|
|
|
|
|
|
|
before(function(done) {
|
|
|
|
this.timeout(100000);
|
|
|
|
|
2016-04-07 15:59:28 -07:00
|
|
|
// enable regtest
|
|
|
|
bitcore.Networks.enableRegtest();
|
2015-09-18 11:55:33 -07:00
|
|
|
var regtestNetwork = bitcore.Networks.get('regtest');
|
|
|
|
var datadir = __dirname + '/data';
|
|
|
|
|
2016-04-07 11:46:19 -07:00
|
|
|
rimraf(datadir + '/regtest', function(err) {
|
2015-09-18 11:55:33 -07:00
|
|
|
if (err) {
|
|
|
|
throw err;
|
|
|
|
}
|
|
|
|
|
|
|
|
bitcoind = require('../').services.Bitcoin({
|
2016-04-07 11:46:19 -07:00
|
|
|
spawn: {
|
2015-09-18 11:55:33 -07:00
|
|
|
datadir: datadir,
|
2016-04-07 13:22:54 -07:00
|
|
|
exec: path.resolve(__dirname, '../bin/bitcoind')
|
2016-04-07 11:46:19 -07:00
|
|
|
},
|
|
|
|
node: {
|
|
|
|
network: bitcore.Networks.testnet
|
2015-09-18 11:55:33 -07:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
bitcoind.on('error', function(err) {
|
|
|
|
log.error('error="%s"', err.message);
|
|
|
|
});
|
|
|
|
|
|
|
|
log.info('Waiting for Bitcoin Core to initialize...');
|
|
|
|
|
2016-04-07 11:46:19 -07:00
|
|
|
bitcoind.start(function(err) {
|
|
|
|
if (err) {
|
|
|
|
throw err;
|
|
|
|
}
|
2015-09-18 11:55:33 -07:00
|
|
|
log.info('Bitcoind started');
|
|
|
|
|
|
|
|
client = new BitcoinRPC({
|
2016-04-07 11:46:19 -07:00
|
|
|
protocol: 'http',
|
2015-09-18 11:55:33 -07:00
|
|
|
host: '127.0.0.1',
|
2016-04-07 11:46:19 -07:00
|
|
|
port: 30331,
|
2015-09-18 11:55:33 -07:00
|
|
|
user: 'bitcoin',
|
|
|
|
pass: 'local321',
|
|
|
|
rejectUnauthorized: false
|
|
|
|
});
|
|
|
|
|
|
|
|
peer = new Peer({
|
|
|
|
host: '127.0.0.1',
|
|
|
|
port: '18444',
|
|
|
|
network: regtestNetwork
|
|
|
|
});
|
|
|
|
|
|
|
|
messages = new Messages({
|
|
|
|
network: regtestNetwork
|
|
|
|
});
|
|
|
|
|
|
|
|
blocks = 500;
|
|
|
|
|
|
|
|
log.info('Generating ' + blocks + ' blocks...');
|
|
|
|
|
|
|
|
// Generate enough blocks so that the initial coinbase transactions
|
|
|
|
// can be spent.
|
|
|
|
|
|
|
|
setImmediate(function() {
|
|
|
|
client.generate(blocks, function(err, response) {
|
|
|
|
if (err) {
|
|
|
|
throw err;
|
|
|
|
}
|
|
|
|
blockHashes = response.result;
|
|
|
|
|
|
|
|
log.info('Preparing test data...');
|
|
|
|
|
|
|
|
// Get all of the unspent outputs
|
|
|
|
client.listUnspent(0, blocks, function(err, response) {
|
|
|
|
var utxos = response.result;
|
|
|
|
|
|
|
|
async.mapSeries(utxos, function(utxo, next) {
|
|
|
|
async.series([
|
|
|
|
function(finished) {
|
|
|
|
// Load all of the transactions for later testing
|
|
|
|
client.getTransaction(utxo.txid, function(err, txresponse) {
|
|
|
|
if (err) {
|
|
|
|
throw err;
|
|
|
|
}
|
|
|
|
// add to the list of transactions for testing later
|
|
|
|
transactionData.push(txresponse.result.hex);
|
|
|
|
finished();
|
|
|
|
});
|
|
|
|
},
|
|
|
|
function(finished) {
|
|
|
|
// Get the private key for each utxo
|
|
|
|
client.dumpPrivKey(utxo.address, function(err, privresponse) {
|
|
|
|
if (err) {
|
|
|
|
throw err;
|
|
|
|
}
|
|
|
|
utxo.privateKeyWIF = privresponse.result;
|
|
|
|
var tx = bitcore.Transaction();
|
|
|
|
tx.from(utxo);
|
|
|
|
tx.change(privateKey.toAddress());
|
|
|
|
tx.to(destKey.toAddress(), utxo.amount * 1e8 - 1000);
|
|
|
|
tx.sign(bitcore.PrivateKey.fromWIF(utxo.privateKeyWIF));
|
|
|
|
txs.push(tx);
|
|
|
|
finished();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
], next);
|
|
|
|
}, function(err) {
|
|
|
|
if (err) {
|
|
|
|
throw err;
|
|
|
|
}
|
|
|
|
peer.on('ready', function() {
|
|
|
|
log.info('Peer ready');
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
log.info('Connecting to peer');
|
|
|
|
peer.connect();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
after(function(done) {
|
|
|
|
this.timeout(20000);
|
|
|
|
peer.on('disconnect', function() {
|
|
|
|
log.info('Peer disconnected');
|
|
|
|
bitcoind.stop(function(err, result) {
|
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
peer.disconnect();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('will be able to handle many inventory messages and be able to send getdata messages and received the txs', function(done) {
|
|
|
|
this.timeout(100000);
|
|
|
|
|
|
|
|
var usedTxs = {};
|
|
|
|
|
2016-04-07 11:46:19 -07:00
|
|
|
bitcoind.on('tx', function(buffer) {
|
|
|
|
var txFromResult = new Transaction().fromBuffer(buffer);
|
2015-09-18 11:55:33 -07:00
|
|
|
var tx = usedTxs[txFromResult.id];
|
|
|
|
should.exist(tx);
|
2016-04-07 11:46:19 -07:00
|
|
|
buffer.toString('hex').should.equal(tx.serialize());
|
2015-09-18 11:55:33 -07:00
|
|
|
delete usedTxs[tx.id];
|
|
|
|
if (Object.keys(usedTxs).length === 0) {
|
|
|
|
done();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
peer.on('getdata', function(message) {
|
|
|
|
var hash = message.inventory[0].hash;
|
|
|
|
var reversedHash = BufferUtil.reverse(hash).toString('hex');
|
|
|
|
var tx = usedTxs[reversedHash];
|
|
|
|
if (reversedHash === tx.id) {
|
|
|
|
var txMessage = messages.Transaction(tx);
|
|
|
|
peer.sendMessage(txMessage);
|
|
|
|
}
|
|
|
|
});
|
2015-09-18 13:15:52 -07:00
|
|
|
async.whilst(
|
|
|
|
function() {
|
|
|
|
return txs.length > 0;
|
|
|
|
},
|
|
|
|
function(callback) {
|
|
|
|
var tx = txs.pop();
|
|
|
|
usedTxs[tx.id] = tx;
|
|
|
|
var message = messages.Inventory.forTransaction(tx.hash);
|
|
|
|
peer.sendMessage(message);
|
|
|
|
callback();
|
|
|
|
},
|
|
|
|
function(err) {
|
|
|
|
if (err) {
|
|
|
|
throw err;
|
|
|
|
}
|
|
|
|
});
|
2015-09-18 11:55:33 -07:00
|
|
|
});
|
|
|
|
|
|
|
|
});
|