diff --git a/README.md b/README.md index 8dbc5d61..bdaf110e 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ var BitcoinNode = require('bitcoind.js'); var configuration = { datadir: '~/.bitcoin', - testnet: true + network: 'testnet' }; var node = new BitcoinNode(configuration); @@ -110,7 +110,7 @@ $ tail -f ~/.bitcoin/debug.log ## Building -There are two main parts of the build, compiling Bitcoin Core and the Node.js bindings. You can run both by using `npm install` and `npm run debug_install`. +There are two main parts of the build, compiling Bitcoin Core and the Node.js bindings. You can run both by using `npm install` and set environment variable, $BITCOINDJS_ENV to 'test' or 'debug'. Both 'test' and 'debug' build libbitcoind with debug symbols whereas 'test' adds wallet capability so that regtest can be used. ### Node.js Bindings @@ -130,6 +130,11 @@ To be able to debug you'll need to have `gdb` and `node` compiled for debugging $ gdb --args node_g path/to/example.js ``` +To run mocha from within gdb (notice _mocha and not mocha so that the tests run in the same process): +```bash +$ gdb --args node /path/to/_mocha -R spec integration/index.js +``` + To run integration tests against testnet or livenet data: ```bash @@ -161,7 +166,7 @@ Most of all the dependencies for building Bitcoin Core are needed, for more info #### Shared Library Patch -To provide native bindings to JavaScript *(or any other language for that matter)*, Bitcoin code, itself, must be linkable. Currently, Bitcoin Core provides a JSON RPC interface to bitcoind as well as a shared library for script validation *(and hopefully more)* called libbitcoinconsensus. There is a node module, [node-libbitcoinconsensus](https://github.com/bitpay/node-libbitcoinconsensus), that exposes these methods. While these interfaces are useful for several use cases, there are additional use cases that are not fulfilled, and being able to implement customized interfaces is necessary. To be able to do this a few simple changes need to be made to Bitcoin Core to compile as a shared library. +To provide native bindings to JavaScript *(or any other language for that matter)*, Bitcoin code, itself, must be linkable. Currently, Bitcoin Core provides a JSON RPC interface to bitcoind as well as a shared library for script validation *(and hopefully more)* called libbitcoinconsensus. There is a node module, [node-libbitcoinconsensus](https://github.com/bitpay/node-libbitcoinconsensus), that exposes these methods. While these interfaces are useful for several use cases, there are additional use cases that are not fulfilled, and being able to implement customized interfaces is necessary. To be able to do this a few simple changes need to be made to Bitcoin Core to compile as a shared library. The patch is located at `etc/bitcoin.patch` and adds a configure option `--enable-daemonlib` to compile all object files with `-fPIC` (Position Independent Code - needed to create a shared object), exposes leveldb variables and objects, exposes the threadpool to the bindings, and conditionally includes the main function. @@ -176,7 +181,7 @@ $ cd /path/to/bitcoind.js $ ./bin/build-libbitcoind ``` -The first argument is 'debug', this will compile node bindings and bitcoind with debug flags. The `PATCH_VERSION` file dictates what version/tag the patch goes clean against. +The `PATCH_VERSION` file dictates what version/tag the patch goes clean against. There is a config_options.sh that has the configure options used to build libbitcoind. `make` will then compile `libbitcoind/src/.libs/libbitcoind.{so|dylib}`. This will completely ignore compiling tests, QT object files and the wallet features in `bitcoind/libbitcoind.{so|dylib}`. diff --git a/benchmarks/index.js b/benchmarks/index.js index 574d512c..436ccabf 100644 --- a/benchmarks/index.js +++ b/benchmarks/index.js @@ -28,7 +28,7 @@ var fixtureData = { var bitcoind = require('../').daemon({ datadir: process.env.BITCOINDJS_DIR || '~/.bitcoin', - testnet: true + network: 'testnet' }); bitcoind.on('error', function(err) { diff --git a/bin/build-libbitcoind b/bin/build-libbitcoind index b73d2d75..dbd1dcf9 100755 --- a/bin/build-libbitcoind +++ b/bin/build-libbitcoind @@ -3,6 +3,7 @@ set -e root_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/.." cd "${root_dir}" +options=`cat ${root_dir}/bin/config_options.sh` os_dir=$(./platform/os.sh osdir) @@ -10,8 +11,13 @@ os_dir=$(./platform/os.sh osdir) export LD_LIBRARY_PATH="${root_dir}/libbitcoind/src/leveldb":"${os_dir}":$LD_LIBRARY_PATH debug= -if test x"$1" = x'debug'; then - debug=--enable-debug +if [ "${BITCOINDJS_ENV}" == "debug" ]; then + options=`cat ${root_dir}/bin/config_options_debug.sh` +fi + +test= +if [ "${BITCOINDJS_ENV}" == "test" ]; then + options=`cat ${root_dir}/bin/config_options_test.sh` fi btc_dir="${root_dir}/libbitcoind" @@ -50,12 +56,11 @@ if [ "${only_make}" = false ]; then echo './autogen.sh' ./autogen.sh - options=`cat ${root_dir}/bin/config_options.sh` - full_options="${options}${os_dir} ${debug}" - echo "running the configure script with the following options:\n :::[\"${full_options}\"]:::" - ${full_options} fi +full_options="${options}${os_dir}" +echo "running the configure script with the following options:\n :::[\"${full_options}\"]:::" +${full_options} echo 'make V=1' make V=1 diff --git a/bin/config_options_debug.sh b/bin/config_options_debug.sh new file mode 100644 index 00000000..b8f11c73 --- /dev/null +++ b/bin/config_options_debug.sh @@ -0,0 +1,2 @@ +./configure --enable_debug --enable-tests=no --enable-daemonlib --with-gui=no --without-qt --without-miniupnpc --without-bdb --disable-wallet --without-utils --prefix= + diff --git a/bin/config_options_test.sh b/bin/config_options_test.sh new file mode 100644 index 00000000..8ba4a8ae --- /dev/null +++ b/bin/config_options_test.sh @@ -0,0 +1,2 @@ +./configure --enable-tests=no --enable-daemonlib --with-gui=no --without-qt --without-miniupnpc --prefix= + diff --git a/example/daemon.js b/example/daemon.js new file mode 100644 index 00000000..d5dcf871 --- /dev/null +++ b/example/daemon.js @@ -0,0 +1,15 @@ +'use strict'; + +process.title = 'bitcoind.js'; + +var daemon = require('../').daemon({ + directory: process.env.BITCOINDJS_DIR || '~/.bitcoin' +}); + +daemon.on('error', function(err) { + daemon.log('error="%s"', err.message); +}); + +daemon.on('open', function(status) { + daemon.log('status="%s"', status); +}); diff --git a/lib/daemon.js b/lib/daemon.js index 5295c925..f1d18045 100644 --- a/lib/daemon.js +++ b/lib/daemon.js @@ -37,14 +37,6 @@ function Daemon(options) { this.options = options || {}; - if (typeof this.options === 'string') { - this.options = { datadir: this.options }; - } - - if (this.options.directory) { - this.options.datadir = this.options.directory; - delete this.options.directory; - } if (!this.options.datadir) { this.options.datadir = '~/.bitcoind.js'; @@ -54,7 +46,13 @@ function Daemon(options) { this.datadir = this.options.datadir; this.config = this.datadir + '/bitcoin.conf'; - this.network = Daemon[this.options.testnet ? 'testnet' : 'livenet']; + this.network = Daemon['livenet']; + + if (this.options.network === 'testnet') { + this.network = Daemon['testnet']; + } else if(this.options.network === 'regtest') { + this.network = Daemon['regtest']; + } if (!fs.existsSync(this.datadir)) { mkdirp.sync(this.datadir); @@ -83,7 +81,6 @@ function Daemon(options) { fs.writeFileSync(data + peers); } - // Copy config into testnet dir if (this.network.name === 'testnet') { if (!fs.existsSync(this.datadir + '/testnet3')) { fs.mkdirSync(this.datadir + '/testnet3'); @@ -93,6 +90,15 @@ function Daemon(options) { fs.readFileSync(this.config)); } + if (this.network.name === 'regtest') { + if (!fs.existsSync(this.datadir + '/regtest')) { + fs.mkdirSync(this.datadir + '/regtest'); + } + fs.writeFileSync( + this.datadir + '/regtest/bitcoin.conf', + fs.readFileSync(this.config)); + } + Object.keys(exports).forEach(function(key) { self[key] = exports[key]; }); @@ -120,6 +126,13 @@ Daemon.testnet = { ] }; +Bitcoin.regtest = { + name: 'regtest', + peers: [ + // hardcoded peers + ] +}; + // Make sure signal handlers are not overwritten Daemon._signalQueue = []; Daemon._processOn = process.on; diff --git a/package.json b/package.json index 74b63809..f8e0794e 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,6 @@ "preinstall": "./bin/build-libbitcoind", "install": "./bin/build-bindings", "start": "node example", - "debug_install": "./bin/build-libbitcoind debug && ./bin/build-bindings debug", "test": "NODE_ENV=test mocha --recursive", "coverage": "istanbul cover _mocha -- --recursive" }, diff --git a/src/bitcoindjs.cc b/src/bitcoindjs.cc index c349de82..82a035c8 100644 --- a/src/bitcoindjs.cc +++ b/src/bitcoindjs.cc @@ -76,6 +76,7 @@ static volatile bool shutdown_complete = false; static char *g_data_dir = NULL; static bool g_rpc = false; static bool g_testnet = false; +static bool g_regtest = false; static bool g_txindex = false; /** @@ -105,6 +106,7 @@ struct async_node_data { std::string datadir; bool rpc; bool testnet; + bool regtest; bool txindex; Eternal callback; }; @@ -298,6 +300,7 @@ NAN_METHOD(StartBitcoind) { std::string datadir = std::string(""); bool rpc = false; bool testnet = false; + bool regtest = false; bool txindex = false; if (args.Length() >= 2 && args[0]->IsObject() && args[1]->IsFunction()) { @@ -309,8 +312,14 @@ NAN_METHOD(StartBitcoind) { if (options->Get(NanNew("rpc"))->IsBoolean()) { rpc = options->Get(NanNew("rpc"))->ToBoolean()->IsTrue(); } - if (options->Get(NanNew("testnet"))->IsBoolean()) { - testnet = options->Get(NanNew("testnet"))->ToBoolean()->IsTrue(); + if (options->Get(NanNew("network"))->IsString()) { + String::Utf8Value network_(options->Get(NanNew("network"))->ToString()); + std::string network = std::string(*network_); + if (network == "testnet") { + testnet = true; + } else if (network == "regtest") { + regtest = true; + } } if (options->Get(NanNew("txindex"))->IsBoolean()) { txindex = options->Get(NanNew("txindex"))->ToBoolean()->IsTrue(); @@ -337,6 +346,7 @@ NAN_METHOD(StartBitcoind) { data->datadir = datadir; data->rpc = rpc; data->testnet = testnet; + data->regtest = regtest; data->txindex = txindex; Eternal eternal(isolate, callback); @@ -370,6 +380,7 @@ async_start_node(uv_work_t *req) { } g_rpc = (bool)data->rpc; g_testnet = (bool)data->testnet; + g_regtest = (bool)data->regtest; g_txindex = (bool)data->txindex; tcgetattr(STDIN_FILENO, &orig_termios); start_node(); @@ -475,6 +486,11 @@ start_node_thread(void) { argc++; } + if (g_regtest) { + argv[argc] = (char *)"-regtest"; + argc++; + } + argv[argc] = (char *)"-txindex"; argc++;