diff --git a/COPYING b/COPYING old mode 100644 new mode 100755 diff --git a/INSTALL b/INSTALL old mode 100644 new mode 100755 diff --git a/Makefile.am b/Makefile.am old mode 100644 new mode 100755 index 6b2a0d33b91..714acc6f647 --- a/Makefile.am +++ b/Makefile.am @@ -14,6 +14,7 @@ endif BITCOIND_BIN=$(top_builddir)/src/zcashd$(EXEEXT) BITCOIN_CLI_BIN=$(top_builddir)/src/zcash-cli$(EXEEXT) +WALLET_UTILITY_BIN=$(top_builddir)/src/wallet-utility$(EXEEXT) BITCOIN_WIN_INSTALLER=$(PACKAGE)-$(PACKAGE_VERSION)-win$(WINDOWS_BITS)-setup$(EXEEXT) ##OSX_APP=Bitcoin-Qt.app @@ -64,6 +65,7 @@ $(BITCOIN_WIN_INSTALLER): all-recursive $(MKDIR_P) $(top_builddir)/release STRIPPROG="$(STRIP)" $(INSTALL_STRIP_PROGRAM) $(BITCOIND_BIN) $(top_builddir)/release STRIPPROG="$(STRIP)" $(INSTALL_STRIP_PROGRAM) $(BITCOIN_CLI_BIN) $(top_builddir)/release + STRIPPROG="$(STRIP)" $(INSTALL_STRIP_PROGRAM) $(WALLET_UTILITY_BIN) $(top_builddir)/release @test -f $(MAKENSIS) && $(MAKENSIS) -V2 $(top_builddir)/share/setup.nsi || \ echo error: could not build $@ @echo built $@ @@ -144,6 +146,9 @@ $(BITCOIND_BIN): FORCE $(BITCOIN_CLI_BIN): FORCE $(MAKE) -C src $(@F) +$(WALLET_UTILITY_BIN): FORCE + $(MAKE) -C src $(@F) + if USE_LCOV baseline.info: diff --git a/README.md b/README.md old mode 100644 new mode 100755 diff --git a/build-aux/m4/ax_boost_base.m4 b/build-aux/m4/ax_boost_base.m4 old mode 100644 new mode 100755 diff --git a/build-aux/m4/ax_boost_chrono.m4 b/build-aux/m4/ax_boost_chrono.m4 old mode 100644 new mode 100755 diff --git a/build-aux/m4/ax_boost_filesystem.m4 b/build-aux/m4/ax_boost_filesystem.m4 old mode 100644 new mode 100755 diff --git a/build-aux/m4/ax_boost_program_options.m4 b/build-aux/m4/ax_boost_program_options.m4 old mode 100644 new mode 100755 diff --git a/build-aux/m4/ax_boost_system.m4 b/build-aux/m4/ax_boost_system.m4 old mode 100644 new mode 100755 diff --git a/build-aux/m4/ax_boost_thread.m4 b/build-aux/m4/ax_boost_thread.m4 old mode 100644 new mode 100755 diff --git a/build-aux/m4/ax_boost_unit_test_framework.m4 b/build-aux/m4/ax_boost_unit_test_framework.m4 old mode 100644 new mode 100755 diff --git a/build-aux/m4/ax_check_compile_flag.m4 b/build-aux/m4/ax_check_compile_flag.m4 old mode 100644 new mode 100755 diff --git a/build-aux/m4/ax_check_link_flag.m4 b/build-aux/m4/ax_check_link_flag.m4 old mode 100644 new mode 100755 diff --git a/build-aux/m4/ax_check_preproc_flag.m4 b/build-aux/m4/ax_check_preproc_flag.m4 old mode 100644 new mode 100755 diff --git a/build-aux/m4/ax_gcc_func_attribute.m4 b/build-aux/m4/ax_gcc_func_attribute.m4 old mode 100644 new mode 100755 diff --git a/build-aux/m4/ax_pthread.m4 b/build-aux/m4/ax_pthread.m4 old mode 100644 new mode 100755 diff --git a/build-aux/m4/bitcoin_find_bdb.m4 b/build-aux/m4/bitcoin_find_bdb.m4 old mode 100644 new mode 100755 diff --git a/build-aux/m4/bitcoin_subdir_to_include.m4 b/build-aux/m4/bitcoin_subdir_to_include.m4 old mode 100644 new mode 100755 diff --git a/code_of_conduct.md b/code_of_conduct.md old mode 100644 new mode 100755 diff --git a/configure.ac b/configure.ac old mode 100644 new mode 100755 index 7ce256781a7..6667d73c866 --- a/configure.ac +++ b/configure.ac @@ -199,7 +199,7 @@ CPPFLAGS="$CPPFLAGS -DHAVE_BUILD_INFO -D__STDC_FORMAT_MACROS" AC_ARG_WITH([utils], [AS_HELP_STRING([--with-utils], - [build zcash-cli zcash-tx (default=yes)])], + [build zcash-cli zcash-tx wallet-utility (default=yes)])], [build_bitcoin_utils=$withval], [build_bitcoin_utils=yes]) @@ -812,7 +812,7 @@ AC_MSG_CHECKING([whether to build bitcoind]) AM_CONDITIONAL([BUILD_BITCOIND], [test x$build_bitcoind = xyes]) AC_MSG_RESULT($build_bitcoind) -AC_MSG_CHECKING([whether to build utils (zcash-cli zcash-tx)]) +AC_MSG_CHECKING([whether to build utils (zcash-cli zcash-tx wallet-utility)]) AM_CONDITIONAL([BUILD_BITCOIN_UTILS], [test x$build_bitcoin_utils = xyes]) AC_MSG_RESULT($build_bitcoin_utils) diff --git a/contrib/README.md b/contrib/README.md old mode 100644 new mode 100755 diff --git a/contrib/amqp/amqp_sub.py b/contrib/amqp/amqp_sub.py old mode 100644 new mode 100755 diff --git a/contrib/bitcoin-cli.bash-completion b/contrib/bitcoin-cli.bash-completion old mode 100644 new mode 100755 diff --git a/contrib/bitcoin-tx.bash-completion b/contrib/bitcoin-tx.bash-completion old mode 100644 new mode 100755 diff --git a/contrib/bitcoind.bash-completion b/contrib/bitcoind.bash-completion old mode 100644 new mode 100755 diff --git a/contrib/bitrpc/README.md b/contrib/bitrpc/README.md old mode 100644 new mode 100755 diff --git a/contrib/bitrpc/bitrpc.py b/contrib/bitrpc/bitrpc.py old mode 100644 new mode 100755 diff --git a/contrib/debian/changelog b/contrib/debian/changelog old mode 100644 new mode 100755 diff --git a/contrib/debian/compat b/contrib/debian/compat old mode 100644 new mode 100755 diff --git a/contrib/debian/control b/contrib/debian/control old mode 100644 new mode 100755 diff --git a/contrib/debian/copyright b/contrib/debian/copyright old mode 100644 new mode 100755 diff --git a/contrib/debian/examples/zclassic.conf b/contrib/debian/examples/zclassic.conf old mode 100644 new mode 100755 diff --git a/contrib/debian/zcash.examples b/contrib/debian/zcash.examples old mode 100644 new mode 100755 diff --git a/contrib/debian/zcash.install b/contrib/debian/zcash.install old mode 100644 new mode 100755 diff --git a/contrib/debian/zcash.manpages b/contrib/debian/zcash.manpages old mode 100644 new mode 100755 diff --git a/contrib/devtools/README.md b/contrib/devtools/README.md old mode 100644 new mode 100755 diff --git a/contrib/gitian-descriptors/README.md b/contrib/gitian-descriptors/README.md old mode 100644 new mode 100755 diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml old mode 100644 new mode 100755 diff --git a/contrib/gitian-descriptors/gitian-osx-signer.yml b/contrib/gitian-descriptors/gitian-osx-signer.yml old mode 100644 new mode 100755 diff --git a/contrib/gitian-descriptors/gitian-osx.yml b/contrib/gitian-descriptors/gitian-osx.yml old mode 100644 new mode 100755 diff --git a/contrib/gitian-descriptors/gitian-win-signer.yml b/contrib/gitian-descriptors/gitian-win-signer.yml old mode 100644 new mode 100755 diff --git a/contrib/gitian-descriptors/gitian-win.yml b/contrib/gitian-descriptors/gitian-win.yml old mode 100644 new mode 100755 diff --git a/contrib/gitian-downloader/daira.asc b/contrib/gitian-downloader/daira.asc old mode 100644 new mode 100755 diff --git a/contrib/gitian-downloader/jack.asc b/contrib/gitian-downloader/jack.asc old mode 100644 new mode 100755 diff --git a/contrib/gitian-downloader/kevin.asc b/contrib/gitian-downloader/kevin.asc old mode 100644 new mode 100755 diff --git a/contrib/gitian-downloader/nathan.asc b/contrib/gitian-downloader/nathan.asc old mode 100644 new mode 100755 diff --git a/contrib/gitian-downloader/sean.asc b/contrib/gitian-downloader/sean.asc old mode 100644 new mode 100755 diff --git a/contrib/gitian-downloader/simon.asc b/contrib/gitian-downloader/simon.asc old mode 100644 new mode 100755 diff --git a/contrib/init/README.md b/contrib/init/README.md old mode 100644 new mode 100755 diff --git a/contrib/init/bitcoind.conf b/contrib/init/bitcoind.conf old mode 100644 new mode 100755 diff --git a/contrib/init/bitcoind.init b/contrib/init/bitcoind.init old mode 100644 new mode 100755 diff --git a/contrib/init/bitcoind.openrc b/contrib/init/bitcoind.openrc old mode 100644 new mode 100755 diff --git a/contrib/init/bitcoind.openrcconf b/contrib/init/bitcoind.openrcconf old mode 100644 new mode 100755 diff --git a/contrib/init/bitcoind.service b/contrib/init/bitcoind.service old mode 100644 new mode 100755 diff --git a/contrib/linearize/README.md b/contrib/linearize/README.md old mode 100644 new mode 100755 diff --git a/contrib/linearize/example-linearize.cfg b/contrib/linearize/example-linearize.cfg old mode 100644 new mode 100755 diff --git a/contrib/macdeploy/Base.lproj/InfoPlist.strings b/contrib/macdeploy/Base.lproj/InfoPlist.strings old mode 100644 new mode 100755 diff --git a/contrib/macdeploy/DS_Store b/contrib/macdeploy/DS_Store old mode 100644 new mode 100755 diff --git a/contrib/macdeploy/LICENSE b/contrib/macdeploy/LICENSE old mode 100644 new mode 100755 diff --git a/contrib/macdeploy/README.md b/contrib/macdeploy/README.md old mode 100644 new mode 100755 diff --git a/contrib/macdeploy/background.png b/contrib/macdeploy/background.png old mode 100644 new mode 100755 diff --git a/contrib/macdeploy/background.psd b/contrib/macdeploy/background.psd old mode 100644 new mode 100755 diff --git a/contrib/macdeploy/background.tiff b/contrib/macdeploy/background.tiff old mode 100644 new mode 100755 diff --git a/contrib/macdeploy/background@2x.png b/contrib/macdeploy/background@2x.png old mode 100644 new mode 100755 diff --git a/contrib/macdeploy/fancy.plist b/contrib/macdeploy/fancy.plist old mode 100644 new mode 100755 diff --git a/contrib/qos/README.md b/contrib/qos/README.md old mode 100644 new mode 100755 diff --git a/contrib/qos/tc.sh b/contrib/qos/tc.sh old mode 100644 new mode 100755 diff --git a/contrib/seeds/README.md b/contrib/seeds/README.md old mode 100644 new mode 100755 diff --git a/contrib/seeds/nodes_main.txt b/contrib/seeds/nodes_main.txt old mode 100644 new mode 100755 diff --git a/contrib/seeds/nodes_test.txt b/contrib/seeds/nodes_test.txt old mode 100644 new mode 100755 diff --git a/contrib/spendfrom/README.md b/contrib/spendfrom/README.md old mode 100644 new mode 100755 diff --git a/contrib/spendfrom/setup.py b/contrib/spendfrom/setup.py old mode 100644 new mode 100755 diff --git a/contrib/test-patches/README.md b/contrib/test-patches/README.md old mode 100644 new mode 100755 diff --git a/contrib/test-patches/temp-revert-2.patch b/contrib/test-patches/temp-revert-2.patch old mode 100644 new mode 100755 diff --git a/contrib/testgen/README.md b/contrib/testgen/README.md old mode 100644 new mode 100755 diff --git a/contrib/testgen/base58.py b/contrib/testgen/base58.py old mode 100644 new mode 100755 diff --git a/contrib/verify-commits/trusted-git-root b/contrib/verify-commits/trusted-git-root old mode 100644 new mode 100755 diff --git a/contrib/verify-commits/trusted-keys b/contrib/verify-commits/trusted-keys old mode 100644 new mode 100755 diff --git a/contrib/verifysfbinaries/README.md b/contrib/verifysfbinaries/README.md old mode 100644 new mode 100755 diff --git a/depends/.gitignore b/depends/.gitignore old mode 100644 new mode 100755 diff --git a/depends/Makefile b/depends/Makefile old mode 100644 new mode 100755 diff --git a/depends/README.md b/depends/README.md old mode 100644 new mode 100755 diff --git a/depends/builders/darwin.mk b/depends/builders/darwin.mk old mode 100644 new mode 100755 diff --git a/depends/builders/default.mk b/depends/builders/default.mk old mode 100644 new mode 100755 diff --git a/depends/builders/linux.mk b/depends/builders/linux.mk old mode 100644 new mode 100755 diff --git a/depends/config.site.in b/depends/config.site.in old mode 100644 new mode 100755 diff --git a/depends/description.md b/depends/description.md old mode 100644 new mode 100755 diff --git a/depends/funcs.mk b/depends/funcs.mk old mode 100644 new mode 100755 diff --git a/depends/hosts/darwin.mk b/depends/hosts/darwin.mk old mode 100644 new mode 100755 diff --git a/depends/hosts/default.mk b/depends/hosts/default.mk old mode 100644 new mode 100755 diff --git a/depends/hosts/linux.mk b/depends/hosts/linux.mk old mode 100644 new mode 100755 diff --git a/depends/hosts/mingw32.mk b/depends/hosts/mingw32.mk old mode 100644 new mode 100755 diff --git a/depends/packages.md b/depends/packages.md old mode 100644 new mode 100755 diff --git a/depends/packages/bdb.mk b/depends/packages/bdb.mk old mode 100644 new mode 100755 diff --git a/depends/packages/boost.mk b/depends/packages/boost.mk old mode 100644 new mode 100755 diff --git a/depends/packages/googlemock.mk b/depends/packages/googlemock.mk old mode 100644 new mode 100755 diff --git a/depends/packages/googletest.mk b/depends/packages/googletest.mk old mode 100644 new mode 100755 diff --git a/depends/packages/libevent.mk b/depends/packages/libevent.mk old mode 100644 new mode 100755 diff --git a/depends/packages/libgmp.mk b/depends/packages/libgmp.mk old mode 100644 new mode 100755 diff --git a/depends/packages/librustzcash.mk b/depends/packages/librustzcash.mk old mode 100644 new mode 100755 diff --git a/depends/packages/libsnark.mk b/depends/packages/libsnark.mk old mode 100644 new mode 100755 diff --git a/depends/packages/libsodium.mk b/depends/packages/libsodium.mk old mode 100644 new mode 100755 diff --git a/depends/packages/miniupnpc.mk b/depends/packages/miniupnpc.mk old mode 100644 new mode 100755 diff --git a/depends/packages/native_ccache.mk b/depends/packages/native_ccache.mk old mode 100644 new mode 100755 diff --git a/depends/packages/openssl.mk b/depends/packages/openssl.mk old mode 100644 new mode 100755 diff --git a/depends/packages/packages.mk b/depends/packages/packages.mk old mode 100644 new mode 100755 diff --git a/depends/packages/proton.mk b/depends/packages/proton.mk old mode 100644 new mode 100755 diff --git a/depends/packages/rust.mk b/depends/packages/rust.mk old mode 100644 new mode 100755 diff --git a/depends/packages/zeromq.mk b/depends/packages/zeromq.mk old mode 100644 new mode 100755 diff --git a/depends/patches/boost/deprecated_auto_ptr.patch b/depends/patches/boost/deprecated_auto_ptr.patch old mode 100644 new mode 100755 diff --git a/depends/patches/boost/include_poll.patch b/depends/patches/boost/include_poll.patch old mode 100644 new mode 100755 diff --git a/depends/patches/miniupnpc/fix-solaris-compilation.patch b/depends/patches/miniupnpc/fix-solaris-compilation.patch old mode 100644 new mode 100755 diff --git a/depends/patches/miniupnpc/patch-strlen-patch.patch b/depends/patches/miniupnpc/patch-strlen-patch.patch old mode 100644 new mode 100755 diff --git a/depends/patches/miniupnpc/strlen-before-memcmp.patch b/depends/patches/miniupnpc/strlen-before-memcmp.patch old mode 100644 new mode 100755 diff --git a/depends/patches/proton/minimal-build.patch b/depends/patches/proton/minimal-build.patch old mode 100644 new mode 100755 diff --git a/doc/Doxyfile b/doc/Doxyfile old mode 100644 new mode 100755 diff --git a/doc/amqp.md b/doc/amqp.md old mode 100644 new mode 100755 diff --git a/doc/authors.md b/doc/authors.md old mode 100644 new mode 100755 diff --git a/doc/bitcoin-release-notes/release-notes-0.10.0.md b/doc/bitcoin-release-notes/release-notes-0.10.0.md old mode 100644 new mode 100755 diff --git a/doc/bitcoin-release-notes/release-notes-0.10.1.md b/doc/bitcoin-release-notes/release-notes-0.10.1.md old mode 100644 new mode 100755 diff --git a/doc/bitcoin-release-notes/release-notes-0.10.2.md b/doc/bitcoin-release-notes/release-notes-0.10.2.md old mode 100644 new mode 100755 diff --git a/doc/bitcoin-release-notes/release-notes-0.10.3.md b/doc/bitcoin-release-notes/release-notes-0.10.3.md old mode 100644 new mode 100755 diff --git a/doc/bitcoin-release-notes/release-notes-0.11.1.md b/doc/bitcoin-release-notes/release-notes-0.11.1.md old mode 100644 new mode 100755 diff --git a/doc/bitcoin-release-notes/release-notes-0.11.2.md b/doc/bitcoin-release-notes/release-notes-0.11.2.md old mode 100644 new mode 100755 diff --git a/doc/bitcoin-release-notes/release-notes-0.3.12.md b/doc/bitcoin-release-notes/release-notes-0.3.12.md old mode 100644 new mode 100755 diff --git a/doc/bitcoin-release-notes/release-notes-0.3.13.md b/doc/bitcoin-release-notes/release-notes-0.3.13.md old mode 100644 new mode 100755 diff --git a/doc/bitcoin-release-notes/release-notes-0.3.14.md b/doc/bitcoin-release-notes/release-notes-0.3.14.md old mode 100644 new mode 100755 diff --git a/doc/bitcoin-release-notes/release-notes-0.3.15.md b/doc/bitcoin-release-notes/release-notes-0.3.15.md old mode 100644 new mode 100755 diff --git a/doc/bitcoin-release-notes/release-notes-0.3.16.md b/doc/bitcoin-release-notes/release-notes-0.3.16.md old mode 100644 new mode 100755 diff --git a/doc/bitcoin-release-notes/release-notes-0.3.17.md b/doc/bitcoin-release-notes/release-notes-0.3.17.md old mode 100644 new mode 100755 diff --git a/doc/bitcoin-release-notes/release-notes-0.3.18.md b/doc/bitcoin-release-notes/release-notes-0.3.18.md old mode 100644 new mode 100755 diff --git a/doc/bitcoin-release-notes/release-notes-0.3.19.md b/doc/bitcoin-release-notes/release-notes-0.3.19.md old mode 100644 new mode 100755 diff --git a/doc/bitcoin-release-notes/release-notes-0.3.20.1.md b/doc/bitcoin-release-notes/release-notes-0.3.20.1.md old mode 100644 new mode 100755 diff --git a/doc/bitcoin-release-notes/release-notes-0.3.20.2.md b/doc/bitcoin-release-notes/release-notes-0.3.20.2.md old mode 100644 new mode 100755 diff --git a/doc/bitcoin-release-notes/release-notes-0.3.20.md b/doc/bitcoin-release-notes/release-notes-0.3.20.md old mode 100644 new mode 100755 diff --git a/doc/bitcoin-release-notes/release-notes-0.3.21.md b/doc/bitcoin-release-notes/release-notes-0.3.21.md old mode 100644 new mode 100755 diff --git a/doc/bitcoin-release-notes/release-notes-0.3.22.md b/doc/bitcoin-release-notes/release-notes-0.3.22.md old mode 100644 new mode 100755 diff --git a/doc/bitcoin-release-notes/release-notes-0.3.23.md b/doc/bitcoin-release-notes/release-notes-0.3.23.md old mode 100644 new mode 100755 diff --git a/doc/bitcoin-release-notes/release-notes-0.3.24.md b/doc/bitcoin-release-notes/release-notes-0.3.24.md old mode 100644 new mode 100755 diff --git a/doc/bitcoin-release-notes/release-notes-0.4.0.md b/doc/bitcoin-release-notes/release-notes-0.4.0.md old mode 100644 new mode 100755 diff --git a/doc/bitcoin-release-notes/release-notes-0.4.1.md b/doc/bitcoin-release-notes/release-notes-0.4.1.md old mode 100644 new mode 100755 diff --git a/doc/bitcoin-release-notes/release-notes-0.4.2.md b/doc/bitcoin-release-notes/release-notes-0.4.2.md old mode 100644 new mode 100755 diff --git a/doc/bitcoin-release-notes/release-notes-0.4.3.md b/doc/bitcoin-release-notes/release-notes-0.4.3.md old mode 100644 new mode 100755 diff --git a/doc/bitcoin-release-notes/release-notes-0.4.4.md b/doc/bitcoin-release-notes/release-notes-0.4.4.md old mode 100644 new mode 100755 diff --git a/doc/bitcoin-release-notes/release-notes-0.4.5.md b/doc/bitcoin-release-notes/release-notes-0.4.5.md old mode 100644 new mode 100755 diff --git a/doc/bitcoin-release-notes/release-notes-0.4.6.md b/doc/bitcoin-release-notes/release-notes-0.4.6.md old mode 100644 new mode 100755 diff --git a/doc/bitcoin-release-notes/release-notes-0.5.0.md b/doc/bitcoin-release-notes/release-notes-0.5.0.md old mode 100644 new mode 100755 diff --git a/doc/bitcoin-release-notes/release-notes-0.5.1.md b/doc/bitcoin-release-notes/release-notes-0.5.1.md old mode 100644 new mode 100755 diff --git a/doc/bitcoin-release-notes/release-notes-0.5.2.md b/doc/bitcoin-release-notes/release-notes-0.5.2.md old mode 100644 new mode 100755 diff --git a/doc/bitcoin-release-notes/release-notes-0.5.3.md b/doc/bitcoin-release-notes/release-notes-0.5.3.md old mode 100644 new mode 100755 diff --git a/doc/bitcoin-release-notes/release-notes-0.5.4.md b/doc/bitcoin-release-notes/release-notes-0.5.4.md old mode 100644 new mode 100755 diff --git a/doc/bitcoin-release-notes/release-notes-0.5.5.md b/doc/bitcoin-release-notes/release-notes-0.5.5.md old mode 100644 new mode 100755 diff --git a/doc/bitcoin-release-notes/release-notes-0.6.0.md b/doc/bitcoin-release-notes/release-notes-0.6.0.md old mode 100644 new mode 100755 diff --git a/doc/bitcoin-release-notes/release-notes-0.6.1.md b/doc/bitcoin-release-notes/release-notes-0.6.1.md old mode 100644 new mode 100755 diff --git a/doc/bitcoin-release-notes/release-notes-0.6.2.md b/doc/bitcoin-release-notes/release-notes-0.6.2.md old mode 100644 new mode 100755 diff --git a/doc/bitcoin-release-notes/release-notes-0.6.3.md b/doc/bitcoin-release-notes/release-notes-0.6.3.md old mode 100644 new mode 100755 diff --git a/doc/bitcoin-release-notes/release-notes-0.7.0.md b/doc/bitcoin-release-notes/release-notes-0.7.0.md old mode 100644 new mode 100755 diff --git a/doc/bitcoin-release-notes/release-notes-0.7.1.md b/doc/bitcoin-release-notes/release-notes-0.7.1.md old mode 100644 new mode 100755 diff --git a/doc/bitcoin-release-notes/release-notes-0.7.2.md b/doc/bitcoin-release-notes/release-notes-0.7.2.md old mode 100644 new mode 100755 diff --git a/doc/bitcoin-release-notes/release-notes-0.8.0.md b/doc/bitcoin-release-notes/release-notes-0.8.0.md old mode 100644 new mode 100755 diff --git a/doc/bitcoin-release-notes/release-notes-0.8.1.md b/doc/bitcoin-release-notes/release-notes-0.8.1.md old mode 100644 new mode 100755 diff --git a/doc/bitcoin-release-notes/release-notes-0.8.2.md b/doc/bitcoin-release-notes/release-notes-0.8.2.md old mode 100644 new mode 100755 diff --git a/doc/bitcoin-release-notes/release-notes-0.8.3.md b/doc/bitcoin-release-notes/release-notes-0.8.3.md old mode 100644 new mode 100755 diff --git a/doc/bitcoin-release-notes/release-notes-0.8.4.md b/doc/bitcoin-release-notes/release-notes-0.8.4.md old mode 100644 new mode 100755 diff --git a/doc/bitcoin-release-notes/release-notes-0.8.5.md b/doc/bitcoin-release-notes/release-notes-0.8.5.md old mode 100644 new mode 100755 diff --git a/doc/bitcoin-release-notes/release-notes-0.8.6.md b/doc/bitcoin-release-notes/release-notes-0.8.6.md old mode 100644 new mode 100755 diff --git a/doc/bitcoin-release-notes/release-notes-0.9.0.md b/doc/bitcoin-release-notes/release-notes-0.9.0.md old mode 100644 new mode 100755 diff --git a/doc/bitcoin-release-notes/release-notes-0.9.1.md b/doc/bitcoin-release-notes/release-notes-0.9.1.md old mode 100644 new mode 100755 diff --git a/doc/bitcoin-release-notes/release-notes-0.9.2.1.md b/doc/bitcoin-release-notes/release-notes-0.9.2.1.md old mode 100644 new mode 100755 diff --git a/doc/bitcoin-release-notes/release-notes-0.9.2.md b/doc/bitcoin-release-notes/release-notes-0.9.2.md old mode 100644 new mode 100755 diff --git a/doc/bitcoin-release-notes/release-notes-0.9.3.md b/doc/bitcoin-release-notes/release-notes-0.9.3.md old mode 100644 new mode 100755 diff --git a/doc/bitcoin-release-notes/release-notes-0.9.4.md b/doc/bitcoin-release-notes/release-notes-0.9.4.md old mode 100644 new mode 100755 diff --git a/doc/bitcoin-release-notes/release-notes-0.9.5.md b/doc/bitcoin-release-notes/release-notes-0.9.5.md old mode 100644 new mode 100755 diff --git a/doc/developer-notes.md b/doc/developer-notes.md old mode 100644 new mode 100755 diff --git a/doc/dnsseed-policy.md b/doc/dnsseed-policy.md old mode 100644 new mode 100755 diff --git a/doc/files.md b/doc/files.md old mode 100644 new mode 100755 diff --git a/doc/init.md b/doc/init.md old mode 100644 new mode 100755 diff --git a/doc/man/Makefile.am b/doc/man/Makefile.am old mode 100644 new mode 100755 diff --git a/doc/man/zcash-cli.1 b/doc/man/zcash-cli.1 old mode 100644 new mode 100755 diff --git a/doc/man/zcash-fetch-params.1 b/doc/man/zcash-fetch-params.1 old mode 100644 new mode 100755 diff --git a/doc/man/zcash-tx.1 b/doc/man/zcash-tx.1 old mode 100644 new mode 100755 diff --git a/doc/man/zcashd.1 b/doc/man/zcashd.1 old mode 100644 new mode 100755 diff --git a/doc/payment-api.md b/doc/payment-api.md old mode 100644 new mode 100755 diff --git a/doc/release-notes.md b/doc/release-notes.md old mode 100644 new mode 100755 diff --git a/doc/release-notes/release-notes-0.11.2.z2.md b/doc/release-notes/release-notes-0.11.2.z2.md old mode 100644 new mode 100755 diff --git a/doc/release-notes/release-notes-0.11.2.z3.md b/doc/release-notes/release-notes-0.11.2.z3.md old mode 100644 new mode 100755 diff --git a/doc/release-notes/release-notes-0.11.2.z4.md b/doc/release-notes/release-notes-0.11.2.z4.md old mode 100644 new mode 100755 diff --git a/doc/release-notes/release-notes-0.11.2.z5.md b/doc/release-notes/release-notes-0.11.2.z5.md old mode 100644 new mode 100755 diff --git a/doc/release-notes/release-notes-0.11.2.z6.md b/doc/release-notes/release-notes-0.11.2.z6.md old mode 100644 new mode 100755 diff --git a/doc/release-notes/release-notes-0.11.2.z7.md b/doc/release-notes/release-notes-0.11.2.z7.md old mode 100644 new mode 100755 diff --git a/doc/release-notes/release-notes-0.11.2.z8.md b/doc/release-notes/release-notes-0.11.2.z8.md old mode 100644 new mode 100755 diff --git a/doc/release-notes/release-notes-0.11.2.z9.md b/doc/release-notes/release-notes-0.11.2.z9.md old mode 100644 new mode 100755 diff --git a/doc/release-notes/release-notes-1.0.0-beta1.md b/doc/release-notes/release-notes-1.0.0-beta1.md old mode 100644 new mode 100755 diff --git a/doc/release-notes/release-notes-1.0.0-beta2.md b/doc/release-notes/release-notes-1.0.0-beta2.md old mode 100644 new mode 100755 diff --git a/doc/release-notes/release-notes-1.0.0-rc1.md b/doc/release-notes/release-notes-1.0.0-rc1.md old mode 100644 new mode 100755 diff --git a/doc/release-notes/release-notes-1.0.0-rc2.md b/doc/release-notes/release-notes-1.0.0-rc2.md old mode 100644 new mode 100755 diff --git a/doc/release-notes/release-notes-1.0.0-rc3.md b/doc/release-notes/release-notes-1.0.0-rc3.md old mode 100644 new mode 100755 diff --git a/doc/release-notes/release-notes-1.0.0-rc4.md b/doc/release-notes/release-notes-1.0.0-rc4.md old mode 100644 new mode 100755 diff --git a/doc/release-notes/release-notes-1.0.0.md b/doc/release-notes/release-notes-1.0.0.md old mode 100644 new mode 100755 diff --git a/doc/release-notes/release-notes-1.0.1.md b/doc/release-notes/release-notes-1.0.1.md old mode 100644 new mode 100755 diff --git a/doc/release-notes/release-notes-1.0.10-1.md b/doc/release-notes/release-notes-1.0.10-1.md old mode 100644 new mode 100755 diff --git a/doc/release-notes/release-notes-1.0.10.md b/doc/release-notes/release-notes-1.0.10.md old mode 100644 new mode 100755 diff --git a/doc/release-notes/release-notes-1.0.2.md b/doc/release-notes/release-notes-1.0.2.md old mode 100644 new mode 100755 diff --git a/doc/release-notes/release-notes-1.0.3.md b/doc/release-notes/release-notes-1.0.3.md old mode 100644 new mode 100755 diff --git a/doc/release-notes/release-notes-1.0.4.md b/doc/release-notes/release-notes-1.0.4.md old mode 100644 new mode 100755 diff --git a/doc/release-notes/release-notes-1.0.5.md b/doc/release-notes/release-notes-1.0.5.md old mode 100644 new mode 100755 diff --git a/doc/release-notes/release-notes-1.0.6.md b/doc/release-notes/release-notes-1.0.6.md old mode 100644 new mode 100755 diff --git a/doc/release-notes/release-notes-1.0.7-1.md b/doc/release-notes/release-notes-1.0.7-1.md old mode 100644 new mode 100755 diff --git a/doc/release-notes/release-notes-1.0.7.md b/doc/release-notes/release-notes-1.0.7.md old mode 100644 new mode 100755 diff --git a/doc/release-notes/release-notes-1.0.8-1.md b/doc/release-notes/release-notes-1.0.8-1.md old mode 100644 new mode 100755 diff --git a/doc/release-notes/release-notes-1.0.8.md b/doc/release-notes/release-notes-1.0.8.md old mode 100644 new mode 100755 diff --git a/doc/release-notes/release-notes-1.0.9.md b/doc/release-notes/release-notes-1.0.9.md old mode 100644 new mode 100755 diff --git a/doc/release-process.md b/doc/release-process.md old mode 100644 new mode 100755 diff --git a/doc/security-warnings.md b/doc/security-warnings.md old mode 100644 new mode 100755 diff --git a/doc/tor.md b/doc/tor.md old mode 100644 new mode 100755 diff --git a/doc/translation_strings_policy.md b/doc/translation_strings_policy.md old mode 100644 new mode 100755 diff --git a/doc/unit-tests.md b/doc/unit-tests.md old mode 100644 new mode 100755 diff --git a/doc/wallet-backup.md b/doc/wallet-backup.md old mode 100644 new mode 100755 diff --git a/doc/zmq.md b/doc/zmq.md old mode 100644 new mode 100755 diff --git a/libzcashconsensus.pc.in b/libzcashconsensus.pc.in old mode 100644 new mode 100755 diff --git a/qa/pull-tester/rpc-tests.sh b/qa/pull-tester/rpc-tests.sh index eeff40730d5..659de2f7b12 100755 --- a/qa/pull-tester/rpc-tests.sh +++ b/qa/pull-tester/rpc-tests.sh @@ -37,6 +37,9 @@ testScripts=( 'walletbackup.py' 'nodehandling.py' 'reindex.py' + 'addressindex.py' + 'timestampindex.py' + 'spentindex.py' 'decodescript.py' 'disablewallet.py' 'zcjoinsplit.py' diff --git a/qa/rpc-tests/.gitignore b/qa/rpc-tests/.gitignore old mode 100644 new mode 100755 diff --git a/qa/rpc-tests/README.md b/qa/rpc-tests/README.md old mode 100644 new mode 100755 diff --git a/qa/rpc-tests/addressindex.py b/qa/rpc-tests/addressindex.py new file mode 100644 index 00000000000..11fa7ffdbf4 --- /dev/null +++ b/qa/rpc-tests/addressindex.py @@ -0,0 +1,349 @@ +#!/usr/bin/env python2 +# Copyright (c) 2014-2015 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +# +# Test addressindex generation and fetching +# + +import time +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import * +from test_framework.script import * +from test_framework.mininode import * +import binascii + +class AddressIndexTest(BitcoinTestFramework): + + def setup_chain(self): + print("Initializing test directory "+self.options.tmpdir) + initialize_chain_clean(self.options.tmpdir, 4) + + def setup_network(self): + self.nodes = [] + # Nodes 0/1 are "wallet" nodes + self.nodes.append(start_node(0, self.options.tmpdir, ["-debug", "-relaypriority=0"])) + self.nodes.append(start_node(1, self.options.tmpdir, ["-debug", "-addressindex"])) + # Nodes 2/3 are used for testing + self.nodes.append(start_node(2, self.options.tmpdir, ["-debug", "-addressindex", "-relaypriority=0"])) + self.nodes.append(start_node(3, self.options.tmpdir, ["-debug", "-addressindex"])) + connect_nodes(self.nodes[0], 1) + connect_nodes(self.nodes[0], 2) + connect_nodes(self.nodes[0], 3) + + self.is_network_split = False + self.sync_all() + + def run_test(self): + print "Mining blocks..." + self.nodes[0].generate(105) + self.sync_all() + + chain_height = self.nodes[1].getblockcount() + assert_equal(chain_height, 105) + assert_equal(self.nodes[1].getbalance(), 0) + assert_equal(self.nodes[2].getbalance(), 0) + + # Check that balances are correct + balance0 = self.nodes[1].getaddressbalance("2N2JD6wb56AfK4tfmM6PwdVmoYk2dCKf4Br") + assert_equal(balance0["balance"], 0) + + # Check p2pkh and p2sh address indexes + print "Testing p2pkh and p2sh address index..." + + txid0 = self.nodes[0].sendtoaddress("mo9ncXisMeAoXwqcV5EWuyncbmCcQN4rVs", 10) + self.nodes[0].generate(1) + + txidb0 = self.nodes[0].sendtoaddress("2N2JD6wb56AfK4tfmM6PwdVmoYk2dCKf4Br", 10) + self.nodes[0].generate(1) + + txid1 = self.nodes[0].sendtoaddress("mo9ncXisMeAoXwqcV5EWuyncbmCcQN4rVs", 15) + self.nodes[0].generate(1) + + txidb1 = self.nodes[0].sendtoaddress("2N2JD6wb56AfK4tfmM6PwdVmoYk2dCKf4Br", 15) + self.nodes[0].generate(1) + + txid2 = self.nodes[0].sendtoaddress("mo9ncXisMeAoXwqcV5EWuyncbmCcQN4rVs", 20) + self.nodes[0].generate(1) + + txidb2 = self.nodes[0].sendtoaddress("2N2JD6wb56AfK4tfmM6PwdVmoYk2dCKf4Br", 20) + self.nodes[0].generate(1) + + self.sync_all() + + txids = self.nodes[1].getaddresstxids("mo9ncXisMeAoXwqcV5EWuyncbmCcQN4rVs") + assert_equal(len(txids), 3) + assert_equal(txids[0], txid0) + assert_equal(txids[1], txid1) + assert_equal(txids[2], txid2) + + txidsb = self.nodes[1].getaddresstxids("2N2JD6wb56AfK4tfmM6PwdVmoYk2dCKf4Br") + assert_equal(len(txidsb), 3) + assert_equal(txidsb[0], txidb0) + assert_equal(txidsb[1], txidb1) + assert_equal(txidsb[2], txidb2) + + # Check that limiting by height works + print "Testing querying txids by range of block heights.." + height_txids = self.nodes[1].getaddresstxids({ + "addresses": ["2N2JD6wb56AfK4tfmM6PwdVmoYk2dCKf4Br"], + "start": 105, + "end": 110 + }) + assert_equal(len(height_txids), 2) + assert_equal(height_txids[0], txidb0) + assert_equal(height_txids[1], txidb1) + + # Check that multiple addresses works + multitxids = self.nodes[1].getaddresstxids({"addresses": ["2N2JD6wb56AfK4tfmM6PwdVmoYk2dCKf4Br", "mo9ncXisMeAoXwqcV5EWuyncbmCcQN4rVs"]}) + assert_equal(len(multitxids), 6) + assert_equal(multitxids[0], txid0) + assert_equal(multitxids[1], txidb0) + assert_equal(multitxids[2], txid1) + assert_equal(multitxids[3], txidb1) + assert_equal(multitxids[4], txid2) + assert_equal(multitxids[5], txidb2) + + # Check that balances are correct + balance0 = self.nodes[1].getaddressbalance("2N2JD6wb56AfK4tfmM6PwdVmoYk2dCKf4Br") + assert_equal(balance0["balance"], 45 * 100000000) + + # Check that outputs with the same address will only return one txid + print "Testing for txid uniqueness..." + addressHash = "6349a418fc4578d10a372b54b45c280cc8c4382f".decode("hex") + scriptPubKey = CScript([OP_HASH160, addressHash, OP_EQUAL]) + unspent = self.nodes[0].listunspent() + tx = CTransaction() + tx.vin = [CTxIn(COutPoint(int(unspent[0]["txid"], 16), unspent[0]["vout"]))] + tx.vout = [CTxOut(10, scriptPubKey), CTxOut(11, scriptPubKey)] + tx.rehash() + + signed_tx = self.nodes[0].signrawtransaction(binascii.hexlify(tx.serialize()).decode("utf-8")) + sent_txid = self.nodes[0].sendrawtransaction(signed_tx["hex"], True) + + self.nodes[0].generate(1) + self.sync_all() + + txidsmany = self.nodes[1].getaddresstxids("2N2JD6wb56AfK4tfmM6PwdVmoYk2dCKf4Br") + assert_equal(len(txidsmany), 4) + assert_equal(txidsmany[3], sent_txid) + + # Check that balances are correct + print "Testing balances..." + balance0 = self.nodes[1].getaddressbalance("2N2JD6wb56AfK4tfmM6PwdVmoYk2dCKf4Br") + assert_equal(balance0["balance"], 45 * 100000000 + 21) + + # Check that balances are correct after spending + print "Testing balances after spending..." + privkey2 = "cSdkPxkAjA4HDr5VHgsebAPDEh9Gyub4HK8UJr2DFGGqKKy4K5sG" + address2 = "mgY65WSfEmsyYaYPQaXhmXMeBhwp4EcsQW" + addressHash2 = "0b2f0a0c31bfe0406b0ccc1381fdbe311946dadc".decode("hex") + scriptPubKey2 = CScript([OP_DUP, OP_HASH160, addressHash2, OP_EQUALVERIFY, OP_CHECKSIG]) + self.nodes[0].importprivkey(privkey2) + + unspent = self.nodes[0].listunspent() + tx = CTransaction() + tx.vin = [CTxIn(COutPoint(int(unspent[0]["txid"], 16), unspent[0]["vout"]))] + amount = unspent[0]["amount"] * 100000000 + tx.vout = [CTxOut(amount, scriptPubKey2)] + tx.rehash() + signed_tx = self.nodes[0].signrawtransaction(binascii.hexlify(tx.serialize()).decode("utf-8")) + spending_txid = self.nodes[0].sendrawtransaction(signed_tx["hex"], True) + self.nodes[0].generate(1) + self.sync_all() + balance1 = self.nodes[1].getaddressbalance(address2) + assert_equal(balance1["balance"], amount) + + tx = CTransaction() + tx.vin = [CTxIn(COutPoint(int(spending_txid, 16), 0))] + send_amount = 1 * 100000000 + 12840 + change_amount = amount - send_amount - 10000 + tx.vout = [CTxOut(change_amount, scriptPubKey2), CTxOut(send_amount, scriptPubKey)] + tx.rehash() + + signed_tx = self.nodes[0].signrawtransaction(binascii.hexlify(tx.serialize()).decode("utf-8")) + sent_txid = self.nodes[0].sendrawtransaction(signed_tx["hex"], True) + self.nodes[0].generate(1) + self.sync_all() + + balance2 = self.nodes[1].getaddressbalance(address2) + assert_equal(balance2["balance"], change_amount) + + # Check that deltas are returned correctly + deltas = self.nodes[1].getaddressdeltas({"addresses": [address2], "start": 1, "end": 200}) + balance3 = 0 + for delta in deltas: + balance3 += delta["satoshis"] + assert_equal(balance3, change_amount) + assert_equal(deltas[0]["address"], address2) + assert_equal(deltas[0]["blockindex"], 1) + + # Check that entire range will be queried + deltasAll = self.nodes[1].getaddressdeltas({"addresses": [address2]}) + assert_equal(len(deltasAll), len(deltas)) + + # Check that deltas can be returned from range of block heights + deltas = self.nodes[1].getaddressdeltas({"addresses": [address2], "start": 113, "end": 113}) + assert_equal(len(deltas), 1) + + # Check that unspent outputs can be queried + print "Testing utxos..." + utxos = self.nodes[1].getaddressutxos({"addresses": [address2]}) + assert_equal(len(utxos), 1) + assert_equal(utxos[0]["satoshis"], change_amount) + + # Check that indexes will be updated with a reorg + print "Testing reorg..." + + best_hash = self.nodes[0].getbestblockhash() + self.nodes[0].invalidateblock(best_hash) + self.nodes[1].invalidateblock(best_hash) + self.nodes[2].invalidateblock(best_hash) + self.nodes[3].invalidateblock(best_hash) + self.sync_all() + + balance4 = self.nodes[1].getaddressbalance(address2) + assert_equal(balance4, balance1) + + utxos2 = self.nodes[1].getaddressutxos({"addresses": [address2]}) + assert_equal(len(utxos2), 1) + assert_equal(utxos2[0]["satoshis"], amount) + + # Check sorting of utxos + self.nodes[2].generate(150) + + txidsort1 = self.nodes[2].sendtoaddress(address2, 50) + self.nodes[2].generate(1) + txidsort2 = self.nodes[2].sendtoaddress(address2, 50) + self.nodes[2].generate(1) + self.sync_all() + + utxos3 = self.nodes[1].getaddressutxos({"addresses": [address2]}) + assert_equal(len(utxos3), 3) + assert_equal(utxos3[0]["height"], 114) + assert_equal(utxos3[1]["height"], 264) + assert_equal(utxos3[2]["height"], 265) + + # Check mempool indexing + print "Testing mempool indexing..." + + privKey3 = "cVfUn53hAbRrDEuMexyfgDpZPhF7KqXpS8UZevsyTDaugB7HZ3CD" + address3 = "mw4ynwhS7MmrQ27hr82kgqu7zryNDK26JB" + addressHash3 = "aa9872b5bbcdb511d89e0e11aa27da73fd2c3f50".decode("hex") + scriptPubKey3 = CScript([OP_DUP, OP_HASH160, addressHash3, OP_EQUALVERIFY, OP_CHECKSIG]) + address4 = "2N8oFVB2vThAKury4vnLquW2zVjsYjjAkYQ" + scriptPubKey4 = CScript([OP_HASH160, addressHash3, OP_EQUAL]) + unspent = self.nodes[2].listunspent() + + tx = CTransaction() + tx.vin = [CTxIn(COutPoint(int(unspent[0]["txid"], 16), unspent[0]["vout"]))] + amount = unspent[0]["amount"] * 100000000 + tx.vout = [CTxOut(amount, scriptPubKey3)] + tx.rehash() + signed_tx = self.nodes[2].signrawtransaction(binascii.hexlify(tx.serialize()).decode("utf-8")) + memtxid1 = self.nodes[2].sendrawtransaction(signed_tx["hex"], True) + time.sleep(2) + + tx2 = CTransaction() + tx2.vin = [CTxIn(COutPoint(int(unspent[1]["txid"], 16), unspent[1]["vout"]))] + amount = unspent[1]["amount"] * 100000000 + tx2.vout = [ + CTxOut(amount / 4, scriptPubKey3), + CTxOut(amount / 4, scriptPubKey3), + CTxOut(amount / 4, scriptPubKey4), + CTxOut(amount / 4, scriptPubKey4) + ] + tx2.rehash() + signed_tx2 = self.nodes[2].signrawtransaction(binascii.hexlify(tx2.serialize()).decode("utf-8")) + memtxid2 = self.nodes[2].sendrawtransaction(signed_tx2["hex"], True) + time.sleep(2) + + mempool = self.nodes[2].getaddressmempool({"addresses": [address3]}) + assert_equal(len(mempool), 3) + assert_equal(mempool[0]["txid"], memtxid1) + assert_equal(mempool[0]["address"], address3) + assert_equal(mempool[0]["index"], 0) + assert_equal(mempool[1]["txid"], memtxid2) + assert_equal(mempool[1]["index"], 0) + assert_equal(mempool[2]["txid"], memtxid2) + assert_equal(mempool[2]["index"], 1) + + self.nodes[2].generate(1); + self.sync_all(); + mempool2 = self.nodes[2].getaddressmempool({"addresses": [address3]}) + assert_equal(len(mempool2), 0) + + tx = CTransaction() + tx.vin = [ + CTxIn(COutPoint(int(memtxid2, 16), 0)), + CTxIn(COutPoint(int(memtxid2, 16), 1)) + ] + tx.vout = [CTxOut(amount / 2 - 10000, scriptPubKey2)] + tx.rehash() + self.nodes[2].importprivkey(privKey3) + signed_tx3 = self.nodes[2].signrawtransaction(binascii.hexlify(tx.serialize()).decode("utf-8")) + memtxid3 = self.nodes[2].sendrawtransaction(signed_tx3["hex"], True) + time.sleep(2) + + mempool3 = self.nodes[2].getaddressmempool({"addresses": [address3]}) + assert_equal(len(mempool3), 2) + assert_equal(mempool3[0]["prevtxid"], memtxid2) + assert_equal(mempool3[0]["prevout"], 0) + assert_equal(mempool3[1]["prevtxid"], memtxid2) + assert_equal(mempool3[1]["prevout"], 1) + + # sending and receiving to the same address + privkey1 = "cQY2s58LhzUCmEXN8jtAp1Etnijx78YRZ466w4ikX1V4UpTpbsf8" + address1 = "myAUWSHnwsQrhuMWv4Br6QsCnpB41vFwHn" + address1hash = "c192bff751af8efec15135d42bfeedf91a6f3e34".decode("hex") + address1script = CScript([OP_DUP, OP_HASH160, address1hash, OP_EQUALVERIFY, OP_CHECKSIG]) + + self.nodes[0].sendtoaddress(address1, 10) + self.nodes[0].generate(1) + self.sync_all() + + utxos = self.nodes[1].getaddressutxos({"addresses": [address1]}) + assert_equal(len(utxos), 1) + + tx = CTransaction() + tx.vin = [ + CTxIn(COutPoint(int(utxos[0]["txid"], 16), utxos[0]["outputIndex"])) + ] + amount = utxos[0]["satoshis"] - 1000 + tx.vout = [CTxOut(amount, address1script)] + tx.rehash() + self.nodes[0].importprivkey(privkey1) + signed_tx = self.nodes[0].signrawtransaction(binascii.hexlify(tx.serialize()).decode("utf-8")) + mem_txid = self.nodes[0].sendrawtransaction(signed_tx["hex"], True) + + self.sync_all() + mempool_deltas = self.nodes[2].getaddressmempool({"addresses": [address1]}) + assert_equal(len(mempool_deltas), 2) + + # Include chaininfo in results + print "Testing results with chain info..." + + deltas_with_info = self.nodes[1].getaddressdeltas({ + "addresses": [address2], + "start": 1, + "end": 200, + "chainInfo": True + }) + start_block_hash = self.nodes[1].getblockhash(1); + end_block_hash = self.nodes[1].getblockhash(200); + assert_equal(deltas_with_info["start"]["height"], 1) + assert_equal(deltas_with_info["start"]["hash"], start_block_hash) + assert_equal(deltas_with_info["end"]["height"], 200) + assert_equal(deltas_with_info["end"]["hash"], end_block_hash) + + utxos_with_info = self.nodes[1].getaddressutxos({"addresses": [address2], "chainInfo": True}) + expected_tip_block_hash = self.nodes[1].getblockhash(267); + assert_equal(utxos_with_info["height"], 267) + assert_equal(utxos_with_info["hash"], expected_tip_block_hash) + + print "Passed\n" + + +if __name__ == '__main__': + AddressIndexTest().main() \ No newline at end of file diff --git a/qa/rpc-tests/spentindex.py b/qa/rpc-tests/spentindex.py new file mode 100644 index 00000000000..ebe2b8cc228 --- /dev/null +++ b/qa/rpc-tests/spentindex.py @@ -0,0 +1,139 @@ +#!/usr/bin/env python2 +# Copyright (c) 2014-2015 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +# +# Test addressindex generation and fetching +# + +import time +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import * +from test_framework.script import * +from test_framework.mininode import * +import binascii + +class SpentIndexTest(BitcoinTestFramework): + + def setup_chain(self): + print("Initializing test directory "+self.options.tmpdir) + initialize_chain_clean(self.options.tmpdir, 4) + + def setup_network(self): + self.nodes = [] + # Nodes 0/1 are "wallet" nodes + self.nodes.append(start_node(0, self.options.tmpdir, ["-debug"])) + self.nodes.append(start_node(1, self.options.tmpdir, ["-debug", "-spentindex"])) + # Nodes 2/3 are used for testing + self.nodes.append(start_node(2, self.options.tmpdir, ["-debug", "-spentindex"])) + self.nodes.append(start_node(3, self.options.tmpdir, ["-debug", "-spentindex", "-txindex"])) + connect_nodes(self.nodes[0], 1) + connect_nodes(self.nodes[0], 2) + connect_nodes(self.nodes[0], 3) + + self.is_network_split = False + self.sync_all() + + def run_test(self): + print "Mining blocks..." + self.nodes[0].generate(105) + self.sync_all() + + chain_height = self.nodes[1].getblockcount() + assert_equal(chain_height, 105) + + # Check that + print "Testing spent index..." + + privkey = "cSdkPxkAjA4HDr5VHgsebAPDEh9Gyub4HK8UJr2DFGGqKKy4K5sG" + address = "mgY65WSfEmsyYaYPQaXhmXMeBhwp4EcsQW" + addressHash = "0b2f0a0c31bfe0406b0ccc1381fdbe311946dadc".decode("hex") + scriptPubKey = CScript([OP_DUP, OP_HASH160, addressHash, OP_EQUALVERIFY, OP_CHECKSIG]) + unspent = self.nodes[0].listunspent() + tx = CTransaction() + amount = unspent[0]["amount"] * 100000000 + tx.vin = [CTxIn(COutPoint(int(unspent[0]["txid"], 16), unspent[0]["vout"]))] + tx.vout = [CTxOut(amount, scriptPubKey)] + tx.rehash() + + signed_tx = self.nodes[0].signrawtransaction(binascii.hexlify(tx.serialize()).decode("utf-8")) + txid = self.nodes[0].sendrawtransaction(signed_tx["hex"], True) + self.nodes[0].generate(1) + self.sync_all() + + print "Testing getspentinfo method..." + + # Check that the spentinfo works standalone + info = self.nodes[1].getspentinfo({"txid": unspent[0]["txid"], "index": unspent[0]["vout"]}) + assert_equal(info["txid"], txid) + assert_equal(info["index"], 0) + assert_equal(info["height"], 106) + + print "Testing getrawtransaction method..." + + # Check that verbose raw transaction includes spent info + txVerbose = self.nodes[3].getrawtransaction(unspent[0]["txid"], 1) + assert_equal(txVerbose["vout"][unspent[0]["vout"]]["spentTxId"], txid) + assert_equal(txVerbose["vout"][unspent[0]["vout"]]["spentIndex"], 0) + assert_equal(txVerbose["vout"][unspent[0]["vout"]]["spentHeight"], 106) + + # Check that verbose raw transaction includes input values + txVerbose2 = self.nodes[3].getrawtransaction(txid, 1) + assert_equal(txVerbose2["vin"][0]["value"], Decimal(unspent[0]["amount"])) + assert_equal(txVerbose2["vin"][0]["valueSat"], amount) + + # Check that verbose raw transaction includes address values and input values + privkey2 = "cSdkPxkAjA4HDr5VHgsebAPDEh9Gyub4HK8UJr2DFGGqKKy4K5sG" + address2 = "mgY65WSfEmsyYaYPQaXhmXMeBhwp4EcsQW" + addressHash2 = "0b2f0a0c31bfe0406b0ccc1381fdbe311946dadc".decode("hex") + scriptPubKey2 = CScript([OP_DUP, OP_HASH160, addressHash2, OP_EQUALVERIFY, OP_CHECKSIG]) + tx2 = CTransaction() + tx2.vin = [CTxIn(COutPoint(int(txid, 16), 0))] + tx2.vout = [CTxOut(amount, scriptPubKey2)] + tx.rehash() + self.nodes[0].importprivkey(privkey) + signed_tx2 = self.nodes[0].signrawtransaction(binascii.hexlify(tx2.serialize()).decode("utf-8")) + txid2 = self.nodes[0].sendrawtransaction(signed_tx2["hex"], True) + + # Check the mempool index + self.sync_all() + txVerbose3 = self.nodes[1].getrawtransaction(txid2, 1) + assert_equal(txVerbose3["vin"][0]["address"], address2) + assert_equal(txVerbose3["vin"][0]["value"], Decimal(unspent[0]["amount"])) + assert_equal(txVerbose3["vin"][0]["valueSat"], amount) + + # Check the database index + block_hash = self.nodes[0].generate(1) + self.sync_all() + + txVerbose4 = self.nodes[3].getrawtransaction(txid2, 1) + assert_equal(txVerbose4["vin"][0]["address"], address2) + assert_equal(txVerbose4["vin"][0]["value"], Decimal(unspent[0]["amount"])) + assert_equal(txVerbose4["vin"][0]["valueSat"], amount) + + + # Check block deltas + print "Testing getblockdeltas..." + + block = self.nodes[3].getblockdeltas(block_hash[0]) + assert_equal(len(block["deltas"]), 2) + assert_equal(block["deltas"][0]["index"], 0) + assert_equal(len(block["deltas"][0]["inputs"]), 0) + assert_equal(len(block["deltas"][0]["outputs"]), 0) + assert_equal(block["deltas"][1]["index"], 1) + assert_equal(block["deltas"][1]["txid"], txid2) + assert_equal(block["deltas"][1]["inputs"][0]["index"], 0) + assert_equal(block["deltas"][1]["inputs"][0]["address"], "mgY65WSfEmsyYaYPQaXhmXMeBhwp4EcsQW") + assert_equal(block["deltas"][1]["inputs"][0]["satoshis"], amount * -1) + assert_equal(block["deltas"][1]["inputs"][0]["prevtxid"], txid) + assert_equal(block["deltas"][1]["inputs"][0]["prevout"], 0) + assert_equal(block["deltas"][1]["outputs"][0]["index"], 0) + assert_equal(block["deltas"][1]["outputs"][0]["address"], "mgY65WSfEmsyYaYPQaXhmXMeBhwp4EcsQW") + assert_equal(block["deltas"][1]["outputs"][0]["satoshis"], amount) + + print "Passed\n" + + +if __name__ == '__main__': + SpentIndexTest().main() \ No newline at end of file diff --git a/qa/rpc-tests/test_framework/__init__.py b/qa/rpc-tests/test_framework/__init__.py old mode 100644 new mode 100755 diff --git a/qa/rpc-tests/test_framework/authproxy.py b/qa/rpc-tests/test_framework/authproxy.py old mode 100644 new mode 100755 diff --git a/qa/rpc-tests/test_framework/bignum.py b/qa/rpc-tests/test_framework/bignum.py old mode 100644 new mode 100755 diff --git a/qa/rpc-tests/test_framework/blockstore.py b/qa/rpc-tests/test_framework/blockstore.py old mode 100644 new mode 100755 diff --git a/qa/rpc-tests/test_framework/blocktools.py b/qa/rpc-tests/test_framework/blocktools.py old mode 100644 new mode 100755 diff --git a/qa/rpc-tests/test_framework/netutil.py b/qa/rpc-tests/test_framework/netutil.py old mode 100644 new mode 100755 diff --git a/qa/rpc-tests/test_framework/script.py b/qa/rpc-tests/test_framework/script.py old mode 100644 new mode 100755 diff --git a/qa/rpc-tests/test_framework/socks5.py b/qa/rpc-tests/test_framework/socks5.py old mode 100644 new mode 100755 diff --git a/qa/rpc-tests/test_framework/util.py b/qa/rpc-tests/test_framework/util.py old mode 100644 new mode 100755 diff --git a/qa/rpc-tests/timestampindex.py b/qa/rpc-tests/timestampindex.py new file mode 100644 index 00000000000..23244159fee --- /dev/null +++ b/qa/rpc-tests/timestampindex.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python2 +# Copyright (c) 2014-2015 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +# +# Test timestampindex generation and fetching +# + +import time + +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import * + + +class TimestampIndexTest(BitcoinTestFramework): + + def setup_chain(self): + print("Initializing test directory "+self.options.tmpdir) + initialize_chain_clean(self.options.tmpdir, 4) + + def setup_network(self): + self.nodes = [] + # Nodes 0/1 are "wallet" nodes + self.nodes.append(start_node(0, self.options.tmpdir, ["-debug"])) + self.nodes.append(start_node(1, self.options.tmpdir, ["-debug", "-timestampindex"])) + # Nodes 2/3 are used for testing + self.nodes.append(start_node(2, self.options.tmpdir, ["-debug"])) + self.nodes.append(start_node(3, self.options.tmpdir, ["-debug", "-timestampindex"])) + connect_nodes(self.nodes[0], 1) + connect_nodes(self.nodes[0], 2) + connect_nodes(self.nodes[0], 3) + + self.is_network_split = False + self.sync_all() + + def run_test(self): + print "Mining 25 blocks..." + blockhashes = self.nodes[0].generate(25) + time.sleep(3) + print "Mining 25 blocks..." + blockhashes.extend(self.nodes[0].generate(25)) + time.sleep(3) + print "Mining 25 blocks..." + blockhashes.extend(self.nodes[0].generate(25)) + self.sync_all() + low = self.nodes[1].getblock(blockhashes[0])["time"] + high = low + 76 + + print "Checking timestamp index..." + hashes = self.nodes[1].getblockhashes(high, low) + + assert_equal(len(hashes), len(blockhashes)) + + assert_equal(hashes, blockhashes) + + print "Passed\n" + + +if __name__ == '__main__': + TimestampIndexTest().main() \ No newline at end of file diff --git a/qa/rpc-tests/txindex.py b/qa/rpc-tests/txindex.py new file mode 100644 index 00000000000..e59b6d7d93d --- /dev/null +++ b/qa/rpc-tests/txindex.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python2 +# Copyright (c) 2014-2015 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +# +# Test txindex generation and fetching +# + +import time +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import * +from test_framework.script import * +from test_framework.mininode import * +import binascii + +class TxIndexTest(BitcoinTestFramework): + + def setup_chain(self): + print("Initializing test directory "+self.options.tmpdir) + initialize_chain_clean(self.options.tmpdir, 4) + + def setup_network(self): + self.nodes = [] + # Nodes 0/1 are "wallet" nodes + self.nodes.append(start_node(0, self.options.tmpdir, ["-debug"])) + self.nodes.append(start_node(1, self.options.tmpdir, ["-debug", "-txindex"])) + # Nodes 2/3 are used for testing + self.nodes.append(start_node(2, self.options.tmpdir, ["-debug", "-txindex"])) + self.nodes.append(start_node(3, self.options.tmpdir, ["-debug", "-txindex"])) + connect_nodes(self.nodes[0], 1) + connect_nodes(self.nodes[0], 2) + connect_nodes(self.nodes[0], 3) + + self.is_network_split = False + self.sync_all() + + def run_test(self): + print "Mining blocks..." + self.nodes[0].generate(105) + self.sync_all() + + chain_height = self.nodes[1].getblockcount() + assert_equal(chain_height, 105) + + print "Testing transaction index..." + + privkey = "cSdkPxkAjA4HDr5VHgsebAPDEh9Gyub4HK8UJr2DFGGqKKy4K5sG" + address = "mgY65WSfEmsyYaYPQaXhmXMeBhwp4EcsQW" + addressHash = "0b2f0a0c31bfe0406b0ccc1381fdbe311946dadc".decode("hex") + scriptPubKey = CScript([OP_DUP, OP_HASH160, addressHash, OP_EQUALVERIFY, OP_CHECKSIG]) + unspent = self.nodes[0].listunspent() + tx = CTransaction() + amount = unspent[0]["amount"] * 100000000 + tx.vin = [CTxIn(COutPoint(int(unspent[0]["txid"], 16), unspent[0]["vout"]))] + tx.vout = [CTxOut(amount, scriptPubKey)] + tx.rehash() + + signed_tx = self.nodes[0].signrawtransaction(binascii.hexlify(tx.serialize()).decode("utf-8")) + txid = self.nodes[0].sendrawtransaction(signed_tx["hex"], True) + self.nodes[0].generate(1) + self.sync_all() + + # Check verbose raw transaction results + verbose = self.nodes[3].getrawtransaction(unspent[0]["txid"], 1) + assert_equal(verbose["vout"][0]["valueSat"], 5000000000); + assert_equal(verbose["vout"][0]["value"], 50); + + print "Passed\n" + + +if __name__ == '__main__': + TxIndexTest().main() \ No newline at end of file diff --git a/qa/rpc-tests/wallet_shieldcoinbase.py b/qa/rpc-tests/wallet_shieldcoinbase.py old mode 100755 new mode 100644 diff --git a/qa/zcash/create_benchmark_archive.py b/qa/zcash/create_benchmark_archive.py old mode 100644 new mode 100755 diff --git a/share/certs/BitcoinFoundation_Apple_Cert.pem b/share/certs/BitcoinFoundation_Apple_Cert.pem old mode 100644 new mode 100755 diff --git a/share/certs/BitcoinFoundation_Comodo_Cert.pem b/share/certs/BitcoinFoundation_Comodo_Cert.pem old mode 100644 new mode 100755 diff --git a/share/certs/PrivateKeyNotes.md b/share/certs/PrivateKeyNotes.md old mode 100644 new mode 100755 diff --git a/share/pixmaps/addressbook16.bmp b/share/pixmaps/addressbook16.bmp old mode 100644 new mode 100755 diff --git a/share/pixmaps/addressbook16mask.bmp b/share/pixmaps/addressbook16mask.bmp old mode 100644 new mode 100755 diff --git a/share/pixmaps/addressbook20.bmp b/share/pixmaps/addressbook20.bmp old mode 100644 new mode 100755 diff --git a/share/pixmaps/addressbook20mask.bmp b/share/pixmaps/addressbook20mask.bmp old mode 100644 new mode 100755 diff --git a/share/pixmaps/bitcoin-bc.ico b/share/pixmaps/bitcoin-bc.ico old mode 100644 new mode 100755 diff --git a/share/pixmaps/bitcoin.ico b/share/pixmaps/bitcoin.ico old mode 100644 new mode 100755 diff --git a/share/pixmaps/bitcoin128.png b/share/pixmaps/bitcoin128.png old mode 100644 new mode 100755 diff --git a/share/pixmaps/bitcoin128.xpm b/share/pixmaps/bitcoin128.xpm old mode 100644 new mode 100755 diff --git a/share/pixmaps/bitcoin16.png b/share/pixmaps/bitcoin16.png old mode 100644 new mode 100755 diff --git a/share/pixmaps/bitcoin16.xpm b/share/pixmaps/bitcoin16.xpm old mode 100644 new mode 100755 diff --git a/share/pixmaps/bitcoin256.png b/share/pixmaps/bitcoin256.png old mode 100644 new mode 100755 diff --git a/share/pixmaps/bitcoin256.xpm b/share/pixmaps/bitcoin256.xpm old mode 100644 new mode 100755 diff --git a/share/pixmaps/bitcoin32.png b/share/pixmaps/bitcoin32.png old mode 100644 new mode 100755 diff --git a/share/pixmaps/bitcoin32.xpm b/share/pixmaps/bitcoin32.xpm old mode 100644 new mode 100755 diff --git a/share/pixmaps/bitcoin64.png b/share/pixmaps/bitcoin64.png old mode 100644 new mode 100755 diff --git a/share/pixmaps/bitcoin64.xpm b/share/pixmaps/bitcoin64.xpm old mode 100644 new mode 100755 diff --git a/share/pixmaps/check.ico b/share/pixmaps/check.ico old mode 100644 new mode 100755 diff --git a/share/pixmaps/favicon.ico b/share/pixmaps/favicon.ico old mode 100644 new mode 100755 diff --git a/share/pixmaps/nsis-header.bmp b/share/pixmaps/nsis-header.bmp old mode 100644 new mode 100755 diff --git a/share/pixmaps/nsis-wizard.bmp b/share/pixmaps/nsis-wizard.bmp old mode 100644 new mode 100755 diff --git a/share/pixmaps/send16.bmp b/share/pixmaps/send16.bmp old mode 100644 new mode 100755 diff --git a/share/pixmaps/send16mask.bmp b/share/pixmaps/send16mask.bmp old mode 100644 new mode 100755 diff --git a/share/pixmaps/send16masknoshadow.bmp b/share/pixmaps/send16masknoshadow.bmp old mode 100644 new mode 100755 diff --git a/share/pixmaps/send20.bmp b/share/pixmaps/send20.bmp old mode 100644 new mode 100755 diff --git a/share/pixmaps/send20mask.bmp b/share/pixmaps/send20mask.bmp old mode 100644 new mode 100755 diff --git a/share/setup.nsi.in b/share/setup.nsi.in old mode 100644 new mode 100755 diff --git a/share/ui.rc b/share/ui.rc old mode 100644 new mode 100755 diff --git a/src/.clang-format b/src/.clang-format old mode 100644 new mode 100755 diff --git a/src/Makefile.am b/src/Makefile.am old mode 100644 new mode 100755 diff --git a/src/Makefile.gtest.include b/src/Makefile.gtest.include old mode 100644 new mode 100755 diff --git a/src/Makefile.test.include b/src/Makefile.test.include old mode 100644 new mode 100755 index d18f2964609..7e8eeaae5d4 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -15,7 +15,9 @@ EXTRA_DIST += \ test/data/tx394b54bb.hex \ test/data/txcreate1.hex \ test/data/txcreate2.hex \ - test/data/txcreatesign.hex + test/data/txcreatesign.hex \ + test/wallet-utility.py \ + test/data/wallet.dat JSON_TEST_FILES = \ test/data/script_valid.json \ @@ -75,6 +77,7 @@ BITCOIN_TESTS =\ test/sanity_tests.cpp \ test/scheduler_tests.cpp \ test/script_P2SH_tests.cpp \ + test/script_P2PKH_tests.cpp \ test/script_tests.cpp \ test/scriptnum_tests.cpp \ test/serialize_tests.cpp \ @@ -136,6 +139,11 @@ bitcoin_test_clean : FORCE check-local: @echo "Running test/bitcoin-util-test.py..." $(AM_V_at)srcdir=$(srcdir) PYTHONPATH=$(builddir)/test $(srcdir)/test/bitcoin-util-test.py + +if ENABLE_WALLET + @echo "Running test/wallet-utility.py..." + $(AM_V_at)srcdir=$(srcdir) PYTHONPATH=$(builddir)/test $(srcdir)/test/wallet-utility.py +endif $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C secp256k1 check $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C univalue check diff --git a/src/Makefile.zcash.include b/src/Makefile.zcash.include old mode 100644 new mode 100755 diff --git a/src/addressindex.h b/src/addressindex.h new file mode 100755 index 00000000000..9e734b84dcd --- /dev/null +++ b/src/addressindex.h @@ -0,0 +1,82 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2015 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_ADDRESSINDEX_H +#define BITCOIN_ADDRESSINDEX_H + +#include "uint256.h" +#include "amount.h" + +struct CMempoolAddressDelta +{ + int64_t time; + CAmount amount; + uint256 prevhash; + unsigned int prevout; + + CMempoolAddressDelta(int64_t t, CAmount a, uint256 hash, unsigned int out) { + time = t; + amount = a; + prevhash = hash; + prevout = out; + } + + CMempoolAddressDelta(int64_t t, CAmount a) { + time = t; + amount = a; + prevhash.SetNull(); + prevout = 0; + } +}; + +struct CMempoolAddressDeltaKey +{ + int type; + uint160 addressBytes; + uint256 txhash; + unsigned int index; + int spending; + + CMempoolAddressDeltaKey(int addressType, uint160 addressHash, uint256 hash, unsigned int i, int s) { + type = addressType; + addressBytes = addressHash; + txhash = hash; + index = i; + spending = s; + } + + CMempoolAddressDeltaKey(int addressType, uint160 addressHash) { + type = addressType; + addressBytes = addressHash; + txhash.SetNull(); + index = 0; + spending = 0; + } +}; + +struct CMempoolAddressDeltaKeyCompare +{ + bool operator()(const CMempoolAddressDeltaKey& a, const CMempoolAddressDeltaKey& b) const { + if (a.type == b.type) { + if (a.addressBytes == b.addressBytes) { + if (a.txhash == b.txhash) { + if (a.index == b.index) { + return a.spending < b.spending; + } else { + return a.index < b.index; + } + } else { + return a.txhash < b.txhash; + } + } else { + return a.addressBytes < b.addressBytes; + } + } else { + return a.type < b.type; + } + } +}; + +#endif // BITCOIN_ADDRESSINDEX_H diff --git a/src/addrman.cpp b/src/addrman.cpp old mode 100644 new mode 100755 diff --git a/src/addrman.h b/src/addrman.h old mode 100644 new mode 100755 diff --git a/src/alert.cpp b/src/alert.cpp old mode 100644 new mode 100755 diff --git a/src/alert.h b/src/alert.h old mode 100644 new mode 100755 diff --git a/src/alertkeys.h b/src/alertkeys.h old mode 100644 new mode 100755 diff --git a/src/amount.cpp b/src/amount.cpp old mode 100644 new mode 100755 diff --git a/src/amount.h b/src/amount.h old mode 100644 new mode 100755 diff --git a/src/amqp/amqpabstractnotifier.cpp b/src/amqp/amqpabstractnotifier.cpp old mode 100644 new mode 100755 diff --git a/src/amqp/amqpabstractnotifier.h b/src/amqp/amqpabstractnotifier.h old mode 100644 new mode 100755 diff --git a/src/amqp/amqpconfig.h b/src/amqp/amqpconfig.h old mode 100644 new mode 100755 diff --git a/src/amqp/amqpnotificationinterface.cpp b/src/amqp/amqpnotificationinterface.cpp old mode 100644 new mode 100755 diff --git a/src/amqp/amqpnotificationinterface.h b/src/amqp/amqpnotificationinterface.h old mode 100644 new mode 100755 diff --git a/src/amqp/amqppublishnotifier.cpp b/src/amqp/amqppublishnotifier.cpp old mode 100644 new mode 100755 diff --git a/src/amqp/amqppublishnotifier.h b/src/amqp/amqppublishnotifier.h old mode 100644 new mode 100755 diff --git a/src/amqp/amqpsender.h b/src/amqp/amqpsender.h old mode 100644 new mode 100755 diff --git a/src/arith_uint256.cpp b/src/arith_uint256.cpp old mode 100644 new mode 100755 diff --git a/src/arith_uint256.h b/src/arith_uint256.h old mode 100644 new mode 100755 diff --git a/src/asyncrpcoperation.cpp b/src/asyncrpcoperation.cpp old mode 100644 new mode 100755 diff --git a/src/asyncrpcoperation.h b/src/asyncrpcoperation.h old mode 100644 new mode 100755 diff --git a/src/asyncrpcqueue.cpp b/src/asyncrpcqueue.cpp old mode 100644 new mode 100755 diff --git a/src/asyncrpcqueue.h b/src/asyncrpcqueue.h old mode 100644 new mode 100755 diff --git a/src/base58.cpp b/src/base58.cpp old mode 100644 new mode 100755 index 12e2496da9b..2c46f7540ed --- a/src/base58.cpp +++ b/src/base58.cpp @@ -275,6 +275,23 @@ CTxDestination CBitcoinAddress::Get() const return CNoDestination(); } +bool CBitcoinAddress::GetIndexKey(uint160& hashBytes, int& type) const +{ + if (!IsValid()) { + return false; + } else if (vchVersion == Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS)) { + memcpy(&hashBytes, &vchData[0], 20); + type = 1; + return true; + } else if (vchVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS)) { + memcpy(&hashBytes, &vchData[0], 20); + type = 2; + return true; + } + + return false; +} + bool CBitcoinAddress::GetKeyID(CKeyID& keyID) const { if (!IsValid() || vchVersion != Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS)) diff --git a/src/base58.h b/src/base58.h old mode 100644 new mode 100755 index 88efadbd6ed..0fad3db0f9c --- a/src/base58.h +++ b/src/base58.h @@ -141,6 +141,7 @@ class CBitcoinAddress : public CBase58Data { CTxDestination Get() const; bool GetKeyID(CKeyID &keyID) const; + bool GetIndexKey(uint160& hashBytes, int& type) const; bool IsScript() const; }; diff --git a/src/bitcoin-cli-res.rc b/src/bitcoin-cli-res.rc old mode 100644 new mode 100755 diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp old mode 100644 new mode 100755 diff --git a/src/bitcoin-tx-res.rc b/src/bitcoin-tx-res.rc old mode 100644 new mode 100755 diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp old mode 100644 new mode 100755 diff --git a/src/bitcoind-res.rc b/src/bitcoind-res.rc old mode 100644 new mode 100755 diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp old mode 100644 new mode 100755 diff --git a/src/bloom.cpp b/src/bloom.cpp old mode 100644 new mode 100755 diff --git a/src/bloom.h b/src/bloom.h old mode 100644 new mode 100755 diff --git a/src/chain.cpp b/src/chain.cpp old mode 100644 new mode 100755 diff --git a/src/chain.h b/src/chain.h old mode 100644 new mode 100755 diff --git a/src/chainparams.cpp b/src/chainparams.cpp old mode 100644 new mode 100755 diff --git a/src/chainparams.h b/src/chainparams.h old mode 100644 new mode 100755 diff --git a/src/chainparamsbase.cpp b/src/chainparamsbase.cpp old mode 100644 new mode 100755 diff --git a/src/chainparamsbase.h b/src/chainparamsbase.h old mode 100644 new mode 100755 diff --git a/src/chainparamsseeds.h b/src/chainparamsseeds.h old mode 100644 new mode 100755 diff --git a/src/checkpoints.cpp b/src/checkpoints.cpp old mode 100644 new mode 100755 diff --git a/src/checkpoints.h b/src/checkpoints.h old mode 100644 new mode 100755 diff --git a/src/checkqueue.h b/src/checkqueue.h old mode 100644 new mode 100755 diff --git a/src/clientversion.cpp b/src/clientversion.cpp old mode 100644 new mode 100755 diff --git a/src/clientversion.h b/src/clientversion.h old mode 100644 new mode 100755 diff --git a/src/coincontrol.h b/src/coincontrol.h old mode 100644 new mode 100755 diff --git a/src/coins.cpp b/src/coins.cpp old mode 100644 new mode 100755 diff --git a/src/coins.h b/src/coins.h old mode 100644 new mode 100755 diff --git a/src/compat.h b/src/compat.h old mode 100644 new mode 100755 diff --git a/src/compat/byteswap.h b/src/compat/byteswap.h old mode 100644 new mode 100755 diff --git a/src/compat/endian.h b/src/compat/endian.h old mode 100644 new mode 100755 diff --git a/src/compat/glibc_compat.cpp b/src/compat/glibc_compat.cpp old mode 100644 new mode 100755 diff --git a/src/compat/glibc_sanity.cpp b/src/compat/glibc_sanity.cpp old mode 100644 new mode 100755 diff --git a/src/compat/glibcxx_sanity.cpp b/src/compat/glibcxx_sanity.cpp old mode 100644 new mode 100755 diff --git a/src/compat/sanity.h b/src/compat/sanity.h old mode 100644 new mode 100755 diff --git a/src/compat/strnlen.cpp b/src/compat/strnlen.cpp old mode 100644 new mode 100755 diff --git a/src/compressor.cpp b/src/compressor.cpp old mode 100644 new mode 100755 diff --git a/src/compressor.h b/src/compressor.h old mode 100644 new mode 100755 diff --git a/src/config/.empty b/src/config/.empty old mode 100644 new mode 100755 diff --git a/src/consensus/consensus.h b/src/consensus/consensus.h old mode 100644 new mode 100755 diff --git a/src/consensus/params.h b/src/consensus/params.h old mode 100644 new mode 100755 diff --git a/src/consensus/validation.h b/src/consensus/validation.h old mode 100644 new mode 100755 diff --git a/src/core_io.h b/src/core_io.h old mode 100644 new mode 100755 diff --git a/src/core_memusage.h b/src/core_memusage.h old mode 100644 new mode 100755 diff --git a/src/core_read.cpp b/src/core_read.cpp old mode 100644 new mode 100755 diff --git a/src/core_write.cpp b/src/core_write.cpp old mode 100644 new mode 100755 diff --git a/src/crypto/common.h b/src/crypto/common.h old mode 100644 new mode 100755 diff --git a/src/crypto/equihash.cpp b/src/crypto/equihash.cpp old mode 100644 new mode 100755 diff --git a/src/crypto/equihash.h b/src/crypto/equihash.h old mode 100644 new mode 100755 diff --git a/src/crypto/equihash.tcc b/src/crypto/equihash.tcc old mode 100644 new mode 100755 diff --git a/src/crypto/hmac_sha256.cpp b/src/crypto/hmac_sha256.cpp old mode 100644 new mode 100755 diff --git a/src/crypto/hmac_sha256.h b/src/crypto/hmac_sha256.h old mode 100644 new mode 100755 diff --git a/src/crypto/hmac_sha512.cpp b/src/crypto/hmac_sha512.cpp old mode 100644 new mode 100755 diff --git a/src/crypto/hmac_sha512.h b/src/crypto/hmac_sha512.h old mode 100644 new mode 100755 diff --git a/src/crypto/ripemd160.cpp b/src/crypto/ripemd160.cpp old mode 100644 new mode 100755 diff --git a/src/crypto/ripemd160.h b/src/crypto/ripemd160.h old mode 100644 new mode 100755 diff --git a/src/crypto/sha1.cpp b/src/crypto/sha1.cpp old mode 100644 new mode 100755 diff --git a/src/crypto/sha1.h b/src/crypto/sha1.h old mode 100644 new mode 100755 diff --git a/src/crypto/sha256.cpp b/src/crypto/sha256.cpp old mode 100644 new mode 100755 diff --git a/src/crypto/sha256.h b/src/crypto/sha256.h old mode 100644 new mode 100755 diff --git a/src/crypto/sha512.cpp b/src/crypto/sha512.cpp old mode 100644 new mode 100755 diff --git a/src/crypto/sha512.h b/src/crypto/sha512.h old mode 100644 new mode 100755 diff --git a/src/deprecation.cpp b/src/deprecation.cpp old mode 100644 new mode 100755 diff --git a/src/deprecation.h b/src/deprecation.h old mode 100644 new mode 100755 diff --git a/src/gtest/json_test_vectors.cpp b/src/gtest/json_test_vectors.cpp old mode 100644 new mode 100755 diff --git a/src/gtest/json_test_vectors.h b/src/gtest/json_test_vectors.h old mode 100644 new mode 100755 diff --git a/src/gtest/main.cpp b/src/gtest/main.cpp old mode 100644 new mode 100755 diff --git a/src/gtest/test_block.cpp b/src/gtest/test_block.cpp old mode 100644 new mode 100755 diff --git a/src/gtest/test_checkblock.cpp b/src/gtest/test_checkblock.cpp old mode 100644 new mode 100755 diff --git a/src/gtest/test_checktransaction.cpp b/src/gtest/test_checktransaction.cpp old mode 100644 new mode 100755 diff --git a/src/gtest/test_circuit.cpp b/src/gtest/test_circuit.cpp old mode 100644 new mode 100755 diff --git a/src/gtest/test_deprecation.cpp b/src/gtest/test_deprecation.cpp old mode 100644 new mode 100755 diff --git a/src/gtest/test_equihash.cpp b/src/gtest/test_equihash.cpp old mode 100644 new mode 100755 diff --git a/src/gtest/test_joinsplit.cpp b/src/gtest/test_joinsplit.cpp old mode 100644 new mode 100755 diff --git a/src/gtest/test_keystore.cpp b/src/gtest/test_keystore.cpp old mode 100644 new mode 100755 diff --git a/src/gtest/test_libzcash_utils.cpp b/src/gtest/test_libzcash_utils.cpp old mode 100644 new mode 100755 diff --git a/src/gtest/test_mempool.cpp b/src/gtest/test_mempool.cpp old mode 100644 new mode 100755 diff --git a/src/gtest/test_merkletree.cpp b/src/gtest/test_merkletree.cpp old mode 100644 new mode 100755 diff --git a/src/gtest/test_metrics.cpp b/src/gtest/test_metrics.cpp old mode 100644 new mode 100755 diff --git a/src/gtest/test_miner.cpp b/src/gtest/test_miner.cpp old mode 100644 new mode 100755 diff --git a/src/gtest/test_noteencryption.cpp b/src/gtest/test_noteencryption.cpp old mode 100644 new mode 100755 diff --git a/src/gtest/test_pow.cpp b/src/gtest/test_pow.cpp old mode 100644 new mode 100755 diff --git a/src/gtest/test_proofs.cpp b/src/gtest/test_proofs.cpp old mode 100644 new mode 100755 diff --git a/src/gtest/test_random.cpp b/src/gtest/test_random.cpp old mode 100644 new mode 100755 diff --git a/src/gtest/test_rpc.cpp b/src/gtest/test_rpc.cpp old mode 100644 new mode 100755 diff --git a/src/gtest/test_tautology.cpp b/src/gtest/test_tautology.cpp old mode 100644 new mode 100755 diff --git a/src/gtest/test_transaction.cpp b/src/gtest/test_transaction.cpp old mode 100644 new mode 100755 diff --git a/src/gtest/test_txid.cpp b/src/gtest/test_txid.cpp old mode 100644 new mode 100755 diff --git a/src/gtest/test_validation.cpp b/src/gtest/test_validation.cpp old mode 100644 new mode 100755 diff --git a/src/gtest/utils.cpp b/src/gtest/utils.cpp old mode 100644 new mode 100755 diff --git a/src/hash.cpp b/src/hash.cpp old mode 100644 new mode 100755 diff --git a/src/hash.h b/src/hash.h old mode 100644 new mode 100755 diff --git a/src/httprpc.cpp b/src/httprpc.cpp old mode 100644 new mode 100755 diff --git a/src/httprpc.h b/src/httprpc.h old mode 100644 new mode 100755 diff --git a/src/httpserver.cpp b/src/httpserver.cpp old mode 100644 new mode 100755 diff --git a/src/httpserver.h b/src/httpserver.h old mode 100644 new mode 100755 diff --git a/src/init.cpp b/src/init.cpp old mode 100644 new mode 100755 index 1419140a379..bab4380098c --- a/src/init.cpp +++ b/src/init.cpp @@ -3,6 +3,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. + #if defined(HAVE_CONFIG_H) #include "config/bitcoin-config.h" #endif @@ -42,6 +43,8 @@ #ifndef WIN32 #include +#else +#include #endif #include @@ -129,6 +132,7 @@ CClientUIInterface uiInterface; // Declared but not defined in ui_interface.h // std::atomic fRequestShutdown(false); +std::atomic fShutdownCompleted(false); void StartShutdown() { @@ -270,6 +274,8 @@ void Shutdown() globalVerifyHandle.reset(); ECC_Stop(); LogPrintf("%s: done\n", __func__); + + fShutdownCompleted = true; } /** @@ -285,6 +291,34 @@ void HandleSIGHUP(int) fReopenDebugLog = true; } +#ifdef WIN32 +BOOL CtrlHandler( DWORD fdwCtrlType ) +{ + int64_t nMaxWait = 15; // seconds + int64_t nStart = GetTime(); + switch (fdwCtrlType) { + case CTRL_C_EVENT: + case CTRL_CLOSE_EVENT: + case CTRL_BREAK_EVENT: + case CTRL_LOGOFF_EVENT: + case CTRL_SHUTDOWN_EVENT: + fRequestShutdown = true; + std::cout << _("Shutting down node. This may take a while, be patient!") << std::endl; + while (!fShutdownCompleted) { + if (GetTime() - nStart >= nMaxWait) { + error("Shutdown didn't complete in a timely manner"); + break; + } + MilliSleep(100); + } + return TRUE; + + default: + return FALSE; + } +} +#endif + bool static InitError(const std::string &str) { uiInterface.ThreadSafeMessageBox(str, "", CClientUIInterface::MSG_ERROR); @@ -367,6 +401,10 @@ std::string HelpMessage(HelpMessageMode mode) #endif strUsage += HelpMessageOpt("-txindex", strprintf(_("Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)"), 0)); + strUsage += HelpMessageOpt("-addressindex", strprintf(_("Maintain a full address index, used to query for the balance, txids and unspent outputs for addresses (default: %u)"), DEFAULT_ADDRESSINDEX)); + strUsage += HelpMessageOpt("-timestampindex", strprintf(_("Maintain a timestamp index for block hashes, used to query blocks hashes by a range of timestamps (default: %u)"), DEFAULT_TIMESTAMPINDEX)); + strUsage += HelpMessageOpt("-spentindex", strprintf(_("Maintain a full spent index, used to query the spending txid and input index for an outpoint (default: %u)"), DEFAULT_SPENTINDEX)); + strUsage += HelpMessageGroup(_("Connection options:")); strUsage += HelpMessageOpt("-addnode=", _("Add a node to connect to and attempt to keep the connection open")); strUsage += HelpMessageOpt("-banscore=", strprintf(_("Threshold for disconnecting misbehaving peers (default: %u)"), 100)); @@ -1326,18 +1364,34 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) } } + // block tree db settings + int dbMaxOpenFiles = GetArg("-dbmaxopenfiles", DEFAULT_DB_MAX_OPEN_FILES); + bool dbCompression = GetBoolArg("-dbcompression", DEFAULT_DB_COMPRESSION); + + LogPrintf("Block index database configuration:\n"); + LogPrintf("* Using %d max open files\n", dbMaxOpenFiles); + LogPrintf("* Compression is %s\n", dbCompression ? "enabled" : "disabled"); + + // cache size calculations int64_t nTotalCache = (GetArg("-dbcache", nDefaultDbCache) << 20); nTotalCache = std::max(nTotalCache, nMinDbCache << 20); // total cache cannot be less than nMinDbCache nTotalCache = std::min(nTotalCache, nMaxDbCache << 20); // total cache cannot be greated than nMaxDbcache int64_t nBlockTreeDBCache = nTotalCache / 8; - if (nBlockTreeDBCache > (1 << 21) && !GetBoolArg("-txindex", false)) - nBlockTreeDBCache = (1 << 21); // block tree db cache shouldn't be larger than 2 MiB + if (GetBoolArg("-addressindex", DEFAULT_ADDRESSINDEX) || GetBoolArg("-spentindex", DEFAULT_SPENTINDEX)) { + // enable 3/4 of the cache if addressindex and/or spentindex is enabled + nBlockTreeDBCache = nTotalCache * 3 / 4; + } else { + if (nBlockTreeDBCache > (1 << 21) && !GetBoolArg("-txindex", false)) { + nBlockTreeDBCache = (1 << 21); // block tree db cache shouldn't be larger than 2 MiB + } + } nTotalCache -= nBlockTreeDBCache; int64_t nCoinDBCache = std::min(nTotalCache / 2, (nTotalCache / 4) + (1 << 23)); // use 25%-50% of the remainder for disk cache nTotalCache -= nCoinDBCache; nCoinCacheUsage = nTotalCache; // the rest goes to in-memory cache LogPrintf("Cache configuration:\n"); + LogPrintf("* Max cache setting possible %.1fMiB\n", nMaxDbCache); LogPrintf("* Using %.1fMiB for block index database\n", nBlockTreeDBCache * (1.0 / 1024 / 1024)); LogPrintf("* Using %.1fMiB for chain state database\n", nCoinDBCache * (1.0 / 1024 / 1024)); LogPrintf("* Using %.1fMiB for in-memory UTXO set\n", nCoinCacheUsage * (1.0 / 1024 / 1024)); @@ -1358,7 +1412,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) delete pcoinscatcher; delete pblocktree; - pblocktree = new CBlockTreeDB(nBlockTreeDBCache, false, fReindex); + pblocktree = new CBlockTreeDB(nBlockTreeDBCache, false, fReindex, dbCompression, dbMaxOpenFiles); pcoinsdbview = new CCoinsViewDB(nCoinDBCache, false, fReindex); pcoinscatcher = new CCoinsViewErrorCatcher(pcoinsdbview); pcoinsTip = new CCoinsViewCache(pcoinscatcher); diff --git a/src/init.h b/src/init.h old mode 100644 new mode 100755 diff --git a/src/key.cpp b/src/key.cpp old mode 100644 new mode 100755 diff --git a/src/key.h b/src/key.h old mode 100644 new mode 100755 diff --git a/src/keystore.cpp b/src/keystore.cpp old mode 100644 new mode 100755 diff --git a/src/keystore.h b/src/keystore.h old mode 100644 new mode 100755 diff --git a/src/leveldb/.gitignore b/src/leveldb/.gitignore old mode 100644 new mode 100755 diff --git a/src/leveldb/AUTHORS b/src/leveldb/AUTHORS old mode 100644 new mode 100755 diff --git a/src/leveldb/CONTRIBUTING.md b/src/leveldb/CONTRIBUTING.md old mode 100644 new mode 100755 diff --git a/src/leveldb/LICENSE b/src/leveldb/LICENSE old mode 100644 new mode 100755 diff --git a/src/leveldb/Makefile b/src/leveldb/Makefile old mode 100644 new mode 100755 diff --git a/src/leveldb/NEWS b/src/leveldb/NEWS old mode 100644 new mode 100755 diff --git a/src/leveldb/README b/src/leveldb/README old mode 100644 new mode 100755 diff --git a/src/leveldb/README.md b/src/leveldb/README.md old mode 100644 new mode 100755 diff --git a/src/leveldb/TODO b/src/leveldb/TODO old mode 100644 new mode 100755 diff --git a/src/leveldb/WINDOWS.md b/src/leveldb/WINDOWS.md old mode 100644 new mode 100755 diff --git a/src/leveldb/db/autocompact_test.cc b/src/leveldb/db/autocompact_test.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/db/builder.cc b/src/leveldb/db/builder.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/db/builder.h b/src/leveldb/db/builder.h old mode 100644 new mode 100755 diff --git a/src/leveldb/db/c.cc b/src/leveldb/db/c.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/db/c_test.c b/src/leveldb/db/c_test.c old mode 100644 new mode 100755 diff --git a/src/leveldb/db/corruption_test.cc b/src/leveldb/db/corruption_test.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/db/db_bench.cc b/src/leveldb/db/db_bench.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/db/db_impl.cc b/src/leveldb/db/db_impl.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/db/db_impl.h b/src/leveldb/db/db_impl.h old mode 100644 new mode 100755 diff --git a/src/leveldb/db/db_iter.cc b/src/leveldb/db/db_iter.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/db/db_iter.h b/src/leveldb/db/db_iter.h old mode 100644 new mode 100755 diff --git a/src/leveldb/db/db_test.cc b/src/leveldb/db/db_test.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/db/dbformat.cc b/src/leveldb/db/dbformat.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/db/dbformat.h b/src/leveldb/db/dbformat.h old mode 100644 new mode 100755 diff --git a/src/leveldb/db/dbformat_test.cc b/src/leveldb/db/dbformat_test.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/db/dumpfile.cc b/src/leveldb/db/dumpfile.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/db/filename.cc b/src/leveldb/db/filename.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/db/filename.h b/src/leveldb/db/filename.h old mode 100644 new mode 100755 diff --git a/src/leveldb/db/filename_test.cc b/src/leveldb/db/filename_test.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/db/leveldb_main.cc b/src/leveldb/db/leveldb_main.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/db/log_format.h b/src/leveldb/db/log_format.h old mode 100644 new mode 100755 diff --git a/src/leveldb/db/log_reader.cc b/src/leveldb/db/log_reader.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/db/log_reader.h b/src/leveldb/db/log_reader.h old mode 100644 new mode 100755 diff --git a/src/leveldb/db/log_test.cc b/src/leveldb/db/log_test.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/db/log_writer.cc b/src/leveldb/db/log_writer.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/db/log_writer.h b/src/leveldb/db/log_writer.h old mode 100644 new mode 100755 diff --git a/src/leveldb/db/memtable.cc b/src/leveldb/db/memtable.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/db/memtable.h b/src/leveldb/db/memtable.h old mode 100644 new mode 100755 diff --git a/src/leveldb/db/repair.cc b/src/leveldb/db/repair.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/db/skiplist.h b/src/leveldb/db/skiplist.h old mode 100644 new mode 100755 diff --git a/src/leveldb/db/skiplist_test.cc b/src/leveldb/db/skiplist_test.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/db/snapshot.h b/src/leveldb/db/snapshot.h old mode 100644 new mode 100755 diff --git a/src/leveldb/db/table_cache.cc b/src/leveldb/db/table_cache.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/db/table_cache.h b/src/leveldb/db/table_cache.h old mode 100644 new mode 100755 diff --git a/src/leveldb/db/version_edit.cc b/src/leveldb/db/version_edit.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/db/version_edit.h b/src/leveldb/db/version_edit.h old mode 100644 new mode 100755 diff --git a/src/leveldb/db/version_edit_test.cc b/src/leveldb/db/version_edit_test.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/db/version_set.cc b/src/leveldb/db/version_set.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/db/version_set.h b/src/leveldb/db/version_set.h old mode 100644 new mode 100755 diff --git a/src/leveldb/db/version_set_test.cc b/src/leveldb/db/version_set_test.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/db/write_batch.cc b/src/leveldb/db/write_batch.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/db/write_batch_internal.h b/src/leveldb/db/write_batch_internal.h old mode 100644 new mode 100755 diff --git a/src/leveldb/db/write_batch_test.cc b/src/leveldb/db/write_batch_test.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/doc/bench/db_bench_sqlite3.cc b/src/leveldb/doc/bench/db_bench_sqlite3.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/doc/bench/db_bench_tree_db.cc b/src/leveldb/doc/bench/db_bench_tree_db.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/doc/benchmark.html b/src/leveldb/doc/benchmark.html old mode 100644 new mode 100755 diff --git a/src/leveldb/doc/doc.css b/src/leveldb/doc/doc.css old mode 100644 new mode 100755 diff --git a/src/leveldb/doc/impl.html b/src/leveldb/doc/impl.html old mode 100644 new mode 100755 diff --git a/src/leveldb/doc/index.html b/src/leveldb/doc/index.html old mode 100644 new mode 100755 diff --git a/src/leveldb/doc/log_format.txt b/src/leveldb/doc/log_format.txt old mode 100644 new mode 100755 diff --git a/src/leveldb/doc/table_format.txt b/src/leveldb/doc/table_format.txt old mode 100644 new mode 100755 diff --git a/src/leveldb/helpers/memenv/memenv.cc b/src/leveldb/helpers/memenv/memenv.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/helpers/memenv/memenv.h b/src/leveldb/helpers/memenv/memenv.h old mode 100644 new mode 100755 diff --git a/src/leveldb/helpers/memenv/memenv_test.cc b/src/leveldb/helpers/memenv/memenv_test.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/include/leveldb/c.h b/src/leveldb/include/leveldb/c.h old mode 100644 new mode 100755 diff --git a/src/leveldb/include/leveldb/cache.h b/src/leveldb/include/leveldb/cache.h old mode 100644 new mode 100755 diff --git a/src/leveldb/include/leveldb/comparator.h b/src/leveldb/include/leveldb/comparator.h old mode 100644 new mode 100755 diff --git a/src/leveldb/include/leveldb/db.h b/src/leveldb/include/leveldb/db.h old mode 100644 new mode 100755 diff --git a/src/leveldb/include/leveldb/dumpfile.h b/src/leveldb/include/leveldb/dumpfile.h old mode 100644 new mode 100755 diff --git a/src/leveldb/include/leveldb/env.h b/src/leveldb/include/leveldb/env.h old mode 100644 new mode 100755 diff --git a/src/leveldb/include/leveldb/filter_policy.h b/src/leveldb/include/leveldb/filter_policy.h old mode 100644 new mode 100755 diff --git a/src/leveldb/include/leveldb/iterator.h b/src/leveldb/include/leveldb/iterator.h old mode 100644 new mode 100755 diff --git a/src/leveldb/include/leveldb/options.h b/src/leveldb/include/leveldb/options.h old mode 100644 new mode 100755 diff --git a/src/leveldb/include/leveldb/slice.h b/src/leveldb/include/leveldb/slice.h old mode 100644 new mode 100755 diff --git a/src/leveldb/include/leveldb/status.h b/src/leveldb/include/leveldb/status.h old mode 100644 new mode 100755 diff --git a/src/leveldb/include/leveldb/table.h b/src/leveldb/include/leveldb/table.h old mode 100644 new mode 100755 diff --git a/src/leveldb/include/leveldb/table_builder.h b/src/leveldb/include/leveldb/table_builder.h old mode 100644 new mode 100755 diff --git a/src/leveldb/include/leveldb/write_batch.h b/src/leveldb/include/leveldb/write_batch.h old mode 100644 new mode 100755 diff --git a/src/leveldb/issues/issue178_test.cc b/src/leveldb/issues/issue178_test.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/issues/issue200_test.cc b/src/leveldb/issues/issue200_test.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/port/README b/src/leveldb/port/README old mode 100644 new mode 100755 diff --git a/src/leveldb/port/atomic_pointer.h b/src/leveldb/port/atomic_pointer.h old mode 100644 new mode 100755 diff --git a/src/leveldb/port/port.h b/src/leveldb/port/port.h old mode 100644 new mode 100755 diff --git a/src/leveldb/port/port_example.h b/src/leveldb/port/port_example.h old mode 100644 new mode 100755 diff --git a/src/leveldb/port/port_posix.cc b/src/leveldb/port/port_posix.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/port/port_posix.h b/src/leveldb/port/port_posix.h old mode 100644 new mode 100755 diff --git a/src/leveldb/port/port_win.cc b/src/leveldb/port/port_win.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/port/port_win.h b/src/leveldb/port/port_win.h old mode 100644 new mode 100755 diff --git a/src/leveldb/port/thread_annotations.h b/src/leveldb/port/thread_annotations.h old mode 100644 new mode 100755 diff --git a/src/leveldb/port/win/stdint.h b/src/leveldb/port/win/stdint.h old mode 100644 new mode 100755 diff --git a/src/leveldb/table/block.cc b/src/leveldb/table/block.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/table/block.h b/src/leveldb/table/block.h old mode 100644 new mode 100755 diff --git a/src/leveldb/table/block_builder.cc b/src/leveldb/table/block_builder.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/table/block_builder.h b/src/leveldb/table/block_builder.h old mode 100644 new mode 100755 diff --git a/src/leveldb/table/filter_block.cc b/src/leveldb/table/filter_block.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/table/filter_block.h b/src/leveldb/table/filter_block.h old mode 100644 new mode 100755 diff --git a/src/leveldb/table/filter_block_test.cc b/src/leveldb/table/filter_block_test.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/table/format.cc b/src/leveldb/table/format.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/table/format.h b/src/leveldb/table/format.h old mode 100644 new mode 100755 diff --git a/src/leveldb/table/iterator.cc b/src/leveldb/table/iterator.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/table/iterator_wrapper.h b/src/leveldb/table/iterator_wrapper.h old mode 100644 new mode 100755 diff --git a/src/leveldb/table/merger.cc b/src/leveldb/table/merger.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/table/merger.h b/src/leveldb/table/merger.h old mode 100644 new mode 100755 diff --git a/src/leveldb/table/table.cc b/src/leveldb/table/table.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/table/table_builder.cc b/src/leveldb/table/table_builder.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/table/table_test.cc b/src/leveldb/table/table_test.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/table/two_level_iterator.cc b/src/leveldb/table/two_level_iterator.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/table/two_level_iterator.h b/src/leveldb/table/two_level_iterator.h old mode 100644 new mode 100755 diff --git a/src/leveldb/util/arena.cc b/src/leveldb/util/arena.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/util/arena.h b/src/leveldb/util/arena.h old mode 100644 new mode 100755 diff --git a/src/leveldb/util/arena_test.cc b/src/leveldb/util/arena_test.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/util/bloom.cc b/src/leveldb/util/bloom.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/util/bloom_test.cc b/src/leveldb/util/bloom_test.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/util/cache.cc b/src/leveldb/util/cache.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/util/cache_test.cc b/src/leveldb/util/cache_test.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/util/coding.cc b/src/leveldb/util/coding.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/util/coding.h b/src/leveldb/util/coding.h old mode 100644 new mode 100755 diff --git a/src/leveldb/util/coding_test.cc b/src/leveldb/util/coding_test.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/util/comparator.cc b/src/leveldb/util/comparator.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/util/crc32c.cc b/src/leveldb/util/crc32c.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/util/crc32c.h b/src/leveldb/util/crc32c.h old mode 100644 new mode 100755 diff --git a/src/leveldb/util/crc32c_test.cc b/src/leveldb/util/crc32c_test.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/util/env.cc b/src/leveldb/util/env.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/util/env_posix.cc b/src/leveldb/util/env_posix.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/util/env_test.cc b/src/leveldb/util/env_test.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/util/env_win.cc b/src/leveldb/util/env_win.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/util/filter_policy.cc b/src/leveldb/util/filter_policy.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/util/hash.cc b/src/leveldb/util/hash.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/util/hash.h b/src/leveldb/util/hash.h old mode 100644 new mode 100755 diff --git a/src/leveldb/util/hash_test.cc b/src/leveldb/util/hash_test.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/util/histogram.cc b/src/leveldb/util/histogram.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/util/histogram.h b/src/leveldb/util/histogram.h old mode 100644 new mode 100755 diff --git a/src/leveldb/util/logging.cc b/src/leveldb/util/logging.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/util/logging.h b/src/leveldb/util/logging.h old mode 100644 new mode 100755 diff --git a/src/leveldb/util/mutexlock.h b/src/leveldb/util/mutexlock.h old mode 100644 new mode 100755 diff --git a/src/leveldb/util/options.cc b/src/leveldb/util/options.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/util/posix_logger.h b/src/leveldb/util/posix_logger.h old mode 100644 new mode 100755 diff --git a/src/leveldb/util/random.h b/src/leveldb/util/random.h old mode 100644 new mode 100755 diff --git a/src/leveldb/util/status.cc b/src/leveldb/util/status.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/util/testharness.cc b/src/leveldb/util/testharness.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/util/testharness.h b/src/leveldb/util/testharness.h old mode 100644 new mode 100755 diff --git a/src/leveldb/util/testutil.cc b/src/leveldb/util/testutil.cc old mode 100644 new mode 100755 diff --git a/src/leveldb/util/testutil.h b/src/leveldb/util/testutil.h old mode 100644 new mode 100755 diff --git a/src/leveldbwrapper.cpp b/src/leveldbwrapper.cpp old mode 100644 new mode 100755 index b5d024abb85..c5d95823a9e --- a/src/leveldbwrapper.cpp +++ b/src/leveldbwrapper.cpp @@ -27,14 +27,14 @@ void HandleError(const leveldb::Status& status) throw leveldb_error("Unknown database error"); } -static leveldb::Options GetOptions(size_t nCacheSize) +static leveldb::Options GetOptions(size_t nCacheSize, bool compression, int maxOpenFiles) { leveldb::Options options; options.block_cache = leveldb::NewLRUCache(nCacheSize / 2); options.write_buffer_size = nCacheSize / 4; // up to two write buffers may be held in memory simultaneously options.filter_policy = leveldb::NewBloomFilterPolicy(10); - options.compression = leveldb::kNoCompression; - options.max_open_files = 64; + options.compression = compression ? leveldb::kSnappyCompression : leveldb::kNoCompression; + options.max_open_files = maxOpenFiles; if (leveldb::kMajorVersion > 1 || (leveldb::kMajorVersion == 1 && leveldb::kMinorVersion >= 16)) { // LevelDB versions before 1.16 consider short writes to be corruption. Only trigger error // on corruption in later versions. @@ -43,14 +43,14 @@ static leveldb::Options GetOptions(size_t nCacheSize) return options; } -CLevelDBWrapper::CLevelDBWrapper(const boost::filesystem::path& path, size_t nCacheSize, bool fMemory, bool fWipe) +CLevelDBWrapper::CLevelDBWrapper(const boost::filesystem::path& path, size_t nCacheSize, bool fMemory, bool fWipe, bool compression, int maxOpenFiles) { penv = NULL; readoptions.verify_checksums = true; iteroptions.verify_checksums = true; iteroptions.fill_cache = false; syncoptions.sync = true; - options = GetOptions(nCacheSize); + options = GetOptions(nCacheSize, compression, maxOpenFiles); options.create_if_missing = true; if (fMemory) { penv = leveldb::NewMemEnv(leveldb::Env::Default()); @@ -86,4 +86,4 @@ bool CLevelDBWrapper::WriteBatch(CLevelDBBatch& batch, bool fSync) leveldb::Status status = pdb->Write(fSync ? syncoptions : writeoptions, &batch.batch); HandleError(status); return true; -} +} \ No newline at end of file diff --git a/src/leveldbwrapper.h b/src/leveldbwrapper.h old mode 100644 new mode 100755 index 639f736a55b..4bf2568901c --- a/src/leveldbwrapper.h +++ b/src/leveldbwrapper.h @@ -86,7 +86,7 @@ class CLevelDBWrapper leveldb::DB* pdb; public: - 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, bool compression = false, int maxOpenFiles = 64); ~CLevelDBWrapper(); template @@ -170,4 +170,4 @@ class CLevelDBWrapper } }; -#endif // BITCOIN_LEVELDBWRAPPER_H +#endif // BITCOIN_LEVELDBWRAPPER_H \ No newline at end of file diff --git a/src/limitedmap.h b/src/limitedmap.h old mode 100644 new mode 100755 diff --git a/src/main.cpp b/src/main.cpp old mode 100644 new mode 100755 index a8a5918b454..a96fdf315f6 --- a/src/main.cpp +++ b/src/main.cpp @@ -62,6 +62,9 @@ bool fExperimentalMode = false; bool fImporting = false; bool fReindex = false; bool fTxIndex = false; +bool fAddressIndex = false; +bool fTimestampIndex = false; +bool fSpentIndex = false; bool fHavePruned = false; bool fPruneMode = false; bool fIsBareMultisigStd = true; @@ -1256,6 +1259,16 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa // Store transaction in memory pool.addUnchecked(hash, entry, !IsInitialBlockDownload()); + + // Add memory address index + if (fAddressIndex) { + pool.addAddressIndex(entry, view); + } + + // Add memory spent index + if (fSpentIndex) { + pool.addSpentIndex(entry, view); + } } SyncWithWallets(tx, NULL); @@ -1263,6 +1276,55 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa return true; } +bool GetTimestampIndex(const unsigned int &high, const unsigned int &low, const bool fActiveOnly, std::vector > &hashes) +{ + if (!fTimestampIndex) + return error("Timestamp index not enabled"); + + if (!pblocktree->ReadTimestampIndex(high, low, fActiveOnly, hashes)) + return error("Unable to get hashes for timestamps"); + + return true; +} + +bool GetSpentIndex(CSpentIndexKey &key, CSpentIndexValue &value) +{ + if (!fSpentIndex) + return false; + + if (mempool.getSpentIndex(key, value)) + return true; + + if (!pblocktree->ReadSpentIndex(key, value)) + return false; + + return true; +} + +bool GetAddressIndex(uint160 addressHash, int type, + std::vector > &addressIndex, int start, int end) +{ + if (!fAddressIndex) + return error("address index not enabled"); + + if (!pblocktree->ReadAddressIndex(addressHash, type, addressIndex, start, end)) + return error("unable to get txids for address"); + + return true; +} + +bool GetAddressUnspent(uint160 addressHash, int type, + std::vector > &unspentOutputs) +{ + if (!fAddressIndex) + return error("address index not enabled"); + + if (!pblocktree->ReadAddressUnspentIndex(addressHash, type, unspentOutputs)) + return error("unable to get txids for address"); + + return true; +} + /** Return transaction in tx, and if it was found inside a block, its hash is placed in hashBlock */ bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock, bool fAllowSlow) { @@ -1883,11 +1945,46 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex if (blockUndo.vtxundo.size() + 1 != block.vtx.size()) return error("DisconnectBlock(): block and undo data inconsistent"); + std::vector > addressIndex; + std::vector > addressUnspentIndex; + std::vector > spentIndex; + // undo transactions in reverse order for (int i = block.vtx.size() - 1; i >= 0; i--) { const CTransaction &tx = block.vtx[i]; uint256 hash = tx.GetHash(); + if (fAddressIndex) { + + for (unsigned int k = tx.vout.size(); k-- > 0;) { + const CTxOut &out = tx.vout[k]; + + if (out.scriptPubKey.IsPayToScriptHash()) { + vector hashBytes(out.scriptPubKey.begin()+2, out.scriptPubKey.begin()+22); + + // undo receiving activity + addressIndex.push_back(make_pair(CAddressIndexKey(2, uint160(hashBytes), pindex->nHeight, i, hash, k, false), out.nValue)); + + // undo unspent index + addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(2, uint160(hashBytes), hash, k), CAddressUnspentValue())); + + } else if (out.scriptPubKey.IsPayToPublicKeyHash()) { + vector hashBytes(out.scriptPubKey.begin()+3, out.scriptPubKey.begin()+23); + + // undo receiving activity + addressIndex.push_back(make_pair(CAddressIndexKey(1, uint160(hashBytes), pindex->nHeight, i, hash, k, false), out.nValue)); + + // undo unspent index + addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(1, uint160(hashBytes), hash, k), CAddressUnspentValue())); + + } else { + continue; + } + + } + + } + // Check that all outputs are available and match the outputs in the block itself // exactly. { @@ -1924,6 +2021,39 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex const CTxInUndo &undo = txundo.vprevout[j]; if (!ApplyTxInUndo(undo, view, out)) fClean = false; + + const CTxIn input = tx.vin[j]; + + if (fSpentIndex) { + // undo and delete the spent index + spentIndex.push_back(make_pair(CSpentIndexKey(input.prevout.hash, input.prevout.n), CSpentIndexValue())); + } + + if (fAddressIndex) { + const CTxOut &prevout = view.GetOutputFor(tx.vin[j]); + if (prevout.scriptPubKey.IsPayToScriptHash()) { + vector hashBytes(prevout.scriptPubKey.begin()+2, prevout.scriptPubKey.begin()+22); + + // undo spending activity + addressIndex.push_back(make_pair(CAddressIndexKey(2, uint160(hashBytes), pindex->nHeight, i, hash, j, true), prevout.nValue * -1)); + + // restore unspent index + addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(2, uint160(hashBytes), input.prevout.hash, input.prevout.n), CAddressUnspentValue(prevout.nValue, prevout.scriptPubKey, undo.nHeight))); + + + } else if (prevout.scriptPubKey.IsPayToPublicKeyHash()) { + vector hashBytes(prevout.scriptPubKey.begin()+3, prevout.scriptPubKey.begin()+23); + + // undo spending activity + addressIndex.push_back(make_pair(CAddressIndexKey(1, uint160(hashBytes), pindex->nHeight, i, hash, j, true), prevout.nValue * -1)); + + // restore unspent index + addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(1, uint160(hashBytes), input.prevout.hash, input.prevout.n), CAddressUnspentValue(prevout.nValue, prevout.scriptPubKey, undo.nHeight))); + + } else { + continue; + } + } } } } @@ -1939,6 +2069,14 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex return true; } + if (fAddressIndex) { + if (!pblocktree->EraseAddressIndex(addressIndex)) { + return AbortNode(state, "Failed to delete address index"); + } + if (!pblocktree->UpdateAddressUnspentIndex(addressUnspentIndex)) { + return AbortNode(state, "Failed to write address unspent index"); + } + } return fClean; } @@ -2107,6 +2245,10 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin vPos.reserve(block.vtx.size()); blockundo.vtxundo.reserve(block.vtx.size() - 1); + std::vector > addressIndex; + std::vector > addressUnspentIndex; + std::vector > spentIndex; + // Construct the incremental merkle tree at the current // block position, auto old_tree_root = view.GetBestAnchor(); @@ -2129,6 +2271,8 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin { const CTransaction &tx = block.vtx[i]; + const uint256 txhash = tx.GetHash(); + nInputs += tx.vin.size(); nSigOps += GetLegacySigOpCount(tx); if (nSigOps > MAX_BLOCK_SIGOPS) @@ -2146,6 +2290,43 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin return state.DoS(100, error("ConnectBlock(): JoinSplit requirements not met"), REJECT_INVALID, "bad-txns-joinsplit-requirements-not-met"); + if (fAddressIndex || fSpentIndex) + { + for (size_t j = 0; j < tx.vin.size(); j++) { + + const CTxIn input = tx.vin[j]; + const CTxOut &prevout = view.GetOutputFor(tx.vin[j]); + uint160 hashBytes; + int addressType; + + if (prevout.scriptPubKey.IsPayToScriptHash()) { + hashBytes = uint160(vector (prevout.scriptPubKey.begin()+2, prevout.scriptPubKey.begin()+22)); + addressType = 2; + } else if (prevout.scriptPubKey.IsPayToPublicKeyHash()) { + hashBytes = uint160(vector (prevout.scriptPubKey.begin()+3, prevout.scriptPubKey.begin()+23)); + addressType = 1; + } else { + hashBytes.SetNull(); + addressType = 0; + } + + if (fAddressIndex && addressType > 0) { + // record spending activity + addressIndex.push_back(make_pair(CAddressIndexKey(addressType, hashBytes, pindex->nHeight, i, txhash, j, true), prevout.nValue * -1)); + + // remove address from unspent index + addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(addressType, hashBytes, input.prevout.hash, input.prevout.n), CAddressUnspentValue())); + } + + if (fSpentIndex) { + // add the spent index to determine the txid and input that spent an output + // and to find the amount and address from an input + spentIndex.push_back(make_pair(CSpentIndexKey(input.prevout.hash, input.prevout.n), CSpentIndexValue(txhash, j, pindex->nHeight, prevout.nValue, addressType, hashBytes))); + } + } + + } + // Add in sigops done by pay-to-script-hash inputs; // this is to prevent a "rogue miner" from creating // an incredibly-expensive-to-validate block. @@ -2162,6 +2343,35 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin control.Add(vChecks); } + if (fAddressIndex) { + for (unsigned int k = 0; k < tx.vout.size(); k++) { + const CTxOut &out = tx.vout[k]; + + if (out.scriptPubKey.IsPayToScriptHash()) { + vector hashBytes(out.scriptPubKey.begin()+2, out.scriptPubKey.begin()+22); + + // record receiving activity + addressIndex.push_back(make_pair(CAddressIndexKey(2, uint160(hashBytes), pindex->nHeight, i, txhash, k, false), out.nValue)); + + // record unspent output + addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(2, uint160(hashBytes), txhash, k), CAddressUnspentValue(out.nValue, out.scriptPubKey, pindex->nHeight))); + + } else if (out.scriptPubKey.IsPayToPublicKeyHash()) { + vector hashBytes(out.scriptPubKey.begin()+3, out.scriptPubKey.begin()+23); + + // record receiving activity + addressIndex.push_back(make_pair(CAddressIndexKey(1, uint160(hashBytes), pindex->nHeight, i, txhash, k, false), out.nValue)); + + // record unspent output + addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(1, uint160(hashBytes), txhash, k), CAddressUnspentValue(out.nValue, out.scriptPubKey, pindex->nHeight))); + + } else { + continue; + } + + } + } + CTxUndo undoDummy; if (i > 0) { blockundo.vtxundo.push_back(CTxUndo()); @@ -2227,6 +2437,41 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin if (!pblocktree->WriteTxIndex(vPos)) return AbortNode(state, "Failed to write transaction index"); + if (fAddressIndex) { + if (!pblocktree->WriteAddressIndex(addressIndex)) { + return AbortNode(state, "Failed to write address index"); + } + + if (!pblocktree->UpdateAddressUnspentIndex(addressUnspentIndex)) { + return AbortNode(state, "Failed to write address unspent index"); + } + } + + if (fSpentIndex) + if (!pblocktree->UpdateSpentIndex(spentIndex)) + return AbortNode(state, "Failed to write transaction index"); + + if (fTimestampIndex) { + unsigned int logicalTS = pindex->nTime; + unsigned int prevLogicalTS = 0; + + // retrieve logical timestamp of the previous block + if (pindex->pprev) + if (!pblocktree->ReadTimestampBlockIndex(pindex->pprev->GetBlockHash(), prevLogicalTS)) + LogPrintf("%s: Failed to read previous block's logical timestamp\n", __func__); + + if (logicalTS <= prevLogicalTS) { + logicalTS = prevLogicalTS + 1; + LogPrintf("%s: Previous logical timestamp is newer Actual[%d] prevLogical[%d] Logical[%d]\n", __func__, pindex->nTime, prevLogicalTS, logicalTS); + } + + if (!pblocktree->WriteTimestampIndex(CTimestampIndexKey(logicalTS, pindex->GetBlockHash()))) + return AbortNode(state, "Failed to write timestamp index"); + + if (!pblocktree->WriteTimestampBlockIndex(CTimestampBlockIndexKey(pindex->GetBlockHash()), CTimestampBlockIndexValue(logicalTS))) + return AbortNode(state, "Failed to write blockhash index"); + } + // add this block to the view's block chain view.SetBestBlock(pindex->GetBlockHash()); @@ -3574,6 +3819,18 @@ bool static LoadBlockIndexDB() pblocktree->ReadFlag("txindex", fTxIndex); LogPrintf("%s: transaction index %s\n", __func__, fTxIndex ? "enabled" : "disabled"); + // Check whether we have an address index + pblocktree->ReadFlag("addressindex", fAddressIndex); + LogPrintf("%s: address index %s\n", __func__, fAddressIndex ? "enabled" : "disabled"); + + // Check whether we have a timestamp index + pblocktree->ReadFlag("timestampindex", fTimestampIndex); + LogPrintf("%s: timestamp index %s\n", __func__, fTimestampIndex ? "enabled" : "disabled"); + + // Check whether we have a spent index + pblocktree->ReadFlag("spentindex", fSpentIndex); + LogPrintf("%s: spent index %s\n", __func__, fSpentIndex ? "enabled" : "disabled"); + // Fill in-memory data BOOST_FOREACH(const PAIRTYPE(uint256, CBlockIndex*)& item, mapBlockIndex) { @@ -3752,6 +4009,18 @@ bool InitBlockIndex() { // Use the provided setting for -txindex in the new database fTxIndex = GetBoolArg("-txindex", false); pblocktree->WriteFlag("txindex", fTxIndex); + + // Use the provided setting for -addressindex in the new database + fAddressIndex = GetBoolArg("-addressindex", DEFAULT_ADDRESSINDEX); + pblocktree->WriteFlag("addressindex", fAddressIndex); + + // Use the provided setting for -timestampindex in the new database + fTimestampIndex = GetBoolArg("-timestampindex", DEFAULT_TIMESTAMPINDEX); + pblocktree->WriteFlag("timestampindex", fTimestampIndex); + + fSpentIndex = GetBoolArg("-spentindex", DEFAULT_SPENTINDEX); + pblocktree->WriteFlag("spentindex", fSpentIndex); + LogPrintf("Initializing databases...\n"); // Only add the genesis block if not reindexing (in which case we reuse the one already on disk) diff --git a/src/main.h b/src/main.h old mode 100644 new mode 100755 index 886542db7e6..9b27a681035 --- a/src/main.h +++ b/src/main.h @@ -21,6 +21,8 @@ #include "script/script.h" #include "script/sigcache.h" #include "script/standard.h" + +#include "spentindex.h" #include "sync.h" #include "tinyformat.h" #include "txmempool.h" @@ -93,6 +95,12 @@ static const unsigned int DATABASE_FLUSH_INTERVAL = 24 * 60 * 60; /** Maximum length of reject messages. */ static const unsigned int MAX_REJECT_MESSAGE_LENGTH = 111; +static const bool DEFAULT_ADDRESSINDEX = false; +static const bool DEFAULT_TIMESTAMPINDEX = false; +static const bool DEFAULT_SPENTINDEX = false; +static const unsigned int DEFAULT_DB_MAX_OPEN_FILES = 1000; +static const bool DEFAULT_DB_COMPRESSION = true; + // Sanity check the magic numbers when we change them BOOST_STATIC_ASSERT(DEFAULT_BLOCK_MAX_SIZE <= MAX_BLOCK_SIZE); BOOST_STATIC_ASSERT(DEFAULT_BLOCK_PRIORITY_SIZE <= DEFAULT_BLOCK_MAX_SIZE); @@ -259,6 +267,338 @@ struct CNodeStateStats { std::vector vHeightInFlight; }; +struct CTimestampIndexIteratorKey { + unsigned int timestamp; + + size_t GetSerializeSize(int nType, int nVersion) const { + return 4; + } + template + void Serialize(Stream& s, int nType, int nVersion) const { + ser_writedata32be(s, timestamp); + } + template + void Unserialize(Stream& s, int nType, int nVersion) { + timestamp = ser_readdata32be(s); + } + + CTimestampIndexIteratorKey(unsigned int time) { + timestamp = time; + } + + CTimestampIndexIteratorKey() { + SetNull(); + } + + void SetNull() { + timestamp = 0; + } +}; + +struct CTimestampIndexKey { + unsigned int timestamp; + uint256 blockHash; + + size_t GetSerializeSize(int nType, int nVersion) const { + return 36; + } + template + void Serialize(Stream& s, int nType, int nVersion) const { + ser_writedata32be(s, timestamp); + blockHash.Serialize(s, nType, nVersion); + } + template + void Unserialize(Stream& s, int nType, int nVersion) { + timestamp = ser_readdata32be(s); + blockHash.Unserialize(s, nType, nVersion); + } + + CTimestampIndexKey(unsigned int time, uint256 hash) { + timestamp = time; + blockHash = hash; + } + + CTimestampIndexKey() { + SetNull(); + } + + void SetNull() { + timestamp = 0; + blockHash.SetNull(); + } +}; + +struct CTimestampBlockIndexKey { + uint256 blockHash; + + size_t GetSerializeSize(int nType, int nVersion) const { + return 32; + } + + template + void Serialize(Stream& s, int nType, int nVersion) const { + blockHash.Serialize(s, nType, nVersion); + } + + template + void Unserialize(Stream& s, int nType, int nVersion) { + blockHash.Unserialize(s, nType, nVersion); + } + + CTimestampBlockIndexKey(uint256 hash) { + blockHash = hash; + } + + CTimestampBlockIndexKey() { + SetNull(); + } + + void SetNull() { + blockHash.SetNull(); + } +}; + +struct CTimestampBlockIndexValue { + unsigned int ltimestamp; + size_t GetSerializeSize(int nType, int nVersion) const { + return 4; + } + + template + void Serialize(Stream& s, int nType, int nVersion) const { + ser_writedata32be(s, ltimestamp); + } + + template + void Unserialize(Stream& s, int nType, int nVersion) { + ltimestamp = ser_readdata32be(s); + } + + CTimestampBlockIndexValue (unsigned int time) { + ltimestamp = time; + } + + CTimestampBlockIndexValue() { + SetNull(); + } + + void SetNull() { + ltimestamp = 0; + } +}; + +struct CAddressUnspentKey { + unsigned int type; + uint160 hashBytes; + uint256 txhash; + size_t index; + + size_t GetSerializeSize(int nType, int nVersion) const { + return 57; + } + template + void Serialize(Stream& s, int nType, int nVersion) const { + ser_writedata8(s, type); + hashBytes.Serialize(s, nType, nVersion); + txhash.Serialize(s, nType, nVersion); + ser_writedata32(s, index); + } + template + void Unserialize(Stream& s, int nType, int nVersion) { + type = ser_readdata8(s); + hashBytes.Unserialize(s, nType, nVersion); + txhash.Unserialize(s, nType, nVersion); + index = ser_readdata32(s); + } + + CAddressUnspentKey(unsigned int addressType, uint160 addressHash, uint256 txid, size_t indexValue) { + type = addressType; + hashBytes = addressHash; + txhash = txid; + index = indexValue; + } + + CAddressUnspentKey() { + SetNull(); + } + + void SetNull() { + type = 0; + hashBytes.SetNull(); + txhash.SetNull(); + index = 0; + } +}; + +struct CAddressUnspentValue { + CAmount satoshis; + CScript script; + int blockHeight; + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { + READWRITE(satoshis); + READWRITE(script); + READWRITE(blockHeight); + } + + CAddressUnspentValue(CAmount sats, CScript scriptPubKey, int height) { + satoshis = sats; + script = scriptPubKey; + blockHeight = height; + } + + CAddressUnspentValue() { + SetNull(); + } + + void SetNull() { + satoshis = -1; + script.clear(); + blockHeight = 0; + } + + bool IsNull() const { + return (satoshis == -1); + } +}; + +struct CAddressIndexKey { + unsigned int type; + uint160 hashBytes; + int blockHeight; + unsigned int txindex; + uint256 txhash; + size_t index; + bool spending; + + size_t GetSerializeSize(int nType, int nVersion) const { + return 66; + } + template + void Serialize(Stream& s, int nType, int nVersion) const { + ser_writedata8(s, type); + hashBytes.Serialize(s, nType, nVersion); + // Heights are stored big-endian for key sorting in LevelDB + ser_writedata32be(s, blockHeight); + ser_writedata32be(s, txindex); + txhash.Serialize(s, nType, nVersion); + ser_writedata32(s, index); + char f = spending; + ser_writedata8(s, f); + } + template + void Unserialize(Stream& s, int nType, int nVersion) { + type = ser_readdata8(s); + hashBytes.Unserialize(s, nType, nVersion); + blockHeight = ser_readdata32be(s); + txindex = ser_readdata32be(s); + txhash.Unserialize(s, nType, nVersion); + index = ser_readdata32(s); + char f = ser_readdata8(s); + spending = f; + } + + CAddressIndexKey(unsigned int addressType, uint160 addressHash, int height, int blockindex, + uint256 txid, size_t indexValue, bool isSpending) { + type = addressType; + hashBytes = addressHash; + blockHeight = height; + txindex = blockindex; + txhash = txid; + index = indexValue; + spending = isSpending; + } + + CAddressIndexKey() { + SetNull(); + } + + void SetNull() { + type = 0; + hashBytes.SetNull(); + blockHeight = 0; + txindex = 0; + txhash.SetNull(); + index = 0; + spending = false; + } + +}; + +struct CAddressIndexIteratorKey { + unsigned int type; + uint160 hashBytes; + + size_t GetSerializeSize(int nType, int nVersion) const { + return 21; + } + template + void Serialize(Stream& s, int nType, int nVersion) const { + ser_writedata8(s, type); + hashBytes.Serialize(s, nType, nVersion); + } + template + void Unserialize(Stream& s, int nType, int nVersion) { + type = ser_readdata8(s); + hashBytes.Unserialize(s, nType, nVersion); + } + + CAddressIndexIteratorKey(unsigned int addressType, uint160 addressHash) { + type = addressType; + hashBytes = addressHash; + } + + CAddressIndexIteratorKey() { + SetNull(); + } + + void SetNull() { + type = 0; + hashBytes.SetNull(); + } +}; + +struct CAddressIndexIteratorHeightKey { + unsigned int type; + uint160 hashBytes; + int blockHeight; + + size_t GetSerializeSize(int nType, int nVersion) const { + return 25; + } + template + void Serialize(Stream& s, int nType, int nVersion) const { + ser_writedata8(s, type); + hashBytes.Serialize(s, nType, nVersion); + ser_writedata32be(s, blockHeight); + } + template + void Unserialize(Stream& s, int nType, int nVersion) { + type = ser_readdata8(s); + hashBytes.Unserialize(s, nType, nVersion); + blockHeight = ser_readdata32be(s); + } + + CAddressIndexIteratorHeightKey(unsigned int addressType, uint160 addressHash, int height) { + type = addressType; + hashBytes = addressHash; + blockHeight = height; + } + + CAddressIndexIteratorHeightKey() { + SetNull(); + } + + void SetNull() { + type = 0; + hashBytes.SetNull(); + blockHeight = 0; + } +}; + struct CDiskTxPos : public CDiskBlockPos { unsigned int nTxOffset; // after header @@ -394,6 +734,14 @@ class CScriptCheck }; +bool GetTimestampIndex(const unsigned int &high, const unsigned int &low, const bool fActiveOnly, std::vector > &hashes); +bool GetSpentIndex(CSpentIndexKey &key, CSpentIndexValue &value); +bool GetAddressIndex(uint160 addressHash, int type, + std::vector > &addressIndex, + int start = 0, int end = 0); +bool GetAddressUnspent(uint160 addressHash, int type, + std::vector > &unspentOutputs); + /** Functions for disk access for blocks */ bool WriteBlockToDisk(CBlock& block, CDiskBlockPos& pos, const CMessageHeader::MessageStartChars& messageStart); bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos); diff --git a/src/memusage.h b/src/memusage.h old mode 100644 new mode 100755 diff --git a/src/merkleblock.cpp b/src/merkleblock.cpp old mode 100644 new mode 100755 diff --git a/src/merkleblock.h b/src/merkleblock.h old mode 100644 new mode 100755 diff --git a/src/metrics.cpp b/src/metrics.cpp old mode 100644 new mode 100755 diff --git a/src/metrics.h b/src/metrics.h old mode 100644 new mode 100755 diff --git a/src/miner.cpp b/src/miner.cpp old mode 100644 new mode 100755 diff --git a/src/miner.h b/src/miner.h old mode 100644 new mode 100755 diff --git a/src/mruset.h b/src/mruset.h old mode 100644 new mode 100755 diff --git a/src/net.cpp b/src/net.cpp old mode 100644 new mode 100755 diff --git a/src/net.h b/src/net.h old mode 100644 new mode 100755 diff --git a/src/netbase.cpp b/src/netbase.cpp old mode 100644 new mode 100755 diff --git a/src/netbase.h b/src/netbase.h old mode 100644 new mode 100755 diff --git a/src/noui.cpp b/src/noui.cpp old mode 100644 new mode 100755 diff --git a/src/noui.h b/src/noui.h old mode 100644 new mode 100755 diff --git a/src/obj-test/.gitignore b/src/obj-test/.gitignore old mode 100644 new mode 100755 diff --git a/src/obj/.gitignore b/src/obj/.gitignore old mode 100644 new mode 100755 diff --git a/src/policy/fees.cpp b/src/policy/fees.cpp old mode 100644 new mode 100755 diff --git a/src/policy/fees.h b/src/policy/fees.h old mode 100644 new mode 100755 diff --git a/src/pow.cpp b/src/pow.cpp old mode 100644 new mode 100755 diff --git a/src/pow.h b/src/pow.h old mode 100644 new mode 100755 diff --git a/src/pow/tromp/equi.h b/src/pow/tromp/equi.h old mode 100644 new mode 100755 diff --git a/src/pow/tromp/equi_miner.h b/src/pow/tromp/equi_miner.h old mode 100644 new mode 100755 diff --git a/src/pow/tromp/osx_barrier.h b/src/pow/tromp/osx_barrier.h old mode 100644 new mode 100755 diff --git a/src/primitives/block.cpp b/src/primitives/block.cpp old mode 100644 new mode 100755 diff --git a/src/primitives/block.h b/src/primitives/block.h old mode 100644 new mode 100755 diff --git a/src/primitives/transaction.cpp b/src/primitives/transaction.cpp old mode 100644 new mode 100755 diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h old mode 100644 new mode 100755 diff --git a/src/protocol.cpp b/src/protocol.cpp old mode 100644 new mode 100755 diff --git a/src/protocol.h b/src/protocol.h old mode 100644 new mode 100755 diff --git a/src/pubkey.cpp b/src/pubkey.cpp old mode 100644 new mode 100755 diff --git a/src/pubkey.h b/src/pubkey.h old mode 100644 new mode 100755 diff --git a/src/random.cpp b/src/random.cpp old mode 100644 new mode 100755 diff --git a/src/random.h b/src/random.h old mode 100644 new mode 100755 diff --git a/src/rest.cpp b/src/rest.cpp old mode 100644 new mode 100755 diff --git a/src/reverselock.h b/src/reverselock.h old mode 100644 new mode 100755 diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp old mode 100644 new mode 100755 index 939430be203..33650ace839 --- a/src/rpcblockchain.cpp +++ b/src/rpcblockchain.cpp @@ -3,11 +3,19 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include "amount.h" +#include "base58.h" +#include "chain.h" +#include "chainparams.h" #include "checkpoints.h" #include "consensus/validation.h" #include "main.h" #include "primitives/transaction.h" #include "rpcserver.h" +#include "script/script.h" +#include "script/script_error.h" +#include "script/sign.h" +#include "script/standard.h" #include "sync.h" #include "util.h" @@ -101,6 +109,112 @@ UniValue blockheaderToJSON(const CBlockIndex* blockindex) return result; } +UniValue blockToDeltasJSON(const CBlock& block, const CBlockIndex* blockindex) +{ + UniValue result(UniValue::VOBJ); + result.push_back(Pair("hash", block.GetHash().GetHex())); + int confirmations = -1; + // Only report confirmations if the block is on the main chain + if (chainActive.Contains(blockindex)) { + confirmations = chainActive.Height() - blockindex->nHeight + 1; + } else { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block is an orphan"); + } + result.push_back(Pair("confirmations", confirmations)); + result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION))); + result.push_back(Pair("height", blockindex->nHeight)); + result.push_back(Pair("version", block.nVersion)); + result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex())); + + UniValue deltas(UniValue::VARR); + + for (unsigned int i = 0; i < block.vtx.size(); i++) { + const CTransaction &tx = block.vtx[i]; + const uint256 txhash = tx.GetHash(); + + UniValue entry(UniValue::VOBJ); + entry.push_back(Pair("txid", txhash.GetHex())); + entry.push_back(Pair("index", (int)i)); + + UniValue inputs(UniValue::VARR); + + if (!tx.IsCoinBase()) { + + for (size_t j = 0; j < tx.vin.size(); j++) { + const CTxIn input = tx.vin[j]; + + UniValue delta(UniValue::VOBJ); + + CSpentIndexValue spentInfo; + CSpentIndexKey spentKey(input.prevout.hash, input.prevout.n); + + if (GetSpentIndex(spentKey, spentInfo)) { + if (spentInfo.addressType == 1) { + delta.push_back(Pair("address", CBitcoinAddress(CKeyID(spentInfo.addressHash)).ToString())); + } else if (spentInfo.addressType == 2) { + delta.push_back(Pair("address", CBitcoinAddress(CScriptID(spentInfo.addressHash)).ToString())); + } else { + continue; + } + delta.push_back(Pair("satoshis", -1 * spentInfo.satoshis)); + delta.push_back(Pair("index", (int)j)); + delta.push_back(Pair("prevtxid", input.prevout.hash.GetHex())); + delta.push_back(Pair("prevout", (int)input.prevout.n)); + + inputs.push_back(delta); + } else { + throw JSONRPCError(RPC_INTERNAL_ERROR, "Spent information not available"); + } + + } + } + + entry.push_back(Pair("inputs", inputs)); + + UniValue outputs(UniValue::VARR); + + for (unsigned int k = 0; k < tx.vout.size(); k++) { + const CTxOut &out = tx.vout[k]; + + UniValue delta(UniValue::VOBJ); + + if (out.scriptPubKey.IsPayToScriptHash()) { + vector hashBytes(out.scriptPubKey.begin()+2, out.scriptPubKey.begin()+22); + delta.push_back(Pair("address", CBitcoinAddress(CScriptID(uint160(hashBytes))).ToString())); + + } else if (out.scriptPubKey.IsPayToPublicKeyHash()) { + vector hashBytes(out.scriptPubKey.begin()+3, out.scriptPubKey.begin()+23); + delta.push_back(Pair("address", CBitcoinAddress(CKeyID(uint160(hashBytes))).ToString())); + } else { + continue; + } + + delta.push_back(Pair("satoshis", out.nValue)); + delta.push_back(Pair("index", (int)k)); + + outputs.push_back(delta); + } + + entry.push_back(Pair("outputs", outputs)); + deltas.push_back(entry); + + } + result.push_back(Pair("deltas", deltas)); + result.push_back(Pair("time", block.GetBlockTime())); + result.push_back(Pair("mediantime", (int64_t)blockindex->GetMedianTimePast())); + result.push_back(Pair("nonce", block.nNonce.GetHex())); + result.push_back(Pair("bits", strprintf("%08x", block.nBits))); + result.push_back(Pair("difficulty", GetDifficulty(blockindex))); + result.push_back(Pair("chainwork", blockindex->nChainWork.GetHex())); + + if (blockindex->pprev) + result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex())); + CBlockIndex *pnext = chainActive.Next(blockindex); + if (pnext) + result.push_back(Pair("nextblockhash", pnext->GetBlockHash().GetHex())); + return result; +} + UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false) { UniValue result(UniValue::VOBJ); @@ -284,6 +398,102 @@ UniValue getrawmempool(const UniValue& params, bool fHelp) return mempoolToJSON(fVerbose); } +UniValue getblockdeltas(const UniValue& params, bool fHelp) +{ + if (fHelp || params.size() != 1) + throw runtime_error(""); + + std::string strHash = params[0].get_str(); + uint256 hash(uint256S(strHash)); + + if (mapBlockIndex.count(hash) == 0) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); + + CBlock block; + CBlockIndex* pblockindex = mapBlockIndex[hash]; + + if (fHavePruned && !(pblockindex->nStatus & BLOCK_HAVE_DATA) && pblockindex->nTx > 0) + throw JSONRPCError(RPC_INTERNAL_ERROR, "Block not available (pruned data)"); + + if(!ReadBlockFromDisk(block, pblockindex)) + throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk"); + + return blockToDeltasJSON(block, pblockindex); +} + +UniValue getblockhashes(const UniValue& params, bool fHelp) +{ + if (fHelp || params.size() < 2) + throw runtime_error( + "getblockhashes timestamp\n" + "\nReturns array of hashes of blocks within the timestamp range provided.\n" + "\nArguments:\n" + "1. high (numeric, required) The newer block timestamp\n" + "2. low (numeric, required) The older block timestamp\n" + "3. options (string, required) A json object\n" + " {\n" + " \"noOrphans\":true (boolean) will only include blocks on the main chain\n" + " \"logicalTimes\":true (boolean) will include logical timestamps with hashes\n" + " }\n" + "\nResult:\n" + "[\n" + " \"hash\" (string) The block hash\n" + "]\n" + "[\n" + " {\n" + " \"blockhash\": (string) The block hash\n" + " \"logicalts\": (numeric) The logical timestamp\n" + " }\n" + "]\n" + "\nExamples:\n" + + HelpExampleCli("getblockhashes", "1231614698 1231024505") + + HelpExampleRpc("getblockhashes", "1231614698, 1231024505") + + HelpExampleCli("getblockhashes", "1231614698 1231024505 '{\"noOrphans\":false, \"logicalTimes\":true}'") + ); + + unsigned int high = params[0].get_int(); + unsigned int low = params[1].get_int(); + bool fActiveOnly = false; + bool fLogicalTS = false; + + if (params.size() > 2) { + if (params[2].isObject()) { + UniValue noOrphans = find_value(params[2].get_obj(), "noOrphans"); + UniValue returnLogical = find_value(params[2].get_obj(), "logicalTimes"); + + if (noOrphans.isBool()) + fActiveOnly = noOrphans.get_bool(); + + if (returnLogical.isBool()) + fLogicalTS = returnLogical.get_bool(); + } + } + + std::vector > blockHashes; + + if (fActiveOnly) + LOCK(cs_main); + + if (!GetTimestampIndex(high, low, fActiveOnly, blockHashes)) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available for block hashes"); + } + + UniValue result(UniValue::VARR); + + for (std::vector >::const_iterator it=blockHashes.begin(); it!=blockHashes.end(); it++) { + if (fLogicalTS) { + UniValue item(UniValue::VOBJ); + item.push_back(Pair("blockhash", it->first.GetHex())); + item.push_back(Pair("logicalts", (int)it->second)); + result.push_back(item); + } else { + result.push_back(it->first.GetHex()); + } + } + + return result; +} + UniValue getblockhash(const UniValue& params, bool fHelp) { if (fHelp || params.size() != 1) diff --git a/src/rpcclient.cpp b/src/rpcclient.cpp old mode 100644 new mode 100755 index 376b2b3d546..4906a895ef6 --- a/src/rpcclient.cpp +++ b/src/rpcclient.cpp @@ -96,6 +96,15 @@ static const CRPCConvertParam vRPCConvertParams[] = { "prioritisetransaction", 2 }, { "setban", 2 }, { "setban", 3 }, + { "getblockhashes", 0 }, + { "getblockhashes", 1 }, + { "getblockhashes", 2 }, + { "getspentinfo", 0}, + { "getaddresstxids", 0}, + { "getaddressbalance", 0}, + { "getaddressdeltas", 0}, + { "getaddressutxos", 0}, + { "getaddressmempool", 0}, { "zcrawjoinsplit", 1 }, { "zcrawjoinsplit", 2 }, { "zcrawjoinsplit", 3 }, diff --git a/src/rpcclient.h b/src/rpcclient.h old mode 100644 new mode 100755 diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp old mode 100644 new mode 100755 diff --git a/src/rpcmisc.cpp b/src/rpcmisc.cpp old mode 100644 new mode 100755 index c12e0ccfac2..cb304a5b182 --- a/src/rpcmisc.cpp +++ b/src/rpcmisc.cpp @@ -11,6 +11,7 @@ #include "netbase.h" #include "rpcserver.h" #include "timedata.h" +#include "txmempool.h" #include "util.h" #ifdef ENABLE_WALLET #include "wallet/wallet.h" @@ -459,3 +460,530 @@ UniValue setmocktime(const UniValue& params, bool fHelp) return NullUniValue; } + +bool getAddressFromIndex(const int &type, const uint160 &hash, std::string &address) +{ + if (type == 2) { + address = CBitcoinAddress(CScriptID(hash)).ToString(); + } else if (type == 1) { + address = CBitcoinAddress(CKeyID(hash)).ToString(); + } else { + return false; + } + return true; +} + +bool getAddressesFromParams(const UniValue& params, std::vector > &addresses) +{ + if (params[0].isStr()) { + CBitcoinAddress address(params[0].get_str()); + uint160 hashBytes; + int type = 0; + if (!address.GetIndexKey(hashBytes, type)) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address"); + } + addresses.push_back(std::make_pair(hashBytes, type)); + } else if (params[0].isObject()) { + + UniValue addressValues = find_value(params[0].get_obj(), "addresses"); + if (!addressValues.isArray()) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Addresses is expected to be an array"); + } + + std::vector values = addressValues.getValues(); + + for (std::vector::iterator it = values.begin(); it != values.end(); ++it) { + + CBitcoinAddress address(it->get_str()); + uint160 hashBytes; + int type = 0; + if (!address.GetIndexKey(hashBytes, type)) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address"); + } + addresses.push_back(std::make_pair(hashBytes, type)); + } + } else { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address"); + } + + return true; +} + +bool heightSort(std::pair a, + std::pair b) { + return a.second.blockHeight < b.second.blockHeight; +} + +bool timestampSort(std::pair a, + std::pair b) { + return a.second.time < b.second.time; +} + +UniValue getaddressmempool(const UniValue& params, bool fHelp) +{ + if (fHelp || params.size() != 1) + throw runtime_error( + "getaddressmempool\n" + "\nReturns all mempool deltas for an address (requires addressindex to be enabled).\n" + "\nArguments:\n" + "{\n" + " \"addresses\"\n" + " [\n" + " \"address\" (string) The base58check encoded address\n" + " ,...\n" + " ]\n" + "}\n" + "\nResult:\n" + "[\n" + " {\n" + " \"address\" (string) The base58check encoded address\n" + " \"txid\" (string) The related txid\n" + " \"index\" (number) The related input or output index\n" + " \"satoshis\" (number) The difference of satoshis\n" + " \"timestamp\" (number) The time the transaction entered the mempool (seconds)\n" + " \"prevtxid\" (string) The previous txid (if spending)\n" + " \"prevout\" (string) The previous transaction output index (if spending)\n" + " }\n" + "]\n" + "\nExamples:\n" + + HelpExampleCli("getaddressmempool", "'{\"addresses\": [\"12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX\"]}'") + + HelpExampleRpc("getaddressmempool", "{\"addresses\": [\"12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX\"]}") + ); + + std::vector > addresses; + + if (!getAddressesFromParams(params, addresses)) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address"); + } + + std::vector > indexes; + + if (!mempool.getAddressIndex(addresses, indexes)) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available for address"); + } + + std::sort(indexes.begin(), indexes.end(), timestampSort); + + UniValue result(UniValue::VARR); + + for (std::vector >::iterator it = indexes.begin(); + it != indexes.end(); it++) { + + std::string address; + if (!getAddressFromIndex(it->first.type, it->first.addressBytes, address)) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Unknown address type"); + } + + UniValue delta(UniValue::VOBJ); + delta.push_back(Pair("address", address)); + delta.push_back(Pair("txid", it->first.txhash.GetHex())); + delta.push_back(Pair("index", (int)it->first.index)); + delta.push_back(Pair("satoshis", it->second.amount)); + delta.push_back(Pair("timestamp", it->second.time)); + if (it->second.amount < 0) { + delta.push_back(Pair("prevtxid", it->second.prevhash.GetHex())); + delta.push_back(Pair("prevout", (int)it->second.prevout)); + } + result.push_back(delta); + } + + return result; +} + +UniValue getaddressutxos(const UniValue& params, bool fHelp) +{ + if (fHelp || params.size() != 1) + throw runtime_error( + "getaddressutxos\n" + "\nReturns all unspent outputs for an address (requires addressindex to be enabled).\n" + "\nArguments:\n" + "{\n" + " \"addresses\"\n" + " [\n" + " \"address\" (string) The base58check encoded address\n" + " ,...\n" + " ],\n" + " \"chainInfo\" (boolean) Include chain info with results\n" + "}\n" + "\nResult\n" + "[\n" + " {\n" + " \"address\" (string) The address base58check encoded\n" + " \"txid\" (string) The output txid\n" + " \"height\" (number) The block height\n" + " \"outputIndex\" (number) The output index\n" + " \"script\" (strin) The script hex encoded\n" + " \"satoshis\" (number) The number of satoshis of the output\n" + " }\n" + "]\n" + "\nExamples:\n" + + HelpExampleCli("getaddressutxos", "'{\"addresses\": [\"12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX\"]}'") + + HelpExampleRpc("getaddressutxos", "{\"addresses\": [\"12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX\"]}") + ); + + bool includeChainInfo = false; + if (params[0].isObject()) { + UniValue chainInfo = find_value(params[0].get_obj(), "chainInfo"); + if (chainInfo.isBool()) { + includeChainInfo = chainInfo.get_bool(); + } + } + + std::vector > addresses; + + if (!getAddressesFromParams(params, addresses)) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address"); + } + + std::vector > unspentOutputs; + + for (std::vector >::iterator it = addresses.begin(); it != addresses.end(); it++) { + if (!GetAddressUnspent((*it).first, (*it).second, unspentOutputs)) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available for address"); + } + } + + std::sort(unspentOutputs.begin(), unspentOutputs.end(), heightSort); + + UniValue utxos(UniValue::VARR); + + for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) { + UniValue output(UniValue::VOBJ); + std::string address; + if (!getAddressFromIndex(it->first.type, it->first.hashBytes, address)) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Unknown address type"); + } + + output.push_back(Pair("address", address)); + output.push_back(Pair("txid", it->first.txhash.GetHex())); + output.push_back(Pair("outputIndex", (int)it->first.index)); + output.push_back(Pair("script", HexStr(it->second.script.begin(), it->second.script.end()))); + output.push_back(Pair("satoshis", it->second.satoshis)); + output.push_back(Pair("height", it->second.blockHeight)); + utxos.push_back(output); + } + + if (includeChainInfo) { + UniValue result(UniValue::VOBJ); + result.push_back(Pair("utxos", utxos)); + + LOCK(cs_main); + result.push_back(Pair("hash", chainActive.Tip()->GetBlockHash().GetHex())); + result.push_back(Pair("height", (int)chainActive.Height())); + return result; + } else { + return utxos; + } +} + +UniValue getaddressdeltas(const UniValue& params, bool fHelp) +{ + if (fHelp || params.size() != 1 || !params[0].isObject()) + throw runtime_error( + "getaddressdeltas\n" + "\nReturns all changes for an address (requires addressindex to be enabled).\n" + "\nArguments:\n" + "{\n" + " \"addresses\"\n" + " [\n" + " \"address\" (string) The base58check encoded address\n" + " ,...\n" + " ]\n" + " \"start\" (number) The start block height\n" + " \"end\" (number) The end block height\n" + " \"chainInfo\" (boolean) Include chain info in results, only applies if start and end specified\n" + "}\n" + "\nResult:\n" + "[\n" + " {\n" + " \"satoshis\" (number) The difference of satoshis\n" + " \"txid\" (string) The related txid\n" + " \"index\" (number) The related input or output index\n" + " \"height\" (number) The block height\n" + " \"address\" (string) The base58check encoded address\n" + " }\n" + "]\n" + "\nExamples:\n" + + HelpExampleCli("getaddressdeltas", "'{\"addresses\": [\"12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX\"]}'") + + HelpExampleRpc("getaddressdeltas", "{\"addresses\": [\"12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX\"]}") + ); + + + UniValue startValue = find_value(params[0].get_obj(), "start"); + UniValue endValue = find_value(params[0].get_obj(), "end"); + + UniValue chainInfo = find_value(params[0].get_obj(), "chainInfo"); + bool includeChainInfo = false; + if (chainInfo.isBool()) { + includeChainInfo = chainInfo.get_bool(); + } + + int start = 0; + int end = 0; + + if (startValue.isNum() && endValue.isNum()) { + start = startValue.get_int(); + end = endValue.get_int(); + if (start <= 0 || end <= 0) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Start and end is expected to be greater than zero"); + } + if (end < start) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "End value is expected to be greater than start"); + } + } + + std::vector > addresses; + + if (!getAddressesFromParams(params, addresses)) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address"); + } + + std::vector > addressIndex; + + for (std::vector >::iterator it = addresses.begin(); it != addresses.end(); it++) { + if (start > 0 && end > 0) { + if (!GetAddressIndex((*it).first, (*it).second, addressIndex, start, end)) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available for address"); + } + } else { + if (!GetAddressIndex((*it).first, (*it).second, addressIndex)) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available for address"); + } + } + } + + UniValue deltas(UniValue::VARR); + + for (std::vector >::const_iterator it=addressIndex.begin(); it!=addressIndex.end(); it++) { + std::string address; + if (!getAddressFromIndex(it->first.type, it->first.hashBytes, address)) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Unknown address type"); + } + + UniValue delta(UniValue::VOBJ); + delta.push_back(Pair("satoshis", it->second)); + delta.push_back(Pair("txid", it->first.txhash.GetHex())); + delta.push_back(Pair("index", (int)it->first.index)); + delta.push_back(Pair("blockindex", (int)it->first.txindex)); + delta.push_back(Pair("height", it->first.blockHeight)); + delta.push_back(Pair("address", address)); + deltas.push_back(delta); + } + + UniValue result(UniValue::VOBJ); + + if (includeChainInfo && start > 0 && end > 0) { + LOCK(cs_main); + + if (start > chainActive.Height() || end > chainActive.Height()) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Start or end is outside chain range"); + } + + CBlockIndex* startIndex = chainActive[start]; + CBlockIndex* endIndex = chainActive[end]; + + UniValue startInfo(UniValue::VOBJ); + UniValue endInfo(UniValue::VOBJ); + + startInfo.push_back(Pair("hash", startIndex->GetBlockHash().GetHex())); + startInfo.push_back(Pair("height", start)); + + endInfo.push_back(Pair("hash", endIndex->GetBlockHash().GetHex())); + endInfo.push_back(Pair("height", end)); + + result.push_back(Pair("deltas", deltas)); + result.push_back(Pair("start", startInfo)); + result.push_back(Pair("end", endInfo)); + + return result; + } else { + return deltas; + } +} + +UniValue getaddressbalance(const UniValue& params, bool fHelp) +{ + if (fHelp || params.size() != 1) + throw runtime_error( + "getaddressbalance\n" + "\nReturns the balance for an address(es) (requires addressindex to be enabled).\n" + "\nArguments:\n" + "{\n" + " \"addresses\"\n" + " [\n" + " \"address\" (string) The base58check encoded address\n" + " ,...\n" + " ]\n" + "}\n" + "\nResult:\n" + "{\n" + " \"balance\" (string) The current balance in satoshis\n" + " \"received\" (string) The total number of satoshis received (including change)\n" + "}\n" + "\nExamples:\n" + + HelpExampleCli("getaddressbalance", "'{\"addresses\": [\"12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX\"]}'") + + HelpExampleRpc("getaddressbalance", "{\"addresses\": [\"12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX\"]}") + ); + + std::vector > addresses; + + if (!getAddressesFromParams(params, addresses)) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address"); + } + + std::vector > addressIndex; + + for (std::vector >::iterator it = addresses.begin(); it != addresses.end(); it++) { + if (!GetAddressIndex((*it).first, (*it).second, addressIndex)) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available for address"); + } + } + + CAmount balance = 0; + CAmount received = 0; + + for (std::vector >::const_iterator it=addressIndex.begin(); it!=addressIndex.end(); it++) { + if (it->second > 0) { + received += it->second; + } + balance += it->second; + } + + UniValue result(UniValue::VOBJ); + result.push_back(Pair("balance", balance)); + result.push_back(Pair("received", received)); + + return result; + +} + +UniValue getaddresstxids(const UniValue& params, bool fHelp) +{ + if (fHelp || params.size() != 1) + throw runtime_error( + "getaddresstxids\n" + "\nReturns the txids for an address(es) (requires addressindex to be enabled).\n" + "\nArguments:\n" + "{\n" + " \"addresses\"\n" + " [\n" + " \"address\" (string) The base58check encoded address\n" + " ,...\n" + " ]\n" + " \"start\" (number) The start block height\n" + " \"end\" (number) The end block height\n" + "}\n" + "\nResult:\n" + "[\n" + " \"transactionid\" (string) The transaction id\n" + " ,...\n" + "]\n" + "\nExamples:\n" + + HelpExampleCli("getaddresstxids", "'{\"addresses\": [\"12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX\"]}'") + + HelpExampleRpc("getaddresstxids", "{\"addresses\": [\"12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX\"]}") + ); + + std::vector > addresses; + + if (!getAddressesFromParams(params, addresses)) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address"); + } + + int start = 0; + int end = 0; + if (params[0].isObject()) { + UniValue startValue = find_value(params[0].get_obj(), "start"); + UniValue endValue = find_value(params[0].get_obj(), "end"); + if (startValue.isNum() && endValue.isNum()) { + start = startValue.get_int(); + end = endValue.get_int(); + } + } + + std::vector > addressIndex; + + for (std::vector >::iterator it = addresses.begin(); it != addresses.end(); it++) { + if (start > 0 && end > 0) { + if (!GetAddressIndex((*it).first, (*it).second, addressIndex, start, end)) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available for address"); + } + } else { + if (!GetAddressIndex((*it).first, (*it).second, addressIndex)) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available for address"); + } + } + } + + std::set > txids; + UniValue result(UniValue::VARR); + + for (std::vector >::const_iterator it=addressIndex.begin(); it!=addressIndex.end(); it++) { + int height = it->first.blockHeight; + std::string txid = it->first.txhash.GetHex(); + + if (addresses.size() > 1) { + txids.insert(std::make_pair(height, txid)); + } else { + if (txids.insert(std::make_pair(height, txid)).second) { + result.push_back(txid); + } + } + } + + if (addresses.size() > 1) { + for (std::set >::const_iterator it=txids.begin(); it!=txids.end(); it++) { + result.push_back(it->second); + } + } + + return result; + +} + +UniValue getspentinfo(const UniValue& params, bool fHelp) +{ + + if (fHelp || params.size() != 1 || !params[0].isObject()) + throw runtime_error( + "getspentinfo\n" + "\nReturns the txid and index where an output is spent.\n" + "\nArguments:\n" + "{\n" + " \"txid\" (string) The hex string of the txid\n" + " \"index\" (number) The start block height\n" + "}\n" + "\nResult:\n" + "{\n" + " \"txid\" (string) The transaction id\n" + " \"index\" (number) The spending input index\n" + " ,...\n" + "}\n" + "\nExamples:\n" + + HelpExampleCli("getspentinfo", "'{\"txid\": \"0437cd7f8525ceed2324359c2d0ba26006d92d856a9c20fa0241106ee5a597c9\", \"index\": 0}'") + + HelpExampleRpc("getspentinfo", "{\"txid\": \"0437cd7f8525ceed2324359c2d0ba26006d92d856a9c20fa0241106ee5a597c9\", \"index\": 0}") + ); + + UniValue txidValue = find_value(params[0].get_obj(), "txid"); + UniValue indexValue = find_value(params[0].get_obj(), "index"); + + if (!txidValue.isStr() || !indexValue.isNum()) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid txid or index"); + } + + uint256 txid = ParseHashV(txidValue, "txid"); + int outputIndex = indexValue.get_int(); + + CSpentIndexKey key(txid, outputIndex); + CSpentIndexValue value; + + if (!GetSpentIndex(key, value)) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Unable to get spent info"); + } + + UniValue obj(UniValue::VOBJ); + obj.push_back(Pair("txid", value.txid.GetHex())); + obj.push_back(Pair("index", (int)value.inputIndex)); + obj.push_back(Pair("height", value.blockHeight)); + + return obj; +} diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp old mode 100644 new mode 100755 diff --git a/src/rpcprotocol.cpp b/src/rpcprotocol.cpp old mode 100644 new mode 100755 diff --git a/src/rpcprotocol.h b/src/rpcprotocol.h old mode 100644 new mode 100755 diff --git a/src/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp old mode 100644 new mode 100755 index 02fb6680298..332f6931eff --- a/src/rpcrawtransaction.cpp +++ b/src/rpcrawtransaction.cpp @@ -62,7 +62,9 @@ UniValue TxJoinSplitToJSON(const CTransaction& tx) { UniValue joinsplit(UniValue::VOBJ); joinsplit.push_back(Pair("vpub_old", ValueFromAmount(jsdescription.vpub_old))); + joinsplit.push_back(Pair("vpub_oldZat", jsdescription.vpub_old)); joinsplit.push_back(Pair("vpub_new", ValueFromAmount(jsdescription.vpub_new))); + joinsplit.push_back(Pair("vpub_newZat", jsdescription.vpub_new)); joinsplit.push_back(Pair("anchor", jsdescription.anchor.GetHex())); @@ -110,9 +112,10 @@ UniValue TxJoinSplitToJSON(const CTransaction& tx) { return vjoinsplit; } -void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry) +void TxToJSONExpanded(const CTransaction& tx, const uint256 hashBlock, UniValue& entry, int nHeight = 0, int nConfirmations = 0, int nBlockTime = 0) { - entry.push_back(Pair("txid", tx.GetHash().GetHex())); + uint256 txid = tx.GetHash(); + entry.push_back(Pair("txid", txid.GetHex())); entry.push_back(Pair("version", tx.nVersion)); entry.push_back(Pair("locktime", (int64_t)tx.nLockTime)); UniValue vin(UniValue::VARR); @@ -127,6 +130,20 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry) o.push_back(Pair("asm", txin.scriptSig.ToString())); o.push_back(Pair("hex", HexStr(txin.scriptSig.begin(), txin.scriptSig.end()))); in.push_back(Pair("scriptSig", o)); + + // Add address and value info if spentindex enabled + CSpentIndexValue spentInfo; + CSpentIndexKey spentKey(txin.prevout.hash, txin.prevout.n); + if (GetSpentIndex(spentKey, spentInfo)) { + in.push_back(Pair("value", ValueFromAmount(spentInfo.satoshis))); + in.push_back(Pair("valueSat", spentInfo.satoshis)); + if (spentInfo.addressType == 1) { + in.push_back(Pair("address", CBitcoinAddress(CKeyID(spentInfo.addressHash)).ToString())); + } else if (spentInfo.addressType == 2) { + in.push_back(Pair("address", CBitcoinAddress(CScriptID(spentInfo.addressHash)).ToString())); + } + } + } in.push_back(Pair("sequence", (int64_t)txin.nSequence)); vin.push_back(in); @@ -137,11 +154,21 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry) const CTxOut& txout = tx.vout[i]; UniValue out(UniValue::VOBJ); out.push_back(Pair("value", ValueFromAmount(txout.nValue))); - out.push_back(Pair("valueZat", txout.nValue)); + out.push_back(Pair("valueSat", txout.nValue)); out.push_back(Pair("n", (int64_t)i)); UniValue o(UniValue::VOBJ); ScriptPubKeyToJSON(txout.scriptPubKey, o, true); out.push_back(Pair("scriptPubKey", o)); + + // Add spent information if spentindex is enabled + CSpentIndexValue spentInfo; + CSpentIndexKey spentKey(txid, i); + if (GetSpentIndex(spentKey, spentInfo)) { + out.push_back(Pair("spentTxId", spentInfo.txid.GetHex())); + out.push_back(Pair("spentIndex", (int)spentInfo.inputIndex)); + out.push_back(Pair("spentHeight", spentInfo.blockHeight)); + } + vout.push_back(out); } entry.push_back(Pair("vout", vout)); @@ -149,18 +176,77 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry) UniValue vjoinsplit = TxJoinSplitToJSON(tx); entry.push_back(Pair("vjoinsplit", vjoinsplit)); + if (!hashBlock.IsNull()) { + entry.push_back(Pair("blockhash", hashBlock.GetHex())); + + if (nConfirmations > 0) { + entry.push_back(Pair("height", nHeight)); + entry.push_back(Pair("confirmations", nConfirmations)); + entry.push_back(Pair("time", nBlockTime)); + entry.push_back(Pair("blocktime", nBlockTime)); + } else { + entry.push_back(Pair("height", -1)); + entry.push_back(Pair("confirmations", 0)); + } + } + +} + +void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry) +{ + + uint256 txid = tx.GetHash(); + entry.push_back(Pair("txid", txid.GetHex())); + entry.push_back(Pair("size", (int)::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION))); + entry.push_back(Pair("version", tx.nVersion)); + entry.push_back(Pair("locktime", (int64_t)tx.nLockTime)); + + UniValue vin(UniValue::VARR); + BOOST_FOREACH(const CTxIn& txin, tx.vin) { + UniValue in(UniValue::VOBJ); + if (tx.IsCoinBase()) + in.push_back(Pair("coinbase", HexStr(txin.scriptSig.begin(), txin.scriptSig.end()))); + else { + in.push_back(Pair("txid", txin.prevout.hash.GetHex())); + in.push_back(Pair("vout", (int64_t)txin.prevout.n)); + UniValue o(UniValue::VOBJ); + o.push_back(Pair("asm", txin.scriptSig.ToString())); + o.push_back(Pair("hex", HexStr(txin.scriptSig.begin(), txin.scriptSig.end()))); + in.push_back(Pair("scriptSig", o)); + } + in.push_back(Pair("sequence", (int64_t)txin.nSequence)); + vin.push_back(in); + } + entry.push_back(Pair("vin", vin)); + + UniValue vout(UniValue::VARR); + for (unsigned int i = 0; i < tx.vout.size(); i++) { + const CTxOut& txout = tx.vout[i]; + UniValue out(UniValue::VOBJ); + out.push_back(Pair("value", ValueFromAmount(txout.nValue))); + out.push_back(Pair("valueSat", txout.nValue)); + out.push_back(Pair("n", (int64_t)i)); + UniValue o(UniValue::VOBJ); + ScriptPubKeyToJSON(txout.scriptPubKey, o, true); + out.push_back(Pair("scriptPubKey", o)); + vout.push_back(out); + } + entry.push_back(Pair("vout", vout)); + if (!hashBlock.IsNull()) { entry.push_back(Pair("blockhash", hashBlock.GetHex())); BlockMap::iterator mi = mapBlockIndex.find(hashBlock); if (mi != mapBlockIndex.end() && (*mi).second) { CBlockIndex* pindex = (*mi).second; if (chainActive.Contains(pindex)) { + entry.push_back(Pair("height", pindex->nHeight)); entry.push_back(Pair("confirmations", 1 + chainActive.Height() - pindex->nHeight)); entry.push_back(Pair("time", pindex->GetBlockTime())); entry.push_back(Pair("blocktime", pindex->GetBlockTime())); - } - else + } else { + entry.push_back(Pair("height", -1)); entry.push_back(Pair("confirmations", 0)); + } } } } @@ -258,7 +344,7 @@ UniValue getrawtransaction(const UniValue& params, bool fHelp) + HelpExampleRpc("getrawtransaction", "\"mytxid\", 1") ); - LOCK(cs_main); + uint256 hash = ParseHashV(params[0], "parameter 1"); @@ -268,8 +354,29 @@ UniValue getrawtransaction(const UniValue& params, bool fHelp) CTransaction tx; uint256 hashBlock; - if (!GetTransaction(hash, tx, hashBlock, true)) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available about transaction"); + int nHeight = 0; + int nConfirmations = 0; + int nBlockTime = 0; + + { + LOCK(cs_main); + if (!GetTransaction(hash, tx, hashBlock, true)) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available about transaction"); + + BlockMap::iterator mi = mapBlockIndex.find(hashBlock); + if (mi != mapBlockIndex.end() && (*mi).second) { + CBlockIndex* pindex = (*mi).second; + if (chainActive.Contains(pindex)) { + nHeight = pindex->nHeight; + nConfirmations = 1 + chainActive.Height() - pindex->nHeight; + nBlockTime = pindex->GetBlockTime(); + } else { + nHeight = -1; + nConfirmations = 0; + nBlockTime = pindex->GetBlockTime(); + } + } + } string strHex = EncodeHexTx(tx); @@ -278,7 +385,7 @@ UniValue getrawtransaction(const UniValue& params, bool fHelp) UniValue result(UniValue::VOBJ); result.push_back(Pair("hex", strHex)); - TxToJSON(tx, hashBlock, result); + TxToJSONExpanded(tx, hashBlock, result, nHeight, nConfirmations, nBlockTime); return result; } diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp old mode 100644 new mode 100755 index d1ba94deb70..324a54e3690 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -280,6 +280,8 @@ static const CRPCCommand vRPCCommands[] = { "blockchain", "getbestblockhash", &getbestblockhash, true }, { "blockchain", "getblockcount", &getblockcount, true }, { "blockchain", "getblock", &getblock, true }, + { "blockchain", "getblockdeltas", &getblockdeltas, false }, + { "blockchain", "getblockhashes", &getblockhashes, true }, { "blockchain", "getblockhash", &getblockhash, true }, { "blockchain", "getblockheader", &getblockheader, true }, { "blockchain", "getchaintips", &getchaintips, true }, @@ -291,6 +293,7 @@ static const CRPCCommand vRPCCommands[] = { "blockchain", "verifytxoutproof", &verifytxoutproof, true }, { "blockchain", "gettxoutsetinfo", &gettxoutsetinfo, true }, { "blockchain", "verifychain", &verifychain, true }, + { "blockchain", "getspentinfo", &getspentinfo, false }, /* Mining */ { "mining", "getblocktemplate", &getblocktemplate, true }, @@ -320,6 +323,13 @@ static const CRPCCommand vRPCCommands[] = { "rawtransactions", "fundrawtransaction", &fundrawtransaction, false }, #endif + /* Address index */ + { "addressindex", "getaddressmempool", &getaddressmempool, true }, + { "addressindex", "getaddressutxos", &getaddressutxos, false }, + { "addressindex", "getaddressdeltas", &getaddressdeltas, false }, + { "addressindex", "getaddresstxids", &getaddresstxids, false }, + { "addressindex", "getaddressbalance", &getaddressbalance, false }, + /* Utility functions */ { "util", "createmultisig", &createmultisig, true }, { "util", "validateaddress", &validateaddress, true }, /* uses wallet if enabled */ diff --git a/src/rpcserver.h b/src/rpcserver.h old mode 100644 new mode 100755 index 4da5154263c..3eacd66ce94 --- a/src/rpcserver.h +++ b/src/rpcserver.h @@ -173,6 +173,13 @@ extern std::string HelpExampleRpc(const std::string& methodname, const std::stri extern void EnsureWalletIsUnlocked(); extern UniValue getconnectioncount(const UniValue& params, bool fHelp); // in rpcnet.cpp + +extern UniValue getaddressmempool(const UniValue& params, bool fHelp); +extern UniValue getaddressutxos(const UniValue& params, bool fHelp); +extern UniValue getaddressdeltas(const UniValue& params, bool fHelp); +extern UniValue getaddresstxids(const UniValue& params, bool fHelp); +extern UniValue getaddressbalance(const UniValue& params, bool fHelp); + extern UniValue getpeerinfo(const UniValue& params, bool fHelp); extern UniValue ping(const UniValue& params, bool fHelp); extern UniValue addnode(const UniValue& params, bool fHelp); @@ -265,9 +272,13 @@ extern UniValue getdifficulty(const UniValue& params, bool fHelp); extern UniValue settxfee(const UniValue& params, bool fHelp); extern UniValue getmempoolinfo(const UniValue& params, bool fHelp); extern UniValue getrawmempool(const UniValue& params, bool fHelp); + +extern UniValue getblockhashes(const UniValue& params, bool fHelp); +extern UniValue getblockdeltas(const UniValue& params, bool fHelp); extern UniValue getblockhash(const UniValue& params, bool fHelp); extern UniValue getblockheader(const UniValue& params, bool fHelp); extern UniValue getblock(const UniValue& params, bool fHelp); + extern UniValue gettxoutsetinfo(const UniValue& params, bool fHelp); extern UniValue gettxout(const UniValue& params, bool fHelp); extern UniValue verifychain(const UniValue& params, bool fHelp); @@ -275,6 +286,8 @@ extern UniValue getchaintips(const UniValue& params, bool fHelp); extern UniValue invalidateblock(const UniValue& params, bool fHelp); extern UniValue reconsiderblock(const UniValue& params, bool fHelp); +extern UniValue getspentinfo(const UniValue& params, bool fHelp); + extern UniValue getblocksubsidy(const UniValue& params, bool fHelp); extern UniValue z_exportkey(const UniValue& params, bool fHelp); // in rpcdump.cpp diff --git a/src/scheduler.cpp b/src/scheduler.cpp old mode 100644 new mode 100755 diff --git a/src/scheduler.h b/src/scheduler.h old mode 100644 new mode 100755 diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp old mode 100644 new mode 100755 diff --git a/src/script/interpreter.h b/src/script/interpreter.h old mode 100644 new mode 100755 diff --git a/src/script/script.cpp b/src/script/script.cpp old mode 100644 new mode 100755 index fd33924732c..bfb860a03f8 --- a/src/script/script.cpp +++ b/src/script/script.cpp @@ -211,6 +211,17 @@ unsigned int CScript::GetSigOpCount(const CScript& scriptSig) const return subscript.GetSigOpCount(true); } +bool CScript::IsPayToPublicKeyHash() const +{ + // Extra-fast test for pay-to-pubkey-hash CScripts: + return (this->size() == 25 && + (*this)[0] == OP_DUP && + (*this)[1] == OP_HASH160 && + (*this)[2] == 0x14 && + (*this)[23] == OP_EQUALVERIFY && + (*this)[24] == OP_CHECKSIG); +} + bool CScript::IsPayToScriptHash() const { // Extra-fast test for pay-to-script-hash CScripts: diff --git a/src/script/script.h b/src/script/script.h old mode 100644 new mode 100755 index e0e89185f79..c996c7538cc --- a/src/script/script.h +++ b/src/script/script.h @@ -561,6 +561,8 @@ class CScript : public std::vector */ unsigned int GetSigOpCount(const CScript& scriptSig) const; + bool IsPayToPublicKeyHash() const; + bool IsPayToScriptHash() const; /** Called by IsStandardTx and P2SH/BIP62 VerifyScript (which makes it consensus-critical). */ diff --git a/src/script/script_error.cpp b/src/script/script_error.cpp old mode 100644 new mode 100755 diff --git a/src/script/script_error.h b/src/script/script_error.h old mode 100644 new mode 100755 diff --git a/src/script/sigcache.cpp b/src/script/sigcache.cpp old mode 100644 new mode 100755 diff --git a/src/script/sigcache.h b/src/script/sigcache.h old mode 100644 new mode 100755 diff --git a/src/script/sign.cpp b/src/script/sign.cpp old mode 100644 new mode 100755 diff --git a/src/script/sign.h b/src/script/sign.h old mode 100644 new mode 100755 diff --git a/src/script/standard.cpp b/src/script/standard.cpp old mode 100644 new mode 100755 diff --git a/src/script/standard.h b/src/script/standard.h old mode 100644 new mode 100755 diff --git a/src/script/zcashconsensus.cpp b/src/script/zcashconsensus.cpp old mode 100644 new mode 100755 diff --git a/src/script/zcashconsensus.h b/src/script/zcashconsensus.h old mode 100644 new mode 100755 diff --git a/src/secp256k1/.gitignore b/src/secp256k1/.gitignore old mode 100644 new mode 100755 diff --git a/src/secp256k1/.travis.yml b/src/secp256k1/.travis.yml old mode 100644 new mode 100755 diff --git a/src/secp256k1/COPYING b/src/secp256k1/COPYING old mode 100644 new mode 100755 diff --git a/src/secp256k1/Makefile.am b/src/secp256k1/Makefile.am old mode 100644 new mode 100755 diff --git a/src/secp256k1/README.md b/src/secp256k1/README.md old mode 100644 new mode 100755 diff --git a/src/secp256k1/TODO b/src/secp256k1/TODO old mode 100644 new mode 100755 diff --git a/src/secp256k1/build-aux/m4/ax_jni_include_dir.m4 b/src/secp256k1/build-aux/m4/ax_jni_include_dir.m4 old mode 100644 new mode 100755 diff --git a/src/secp256k1/build-aux/m4/ax_prog_cc_for_build.m4 b/src/secp256k1/build-aux/m4/ax_prog_cc_for_build.m4 old mode 100644 new mode 100755 diff --git a/src/secp256k1/build-aux/m4/bitcoin_secp.m4 b/src/secp256k1/build-aux/m4/bitcoin_secp.m4 old mode 100644 new mode 100755 diff --git a/src/secp256k1/configure.ac b/src/secp256k1/configure.ac old mode 100644 new mode 100755 diff --git a/src/secp256k1/contrib/lax_der_parsing.c b/src/secp256k1/contrib/lax_der_parsing.c old mode 100644 new mode 100755 diff --git a/src/secp256k1/contrib/lax_der_parsing.h b/src/secp256k1/contrib/lax_der_parsing.h old mode 100644 new mode 100755 diff --git a/src/secp256k1/contrib/lax_der_privatekey_parsing.c b/src/secp256k1/contrib/lax_der_privatekey_parsing.c old mode 100644 new mode 100755 diff --git a/src/secp256k1/contrib/lax_der_privatekey_parsing.h b/src/secp256k1/contrib/lax_der_privatekey_parsing.h old mode 100644 new mode 100755 diff --git a/src/secp256k1/include/secp256k1.h b/src/secp256k1/include/secp256k1.h old mode 100644 new mode 100755 diff --git a/src/secp256k1/include/secp256k1_ecdh.h b/src/secp256k1/include/secp256k1_ecdh.h old mode 100644 new mode 100755 diff --git a/src/secp256k1/include/secp256k1_recovery.h b/src/secp256k1/include/secp256k1_recovery.h old mode 100644 new mode 100755 diff --git a/src/secp256k1/libsecp256k1.pc.in b/src/secp256k1/libsecp256k1.pc.in old mode 100644 new mode 100755 diff --git a/src/secp256k1/obj/.gitignore b/src/secp256k1/obj/.gitignore old mode 100644 new mode 100755 diff --git a/src/secp256k1/sage/group_prover.sage b/src/secp256k1/sage/group_prover.sage old mode 100644 new mode 100755 diff --git a/src/secp256k1/sage/secp256k1.sage b/src/secp256k1/sage/secp256k1.sage old mode 100644 new mode 100755 diff --git a/src/secp256k1/sage/weierstrass_prover.sage b/src/secp256k1/sage/weierstrass_prover.sage old mode 100644 new mode 100755 diff --git a/src/secp256k1/src/asm/field_10x26_arm.s b/src/secp256k1/src/asm/field_10x26_arm.s old mode 100644 new mode 100755 diff --git a/src/secp256k1/src/basic-config.h b/src/secp256k1/src/basic-config.h old mode 100644 new mode 100755 diff --git a/src/secp256k1/src/bench.h b/src/secp256k1/src/bench.h old mode 100644 new mode 100755 diff --git a/src/secp256k1/src/bench_ecdh.c b/src/secp256k1/src/bench_ecdh.c old mode 100644 new mode 100755 diff --git a/src/secp256k1/src/bench_internal.c b/src/secp256k1/src/bench_internal.c old mode 100644 new mode 100755 diff --git a/src/secp256k1/src/bench_recover.c b/src/secp256k1/src/bench_recover.c old mode 100644 new mode 100755 diff --git a/src/secp256k1/src/bench_sign.c b/src/secp256k1/src/bench_sign.c old mode 100644 new mode 100755 diff --git a/src/secp256k1/src/bench_verify.c b/src/secp256k1/src/bench_verify.c old mode 100644 new mode 100755 diff --git a/src/secp256k1/src/ecdsa.h b/src/secp256k1/src/ecdsa.h old mode 100644 new mode 100755 diff --git a/src/secp256k1/src/ecdsa_impl.h b/src/secp256k1/src/ecdsa_impl.h old mode 100644 new mode 100755 diff --git a/src/secp256k1/src/eckey.h b/src/secp256k1/src/eckey.h old mode 100644 new mode 100755 diff --git a/src/secp256k1/src/eckey_impl.h b/src/secp256k1/src/eckey_impl.h old mode 100644 new mode 100755 diff --git a/src/secp256k1/src/ecmult.h b/src/secp256k1/src/ecmult.h old mode 100644 new mode 100755 diff --git a/src/secp256k1/src/ecmult_const.h b/src/secp256k1/src/ecmult_const.h old mode 100644 new mode 100755 diff --git a/src/secp256k1/src/ecmult_const_impl.h b/src/secp256k1/src/ecmult_const_impl.h old mode 100644 new mode 100755 diff --git a/src/secp256k1/src/ecmult_gen.h b/src/secp256k1/src/ecmult_gen.h old mode 100644 new mode 100755 diff --git a/src/secp256k1/src/ecmult_gen_impl.h b/src/secp256k1/src/ecmult_gen_impl.h old mode 100644 new mode 100755 diff --git a/src/secp256k1/src/ecmult_impl.h b/src/secp256k1/src/ecmult_impl.h old mode 100644 new mode 100755 diff --git a/src/secp256k1/src/field.h b/src/secp256k1/src/field.h old mode 100644 new mode 100755 diff --git a/src/secp256k1/src/field_10x26.h b/src/secp256k1/src/field_10x26.h old mode 100644 new mode 100755 diff --git a/src/secp256k1/src/field_10x26_impl.h b/src/secp256k1/src/field_10x26_impl.h old mode 100644 new mode 100755 diff --git a/src/secp256k1/src/field_5x52.h b/src/secp256k1/src/field_5x52.h old mode 100644 new mode 100755 diff --git a/src/secp256k1/src/field_5x52_asm_impl.h b/src/secp256k1/src/field_5x52_asm_impl.h old mode 100644 new mode 100755 diff --git a/src/secp256k1/src/field_5x52_impl.h b/src/secp256k1/src/field_5x52_impl.h old mode 100644 new mode 100755 diff --git a/src/secp256k1/src/field_5x52_int128_impl.h b/src/secp256k1/src/field_5x52_int128_impl.h old mode 100644 new mode 100755 diff --git a/src/secp256k1/src/field_impl.h b/src/secp256k1/src/field_impl.h old mode 100644 new mode 100755 diff --git a/src/secp256k1/src/gen_context.c b/src/secp256k1/src/gen_context.c old mode 100644 new mode 100755 diff --git a/src/secp256k1/src/group.h b/src/secp256k1/src/group.h old mode 100644 new mode 100755 diff --git a/src/secp256k1/src/group_impl.h b/src/secp256k1/src/group_impl.h old mode 100644 new mode 100755 diff --git a/src/secp256k1/src/hash.h b/src/secp256k1/src/hash.h old mode 100644 new mode 100755 diff --git a/src/secp256k1/src/hash_impl.h b/src/secp256k1/src/hash_impl.h old mode 100644 new mode 100755 diff --git a/src/secp256k1/src/java/org/bitcoin/NativeSecp256k1.java b/src/secp256k1/src/java/org/bitcoin/NativeSecp256k1.java old mode 100644 new mode 100755 diff --git a/src/secp256k1/src/java/org/bitcoin/NativeSecp256k1Test.java b/src/secp256k1/src/java/org/bitcoin/NativeSecp256k1Test.java old mode 100644 new mode 100755 diff --git a/src/secp256k1/src/java/org/bitcoin/NativeSecp256k1Util.java b/src/secp256k1/src/java/org/bitcoin/NativeSecp256k1Util.java old mode 100644 new mode 100755 diff --git a/src/secp256k1/src/java/org/bitcoin/Secp256k1Context.java b/src/secp256k1/src/java/org/bitcoin/Secp256k1Context.java old mode 100644 new mode 100755 diff --git a/src/secp256k1/src/java/org_bitcoin_NativeSecp256k1.c b/src/secp256k1/src/java/org_bitcoin_NativeSecp256k1.c old mode 100644 new mode 100755 diff --git a/src/secp256k1/src/java/org_bitcoin_NativeSecp256k1.h b/src/secp256k1/src/java/org_bitcoin_NativeSecp256k1.h old mode 100644 new mode 100755 diff --git a/src/secp256k1/src/java/org_bitcoin_Secp256k1Context.c b/src/secp256k1/src/java/org_bitcoin_Secp256k1Context.c old mode 100644 new mode 100755 diff --git a/src/secp256k1/src/java/org_bitcoin_Secp256k1Context.h b/src/secp256k1/src/java/org_bitcoin_Secp256k1Context.h old mode 100644 new mode 100755 diff --git a/src/secp256k1/src/modules/ecdh/Makefile.am.include b/src/secp256k1/src/modules/ecdh/Makefile.am.include old mode 100644 new mode 100755 diff --git a/src/secp256k1/src/modules/ecdh/main_impl.h b/src/secp256k1/src/modules/ecdh/main_impl.h old mode 100644 new mode 100755 diff --git a/src/secp256k1/src/modules/ecdh/tests_impl.h b/src/secp256k1/src/modules/ecdh/tests_impl.h old mode 100644 new mode 100755 diff --git a/src/secp256k1/src/modules/recovery/Makefile.am.include b/src/secp256k1/src/modules/recovery/Makefile.am.include old mode 100644 new mode 100755 diff --git a/src/secp256k1/src/modules/recovery/tests_impl.h b/src/secp256k1/src/modules/recovery/tests_impl.h old mode 100644 new mode 100755 diff --git a/src/secp256k1/src/num.h b/src/secp256k1/src/num.h old mode 100644 new mode 100755 diff --git a/src/secp256k1/src/num_gmp.h b/src/secp256k1/src/num_gmp.h old mode 100644 new mode 100755 diff --git a/src/secp256k1/src/num_gmp_impl.h b/src/secp256k1/src/num_gmp_impl.h old mode 100644 new mode 100755 diff --git a/src/secp256k1/src/num_impl.h b/src/secp256k1/src/num_impl.h old mode 100644 new mode 100755 diff --git a/src/secp256k1/src/scalar.h b/src/secp256k1/src/scalar.h old mode 100644 new mode 100755 diff --git a/src/secp256k1/src/scalar_4x64.h b/src/secp256k1/src/scalar_4x64.h old mode 100644 new mode 100755 diff --git a/src/secp256k1/src/scalar_4x64_impl.h b/src/secp256k1/src/scalar_4x64_impl.h old mode 100644 new mode 100755 diff --git a/src/secp256k1/src/scalar_8x32.h b/src/secp256k1/src/scalar_8x32.h old mode 100644 new mode 100755 diff --git a/src/secp256k1/src/scalar_8x32_impl.h b/src/secp256k1/src/scalar_8x32_impl.h old mode 100644 new mode 100755 diff --git a/src/secp256k1/src/scalar_impl.h b/src/secp256k1/src/scalar_impl.h old mode 100644 new mode 100755 diff --git a/src/secp256k1/src/scalar_low.h b/src/secp256k1/src/scalar_low.h old mode 100644 new mode 100755 diff --git a/src/secp256k1/src/scalar_low_impl.h b/src/secp256k1/src/scalar_low_impl.h old mode 100644 new mode 100755 diff --git a/src/secp256k1/src/secp256k1.c b/src/secp256k1/src/secp256k1.c old mode 100644 new mode 100755 diff --git a/src/secp256k1/src/testrand.h b/src/secp256k1/src/testrand.h old mode 100644 new mode 100755 diff --git a/src/secp256k1/src/testrand_impl.h b/src/secp256k1/src/testrand_impl.h old mode 100644 new mode 100755 diff --git a/src/secp256k1/src/tests.c b/src/secp256k1/src/tests.c old mode 100644 new mode 100755 diff --git a/src/secp256k1/src/tests_exhaustive.c b/src/secp256k1/src/tests_exhaustive.c old mode 100644 new mode 100755 diff --git a/src/secp256k1/src/util.h b/src/secp256k1/src/util.h old mode 100644 new mode 100755 diff --git a/src/sendalert.cpp b/src/sendalert.cpp old mode 100644 new mode 100755 diff --git a/src/serialize.h b/src/serialize.h old mode 100644 new mode 100755 index f776d6d99a5..4501103c9ec --- a/src/serialize.h +++ b/src/serialize.h @@ -95,6 +95,11 @@ template inline void ser_writedata32(Stream &s, uint32_t obj) obj = htole32(obj); s.write((char*)&obj, 4); } +template inline void ser_writedata32be(Stream &s, uint32_t obj) +{ + obj = htobe32(obj); + s.write((char*)&obj, 4); +} template inline void ser_writedata64(Stream &s, uint64_t obj) { obj = htole64(obj); @@ -118,6 +123,12 @@ template inline uint32_t ser_readdata32(Stream &s) s.read((char*)&obj, 4); return le32toh(obj); } +template inline uint32_t ser_readdata32be(Stream &s) +{ + uint32_t obj; + s.read((char*)&obj, 4); + return be32toh(obj); +} template inline uint64_t ser_readdata64(Stream &s) { uint64_t obj; diff --git a/src/spentindex.h b/src/spentindex.h new file mode 100755 index 00000000000..bd5da45d60d --- /dev/null +++ b/src/spentindex.h @@ -0,0 +1,98 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2015 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_SPENTINDEX_H +#define BITCOIN_SPENTINDEX_H + +#include "uint256.h" +#include "amount.h" + +struct CSpentIndexKey { + uint256 txid; + unsigned int outputIndex; + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { + READWRITE(txid); + READWRITE(outputIndex); + } + + CSpentIndexKey(uint256 t, unsigned int i) { + txid = t; + outputIndex = i; + } + + CSpentIndexKey() { + SetNull(); + } + + void SetNull() { + txid.SetNull(); + outputIndex = 0; + } + +}; + +struct CSpentIndexValue { + uint256 txid; + unsigned int inputIndex; + int blockHeight; + CAmount satoshis; + int addressType; + uint160 addressHash; + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { + READWRITE(txid); + READWRITE(inputIndex); + READWRITE(blockHeight); + READWRITE(satoshis); + READWRITE(addressType); + READWRITE(addressHash); + } + + CSpentIndexValue(uint256 t, unsigned int i, int h, CAmount s, int type, uint160 a) { + txid = t; + inputIndex = i; + blockHeight = h; + satoshis = s; + addressType = type; + addressHash = a; + } + + CSpentIndexValue() { + SetNull(); + } + + void SetNull() { + txid.SetNull(); + inputIndex = 0; + blockHeight = 0; + satoshis = 0; + addressType = 0; + addressHash.SetNull(); + } + + bool IsNull() const { + return txid.IsNull(); + } +}; + +struct CSpentIndexKeyCompare +{ + bool operator()(const CSpentIndexKey& a, const CSpentIndexKey& b) const { + if (a.txid == b.txid) { + return a.outputIndex < b.outputIndex; + } else { + return a.txid < b.txid; + } + } +}; + +#endif // BITCOIN_SPENTINDEX_H diff --git a/src/streams.h b/src/streams.h old mode 100644 new mode 100755 diff --git a/src/support/allocators/secure.h b/src/support/allocators/secure.h old mode 100644 new mode 100755 diff --git a/src/support/allocators/zeroafterfree.h b/src/support/allocators/zeroafterfree.h old mode 100644 new mode 100755 diff --git a/src/support/cleanse.cpp b/src/support/cleanse.cpp old mode 100644 new mode 100755 diff --git a/src/support/cleanse.h b/src/support/cleanse.h old mode 100644 new mode 100755 diff --git a/src/support/events.h b/src/support/events.h old mode 100644 new mode 100755 diff --git a/src/support/pagelocker.cpp b/src/support/pagelocker.cpp old mode 100644 new mode 100755 diff --git a/src/support/pagelocker.h b/src/support/pagelocker.h old mode 100644 new mode 100755 diff --git a/src/sync.cpp b/src/sync.cpp old mode 100644 new mode 100755 diff --git a/src/sync.h b/src/sync.h old mode 100644 new mode 100755 diff --git a/src/test/Checkpoints_tests.cpp b/src/test/Checkpoints_tests.cpp old mode 100644 new mode 100755 diff --git a/src/test/DoS_tests.cpp b/src/test/DoS_tests.cpp old mode 100644 new mode 100755 diff --git a/src/test/Makefile b/src/test/Makefile old mode 100644 new mode 100755 diff --git a/src/test/README.md b/src/test/README.md old mode 100644 new mode 100755 diff --git a/src/test/accounting_tests.cpp b/src/test/accounting_tests.cpp old mode 100644 new mode 100755 diff --git a/src/test/addrman_tests.cpp b/src/test/addrman_tests.cpp old mode 100644 new mode 100755 diff --git a/src/test/alert_tests.cpp b/src/test/alert_tests.cpp old mode 100644 new mode 100755 diff --git a/src/test/allocator_tests.cpp b/src/test/allocator_tests.cpp old mode 100644 new mode 100755 diff --git a/src/test/arith_uint256_tests.cpp b/src/test/arith_uint256_tests.cpp old mode 100644 new mode 100755 diff --git a/src/test/base32_tests.cpp b/src/test/base32_tests.cpp old mode 100644 new mode 100755 diff --git a/src/test/base58_tests.cpp b/src/test/base58_tests.cpp old mode 100644 new mode 100755 diff --git a/src/test/base64_tests.cpp b/src/test/base64_tests.cpp old mode 100644 new mode 100755 diff --git a/src/test/bctest.py b/src/test/bctest.py old mode 100644 new mode 100755 diff --git a/src/test/bignum.h b/src/test/bignum.h old mode 100644 new mode 100755 diff --git a/src/test/bip32_tests.cpp b/src/test/bip32_tests.cpp old mode 100644 new mode 100755 diff --git a/src/test/bloom_tests.cpp b/src/test/bloom_tests.cpp old mode 100644 new mode 100755 diff --git a/src/test/buildenv.py.in b/src/test/buildenv.py.in old mode 100644 new mode 100755 diff --git a/src/test/checkblock_tests.cpp b/src/test/checkblock_tests.cpp old mode 100644 new mode 100755 diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp old mode 100644 new mode 100755 diff --git a/src/test/compress_tests.cpp b/src/test/compress_tests.cpp old mode 100644 new mode 100755 diff --git a/src/test/crypto_tests.cpp b/src/test/crypto_tests.cpp old mode 100644 new mode 100755 diff --git a/src/test/data/README.md b/src/test/data/README.md old mode 100644 new mode 100755 diff --git a/src/test/data/alertTests.raw b/src/test/data/alertTests.raw old mode 100644 new mode 100755 diff --git a/src/test/data/base58_encode_decode.json b/src/test/data/base58_encode_decode.json old mode 100644 new mode 100755 diff --git a/src/test/data/base58_keys_invalid.json b/src/test/data/base58_keys_invalid.json old mode 100644 new mode 100755 diff --git a/src/test/data/base58_keys_valid.json b/src/test/data/base58_keys_valid.json old mode 100644 new mode 100755 diff --git a/src/test/data/bitcoin-util-test.json b/src/test/data/bitcoin-util-test.json old mode 100644 new mode 100755 diff --git a/src/test/data/blanktx.hex b/src/test/data/blanktx.hex old mode 100644 new mode 100755 diff --git a/src/test/data/g1_compressed.json b/src/test/data/g1_compressed.json old mode 100644 new mode 100755 diff --git a/src/test/data/g2_compressed.json b/src/test/data/g2_compressed.json old mode 100644 new mode 100755 diff --git a/src/test/data/merkle_commitments.json b/src/test/data/merkle_commitments.json old mode 100644 new mode 100755 diff --git a/src/test/data/merkle_path.json b/src/test/data/merkle_path.json old mode 100644 new mode 100755 diff --git a/src/test/data/merkle_roots.json b/src/test/data/merkle_roots.json old mode 100644 new mode 100755 diff --git a/src/test/data/merkle_roots_empty.json b/src/test/data/merkle_roots_empty.json old mode 100644 new mode 100755 diff --git a/src/test/data/merkle_serialization.json b/src/test/data/merkle_serialization.json old mode 100644 new mode 100755 diff --git a/src/test/data/merkle_witness_serialization.json b/src/test/data/merkle_witness_serialization.json old mode 100644 new mode 100755 diff --git a/src/test/data/script_invalid.json b/src/test/data/script_invalid.json old mode 100644 new mode 100755 diff --git a/src/test/data/script_valid.json b/src/test/data/script_valid.json old mode 100644 new mode 100755 diff --git a/src/test/data/sighash.json b/src/test/data/sighash.json old mode 100644 new mode 100755 diff --git a/src/test/data/tt-delin1-out.hex b/src/test/data/tt-delin1-out.hex old mode 100644 new mode 100755 diff --git a/src/test/data/tt-delout1-out.hex b/src/test/data/tt-delout1-out.hex old mode 100644 new mode 100755 diff --git a/src/test/data/tt-locktime317000-out.hex b/src/test/data/tt-locktime317000-out.hex old mode 100644 new mode 100755 diff --git a/src/test/data/tx394b54bb.hex b/src/test/data/tx394b54bb.hex old mode 100644 new mode 100755 diff --git a/src/test/data/tx_invalid.json b/src/test/data/tx_invalid.json old mode 100644 new mode 100755 diff --git a/src/test/data/tx_valid.json b/src/test/data/tx_valid.json old mode 100644 new mode 100755 diff --git a/src/test/data/txcreate1.hex b/src/test/data/txcreate1.hex old mode 100644 new mode 100755 diff --git a/src/test/data/txcreate2.hex b/src/test/data/txcreate2.hex old mode 100644 new mode 100755 diff --git a/src/test/data/txcreatesign.hex b/src/test/data/txcreatesign.hex old mode 100644 new mode 100755 diff --git a/src/test/equihash_tests.cpp b/src/test/equihash_tests.cpp old mode 100644 new mode 100755 diff --git a/src/test/getarg_tests.cpp b/src/test/getarg_tests.cpp old mode 100644 new mode 100755 diff --git a/src/test/hash_tests.cpp b/src/test/hash_tests.cpp old mode 100644 new mode 100755 diff --git a/src/test/key_tests.cpp b/src/test/key_tests.cpp old mode 100644 new mode 100755 diff --git a/src/test/main_tests.cpp b/src/test/main_tests.cpp old mode 100644 new mode 100755 diff --git a/src/test/mempool_tests.cpp b/src/test/mempool_tests.cpp old mode 100644 new mode 100755 diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp old mode 100644 new mode 100755 diff --git a/src/test/mruset_tests.cpp b/src/test/mruset_tests.cpp old mode 100644 new mode 100755 diff --git a/src/test/multisig_tests.cpp b/src/test/multisig_tests.cpp old mode 100644 new mode 100755 diff --git a/src/test/netbase_tests.cpp b/src/test/netbase_tests.cpp old mode 100644 new mode 100755 diff --git a/src/test/pmt_tests.cpp b/src/test/pmt_tests.cpp old mode 100644 new mode 100755 diff --git a/src/test/policyestimator_tests.cpp b/src/test/policyestimator_tests.cpp old mode 100644 new mode 100755 diff --git a/src/test/pow_tests.cpp b/src/test/pow_tests.cpp old mode 100644 new mode 100755 diff --git a/src/test/raii_event_tests.cpp b/src/test/raii_event_tests.cpp old mode 100644 new mode 100755 diff --git a/src/test/reverselock_tests.cpp b/src/test/reverselock_tests.cpp old mode 100644 new mode 100755 diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp old mode 100644 new mode 100755 diff --git a/src/test/rpc_wallet_tests.cpp b/src/test/rpc_wallet_tests.cpp old mode 100644 new mode 100755 diff --git a/src/test/sanity_tests.cpp b/src/test/sanity_tests.cpp old mode 100644 new mode 100755 diff --git a/src/test/scheduler_tests.cpp b/src/test/scheduler_tests.cpp old mode 100644 new mode 100755 diff --git a/src/test/script_P2PKH_tests.cpp b/src/test/script_P2PKH_tests.cpp new file mode 100644 index 00000000000..8fbb054b9f0 --- /dev/null +++ b/src/test/script_P2PKH_tests.cpp @@ -0,0 +1,59 @@ +// Copyright (c) 2012-2015 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "script/script.h" +#include "test/test_bitcoin.h" + +#include + +using namespace std; + +BOOST_FIXTURE_TEST_SUITE(script_P2PKH_tests, BasicTestingSetup) + +BOOST_AUTO_TEST_CASE(IsPayToPublicKeyHash) +{ + // Test CScript::IsPayToPublicKeyHash() + uint160 dummy; + CScript p2pkh; + p2pkh << OP_DUP << OP_HASH160 << ToByteVector(dummy) << OP_EQUALVERIFY << OP_CHECKSIG; + BOOST_CHECK(p2pkh.IsPayToPublicKeyHash()); + + static const unsigned char direct[] = { + OP_DUP, OP_HASH160, 20, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, OP_EQUALVERIFY, OP_CHECKSIG + }; + BOOST_CHECK(CScript(direct, direct+sizeof(direct)).IsPayToPublicKeyHash()); + + static const unsigned char notp2pkh1[] = { + OP_DUP, OP_HASH160, 20, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, OP_EQUALVERIFY, OP_CHECKSIG, OP_CHECKSIG + }; + BOOST_CHECK(!CScript(notp2pkh1, notp2pkh1+sizeof(notp2pkh1)).IsPayToPublicKeyHash()); + + static const unsigned char p2sh[] = { + OP_HASH160, 20, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, OP_EQUAL + }; + BOOST_CHECK(!CScript(p2sh, p2sh+sizeof(p2sh)).IsPayToPublicKeyHash()); + + static const unsigned char extra[] = { + OP_DUP, OP_HASH160, 20, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, OP_EQUALVERIFY, OP_CHECKSIG, OP_CHECKSIG + }; + BOOST_CHECK(!CScript(extra, extra+sizeof(extra)).IsPayToPublicKeyHash()); + + static const unsigned char missing[] = { + OP_HASH160, 20, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, OP_EQUALVERIFY, OP_CHECKSIG, OP_RETURN + }; + BOOST_CHECK(!CScript(missing, missing+sizeof(missing)).IsPayToPublicKeyHash()); + + static const unsigned char missing2[] = { + OP_DUP, OP_HASH160, 20, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + }; + BOOST_CHECK(!CScript(missing2, missing2+sizeof(missing)).IsPayToPublicKeyHash()); + + static const unsigned char tooshort[] = { + OP_DUP, OP_HASH160, 2, 0,0, OP_EQUALVERIFY, OP_CHECKSIG + }; + BOOST_CHECK(!CScript(tooshort, tooshort+sizeof(direct)).IsPayToPublicKeyHash()); + +} + +BOOST_AUTO_TEST_SUITE_END() \ No newline at end of file diff --git a/src/test/script_P2SH_tests.cpp b/src/test/script_P2SH_tests.cpp old mode 100644 new mode 100755 diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp old mode 100644 new mode 100755 diff --git a/src/test/scriptnum_tests.cpp b/src/test/scriptnum_tests.cpp old mode 100644 new mode 100755 diff --git a/src/test/serialize_tests.cpp b/src/test/serialize_tests.cpp old mode 100644 new mode 100755 diff --git a/src/test/sha256compress_tests.cpp b/src/test/sha256compress_tests.cpp old mode 100644 new mode 100755 diff --git a/src/test/sighash_tests.cpp b/src/test/sighash_tests.cpp old mode 100644 new mode 100755 diff --git a/src/test/sigopcount_tests.cpp b/src/test/sigopcount_tests.cpp old mode 100644 new mode 100755 diff --git a/src/test/skiplist_tests.cpp b/src/test/skiplist_tests.cpp old mode 100644 new mode 100755 diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp old mode 100644 new mode 100755 diff --git a/src/test/test_bitcoin.h b/src/test/test_bitcoin.h old mode 100644 new mode 100755 index 205e5b5c46c..5ed340d0b73 --- a/src/test/test_bitcoin.h +++ b/src/test/test_bitcoin.h @@ -1,6 +1,7 @@ #ifndef BITCOIN_TEST_TEST_BITCOIN_H #define BITCOIN_TEST_TEST_BITCOIN_H +#include "chainparamsbase.h" #include "pubkey.h" #include "txdb.h" diff --git a/src/test/timedata_tests.cpp b/src/test/timedata_tests.cpp old mode 100644 new mode 100755 diff --git a/src/test/torcontrol_tests.cpp b/src/test/torcontrol_tests.cpp old mode 100644 new mode 100755 diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp old mode 100644 new mode 100755 diff --git a/src/test/uint256_tests.cpp b/src/test/uint256_tests.cpp old mode 100644 new mode 100755 diff --git a/src/test/univalue_tests.cpp b/src/test/univalue_tests.cpp old mode 100644 new mode 100755 diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp old mode 100644 new mode 100755 diff --git a/src/test/wallet-utility.py b/src/test/wallet-utility.py new file mode 100644 index 00000000000..c0a7bfb9ea9 --- /dev/null +++ b/src/test/wallet-utility.py @@ -0,0 +1,61 @@ +#!/usr/bin/python +# Copyright 2014 BitPay, Inc. +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +import subprocess +import os +import json +import sys +import buildenv +import shutil + +def assert_equal(thing1, thing2): + if thing1 != thing2: + raise AssertionError("%s != %s"%(str(thing1),str(thing2))) + +if __name__ == '__main__': + datadir = os.environ["srcdir"] + "/test/data" + execprog = './wallet-utility' + buildenv.exeext + execargs = '-datadir=' + datadir + execrun = execprog + ' ' + execargs + + proc = subprocess.Popen(execrun, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, shell=True) + try: + outs = proc.communicate() + except OSError: + print("OSError, Failed to execute " + execprog) + sys.exit(1) + + output = json.loads(outs[0]) + + assert_equal(output[0], "13EngsxkRi7SJPPqCyJsKf34U8FoX9E9Av") + assert_equal(output[1], "1FKCLGTpPeYBUqfNxktck8k5nqxB8sjim8") + assert_equal(output[2], "13cdtE9tnNeXCZJ8KQ5WELgEmLSBLnr48F") + + execargs = '-datadir=' + datadir + ' -dumppass' + execrun = execprog + ' ' + execargs + + proc = subprocess.Popen(execrun, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, shell=True) + try: + outs = proc.communicate() + except OSError: + print("OSError, Failed to execute " + execprog) + sys.exit(1) + + output = json.loads(outs[0]) + + assert_equal(output[0]['addr'], "13EngsxkRi7SJPPqCyJsKf34U8FoX9E9Av") + assert_equal(output[0]['pkey'], "5Jz5BWE2WQxp1hGqDZeisQFV1mRFR2AVBAgiXCbNcZyXNjD9aUd") + assert_equal(output[1]['addr'], "1FKCLGTpPeYBUqfNxktck8k5nqxB8sjim8") + assert_equal(output[1]['pkey'], "5HsX2b3v2GjngYQ5ZM4mLp2b2apw6aMNVaPELV1YmpiYR1S4jzc") + assert_equal(output[2]['addr'], "13cdtE9tnNeXCZJ8KQ5WELgEmLSBLnr48F") + assert_equal(output[2]['pkey'], "5KCWAs1wX2ESiL4PfDR8XYVSSETHFd2jaRGxt1QdanBFTit4XcH") + + if os.path.exists(datadir + '/database'): + if os.path.isdir(datadir + '/database'): + shutil.rmtree(datadir + '/database') + + if os.path.exists(datadir + '/db.log'): + os.remove(datadir + '/db.log') + sys.exit(0) \ No newline at end of file diff --git a/src/threadsafety.h b/src/threadsafety.h old mode 100644 new mode 100755 diff --git a/src/timedata.cpp b/src/timedata.cpp old mode 100644 new mode 100755 diff --git a/src/timedata.h b/src/timedata.h old mode 100644 new mode 100755 diff --git a/src/tinyformat.h b/src/tinyformat.h old mode 100644 new mode 100755 diff --git a/src/torcontrol.cpp b/src/torcontrol.cpp old mode 100644 new mode 100755 diff --git a/src/torcontrol.h b/src/torcontrol.h old mode 100644 new mode 100755 diff --git a/src/txdb.cpp b/src/txdb.cpp old mode 100644 new mode 100755 index 8ad9ffc9d6c..4183691a89a --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -22,6 +22,12 @@ static const char DB_NULLIFIER = 's'; static const char DB_COINS = 'c'; static const char DB_BLOCK_FILES = 'f'; static const char DB_TXINDEX = 't'; + +static const char DB_ADDRESSINDEX = 'd'; +static const char DB_ADDRESSUNSPENTINDEX = 'u'; +static const char DB_TIMESTAMPINDEX = 'S'; +static const char DB_BLOCKHASHINDEX = 'z'; +static const char DB_SPENTINDEX = 'p'; static const char DB_BLOCK_INDEX = 'b'; static const char DB_BEST_BLOCK = 'B'; @@ -65,10 +71,10 @@ void static BatchWriteHashBestAnchor(CLevelDBBatch &batch, const uint256 &hash) batch.Write(DB_BEST_ANCHOR, hash); } -CCoinsViewDB::CCoinsViewDB(std::string dbName, size_t nCacheSize, bool fMemory, bool fWipe) : db(GetDataDir() / dbName, nCacheSize, fMemory, fWipe) { +CCoinsViewDB::CCoinsViewDB(std::string dbName, size_t nCacheSize, bool fMemory, bool fWipe) : db(GetDataDir() / dbName, nCacheSize, fMemory, fWipe, false, 64) { } -CCoinsViewDB::CCoinsViewDB(size_t nCacheSize, bool fMemory, bool fWipe) : db(GetDataDir() / "chainstate", nCacheSize, fMemory, fWipe) { +CCoinsViewDB::CCoinsViewDB(size_t nCacheSize, bool fMemory, bool fWipe) : db(GetDataDir() / "chainstate", nCacheSize, fMemory, fWipe, false, 64) { } @@ -158,7 +164,7 @@ bool CCoinsViewDB::BatchWrite(CCoinsMap &mapCoins, return db.WriteBatch(batch); } -CBlockTreeDB::CBlockTreeDB(size_t nCacheSize, bool fMemory, bool fWipe) : CLevelDBWrapper(GetDataDir() / "blocks" / "index", nCacheSize, fMemory, fWipe) { +CBlockTreeDB::CBlockTreeDB(size_t nCacheSize, bool fMemory, bool fWipe, bool compression, int maxOpenFiles) : CLevelDBWrapper(GetDataDir() / "blocks" / "index", nCacheSize, fMemory, fWipe, compression, maxOpenFiles) { } bool CBlockTreeDB::ReadBlockFileInfo(int nFile, CBlockFileInfo &info) { @@ -260,6 +266,197 @@ bool CBlockTreeDB::WriteTxIndex(const std::vector return WriteBatch(batch); } +bool CBlockTreeDB::ReadSpentIndex(CSpentIndexKey &key, CSpentIndexValue &value) { + return Read(make_pair(DB_SPENTINDEX, key), value); +} + +bool CBlockTreeDB::UpdateSpentIndex(const std::vector >&vect) { + CLevelDBBatch batch; + for (std::vector >::const_iterator it=vect.begin(); it!=vect.end(); it++) { + if (it->second.IsNull()) { + batch.Erase(make_pair(DB_SPENTINDEX, it->first)); + } else { + batch.Write(make_pair(DB_SPENTINDEX, it->first), it->second); + } + } + return WriteBatch(batch); +} + +bool CBlockTreeDB::UpdateAddressUnspentIndex(const std::vector >&vect) { + CLevelDBBatch batch; + for (std::vector >::const_iterator it=vect.begin(); it!=vect.end(); it++) { + if (it->second.IsNull()) { + batch.Erase(make_pair(DB_ADDRESSUNSPENTINDEX, it->first)); + } else { + batch.Write(make_pair(DB_ADDRESSUNSPENTINDEX, it->first), it->second); + } + } + return WriteBatch(batch); +} + +bool CBlockTreeDB::ReadAddressUnspentIndex(uint160 addressHash, int type, + std::vector > &unspentOutputs) { + + boost::scoped_ptr pcursor(NewIterator()); + + CDataStream ssKeySet(SER_DISK, CLIENT_VERSION); + ssKeySet << make_pair(DB_ADDRESSUNSPENTINDEX, CAddressIndexIteratorKey(type, addressHash)); + pcursor->Seek(ssKeySet.str()); + + while (pcursor->Valid()) { + boost::this_thread::interruption_point(); + try { + leveldb::Slice slKey = pcursor->key(); + CDataStream ssKey(slKey.data(), slKey.data()+slKey.size(), SER_DISK, CLIENT_VERSION); + char chType; + CAddressUnspentKey indexKey; + ssKey >> chType; + ssKey >> indexKey; + if (chType == DB_ADDRESSUNSPENTINDEX && indexKey.hashBytes == addressHash) { + try { + leveldb::Slice slValue = pcursor->value(); + CDataStream ssValue(slValue.data(), slValue.data()+slValue.size(), SER_DISK, CLIENT_VERSION); + CAddressUnspentValue nValue; + ssValue >> nValue; + unspentOutputs.push_back(make_pair(indexKey, nValue)); + pcursor->Next(); + } catch (const std::exception& e) { + return error("failed to get address unspent value"); + } + } else { + break; + } + } catch (const std::exception& e) { + break; + } + } + + return true; +} + +bool CBlockTreeDB::WriteAddressIndex(const std::vector >&vect) { + CLevelDBBatch batch; + for (std::vector >::const_iterator it=vect.begin(); it!=vect.end(); it++) + batch.Write(make_pair(DB_ADDRESSINDEX, it->first), it->second); + return WriteBatch(batch); +} + +bool CBlockTreeDB::EraseAddressIndex(const std::vector >&vect) { + CLevelDBBatch batch; + for (std::vector >::const_iterator it=vect.begin(); it!=vect.end(); it++) + batch.Erase(make_pair(DB_ADDRESSINDEX, it->first)); + return WriteBatch(batch); +} + +bool CBlockTreeDB::ReadAddressIndex(uint160 addressHash, int type, + std::vector > &addressIndex, + int start, int end) { + + boost::scoped_ptr pcursor(NewIterator()); + + CDataStream ssKeySet(SER_DISK, CLIENT_VERSION); + if (start > 0 && end > 0) { + ssKeySet << make_pair(DB_ADDRESSINDEX, CAddressIndexIteratorHeightKey(type, addressHash, start)); + } else { + ssKeySet << make_pair(DB_ADDRESSINDEX, CAddressIndexIteratorKey(type, addressHash)); + } + pcursor->Seek(ssKeySet.str()); + + while (pcursor->Valid()) { + boost::this_thread::interruption_point(); + try { + leveldb::Slice slKey = pcursor->key(); + CDataStream ssKey(slKey.data(), slKey.data()+slKey.size(), SER_DISK, CLIENT_VERSION); + char chType; + CAddressIndexKey indexKey; + ssKey >> chType; + ssKey >> indexKey; + if (chType == DB_ADDRESSINDEX && indexKey.hashBytes == addressHash) { + if (end > 0 && indexKey.blockHeight > end) { + break; + } + try { + leveldb::Slice slValue = pcursor->value(); + CDataStream ssValue(slValue.data(), slValue.data()+slValue.size(), SER_DISK, CLIENT_VERSION); + CAmount nValue; + ssValue >> nValue; + + addressIndex.push_back(make_pair(indexKey, nValue)); + pcursor->Next(); + } catch (const std::exception& e) { + return error("failed to get address index value"); + } + } else { + break; + } + } catch (const std::exception& e) { + break; + } + } + + return true; +} + +bool CBlockTreeDB::WriteTimestampIndex(const CTimestampIndexKey ×tampIndex) { + CLevelDBBatch batch; + batch.Write(make_pair(DB_TIMESTAMPINDEX, timestampIndex), 0); + return WriteBatch(batch); +} + +bool CBlockTreeDB::ReadTimestampIndex(const unsigned int &high, const unsigned int &low, const bool fActiveOnly, std::vector > &hashes) { + + boost::scoped_ptr pcursor(NewIterator()); + + CDataStream ssKeySet(SER_DISK, CLIENT_VERSION); + ssKeySet << make_pair(DB_TIMESTAMPINDEX, CTimestampIndexIteratorKey(low)); + pcursor->Seek(ssKeySet.str()); + + while (pcursor->Valid()) { + boost::this_thread::interruption_point(); + try { + leveldb::Slice slKey = pcursor->key(); + CDataStream ssKey(slKey.data(), slKey.data()+slKey.size(), SER_DISK, CLIENT_VERSION); + char chType; + CTimestampIndexKey indexKey; + ssKey >> chType; + ssKey >> indexKey; + if (chType == DB_TIMESTAMPINDEX && indexKey.timestamp < high) { + if (fActiveOnly) { + if (blockOnchainActive(indexKey.blockHash)) { + hashes.push_back(std::make_pair(indexKey.blockHash, indexKey.timestamp)); + } + } else { + hashes.push_back(std::make_pair(indexKey.blockHash, indexKey.timestamp)); + } + + pcursor->Next(); + } else { + break; + } + } catch (const std::exception& e) { + break; + } + } + + return true; +} + +bool CBlockTreeDB::WriteTimestampBlockIndex(const CTimestampBlockIndexKey &blockhashIndex, const CTimestampBlockIndexValue &logicalts) { + CLevelDBBatch batch; + batch.Write(make_pair(DB_BLOCKHASHINDEX, blockhashIndex), logicalts); + return WriteBatch(batch); +} + +bool CBlockTreeDB::ReadTimestampBlockIndex(const uint256 &hash, unsigned int <imestamp) { + + CTimestampBlockIndexValue(lts); + if (!Read(std::make_pair(DB_BLOCKHASHINDEX, hash), lts)) + return false; + + ltimestamp = lts.ltimestamp; + return true; +} + bool CBlockTreeDB::WriteFlag(const std::string &name, bool fValue) { return Write(std::make_pair(DB_FLAG, name), fValue ? '1' : '0'); } @@ -272,6 +469,16 @@ bool CBlockTreeDB::ReadFlag(const std::string &name, bool &fValue) { return true; } +bool CBlockTreeDB::blockOnchainActive(const uint256 &hash) { + CBlockIndex* pblockindex = mapBlockIndex[hash]; + + if (!chainActive.Contains(pblockindex)) { + return false; + } + + return true; +} + bool CBlockTreeDB::LoadBlockIndexGuts() { boost::scoped_ptr pcursor(NewIterator()); diff --git a/src/txdb.h b/src/txdb.h old mode 100644 new mode 100755 index a2764b8c2d5..c93f692462c --- a/src/txdb.h +++ b/src/txdb.h @@ -17,6 +17,17 @@ class CBlockFileInfo; class CBlockIndex; struct CDiskTxPos; +struct CAddressUnspentKey; +struct CAddressUnspentValue; +struct CAddressIndexKey; +struct CAddressIndexIteratorKey; +struct CAddressIndexIteratorHeightKey; +struct CTimestampIndexKey; +struct CTimestampIndexIteratorKey; +struct CTimestampBlockIndexKey; +struct CTimestampBlockIndexValue; +struct CSpentIndexKey; +struct CSpentIndexValue; class uint256; //! -dbcache default (MiB) @@ -53,7 +64,7 @@ class CCoinsViewDB : public CCoinsView class CBlockTreeDB : public CLevelDBWrapper { public: - CBlockTreeDB(size_t nCacheSize, bool fMemory = false, bool fWipe = false); + CBlockTreeDB(size_t nCacheSize, bool fMemory = false, bool fWipe = false, bool compression = true, int maxOpenFiles = 1000); private: CBlockTreeDB(const CBlockTreeDB&); void operator=(const CBlockTreeDB&); @@ -65,9 +76,24 @@ class CBlockTreeDB : public CLevelDBWrapper bool ReadReindexing(bool &fReindex); bool ReadTxIndex(const uint256 &txid, CDiskTxPos &pos); bool WriteTxIndex(const std::vector > &list); + bool ReadSpentIndex(CSpentIndexKey &key, CSpentIndexValue &value); + bool UpdateSpentIndex(const std::vector >&vect); + bool UpdateAddressUnspentIndex(const std::vector >&vect); + bool ReadAddressUnspentIndex(uint160 addressHash, int type, + std::vector > &vect); + bool WriteAddressIndex(const std::vector > &vect); + bool EraseAddressIndex(const std::vector > &vect); + bool ReadAddressIndex(uint160 addressHash, int type, + std::vector > &addressIndex, + int start = 0, int end = 0); + bool WriteTimestampIndex(const CTimestampIndexKey ×tampIndex); + bool ReadTimestampIndex(const unsigned int &high, const unsigned int &low, const bool fActiveOnly, std::vector > &vect); + bool WriteTimestampBlockIndex(const CTimestampBlockIndexKey &blockhashIndex, const CTimestampBlockIndexValue &logicalts); + bool ReadTimestampBlockIndex(const uint256 &hash, unsigned int &logicalTS); bool WriteFlag(const std::string &name, bool fValue); bool ReadFlag(const std::string &name, bool &fValue); bool LoadBlockIndexGuts(); + bool blockOnchainActive(const uint256 &hash); }; #endif // BITCOIN_TXDB_H diff --git a/src/txmempool.cpp b/src/txmempool.cpp old mode 100644 new mode 100755 index ed565323099..71dcab0d6b9 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -113,6 +113,144 @@ bool CTxMemPool::addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry, return true; } +void CTxMemPool::addAddressIndex(const CTxMemPoolEntry &entry, const CCoinsViewCache &view) +{ + LOCK(cs); + const CTransaction& tx = entry.GetTx(); + std::vector inserted; + + uint256 txhash = tx.GetHash(); + for (unsigned int j = 0; j < tx.vin.size(); j++) { + const CTxIn input = tx.vin[j]; + const CTxOut &prevout = view.GetOutputFor(input); + if (prevout.scriptPubKey.IsPayToScriptHash()) { + vector hashBytes(prevout.scriptPubKey.begin()+2, prevout.scriptPubKey.begin()+22); + CMempoolAddressDeltaKey key(2, uint160(hashBytes), txhash, j, 1); + CMempoolAddressDelta delta(entry.GetTime(), prevout.nValue * -1, input.prevout.hash, input.prevout.n); + mapAddress.insert(make_pair(key, delta)); + inserted.push_back(key); + } else if (prevout.scriptPubKey.IsPayToPublicKeyHash()) { + vector hashBytes(prevout.scriptPubKey.begin()+3, prevout.scriptPubKey.begin()+23); + CMempoolAddressDeltaKey key(1, uint160(hashBytes), txhash, j, 1); + CMempoolAddressDelta delta(entry.GetTime(), prevout.nValue * -1, input.prevout.hash, input.prevout.n); + mapAddress.insert(make_pair(key, delta)); + inserted.push_back(key); + } + } + + for (unsigned int k = 0; k < tx.vout.size(); k++) { + const CTxOut &out = tx.vout[k]; + if (out.scriptPubKey.IsPayToScriptHash()) { + vector hashBytes(out.scriptPubKey.begin()+2, out.scriptPubKey.begin()+22); + CMempoolAddressDeltaKey key(2, uint160(hashBytes), txhash, k, 0); + mapAddress.insert(make_pair(key, CMempoolAddressDelta(entry.GetTime(), out.nValue))); + inserted.push_back(key); + } else if (out.scriptPubKey.IsPayToPublicKeyHash()) { + vector hashBytes(out.scriptPubKey.begin()+3, out.scriptPubKey.begin()+23); + std::pair ret; + CMempoolAddressDeltaKey key(1, uint160(hashBytes), txhash, k, 0); + mapAddress.insert(make_pair(key, CMempoolAddressDelta(entry.GetTime(), out.nValue))); + inserted.push_back(key); + } + } + + mapAddressInserted.insert(make_pair(txhash, inserted)); +} + +bool CTxMemPool::getAddressIndex(std::vector > &addresses, + std::vector > &results) +{ + LOCK(cs); + for (std::vector >::iterator it = addresses.begin(); it != addresses.end(); it++) { + addressDeltaMap::iterator ait = mapAddress.lower_bound(CMempoolAddressDeltaKey((*it).second, (*it).first)); + while (ait != mapAddress.end() && (*ait).first.addressBytes == (*it).first && (*ait).first.type == (*it).second) { + results.push_back(*ait); + ait++; + } + } + return true; +} + +bool CTxMemPool::removeAddressIndex(const uint256 txhash) +{ + LOCK(cs); + addressDeltaMapInserted::iterator it = mapAddressInserted.find(txhash); + + if (it != mapAddressInserted.end()) { + std::vector keys = (*it).second; + for (std::vector::iterator mit = keys.begin(); mit != keys.end(); mit++) { + mapAddress.erase(*mit); + } + mapAddressInserted.erase(it); + } + + return true; +} + +void CTxMemPool::addSpentIndex(const CTxMemPoolEntry &entry, const CCoinsViewCache &view) +{ + LOCK(cs); + + const CTransaction& tx = entry.GetTx(); + std::vector inserted; + + uint256 txhash = tx.GetHash(); + for (unsigned int j = 0; j < tx.vin.size(); j++) { + const CTxIn input = tx.vin[j]; + const CTxOut &prevout = view.GetOutputFor(input); + uint160 addressHash; + int addressType; + + if (prevout.scriptPubKey.IsPayToScriptHash()) { + addressHash = uint160(vector (prevout.scriptPubKey.begin()+2, prevout.scriptPubKey.begin()+22)); + addressType = 2; + } else if (prevout.scriptPubKey.IsPayToPublicKeyHash()) { + addressHash = uint160(vector (prevout.scriptPubKey.begin()+3, prevout.scriptPubKey.begin()+23)); + addressType = 1; + } else { + addressHash.SetNull(); + addressType = 0; + } + + CSpentIndexKey key = CSpentIndexKey(input.prevout.hash, input.prevout.n); + CSpentIndexValue value = CSpentIndexValue(txhash, j, -1, prevout.nValue, addressType, addressHash); + + mapSpent.insert(make_pair(key, value)); + inserted.push_back(key); + + } + + mapSpentInserted.insert(make_pair(txhash, inserted)); +} + +bool CTxMemPool::getSpentIndex(CSpentIndexKey &key, CSpentIndexValue &value) +{ + LOCK(cs); + mapSpentIndex::iterator it; + + it = mapSpent.find(key); + if (it != mapSpent.end()) { + value = it->second; + return true; + } + return false; +} + +bool CTxMemPool::removeSpentIndex(const uint256 txhash) +{ + LOCK(cs); + mapSpentIndexInserted::iterator it = mapSpentInserted.find(txhash); + + if (it != mapSpentInserted.end()) { + std::vector keys = (*it).second; + for (std::vector::iterator mit = keys.begin(); mit != keys.end(); mit++) { + mapSpent.erase(*mit); + } + mapSpentInserted.erase(it); + } + + return true; +} void CTxMemPool::remove(const CTransaction &origTx, std::list& removed, bool fRecursive) { @@ -162,6 +300,8 @@ void CTxMemPool::remove(const CTransaction &origTx, std::list& rem mapTx.erase(hash); nTransactionsUpdated++; minerPolicyEstimator->removeTx(hash); + removeAddressIndex(hash); + removeSpentIndex(hash); } } } diff --git a/src/txmempool.h b/src/txmempool.h old mode 100644 new mode 100755 index cd0f9a54bf4..b7320115d77 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -8,6 +8,8 @@ #include +#include "addressindex.h" +#include "spentindex.h" #include "amount.h" #include "coins.h" #include "primitives/transaction.h" @@ -101,6 +103,21 @@ class CTxMemPool public: mutable CCriticalSection cs; std::map mapTx; + +private: + typedef std::map addressDeltaMap; + addressDeltaMap mapAddress; + + typedef std::map > addressDeltaMapInserted; + addressDeltaMapInserted mapAddressInserted; + + typedef std::map mapSpentIndex; + mapSpentIndex mapSpent; + + typedef std::map > mapSpentIndexInserted; + mapSpentIndexInserted mapSpentInserted; + +public: std::map mapNextTx; std::map mapNullifiers; std::map > mapDeltas; @@ -118,6 +135,16 @@ class CTxMemPool void setSanityCheck(bool _fSanityCheck) { fSanityCheck = _fSanityCheck; } bool addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry, bool fCurrentEstimate = true); + + void addAddressIndex(const CTxMemPoolEntry &entry, const CCoinsViewCache &view); + bool getAddressIndex(std::vector > &addresses, + std::vector > &results); + bool removeAddressIndex(const uint256 txhash); + + void addSpentIndex(const CTxMemPoolEntry &entry, const CCoinsViewCache &view); + bool getSpentIndex(CSpentIndexKey &key, CSpentIndexValue &value); + bool removeSpentIndex(const uint256 txhash); + void remove(const CTransaction &tx, std::list& removed, bool fRecursive = false); void removeWithAnchor(const uint256 &invalidRoot); void removeCoinbaseSpends(const CCoinsViewCache *pcoins, unsigned int nMemPoolHeight); diff --git a/src/ui_interface.h b/src/ui_interface.h old mode 100644 new mode 100755 diff --git a/src/uint252.h b/src/uint252.h old mode 100644 new mode 100755 diff --git a/src/uint256.cpp b/src/uint256.cpp old mode 100644 new mode 100755 diff --git a/src/uint256.h b/src/uint256.h old mode 100644 new mode 100755 diff --git a/src/undo.h b/src/undo.h old mode 100644 new mode 100755 diff --git a/src/univalue/.gitignore b/src/univalue/.gitignore old mode 100644 new mode 100755 diff --git a/src/univalue/.travis.yml b/src/univalue/.travis.yml old mode 100644 new mode 100755 diff --git a/src/univalue/COPYING b/src/univalue/COPYING old mode 100644 new mode 100755 diff --git a/src/univalue/Makefile.am b/src/univalue/Makefile.am old mode 100644 new mode 100755 diff --git a/src/univalue/README b/src/univalue/README old mode 100644 new mode 100755 diff --git a/src/univalue/TODO b/src/univalue/TODO old mode 100644 new mode 100755 diff --git a/src/univalue/build-aux/m4/.gitignore b/src/univalue/build-aux/m4/.gitignore old mode 100644 new mode 100755 diff --git a/src/univalue/configure.ac b/src/univalue/configure.ac old mode 100644 new mode 100755 diff --git a/src/univalue/gen/gen.cpp b/src/univalue/gen/gen.cpp old mode 100644 new mode 100755 diff --git a/src/univalue/include/univalue.h b/src/univalue/include/univalue.h old mode 100644 new mode 100755 diff --git a/src/univalue/lib/.gitignore b/src/univalue/lib/.gitignore old mode 100644 new mode 100755 diff --git a/src/univalue/lib/univalue.cpp b/src/univalue/lib/univalue.cpp old mode 100644 new mode 100755 diff --git a/src/univalue/lib/univalue_escapes.h b/src/univalue/lib/univalue_escapes.h old mode 100644 new mode 100755 diff --git a/src/univalue/lib/univalue_read.cpp b/src/univalue/lib/univalue_read.cpp old mode 100644 new mode 100755 diff --git a/src/univalue/lib/univalue_utffilter.h b/src/univalue/lib/univalue_utffilter.h old mode 100644 new mode 100755 diff --git a/src/univalue/lib/univalue_write.cpp b/src/univalue/lib/univalue_write.cpp old mode 100644 new mode 100755 diff --git a/src/univalue/pc/libunivalue-uninstalled.pc.in b/src/univalue/pc/libunivalue-uninstalled.pc.in old mode 100644 new mode 100755 diff --git a/src/univalue/pc/libunivalue.pc.in b/src/univalue/pc/libunivalue.pc.in old mode 100644 new mode 100755 diff --git a/src/univalue/test/.gitignore b/src/univalue/test/.gitignore old mode 100644 new mode 100755 diff --git a/src/univalue/test/fail1.json b/src/univalue/test/fail1.json old mode 100644 new mode 100755 diff --git a/src/univalue/test/fail10.json b/src/univalue/test/fail10.json old mode 100644 new mode 100755 diff --git a/src/univalue/test/fail11.json b/src/univalue/test/fail11.json old mode 100644 new mode 100755 diff --git a/src/univalue/test/fail12.json b/src/univalue/test/fail12.json old mode 100644 new mode 100755 diff --git a/src/univalue/test/fail13.json b/src/univalue/test/fail13.json old mode 100644 new mode 100755 diff --git a/src/univalue/test/fail14.json b/src/univalue/test/fail14.json old mode 100644 new mode 100755 diff --git a/src/univalue/test/fail15.json b/src/univalue/test/fail15.json old mode 100644 new mode 100755 diff --git a/src/univalue/test/fail16.json b/src/univalue/test/fail16.json old mode 100644 new mode 100755 diff --git a/src/univalue/test/fail17.json b/src/univalue/test/fail17.json old mode 100644 new mode 100755 diff --git a/src/univalue/test/fail18.json b/src/univalue/test/fail18.json old mode 100644 new mode 100755 diff --git a/src/univalue/test/fail19.json b/src/univalue/test/fail19.json old mode 100644 new mode 100755 diff --git a/src/univalue/test/fail2.json b/src/univalue/test/fail2.json old mode 100644 new mode 100755 diff --git a/src/univalue/test/fail20.json b/src/univalue/test/fail20.json old mode 100644 new mode 100755 diff --git a/src/univalue/test/fail21.json b/src/univalue/test/fail21.json old mode 100644 new mode 100755 diff --git a/src/univalue/test/fail22.json b/src/univalue/test/fail22.json old mode 100644 new mode 100755 diff --git a/src/univalue/test/fail23.json b/src/univalue/test/fail23.json old mode 100644 new mode 100755 diff --git a/src/univalue/test/fail24.json b/src/univalue/test/fail24.json old mode 100644 new mode 100755 diff --git a/src/univalue/test/fail25.json b/src/univalue/test/fail25.json old mode 100644 new mode 100755 diff --git a/src/univalue/test/fail26.json b/src/univalue/test/fail26.json old mode 100644 new mode 100755 diff --git a/src/univalue/test/fail27.json b/src/univalue/test/fail27.json old mode 100644 new mode 100755 diff --git a/src/univalue/test/fail28.json b/src/univalue/test/fail28.json old mode 100644 new mode 100755 diff --git a/src/univalue/test/fail29.json b/src/univalue/test/fail29.json old mode 100644 new mode 100755 diff --git a/src/univalue/test/fail3.json b/src/univalue/test/fail3.json old mode 100644 new mode 100755 diff --git a/src/univalue/test/fail30.json b/src/univalue/test/fail30.json old mode 100644 new mode 100755 diff --git a/src/univalue/test/fail31.json b/src/univalue/test/fail31.json old mode 100644 new mode 100755 diff --git a/src/univalue/test/fail32.json b/src/univalue/test/fail32.json old mode 100644 new mode 100755 diff --git a/src/univalue/test/fail33.json b/src/univalue/test/fail33.json old mode 100644 new mode 100755 diff --git a/src/univalue/test/fail34.json b/src/univalue/test/fail34.json old mode 100644 new mode 100755 diff --git a/src/univalue/test/fail35.json b/src/univalue/test/fail35.json old mode 100644 new mode 100755 diff --git a/src/univalue/test/fail36.json b/src/univalue/test/fail36.json old mode 100644 new mode 100755 diff --git a/src/univalue/test/fail37.json b/src/univalue/test/fail37.json old mode 100644 new mode 100755 diff --git a/src/univalue/test/fail38.json b/src/univalue/test/fail38.json old mode 100644 new mode 100755 diff --git a/src/univalue/test/fail39.json b/src/univalue/test/fail39.json old mode 100644 new mode 100755 diff --git a/src/univalue/test/fail4.json b/src/univalue/test/fail4.json old mode 100644 new mode 100755 diff --git a/src/univalue/test/fail40.json b/src/univalue/test/fail40.json old mode 100644 new mode 100755 diff --git a/src/univalue/test/fail41.json b/src/univalue/test/fail41.json old mode 100644 new mode 100755 diff --git a/src/univalue/test/fail42.json b/src/univalue/test/fail42.json old mode 100644 new mode 100755 diff --git a/src/univalue/test/fail5.json b/src/univalue/test/fail5.json old mode 100644 new mode 100755 diff --git a/src/univalue/test/fail6.json b/src/univalue/test/fail6.json old mode 100644 new mode 100755 diff --git a/src/univalue/test/fail7.json b/src/univalue/test/fail7.json old mode 100644 new mode 100755 diff --git a/src/univalue/test/fail8.json b/src/univalue/test/fail8.json old mode 100644 new mode 100755 diff --git a/src/univalue/test/fail9.json b/src/univalue/test/fail9.json old mode 100644 new mode 100755 diff --git a/src/univalue/test/no_nul.cpp b/src/univalue/test/no_nul.cpp old mode 100644 new mode 100755 diff --git a/src/univalue/test/pass1.json b/src/univalue/test/pass1.json old mode 100644 new mode 100755 diff --git a/src/univalue/test/pass2.json b/src/univalue/test/pass2.json old mode 100644 new mode 100755 diff --git a/src/univalue/test/pass3.json b/src/univalue/test/pass3.json old mode 100644 new mode 100755 diff --git a/src/univalue/test/round1.json b/src/univalue/test/round1.json old mode 100644 new mode 100755 diff --git a/src/univalue/test/round2.json b/src/univalue/test/round2.json old mode 100644 new mode 100755 diff --git a/src/univalue/test/round3.json b/src/univalue/test/round3.json old mode 100644 new mode 100755 diff --git a/src/univalue/test/round4.json b/src/univalue/test/round4.json old mode 100644 new mode 100755 diff --git a/src/univalue/test/round5.json b/src/univalue/test/round5.json old mode 100644 new mode 100755 diff --git a/src/univalue/test/round6.json b/src/univalue/test/round6.json old mode 100644 new mode 100755 diff --git a/src/univalue/test/round7.json b/src/univalue/test/round7.json old mode 100644 new mode 100755 diff --git a/src/univalue/test/test_json.cpp b/src/univalue/test/test_json.cpp old mode 100644 new mode 100755 diff --git a/src/univalue/test/unitester.cpp b/src/univalue/test/unitester.cpp old mode 100644 new mode 100755 diff --git a/src/util.cpp b/src/util.cpp old mode 100644 new mode 100755 diff --git a/src/util.h b/src/util.h old mode 100644 new mode 100755 diff --git a/src/utilmoneystr.cpp b/src/utilmoneystr.cpp old mode 100644 new mode 100755 diff --git a/src/utilmoneystr.h b/src/utilmoneystr.h old mode 100644 new mode 100755 diff --git a/src/utilstrencodings.cpp b/src/utilstrencodings.cpp old mode 100644 new mode 100755 diff --git a/src/utilstrencodings.h b/src/utilstrencodings.h old mode 100644 new mode 100755 diff --git a/src/utiltest.cpp b/src/utiltest.cpp old mode 100644 new mode 100755 diff --git a/src/utiltest.h b/src/utiltest.h old mode 100644 new mode 100755 diff --git a/src/utiltime.cpp b/src/utiltime.cpp old mode 100644 new mode 100755 diff --git a/src/utiltime.h b/src/utiltime.h old mode 100644 new mode 100755 diff --git a/src/validationinterface.cpp b/src/validationinterface.cpp old mode 100644 new mode 100755 diff --git a/src/validationinterface.h b/src/validationinterface.h old mode 100644 new mode 100755 diff --git a/src/version.h b/src/version.h old mode 100644 new mode 100755 diff --git a/src/wallet-utility.cpp b/src/wallet-utility.cpp new file mode 100644 index 00000000000..87335f4e3ca --- /dev/null +++ b/src/wallet-utility.cpp @@ -0,0 +1,339 @@ +#include +#include + +// Include local headers +#include "wallet/walletdb.h" +#include "util.h" +#include "base58.h" +#include "wallet/crypter.h" +#include + + +void show_help() +{ + std::cout << + "This program outputs Bitcoin addresses and private keys from a wallet.dat file" << std::endl + << std::endl + << "Usage and options: " + << std::endl + << " -datadir= to tell the program where your wallet is" + << std::endl + << " -wallet= (Optional) if your wallet is not named wallet.dat" + << std::endl + << " -regtest or -testnet (Optional) dumps addresses from regtest/testnet" + << std::endl + << " -dumppass (Optional)if you want to extract private keys associated with addresses" + << std::endl + << " -pass= if you have encrypted private keys stored in your wallet" + << std::endl; +} + + +class WalletUtilityDB : public CDB +{ + private: + typedef std::map MasterKeyMap; + MasterKeyMap mapMasterKeys; + unsigned int nMasterKeyMaxID; + SecureString mPass; + std::vector vMKeys; + + public: + WalletUtilityDB(const std::string& strFilename, const char* pszMode = "r+", bool fFlushOnClose = true) : CDB(strFilename, pszMode, fFlushOnClose) + { + nMasterKeyMaxID = 0; + mPass.reserve(100); + } + + std::string getAddress(CDataStream ssKey); + std::string getKey(CDataStream ssKey, CDataStream ssValue); + std::string getCryptedKey(CDataStream ssKey, CDataStream ssValue, std::string masterPass); + bool updateMasterKeys(CDataStream ssKey, CDataStream ssValue); + bool parseKeys(bool dumppriv, std::string masterPass); + + bool DecryptSecret(const std::vector& vchCiphertext, const uint256& nIV, CKeyingMaterial& vchPlaintext); + bool Unlock(); + bool DecryptKey(const std::vector& vchCryptedSecret, const CPubKey& vchPubKey, CKey& key); +}; + + +/* + * Address from a public key in base58 + */ +std::string WalletUtilityDB::getAddress(CDataStream ssKey) +{ + CPubKey vchPubKey; + ssKey >> vchPubKey; + CKeyID id = vchPubKey.GetID(); + std::string strAddr = CBitcoinAddress(id).ToString(); + + return strAddr; +} + + +/* + * Non encrypted private key in WIF + */ +std::string WalletUtilityDB::getKey(CDataStream ssKey, CDataStream ssValue) +{ + std::string strKey; + CPubKey vchPubKey; + ssKey >> vchPubKey; + CPrivKey pkey; + CKey key; + + ssValue >> pkey; + if (key.Load(pkey, vchPubKey, true)) + strKey = CBitcoinSecret(key).ToString(); + + return strKey; +} + + +bool WalletUtilityDB::DecryptSecret(const std::vector& vchCiphertext, const uint256& nIV, CKeyingMaterial& vchPlaintext) +{ + CCrypter cKeyCrypter; + std::vector chIV(WALLET_CRYPTO_KEY_SIZE); + memcpy(&chIV[0], &nIV, WALLET_CRYPTO_KEY_SIZE); + + BOOST_FOREACH(const CKeyingMaterial vMKey, vMKeys) + { + if(!cKeyCrypter.SetKey(vMKey, chIV)) + continue; + if (cKeyCrypter.Decrypt(vchCiphertext, *((CKeyingMaterial*)&vchPlaintext))) + return true; + } + return false; +} + + +bool WalletUtilityDB::Unlock() +{ + CCrypter crypter; + CKeyingMaterial vMasterKey; + + BOOST_FOREACH(const MasterKeyMap::value_type& pMasterKey, mapMasterKeys) + { + if(!crypter.SetKeyFromPassphrase(mPass, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod)) + return false; + if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, vMasterKey)) + continue; // try another master key + vMKeys.push_back(vMasterKey); + } + return true; +} + + +bool WalletUtilityDB::DecryptKey(const std::vector& vchCryptedSecret, const CPubKey& vchPubKey, CKey& key) +{ + CKeyingMaterial vchSecret; + if(!DecryptSecret(vchCryptedSecret, vchPubKey.GetHash(), vchSecret)) + return false; + + if (vchSecret.size() != 32) + return false; + + key.Set(vchSecret.begin(), vchSecret.end(), vchPubKey.IsCompressed()); + return true; +} + + +/* + * Encrypted private key in WIF format + */ +std::string WalletUtilityDB::getCryptedKey(CDataStream ssKey, CDataStream ssValue, std::string masterPass) +{ + mPass = masterPass.c_str(); + CPubKey vchPubKey; + ssKey >> vchPubKey; + CKey key; + + std::vector vKey; + ssValue >> vKey; + + if (!Unlock()) + return ""; + + if(!DecryptKey(vKey, vchPubKey, key)) + return ""; + + std::string strKey = CBitcoinSecret(key).ToString(); + return strKey; +} + + +/* + * Master key derivation + */ +bool WalletUtilityDB::updateMasterKeys(CDataStream ssKey, CDataStream ssValue) +{ + unsigned int nID; + ssKey >> nID; + CMasterKey kMasterKey; + ssValue >> kMasterKey; + if (mapMasterKeys.count(nID) != 0) + { + std::cout << "Error reading wallet database: duplicate CMasterKey id " << nID << std::endl; + return false; + } + mapMasterKeys[nID] = kMasterKey; + + if (nMasterKeyMaxID < nID) + nMasterKeyMaxID = nID; + + return true; +} + + +/* + * Look at all the records and parse keys for addresses and private keys + */ +bool WalletUtilityDB::parseKeys(bool dumppriv, std::string masterPass) +{ + DBErrors result = DB_LOAD_OK; + std::string strType; + bool first = true; + + try { + Dbc* pcursor = GetCursor(); + if (!pcursor) + { + LogPrintf("Error getting wallet database cursor\n"); + result = DB_CORRUPT; + } + + if (dumppriv) + { + while (result == DB_LOAD_OK && true) + { + CDataStream ssKey(SER_DISK, CLIENT_VERSION); + CDataStream ssValue(SER_DISK, CLIENT_VERSION); + int result = ReadAtCursor(pcursor, ssKey, ssValue); + + if (result == DB_NOTFOUND) { + break; + } + else if (result != 0) + { + LogPrintf("Error reading next record from wallet database\n"); + result = DB_CORRUPT; + break; + } + + ssKey >> strType; + if (strType == "mkey") + { + updateMasterKeys(ssKey, ssValue); + } + } + pcursor->close(); + pcursor = GetCursor(); + } + + while (result == DB_LOAD_OK && true) + { + CDataStream ssKey(SER_DISK, CLIENT_VERSION); + CDataStream ssValue(SER_DISK, CLIENT_VERSION); + int ret = ReadAtCursor(pcursor, ssKey, ssValue); + + if (ret == DB_NOTFOUND) + { + std::cout << " ]" << std::endl; + first = true; + break; + } + else if (ret != DB_LOAD_OK) + { + LogPrintf("Error reading next record from wallet database\n"); + result = DB_CORRUPT; + break; + } + + ssKey >> strType; + + if (strType == "key" || strType == "ckey") + { + std::string strAddr = getAddress(ssKey); + std::string strKey = ""; + + + if (dumppriv && strType == "key") + strKey = getKey(ssKey, ssValue); + if (dumppriv && strType == "ckey") + { + if (masterPass == "") + { + std::cout << "Encrypted wallet, please provide a password. See help below" << std::endl; + show_help(); + result = DB_LOAD_FAIL; + break; + } + strKey = getCryptedKey(ssKey, ssValue, masterPass); + } + + if (strAddr != "") + { + if (first) + std::cout << "[ "; + else + std::cout << ", "; + } + + if (dumppriv) + { + std::cout << "{\"addr\" : \"" + strAddr + "\", " + << "\"pkey\" : \"" + strKey + "\"}" + << std::flush; + } + else + { + std::cout << "\"" + strAddr + "\""; + } + + first = false; + } + } + + pcursor->close(); + } catch (DbException &e) { + std::cout << "DBException caught " << e.get_errno() << std::endl; + } catch (std::exception &e) { + std::cout << "Exception caught " << std::endl; + } + + if (result == DB_LOAD_OK) + return true; + else + return false; +} + + +int main(int argc, char* argv[]) +{ + ParseParameters(argc, argv); + std::string walletFile = GetArg("-wallet", "wallet.dat"); + std::string masterPass = GetArg("-pass", ""); + bool fDumpPass = GetBoolArg("-dumppass", false); + bool help = GetBoolArg("-h", false); + bool result = false; + + if (help) + { + show_help(); + return 0; + } + + try { + SelectParamsFromCommandLine(); + result = WalletUtilityDB(walletFile, "r").parseKeys(fDumpPass, masterPass); + } + catch (const std::exception& e) { + std::cout << "Error opening wallet file " << walletFile << std::endl; + std::cout << e.what() << std::endl; + } + + if (result) + return 0; + else + return -1; +} diff --git a/src/wallet/asyncrpcoperation_sendmany.cpp b/src/wallet/asyncrpcoperation_sendmany.cpp old mode 100644 new mode 100755 diff --git a/src/wallet/asyncrpcoperation_sendmany.h b/src/wallet/asyncrpcoperation_sendmany.h old mode 100644 new mode 100755 diff --git a/src/wallet/crypter.cpp b/src/wallet/crypter.cpp old mode 100644 new mode 100755 diff --git a/src/wallet/crypter.h b/src/wallet/crypter.h old mode 100644 new mode 100755 diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp old mode 100644 new mode 100755 diff --git a/src/wallet/db.h b/src/wallet/db.h old mode 100644 new mode 100755 diff --git a/src/wallet/gtest/test_wallet.cpp b/src/wallet/gtest/test_wallet.cpp old mode 100644 new mode 100755 diff --git a/src/wallet/gtest/test_wallet_zkeys.cpp b/src/wallet/gtest/test_wallet_zkeys.cpp old mode 100644 new mode 100755 diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp old mode 100644 new mode 100755 diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp old mode 100644 new mode 100755 diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp old mode 100644 new mode 100755 diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp old mode 100644 new mode 100755 diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h old mode 100644 new mode 100755 diff --git a/src/wallet/wallet_ismine.cpp b/src/wallet/wallet_ismine.cpp old mode 100644 new mode 100755 diff --git a/src/wallet/wallet_ismine.h b/src/wallet/wallet_ismine.h old mode 100644 new mode 100755 diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp old mode 100644 new mode 100755 diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h old mode 100644 new mode 100755 diff --git a/src/zcash/Address.cpp b/src/zcash/Address.cpp old mode 100644 new mode 100755 diff --git a/src/zcash/Address.hpp b/src/zcash/Address.hpp old mode 100644 new mode 100755 diff --git a/src/zcash/CreateJoinSplit.cpp b/src/zcash/CreateJoinSplit.cpp old mode 100644 new mode 100755 diff --git a/src/zcash/GenerateParams.cpp b/src/zcash/GenerateParams.cpp old mode 100644 new mode 100755 diff --git a/src/zcash/IncrementalMerkleTree.cpp b/src/zcash/IncrementalMerkleTree.cpp old mode 100644 new mode 100755 diff --git a/src/zcash/IncrementalMerkleTree.hpp b/src/zcash/IncrementalMerkleTree.hpp old mode 100644 new mode 100755 diff --git a/src/zcash/JoinSplit.cpp b/src/zcash/JoinSplit.cpp old mode 100644 new mode 100755 diff --git a/src/zcash/JoinSplit.hpp b/src/zcash/JoinSplit.hpp old mode 100644 new mode 100755 diff --git a/src/zcash/Note.cpp b/src/zcash/Note.cpp old mode 100644 new mode 100755 diff --git a/src/zcash/Note.hpp b/src/zcash/Note.hpp old mode 100644 new mode 100755 diff --git a/src/zcash/NoteEncryption.cpp b/src/zcash/NoteEncryption.cpp old mode 100644 new mode 100755 diff --git a/src/zcash/NoteEncryption.hpp b/src/zcash/NoteEncryption.hpp old mode 100644 new mode 100755 diff --git a/src/zcash/Proof.cpp b/src/zcash/Proof.cpp old mode 100644 new mode 100755 diff --git a/src/zcash/Proof.hpp b/src/zcash/Proof.hpp old mode 100644 new mode 100755 diff --git a/src/zcash/Zcash.h b/src/zcash/Zcash.h old mode 100644 new mode 100755 diff --git a/src/zcash/circuit/commitment.tcc b/src/zcash/circuit/commitment.tcc old mode 100644 new mode 100755 diff --git a/src/zcash/circuit/gadget.tcc b/src/zcash/circuit/gadget.tcc old mode 100644 new mode 100755 diff --git a/src/zcash/circuit/merkle.tcc b/src/zcash/circuit/merkle.tcc old mode 100644 new mode 100755 diff --git a/src/zcash/circuit/note.tcc b/src/zcash/circuit/note.tcc old mode 100644 new mode 100755 diff --git a/src/zcash/circuit/prfs.tcc b/src/zcash/circuit/prfs.tcc old mode 100644 new mode 100755 diff --git a/src/zcash/circuit/utils.tcc b/src/zcash/circuit/utils.tcc old mode 100644 new mode 100755 diff --git a/src/zcash/prf.cpp b/src/zcash/prf.cpp old mode 100644 new mode 100755 diff --git a/src/zcash/prf.h b/src/zcash/prf.h old mode 100644 new mode 100755 diff --git a/src/zcash/util.cpp b/src/zcash/util.cpp old mode 100644 new mode 100755 diff --git a/src/zcash/util.h b/src/zcash/util.h old mode 100644 new mode 100755 diff --git a/src/zcbenchmarks.cpp b/src/zcbenchmarks.cpp old mode 100644 new mode 100755 diff --git a/src/zcbenchmarks.h b/src/zcbenchmarks.h old mode 100644 new mode 100755 diff --git a/src/zmq/zmqabstractnotifier.cpp b/src/zmq/zmqabstractnotifier.cpp old mode 100644 new mode 100755 diff --git a/src/zmq/zmqabstractnotifier.h b/src/zmq/zmqabstractnotifier.h old mode 100644 new mode 100755 diff --git a/src/zmq/zmqconfig.h b/src/zmq/zmqconfig.h old mode 100644 new mode 100755 diff --git a/src/zmq/zmqnotificationinterface.cpp b/src/zmq/zmqnotificationinterface.cpp old mode 100644 new mode 100755 diff --git a/src/zmq/zmqnotificationinterface.h b/src/zmq/zmqnotificationinterface.h old mode 100644 new mode 100755 diff --git a/src/zmq/zmqpublishnotifier.cpp b/src/zmq/zmqpublishnotifier.cpp old mode 100644 new mode 100755 diff --git a/src/zmq/zmqpublishnotifier.h b/src/zmq/zmqpublishnotifier.h old mode 100644 new mode 100755