From f4061037b6bef481ef794dd88e9ff9ddb4b00621 Mon Sep 17 00:00:00 2001 From: Braydon Fuller Date: Fri, 31 Jul 2015 11:40:15 -0400 Subject: [PATCH] Update name to Bitcore Node --- .travis.yml | 2 +- README.md | 31 +- bin/build-libbitcoind | 6 +- binding.gyp | 4 +- example/index.js | 2 +- example/node.js | 2 +- index.js | 4 +- index_stripped.js | 1 - integration/regtest.js | 4 +- lib/daemon.js | 110 +++--- package.json | 12 +- src/bitcoindjs_stripped.cc | 517 -------------------------- src/bitcoindjs_stripped.h | 19 - src/{bitcoindjs.cc => libbitcoind.cc} | 4 +- src/{bitcoindjs.h => libbitcoind.h} | 0 15 files changed, 89 insertions(+), 629 deletions(-) delete mode 100644 index_stripped.js delete mode 100644 src/bitcoindjs_stripped.cc delete mode 100644 src/bitcoindjs_stripped.h rename src/{bitcoindjs.cc => libbitcoind.cc} (99%) rename src/{bitcoindjs.h => libbitcoind.h} (100%) diff --git a/.travis.yml b/.travis.yml index 45957147..16935783 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ sudo: false language: node_js env: -- BITCOINDJS_ENV=test BITCOINDJS_ASSUME_YES=true +- BITCORENODE_ENV=test BITCORENODE_ASSUME_YES=true node_js: - "0.12" before_install: diff --git a/README.md b/README.md index 9570cc7d..f1de1f01 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,13 @@ -bitcoind.js +Bitcore Node ======= -[![Build Status](https://img.shields.io/travis/bitpay/bitcoind.js.svg?branch=master&style=flat-square)](https://travis-ci.org/bitpay/bitcoind.js) -[![Coverage Status](https://img.shields.io/coveralls/bitpay/bitcoind.js.svg?style=flat-square)](https://coveralls.io/r/bitpay/bitcoind.js) A Node.js module that adds a native interface to Bitcoin Core for querying information about the Bitcoin blockchain. Bindings are linked to Bitcore Core compiled as a shared library. ## Install ```bash -git clone https://github.com/bitpay/bitcoind.js.git -cd bitcoind.js +git clone https://github.com/bitpay/bitcore-node.git +cd bitcore-node npm install ``` @@ -17,7 +15,7 @@ npm install ```js -var BitcoinNode = require('bitcoind.js'); +var BitcoinNode = require('bitcore-node'); var configuration = { datadir: '~/.bitcoin', @@ -101,22 +99,22 @@ $ tail -f ~/.bitcoin/debug.log ## Modules -Bitcoind.js has a module system where additional information can be indexed and queried from +Bitcore Node has a module system where additional information can be indexed and queried from the blockchain. One built-in module is the address module which exposes the API methods for getting balances and outputs. ### Writing a Module -A new module can be created by inheriting from `BitcoindJS.Module`, implementing the methods `blockHandler()`, `getAPIMethods()`, `getPublishEvents()` and any additional methods for querying the data. Here is an example: +A new module can be created by inheriting from `Node.Module`, implementing the methods `blockHandler()`, `getAPIMethods()`, `getPublishEvents()` and any additional methods for querying the data. Here is an example: ```js var inherits = require('util').inherits; -var BitcoindJS = require('bitcoind.js'); +var Node = require('bitcore-node').Node; var MyModule = function(options) { - BitcoindJS.Module.call(this, options); + Node.Module.call(this, options); }; -inherits(MyModule, BitcoindJS.Module); +inherits(MyModule, Node.Module); /** * blockHandler @@ -195,13 +193,13 @@ The module can then be used when running a node: ```js var configuration = { - datadir: process.env.BITCOINDJS_DIR || '~/.bitcoin', + datadir: process.env.BITCORENODE_DIR || '~/.bitcoin', db: { modules: [MyModule] } }; -var node = new BitcoindJS.Node(configuration); +var node = new Node(configuration); node.on('ready', function() { node.getData('key', function(err, value) { @@ -210,7 +208,7 @@ node.on('ready', function() { }); ``` -Note that if you already have a bitcoind.js database, and you want to query data from previous blocks in the blockchain, you will need to reindex. Reindexing right now means deleting your bitcoind.js database and resyncing. +Note that if you already have a bitcore-node database, and you want to query data from previous blocks in the blockchain, you will need to reindex. Reindexing right now means deleting your bitcore-node database and resyncing. ## Daemon Documentation @@ -290,7 +288,7 @@ Every effort will be made to ensure that this patch stays up-to-date with the la There is a build script that will download Bitcoin Core v0.10.2 and apply the necessary patch, compile `libbitcoind.{so|dylib}` and copy the artifact into `platform/`. Unix/Linux uses the file extension "so" whereas Mac OSX uses "dylib" *(bitcoind compiled as a shared library)*. ```bash -$ cd /path/to/bitcoind.js +$ cd /path/to/bitcore-node $ ./bin/build-libbitcoind ``` @@ -327,10 +325,9 @@ $ cp -R libbitcoind/src/.libs/libbitcoind.*dylib platform/osx/lib ## License -Code released under [the MIT license](https://github.com/bitpay/bitcoind.js/blob/master/LICENSE). +Code released under [the MIT license](https://github.com/bitpay/bitcore-node/blob/master/LICENSE). Copyright 2013-2015 BitPay, Inc. - bitcoin: Copyright (c) 2009-2015 Bitcoin Core Developers (MIT License) - bcoin (some code borrowed temporarily): Copyright Fedor Indutny, 2014. - diff --git a/bin/build-libbitcoind b/bin/build-libbitcoind index ac4ffe71..049f1a65 100755 --- a/bin/build-libbitcoind +++ b/bin/build-libbitcoind @@ -64,12 +64,12 @@ compare_patch () { } debug= -if [ "${BITCOINDJS_ENV}" == "debug" ]; then +if [ "${BITCORENODE_ENV}" == "debug" ]; then options=`cat ${root_dir}/bin/config_options_debug.sh` fi test=false -if [ "${BITCOINDJS_ENV}" == "test" ]; then +if [ "${BITCORENODE_ENV}" == "test" ]; then test=true options=`cat ${root_dir}/bin/config_options_test.sh` fi @@ -96,7 +96,7 @@ if [ "${shared_file_built}" = false ]; then ${root_dir}/etc/bitcoin.patch." echo -n "Would you like to remove the current patch, checkout the tag: ${tag} and \ apply the current patch from "${root_dir}"/etc/bitcoin.patch? (y/N): " - if [ "${BITCOINDJS_ASSUME_YES}" = true ]; then + if [ "${BITCORENODE_ASSUME_YES}" = true ]; then input=y echo "" else diff --git a/binding.gyp b/binding.gyp index 08a19576..33a10df1 100755 --- a/binding.gyp +++ b/binding.gyp @@ -1,6 +1,6 @@ { 'targets': [{ - 'target_name': 'bitcoindjs', + 'target_name': 'libbitcoind', 'include_dirs' : [ '", - "version": "0.0.8", + "version": "0.2.0", "main": "./index.js", - "repository": "git://github.com/bitpay/bitcoind.js.git", - "homepage": "https://github.com/bitpay/bitcoind.js", + "repository": "git://github.com/bitpay/bitcore-node.git", + "homepage": "https://github.com/bitpay/bitcore-node.js", "bugs": { - "url": "https://github.com/bitpay/bitcoind.js/issues" + "url": "https://github.com/bitpay/bitcore-node/issues" }, "contributors": [ { diff --git a/src/bitcoindjs_stripped.cc b/src/bitcoindjs_stripped.cc deleted file mode 100644 index a9645490..00000000 --- a/src/bitcoindjs_stripped.cc +++ /dev/null @@ -1,517 +0,0 @@ -/** - * bitcoind.js - a binding for node.js which links to libbitcoind.so/dylib. - * Copyright (c) 2015, BitPay (MIT License) - * - * bitcoindjs.cc: - * A bitcoind node.js binding. - */ - -#include "bitcoindjs_stripped.h" - -using namespace std; -using namespace boost; -using namespace node; -using namespace v8; - -/** - * Bitcoin Globals - */ - -// These global functions and variables are -// required to be defined/exposed here. - -extern void DetectShutdownThread(boost::thread_group*); -extern int nScriptCheckThreads; -static termios orig_termios; - -/** - * Node.js Internal Function Templates - */ - -static void -async_start_node(uv_work_t *req); - -static void -async_start_node_after(uv_work_t *req); - -static void -async_stop_node(uv_work_t *req); - -static void -async_stop_node_after(uv_work_t *req); - -static int -start_node(void); - -static void -start_node_thread(void); - -extern "C" void -init(Handle); - -/** - * Private Global Variables - * Used only by bitcoindjs functions. - */ - -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_txindex = false; - -/** - * Private Structs - * Used for async functions and necessary linked lists at points. - */ - -/** - * async_node_data - * Where the uv async request data resides. - */ - -struct async_node_data { - std::string err_msg; - std::string result; - std::string datadir; - bool rpc; - bool testnet; - bool txindex; - Eternal callback; -}; - - -/** - * Helpers - */ - -static bool -set_cooked(void); - -/** - * Functions - */ - -/** - * StartBitcoind() - * bitcoind.start(callback) - * Start the bitcoind node with AppInit2() on a separate thread. - */ - -NAN_METHOD(StartBitcoind) { - Isolate* isolate = Isolate::GetCurrent(); - HandleScope scope(isolate); - - Local callback; - std::string datadir = std::string(""); - bool rpc = false; - bool testnet = false; - bool txindex = false; - - if (args.Length() >= 2 && args[0]->IsObject() && args[1]->IsFunction()) { - Local options = Local::Cast(args[0]); - if (options->Get(NanNew("datadir"))->IsString()) { - String::Utf8Value datadir_(options->Get(NanNew("datadir"))->ToString()); - datadir = std::string(*datadir_); - } - 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("txindex"))->IsBoolean()) { - txindex = options->Get(NanNew("txindex"))->ToBoolean()->IsTrue(); - } - callback = Local::Cast(args[1]); - } else if (args.Length() >= 2 - && (args[0]->IsUndefined() || args[0]->IsNull()) - && args[1]->IsFunction()) { - callback = Local::Cast(args[1]); - } else if (args.Length() >= 1 && args[0]->IsFunction()) { - callback = Local::Cast(args[0]); - } else { - return NanThrowError( - "Usage: bitcoind.start(callback)"); - } - - // - // Run bitcoind's StartNode() on a separate thread. - // - - async_node_data *data = new async_node_data(); - data->err_msg = std::string(""); - data->result = std::string(""); - data->datadir = datadir; - data->rpc = rpc; - data->testnet = testnet; - data->txindex = txindex; - - Eternal eternal(isolate, callback); - - data->callback = eternal; - uv_work_t *req = new uv_work_t(); - req->data = data; - - int status = uv_queue_work(uv_default_loop(), - req, async_start_node, - (uv_after_work_cb)async_start_node_after); - - assert(status == 0); - - NanReturnValue(Undefined(isolate)); -} - -/** - * async_start_node() - * Call start_node() and start all our boost threads. - */ - -static void -async_start_node(uv_work_t *req) { - async_node_data *data = static_cast(req->data); - if (data->datadir != "") { - g_data_dir = (char *)data->datadir.c_str(); - } else { - g_data_dir = (char *)malloc(sizeof(char) * 512); - snprintf(g_data_dir, sizeof(char) * 512, "%s/.bitcoind.js", getenv("HOME")); - } - g_rpc = (bool)data->rpc; - g_testnet = (bool)data->testnet; - g_txindex = (bool)data->txindex; - tcgetattr(STDIN_FILENO, &orig_termios); - start_node(); - data->result = std::string("bitcoind opened."); -} - -/** - * async_start_node_after() - * Execute our callback. - */ - -static void -async_start_node_after(uv_work_t *req) { - Isolate* isolate = Isolate::GetCurrent(); - HandleScope scope(isolate); - async_node_data *data = static_cast(req->data); - - Local cb = data->callback.Get(isolate); - if (data->err_msg != "") { - Local err = Exception::Error(NanNew(data->err_msg)); - const unsigned argc = 1; - Local argv[argc] = { err }; - TryCatch try_catch; - cb->Call(isolate->GetCurrentContext()->Global(), argc, argv); - if (try_catch.HasCaught()) { - node::FatalException(try_catch); - } - } else { - const unsigned argc = 2; - Local argv[argc] = { - v8::Null(isolate), - Local::New(isolate, NanNew(data->result)) - }; - TryCatch try_catch; - cb->Call(isolate->GetCurrentContext()->Global(), argc, argv); - if (try_catch.HasCaught()) { - node::FatalException(try_catch); - } - } - - delete data; - delete req; -} - -/** - * start_node(void) - * Start AppInit2() on a separate thread, wait for - * Unfortunately, we need to wait for the initialization - * to unhook the signal handlers so we can use them - * from node.js in javascript. - */ - -static int -start_node(void) { - SetupEnvironment(); - - noui_connect(); - - new boost::thread(boost::bind(&start_node_thread)); - - // Drop the bitcoind signal handlers: we want our own. - signal(SIGINT, SIG_DFL); - signal(SIGHUP, SIG_DFL); - signal(SIGQUIT, SIG_DFL); - - // Hook into packet handling - //new boost::thread(boost::bind(&hook_packets)); - - return 0; -} - -static void -start_node_thread(void) { - boost::thread_group threadGroup; - boost::thread* detectShutdownThread = NULL; - - // Workaround for AppInit2() arg parsing. Not ideal, but it works. - int argc = 0; - char **argv = (char **)malloc((4 + 1) * sizeof(char **)); - - argv[argc] = (char *)"bitcoind"; - argc++; - - if (g_data_dir) { - const int argl = 9 + strlen(g_data_dir) + 1; - char *arg = (char *)malloc(sizeof(char) * argl); - int w = snprintf(arg, argl, "-datadir=%s", g_data_dir); - if (w >= 10 && w <= argl) { - arg[w] = '\0'; - argv[argc] = arg; - argc++; - } else { - if (set_cooked()) { - fprintf(stderr, "bitcoind.js: Bad -datadir value.\n"); - } - } - } - - if (g_rpc) { - argv[argc] = (char *)"-server"; - argc++; - } - - if (g_testnet) { - argv[argc] = (char *)"-testnet"; - argc++; - } - - if (g_txindex) { - argv[argc] = (char *)"-txindex"; - argc++; - } - - argv[argc] = NULL; - - bool fRet = false; - try { - ParseParameters((const int)argc, (const char **)argv); - - if (!boost::filesystem::is_directory(GetDataDir(false))) { - if (set_cooked()) { - fprintf(stderr, - "bitcoind.js: Specified data directory \"%s\" does not exist.\n", - mapArgs["-datadir"].c_str()); - } - shutdown_complete = true; - _exit(1); - return; - } - - try { - ReadConfigFile(mapArgs, mapMultiArgs); - } catch(std::exception &e) { - if (set_cooked()) { - fprintf(stderr, - "bitcoind.js: Error reading configuration file: %s\n", e.what()); - } - shutdown_complete = true; - _exit(1); - return; - } - - if (!SelectParamsFromCommandLine()) { - if (set_cooked()) { - fprintf(stderr, - "bitcoind.js: Invalid combination of -regtest and -testnet.\n"); - } - shutdown_complete = true; - _exit(1); - return; - } - - CreatePidFile(GetPidFile(), getpid()); - - detectShutdownThread = new boost::thread( - boost::bind(&DetectShutdownThread, &threadGroup)); - - fRet = AppInit2(threadGroup); - - } catch (std::exception& e) { - if (set_cooked()) { - fprintf(stderr, "bitcoind.js: AppInit(): std::exception\n"); - } - } catch (...) { - if (set_cooked()) { - fprintf(stderr, "bitcoind.js: AppInit(): other exception\n"); - } - } - - if (!fRet) { - if (detectShutdownThread) { - detectShutdownThread->interrupt(); - } - threadGroup.interrupt_all(); - } - - if (detectShutdownThread) { - detectShutdownThread->join(); - delete detectShutdownThread; - detectShutdownThread = NULL; - } - Shutdown(); - - // bitcoind is shutdown. Notify the main thread - // which is polling this variable: - shutdown_complete = true; -} - -/** - * StopBitcoind() - * bitcoind.stop(callback) - */ - -NAN_METHOD(StopBitcoind) { - fprintf(stderr, "Stopping Bitcoind please wait!"); - Isolate* isolate = Isolate::GetCurrent(); - HandleScope scope(isolate); - - if (args.Length() < 1 || !args[0]->IsFunction()) { - return NanThrowError( - "Usage: bitcoind.stop(callback)"); - } - - Local callback = Local::Cast(args[0]); - - // - // Run bitcoind's StartShutdown() on a separate thread. - // - - async_node_data *data = new async_node_data(); - data->err_msg = std::string(""); - data->result = std::string(""); - Eternal eternal(isolate, callback); - data->callback = eternal; - - uv_work_t *req = new uv_work_t(); - req->data = data; - - int status = uv_queue_work(uv_default_loop(), - req, async_stop_node, - (uv_after_work_cb)async_stop_node_after); - - assert(status == 0); - NanReturnValue(Undefined(isolate)); - -} - -/** - * async_stop_node() - * Call StartShutdown() to join the boost threads, which will call Shutdown() - * and set shutdown_complete to true to notify the main node.js thread. - */ - -static void -async_stop_node(uv_work_t *req) { - async_node_data *data = static_cast(req->data); - StartShutdown(); - data->result = std::string("bitcoind shutdown."); -} - -/** - * async_stop_node_after() - * Execute our callback. - */ - -static void -async_stop_node_after(uv_work_t *req) { - Isolate* isolate = Isolate::GetCurrent(); - HandleScope scope(isolate); - async_node_data* data = static_cast(req->data); - - Local cb = data->callback.Get(isolate); - if (data->err_msg != "") { - Local err = Exception::Error(NanNew(data->err_msg)); - const unsigned argc = 1; - Local argv[argc] = { err }; - TryCatch try_catch; - cb->Call(isolate->GetCurrentContext()->Global(), argc, argv); - if (try_catch.HasCaught()) { - node::FatalException(try_catch); - } - } else { - const unsigned argc = 2; - Local argv[argc] = { - Local::New(isolate, NanNull()), - Local::New(isolate, NanNew(data->result)) - }; - TryCatch try_catch; - cb->Call(isolate->GetCurrentContext()->Global(), argc, argv); - if (try_catch.HasCaught()) { - node::FatalException(try_catch); - } - } - - delete data; - delete req; -} - -/** - * IsStopping() - * bitcoind.stopping() - * Check whether bitcoind is in the process of shutting down. This is polled - * from javascript. - */ - -NAN_METHOD(IsStopping) { - NanScope(); - NanReturnValue(NanNew(ShutdownRequested())); -} - -/** - * IsStopped() - * bitcoind.stopped() - * Check whether bitcoind has shutdown completely. This will be polled by - * javascript to check whether the libuv event loop is safe to stop. - */ - -NAN_METHOD(IsStopped) { - NanScope(); - NanReturnValue(NanNew(shutdown_complete)); -} - -/** - * Helpers - */ - -static bool -set_cooked(void) { - uv_tty_t tty; - tty.mode = 1; - tty.orig_termios = orig_termios; - - if (!uv_tty_set_mode(&tty, 0)) { - printf("\x1b[H\x1b[J"); - return true; - } - - return false; -} - -/** - * Init() - * Initialize the singleton object known as bitcoindjs. - */ - -extern "C" void -init(Handle target) { - NanScope(); - - NODE_SET_METHOD(target, "start", StartBitcoind); - NODE_SET_METHOD(target, "stop", StopBitcoind); - NODE_SET_METHOD(target, "stopping", IsStopping); - NODE_SET_METHOD(target, "stopped", IsStopped); - -} - -NODE_MODULE(bitcoindjs, init) diff --git a/src/bitcoindjs_stripped.h b/src/bitcoindjs_stripped.h deleted file mode 100644 index 17ea03be..00000000 --- a/src/bitcoindjs_stripped.h +++ /dev/null @@ -1,19 +0,0 @@ -/** - * bitcoind.js - * Copyright (c) 2014, BitPay (MIT License) - * - * bitcoindjs.h: - * A bitcoind node.js binding header file. - */ -#include "nan.h" -#include "addrman.h" -#include "base58.h" -#include "init.h" -#include "noui.h" -#include -#include - -NAN_METHOD(StartBitcoind); -NAN_METHOD(IsStopping); -NAN_METHOD(IsStopped); -NAN_METHOD(StopBitcoind); diff --git a/src/bitcoindjs.cc b/src/libbitcoind.cc similarity index 99% rename from src/bitcoindjs.cc rename to src/libbitcoind.cc index fb153016..da64bef6 100644 --- a/src/bitcoindjs.cc +++ b/src/libbitcoind.cc @@ -6,7 +6,7 @@ * A bitcoind node.js binding. */ -#include "bitcoindjs.h" +#include "libbitcoind.h" using namespace std; using namespace boost; @@ -1634,4 +1634,4 @@ init(Handle target) { } -NODE_MODULE(bitcoindjs, init) +NODE_MODULE(libbitcoind, init) diff --git a/src/bitcoindjs.h b/src/libbitcoind.h similarity index 100% rename from src/bitcoindjs.h rename to src/libbitcoind.h