Merge pull request #44 from braydonf/regtest
Add "regtest" testing capabilities
This commit is contained in:
commit
6cc6d7f4de
|
@ -1,7 +1,15 @@
|
||||||
language: node_js
|
language: node_js
|
||||||
|
env:
|
||||||
|
- BITCOINDJS_ENV=test
|
||||||
node_js:
|
node_js:
|
||||||
- "0.12"
|
- "0.12"
|
||||||
before_install:
|
before_install:
|
||||||
- sudo apt-get install libboost1.48-all-dev
|
- sudo apt-get install libboost1.48-all-dev
|
||||||
|
- sudo add-apt-repository -y ppa:bitcoin/bitcoin
|
||||||
|
- sudo apt-get update
|
||||||
|
- sudo apt-get install libdb4.8-dev libdb4.8++-dev
|
||||||
- git config --global user.email "dev@bitpay.com"
|
- git config --global user.email "dev@bitpay.com"
|
||||||
- git config --global user.name "BitPay, Inc."
|
- git config --global user.name "BitPay, Inc."
|
||||||
|
script:
|
||||||
|
- _mocha -R spec integration/regtest.js
|
||||||
|
- _mocha -R spec --recursive
|
||||||
|
|
13
README.md
13
README.md
|
@ -21,7 +21,7 @@ var BitcoinNode = require('bitcoind.js');
|
||||||
|
|
||||||
var configuration = {
|
var configuration = {
|
||||||
datadir: '~/.bitcoin',
|
datadir: '~/.bitcoin',
|
||||||
testnet: true
|
network: 'testnet'
|
||||||
};
|
};
|
||||||
|
|
||||||
var node = new BitcoinNode(configuration);
|
var node = new BitcoinNode(configuration);
|
||||||
|
@ -110,7 +110,7 @@ $ tail -f ~/.bitcoin/debug.log
|
||||||
|
|
||||||
## Building
|
## 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
|
### 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
|
$ 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:
|
To run integration tests against testnet or livenet data:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
@ -161,7 +166,7 @@ Most of all the dependencies for building Bitcoin Core are needed, for more info
|
||||||
|
|
||||||
#### Shared Library Patch
|
#### 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.
|
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
|
$ ./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}`.
|
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}`.
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ var fixtureData = {
|
||||||
|
|
||||||
var bitcoind = require('../').daemon({
|
var bitcoind = require('../').daemon({
|
||||||
datadir: process.env.BITCOINDJS_DIR || '~/.bitcoin',
|
datadir: process.env.BITCOINDJS_DIR || '~/.bitcoin',
|
||||||
testnet: true
|
network: 'testnet'
|
||||||
});
|
});
|
||||||
|
|
||||||
bitcoind.on('error', function(err) {
|
bitcoind.on('error', function(err) {
|
||||||
|
|
|
@ -3,6 +3,7 @@ set -e
|
||||||
|
|
||||||
root_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/.."
|
root_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/.."
|
||||||
cd "${root_dir}"
|
cd "${root_dir}"
|
||||||
|
options=`cat ${root_dir}/bin/config_options.sh`
|
||||||
|
|
||||||
os_dir=$(./platform/os.sh osdir)
|
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
|
export LD_LIBRARY_PATH="${root_dir}/libbitcoind/src/leveldb":"${os_dir}":$LD_LIBRARY_PATH
|
||||||
|
|
||||||
debug=
|
debug=
|
||||||
if test x"$1" = x'debug'; then
|
if [ "${BITCOINDJS_ENV}" == "debug" ]; then
|
||||||
debug=--enable-debug
|
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
|
fi
|
||||||
|
|
||||||
btc_dir="${root_dir}/libbitcoind"
|
btc_dir="${root_dir}/libbitcoind"
|
||||||
|
@ -50,12 +56,11 @@ if [ "${only_make}" = false ]; then
|
||||||
|
|
||||||
echo './autogen.sh'
|
echo './autogen.sh'
|
||||||
./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
|
fi
|
||||||
|
|
||||||
|
full_options="${options}${os_dir}"
|
||||||
|
echo "running the configure script with the following options:\n :::[\"${full_options}\"]:::"
|
||||||
|
${full_options}
|
||||||
echo 'make V=1'
|
echo 'make V=1'
|
||||||
make V=1
|
make V=1
|
||||||
|
|
||||||
|
|
|
@ -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=
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
./configure --enable-debug --enable-tests=no --enable-daemonlib --with-gui=no --without-qt --without-miniupnpc --prefix=
|
||||||
|
|
|
@ -1,18 +1,8 @@
|
||||||
From 05084f2a640b862132588b322461ec8e13058fc3 Mon Sep 17 00:00:00 2001
|
commit 29c1ca452ba6178d6b17be0a0b5a65567ba846af
|
||||||
From: Chris Kleeschulte <chrisk@bitpay.com>
|
Author: Chris Kleeschulte <chrisk@bitpay.com>
|
||||||
Date: Mon, 13 Jul 2015 12:49:30 -0400
|
Date: Mon Jul 13 16:35:37 2015 -0400
|
||||||
Subject: [PATCH] libbitcoind
|
|
||||||
|
|
||||||
---
|
allow compiling of libbitcoind.so.
|
||||||
config_me.sh | 1 +
|
|
||||||
configure.ac | 37 ++++++++++++++++++++++++++++++++-----
|
|
||||||
src/Makefile.am | 42 ++++++++++++++++++++++++++++++++++--------
|
|
||||||
src/bitcoind.cpp | 6 ++++++
|
|
||||||
src/init.h | 5 +++++
|
|
||||||
src/leveldb/Makefile | 6 +++++-
|
|
||||||
src/leveldbwrapper.h | 12 ++++++++++++
|
|
||||||
7 files changed, 95 insertions(+), 14 deletions(-)
|
|
||||||
create mode 100644 config_me.sh
|
|
||||||
|
|
||||||
diff --git a/config_me.sh b/config_me.sh
|
diff --git a/config_me.sh b/config_me.sh
|
||||||
new file mode 100644
|
new file mode 100644
|
||||||
|
@ -22,13 +12,13 @@ index 0000000..19e9a1b
|
||||||
@@ -0,0 +1 @@
|
@@ -0,0 +1 @@
|
||||||
+./configure --enable-tests=no --enable-daemonlib --with-gui=no --without-qt --without-miniupnpc --without-bdb --enable-debug --disable-wallet --without-utils
|
+./configure --enable-tests=no --enable-daemonlib --with-gui=no --without-qt --without-miniupnpc --without-bdb --enable-debug --disable-wallet --without-utils
|
||||||
diff --git a/configure.ac b/configure.ac
|
diff --git a/configure.ac b/configure.ac
|
||||||
index 37fe47e..27a9b9a 100644
|
index 37fe47e..83cfe70 100644
|
||||||
--- a/configure.ac
|
--- a/configure.ac
|
||||||
+++ b/configure.ac
|
+++ b/configure.ac
|
||||||
@@ -119,6 +119,12 @@ AC_ARG_ENABLE([reduce-exports],
|
@@ -119,6 +119,12 @@ AC_ARG_ENABLE([reduce-exports],
|
||||||
[use_reduce_exports=$enableval],
|
[use_reduce_exports=$enableval],
|
||||||
[use_reduce_exports=no])
|
[use_reduce_exports=no])
|
||||||
|
|
||||||
+AC_ARG_ENABLE([daemonlib],
|
+AC_ARG_ENABLE([daemonlib],
|
||||||
+ [AS_HELP_STRING([--enable-daemonlib],
|
+ [AS_HELP_STRING([--enable-daemonlib],
|
||||||
+ [compile all of bitcoind as a library (default is no)])],
|
+ [compile all of bitcoind as a library (default is no)])],
|
||||||
|
@ -45,13 +35,13 @@ index 37fe47e..27a9b9a 100644
|
||||||
+ if test x$use_daemonlib = xno; then
|
+ if test x$use_daemonlib = xno; then
|
||||||
+ AX_CHECK_COMPILE_FLAG([-fPIE],[HARDENED_CXXFLAGS="$HARDENED_CXXFLAGS -fPIE"])
|
+ AX_CHECK_COMPILE_FLAG([-fPIE],[HARDENED_CXXFLAGS="$HARDENED_CXXFLAGS -fPIE"])
|
||||||
+ fi
|
+ fi
|
||||||
|
|
||||||
AX_CHECK_PREPROC_FLAG([-D_FORTIFY_SOURCE=2],[
|
AX_CHECK_PREPROC_FLAG([-D_FORTIFY_SOURCE=2],[
|
||||||
AX_CHECK_PREPROC_FLAG([-U_FORTIFY_SOURCE],[
|
AX_CHECK_PREPROC_FLAG([-U_FORTIFY_SOURCE],[
|
||||||
@@ -415,7 +424,7 @@ if test x$use_hardening != xno; then
|
@@ -415,7 +424,7 @@ if test x$use_hardening != xno; then
|
||||||
AX_CHECK_LINK_FLAG([[-Wl,-z,relro]], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,-z,relro"])
|
AX_CHECK_LINK_FLAG([[-Wl,-z,relro]], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,-z,relro"])
|
||||||
AX_CHECK_LINK_FLAG([[-Wl,-z,now]], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,-z,now"])
|
AX_CHECK_LINK_FLAG([[-Wl,-z,now]], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,-z,now"])
|
||||||
|
|
||||||
- if test x$TARGET_OS != xwindows; then
|
- if test x$TARGET_OS != xwindows; then
|
||||||
+ if test x$TARGET_OS != xwindows -a x$use_daemonlib = xno; then
|
+ if test x$TARGET_OS != xwindows -a x$use_daemonlib = xno; then
|
||||||
# All windows code is PIC, forcing it on just adds useless compile warnings
|
# All windows code is PIC, forcing it on just adds useless compile warnings
|
||||||
|
@ -60,7 +50,7 @@ index 37fe47e..27a9b9a 100644
|
||||||
@@ -433,6 +442,17 @@ if test x$use_hardening != xno; then
|
@@ -433,6 +442,17 @@ if test x$use_hardening != xno; then
|
||||||
OBJCXXFLAGS="$CXXFLAGS"
|
OBJCXXFLAGS="$CXXFLAGS"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
+AC_DEFINE([ENABLE_DAEMONLIB],[0],[Enable daemonlib.])
|
+AC_DEFINE([ENABLE_DAEMONLIB],[0],[Enable daemonlib.])
|
||||||
+AM_CONDITIONAL([ENABLE_DAEMONLIB],[false])
|
+AM_CONDITIONAL([ENABLE_DAEMONLIB],[false])
|
||||||
+if test x$use_daemonlib != xno; then
|
+if test x$use_daemonlib != xno; then
|
||||||
|
@ -78,13 +68,13 @@ index 37fe47e..27a9b9a 100644
|
||||||
@@ -483,11 +503,18 @@ AC_LINK_IFELSE([AC_LANG_SOURCE([
|
@@ -483,11 +503,18 @@ AC_LINK_IFELSE([AC_LANG_SOURCE([
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
-if test x$use_reduce_exports = xyes; then
|
-if test x$use_reduce_exports = xyes; then
|
||||||
+if test x$use_reduce_exports = xyes -a x$use_daemonlib = xno; then
|
+if test x$use_reduce_exports = xyes -a x$use_daemonlib = xno; then
|
||||||
AX_CHECK_COMPILE_FLAG([-fvisibility=hidden],[RE_CXXFLAGS="-fvisibility=hidden"],
|
AX_CHECK_COMPILE_FLAG([-fvisibility=hidden],[RE_CXXFLAGS="-fvisibility=hidden"],
|
||||||
[AC_MSG_ERROR([Cannot set default symbol visibility. Use --disable-reduce-exports.])])
|
[AC_MSG_ERROR([Cannot set default symbol visibility. Use --disable-reduce-exports.])])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
+AC_MSG_CHECKING([whether to compile as daemonlib])
|
+AC_MSG_CHECKING([whether to compile as daemonlib])
|
||||||
+if test x$use_daemonlib != xno; then
|
+if test x$use_daemonlib != xno; then
|
||||||
+ AC_MSG_RESULT([yes])
|
+ AC_MSG_RESULT([yes])
|
||||||
|
@ -96,18 +86,19 @@ index 37fe47e..27a9b9a 100644
|
||||||
LIBLEVELDB=
|
LIBLEVELDB=
|
||||||
LIBMEMENV=
|
LIBMEMENV=
|
||||||
diff --git a/src/Makefile.am b/src/Makefile.am
|
diff --git a/src/Makefile.am b/src/Makefile.am
|
||||||
index 1c2f770..632f608 100644
|
index 1c2f770..ddcae0f 100644
|
||||||
--- a/src/Makefile.am
|
--- a/src/Makefile.am
|
||||||
+++ b/src/Makefile.am
|
+++ b/src/Makefile.am
|
||||||
@@ -1,6 +1,7 @@
|
@@ -1,6 +1,8 @@
|
||||||
DIST_SUBDIRS = secp256k1
|
DIST_SUBDIRS = secp256k1
|
||||||
AM_LDFLAGS = $(PTHREAD_CFLAGS) $(LIBTOOL_LDFLAGS)
|
AM_LDFLAGS = $(PTHREAD_CFLAGS) $(LIBTOOL_LDFLAGS)
|
||||||
|
|
||||||
+lib_LTLIBRARIES =
|
+lib_LTLIBRARIES =
|
||||||
|
+libbitcoind_la_LIBADD =
|
||||||
|
|
||||||
if EMBEDDED_LEVELDB
|
if EMBEDDED_LEVELDB
|
||||||
LEVELDB_CPPFLAGS += -I$(srcdir)/leveldb/include
|
LEVELDB_CPPFLAGS += -I$(srcdir)/leveldb/include
|
||||||
@@ -15,6 +16,10 @@ $(LIBLEVELDB) $(LIBMEMENV):
|
@@ -15,6 +17,10 @@ $(LIBLEVELDB) $(LIBMEMENV):
|
||||||
@echo "Building LevelDB ..." && $(MAKE) -C $(@D) $(@F) CXX="$(CXX)" \
|
@echo "Building LevelDB ..." && $(MAKE) -C $(@D) $(@F) CXX="$(CXX)" \
|
||||||
CC="$(CC)" PLATFORM=$(TARGET_OS) AR="$(AR)" $(LEVELDB_TARGET_FLAGS) \
|
CC="$(CC)" PLATFORM=$(TARGET_OS) AR="$(AR)" $(LEVELDB_TARGET_FLAGS) \
|
||||||
OPT="$(CXXFLAGS) $(CPPFLAGS) -D__STDC_LIMIT_MACROS"
|
OPT="$(CXXFLAGS) $(CPPFLAGS) -D__STDC_LIMIT_MACROS"
|
||||||
|
@ -116,12 +107,12 @@ index 1c2f770..632f608 100644
|
||||||
+ @echo "Building the LevelDB shared library..." && $(MAKE) -C ./leveldb
|
+ @echo "Building the LevelDB shared library..." && $(MAKE) -C ./leveldb
|
||||||
+
|
+
|
||||||
endif
|
endif
|
||||||
|
|
||||||
BITCOIN_CONFIG_INCLUDES=-I$(builddir)/config
|
BITCOIN_CONFIG_INCLUDES=-I$(builddir)/config
|
||||||
@@ -49,16 +54,16 @@ BITCOIN_INCLUDES += $(BDB_CPPFLAGS)
|
@@ -49,16 +55,16 @@ BITCOIN_INCLUDES += $(BDB_CPPFLAGS)
|
||||||
EXTRA_LIBRARIES += libbitcoin_wallet.a
|
EXTRA_LIBRARIES += libbitcoin_wallet.a
|
||||||
endif
|
endif
|
||||||
|
|
||||||
-if BUILD_BITCOIN_LIBS
|
-if BUILD_BITCOIN_LIBS
|
||||||
-lib_LTLIBRARIES = libbitcoinconsensus.la
|
-lib_LTLIBRARIES = libbitcoinconsensus.la
|
||||||
-LIBBITCOIN_CONSENSUS=libbitcoinconsensus.la
|
-LIBBITCOIN_CONSENSUS=libbitcoinconsensus.la
|
||||||
|
@ -132,7 +123,7 @@ index 1c2f770..632f608 100644
|
||||||
+LIBBITCOIN_CONSENSUS =
|
+LIBBITCOIN_CONSENSUS =
|
||||||
bin_PROGRAMS =
|
bin_PROGRAMS =
|
||||||
TESTS =
|
TESTS =
|
||||||
|
|
||||||
+if BUILD_BITCOIN_LIBS
|
+if BUILD_BITCOIN_LIBS
|
||||||
+lib_LTLIBRARIES += libbitcoinconsensus.la
|
+lib_LTLIBRARIES += libbitcoinconsensus.la
|
||||||
+LIBBITCOIN_CONSENSUS += libbitcoinconsensus.la
|
+LIBBITCOIN_CONSENSUS += libbitcoinconsensus.la
|
||||||
|
@ -142,28 +133,28 @@ index 1c2f770..632f608 100644
|
||||||
if BUILD_BITCOIND
|
if BUILD_BITCOIND
|
||||||
bin_PROGRAMS += bitcoind
|
bin_PROGRAMS += bitcoind
|
||||||
endif
|
endif
|
||||||
@@ -66,6 +71,9 @@ endif
|
@@ -66,6 +72,9 @@ endif
|
||||||
if BUILD_BITCOIN_UTILS
|
if BUILD_BITCOIN_UTILS
|
||||||
bin_PROGRAMS += bitcoin-cli bitcoin-tx
|
bin_PROGRAMS += bitcoin-cli bitcoin-tx
|
||||||
endif
|
endif
|
||||||
+else
|
+else
|
||||||
+lib_LTLIBRARIES += libbitcoind.la
|
+lib_LTLIBRARIES += libbitcoind.la
|
||||||
+endif
|
+endif
|
||||||
|
|
||||||
.PHONY: FORCE
|
.PHONY: FORCE
|
||||||
# bitcoin core #
|
# bitcoin core #
|
||||||
@@ -169,8 +177,9 @@ obj/build.h: FORCE
|
@@ -169,8 +178,9 @@ obj/build.h: FORCE
|
||||||
@$(MKDIR_P) $(builddir)/obj
|
@$(MKDIR_P) $(builddir)/obj
|
||||||
@$(top_srcdir)/share/genbuild.sh $(abs_top_builddir)/src/obj/build.h \
|
@$(top_srcdir)/share/genbuild.sh $(abs_top_builddir)/src/obj/build.h \
|
||||||
$(abs_top_srcdir)
|
$(abs_top_srcdir)
|
||||||
-libbitcoin_util_a-clientversion.$(OBJEXT): obj/build.h
|
-libbitcoin_util_a-clientversion.$(OBJEXT): obj/build.h
|
||||||
|
|
||||||
+libbitcoin_util_a-clientversion.$(OBJEXT): obj/build.h
|
+libbitcoin_util_a-clientversion.$(OBJEXT): obj/build.h
|
||||||
+clientversion.cpp: obj/build.h
|
+clientversion.cpp: obj/build.h
|
||||||
# server: shared between bitcoind and bitcoin-qt
|
# server: shared between bitcoind and bitcoin-qt
|
||||||
libbitcoin_server_a_CPPFLAGS = $(BITCOIN_INCLUDES) $(MINIUPNPC_CPPFLAGS)
|
libbitcoin_server_a_CPPFLAGS = $(BITCOIN_INCLUDES) $(MINIUPNPC_CPPFLAGS)
|
||||||
libbitcoin_server_a_SOURCES = \
|
libbitcoin_server_a_SOURCES = \
|
||||||
@@ -309,9 +318,18 @@ nodist_libbitcoin_util_a_SOURCES = $(srcdir)/obj/build.h
|
@@ -309,9 +319,18 @@ nodist_libbitcoin_util_a_SOURCES = $(srcdir)/obj/build.h
|
||||||
bitcoind_SOURCES = bitcoind.cpp
|
bitcoind_SOURCES = bitcoind.cpp
|
||||||
bitcoind_CPPFLAGS = $(BITCOIN_INCLUDES)
|
bitcoind_CPPFLAGS = $(BITCOIN_INCLUDES)
|
||||||
bitcoind_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
|
bitcoind_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
|
||||||
|
@ -175,37 +166,41 @@ index 1c2f770..632f608 100644
|
||||||
+libbitcoind_la_SOURCES += $(libbitcoin_server_a_SOURCES)
|
+libbitcoind_la_SOURCES += $(libbitcoin_server_a_SOURCES)
|
||||||
+libbitcoind_la_SOURCES += $(crypto_libbitcoin_crypto_a_SOURCES)
|
+libbitcoind_la_SOURCES += $(crypto_libbitcoin_crypto_a_SOURCES)
|
||||||
+libbitcoind_la_SOURCES += $(univalue_libbitcoin_univalue_a_SOURCES)
|
+libbitcoind_la_SOURCES += $(univalue_libbitcoin_univalue_a_SOURCES)
|
||||||
|
|
||||||
if TARGET_WINDOWS
|
if TARGET_WINDOWS
|
||||||
bitcoind_SOURCES += bitcoind-res.rc
|
bitcoind_SOURCES += bitcoind-res.rc
|
||||||
+libbitcoind_la_SOURCES += bitcoind-res.rc
|
+libbitcoind_la_SOURCES += bitcoind-res.rc
|
||||||
endif
|
endif
|
||||||
|
|
||||||
bitcoind_LDADD = \
|
bitcoind_LDADD = \
|
||||||
@@ -328,7 +346,15 @@ if ENABLE_WALLET
|
@@ -326,9 +345,19 @@ bitcoind_LDADD = \
|
||||||
|
|
||||||
|
if ENABLE_WALLET
|
||||||
bitcoind_LDADD += libbitcoin_wallet.a
|
bitcoind_LDADD += libbitcoin_wallet.a
|
||||||
|
+libbitcoind_la_LIBADD += $(BDB_LIBS)
|
||||||
|
+libbitcoind_la_SOURCES += $(libbitcoin_wallet_a_SOURCES)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
+MEMOBJ = helpers/memenv/memenv.lo
|
+MEMOBJ = helpers/memenv/memenv.lo
|
||||||
+$(MEMOBJ):
|
+$(MEMOBJ):
|
||||||
+ @echo "Building the Memenv shared library..." && $(MAKE) -C ./leveldb $@
|
+ @echo "Building the Memenv shared library..." && $(MAKE) -C ./leveldb $@
|
||||||
+
|
+
|
||||||
bitcoind_LDADD += $(BOOST_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS)
|
bitcoind_LDADD += $(BOOST_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS)
|
||||||
+libbitcoind_la_LIBADD = $(BOOST_LIBS) $(SSL_LIBS) $(LIBSECP256K1) $(CRYPTO_LIBS) leveldb/$(MEMOBJ)
|
+libbitcoind_la_LIBADD += $(BOOST_LIBS) $(SSL_LIBS) $(LIBSECP256K1) $(CRYPTO_LIBS) leveldb/$(MEMOBJ)
|
||||||
+libbitcoind_la_CPPFLAGS = $(BITCOIN_INCLUDES)
|
+libbitcoind_la_CPPFLAGS = $(BITCOIN_INCLUDES)
|
||||||
+libbitcoind_la_LDFLAGS = -lleveldb -L./leveldb $(RELDFLAGS) -no-undefined
|
+libbitcoind_la_LDFLAGS = -lleveldb -L./leveldb $(RELDFLAGS) -no-undefined
|
||||||
+libbitcoind_la_DEPENDENCIES = $(LIBSECP256K1) LIBLEVELDB_SHARED $(MEMOBJ)
|
+libbitcoind_la_DEPENDENCIES = $(LIBSECP256K1) LIBLEVELDB_SHARED $(MEMOBJ)
|
||||||
#
|
#
|
||||||
|
|
||||||
# bitcoin-cli binary #
|
# bitcoin-cli binary #
|
||||||
diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp
|
diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp
|
||||||
index cce687a..0f162ff 100644
|
index cce687a..0f162ff 100644
|
||||||
--- a/src/bitcoind.cpp
|
--- a/src/bitcoind.cpp
|
||||||
+++ b/src/bitcoind.cpp
|
+++ b/src/bitcoind.cpp
|
||||||
@@ -33,6 +33,10 @@
|
@@ -33,6 +33,10 @@
|
||||||
|
|
||||||
static bool fDaemon;
|
static bool fDaemon;
|
||||||
|
|
||||||
+#if ENABLE_DAEMONLIB
|
+#if ENABLE_DAEMONLIB
|
||||||
+extern void WaitForShutdown(boost::thread_group* threadGroup);
|
+extern void WaitForShutdown(boost::thread_group* threadGroup);
|
||||||
+#endif
|
+#endif
|
||||||
|
@ -216,13 +211,13 @@ index cce687a..0f162ff 100644
|
||||||
@@ -166,6 +170,7 @@ bool AppInit(int argc, char* argv[])
|
@@ -166,6 +170,7 @@ bool AppInit(int argc, char* argv[])
|
||||||
return fRet;
|
return fRet;
|
||||||
}
|
}
|
||||||
|
|
||||||
+#if !ENABLE_DAEMONLIB
|
+#if !ENABLE_DAEMONLIB
|
||||||
int main(int argc, char* argv[])
|
int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
SetupEnvironment();
|
SetupEnvironment();
|
||||||
@@ -175,3 +180,4 @@ int main(int argc, char* argv[])
|
@@ -175,3 +180,4 @@ int main(int argc, char* argv[])
|
||||||
|
|
||||||
return (AppInit(argc, argv) ? 0 : 1);
|
return (AppInit(argc, argv) ? 0 : 1);
|
||||||
}
|
}
|
||||||
+#endif
|
+#endif
|
||||||
|
@ -231,9 +226,9 @@ index dcb2b29..5ce68ba 100644
|
||||||
--- a/src/init.h
|
--- a/src/init.h
|
||||||
+++ b/src/init.h
|
+++ b/src/init.h
|
||||||
@@ -18,6 +18,11 @@ class thread_group;
|
@@ -18,6 +18,11 @@ class thread_group;
|
||||||
|
|
||||||
extern CWallet* pwalletMain;
|
extern CWallet* pwalletMain;
|
||||||
|
|
||||||
+#if ENABLE_DAEMONLIB
|
+#if ENABLE_DAEMONLIB
|
||||||
+#include <boost/filesystem/path.hpp>
|
+#include <boost/filesystem/path.hpp>
|
||||||
+#include <boost/thread/mutex.hpp>
|
+#include <boost/thread/mutex.hpp>
|
||||||
|
@ -248,24 +243,24 @@ index 2bd2cad..490ba66 100644
|
||||||
+++ b/src/leveldb/Makefile
|
+++ b/src/leveldb/Makefile
|
||||||
@@ -103,7 +103,7 @@ check: all $(PROGRAMS) $(TESTS)
|
@@ -103,7 +103,7 @@ check: all $(PROGRAMS) $(TESTS)
|
||||||
for t in $(TESTS); do echo "***** Running $$t"; ./$$t || exit 1; done
|
for t in $(TESTS); do echo "***** Running $$t"; ./$$t || exit 1; done
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
- -rm -f $(PROGRAMS) $(BENCHMARKS) $(LIBRARY) $(SHARED) $(MEMENVLIBRARY) */*.o */*/*.o ios-x86/*/*.o ios-arm/*/*.o build_config.mk
|
- -rm -f $(PROGRAMS) $(BENCHMARKS) $(LIBRARY) $(SHARED) $(MEMENVLIBRARY) */*.o */*/*.o ios-x86/*/*.o ios-arm/*/*.o build_config.mk
|
||||||
+ -rm -f $(PROGRAMS) $(BENCHMARKS) $(LIBRARY) $(SHARED) $(MEMENVLIBRARY) */*.o */*/*.lo helpers/memenv/.deps/*.Plo helpers/memenv/.deps/*.Tpo */*/*.o ios-x86/*/*.o ios-arm/*/*.o build_config.mk
|
+ -rm -f $(PROGRAMS) $(BENCHMARKS) $(LIBRARY) $(SHARED) $(MEMENVLIBRARY) */*.o */*/*.lo helpers/memenv/.deps/*.Plo helpers/memenv/.deps/*.Tpo */*/*.o ios-x86/*/*.o ios-arm/*/*.o build_config.mk
|
||||||
-rm -rf ios-x86/* ios-arm/*
|
-rm -rf ios-x86/* ios-arm/*
|
||||||
|
|
||||||
$(LIBRARY): $(LIBOBJECTS)
|
$(LIBRARY): $(LIBOBJECTS)
|
||||||
@@ -192,6 +192,10 @@ $(MEMENVLIBRARY) : $(MEMENVOBJECTS)
|
@@ -192,6 +192,10 @@ $(MEMENVLIBRARY) : $(MEMENVOBJECTS)
|
||||||
rm -f $@
|
rm -f $@
|
||||||
$(AR) -rs $@ $(MEMENVOBJECTS)
|
$(AR) -rs $@ $(MEMENVOBJECTS)
|
||||||
|
|
||||||
+helpers/memenv/memenv.lo: helpers/memenv/memenv.cc
|
+helpers/memenv/memenv.lo: helpers/memenv/memenv.cc
|
||||||
+ -mkdir -p helpers/memenv/.deps
|
+ -mkdir -p helpers/memenv/.deps
|
||||||
+ /bin/bash ../../libtool --tag=CXX --mode=compile $(CXX) $(CXXFLAGS) $(CFLAGS) -fPIC -MT $@ -MD -MP -MF helpers/memenv/.deps/memenv.Tpo -c -o $@ $<
|
+ /bin/bash ../../libtool --tag=CXX --mode=compile $(CXX) $(CXXFLAGS) $(CFLAGS) -fPIC -MT $@ -MD -MP -MF helpers/memenv/.deps/memenv.Tpo -c -o $@ $<
|
||||||
+
|
+
|
||||||
memenv_test : helpers/memenv/memenv_test.o $(MEMENVLIBRARY) $(LIBRARY) $(TESTHARNESS)
|
memenv_test : helpers/memenv/memenv_test.o $(MEMENVLIBRARY) $(LIBRARY) $(TESTHARNESS)
|
||||||
$(CXX) $(LDFLAGS) helpers/memenv/memenv_test.o $(MEMENVLIBRARY) $(LIBRARY) $(TESTHARNESS) -o $@ $(LIBS)
|
$(CXX) $(LDFLAGS) helpers/memenv/memenv_test.o $(MEMENVLIBRARY) $(LIBRARY) $(TESTHARNESS) -o $@ $(LIBS)
|
||||||
|
|
||||||
diff --git a/src/leveldbwrapper.h b/src/leveldbwrapper.h
|
diff --git a/src/leveldbwrapper.h b/src/leveldbwrapper.h
|
||||||
index c65e842..0e44bb5 100644
|
index c65e842..0e44bb5 100644
|
||||||
--- a/src/leveldbwrapper.h
|
--- a/src/leveldbwrapper.h
|
||||||
|
@ -273,14 +268,14 @@ index c65e842..0e44bb5 100644
|
||||||
@@ -29,10 +29,16 @@ class CLevelDBBatch
|
@@ -29,10 +29,16 @@ class CLevelDBBatch
|
||||||
{
|
{
|
||||||
friend class CLevelDBWrapper;
|
friend class CLevelDBWrapper;
|
||||||
|
|
||||||
+#if ENABLE_DAEMONLIB
|
+#if ENABLE_DAEMONLIB
|
||||||
+public:
|
+public:
|
||||||
+#else
|
+#else
|
||||||
private:
|
private:
|
||||||
+#endif
|
+#endif
|
||||||
leveldb::WriteBatch batch;
|
leveldb::WriteBatch batch;
|
||||||
|
|
||||||
+#if !ENABLE_DAEMONLIB
|
+#if !ENABLE_DAEMONLIB
|
||||||
public:
|
public:
|
||||||
+#endif
|
+#endif
|
||||||
|
@ -288,7 +283,7 @@ index c65e842..0e44bb5 100644
|
||||||
void Write(const K& key, const V& value)
|
void Write(const K& key, const V& value)
|
||||||
{
|
{
|
||||||
@@ -63,7 +69,11 @@ public:
|
@@ -63,7 +69,11 @@ public:
|
||||||
|
|
||||||
class CLevelDBWrapper
|
class CLevelDBWrapper
|
||||||
{
|
{
|
||||||
+#if ENABLE_DAEMONLIB
|
+#if ENABLE_DAEMONLIB
|
||||||
|
@ -298,17 +293,14 @@ index c65e842..0e44bb5 100644
|
||||||
+#endif
|
+#endif
|
||||||
//! custom environment this database is using (may be NULL in case of default environment)
|
//! custom environment this database is using (may be NULL in case of default environment)
|
||||||
leveldb::Env* penv;
|
leveldb::Env* penv;
|
||||||
|
|
||||||
@@ -85,7 +95,9 @@ private:
|
@@ -85,7 +95,9 @@ private:
|
||||||
//! the database itself
|
//! the database itself
|
||||||
leveldb::DB* pdb;
|
leveldb::DB* pdb;
|
||||||
|
|
||||||
+#if !ENABLE_DAEMONLIB
|
+#if !ENABLE_DAEMONLIB
|
||||||
public:
|
public:
|
||||||
+#endif
|
+#endif
|
||||||
CLevelDBWrapper(const boost::filesystem::path& path, size_t nCacheSize, bool fMemory = false, bool fWipe = false);
|
CLevelDBWrapper(const boost::filesystem::path& path, size_t nCacheSize, bool fMemory = false, bool fWipe = false);
|
||||||
~CLevelDBWrapper();
|
~CLevelDBWrapper();
|
||||||
|
|
||||||
--
|
|
||||||
2.3.2 (Apple Git-55)
|
|
||||||
|
|
||||||
|
|
|
@ -1,35 +0,0 @@
|
||||||
#!/usr/bin/env node
|
|
||||||
|
|
||||||
/**
|
|
||||||
* bitcoind.js example
|
|
||||||
*/
|
|
||||||
|
|
||||||
process.title = 'bitcoind.js';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* daemon
|
|
||||||
*/
|
|
||||||
|
|
||||||
var daemon = require('../index.js').daemon({
|
|
||||||
directory: process.env.BITCOINDJS_DIR || '~/.bitcoin'
|
|
||||||
});
|
|
||||||
|
|
||||||
daemon.on('error', function(err) {
|
|
||||||
daemon.log('error="%s"', err.message);
|
|
||||||
});
|
|
||||||
|
|
||||||
daemon.on('ready', function(err, result) {
|
|
||||||
console.log('Ready!');
|
|
||||||
|
|
||||||
daemon.getBlock('000000000000000082ccf8f1557c5d40b21edabb18d2d691cfbf87118bac7254', function(err, block) {
|
|
||||||
if (err) {
|
|
||||||
console.log(err);
|
|
||||||
}
|
|
||||||
console.log('block', block);
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
daemon.on('open', function(status) {
|
|
||||||
daemon.log('status="%s"', status);
|
|
||||||
});
|
|
|
@ -13,7 +13,8 @@ process.title = 'bitcoind.js';
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var daemon = require('../').daemon({
|
var daemon = require('../').daemon({
|
||||||
directory: process.env.BITCOINDJS_DIR || '~/.bitcoin'
|
datadir: process.env.BITCOINDJS_DIR || '~/.bitcoin',
|
||||||
|
network: 'regtest'
|
||||||
});
|
});
|
||||||
|
|
||||||
daemon.on('error', function(err) {
|
daemon.on('error', function(err) {
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
#!/usr/bin/env node
|
|
||||||
|
|
||||||
/**
|
|
||||||
* bitcoind.js example
|
|
||||||
*/
|
|
||||||
|
|
||||||
process.title = 'bitcoind_stripped.js';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* daemon
|
|
||||||
*/
|
|
||||||
|
|
||||||
var daemon = require('../index_stripped.js')({
|
|
||||||
directory: '~/.libbitcoind-example'
|
|
||||||
});
|
|
||||||
|
|
||||||
daemon.on('error', function(err) {
|
|
||||||
daemon.log('error="%s"', err.message);
|
|
||||||
});
|
|
||||||
|
|
||||||
daemon.on('open', function(status) {
|
|
||||||
daemon.log('status="%s"', status);
|
|
||||||
});
|
|
|
@ -8,7 +8,7 @@ var log = chainlib.log;
|
||||||
|
|
||||||
var configuration = {
|
var configuration = {
|
||||||
datadir: process.env.BITCOINDJS_DIR || '~/.bitcoin',
|
datadir: process.env.BITCOINDJS_DIR || '~/.bitcoin',
|
||||||
testnet: true
|
network: 'testnet'
|
||||||
};
|
};
|
||||||
|
|
||||||
var node = new BitcoinNode(configuration);
|
var node = new BitcoinNode(configuration);
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
server=1
|
||||||
|
whitelist=127.0.0.1
|
||||||
|
txindex=1
|
||||||
|
rpcallowip=127.0.0.1
|
||||||
|
rpcuser=bitcoin
|
||||||
|
rpcpassword=local321
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
// These tests require a fully synced Bitcore Code data directory.
|
// These tests require a fully synced Bitcore Code data directory.
|
||||||
// To run the tests: $ mocha -R spec index.js
|
// To run the tests: $ mocha -R spec livenet.js
|
||||||
|
|
||||||
var chai = require('chai');
|
var chai = require('chai');
|
||||||
var bitcore = require('bitcore');
|
var bitcore = require('bitcore');
|
||||||
|
@ -23,7 +23,7 @@ describe('Basic Functionality', function() {
|
||||||
before(function(done) {
|
before(function(done) {
|
||||||
this.timeout(30000);
|
this.timeout(30000);
|
||||||
bitcoind = require('../').daemon({
|
bitcoind = require('../').daemon({
|
||||||
directory: process.env.BITCOINDJS_DIR || '~/.bitcoin',
|
datadir: process.env.BITCOINDJS_DIR || '~/.bitcoin',
|
||||||
});
|
});
|
||||||
|
|
||||||
bitcoind.on('error', function(err) {
|
bitcoind.on('error', function(err) {
|
|
@ -0,0 +1,172 @@
|
||||||
|
'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
|
||||||
|
|
||||||
|
if (process.env.BITCOINDJS_ENV !== 'test') {
|
||||||
|
console.log('Please set the environment variable BITCOINDJS_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 bitcoind;
|
||||||
|
|
||||||
|
/* jshint unused: false */
|
||||||
|
var should = chai.should();
|
||||||
|
var assert = chai.assert;
|
||||||
|
var sinon = require('sinon');
|
||||||
|
var BitcoinRPC = require('bitcoind-rpc');
|
||||||
|
var blockHashes = [];
|
||||||
|
|
||||||
|
describe('Basic Functionality', function() {
|
||||||
|
|
||||||
|
before(function(done) {
|
||||||
|
this.timeout(30000);
|
||||||
|
|
||||||
|
var datadir = __dirname + '/data';
|
||||||
|
|
||||||
|
rimraf(datadir + '/regtest', function(err) {
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
|
||||||
|
bitcoind = require('../').daemon({
|
||||||
|
datadir: datadir,
|
||||||
|
network: 'regtest'
|
||||||
|
});
|
||||||
|
|
||||||
|
bitcoind.on('error', function(err) {
|
||||||
|
bitcoind.log('error="%s"', err.message);
|
||||||
|
});
|
||||||
|
|
||||||
|
bitcoind.on('open', function(status) {
|
||||||
|
bitcoind.log('status="%s"', status);
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log('Waiting for Bitcoin Core to initialize...');
|
||||||
|
|
||||||
|
bitcoind.on('ready', function() {
|
||||||
|
|
||||||
|
var client = new BitcoinRPC({
|
||||||
|
protocol: 'http',
|
||||||
|
host: '127.0.0.1',
|
||||||
|
port: 18332,
|
||||||
|
user: 'bitcoin',
|
||||||
|
pass: 'local321'
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log('Generating 100 blocks...');
|
||||||
|
|
||||||
|
client.generate(100, function(err, response) {
|
||||||
|
if (err) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
blockHashes = response.result;
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
after(function(done) {
|
||||||
|
this.timeout(20000);
|
||||||
|
bitcoind.stop(function(err, result) {
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('mempool functionality', function() {
|
||||||
|
|
||||||
|
var fromAddress = 'mszYqVnqKoQx4jcTdJXxwKAissE3Jbrrc1';
|
||||||
|
var utxo = {
|
||||||
|
address: fromAddress,
|
||||||
|
txId: 'a477af6b2667c29670467e4e0728b685ee07b240235771862318e29ddbe58458',
|
||||||
|
outputIndex: 0,
|
||||||
|
script: bitcore.Script.buildPublicKeyHashOut(fromAddress).toString(),
|
||||||
|
satoshis: 100000
|
||||||
|
};
|
||||||
|
var toAddress = 'mrU9pEmAx26HcbKVrABvgL7AwA5fjNFoDc';
|
||||||
|
var changeAddress = 'mgBCJAsvzgT2qNNeXsoECg2uPKrUsZ76up';
|
||||||
|
var changeAddressP2SH = '2N7T3TAetJrSCruQ39aNrJvYLhG1LJosujf';
|
||||||
|
var privateKey = 'cSBnVM4xvxarwGQuAfQFwqDg9k5tErHUHzgWsEfD4zdwUasvqRVY';
|
||||||
|
var private1 = '6ce7e97e317d2af16c33db0b9270ec047a91bff3eff8558afb5014afb2bb5976';
|
||||||
|
var private2 = 'c9b26b0f771a0d2dad88a44de90f05f416b3b385ff1d989343005546a0032890';
|
||||||
|
var tx = new bitcore.Transaction();
|
||||||
|
tx.from(utxo);
|
||||||
|
tx.to(toAddress, 50000);
|
||||||
|
tx.change(changeAddress);
|
||||||
|
tx.sign(privateKey);
|
||||||
|
|
||||||
|
it('will add an unchecked transaction', function() {
|
||||||
|
var added = bitcoind.addMempoolUncheckedTransaction(tx.serialize());
|
||||||
|
added.should.equal(true);
|
||||||
|
bitcoind.getTransaction(tx.hash, true, function(err, txBuffer) {
|
||||||
|
if(err) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
var expected = tx.toBuffer().toString('hex');
|
||||||
|
txBuffer.toString('hex').should.equal(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it('get outputs by address', function() {
|
||||||
|
var outputs = bitcoind.getMempoolOutputs(changeAddress);
|
||||||
|
var expected = [
|
||||||
|
{
|
||||||
|
script: 'OP_DUP OP_HASH160 073b7eae2823efa349e3b9155b8a735526463a0f OP_EQUALVERIFY OP_CHECKSIG',
|
||||||
|
satoshis: 40000,
|
||||||
|
txid: tx.hash,
|
||||||
|
outputIndex: 1
|
||||||
|
}
|
||||||
|
];
|
||||||
|
outputs.should.deep.equal(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('get blocks by hash', function() {
|
||||||
|
|
||||||
|
[0,1,2,3,5,6,7,8,9].forEach(function(i) {
|
||||||
|
it('generated block ' + i, function(done) {
|
||||||
|
bitcoind.getBlock(blockHashes[i], function(err, response) {
|
||||||
|
if (err) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
should.exist(response);
|
||||||
|
var block = bitcore.Block.fromBuffer(response);
|
||||||
|
block.hash.should.equal(blockHashes[i]);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('get blocks by height', function() {
|
||||||
|
|
||||||
|
[0,1,2,3,5,6,7,8,9].forEach(function(i) {
|
||||||
|
it('generated block ' + i, function(done) {
|
||||||
|
// add the genesis block
|
||||||
|
var height = i + 1;
|
||||||
|
bitcoind.getBlock(i + 1, function(err, response) {
|
||||||
|
if (err) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
should.exist(response);
|
||||||
|
var block = bitcore.Block.fromBuffer(response);
|
||||||
|
block.hash.should.equal(blockHashes[i]);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
|
@ -37,14 +37,6 @@ function Daemon(options) {
|
||||||
|
|
||||||
this.options = 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) {
|
if (!this.options.datadir) {
|
||||||
this.options.datadir = '~/.bitcoind.js';
|
this.options.datadir = '~/.bitcoind.js';
|
||||||
|
@ -54,7 +46,13 @@ function Daemon(options) {
|
||||||
|
|
||||||
this.datadir = this.options.datadir;
|
this.datadir = this.options.datadir;
|
||||||
this.config = this.datadir + '/bitcoin.conf';
|
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)) {
|
if (!fs.existsSync(this.datadir)) {
|
||||||
mkdirp.sync(this.datadir);
|
mkdirp.sync(this.datadir);
|
||||||
|
@ -83,7 +81,6 @@ function Daemon(options) {
|
||||||
fs.writeFileSync(data + peers);
|
fs.writeFileSync(data + peers);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy config into testnet dir
|
|
||||||
if (this.network.name === 'testnet') {
|
if (this.network.name === 'testnet') {
|
||||||
if (!fs.existsSync(this.datadir + '/testnet3')) {
|
if (!fs.existsSync(this.datadir + '/testnet3')) {
|
||||||
fs.mkdirSync(this.datadir + '/testnet3');
|
fs.mkdirSync(this.datadir + '/testnet3');
|
||||||
|
@ -93,6 +90,15 @@ function Daemon(options) {
|
||||||
fs.readFileSync(this.config));
|
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) {
|
Object.keys(exports).forEach(function(key) {
|
||||||
self[key] = exports[key];
|
self[key] = exports[key];
|
||||||
});
|
});
|
||||||
|
@ -120,6 +126,13 @@ Daemon.testnet = {
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Daemon.regtest = {
|
||||||
|
name: 'regtest',
|
||||||
|
peers: [
|
||||||
|
// hardcoded peers
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
// Make sure signal handlers are not overwritten
|
// Make sure signal handlers are not overwritten
|
||||||
Daemon._signalQueue = [];
|
Daemon._signalQueue = [];
|
||||||
Daemon._processOn = process.on;
|
Daemon._processOn = process.on;
|
||||||
|
|
|
@ -1,959 +0,0 @@
|
||||||
/**
|
|
||||||
* bitcoind.js
|
|
||||||
* Copyright (c) 2014, BitPay (MIT License)
|
|
||||||
* A bitcoind node.js binding.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var net = require('net');
|
|
||||||
var EventEmitter = require('events').EventEmitter;
|
|
||||||
var bitcoindjs = require('../build/Debug/bitcoindjs.node');
|
|
||||||
var util = require('util');
|
|
||||||
var fs = require('fs');
|
|
||||||
var mkdirp = require('mkdirp');
|
|
||||||
var tiny = require('tiny').json;
|
|
||||||
|
|
||||||
// Compatibility with old node versions:
|
|
||||||
var setImmediate = global.setImmediate || process.nextTick.bind(process);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Daemon
|
|
||||||
*/
|
|
||||||
|
|
||||||
var daemon = Daemon;
|
|
||||||
|
|
||||||
function Daemon(options) {
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
if (!(this instanceof Daemon)) {
|
|
||||||
return new Daemon(options);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Object.keys(this.instances).length) {
|
|
||||||
throw new
|
|
||||||
Error('bitcoind.js cannot be instantiated more than once.');
|
|
||||||
}
|
|
||||||
|
|
||||||
EventEmitter.call(this);
|
|
||||||
|
|
||||||
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';
|
|
||||||
}
|
|
||||||
|
|
||||||
this.options.datadir = this.options.datadir.replace(/^~/, process.env.HOME);
|
|
||||||
|
|
||||||
this.datadir = this.options.datadir;
|
|
||||||
this.config = this.datadir + '/bitcoin.conf';
|
|
||||||
this.network = Daemon[this.options.testnet ? 'testnet' : 'livenet'];
|
|
||||||
|
|
||||||
if (!fs.existsSync(this.datadir)) {
|
|
||||||
mkdirp.sync(this.datadir);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!fs.existsSync(this.config)) {
|
|
||||||
var password = ''
|
|
||||||
+ Math.random().toString(36).slice(2)
|
|
||||||
+ Math.random().toString(36).slice(2)
|
|
||||||
+ Math.random().toString(36).slice(2);
|
|
||||||
fs.writeFileSync(this.config, ''
|
|
||||||
+ 'rpcuser=bitcoinrpc\n'
|
|
||||||
+ 'rpcpassword=' + password + '\n'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add hardcoded peers
|
|
||||||
var data = fs.readFileSync(this.config, 'utf8');
|
|
||||||
if (this.network.peers.length) {
|
|
||||||
var peers = this.network.peers.reduce(function(out, peer) {
|
|
||||||
if (!~data.indexOf('addnode=' + peer)) {
|
|
||||||
return out + 'addnode=' + peer + '\n';
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
}, '\n');
|
|
||||||
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');
|
|
||||||
}
|
|
||||||
fs.writeFileSync(
|
|
||||||
this.datadir + '/testnet3/bitcoin.conf',
|
|
||||||
fs.readFileSync(this.config));
|
|
||||||
}
|
|
||||||
|
|
||||||
Object.keys(exports).forEach(function(key) {
|
|
||||||
self[key] = exports[key];
|
|
||||||
});
|
|
||||||
|
|
||||||
this.on('newListener', function(name) {
|
|
||||||
if (name === 'open') {
|
|
||||||
self.start();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Daemon.prototype.__proto__ = EventEmitter.prototype;
|
|
||||||
|
|
||||||
Daemon.livenet = {
|
|
||||||
name: 'livenet',
|
|
||||||
peers: [
|
|
||||||
// hardcoded peers
|
|
||||||
]
|
|
||||||
};
|
|
||||||
|
|
||||||
Daemon.testnet = {
|
|
||||||
name: 'testnet',
|
|
||||||
peers: [
|
|
||||||
// hardcoded peers
|
|
||||||
]
|
|
||||||
};
|
|
||||||
|
|
||||||
// Make sure signal handlers are not overwritten
|
|
||||||
Daemon._signalQueue = [];
|
|
||||||
Daemon._processOn = process.on;
|
|
||||||
process.addListener =
|
|
||||||
process.on = function(name, listener) {
|
|
||||||
if (~['SIGINT', 'SIGHUP', 'SIGQUIT'].indexOf(name.toUpperCase())) {
|
|
||||||
if (!Daemon.global || !Daemon.global._started) {
|
|
||||||
Daemon._signalQueue.push([name, listener]);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Daemon._processOn.apply(this, arguments);
|
|
||||||
};
|
|
||||||
|
|
||||||
Daemon.instances = {};
|
|
||||||
Daemon.prototype.instances = Daemon.instances;
|
|
||||||
|
|
||||||
Daemon.__defineGetter__('global', function() {
|
|
||||||
if (daemon.stopping) return [];
|
|
||||||
return Daemon.instances[Object.keys(Daemon.instances)[0]];
|
|
||||||
});
|
|
||||||
|
|
||||||
Daemon.prototype.__defineGetter__('global', function() {
|
|
||||||
if (daemon.stopping) return [];
|
|
||||||
return Daemon.global;
|
|
||||||
});
|
|
||||||
|
|
||||||
tiny.debug = function() {};
|
|
||||||
tiny.prototype.debug = function() {};
|
|
||||||
tiny.error = function() {};
|
|
||||||
tiny.prototype.error = function() {};
|
|
||||||
|
|
||||||
Daemon.db = tiny({
|
|
||||||
file: process.env.HOME + '/.bitcoindjs.db',
|
|
||||||
saveIndex: false,
|
|
||||||
initialCache: false
|
|
||||||
});
|
|
||||||
|
|
||||||
Daemon.prototype.start = function(options, callback) {
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
if (!callback) {
|
|
||||||
callback = options;
|
|
||||||
options = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!options) {
|
|
||||||
options = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!callback) {
|
|
||||||
callback = utils.NOOP;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.instances[this.datadir]) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.instances[this.datadir] = true;
|
|
||||||
|
|
||||||
var none = {};
|
|
||||||
var isSignal = {};
|
|
||||||
var sigint = { name: 'SIGINT', signal: isSignal };
|
|
||||||
var sighup = { name: 'SIGHUP', signal: isSignal };
|
|
||||||
var sigquit = { name: 'SIGQUIT', signal: isSignal };
|
|
||||||
var exitCaught = none;
|
|
||||||
var errorCaught = none;
|
|
||||||
|
|
||||||
Object.keys(this.options).forEach(function(key) {
|
|
||||||
if (options[key] == null) {
|
|
||||||
options[key] = self.options[key];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
bitcoindjs.start(options, function(err, status) {
|
|
||||||
self._started = true;
|
|
||||||
|
|
||||||
|
|
||||||
[sigint, sighup, sigquit].forEach(function(signal) {
|
|
||||||
process.on(signal.name, signal.listener = function() {
|
|
||||||
if (process.listeners(signal.name).length > 1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!self._shutdown) {
|
|
||||||
process.exit(0);
|
|
||||||
} else {
|
|
||||||
self.stop();
|
|
||||||
exitCaught = signal;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Finally set signal handlers
|
|
||||||
process.on = process.addListener = Daemon._processOn;
|
|
||||||
Daemon._signalQueue.forEach(function(event) {
|
|
||||||
process.on(event[0], event[1]);
|
|
||||||
});
|
|
||||||
|
|
||||||
var exit = process.exit;
|
|
||||||
self._exit = function() {
|
|
||||||
return exit.apply(process, arguments);
|
|
||||||
};
|
|
||||||
|
|
||||||
process.exit = function(code) {
|
|
||||||
exitCaught = code || 0;
|
|
||||||
if (!self._shutdown) {
|
|
||||||
return self._exit(code);
|
|
||||||
}
|
|
||||||
self.stop();
|
|
||||||
};
|
|
||||||
|
|
||||||
process.on('uncaughtException', function(err) {
|
|
||||||
if (process.listeners('uncaughtException').length > 1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
errorCaught = err;
|
|
||||||
self.error('Uncaught error: shutting down safely before throwing...');
|
|
||||||
if (!self._shutdown) {
|
|
||||||
if (err && err.stack) {
|
|
||||||
console.error(err.stack);
|
|
||||||
}
|
|
||||||
self._exit(1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
self.stop();
|
|
||||||
});
|
|
||||||
|
|
||||||
setTimeout(function callee() {
|
|
||||||
// Wait until wallet is loaded:
|
|
||||||
if (callback) {
|
|
||||||
callback(err ? err : null);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (err) {
|
|
||||||
self.emit('error', err);
|
|
||||||
} else {
|
|
||||||
if (callback) {
|
|
||||||
self.emit('open', status);
|
|
||||||
} else {
|
|
||||||
self.emit('status', status);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (callback) {
|
|
||||||
callback = null;
|
|
||||||
}
|
|
||||||
}, 100);
|
|
||||||
});
|
|
||||||
|
|
||||||
// bitcoind's boost threads aren't in the thread pool
|
|
||||||
// or on node's event loop, so we need to keep node open.
|
|
||||||
this._shutdown = setInterval(function() {
|
|
||||||
if (!self._stoppingSaid && bitcoindjs.stopping()) {
|
|
||||||
self._stoppingSaid = true;
|
|
||||||
self.log('shutting down...');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bitcoindjs.stopped()) {
|
|
||||||
self.log('shut down.');
|
|
||||||
|
|
||||||
clearInterval(self._shutdown);
|
|
||||||
delete self._shutdown;
|
|
||||||
|
|
||||||
if (exitCaught !== none) {
|
|
||||||
if (exitCaught.signal === isSignal) {
|
|
||||||
process.removeListener(exitCaught.name, exitCaught.listener);
|
|
||||||
setImmediate(function() {
|
|
||||||
process.kill(process.pid, exitCaught.name);
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
return self._exit(exitCaught);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (errorCaught !== none) {
|
|
||||||
if (errorCaught && errorCaught.stack) {
|
|
||||||
console.error(errorCaught.stack);
|
|
||||||
}
|
|
||||||
return self._exit(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, 1000);
|
|
||||||
};
|
|
||||||
|
|
||||||
Daemon.prototype.getBlock = function(blockhash, callback) {
|
|
||||||
if (daemon.stopping) return [];
|
|
||||||
return bitcoindjs.getBlock(blockhash, function(err, block) {
|
|
||||||
if (err) return callback(err);
|
|
||||||
return callback(null, daemon.block(block));
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
Daemon.prototype.getBlockHeight = function(height, callback) {
|
|
||||||
if (daemon.stopping) return [];
|
|
||||||
return bitcoindjs.getBlock(+height, function(err, block) {
|
|
||||||
if (err) return callback(err);
|
|
||||||
return callback(null, daemon.block(block));
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
Daemon.prototype.getTransaction =
|
|
||||||
Daemon.prototype.getTx = function(txid, blockhash, callback) {
|
|
||||||
if (daemon.stopping) return [];
|
|
||||||
if (typeof txid === 'object' && txid) {
|
|
||||||
var options = txid;
|
|
||||||
callback = blockhash;
|
|
||||||
txid = options.txid || options.tx || options.txhash || options.id || options.hash;
|
|
||||||
blockhash = options.blockhash || options.block;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof blockhash === 'function') {
|
|
||||||
callback = blockhash;
|
|
||||||
blockhash = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof blockhash !== 'string') {
|
|
||||||
if (blockhash) {
|
|
||||||
blockhash = blockhash.hash
|
|
||||||
|| blockhash.blockhash
|
|
||||||
|| (blockhash.getHash && blockhash.getHash())
|
|
||||||
|| '';
|
|
||||||
} else {
|
|
||||||
blockhash = '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return bitcoindjs.getTransaction(txid, blockhash, function(err, tx) {
|
|
||||||
if (err) return callback(err);
|
|
||||||
return callback(null, daemon.tx(tx));
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
Daemon.prototype.getTransactionWithBlock = function(txid, blockhash, callback) {
|
|
||||||
if (daemon.stopping) return [];
|
|
||||||
|
|
||||||
var self = this;
|
|
||||||
var slow = true;
|
|
||||||
|
|
||||||
if (typeof txid === 'object' && txid) {
|
|
||||||
var options = txid;
|
|
||||||
callback = blockhash;
|
|
||||||
txid = options.txid || options.tx || options.txhash || options.id || options.hash;
|
|
||||||
blockhash = options.blockhash || options.block;
|
|
||||||
slow = options.slow !== false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof blockhash === 'function') {
|
|
||||||
callback = blockhash;
|
|
||||||
blockhash = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof blockhash !== 'string') {
|
|
||||||
if (blockhash) {
|
|
||||||
blockhash = blockhash.hash
|
|
||||||
|| blockhash.blockhash
|
|
||||||
|| (blockhash.getHash && blockhash.getHash())
|
|
||||||
|| '';
|
|
||||||
} else {
|
|
||||||
blockhash = '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return bitcoindjs.getTransaction(txid, blockhash, function(err, tx) {
|
|
||||||
if (err) return callback(err);
|
|
||||||
|
|
||||||
if (slow && !tx.blockhash) {
|
|
||||||
return self.getBlockByTx(txid, function(err, block, tx_) {
|
|
||||||
if (err) return callback(err);
|
|
||||||
return callback(null, tx, block);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return bitcoindjs.getBlock(tx.blockhash, function(err, block) {
|
|
||||||
if (err) return callback(err);
|
|
||||||
return callback(null, daemon.tx(tx), daemon.block(block));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
Daemon.prototype.getInfo = function() {
|
|
||||||
if (daemon.stopping) return [];
|
|
||||||
return bitcoindjs.getInfo();
|
|
||||||
};
|
|
||||||
|
|
||||||
Daemon.prototype.getPeerInfo = function() {
|
|
||||||
if (daemon.stopping) return [];
|
|
||||||
return bitcoindjs.getPeerInfo();
|
|
||||||
};
|
|
||||||
|
|
||||||
Daemon.prototype.getAddresses = function() {
|
|
||||||
if (daemon.stopping) return [];
|
|
||||||
return bitcoindjs.getAddresses();
|
|
||||||
};
|
|
||||||
|
|
||||||
Daemon.prototype.getProgress = function(callback) {
|
|
||||||
if (daemon.stopping) return [];
|
|
||||||
return bitcoindjs.getProgress(callback);
|
|
||||||
};
|
|
||||||
|
|
||||||
Daemon.prototype.setGenerate = function(options) {
|
|
||||||
if (daemon.stopping) return [];
|
|
||||||
return bitcoindjs.setGenerate(options || {});
|
|
||||||
};
|
|
||||||
|
|
||||||
Daemon.prototype.getGenerate = function(options) {
|
|
||||||
if (daemon.stopping) return [];
|
|
||||||
return bitcoindjs.getGenerate(options || {});
|
|
||||||
};
|
|
||||||
|
|
||||||
Daemon.prototype.getMiningInfo = function() {
|
|
||||||
if (daemon.stopping) return [];
|
|
||||||
return bitcoindjs.getMiningInfo();
|
|
||||||
};
|
|
||||||
|
|
||||||
Daemon.prototype.getAddrTransactions = function(address, callback) {
|
|
||||||
if (daemon.stopping) return [];
|
|
||||||
return daemon.db.get('addr-tx/' + address, function(err, records) {
|
|
||||||
var options = {
|
|
||||||
address: address,
|
|
||||||
blockheight: (records || []).reduce(function(out, record) {
|
|
||||||
return record.blockheight > out
|
|
||||||
? record.blockheight
|
|
||||||
: out;
|
|
||||||
}, -1),
|
|
||||||
blocktime: (records || []).reduce(function(out, record) {
|
|
||||||
return record.blocktime > out
|
|
||||||
? record.blocktime
|
|
||||||
: out;
|
|
||||||
}, -1)
|
|
||||||
};
|
|
||||||
return bitcoindjs.getAddrTransactions(options, function(err, addr) {
|
|
||||||
if (err) return callback(err);
|
|
||||||
addr = daemon.addr(addr);
|
|
||||||
if (addr.tx[0] && !addr.tx[0].vout[0]) {
|
|
||||||
return daemon.db.set('addr-tx/' + address, [{
|
|
||||||
txid: null,
|
|
||||||
blockhash: null,
|
|
||||||
blockheight: null,
|
|
||||||
blocktime: null
|
|
||||||
}], function() {
|
|
||||||
return callback(null, daemon.addr({
|
|
||||||
address: addr.address,
|
|
||||||
tx: []
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
var set = [];
|
|
||||||
if (records && records.length) {
|
|
||||||
set = records;
|
|
||||||
}
|
|
||||||
addr.tx.forEach(function(tx) {
|
|
||||||
set.push({
|
|
||||||
txid: tx.txid,
|
|
||||||
blockhash: tx.blockhash,
|
|
||||||
blockheight: tx.blockheight,
|
|
||||||
blocktime: tx.blocktime
|
|
||||||
});
|
|
||||||
});
|
|
||||||
return daemon.db.set('addr-tx/' + address, set, function() {
|
|
||||||
return callback(null, addr);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
Daemon.prototype.getBestBlock = function(callback) {
|
|
||||||
if (daemon.stopping) return [];
|
|
||||||
var hash = bitcoindjs.getBestBlock();
|
|
||||||
return bitcoindjs.getBlock(hash, callback);
|
|
||||||
};
|
|
||||||
|
|
||||||
Daemon.prototype.getChainHeight = function() {
|
|
||||||
if (daemon.stopping) return [];
|
|
||||||
return bitcoindjs.getChainHeight();
|
|
||||||
};
|
|
||||||
|
|
||||||
Daemon.prototype.__defineGetter__('chainHeight', function() {
|
|
||||||
if (daemon.stopping) return [];
|
|
||||||
return this.getChainHeight();
|
|
||||||
});
|
|
||||||
|
|
||||||
Daemon.prototype.getBlockByTxid =
|
|
||||||
Daemon.prototype.getBlockByTx = function(txid, callback) {
|
|
||||||
if (daemon.stopping) return [];
|
|
||||||
return daemon.db.get('block-tx/' + txid, function(err, block) {
|
|
||||||
if (block) {
|
|
||||||
return self.getBlock(block.hash, function(err, block) {
|
|
||||||
if (err) return callback(err);
|
|
||||||
var tx_ = block.tx.filter(function(tx) {
|
|
||||||
return tx.txid === txid;
|
|
||||||
})[0];
|
|
||||||
return callback(null, block, tx_);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return bitcoindjs.getBlockByTx(txid, function(err, block, tx_) {
|
|
||||||
if (err) return callback(err);
|
|
||||||
daemon.db.set('block-tx/' + txid, { hash: block.hash }, utils.NOOP);
|
|
||||||
return callback(null, daemon.block(block), daemon.tx(tx_));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
Daemon.prototype.getBlocksByDate =
|
|
||||||
Daemon.prototype.getBlocksByTime = function(options, callback) {
|
|
||||||
if (daemon.stopping) return [];
|
|
||||||
return bitcoindjs.getBlocksByTime(options, function(err, blocks) {
|
|
||||||
if (err) return callback(err);
|
|
||||||
return callback(null, blocks.map(function(block) {
|
|
||||||
return daemon.block(block)
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
Daemon.prototype.getFromTx = function(txid, callback) {
|
|
||||||
if (daemon.stopping) return [];
|
|
||||||
return bitcoindjs.getFromTx(txid, function(err, txs) {
|
|
||||||
if (err) return callback(err);
|
|
||||||
return callback(null, txs.map(function(tx) {
|
|
||||||
return daemon.tx(tx)
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
Daemon.prototype.getLastFileIndex = function() {
|
|
||||||
if (daemon.stopping) return [];
|
|
||||||
return bitcoindjs.getLastFileIndex();
|
|
||||||
};
|
|
||||||
|
|
||||||
Daemon.prototype.log =
|
|
||||||
Daemon.prototype.info = function() {
|
|
||||||
if (daemon.stopping) return [];
|
|
||||||
if (this.options.silent) return;
|
|
||||||
if (typeof arguments[0] !== 'string') {
|
|
||||||
var out = util.inspect(arguments[0], null, 20, true);
|
|
||||||
return process.stdout.write('bitcoind.js: ' + out + '\n');
|
|
||||||
}
|
|
||||||
var out = util.format.apply(util, arguments);
|
|
||||||
return process.stdout.write('bitcoind.js: ' + out + '\n');
|
|
||||||
};
|
|
||||||
|
|
||||||
Daemon.prototype.error = function() {
|
|
||||||
if (daemon.stopping) return [];
|
|
||||||
if (this.options.silent) return;
|
|
||||||
if (typeof arguments[0] !== 'string') {
|
|
||||||
var out = util.inspect(arguments[0], null, 20, true);
|
|
||||||
return process.stderr.write('bitcoind.js: ' + out + '\n');
|
|
||||||
}
|
|
||||||
var out = util.format.apply(util, arguments);
|
|
||||||
return process.stderr.write('bitcoind.js: ' + out + '\n');
|
|
||||||
};
|
|
||||||
|
|
||||||
Daemon.prototype.stop =
|
|
||||||
Daemon.prototype.close = function(callback) {
|
|
||||||
if (daemon.stopping) return [];
|
|
||||||
var self = this;
|
|
||||||
return bitcoindjs.stop(function(err, status) {
|
|
||||||
if (err) {
|
|
||||||
self.error(err.message);
|
|
||||||
} else {
|
|
||||||
self.log(status);
|
|
||||||
}
|
|
||||||
if (!callback) return;
|
|
||||||
return callback(err, status);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
Daemon.prototype.__defineGetter__('stopping', function() {
|
|
||||||
return bitcoindjs.stopping() || bitcoindjs.stopped();
|
|
||||||
});
|
|
||||||
|
|
||||||
Daemon.prototype.__defineGetter__('stopped', function() {
|
|
||||||
return bitcoindjs.stopped();
|
|
||||||
});
|
|
||||||
|
|
||||||
Daemon.__defineGetter__('stopping', function() {
|
|
||||||
return bitcoindjs.stopping() || bitcoindjs.stopped();
|
|
||||||
});
|
|
||||||
|
|
||||||
Daemon.__defineGetter__('stopped', function() {
|
|
||||||
return bitcoindjs.stopped();
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Block
|
|
||||||
*/
|
|
||||||
|
|
||||||
function Block(data) {
|
|
||||||
if (!(this instanceof Block)) {
|
|
||||||
return new Block(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof data === 'string') {
|
|
||||||
return Block.fromHex(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data instanceof Block) {
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (daemon.stopping) return [];
|
|
||||||
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
Object.keys(data).forEach(function(key) {
|
|
||||||
if (!self[key]) {
|
|
||||||
self[key] = data[key];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this.tx = this.tx.map(function(tx) {
|
|
||||||
return daemon.tx(tx);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!this.hex) {
|
|
||||||
this.hex = this.toHex();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Object.defineProperty(Block.prototype, '_blockFlag', {
|
|
||||||
__proto__: null,
|
|
||||||
configurable: false,
|
|
||||||
enumerable: false,
|
|
||||||
writable: false,
|
|
||||||
value: {}
|
|
||||||
});
|
|
||||||
|
|
||||||
Block.isBlock = function(block) {
|
|
||||||
if (daemon.stopping) return [];
|
|
||||||
return block._blockFlag === Block.prototype._blockFlag;
|
|
||||||
};
|
|
||||||
|
|
||||||
Block.fromHex = function(hex) {
|
|
||||||
if (daemon.stopping) return [];
|
|
||||||
return daemon.block(bitcoindjs.blockFromHex(hex));
|
|
||||||
};
|
|
||||||
|
|
||||||
Block.prototype.getHash = function(enc) {
|
|
||||||
if (daemon.stopping) return [];
|
|
||||||
var data = bitcoindjs.getBlockHex(this);
|
|
||||||
if (!this.hash || this.hash !== data.hash) {
|
|
||||||
this.hash = data.hash;
|
|
||||||
}
|
|
||||||
if (enc === 'hex') return data.hash;
|
|
||||||
var buf = new Buffer(data.hash, 'hex');
|
|
||||||
var out = enc ? buf.toString(enc) : buf;
|
|
||||||
return out;
|
|
||||||
};
|
|
||||||
|
|
||||||
Block.prototype.verify = function() {
|
|
||||||
if (daemon.stopping) return [];
|
|
||||||
return this.verified = this.verified || bitcoindjs.verifyBlock(this);
|
|
||||||
};
|
|
||||||
|
|
||||||
Block.prototype.toHex = function() {
|
|
||||||
if (daemon.stopping) return [];
|
|
||||||
var hex = Block.toHex(this);
|
|
||||||
if (!this.hex || this.hex !== hex) {
|
|
||||||
this.hex = hex;
|
|
||||||
}
|
|
||||||
return hex;
|
|
||||||
};
|
|
||||||
|
|
||||||
Block.toHex = function(block) {
|
|
||||||
if (daemon.stopping) return [];
|
|
||||||
var data = bitcoindjs.getBlockHex(block);
|
|
||||||
return data.hex;
|
|
||||||
};
|
|
||||||
|
|
||||||
Block.prototype.toBinary = function() {
|
|
||||||
if (daemon.stopping) return [];
|
|
||||||
return Block.toBinary(this);
|
|
||||||
};
|
|
||||||
|
|
||||||
Block.toBinary = function(block) {
|
|
||||||
if (daemon.stopping) return [];
|
|
||||||
var data = bitcoindjs.getBlockHex(block);
|
|
||||||
return new Buffer(data.hex, 'hex');
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Transaction
|
|
||||||
*/
|
|
||||||
|
|
||||||
function Transaction(data) {
|
|
||||||
if (!(this instanceof Transaction)) {
|
|
||||||
return new Transaction(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof data === 'string') {
|
|
||||||
return Transaction.fromHex(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data instanceof Transaction) {
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (daemon.stopping) return [];
|
|
||||||
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
Object.keys(data).forEach(function(key) {
|
|
||||||
if (!self[key]) {
|
|
||||||
self[key] = data[key];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!this.hex) {
|
|
||||||
this.hex = this.toHex();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Object.defineProperty(Transaction.prototype, '_txFlag', {
|
|
||||||
__proto__: null,
|
|
||||||
configurable: false,
|
|
||||||
enumerable: false,
|
|
||||||
writable: false,
|
|
||||||
value: {}
|
|
||||||
});
|
|
||||||
|
|
||||||
Transaction.isTransaction =
|
|
||||||
Transaction.isTx = function(tx) {
|
|
||||||
if (daemon.stopping) return [];
|
|
||||||
return tx._txFlag === Transaction.prototype._txFlag;
|
|
||||||
};
|
|
||||||
|
|
||||||
Transaction.fromHex = function(hex) {
|
|
||||||
if (daemon.stopping) return [];
|
|
||||||
return daemon.tx(bitcoindjs.txFromHex(hex));
|
|
||||||
};
|
|
||||||
|
|
||||||
Transaction.prototype.verify = function() {
|
|
||||||
if (daemon.stopping) return [];
|
|
||||||
return this.verified = this.verified || bitcoindjs.verifyTransaction(this);
|
|
||||||
};
|
|
||||||
|
|
||||||
Transaction.prototype.sign =
|
|
||||||
Transaction.prototype.fill = function(options) {
|
|
||||||
if (daemon.stopping) return [];
|
|
||||||
return Transaction.fill(this, options);
|
|
||||||
};
|
|
||||||
|
|
||||||
Transaction.sign =
|
|
||||||
Transaction.fill = function(tx, options) {
|
|
||||||
if (daemon.stopping) return [];
|
|
||||||
var isTx = daemon.tx.isTx(tx)
|
|
||||||
, newTx;
|
|
||||||
|
|
||||||
if (!isTx) {
|
|
||||||
tx = daemon.tx(tx);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
newTx = bitcoindjs.fillTransaction(tx, options || {});
|
|
||||||
} catch (e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Object.keys(newTx).forEach(function(key) {
|
|
||||||
tx[key] = newTx[key];
|
|
||||||
});
|
|
||||||
|
|
||||||
return tx;
|
|
||||||
};
|
|
||||||
|
|
||||||
Transaction.prototype.getHash = function(enc) {
|
|
||||||
if (daemon.stopping) return [];
|
|
||||||
var data = bitcoindjs.getTxHex(this);
|
|
||||||
if (!this.txid || this.txid !== data.hash) {
|
|
||||||
this.txid = data.hash;
|
|
||||||
}
|
|
||||||
if (enc === 'hex') return data.hash;
|
|
||||||
var buf = new Buffer(data.hash, 'hex');
|
|
||||||
var out = enc ? buf.toString(enc) : buf;
|
|
||||||
return out;
|
|
||||||
};
|
|
||||||
|
|
||||||
Transaction.prototype.isCoinbase = function() {
|
|
||||||
if (daemon.stopping) return [];
|
|
||||||
return this.vin.length === 1 && this.vin[0].coinbase;
|
|
||||||
};
|
|
||||||
|
|
||||||
Transaction.prototype.toHex = function() {
|
|
||||||
if (daemon.stopping) return [];
|
|
||||||
var hex = Transaction.toHex(this);
|
|
||||||
if (!this.hex || hex !== this.hex) {
|
|
||||||
this.hex = hex;
|
|
||||||
}
|
|
||||||
return hex;
|
|
||||||
};
|
|
||||||
|
|
||||||
Transaction.toHex = function(tx) {
|
|
||||||
if (daemon.stopping) return [];
|
|
||||||
var data = bitcoindjs.getTxHex(tx);
|
|
||||||
return data.hex;
|
|
||||||
};
|
|
||||||
|
|
||||||
Transaction.prototype.toBinary = function() {
|
|
||||||
if (daemon.stopping) return [];
|
|
||||||
return Transaction.toBinary(this);
|
|
||||||
};
|
|
||||||
|
|
||||||
Transaction.toBinary = function(tx) {
|
|
||||||
if (daemon.stopping) return [];
|
|
||||||
var data = bitcoindjs.getTxHex(tx);
|
|
||||||
return new Buffer(data.hex, 'hex');
|
|
||||||
};
|
|
||||||
|
|
||||||
Transaction.broadcast = function(tx, options, callback) {
|
|
||||||
if (daemon.stopping) return [];
|
|
||||||
if (typeof tx === 'string') {
|
|
||||||
tx = { hex: tx };
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!callback) {
|
|
||||||
callback = options;
|
|
||||||
options = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!options) {
|
|
||||||
options = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
var fee = options.overrideFees = options.overrideFees || false;
|
|
||||||
var own = options.ownOnly = options.ownOnly || false;
|
|
||||||
|
|
||||||
if (!callback) {
|
|
||||||
callback = utils.NOOP;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!daemon.isTx(tx)) {
|
|
||||||
tx = daemon.tx(tx);
|
|
||||||
}
|
|
||||||
|
|
||||||
return bitcoindjs.broadcastTx(tx, fee, own, function(err, hash, tx) {
|
|
||||||
if (err) {
|
|
||||||
if (callback === utils.NOOP) {
|
|
||||||
daemon.global.emit('error', err);
|
|
||||||
}
|
|
||||||
return callback(err);
|
|
||||||
}
|
|
||||||
tx = daemon.tx(tx);
|
|
||||||
daemon.global.emit('broadcast', tx);
|
|
||||||
return callback(null, hash, tx);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
Transaction.prototype.broadcast = function(options, callback) {
|
|
||||||
if (daemon.stopping) return [];
|
|
||||||
if (!callback) {
|
|
||||||
callback = options;
|
|
||||||
options = null;
|
|
||||||
}
|
|
||||||
return Transaction.broadcast(this, options, callback);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Addresses
|
|
||||||
*/
|
|
||||||
|
|
||||||
function Addresses(data) {
|
|
||||||
if (!(this instanceof Addresses)) {
|
|
||||||
return new Addresses(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data instanceof Addresses) {
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (daemon.stopping) return [];
|
|
||||||
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
Object.keys(data).forEach(function(key) {
|
|
||||||
if (!self[key]) {
|
|
||||||
self[key] = data[key];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Object.defineProperty(Transaction.prototype, '_addrFlag', {
|
|
||||||
__proto__: null,
|
|
||||||
configurable: false,
|
|
||||||
enumerable: false,
|
|
||||||
writable: false,
|
|
||||||
value: {}
|
|
||||||
});
|
|
||||||
|
|
||||||
Addresses.isAddresses =
|
|
||||||
Addresses.isAddr = function(addr) {
|
|
||||||
if (daemon.stopping) return [];
|
|
||||||
return addr._txFlag === Addresses.prototype._addrFlag;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Utils
|
|
||||||
*/
|
|
||||||
|
|
||||||
var utils = {};
|
|
||||||
|
|
||||||
utils.forEach = function(obj, iter, done) {
|
|
||||||
if (daemon.stopping) return [];
|
|
||||||
var pending = obj.length;
|
|
||||||
if (!pending) return done();
|
|
||||||
var next = function() {
|
|
||||||
if (!--pending) done();
|
|
||||||
};
|
|
||||||
obj.forEach(function(item) {
|
|
||||||
iter(item, next);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
utils.NOOP = function() {};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Expose
|
|
||||||
*/
|
|
||||||
|
|
||||||
module.exports = exports = daemon;
|
|
||||||
|
|
||||||
exports.Daemon = daemon;
|
|
||||||
exports.daemon = daemon;
|
|
||||||
exports.bitcoind = daemon;
|
|
||||||
|
|
||||||
exports.native = bitcoindjs;
|
|
||||||
exports.bitcoindjs = bitcoindjs;
|
|
||||||
|
|
||||||
exports.Block = Block;
|
|
||||||
exports.block = Block;
|
|
||||||
|
|
||||||
exports.Transaction = Transaction;
|
|
||||||
exports.transaction = Transaction;
|
|
||||||
exports.tx = Transaction;
|
|
||||||
|
|
||||||
exports.Addresses = Addresses;
|
|
||||||
exports.addresses = Addresses;
|
|
||||||
exports.addr = Addresses;
|
|
||||||
|
|
||||||
exports.utils = utils;
|
|
31
lib/node.js
31
lib/node.js
|
@ -74,7 +74,7 @@ Node.prototype._loadBitcoinConf = function(config) {
|
||||||
Node.prototype._loadBitcoind = function(config) {
|
Node.prototype._loadBitcoind = function(config) {
|
||||||
var bitcoindConfig = {};
|
var bitcoindConfig = {};
|
||||||
bitcoindConfig.datadir = config.datadir;
|
bitcoindConfig.datadir = config.datadir;
|
||||||
bitcoindConfig.testnet = config.testnet;
|
bitcoindConfig.network = config.network;
|
||||||
|
|
||||||
// start the bitcoind daemon
|
// start the bitcoind daemon
|
||||||
this.bitcoind = daemon(bitcoindConfig);
|
this.bitcoind = daemon(bitcoindConfig);
|
||||||
|
@ -117,11 +117,23 @@ Node.prototype._syncBitcoind = function() {
|
||||||
};
|
};
|
||||||
|
|
||||||
Node.prototype._loadNetwork = function(config) {
|
Node.prototype._loadNetwork = function(config) {
|
||||||
if (config.network) {
|
if (config.network === 'testnet') {
|
||||||
Networks.add(config.network);
|
|
||||||
this.network = Networks.get(config.network.name);
|
|
||||||
} else if (config.testnet) {
|
|
||||||
this.network = Networks.get('testnet');
|
this.network = Networks.get('testnet');
|
||||||
|
} else if (config.network === 'regtest') {
|
||||||
|
Networks.remove(Networks.testnet);
|
||||||
|
Networks.add({
|
||||||
|
name: 'regtest',
|
||||||
|
alias: 'regtest',
|
||||||
|
pubkeyhash: 0x6f,
|
||||||
|
privatekey: 0xef,
|
||||||
|
scripthash: 0xc4,
|
||||||
|
xpubkey: 0x043587cf,
|
||||||
|
xprivkey: 0x04358394,
|
||||||
|
networkMagic: 0xfabfb5da,
|
||||||
|
port: 18444,
|
||||||
|
dnsSeeds: [ ]
|
||||||
|
});
|
||||||
|
this.network = Networks.get('regtest');
|
||||||
} else {
|
} else {
|
||||||
this.network = Networks.get('livenet');
|
this.network = Networks.get('livenet');
|
||||||
}
|
}
|
||||||
|
@ -142,11 +154,14 @@ Node.prototype._loadDB = function(config) {
|
||||||
// based on the network configuration and the datadir
|
// based on the network configuration and the datadir
|
||||||
$.checkArgument(config.datadir, 'Please specify "datadir" in configuration options');
|
$.checkArgument(config.datadir, 'Please specify "datadir" in configuration options');
|
||||||
$.checkState(this.network, 'Network property not defined');
|
$.checkState(this.network, 'Network property not defined');
|
||||||
|
var regtest = Networks.get('regtest');
|
||||||
var datadir = config.datadir.replace(/^~/, process.env.HOME);
|
var datadir = config.datadir.replace(/^~/, process.env.HOME);
|
||||||
if (this.network === Networks.testnet) {
|
if (this.network === Networks.livenet) {
|
||||||
config.db.path = datadir + '/testnet3/bitcoindjs.db';
|
|
||||||
} else if (this.network === Networks.livenet) {
|
|
||||||
config.db.path = datadir + '/bitcoindjs.db';
|
config.db.path = datadir + '/bitcoindjs.db';
|
||||||
|
} else if (this.network === Networks.testnet) {
|
||||||
|
config.db.path = datadir + '/testnet3/bitcoindjs.db';
|
||||||
|
} else if (this.network === regtest) {
|
||||||
|
config.db.path = datadir + '/regtest/bitcoindjs.db';
|
||||||
} else {
|
} else {
|
||||||
throw new Error('Unknown network: ' + this.network);
|
throw new Error('Unknown network: ' + this.network);
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,6 @@
|
||||||
"preinstall": "./bin/build-libbitcoind",
|
"preinstall": "./bin/build-libbitcoind",
|
||||||
"install": "./bin/build-bindings",
|
"install": "./bin/build-bindings",
|
||||||
"start": "node example",
|
"start": "node example",
|
||||||
"debug_install": "./bin/build-libbitcoind debug && ./bin/build-bindings debug",
|
|
||||||
"test": "NODE_ENV=test mocha --recursive",
|
"test": "NODE_ENV=test mocha --recursive",
|
||||||
"coverage": "istanbul cover _mocha -- --recursive"
|
"coverage": "istanbul cover _mocha -- --recursive"
|
||||||
},
|
},
|
||||||
|
@ -51,10 +50,12 @@
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"benchmark": "1.0.0",
|
"benchmark": "1.0.0",
|
||||||
"bitcoin": "^2.3.2",
|
"bitcoin": "^2.3.2",
|
||||||
|
"bitcoind-rpc": "^0.3.0",
|
||||||
"bitcore": "^0.12.12",
|
"bitcore": "^0.12.12",
|
||||||
"chai": "^3.0.0",
|
"chai": "^3.0.0",
|
||||||
"mocha": "~1.16.2",
|
"mocha": "~1.16.2",
|
||||||
"sinon": "^1.15.4",
|
"proxyquire": "^1.3.1",
|
||||||
"proxyquire": "^1.3.1"
|
"rimraf": "^2.4.2",
|
||||||
|
"sinon": "^1.15.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,6 +76,7 @@ static volatile bool shutdown_complete = false;
|
||||||
static char *g_data_dir = NULL;
|
static char *g_data_dir = NULL;
|
||||||
static bool g_rpc = false;
|
static bool g_rpc = false;
|
||||||
static bool g_testnet = false;
|
static bool g_testnet = false;
|
||||||
|
static bool g_regtest = false;
|
||||||
static bool g_txindex = false;
|
static bool g_txindex = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -105,6 +106,7 @@ struct async_node_data {
|
||||||
std::string datadir;
|
std::string datadir;
|
||||||
bool rpc;
|
bool rpc;
|
||||||
bool testnet;
|
bool testnet;
|
||||||
|
bool regtest;
|
||||||
bool txindex;
|
bool txindex;
|
||||||
Eternal<Function> callback;
|
Eternal<Function> callback;
|
||||||
};
|
};
|
||||||
|
@ -298,6 +300,7 @@ NAN_METHOD(StartBitcoind) {
|
||||||
std::string datadir = std::string("");
|
std::string datadir = std::string("");
|
||||||
bool rpc = false;
|
bool rpc = false;
|
||||||
bool testnet = false;
|
bool testnet = false;
|
||||||
|
bool regtest = false;
|
||||||
bool txindex = false;
|
bool txindex = false;
|
||||||
|
|
||||||
if (args.Length() >= 2 && args[0]->IsObject() && args[1]->IsFunction()) {
|
if (args.Length() >= 2 && args[0]->IsObject() && args[1]->IsFunction()) {
|
||||||
|
@ -309,8 +312,14 @@ NAN_METHOD(StartBitcoind) {
|
||||||
if (options->Get(NanNew<String>("rpc"))->IsBoolean()) {
|
if (options->Get(NanNew<String>("rpc"))->IsBoolean()) {
|
||||||
rpc = options->Get(NanNew<String>("rpc"))->ToBoolean()->IsTrue();
|
rpc = options->Get(NanNew<String>("rpc"))->ToBoolean()->IsTrue();
|
||||||
}
|
}
|
||||||
if (options->Get(NanNew<String>("testnet"))->IsBoolean()) {
|
if (options->Get(NanNew<String>("network"))->IsString()) {
|
||||||
testnet = options->Get(NanNew<String>("testnet"))->ToBoolean()->IsTrue();
|
String::Utf8Value network_(options->Get(NanNew<String>("network"))->ToString());
|
||||||
|
std::string network = std::string(*network_);
|
||||||
|
if (network == "testnet") {
|
||||||
|
testnet = true;
|
||||||
|
} else if (network == "regtest") {
|
||||||
|
regtest = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (options->Get(NanNew<String>("txindex"))->IsBoolean()) {
|
if (options->Get(NanNew<String>("txindex"))->IsBoolean()) {
|
||||||
txindex = options->Get(NanNew<String>("txindex"))->ToBoolean()->IsTrue();
|
txindex = options->Get(NanNew<String>("txindex"))->ToBoolean()->IsTrue();
|
||||||
|
@ -337,6 +346,7 @@ NAN_METHOD(StartBitcoind) {
|
||||||
data->datadir = datadir;
|
data->datadir = datadir;
|
||||||
data->rpc = rpc;
|
data->rpc = rpc;
|
||||||
data->testnet = testnet;
|
data->testnet = testnet;
|
||||||
|
data->regtest = regtest;
|
||||||
data->txindex = txindex;
|
data->txindex = txindex;
|
||||||
|
|
||||||
Eternal<Function> eternal(isolate, callback);
|
Eternal<Function> eternal(isolate, callback);
|
||||||
|
@ -370,6 +380,7 @@ async_start_node(uv_work_t *req) {
|
||||||
}
|
}
|
||||||
g_rpc = (bool)data->rpc;
|
g_rpc = (bool)data->rpc;
|
||||||
g_testnet = (bool)data->testnet;
|
g_testnet = (bool)data->testnet;
|
||||||
|
g_regtest = (bool)data->regtest;
|
||||||
g_txindex = (bool)data->txindex;
|
g_txindex = (bool)data->txindex;
|
||||||
tcgetattr(STDIN_FILENO, &orig_termios);
|
tcgetattr(STDIN_FILENO, &orig_termios);
|
||||||
start_node();
|
start_node();
|
||||||
|
@ -475,6 +486,11 @@ start_node_thread(void) {
|
||||||
argc++;
|
argc++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (g_regtest) {
|
||||||
|
argv[argc] = (char *)"-regtest";
|
||||||
|
argc++;
|
||||||
|
}
|
||||||
|
|
||||||
argv[argc] = (char *)"-txindex";
|
argv[argc] = (char *)"-txindex";
|
||||||
argc++;
|
argc++;
|
||||||
|
|
||||||
|
|
|
@ -168,38 +168,24 @@ describe('Bitcoind Node', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('#_loadNetwork', function() {
|
describe('#_loadNetwork', function() {
|
||||||
it('should add the network that was listed in the config', function() {
|
|
||||||
var config = {
|
|
||||||
network: {
|
|
||||||
name: 'chainlib',
|
|
||||||
alias: 'chainlib',
|
|
||||||
pubkeyhash: 0x1c,
|
|
||||||
privatekey: 0x1e,
|
|
||||||
scripthash: 0x28,
|
|
||||||
xpubkey: 0x02e8de8f,
|
|
||||||
xprivkey: 0x02e8da54,
|
|
||||||
networkMagic: 0x0c110907,
|
|
||||||
port: 9333
|
|
||||||
}
|
|
||||||
};
|
|
||||||
var node = new Node(config);
|
|
||||||
node._loadNetwork(config);
|
|
||||||
var network = Networks.get('chainlib');
|
|
||||||
should.exist(network);
|
|
||||||
node.network.name.should.equal('chainlib');
|
|
||||||
});
|
|
||||||
it('should use the testnet network if testnet is specified', function() {
|
it('should use the testnet network if testnet is specified', function() {
|
||||||
var config = {
|
var config = {
|
||||||
testnet: true
|
network: 'testnet'
|
||||||
};
|
};
|
||||||
|
|
||||||
var node = new Node(config);
|
var node = new Node(config);
|
||||||
node._loadNetwork(config);
|
node._loadNetwork(config);
|
||||||
node.network.name.should.equal('testnet');
|
node.network.name.should.equal('testnet');
|
||||||
});
|
});
|
||||||
|
it('should use the regtest network if regtest is specified', function() {
|
||||||
|
var config = {
|
||||||
|
network: 'regtest'
|
||||||
|
};
|
||||||
|
var node = new Node(config);
|
||||||
|
node._loadNetwork(config);
|
||||||
|
node.network.name.should.equal('regtest');
|
||||||
|
});
|
||||||
it('should use the livenet network if nothing is specified', function() {
|
it('should use the livenet network if nothing is specified', function() {
|
||||||
var config = {};
|
var config = {};
|
||||||
|
|
||||||
var node = new Node(config);
|
var node = new Node(config);
|
||||||
node._loadNetwork(config);
|
node._loadNetwork(config);
|
||||||
node.network.name.should.equal('livenet');
|
node.network.name.should.equal('livenet');
|
||||||
|
@ -245,6 +231,54 @@ describe('Bitcoind Node', function() {
|
||||||
node._loadDB(config);
|
node._loadDB(config);
|
||||||
}).should.throw('Unknown network');
|
}).should.throw('Unknown network');
|
||||||
});
|
});
|
||||||
|
it('should load the db with regtest', function() {
|
||||||
|
var DB = function(config) {
|
||||||
|
config.path.should.equal(process.env.HOME + '/.bitcoin/regtest/bitcoindjs.db');
|
||||||
|
};
|
||||||
|
var config = {
|
||||||
|
DB: DB,
|
||||||
|
datadir: '~/.bitcoin'
|
||||||
|
};
|
||||||
|
|
||||||
|
var node = new Node(config);
|
||||||
|
// Switch to use regtest
|
||||||
|
Networks.remove(Networks.testnet);
|
||||||
|
Networks.add({
|
||||||
|
name: 'regtest',
|
||||||
|
alias: 'regtest',
|
||||||
|
pubkeyhash: 0x6f,
|
||||||
|
privatekey: 0xef,
|
||||||
|
scripthash: 0xc4,
|
||||||
|
xpubkey: 0x043587cf,
|
||||||
|
xprivkey: 0x04358394,
|
||||||
|
networkMagic: 0xfabfb5da,
|
||||||
|
port: 18444,
|
||||||
|
dnsSeeds: [ ]
|
||||||
|
});
|
||||||
|
var regtest = Networks.get('regtest');
|
||||||
|
node.network = regtest;
|
||||||
|
node._loadDB(config);
|
||||||
|
node.db.should.be.instanceof(DB);
|
||||||
|
Networks.remove(regtest);
|
||||||
|
// Add testnet back
|
||||||
|
Networks.add({
|
||||||
|
name: 'testnet',
|
||||||
|
alias: 'testnet',
|
||||||
|
pubkeyhash: 0x6f,
|
||||||
|
privatekey: 0xef,
|
||||||
|
scripthash: 0xc4,
|
||||||
|
xpubkey: 0x043587cf,
|
||||||
|
xprivkey: 0x04358394,
|
||||||
|
networkMagic: 0x0b110907,
|
||||||
|
port: 18333,
|
||||||
|
dnsSeeds: [
|
||||||
|
'testnet-seed.bitcoin.petertodd.org',
|
||||||
|
'testnet-seed.bluematt.me',
|
||||||
|
'testnet-seed.alexykot.me',
|
||||||
|
'testnet-seed.bitcoin.schildbach.de'
|
||||||
|
]
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
describe('#_loadP2P', function() {
|
describe('#_loadP2P', function() {
|
||||||
it('should load p2p', function() {
|
it('should load p2p', function() {
|
||||||
|
|
Loading…
Reference in New Issue